2024-03-27 15:26:01 +01:00
|
|
|
import { ResizeController } from "@lit-labs/observers/resize-controller";
|
2023-03-29 12:17:42 +02:00
|
|
|
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
2024-03-27 15:26:01 +01:00
|
|
|
import "@material/mwc-button/mwc-button";
|
2024-04-02 10:14:17 +02:00
|
|
|
import "@material/web/divider/divider";
|
2024-03-27 15:26:01 +01:00
|
|
|
import {
|
|
|
|
mdiArrowDown,
|
|
|
|
mdiArrowUp,
|
|
|
|
mdiClose,
|
|
|
|
mdiFilterVariant,
|
2024-04-02 10:14:17 +02:00
|
|
|
mdiFilterVariantRemove,
|
2024-03-27 15:26:01 +01:00
|
|
|
mdiFormatListChecks,
|
|
|
|
mdiMenuDown,
|
|
|
|
} from "@mdi/js";
|
|
|
|
import {
|
|
|
|
CSSResultGroup,
|
|
|
|
LitElement,
|
|
|
|
TemplateResult,
|
|
|
|
css,
|
|
|
|
html,
|
|
|
|
nothing,
|
|
|
|
} from "lit";
|
|
|
|
import { customElement, property, query, state } from "lit/decorators";
|
2024-03-29 16:15:21 +01:00
|
|
|
import { classMap } from "lit/directives/class-map";
|
2021-03-28 18:29:55 +02:00
|
|
|
import { fireEvent } from "../common/dom/fire_event";
|
2021-05-18 16:37:53 +02:00
|
|
|
import { LocalizeFunc } from "../common/translations/localize";
|
2024-03-27 15:26:01 +01:00
|
|
|
import "../components/chips/ha-assist-chip";
|
|
|
|
import "../components/chips/ha-filter-chip";
|
2020-02-13 19:53:48 +01:00
|
|
|
import "../components/data-table/ha-data-table";
|
2020-04-14 18:05:45 +02:00
|
|
|
import type {
|
2020-02-13 19:53:48 +01:00
|
|
|
DataTableColumnContainer,
|
|
|
|
DataTableRowData,
|
2020-04-14 18:05:45 +02:00
|
|
|
HaDataTable,
|
2024-03-27 15:26:01 +01:00
|
|
|
SortingDirection,
|
2020-02-13 19:53:48 +01:00
|
|
|
} from "../components/data-table/ha-data-table";
|
2024-04-02 10:14:17 +02:00
|
|
|
import "../components/ha-button-menu-new";
|
2024-03-27 15:26:01 +01:00
|
|
|
import "../components/ha-dialog";
|
2024-04-02 10:14:17 +02:00
|
|
|
import { HaMenu } from "../components/ha-menu";
|
2024-03-31 12:28:28 +02:00
|
|
|
import "../components/ha-menu-item";
|
2024-04-02 10:14:17 +02:00
|
|
|
import "../components/search-input-outlined";
|
2020-04-14 18:05:45 +02:00
|
|
|
import type { HomeAssistant, Route } from "../types";
|
2020-02-13 19:53:48 +01:00
|
|
|
import "./hass-tabs-subpage";
|
2020-04-14 18:05:45 +02:00
|
|
|
import type { PageNavigation } from "./hass-tabs-subpage";
|
2020-02-13 19:53:48 +01:00
|
|
|
|
2021-03-28 18:29:55 +02:00
|
|
|
declare global {
|
|
|
|
// for fire event
|
|
|
|
interface HASSDomEvents {
|
|
|
|
"search-changed": { value: string };
|
|
|
|
"clear-filter": undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
@customElement("hass-tabs-subpage-data-table")
|
|
|
|
export class HaTabsSubpageDataTable extends LitElement {
|
2020-07-15 06:38:36 +02:00
|
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2021-05-10 18:17:16 +02:00
|
|
|
@property({ attribute: false }) public localizeFunc?: LocalizeFunc;
|
|
|
|
|
2020-07-30 18:27:27 +02:00
|
|
|
@property({ type: Boolean }) public isWide = false;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-07-30 18:27:27 +02:00
|
|
|
@property({ type: Boolean, reflect: true }) public narrow = false;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2021-05-15 12:25:28 +02:00
|
|
|
@property({ type: Boolean }) public supervisor = false;
|
|
|
|
|
|
|
|
@property({ type: Boolean, attribute: "main-page" }) public mainPage = false;
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Object with the columns.
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
@property({ type: Object }) public columns: DataTableColumnContainer = {};
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Data to show in the table.
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
|
|
|
@property({ type: Array }) public data: DataTableRowData[] = [];
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Should rows be selectable.
|
|
|
|
* @type {Boolean}
|
|
|
|
*/
|
|
|
|
@property({ type: Boolean }) public selectable = false;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-10-15 15:57:05 +02:00
|
|
|
/**
|
|
|
|
* Should rows be clickable.
|
|
|
|
* @type {Boolean}
|
|
|
|
*/
|
|
|
|
@property({ type: Boolean }) public clickable = false;
|
|
|
|
|
2020-04-03 17:46:19 +02:00
|
|
|
/**
|
|
|
|
* Do we need to add padding for a fab.
|
|
|
|
* @type {Boolean}
|
|
|
|
*/
|
|
|
|
@property({ type: Boolean }) public hasFab = false;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-12-12 20:38:10 +01:00
|
|
|
/**
|
2020-12-29 22:52:20 +01:00
|
|
|
* Add an extra row at the bottom of the data table
|
2020-12-12 20:38:10 +01:00
|
|
|
* @type {TemplateResult}
|
|
|
|
*/
|
2021-03-28 18:29:55 +02:00
|
|
|
@property({ attribute: false }) public appendRow?: TemplateResult;
|
2020-12-12 20:38:10 +01:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Field with a unique id per entry in data.
|
|
|
|
* @type {String}
|
|
|
|
*/
|
|
|
|
@property({ type: String }) public id = "id";
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* String to filter the data in the data table on.
|
|
|
|
* @type {String}
|
|
|
|
*/
|
|
|
|
@property({ type: String }) public filter = "";
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2021-03-28 18:29:55 +02:00
|
|
|
@property() public searchLabel?: string;
|
|
|
|
|
2020-04-22 11:51:50 +02:00
|
|
|
/**
|
2024-03-27 15:26:01 +01:00
|
|
|
* Number of active filters.
|
|
|
|
* @type {Number}
|
2021-03-28 18:29:55 +02:00
|
|
|
*/
|
2024-03-27 15:26:01 +01:00
|
|
|
@property({ type: Number }) public filters?;
|
2021-03-28 18:29:55 +02:00
|
|
|
|
|
|
|
/**
|
2024-03-27 15:26:01 +01:00
|
|
|
* Number of current selections.
|
2021-03-28 18:29:55 +02:00
|
|
|
* @type {Number}
|
|
|
|
*/
|
2024-03-27 15:26:01 +01:00
|
|
|
@property({ type: Number }) public selected?;
|
2021-03-28 18:29:55 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* What path to use when the back button is pressed.
|
|
|
|
* @type {String}
|
|
|
|
* @attr back-path
|
|
|
|
*/
|
|
|
|
@property({ type: String, attribute: "back-path" }) public backPath?: string;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Function to call when the back button is pressed.
|
|
|
|
* @type {() => void}
|
|
|
|
*/
|
2024-01-22 18:03:42 +01:00
|
|
|
@property({ attribute: false }) public backCallback?: () => void;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-03-11 08:42:52 +01:00
|
|
|
/**
|
|
|
|
* String to show when there are no records in the data table.
|
|
|
|
* @type {String}
|
|
|
|
*/
|
|
|
|
@property({ type: String }) public noDataText?: string;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2023-12-18 13:59:36 +01:00
|
|
|
/**
|
|
|
|
* Hides the data table and show an empty message.
|
|
|
|
* @type {Boolean}
|
|
|
|
*/
|
|
|
|
@property({ type: Boolean }) public empty = false;
|
|
|
|
|
2024-01-15 15:52:10 +01:00
|
|
|
@property({ attribute: false }) public route!: Route;
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
/**
|
|
|
|
* Array of tabs to show on the page.
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
2024-01-22 18:03:42 +01:00
|
|
|
@property({ attribute: false }) public tabs: PageNavigation[] = [];
|
2020-04-14 18:05:45 +02:00
|
|
|
|
2022-03-30 19:52:05 +02:00
|
|
|
/**
|
2024-03-27 15:26:01 +01:00
|
|
|
* Show the filter menu.
|
2022-03-30 19:52:05 +02:00
|
|
|
* @type {Boolean}
|
|
|
|
*/
|
2024-03-27 15:26:01 +01:00
|
|
|
@property({ type: Boolean }) public hasFilters = false;
|
|
|
|
|
|
|
|
@property({ type: Boolean }) public showFilters = false;
|
|
|
|
|
|
|
|
@property() public initialGroupColumn?: string;
|
|
|
|
|
|
|
|
@state() private _sortColumn?: string;
|
|
|
|
|
|
|
|
@state() private _sortDirection: SortingDirection = null;
|
|
|
|
|
|
|
|
@state() private _groupColumn?: string;
|
|
|
|
|
|
|
|
@state() private _selectMode = false;
|
2022-03-30 19:52:05 +02:00
|
|
|
|
2020-10-06 15:55:55 +02:00
|
|
|
@query("ha-data-table", true) private _dataTable!: HaDataTable;
|
2020-02-13 19:53:48 +01:00
|
|
|
|
2024-03-31 12:28:28 +02:00
|
|
|
@query("#group-by-menu") private _groupByMenu!: HaMenu;
|
2024-03-29 16:15:21 +01:00
|
|
|
|
2024-03-31 12:28:28 +02:00
|
|
|
@query("#sort-by-menu") private _sortByMenu!: HaMenu;
|
2024-03-29 16:15:21 +01:00
|
|
|
|
2024-03-27 15:26:01 +01:00
|
|
|
private _showPaneController = new ResizeController(this, {
|
|
|
|
callback: (entries) => entries[0]?.contentRect.width > 750,
|
|
|
|
});
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
public clearSelection() {
|
|
|
|
this._dataTable.clearSelection();
|
|
|
|
}
|
|
|
|
|
2024-03-27 15:26:01 +01:00
|
|
|
protected firstUpdated() {
|
|
|
|
if (this.initialGroupColumn) {
|
|
|
|
this._groupColumn = this.initialGroupColumn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-29 16:15:21 +01:00
|
|
|
private _toggleGroupBy() {
|
|
|
|
this._groupByMenu.open = !this._groupByMenu.open;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _toggleSortBy() {
|
|
|
|
this._sortByMenu.open = !this._sortByMenu.open;
|
|
|
|
}
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
protected render(): TemplateResult {
|
2024-03-27 15:26:01 +01:00
|
|
|
const localize = this.localizeFunc || this.hass.localize;
|
|
|
|
const showPane = this._showPaneController.value ?? !this.narrow;
|
|
|
|
const filterButton = this.hasFilters
|
|
|
|
? html`<div class="relative">
|
|
|
|
<ha-assist-chip
|
|
|
|
.label=${localize("ui.components.subpage-data-table.filters")}
|
|
|
|
.active=${this.filters}
|
|
|
|
@click=${this._toggleFilters}
|
|
|
|
>
|
|
|
|
<ha-svg-icon slot="icon" .path=${mdiFilterVariant}></ha-svg-icon>
|
|
|
|
</ha-assist-chip>
|
|
|
|
${this.filters
|
|
|
|
? html`<div class="badge">${this.filters}</div>`
|
|
|
|
: nothing}
|
|
|
|
</div>`
|
|
|
|
: nothing;
|
|
|
|
|
|
|
|
const selectModeBtn =
|
|
|
|
this.selectable && !this._selectMode
|
|
|
|
? html`<ha-assist-chip
|
|
|
|
class="has-dropdown select-mode-chip"
|
|
|
|
.active=${this._selectMode}
|
|
|
|
@click=${this._enableSelectMode}
|
2024-04-02 10:14:17 +02:00
|
|
|
.title=${localize(
|
2024-03-30 21:11:35 +01:00
|
|
|
"ui.components.subpage-data-table.enter_selection_mode"
|
|
|
|
)}
|
2024-03-27 15:26:01 +01:00
|
|
|
>
|
|
|
|
<ha-svg-icon slot="icon" .path=${mdiFormatListChecks}></ha-svg-icon>
|
|
|
|
</ha-assist-chip>`
|
|
|
|
: nothing;
|
|
|
|
|
|
|
|
const searchBar = html`<search-input-outlined
|
2022-02-11 19:34:50 +01:00
|
|
|
.hass=${this.hass}
|
|
|
|
.filter=${this.filter}
|
|
|
|
@value-changed=${this._handleSearchChange}
|
2023-07-10 00:39:51 +02:00
|
|
|
.label=${this.searchLabel}
|
2024-03-27 15:26:01 +01:00
|
|
|
.placeholder=${this.searchLabel}
|
2022-02-11 19:34:50 +01:00
|
|
|
>
|
2024-03-27 15:26:01 +01:00
|
|
|
</search-input-outlined>`;
|
|
|
|
|
|
|
|
const sortByMenu = Object.values(this.columns).find((col) => col.sortable)
|
2024-03-29 16:15:21 +01:00
|
|
|
? html`
|
2024-03-27 15:26:01 +01:00
|
|
|
<ha-assist-chip
|
|
|
|
.label=${localize("ui.components.subpage-data-table.sort_by", {
|
|
|
|
sortColumn: this._sortColumn
|
|
|
|
? ` ${this.columns[this._sortColumn].title || this.columns[this._sortColumn].label}`
|
|
|
|
: "",
|
|
|
|
})}
|
2024-03-29 16:15:21 +01:00
|
|
|
id="sort-by-anchor"
|
|
|
|
@click=${this._toggleSortBy}
|
2022-02-11 23:24:29 +01:00
|
|
|
>
|
2024-04-02 10:14:17 +02:00
|
|
|
<ha-svg-icon
|
|
|
|
slot="trailing-icon"
|
|
|
|
.path=${mdiMenuDown}
|
|
|
|
></ha-svg-icon>
|
|
|
|
</ha-assist-chip>
|
2024-03-29 16:15:21 +01:00
|
|
|
`
|
2024-03-27 15:26:01 +01:00
|
|
|
: nothing;
|
|
|
|
|
|
|
|
const groupByMenu = Object.values(this.columns).find((col) => col.groupable)
|
2024-03-29 16:15:21 +01:00
|
|
|
? html`
|
2024-03-27 15:26:01 +01:00
|
|
|
<ha-assist-chip
|
|
|
|
.label=${localize("ui.components.subpage-data-table.group_by", {
|
|
|
|
groupColumn: this._groupColumn
|
|
|
|
? ` ${this.columns[this._groupColumn].title || this.columns[this._groupColumn].label}`
|
|
|
|
: "",
|
|
|
|
})}
|
2024-03-29 16:15:21 +01:00
|
|
|
id="group-by-anchor"
|
|
|
|
@click=${this._toggleGroupBy}
|
2024-03-27 15:26:01 +01:00
|
|
|
>
|
|
|
|
<ha-svg-icon slot="trailing-icon" .path=${mdiMenuDown}></ha-svg-icon
|
|
|
|
></ha-assist-chip>
|
2024-03-29 16:15:21 +01:00
|
|
|
`
|
2024-03-27 15:26:01 +01:00
|
|
|
: nothing;
|
2021-03-28 18:29:55 +02:00
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
return html`
|
|
|
|
<hass-tabs-subpage
|
|
|
|
.hass=${this.hass}
|
2021-05-10 18:17:16 +02:00
|
|
|
.localizeFunc=${this.localizeFunc}
|
2020-02-13 19:53:48 +01:00
|
|
|
.narrow=${this.narrow}
|
2020-07-30 18:27:27 +02:00
|
|
|
.isWide=${this.isWide}
|
2020-02-13 19:53:48 +01:00
|
|
|
.backPath=${this.backPath}
|
|
|
|
.backCallback=${this.backCallback}
|
|
|
|
.route=${this.route}
|
|
|
|
.tabs=${this.tabs}
|
2021-05-15 12:25:28 +02:00
|
|
|
.mainPage=${this.mainPage}
|
|
|
|
.supervisor=${this.supervisor}
|
2024-03-27 15:26:01 +01:00
|
|
|
.pane=${showPane && this.showFilters}
|
|
|
|
@sorting-changed=${this._sortingChanged}
|
2020-02-13 19:53:48 +01:00
|
|
|
>
|
2024-03-27 15:26:01 +01:00
|
|
|
${this._selectMode
|
|
|
|
? html`<div class="selection-bar" slot="toolbar">
|
2024-04-02 10:14:17 +02:00
|
|
|
<div class="selection-controls">
|
2024-03-27 15:26:01 +01:00
|
|
|
<ha-icon-button
|
|
|
|
.path=${mdiClose}
|
|
|
|
@click=${this._disableSelectMode}
|
2024-03-30 21:11:35 +01:00
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.exit_selection_mode"
|
|
|
|
)}
|
2024-03-27 15:26:01 +01:00
|
|
|
></ha-icon-button>
|
2024-04-02 10:14:17 +02:00
|
|
|
<ha-button-menu-new positioning="absolute">
|
|
|
|
<ha-assist-chip
|
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.select"
|
|
|
|
)}
|
|
|
|
slot="trigger"
|
|
|
|
>
|
|
|
|
<ha-svg-icon
|
|
|
|
slot="icon"
|
|
|
|
.path=${mdiFormatListChecks}
|
|
|
|
></ha-svg-icon>
|
|
|
|
<ha-svg-icon
|
|
|
|
slot="trailing-icon"
|
|
|
|
.path=${mdiMenuDown}
|
|
|
|
></ha-svg-icon
|
|
|
|
></ha-assist-chip>
|
|
|
|
<ha-menu-item .value=${undefined} @click=${this._selectAll}
|
|
|
|
>${localize("ui.components.subpage-data-table.select_all")}
|
|
|
|
</ha-menu-item>
|
|
|
|
<ha-menu-item .value=${undefined} @click=${this._selectNone}
|
|
|
|
>${localize("ui.components.subpage-data-table.select_none")}
|
|
|
|
</ha-menu-item>
|
|
|
|
<md-divider role="separator" tabindex="-1"></md-divider>
|
|
|
|
<ha-menu-item
|
|
|
|
.value=${undefined}
|
|
|
|
@click=${this._disableSelectMode}
|
|
|
|
>${localize(
|
|
|
|
"ui.components.subpage-data-table.close_select_mode"
|
|
|
|
)}
|
|
|
|
</ha-menu-item>
|
|
|
|
</ha-button-menu-new>
|
2024-03-27 15:26:01 +01:00
|
|
|
<p>
|
|
|
|
${localize("ui.components.subpage-data-table.selected", {
|
|
|
|
selected: this.selected || "0",
|
|
|
|
})}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="center-vertical">
|
|
|
|
<slot name="selection-bar"></slot>
|
|
|
|
</div>
|
|
|
|
</div>`
|
|
|
|
: nothing}
|
|
|
|
${this.showFilters
|
|
|
|
? !showPane
|
|
|
|
? html`<ha-dialog
|
|
|
|
open
|
|
|
|
hideActions
|
|
|
|
.heading=${localize("ui.components.subpage-data-table.filters")}
|
|
|
|
>
|
|
|
|
<ha-dialog-header slot="heading">
|
|
|
|
<ha-icon-button
|
|
|
|
slot="navigationIcon"
|
|
|
|
.path=${mdiClose}
|
|
|
|
@click=${this._toggleFilters}
|
2024-03-30 21:11:35 +01:00
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.close_filter"
|
|
|
|
)}
|
2024-03-27 15:26:01 +01:00
|
|
|
></ha-icon-button>
|
|
|
|
<span slot="title"
|
|
|
|
>${localize(
|
|
|
|
"ui.components.subpage-data-table.filters"
|
|
|
|
)}</span
|
|
|
|
>
|
2024-04-02 22:05:03 +02:00
|
|
|
${this.filters
|
|
|
|
? html`<ha-icon-button
|
|
|
|
slot="actionItems"
|
|
|
|
@click=${this._clearFilters}
|
|
|
|
.path=${mdiFilterVariantRemove}
|
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.clear_filter"
|
|
|
|
)}
|
|
|
|
></ha-icon-button>`
|
|
|
|
: nothing}
|
2024-03-27 15:26:01 +01:00
|
|
|
</ha-dialog-header>
|
|
|
|
<div class="filter-dialog-content">
|
|
|
|
<slot name="filter-pane"></slot></div
|
|
|
|
></ha-dialog>`
|
|
|
|
: html`<div class="pane" slot="pane">
|
|
|
|
<div class="table-header">
|
|
|
|
<ha-assist-chip
|
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.filters"
|
|
|
|
)}
|
|
|
|
active
|
|
|
|
@click=${this._toggleFilters}
|
|
|
|
>
|
|
|
|
<ha-svg-icon
|
|
|
|
slot="icon"
|
|
|
|
.path=${mdiFilterVariant}
|
|
|
|
></ha-svg-icon>
|
|
|
|
</ha-assist-chip>
|
2024-04-02 22:05:03 +02:00
|
|
|
${this.filters
|
|
|
|
? html`<ha-icon-button
|
|
|
|
.path=${mdiFilterVariantRemove}
|
|
|
|
@click=${this._clearFilters}
|
|
|
|
.label=${localize(
|
|
|
|
"ui.components.subpage-data-table.clear_filter"
|
|
|
|
)}
|
|
|
|
></ha-icon-button>`
|
|
|
|
: nothing}
|
2024-03-27 15:26:01 +01:00
|
|
|
</div>
|
|
|
|
<div class="pane-content">
|
|
|
|
<slot name="filter-pane"></slot>
|
|
|
|
</div>
|
|
|
|
</div>`
|
|
|
|
: nothing}
|
2023-12-18 13:59:36 +01:00
|
|
|
${this.empty
|
|
|
|
? html`<div class="center">
|
|
|
|
<slot name="empty">${this.noDataText}</slot>
|
|
|
|
</div>`
|
2024-03-27 15:26:01 +01:00
|
|
|
: html`<div slot="toolbar-icon">
|
|
|
|
<slot name="toolbar-icon"></slot>
|
|
|
|
</div>
|
2023-12-18 13:59:36 +01:00
|
|
|
${this.narrow
|
|
|
|
? html`
|
|
|
|
<div slot="header">
|
|
|
|
<slot name="header">
|
2024-03-27 15:26:01 +01:00
|
|
|
<div class="search-toolbar">${searchBar}</div>
|
2023-12-18 13:59:36 +01:00
|
|
|
</slot>
|
|
|
|
</div>
|
|
|
|
`
|
|
|
|
: ""}
|
|
|
|
<ha-data-table
|
|
|
|
.hass=${this.hass}
|
|
|
|
.columns=${this.columns}
|
|
|
|
.data=${this.data}
|
|
|
|
.noDataText=${this.noDataText}
|
|
|
|
.filter=${this.filter}
|
2024-03-27 15:26:01 +01:00
|
|
|
.selectable=${this._selectMode}
|
2023-12-18 13:59:36 +01:00
|
|
|
.hasFab=${this.hasFab}
|
|
|
|
.id=${this.id}
|
|
|
|
.clickable=${this.clickable}
|
|
|
|
.appendRow=${this.appendRow}
|
2024-03-27 15:26:01 +01:00
|
|
|
.sortColumn=${this._sortColumn}
|
|
|
|
.sortDirection=${this._sortDirection}
|
|
|
|
.groupColumn=${this._groupColumn}
|
2023-12-18 13:59:36 +01:00
|
|
|
>
|
|
|
|
${!this.narrow
|
2022-03-30 19:52:05 +02:00
|
|
|
? html`
|
2023-12-18 13:59:36 +01:00
|
|
|
<div slot="header">
|
|
|
|
<slot name="header">
|
2024-03-27 15:26:01 +01:00
|
|
|
<div class="table-header">
|
|
|
|
${this.hasFilters && !this.showFilters
|
|
|
|
? html`${filterButton}`
|
|
|
|
: nothing}${selectModeBtn}${searchBar}${groupByMenu}${sortByMenu}
|
|
|
|
</div>
|
2023-12-18 13:59:36 +01:00
|
|
|
</slot>
|
2022-03-30 19:52:05 +02:00
|
|
|
</div>
|
|
|
|
`
|
2024-03-27 15:26:01 +01:00
|
|
|
: html`<div slot="header"></div>
|
|
|
|
<div slot="header-row" class="narrow-header-row">
|
|
|
|
${this.hasFilters && !this.showFilters
|
|
|
|
? html`${filterButton}`
|
|
|
|
: nothing}
|
|
|
|
${selectModeBtn}${groupByMenu}${sortByMenu}
|
|
|
|
</div>`}
|
2023-12-18 13:59:36 +01:00
|
|
|
</ha-data-table>`}
|
2020-07-30 18:27:27 +02:00
|
|
|
<div slot="fab"><slot name="fab"></slot></div>
|
2020-02-13 19:53:48 +01:00
|
|
|
</hass-tabs-subpage>
|
2024-03-31 12:28:28 +02:00
|
|
|
<ha-menu anchor="group-by-anchor" id="group-by-menu" positioning="fixed">
|
2024-03-29 16:15:21 +01:00
|
|
|
${Object.entries(this.columns).map(([id, column]) =>
|
|
|
|
column.groupable
|
|
|
|
? html`
|
2024-03-31 12:28:28 +02:00
|
|
|
<ha-menu-item
|
2024-03-29 16:15:21 +01:00
|
|
|
.value=${id}
|
|
|
|
@click=${this._handleGroupBy}
|
|
|
|
.selected=${id === this._groupColumn}
|
|
|
|
class=${classMap({ selected: id === this._groupColumn })}
|
|
|
|
>
|
|
|
|
${column.title || column.label}
|
2024-03-31 12:28:28 +02:00
|
|
|
</ha-menu-item>
|
2024-03-29 16:15:21 +01:00
|
|
|
`
|
|
|
|
: nothing
|
|
|
|
)}
|
2024-04-02 10:14:17 +02:00
|
|
|
<md-divider role="separator" tabindex="-1"></md-divider>
|
2024-03-31 12:28:28 +02:00
|
|
|
<ha-menu-item
|
2024-03-29 16:15:21 +01:00
|
|
|
.value=${undefined}
|
|
|
|
@click=${this._handleGroupBy}
|
|
|
|
.selected=${this._groupColumn === undefined}
|
|
|
|
class=${classMap({ selected: this._groupColumn === undefined })}
|
|
|
|
>
|
2024-04-02 10:14:17 +02:00
|
|
|
${localize("ui.components.subpage-data-table.dont_group_by")}
|
|
|
|
</ha-menu-item>
|
2024-03-31 12:28:28 +02:00
|
|
|
</ha-menu>
|
|
|
|
<ha-menu anchor="sort-by-anchor" id="sort-by-menu" positioning="fixed">
|
2024-03-29 16:15:21 +01:00
|
|
|
${Object.entries(this.columns).map(([id, column]) =>
|
|
|
|
column.sortable
|
|
|
|
? html`
|
2024-03-31 12:28:28 +02:00
|
|
|
<ha-menu-item
|
2024-03-29 16:15:21 +01:00
|
|
|
.value=${id}
|
|
|
|
@click=${this._handleSortBy}
|
2024-04-02 10:14:17 +02:00
|
|
|
keep-open
|
2024-03-29 16:15:21 +01:00
|
|
|
.selected=${id === this._sortColumn}
|
|
|
|
class=${classMap({ selected: id === this._sortColumn })}
|
|
|
|
>
|
|
|
|
${this._sortColumn === id
|
|
|
|
? html`
|
|
|
|
<ha-svg-icon
|
|
|
|
slot="end"
|
|
|
|
.path=${this._sortDirection === "desc"
|
|
|
|
? mdiArrowDown
|
|
|
|
: mdiArrowUp}
|
|
|
|
></ha-svg-icon>
|
|
|
|
`
|
|
|
|
: nothing}
|
|
|
|
${column.title || column.label}
|
2024-03-31 12:28:28 +02:00
|
|
|
</ha-menu-item>
|
2024-03-29 16:15:21 +01:00
|
|
|
`
|
|
|
|
: nothing
|
|
|
|
)}
|
2024-03-31 12:28:28 +02:00
|
|
|
</ha-menu>
|
2020-02-13 19:53:48 +01:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2024-03-27 15:26:01 +01:00
|
|
|
private _clearFilters() {
|
|
|
|
fireEvent(this, "clear-filter");
|
|
|
|
}
|
|
|
|
|
|
|
|
private _toggleFilters() {
|
|
|
|
this.showFilters = !this.showFilters;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _sortingChanged(ev) {
|
|
|
|
this._sortDirection = ev.detail.direction;
|
|
|
|
this._sortColumn = this._sortDirection ? ev.detail.column : undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _handleSortBy(ev) {
|
|
|
|
const columnId = ev.currentTarget.value;
|
|
|
|
if (!this._sortDirection || this._sortColumn !== columnId) {
|
|
|
|
this._sortDirection = "asc";
|
|
|
|
} else if (this._sortDirection === "asc") {
|
|
|
|
this._sortDirection = "desc";
|
|
|
|
} else {
|
|
|
|
this._sortDirection = null;
|
|
|
|
}
|
|
|
|
this._sortColumn = this._sortDirection === null ? undefined : columnId;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _handleGroupBy(ev) {
|
|
|
|
this._groupColumn = ev.currentTarget.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _enableSelectMode() {
|
|
|
|
this._selectMode = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _disableSelectMode() {
|
|
|
|
this._selectMode = false;
|
2024-03-27 17:26:56 +01:00
|
|
|
this._dataTable.clearSelection();
|
2022-02-11 23:24:29 +01:00
|
|
|
}
|
|
|
|
|
2024-04-02 10:14:17 +02:00
|
|
|
private _selectAll() {
|
|
|
|
this._dataTable.selectAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
private _selectNone() {
|
|
|
|
this._dataTable.clearSelection();
|
|
|
|
}
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
private _handleSearchChange(ev: CustomEvent) {
|
2022-02-06 23:26:42 +01:00
|
|
|
if (this.filter === ev.detail.value) {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-13 19:53:48 +01:00
|
|
|
this.filter = ev.detail.value;
|
2021-03-28 18:29:55 +02:00
|
|
|
fireEvent(this, "search-changed", { value: this.filter });
|
2020-02-13 19:53:48 +01:00
|
|
|
}
|
|
|
|
|
2021-05-07 22:16:14 +02:00
|
|
|
static get styles(): CSSResultGroup {
|
2020-02-13 19:53:48 +01:00
|
|
|
return css`
|
2024-03-27 15:26:01 +01:00
|
|
|
:host {
|
|
|
|
display: block;
|
|
|
|
}
|
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
ha-data-table {
|
|
|
|
width: 100%;
|
2020-03-05 20:52:16 +01:00
|
|
|
height: 100%;
|
2020-02-13 19:53:48 +01:00
|
|
|
--data-table-border-width: 0;
|
|
|
|
}
|
2024-03-27 15:26:01 +01:00
|
|
|
:host(:not([narrow])) ha-data-table,
|
|
|
|
.pane {
|
2020-10-21 14:18:33 +02:00
|
|
|
height: calc(100vh - 1px - var(--header-height));
|
2020-02-13 19:53:48 +01:00
|
|
|
display: block;
|
|
|
|
}
|
2024-03-27 15:26:01 +01:00
|
|
|
|
|
|
|
.pane-content {
|
|
|
|
height: calc(100vh - 1px - var(--header-height) - var(--header-height));
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
2022-04-26 17:39:50 +02:00
|
|
|
:host([narrow]) hass-tabs-subpage {
|
|
|
|
--main-title-margin: 0;
|
|
|
|
}
|
2024-03-27 15:26:01 +01:00
|
|
|
:host([narrow]) {
|
|
|
|
--expansion-panel-summary-padding: 0 16px;
|
|
|
|
}
|
2020-02-13 19:53:48 +01:00
|
|
|
.table-header {
|
2020-04-22 11:51:50 +02:00
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2022-02-10 15:23:21 +01:00
|
|
|
--mdc-shape-small: 0;
|
|
|
|
height: 56px;
|
2024-03-27 15:26:01 +01:00
|
|
|
width: 100%;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 0 16px;
|
|
|
|
gap: 16px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
background: var(--primary-background-color);
|
|
|
|
border-bottom: 1px solid var(--divider-color);
|
|
|
|
}
|
|
|
|
search-input-outlined {
|
|
|
|
flex: 1;
|
2020-02-13 19:53:48 +01:00
|
|
|
}
|
|
|
|
.search-toolbar {
|
2020-04-22 11:51:50 +02:00
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2020-02-13 19:53:48 +01:00
|
|
|
color: var(--secondary-text-color);
|
|
|
|
}
|
2022-02-10 15:23:21 +01:00
|
|
|
.filters {
|
2022-02-11 23:24:29 +01:00
|
|
|
--mdc-text-field-fill-color: var(--input-fill-color);
|
|
|
|
--mdc-text-field-idle-line-color: var(--input-idle-line-color);
|
|
|
|
--mdc-shape-small: 4px;
|
2022-02-11 19:34:50 +01:00
|
|
|
--text-field-overflow: initial;
|
2022-02-10 15:23:21 +01:00
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
2022-02-11 23:24:29 +01:00
|
|
|
color: var(--primary-text-color);
|
2020-04-02 16:39:59 +02:00
|
|
|
}
|
2020-04-22 11:51:50 +02:00
|
|
|
.active-filters {
|
|
|
|
color: var(--primary-text-color);
|
|
|
|
position: relative;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 2px 2px 2px 8px;
|
|
|
|
margin-left: 4px;
|
2023-02-20 18:16:03 +01:00
|
|
|
margin-inline-start: 4px;
|
|
|
|
margin-inline-end: initial;
|
2020-04-22 11:51:50 +02:00
|
|
|
font-size: 14px;
|
2022-02-11 19:34:50 +01:00
|
|
|
width: max-content;
|
2022-02-11 23:24:29 +01:00
|
|
|
cursor: initial;
|
2023-02-20 18:16:03 +01:00
|
|
|
direction: var(--direction);
|
2020-04-22 11:51:50 +02:00
|
|
|
}
|
2021-10-07 00:41:37 +02:00
|
|
|
.active-filters ha-svg-icon {
|
2020-04-22 11:51:50 +02:00
|
|
|
color: var(--primary-color);
|
|
|
|
}
|
|
|
|
.active-filters mwc-button {
|
|
|
|
margin-left: 8px;
|
2023-02-20 18:16:03 +01:00
|
|
|
margin-inline-start: 8px;
|
|
|
|
margin-inline-end: initial;
|
|
|
|
direction: var(--direction);
|
2020-04-22 11:51:50 +02:00
|
|
|
}
|
|
|
|
.active-filters::before {
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
opacity: 0.12;
|
|
|
|
border-radius: 4px;
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
content: "";
|
|
|
|
}
|
2022-02-11 19:34:50 +01:00
|
|
|
.badge {
|
|
|
|
min-width: 20px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
border-radius: 50%;
|
|
|
|
font-weight: 400;
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
line-height: 20px;
|
|
|
|
text-align: center;
|
|
|
|
padding: 0px 4px;
|
|
|
|
color: var(--text-primary-color);
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
2024-02-26 15:14:32 +01:00
|
|
|
inset-inline-end: 0;
|
|
|
|
inset-inline-start: initial;
|
2022-02-11 19:34:50 +01:00
|
|
|
top: 4px;
|
|
|
|
font-size: 0.65em;
|
|
|
|
}
|
2023-12-18 13:59:36 +01:00
|
|
|
.center {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
text-align: center;
|
|
|
|
box-sizing: border-box;
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
padding: 16px;
|
|
|
|
}
|
2024-03-27 15:26:01 +01:00
|
|
|
|
|
|
|
.badge {
|
|
|
|
position: absolute;
|
|
|
|
top: -4px;
|
|
|
|
right: -4px;
|
2024-03-30 13:32:29 +01:00
|
|
|
inset-inline-end: -4px;
|
|
|
|
inset-inline-start: initial;
|
2024-03-27 15:26:01 +01:00
|
|
|
min-width: 16px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
border-radius: 50%;
|
|
|
|
font-weight: 400;
|
|
|
|
font-size: 11px;
|
2024-03-29 16:12:18 +01:00
|
|
|
background-color: var(--primary-color);
|
2024-03-27 15:26:01 +01:00
|
|
|
line-height: 16px;
|
|
|
|
text-align: center;
|
|
|
|
padding: 0px 2px;
|
2024-03-29 16:12:18 +01:00
|
|
|
color: var(--text-primary-color);
|
2024-03-27 15:26:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.narrow-header-row {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 16px;
|
|
|
|
padding: 0 16px;
|
|
|
|
overflow-x: scroll;
|
|
|
|
-ms-overflow-style: none;
|
|
|
|
scrollbar-width: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.selection-bar {
|
|
|
|
background: rgba(var(--rgb-primary-color), 0.1);
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 8px 12px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
font-size: 14px;
|
2024-04-02 10:14:17 +02:00
|
|
|
--ha-assist-chip-container-color: var(--primary-background-color);
|
|
|
|
}
|
|
|
|
|
|
|
|
.selection-controls {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.selection-controls p {
|
|
|
|
margin-left: 8px;
|
|
|
|
margin-inline-start: 8px;
|
|
|
|
margin-inline-end: initial;
|
2024-03-27 15:26:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.center-vertical {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2024-04-02 10:14:17 +02:00
|
|
|
gap: 8px;
|
2024-03-27 15:26:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.relative {
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
ha-assist-chip {
|
|
|
|
--ha-assist-chip-container-shape: 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.select-mode-chip {
|
|
|
|
--md-assist-chip-icon-label-space: 0;
|
2024-03-27 17:26:56 +01:00
|
|
|
--md-assist-chip-trailing-space: 8px;
|
2024-03-27 15:26:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ha-dialog {
|
|
|
|
--mdc-dialog-min-width: calc(
|
|
|
|
100vw - env(safe-area-inset-right) - env(safe-area-inset-left)
|
|
|
|
);
|
|
|
|
--mdc-dialog-max-width: calc(
|
|
|
|
100vw - env(safe-area-inset-right) - env(safe-area-inset-left)
|
|
|
|
);
|
|
|
|
--mdc-dialog-min-height: 100%;
|
|
|
|
--mdc-dialog-max-height: 100%;
|
|
|
|
--vertical-align-dialog: flex-end;
|
|
|
|
--ha-dialog-border-radius: 0;
|
|
|
|
--dialog-content-padding: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.filter-dialog-content {
|
|
|
|
height: calc(100vh - 1px - var(--header-height));
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
2024-04-02 10:14:17 +02:00
|
|
|
|
2024-03-29 16:15:21 +01:00
|
|
|
#sort-by-anchor,
|
2024-04-02 10:14:17 +02:00
|
|
|
#group-by-anchor,
|
|
|
|
ha-button-menu-new ha-assist-chip {
|
2024-03-29 16:15:21 +01:00
|
|
|
--md-assist-chip-trailing-space: 8px;
|
|
|
|
}
|
2020-02-13 19:53:48 +01:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
}
|
2022-09-06 16:48:22 +02:00
|
|
|
|
|
|
|
declare global {
|
|
|
|
interface HTMLElementTagNameMap {
|
|
|
|
"hass-tabs-subpage-data-table": HaTabsSubpageDataTable;
|
|
|
|
}
|
|
|
|
}
|