2020-04-24 15:49:25 +02:00
|
|
|
import "@material/mwc-button/mwc-button";
|
2021-03-28 18:29:55 +02:00
|
|
|
import { mdiFilterVariant } from "@mdi/js";
|
2020-04-24 15:49:25 +02:00
|
|
|
import "@polymer/paper-tooltip/paper-tooltip";
|
2020-02-13 19:53:48 +01:00
|
|
|
import {
|
|
|
|
css,
|
2021-05-07 22:16:14 +02:00
|
|
|
CSSResultGroup,
|
2020-02-13 19:53:48 +01:00
|
|
|
customElement,
|
|
|
|
html,
|
|
|
|
LitElement,
|
|
|
|
property,
|
|
|
|
query,
|
|
|
|
TemplateResult,
|
|
|
|
} from "lit-element";
|
2021-05-10 18:17:16 +02:00
|
|
|
import { LocalizeFunc } from "../common/translations/localize";
|
2021-03-28 18:29:55 +02:00
|
|
|
import { fireEvent } from "../common/dom/fire_event";
|
2020-08-30 10:03:04 +02:00
|
|
|
import { computeRTLDirection } from "../common/util/compute_rtl";
|
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,
|
2020-02-13 19:53:48 +01:00
|
|
|
} from "../components/data-table/ha-data-table";
|
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
|
|
|
/**
|
|
|
|
* List of strings that show what the data is currently filtered by.
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
|
|
|
@property({ type: Array }) public activeFilters?;
|
|
|
|
|
2021-03-28 18:29:55 +02:00
|
|
|
/**
|
|
|
|
* Text to how how many items are hidden.
|
|
|
|
* @type {String}
|
|
|
|
*/
|
|
|
|
@property() public hiddenLabel?: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* How many items are hidden because of active filters.
|
|
|
|
* @type {Number}
|
|
|
|
*/
|
|
|
|
@property({ type: Number }) public numHidden = 0;
|
|
|
|
|
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}
|
|
|
|
*/
|
|
|
|
@property() 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
|
|
|
|
2020-02-13 19:53:48 +01:00
|
|
|
@property() 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}
|
|
|
|
*/
|
|
|
|
@property() public tabs!: PageNavigation[];
|
2020-04-14 18:05:45 +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
|
|
|
|
|
|
|
public clearSelection() {
|
|
|
|
this._dataTable.clearSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected render(): TemplateResult {
|
2021-03-28 18:29:55 +02:00
|
|
|
const hiddenLabel = this.numHidden
|
|
|
|
? this.hiddenLabel ||
|
|
|
|
this.hass.localize(
|
|
|
|
"ui.components.data-table.hidden",
|
|
|
|
"number",
|
|
|
|
this.numHidden
|
|
|
|
) ||
|
|
|
|
this.numHidden
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
const filterInfo = this.activeFilters
|
|
|
|
? html`${this.hass.localize("ui.components.data-table.filtering_by")}
|
|
|
|
${this.activeFilters.join(", ")}
|
|
|
|
${hiddenLabel ? `(${hiddenLabel})` : ""}`
|
|
|
|
: hiddenLabel;
|
|
|
|
|
|
|
|
const headerToolbar = html`<search-input
|
|
|
|
.filter=${this.filter}
|
|
|
|
no-label-float
|
|
|
|
no-underline
|
|
|
|
@value-changed=${this._handleSearchChange}
|
|
|
|
.label=${this.searchLabel ||
|
|
|
|
this.hass.localize("ui.components.data-table.search")}
|
|
|
|
>
|
|
|
|
</search-input
|
|
|
|
>${filterInfo
|
|
|
|
? html`<div class="active-filters">
|
|
|
|
${this.narrow
|
|
|
|
? html`<div>
|
|
|
|
<ha-svg-icon .path="${mdiFilterVariant}"></ha-svg-icon>
|
|
|
|
<paper-tooltip animation-delay="0" position="left">
|
|
|
|
${filterInfo}
|
|
|
|
</paper-tooltip>
|
|
|
|
</div>`
|
|
|
|
: filterInfo}
|
|
|
|
<mwc-button @click=${this._clearFilter}>
|
|
|
|
${this.hass.localize("ui.components.data-table.clear")}
|
|
|
|
</mwc-button>
|
|
|
|
</div>`
|
|
|
|
: ""}<slot name="filter-menu"></slot>`;
|
|
|
|
|
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}
|
2020-02-13 19:53:48 +01:00
|
|
|
>
|
2020-03-30 14:21:36 +02:00
|
|
|
<div slot="toolbar-icon"><slot name="toolbar-icon"></slot></div>
|
2020-02-13 19:53:48 +01:00
|
|
|
${this.narrow
|
|
|
|
? html`
|
|
|
|
<div slot="header">
|
|
|
|
<slot name="header">
|
2021-04-30 21:15:31 +02:00
|
|
|
<div class="search-toolbar">${headerToolbar}</div>
|
2020-02-13 19:53:48 +01:00
|
|
|
</slot>
|
|
|
|
</div>
|
|
|
|
`
|
|
|
|
: ""}
|
|
|
|
<ha-data-table
|
|
|
|
.columns=${this.columns}
|
|
|
|
.data=${this.data}
|
|
|
|
.filter=${this.filter}
|
|
|
|
.selectable=${this.selectable}
|
2020-04-03 17:46:19 +02:00
|
|
|
.hasFab=${this.hasFab}
|
2020-02-13 19:53:48 +01:00
|
|
|
.id=${this.id}
|
2020-03-11 08:42:52 +01:00
|
|
|
.noDataText=${this.noDataText}
|
2020-07-07 09:24:09 +02:00
|
|
|
.dir=${computeRTLDirection(this.hass)}
|
2020-10-15 15:57:05 +02:00
|
|
|
.clickable=${this.clickable}
|
2020-12-12 20:38:10 +01:00
|
|
|
.appendRow=${this.appendRow}
|
2020-02-13 19:53:48 +01:00
|
|
|
>
|
|
|
|
${!this.narrow
|
|
|
|
? html`
|
|
|
|
<div slot="header">
|
|
|
|
<slot name="header">
|
2021-04-30 21:15:31 +02:00
|
|
|
<div class="table-header">${headerToolbar}</div>
|
2020-07-30 18:27:27 +02:00
|
|
|
</slot>
|
2020-02-13 19:53:48 +01:00
|
|
|
</div>
|
|
|
|
`
|
2020-04-14 18:05:45 +02:00
|
|
|
: html` <div slot="header"></div> `}
|
2020-02-13 19:53:48 +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>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
|
|
|
private _handleSearchChange(ev: CustomEvent) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-04-22 11:51:50 +02:00
|
|
|
private _clearFilter() {
|
2021-03-28 18:29:55 +02:00
|
|
|
fireEvent(this, "clear-filter");
|
2020-04-22 11:51:50 +02:00
|
|
|
}
|
|
|
|
|
2021-05-07 22:16:14 +02:00
|
|
|
static get styles(): CSSResultGroup {
|
2020-02-13 19:53:48 +01:00
|
|
|
return css`
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
:host(:not([narrow])) ha-data-table {
|
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;
|
|
|
|
}
|
|
|
|
.table-header {
|
|
|
|
border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12);
|
2020-04-09 14:44:08 +02:00
|
|
|
padding: 0 16px;
|
2020-04-22 11:51:50 +02:00
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
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);
|
|
|
|
}
|
|
|
|
search-input {
|
|
|
|
position: relative;
|
|
|
|
top: 2px;
|
2020-04-22 11:51:50 +02:00
|
|
|
flex-grow: 1;
|
2020-02-13 19:53:48 +01:00
|
|
|
}
|
2020-04-02 16:39:59 +02:00
|
|
|
search-input.header {
|
|
|
|
left: -8px;
|
|
|
|
}
|
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;
|
|
|
|
font-size: 14px;
|
|
|
|
}
|
|
|
|
.active-filters ha-icon {
|
|
|
|
color: var(--primary-color);
|
|
|
|
}
|
|
|
|
.active-filters mwc-button {
|
|
|
|
margin-left: 8px;
|
|
|
|
}
|
|
|
|
.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: "";
|
|
|
|
}
|
2020-02-13 19:53:48 +01:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
}
|