From 7903541689144478e5e0498ff8db10ef26c453df Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 13 Feb 2020 19:53:48 +0100 Subject: [PATCH] Add toolbars and mobile headers + layout tweaks (#4803) * Add toolbars and mobile headers + layout tweaks * Comments --- src/common/search/search-input.ts | 24 +- src/components/data-table/ha-data-table.ts | 215 +++++++------ .../device/ha-area-devices-picker.ts | 2 +- src/components/device/ha-device-picker.ts | 2 +- src/data/device_registry.ts | 4 + src/layouts/hass-tabs-subpage-data-table.ts | 157 +++++++++ src/layouts/hass-tabs-subpage.ts | 10 +- .../config/automation/ha-automation-editor.ts | 277 ++++++++-------- .../config/devices/ha-config-device-page.ts | 20 +- .../devices/ha-config-devices-dashboard.ts | 233 +++++++++++++- .../config/devices/ha-devices-data-table.ts | 5 +- .../config/entities/ha-config-entities.ts | 297 +++++++++--------- src/panels/config/scene/ha-scene-editor.ts | 27 +- src/panels/config/script/ha-script-editor.ts | 12 +- 14 files changed, 855 insertions(+), 430 deletions(-) create mode 100644 src/layouts/hass-tabs-subpage-data-table.ts diff --git a/src/common/search/search-input.ts b/src/common/search/search-input.ts index b1654a3fe6..e0e5065075 100644 --- a/src/common/search/search-input.ts +++ b/src/common/search/search-input.ts @@ -7,14 +7,18 @@ import { property, } from "lit-element"; import { fireEvent } from "../dom/fire_event"; -import "@polymer/iron-icon/iron-icon"; import "@polymer/paper-input/paper-input"; import "@polymer/paper-icon-button/paper-icon-button"; -import "@material/mwc-button"; +import "../../components/ha-icon"; +import { classMap } from "lit-html/directives/class-map"; @customElement("search-input") class SearchInput extends LitElement { @property() public filter?: string; + @property({ type: Boolean, attribute: "no-label-float" }) + public noLabelFloat? = false; + @property({ type: Boolean, attribute: "no-underline" }) + public noUnderline = false; public focus() { this.shadowRoot!.querySelector("paper-input")!.focus(); @@ -22,18 +26,24 @@ class SearchInput extends LitElement { protected render(): TemplateResult { return html` +
- + ${this.filter && html` - + ${this._filterable ? html`
@@ -181,112 +183,114 @@ export class HaDataTable extends BaseElement { ` : ""} - - - - ${this.selectable - ? html` +
+
+ + + ${this.selectable + ? html` + + ` + : ""} + ${Object.entries(this.columns).map((columnEntry) => { + const [key, column] = columnEntry; + const sorted = key === this._sortColumn; + const classes = { + "mdc-data-table__header-cell--numeric": Boolean( + column.type && column.type === "numeric" + ), + "mdc-data-table__header-cell--icon": Boolean( + column.type && column.type === "icon" + ), + sortable: Boolean(column.sortable), + "not-sorted": Boolean(column.sortable && !sorted), + }; + return html` - ` - : ""} - ${Object.entries(this.columns).map((columnEntry) => { - const [key, column] = columnEntry; - const sorted = key === this._sortColumn; - const classes = { - "mdc-data-table__header-cell--numeric": Boolean( - column.type && column.type === "numeric" - ), - "mdc-data-table__header-cell--icon": Boolean( - column.type && column.type === "icon" - ), - sortable: Boolean(column.sortable), - "not-sorted": Boolean(column.sortable && !sorted), - }; - return html` - + + ${repeat( + this._filteredData!, + (row: DataTableRowData) => row[this.id], + (row: DataTableRowData) => html` + - ${column.sortable + ${this.selectable ? html` - + ` : ""} - ${column.title} - - `; - })} - - - - ${repeat( - this._filteredData!, - (row: DataTableRowData) => row[this.id], - (row: DataTableRowData) => html` - - ${this.selectable - ? html` + ${Object.entries(this.columns).map((columnEntry) => { + const [key, column] = columnEntry; + return html` - ` - : ""} - ${Object.entries(this.columns).map((columnEntry) => { - const [key, column] = columnEntry; - return html` - - `; - })} - - ` - )} - -
+ + + - - + ${column.sortable + ? html` + + ` + : ""} + ${column.title} +
+ + +
- - + ${column.template + ? column.template(row[key], row) + : row[key]} - ${column.template - ? column.template(row[key], row) - : row[key]} -
+ `; + })} + + ` + )} + + +
`; } @@ -434,6 +438,11 @@ export class HaDataTable extends BaseElement { this._debounceSearch(ev.detail.value); } + private async _calcScrollHeight() { + await this.updateComplete; + this._scroller.style.maxHeight = `calc(100% - ${this._header.clientHeight}px)`; + } + static get styles(): CSSResult { return css` /* default mdc styles, colors changed, without checkbox styles */ @@ -584,8 +593,14 @@ export class HaDataTable extends BaseElement { /* custom from here */ + :host { + display: block; + } + .mdc-data-table { display: block; + border-width: var(--data-table-border-width, 1px); + height: 100%; } .mdc-data-table__header-cell { overflow: hidden; @@ -614,6 +629,16 @@ export class HaDataTable extends BaseElement { .table-header { border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12); } + search-input { + position: relative; + top: 2px; + } + .scroller { + overflow: auto; + } + slot[name="header"] { + display: block; + } `; } } diff --git a/src/components/device/ha-area-devices-picker.ts b/src/components/device/ha-area-devices-picker.ts index c6195d7b93..8e691a2388 100644 --- a/src/components/device/ha-area-devices-picker.ts +++ b/src/components/device/ha-area-devices-picker.ts @@ -23,6 +23,7 @@ import { fireEvent } from "../../common/dom/fire_event"; import { DeviceRegistryEntry, subscribeDeviceRegistry, + DeviceEntityLookup, } from "../../data/device_registry"; import { compare } from "../../common/string/compare"; import { PolymerChangedEvent } from "../../polymer-types"; @@ -30,7 +31,6 @@ import { AreaRegistryEntry, subscribeAreaRegistry, } from "../../data/area_registry"; -import { DeviceEntityLookup } from "../../panels/config/devices/ha-devices-data-table"; import { EntityRegistryEntry, subscribeEntityRegistry, diff --git a/src/components/device/ha-device-picker.ts b/src/components/device/ha-device-picker.ts index 4463bb7b80..c232393e4c 100644 --- a/src/components/device/ha-device-picker.ts +++ b/src/components/device/ha-device-picker.ts @@ -22,6 +22,7 @@ import { DeviceRegistryEntry, subscribeDeviceRegistry, computeDeviceName, + DeviceEntityLookup, } from "../../data/device_registry"; import { compare } from "../../common/string/compare"; import { PolymerChangedEvent } from "../../polymer-types"; @@ -29,7 +30,6 @@ import { AreaRegistryEntry, subscribeAreaRegistry, } from "../../data/area_registry"; -import { DeviceEntityLookup } from "../../panels/config/devices/ha-devices-data-table"; import { EntityRegistryEntry, subscribeEntityRegistry, diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index cdd8052b1a..fabfe7da26 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -17,6 +17,10 @@ export interface DeviceRegistryEntry { name_by_user?: string; } +export interface DeviceEntityLookup { + [deviceId: string]: EntityRegistryEntry[]; +} + export interface DeviceRegistryEntryMutableParams { area_id?: string | null; name_by_user?: string | null; diff --git a/src/layouts/hass-tabs-subpage-data-table.ts b/src/layouts/hass-tabs-subpage-data-table.ts new file mode 100644 index 0000000000..c24cdfccf1 --- /dev/null +++ b/src/layouts/hass-tabs-subpage-data-table.ts @@ -0,0 +1,157 @@ +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + query, + TemplateResult, +} from "lit-element"; +import "../components/data-table/ha-data-table"; +// tslint:disable-next-line +import { + HaDataTable, + DataTableColumnContainer, + DataTableRowData, +} from "../components/data-table/ha-data-table"; +import "./hass-tabs-subpage"; +import { HomeAssistant, Route } from "../types"; +// tslint:disable-next-line +import { PageNavigation } from "./hass-tabs-subpage"; + +@customElement("hass-tabs-subpage-data-table") +export class HaTabsSubpageDataTable extends LitElement { + @property() public hass!: HomeAssistant; + @property() public isWide!: boolean; + @property({ type: Boolean, reflect: true }) public narrow!: boolean; + /** + * Object with the columns. + * @type {Object} + */ + @property({ type: Object }) public columns: DataTableColumnContainer = {}; + /** + * Data to show in the table. + * @type {Array} + */ + @property({ type: Array }) public data: DataTableRowData[] = []; + /** + * Should rows be selectable. + * @type {Boolean} + */ + @property({ type: Boolean }) public selectable = false; + /** + * Field with a unique id per entry in data. + * @type {String} + */ + @property({ type: String }) public id = "id"; + /** + * String to filter the data in the data table on. + * @type {String} + */ + @property({ type: String }) public filter = ""; + /** + * What path to use when the back button is pressed. + * @type {String} + * @attr back-path + */ + @property({ type: String, attribute: "back-path" }) public backPath?: string; + /** + * Function to call when the back button is pressed. + * @type {() => void} + */ + @property() public backCallback?: () => void; + @property() public route!: Route; + /** + * Array of tabs to show on the page. + * @type {Array} + */ + @property() public tabs!: PageNavigation[]; + @query("ha-data-table") private _dataTable!: HaDataTable; + + public clearSelection() { + this._dataTable.clearSelection(); + } + + protected render(): TemplateResult { + return html` + + ${this.narrow + ? html` +
+ +
+ +
+
+
+ ` + : ""} + + ${!this.narrow + ? html` +
+ + +
+
+
+ ` + : html` +
+ `} +
+
+ `; + } + + private _handleSearchChange(ev: CustomEvent) { + this.filter = ev.detail.value; + } + + static get styles(): CSSResult { + return css` + ha-data-table { + width: 100%; + --data-table-border-width: 0; + } + :host(:not([narrow])) ha-data-table { + height: calc(100vh - 65px); + display: block; + } + .table-header { + border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12); + } + .search-toolbar { + margin-left: -24px; + color: var(--secondary-text-color); + } + search-input { + position: relative; + top: 2px; + } + `; + } +} diff --git a/src/layouts/hass-tabs-subpage.ts b/src/layouts/hass-tabs-subpage.ts index fc2b689f9e..a3130916df 100644 --- a/src/layouts/hass-tabs-subpage.ts +++ b/src/layouts/hass-tabs-subpage.ts @@ -56,6 +56,11 @@ class HassTabsSubpage extends LitElement { .hassio=${this.hassio} @click=${this._backTapped} > + ${this.narrow + ? html` +
+ ` + : ""}
${this.tabs.map((page, index) => (!page.component || @@ -138,11 +143,6 @@ class HassTabsSubpage extends LitElement { box-sizing: border-box; } - :host([narrow]) .toolbar { - background-color: var(--primary-background-color); - border-bottom: none; - } - #tabbar { display: flex; font-size: 14px; diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 221f5ec6ad..9685340d59 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -77,154 +77,155 @@ export class HaAutomationEditor extends LitElement {
${this._errors}
` : ""} -
- ${this._config - ? html` - - ${this._config.alias} - - ${this.hass.localize( - "ui.panel.config.automation.editor.introduction" - )} - - -
- - - -
- ${this.creatingNew - ? "" - : html` -
-
- - ${this.hass.localize( - "ui.panel.config.automation.editor.enable_disable" - )} -
- - ${this.hass.localize( - "ui.card.automation.trigger" - )} - + ${this._config + ? html` + ${this.narrow + ? html` + ${this._config?.alias} + ` + : ""} + + ${!this.narrow + ? html` + ${this._config.alias} + ` + : ""} + + ${this.hass.localize( + "ui.panel.config.automation.editor.introduction" + )} + + +
+ + + +
+ ${this.creatingNew + ? "" + : html` +
+
+ + ${this.hass.localize( + "ui.panel.config.automation.editor.enable_disable" + )}
- `} - - + + ${this.hass.localize("ui.card.automation.trigger")} + +
+ `} +
+
- - + + + ${this.hass.localize( + "ui.panel.config.automation.editor.triggers.header" + )} + + +

${this.hass.localize( - "ui.panel.config.automation.editor.triggers.header" + "ui.panel.config.automation.editor.triggers.introduction" )} - - -

- ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.introduction" - )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.learn_more" - )} - -
- -
+

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.triggers.learn_more" + )} + +
+ +
- - + + + ${this.hass.localize( + "ui.panel.config.automation.editor.conditions.header" + )} + + +

${this.hass.localize( - "ui.panel.config.automation.editor.conditions.header" + "ui.panel.config.automation.editor.conditions.introduction" )} - - -

- ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.introduction" - )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.learn_more" - )} - -
- -
+

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.conditions.learn_more" + )} + +
+ +
- - + + + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.header" + )} + + +

${this.hass.localize( - "ui.panel.config.automation.editor.actions.header" + "ui.panel.config.automation.editor.actions.introduction" )} - - -

- ${this.hass.localize( - "ui.panel.config.automation.editor.actions.introduction" - )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.learn_more" - )} - -
- -
- ` - : ""} -
+

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.learn_more" + )} + + + +
+ ` + : ""} + ${ + this.narrow + ? html` + ${device.name_by_user || device.name} + ` + : "" + } +
-

${device.name_by_user || device.name}

+ ${ + this.narrow + ? "" + : html` +

${device.name_by_user || device.name}

+ ` + } *:first-child { + padding-top: 0; + } + :host([narrow]) .container { margin-top: 0; } diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index e60b990e92..27b40308a5 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -1,5 +1,4 @@ -import "../../../layouts/hass-tabs-subpage"; -import "./ha-devices-data-table"; +import "../../../layouts/hass-tabs-subpage-data-table"; import { LitElement, @@ -11,11 +10,24 @@ import { css, } from "lit-element"; import { HomeAssistant, Route } from "../../../types"; -import { DeviceRegistryEntry } from "../../../data/device_registry"; +import { + DeviceRegistryEntry, + computeDeviceName, + DeviceEntityLookup, +} from "../../../data/device_registry"; import { EntityRegistryEntry } from "../../../data/entity_registry"; import { ConfigEntry } from "../../../data/config_entries"; import { AreaRegistryEntry } from "../../../data/area_registry"; import { configSections } from "../ha-panel-config"; +import memoizeOne from "memoize-one"; +import { LocalizeFunc } from "../../../common/translations/localize"; +import { DeviceRowData } from "./ha-devices-data-table"; +import { + DataTableColumnContainer, + DataTableRowData, + RowClickedEvent, +} from "../../../components/data-table/ha-data-table"; +import { navigate } from "../../../common/navigate"; @customElement("ha-config-devices-dashboard") export class HaConfigDeviceDashboard extends LitElement { @@ -29,30 +41,219 @@ export class HaConfigDeviceDashboard extends LitElement { @property() public domain!: string; @property() public route!: Route; + private _devices = memoizeOne( + ( + devices: DeviceRegistryEntry[], + entries: ConfigEntry[], + entities: EntityRegistryEntry[], + areas: AreaRegistryEntry[], + domain: string, + localize: LocalizeFunc + ) => { + // Some older installations might have devices pointing at invalid entryIDs + // So we guard for that. + + let outputDevices: DeviceRowData[] = devices; + + const deviceLookup: { [deviceId: string]: DeviceRegistryEntry } = {}; + for (const device of devices) { + deviceLookup[device.id] = device; + } + + const deviceEntityLookup: DeviceEntityLookup = {}; + for (const entity of entities) { + if (!entity.device_id) { + continue; + } + if (!(entity.device_id in deviceEntityLookup)) { + deviceEntityLookup[entity.device_id] = []; + } + deviceEntityLookup[entity.device_id].push(entity); + } + + const entryLookup: { [entryId: string]: ConfigEntry } = {}; + for (const entry of entries) { + entryLookup[entry.entry_id] = entry; + } + + const areaLookup: { [areaId: string]: AreaRegistryEntry } = {}; + for (const area of areas) { + areaLookup[area.area_id] = area; + } + + if (domain) { + outputDevices = outputDevices.filter((device) => + device.config_entries.find( + (entryId) => + entryId in entryLookup && entryLookup[entryId].domain === domain + ) + ); + } + + outputDevices = outputDevices.map((device) => { + return { + ...device, + name: computeDeviceName( + device, + this.hass, + deviceEntityLookup[device.id] + ), + model: device.model || "", + manufacturer: device.manufacturer || "", + area: device.area_id ? areaLookup[device.area_id].name : "No area", + integration: device.config_entries.length + ? device.config_entries + .filter((entId) => entId in entryLookup) + .map( + (entId) => + localize( + `component.${entryLookup[entId].domain}.config.title` + ) || entryLookup[entId].domain + ) + .join(", ") + : "No integration", + battery_entity: this._batteryEntity(device.id, deviceEntityLookup), + }; + }); + + return outputDevices; + } + ); + + private _columns = memoizeOne( + (narrow: boolean): DataTableColumnContainer => + narrow + ? { + name: { + title: "Device", + sortable: true, + filterable: true, + direction: "asc", + template: (name, device: DataTableRowData) => { + const battery = device.battery_entity + ? this.hass.states[device.battery_entity] + : undefined; + // Have to work on a nice layout for mobile + return html` + ${name}
+ ${device.area} | ${device.integration}
+ ${battery && !isNaN(battery.state as any) + ? html` + ${battery.state}% + + ` + : ""} + `; + }, + }, + } + : { + name: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.device" + ), + sortable: true, + filterable: true, + direction: "asc", + }, + manufacturer: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.manufacturer" + ), + sortable: true, + filterable: true, + }, + model: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.model" + ), + sortable: true, + filterable: true, + }, + area: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.area" + ), + sortable: true, + filterable: true, + }, + integration: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.integration" + ), + sortable: true, + filterable: true, + }, + battery_entity: { + title: this.hass.localize( + "ui.panel.config.devices.data_table.battery" + ), + sortable: true, + type: "numeric", + template: (batteryEntity: string) => { + const battery = batteryEntity + ? this.hass.states[batteryEntity] + : undefined; + return battery && !isNaN(battery.state as any) + ? html` + ${battery.state}% + + ` + : html` + - + `; + }, + }, + } + ); + protected render(): TemplateResult { return html` - -
- -
-
+ `; } + private _batteryEntity( + deviceId: string, + deviceEntityLookup: DeviceEntityLookup + ): string | undefined { + const batteryEntity = (deviceEntityLookup[deviceId] || []).find( + (entity) => + this.hass.states[entity.entity_id] && + this.hass.states[entity.entity_id].attributes.device_class === "battery" + ); + + return batteryEntity ? batteryEntity.entity_id : undefined; + } + + private _handleRowClicked(ev: CustomEvent) { + const deviceId = (ev.detail as RowClickedEvent).id; + navigate(this, `/config/devices/device/${deviceId}`); + } + static get styles(): CSSResult { return css` .content { diff --git a/src/panels/config/devices/ha-devices-data-table.ts b/src/panels/config/devices/ha-devices-data-table.ts index fbed2b5365..8a05bd1f95 100644 --- a/src/panels/config/devices/ha-devices-data-table.ts +++ b/src/panels/config/devices/ha-devices-data-table.ts @@ -21,6 +21,7 @@ import { import { DeviceRegistryEntry, computeDeviceName, + DeviceEntityLookup, } from "../../../data/device_registry"; import { EntityRegistryEntry } from "../../../data/entity_registry"; import { ConfigEntry } from "../../../data/config_entries"; @@ -35,10 +36,6 @@ export interface DeviceRowData extends DeviceRegistryEntry { battery_entity?: string; } -export interface DeviceEntityLookup { - [deviceId: string]: EntityRegistryEntry[]; -} - @customElement("ha-devices-data-table") export class HaDevicesDataTable extends LitElement { @property() public hass!: HomeAssistant; diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index f16cfd5fb2..77282d6f94 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -19,8 +19,6 @@ import memoize from "memoize-one"; import { computeDomain } from "../../../common/entity/compute_domain"; import { domainIcon } from "../../../common/entity/domain_icon"; import { stateIcon } from "../../../common/entity/state_icon"; -import "../../../components/data-table/ha-data-table"; -// tslint:disable-next-line import { DataTableColumnContainer, DataTableColumnData, @@ -29,6 +27,7 @@ import { SelectionChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/ha-icon"; +import "../../../common/search/search-input"; import { computeEntityRegistryName, EntityRegistryEntry, @@ -38,7 +37,7 @@ import { } from "../../../data/entity_registry"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-loading-screen"; -import "../../../layouts/hass-tabs-subpage"; +import "../../../layouts/hass-tabs-subpage-data-table"; import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { HomeAssistant, Route } from "../../../types"; import { DialogEntityRegistryDetail } from "./dialog-entity-registry-detail"; @@ -47,6 +46,7 @@ import { showEntityRegistryDetailDialog, } from "./show-dialog-entity-registry-detail"; import { configSections } from "../ha-panel-config"; +import { classMap } from "lit-html/directives/class-map"; @customElement("ha-config-entities") export class HaConfigEntities extends SubscribeMixin(LitElement) { @@ -223,154 +223,136 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { `; } + const headerToolbar = this._selectedEntities.length + ? html` +

+ ${this.hass.localize( + "ui.panel.config.entities.picker.selected", + "number", + this._selectedEntities.length + )} +

+
+ ${!this.narrow + ? html` + ${this.hass.localize( + "ui.panel.config.entities.picker.enable_selected.button" + )} + ${this.hass.localize( + "ui.panel.config.entities.picker.disable_selected.button" + )} + ${this.hass.localize( + "ui.panel.config.entities.picker.remove_selected.button" + )} + ` + : html` + + + ${this.hass.localize( + "ui.panel.config.entities.picker.enable_selected.button" + )} + + + + ${this.hass.localize( + "ui.panel.config.entities.picker.disable_selected.button" + )} + + + + ${this.hass.localize( + "ui.panel.config.entities.picker.remove_selected.button" + )} + + `} +
+ ` + : html` + + + + + + + ${this.hass!.localize( + "ui.panel.config.entities.picker.filter.show_disabled" + )} + + + + ${this.hass!.localize( + "ui.panel.config.entities.picker.filter.show_unavailable" + )} + + + + `; + return html` - -
-
-

- ${this.hass.localize("ui.panel.config.entities.picker.header")} -

-

- ${this.hass.localize( - "ui.panel.config.entities.picker.introduction" - )} -

- -

- ${this.hass.localize( - "ui.panel.config.entities.picker.introduction2" - )} -

- - ${this.hass.localize( - "ui.panel.config.entities.picker.integrations_page" - )} - -
- -
- ${this._selectedEntities.length - ? html` -

- ${this.hass.localize( - "ui.panel.config.entities.picker.selected", - "number", - this._selectedEntities.length - )} -

-
- ${!this.narrow - ? html` - ${this.hass.localize( - "ui.panel.config.entities.picker.enable_selected.button" - )} - ${this.hass.localize( - "ui.panel.config.entities.picker.disable_selected.button" - )} - ${this.hass.localize( - "ui.panel.config.entities.picker.remove_selected.button" - )} - ` - : html` - - - ${this.hass.localize( - "ui.panel.config.entities.picker.enable_selected.button" - )} - - - - ${this.hass.localize( - "ui.panel.config.entities.picker.disable_selected.button" - )} - - - - ${this.hass.localize( - "ui.panel.config.entities.picker.remove_selected.button" - )} - - `} -
- ` - : html` - - - - - - - ${this.hass!.localize( - "ui.panel.config.entities.picker.filter.show_disabled" - )} - - - - ${this.hass!.localize( - "ui.panel.config.entities.picker.filter.show_unavailable" - )} - - - - `} -
-
-
-
+
+ ${headerToolbar} +
+ + `; } @@ -520,14 +502,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height); } - .intro { - padding: 24px 16px; - } - .content { - padding: 4px; - } ha-data-table { width: 100%; + --data-table-border-width: 0; + } + :host(:not([narrow])) ha-data-table { + height: calc(100vh - 65px); + display: block; } ha-switch { margin-top: 16px; @@ -540,12 +521,26 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { } search-input { flex-grow: 1; + position: relative; + top: 2px; + } + .search-toolbar { + display: flex; + justify-content: space-between; + align-items: flex-end; + margin-left: -24px; + color: var(--secondary-text-color); } .selected-txt { font-weight: bold; - margin-top: 38px; padding-left: 16px; } + .table-header .selected-txt { + margin-top: 20px; + } + .search-toolbar .selected-txt { + font-size: 16px; + } .header-btns > mwc-button, .header-btns > paper-icon-button { margin: 8px; diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index 283195e62a..a7a7254b08 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -160,6 +160,10 @@ export class HaSceneEditor extends SubscribeMixin(LitElement) { this._deviceEntityLookup, this._deviceRegistryEntries ); + const name = this.scene + ? computeStateName(this.scene) + : this.hass.localize("ui.panel.config.scene.editor.default_name"); + return html` ${name} + ` + : "" + }
-
- ${ - this.scene - ? computeStateName(this.scene) - : this.hass.localize( - "ui.panel.config.scene.editor.default_name" - ) - } -
+ ${ + !this.narrow + ? html` + ${name} + ` + : "" + }
${this.hass.localize( "ui.panel.config.scene.editor.introduction" diff --git a/src/panels/config/script/ha-script-editor.ts b/src/panels/config/script/ha-script-editor.ts index a27b1a73c3..f98c2997a4 100644 --- a/src/panels/config/script/ha-script-editor.ts +++ b/src/panels/config/script/ha-script-editor.ts @@ -63,7 +63,11 @@ export class HaScriptEditor extends LitElement { @click=${this._deleteConfirm} > `} - + ${this.narrow + ? html` + ${this._config?.alias} + ` + : ""}
${this._errors ? html` @@ -78,7 +82,11 @@ export class HaScriptEditor extends LitElement { ${this._config ? html` - ${this._config.alias} + ${!this.narrow + ? html` + ${this._config.alias} + ` + : ""} ${this.hass.localize( "ui.panel.config.script.editor.introduction"