From f5b4cc067ed6d52d5706664837214df10e97d05e Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 24 Aug 2020 21:59:18 -0500 Subject: [PATCH 01/13] Add by entity picker --- .../editor/card-editor/hui-card-picker.ts | 211 ++++++++++++++---- .../card-editor/hui-dialog-edit-card.ts | 31 +++ src/translations/en.json | 5 +- yarn.lock | 6 +- 4 files changed, 201 insertions(+), 52 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index dce01a77c445..4247c20bf42e 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -1,4 +1,7 @@ +import "@material/mwc-tab-bar/mwc-tab-bar"; +import "@material/mwc-tab/mwc-tab"; import Fuse from "fuse.js"; +import memoizeOne from "memoize-one"; import { css, CSSResult, @@ -11,30 +14,41 @@ import { TemplateResult, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; +import { styleMap } from "lit-html/directives/style-map"; import { until } from "lit-html/directives/until"; -import memoizeOne from "memoize-one"; -import { fireEvent } from "../../../../common/dom/fire_event"; -import "../../../../common/search/search-input"; +import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; import { UNAVAILABLE_STATES } from "../../../../data/entity"; -import { LovelaceCardConfig, LovelaceConfig } from "../../../../data/lovelace"; import { CustomCardEntry, customCards, CUSTOM_TYPE_PREFIX, getCustomCardEntry, } from "../../../../data/lovelace_custom_cards"; -import { HomeAssistant } from "../../../../types"; import { - calcUnusedEntities, computeUsedEntities, + calcUnusedEntities, } from "../../common/compute-unused-entities"; import { tryCreateCardElement } from "../../create-element/create-card-element"; -import { LovelaceCard } from "../../types"; import { getCardStubConfig } from "../get-card-stub-config"; -import { CardPickTarget, Card } from "../types"; import { coreCards } from "../lovelace-cards"; -import { styleMap } from "lit-html/directives/style-map"; +import { computeStateName } from "../../../../common/entity/compute_state_name"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { computeRTLDirection } from "../../../../common/util/compute_rtl"; +import type { + DataTableRowData, + SelectionChangedEvent, +} from "../../../../components/data-table/ha-data-table"; +import type { CardPickTarget, Card } from "../types"; +import type { LovelaceCard } from "../../types"; +import type { HomeAssistant } from "../../../../types"; +import type { + LovelaceCardConfig, + LovelaceConfig, +} from "../../../../data/lovelace"; +import "../../../../components/entity/state-badge"; import "../../../../components/ha-circular-progress"; +import "../../../../components/data-table/ha-data-table"; +import "../../../../common/search/search-input"; interface CardElement { card: Card; @@ -53,14 +67,16 @@ export class HuiCardPicker extends LitElement { @internalProperty() private _filter = ""; - private _unusedEntities?: string[]; - - private _usedEntities?: string[]; - @internalProperty() private _width?: number; @internalProperty() private _height?: number; + @internalProperty() private _tabIndex = 0; + + private _unusedEntities?: string[]; + + private _usedEntities?: string[]; + private _filterCards = memoizeOne( (cardElements: CardElement[], filter?: string): CardElement[] => { if (!filter) { @@ -94,45 +110,83 @@ export class HuiCardPicker extends LitElement { } return html` - -
{ + this._tabIndex = tabIndex.detail.index; + }} > -
- ${this._filterCards(this._cards, this._filter).map( - (cardElement: CardElement) => cardElement.element - )} -
-
-
-
- ${this.hass!.localize( - `ui.panel.lovelace.editor.card.generic.manual` + + + + ${this._tabIndex === 0 + ? html` + +
+
+ ${this._filterCards(this._cards, this._filter).map( + (cardElement: CardElement) => cardElement.element + )} +
+
+
+
+ ${this.hass!.localize( + `ui.panel.lovelace.editor.card.generic.manual` + )} +
+
+ ${this.hass!.localize( + `ui.panel.lovelace.editor.card.generic.manual_description` + )} +
+
+
-
- ${this.hass!.localize( - `ui.panel.lovelace.editor.card.generic.manual_description` - )} + ` + : html` +
+ { + const stateObj = this.hass!.states[entity]; + return { + icon: "", + entity_id: entity, + stateObj, + name: computeStateName(stateObj), + domain: computeDomain(entity), + last_changed: stateObj!.last_changed, + }; + }) as DataTableRowData[]} + .dir=${computeRTLDirection(this.hass)} + .searchLabel=${this.hass.localize( + "ui.panel.lovelace.unused_entities.search" + )} + @selection-changed=${this._handleSelectionChanged} + >
-
-
-
+ `} `; } @@ -232,6 +286,46 @@ export class HuiCardPicker extends LitElement { this._filter = value; } + private _columns() { + return { + icon: { + title: "", + type: "icon", + template: (_icon, entity: any) => html` + + `, + }, + name: { + title: this.hass!.localize( + "ui.panel.lovelace.editor.cardpicker.entity" + ), + sortable: true, + filterable: true, + grows: true, + direction: "asc", + template: (name, entity: any) => html` +
+ ${name} +
+ ${entity.stateObj.entity_id} +
+
+ `, + }, + domain: { + title: this.hass!.localize( + "ui.panel.lovelace.editor.cardpicker.domain" + ), + sortable: true, + filterable: true, + width: "25%", + }, + }; + } + static get styles(): CSSResult[] { return [ css` @@ -307,6 +401,19 @@ export class HuiCardPicker extends LitElement { .manual { max-width: none; } + + ha-data-table { + --data-table-border-width: 0; + flex-grow: 1; + margin-top: -20px; + } + + .container { + display: flex; + flex-direction: column; + height: 100%; + min-height: calc(100vh - 112px); + } `, ]; } @@ -318,6 +425,14 @@ export class HuiCardPicker extends LitElement { fireEvent(this, "config-changed", { config }); } + private _handleSelectionChanged( + ev: HASSDomEvent + ): void { + const selectedEntities = ev.detail.value; + + fireEvent(this, "selected-changed", { selectedEntities }); + } + private _tryCreateCardElement(cardConfig: LovelaceCardConfig) { const element = tryCreateCardElement(cardConfig) as LovelaceCard; element.hass = this.hass; diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index effc79466537..b5faade2ffa1 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -33,11 +33,13 @@ import { mdiHelpCircle } from "@mdi/js"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import { HassDialog } from "../../../../dialogs/make-dialog-manager"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; +import { showSuggestCardDialog } from "./show-suggest-card-dialog"; declare global { // for fire event interface HASSDomEvents { "reload-lovelace": undefined; + "selected-changed": SelectedChangedEvent; } // for add event listener interface HTMLElementEventMap { @@ -45,6 +47,10 @@ declare global { } } +interface SelectedChangedEvent { + selectedEntities: string[]; +} + @customElement("hui-dialog-edit-card") export class HuiDialogEditCard extends LitElement implements HassDialog { @property() protected hass!: HomeAssistant; @@ -69,6 +75,8 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @internalProperty() private _dirty = false; + @internalProperty() private _selectedEntities: string[] = []; + public async showDialog(params: EditCardDialogParams): Promise { this._params = params; this._GUImode = true; @@ -175,6 +183,7 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { .lovelace=${this._params.lovelaceConfig} .hass=${this.hass} @config-changed=${this._handleCardPicked} + @selected-changed=${this._handleSelectedChanged} > ` : html` @@ -247,6 +256,13 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { ` : ``} + ${this._selectedEntities.length + ? html` + + ${this.hass!.localize("ui.common.continue")} + + ` + : ""}
`; @@ -383,6 +399,10 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { this._dirty = true; } + private _handleSelectedChanged(ev: CustomEvent): void { + this._selectedEntities = ev.detail.selectedEntities; + } + private _handleGUIModeChanged(ev: HASSDomEvent): void { ev.stopPropagation(); this._GUImode = ev.detail.guiMode; @@ -463,6 +483,17 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { showSaveSuccessToast(this, this.hass); this.closeDialog(); } + + private _suggestCards(): void { + showSuggestCardDialog(this, { + lovelaceConfig: this._params!.lovelaceConfig, + saveConfig: this._params!.saveConfig, + path: this._params!.path as [number], + entities: this._selectedEntities, + }); + + this.closeDialog(); + } } declare global { diff --git a/src/translations/en.json b/src/translations/en.json index 48d51fa5aa81..6f73ede490bf 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -253,6 +253,7 @@ }, "common": { "and": "and", + "continue": "Continue", "previous": "Previous", "loading": "Loading", "refresh": "Refresh", @@ -2168,7 +2169,9 @@ }, "cardpicker": { "no_description": "No description available.", - "custom_card": "Custom" + "custom_card": "Custom", + "domain": "Domain", + "entity": "Entity" } }, "warning": { diff --git a/yarn.lock b/yarn.lock index e6976c9b3627..fdf3f3496871 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1345,7 +1345,7 @@ "@babel/runtime" "^7.7.2" core-js "^3.4.1" -"@material/animation@8.0.0-canary.096a7a066.0", "@material/animation@8.0.0-canary.a78ceb112.0", "@material/animation@=8.0.0-canary.096a7a066.0": +"@material/animation@8.0.0-canary.096a7a066.0", "@material/animation@8.0.0-canary.a78ceb112.0": version "8.0.0-canary.096a7a066.0" resolved "https://registry.yarnpkg.com/@material/animation/-/animation-8.0.0-canary.096a7a066.0.tgz#9c1b3d31858889e04e722ca8f1ade7ae3c54f7e6" integrity sha512-hGL6sMGcyd9JoxcyhRkAhD6KKQwZVRkhaFcra9YMBYHUbWRxfUbfDTjUZ3ZxmLDDcsjL4Hqjblet6Xmtq3Br5g== @@ -1463,7 +1463,7 @@ "@material/feature-targeting" "8.0.0-canary.096a7a066.0" "@material/theme" "8.0.0-canary.096a7a066.0" -"@material/feature-targeting@8.0.0-canary.096a7a066.0", "@material/feature-targeting@8.0.0-canary.a78ceb112.0", "@material/feature-targeting@=8.0.0-canary.096a7a066.0": +"@material/feature-targeting@8.0.0-canary.096a7a066.0", "@material/feature-targeting@8.0.0-canary.a78ceb112.0": version "8.0.0-canary.096a7a066.0" resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-8.0.0-canary.096a7a066.0.tgz#fca721c287b08e0868467ee60daa5d32aad16430" integrity sha512-5nxnG08PjdwhrLMNxfeCOImbdEtP/bVveOVr72hdqldHuwfnzNjp0lwWAAh/QZrpJNl4Ve2Cnp/LkRnlOELIkw== @@ -1839,7 +1839,7 @@ "@material/typography" "8.0.0-canary.096a7a066.0" tslib "^1.9.3" -"@material/theme@8.0.0-canary.096a7a066.0", "@material/theme@8.0.0-canary.a78ceb112.0", "@material/theme@=8.0.0-canary.096a7a066.0": +"@material/theme@8.0.0-canary.096a7a066.0", "@material/theme@8.0.0-canary.a78ceb112.0": version "8.0.0-canary.096a7a066.0" resolved "https://registry.yarnpkg.com/@material/theme/-/theme-8.0.0-canary.096a7a066.0.tgz#f657eaa545797ee3e6a2d96e4a61f844ad3dc425" integrity sha512-FdAUEjq7KJ835sobJQL0w0XWD5PabXl77HmBuy5F3bEYbYterWOutvuHbTkAEN6sTzgHCKhdoMubRxMKidqafA== From 751f393e1ade3a606dc5cdff16fd3431b16260a3 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 10:52:22 -0500 Subject: [PATCH 02/13] Comments --- .../editor/card-editor/hui-card-picker.ts | 26 ++++---- .../card-editor/hui-dialog-edit-card.ts | 65 ++++++++++++++----- 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 4247c20bf42e..65df1a3a8837 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -1,7 +1,10 @@ import "@material/mwc-tab-bar/mwc-tab-bar"; import "@material/mwc-tab/mwc-tab"; import Fuse from "fuse.js"; +// eslint-disable-next-line import/no-duplicates import memoizeOne from "memoize-one"; +// eslint-disable-next-line import/no-duplicates +import memoize from "memoize-one"; import { css, CSSResult, @@ -59,6 +62,8 @@ interface CardElement { export class HuiCardPicker extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; + @property({ attribute: false }) public tabIndex = 0; + @internalProperty() private _cards: CardElement[] = []; public lovelace?: LovelaceConfig; @@ -71,8 +76,6 @@ export class HuiCardPicker extends LitElement { @internalProperty() private _height?: number; - @internalProperty() private _tabIndex = 0; - private _unusedEntities?: string[]; private _usedEntities?: string[]; @@ -110,16 +113,7 @@ export class HuiCardPicker extends LitElement { } return html` - { - this._tabIndex = tabIndex.detail.index; - }} - > - - - - ${this._tabIndex === 0 + ${this.tabIndex === 0 ? html` { + .data=${this._allEntities(this.hass).map((entity) => { const stateObj = this.hass!.states[entity]; return { icon: "", @@ -200,6 +194,10 @@ export class HuiCardPicker extends LitElement { return true; } + if (changedProps.has("tabIndex")) { + return true; + } + return false; } @@ -326,6 +324,8 @@ export class HuiCardPicker extends LitElement { }; } + private _allEntities = memoize((hass) => Object.keys(hass.states)); + static get styles(): CSSResult[] { return [ css` diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index b5faade2ffa1..ff6672fd0bd6 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -77,6 +77,8 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @internalProperty() private _selectedEntities: string[] = []; + @internalProperty() private _tabIndex = 0; + public async showDialog(params: EditCardDialogParams): Promise { this._params = params; this._GUImode = true; @@ -108,6 +110,8 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { } protected updated(changedProps: PropertyValues): void { + console.log("updated"); + if ( !this._cardConfig || this._documentationURL !== undefined || @@ -158,30 +162,47 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @keydown=${this._ignoreKeydown} @closed=${this._cancel} @opened=${this._opened} - .heading=${html`${heading} - ${this._documentationURL !== undefined - ? html` - - - - - - ` - : ""}`} + .heading=${html` + ${heading} + ${this._documentationURL !== undefined + ? html` + + + + + + ` + : ""} + ${!this._cardConfig + ? html` + + this._handleTabChanged(ev)} + > + + + + ` + : ""} + `} >
${this._cardConfig === undefined ? html` + ${console.log(this._tabIndex)} @@ -399,6 +420,16 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { this._dirty = true; } + private _handleTabChanged(ev: CustomEvent): void { + const newTab = ev.detail.index; + if (newTab === this._tabIndex) { + return; + } + + this._tabIndex = ev.detail.index; + this._selectedEntities = []; + } + private _handleSelectedChanged(ev: CustomEvent): void { this._selectedEntities = ev.detail.selectedEntities; } From 289d0f101e4af148714eb5663094913b23ab60b6 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 10:57:23 -0500 Subject: [PATCH 03/13] console.bye --- src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index ff6672fd0bd6..227c854701e1 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -110,8 +110,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { } protected updated(changedProps: PropertyValues): void { - console.log("updated"); - if ( !this._cardConfig || this._documentationURL !== undefined || @@ -198,7 +196,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
${this._cardConfig === undefined ? html` - ${console.log(this._tabIndex)} Date: Tue, 25 Aug 2020 12:21:39 -0500 Subject: [PATCH 04/13] Localize --- .../editor/card-editor/hui-dialog-edit-card.ts | 12 ++++++++++-- src/translations/en.json | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 227c854701e1..8860d9652da9 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -186,8 +186,16 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @MDCTabBar:activated=${(ev: CustomEvent) => this._handleTabChanged(ev)} > - - + + ` : ""} diff --git a/src/translations/en.json b/src/translations/en.json index 6f73ede490bf..4d7cfafd6672 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2171,7 +2171,9 @@ "no_description": "No description available.", "custom_card": "Custom", "domain": "Domain", - "entity": "Entity" + "entity": "Entity", + "by_entity": "By Entity", + "by_card": "By Card" } }, "warning": { From 20f58b676d109ce6fe4c646a831a57fd74549785 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 15:09:04 -0500 Subject: [PATCH 05/13] use heading slot --- .../card-editor/hui-dialog-edit-card.ts | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 8860d9652da9..9119cfb731d9 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -34,6 +34,7 @@ import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import { HassDialog } from "../../../../dialogs/make-dialog-manager"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import { showSuggestCardDialog } from "./show-suggest-card-dialog"; +import "../../../../components/ha-header-bar"; declare global { // for fire event @@ -160,28 +161,32 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @keydown=${this._ignoreKeydown} @closed=${this._cancel} @opened=${this._opened} - .heading=${html` - ${heading} - ${this._documentationURL !== undefined - ? html` - - - - - - ` - : ""} + .heading=${true} + > +
+ +
${heading}
+ ${this._documentationURL !== undefined + ? html` + + + + + + ` + : ""} +
${!this._cardConfig ? html` this._handleTabChanged(ev)} @@ -199,8 +204,7 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { ` : ""} - `} - > +
${this._cardConfig === undefined ? html` @@ -324,6 +328,14 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { --mdc-dialog-max-width: 845px; } + ha-header-bar { + --mdc-theme-on-primary: var(--primary-text-color); + --mdc-theme-primary: var(--mdc-theme-surface); + flex-shrink: 0; + border-bottom: 1px solid + var(--mdc-dialog-scroll-divider-color, rgba(0, 0, 0, 0.12)); + } + .center { margin-left: auto; margin-right: auto; @@ -400,6 +412,13 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { align-items: center; justify-content: space-between; } + .header_button { + color: inherit; + text-decoration: none; + } + mwc-tab-bar { + padding-top: 8px; + } `, ]; } From a0f79f8bb3c690126963a24368eb803a31924819 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 16:43:29 -0500 Subject: [PATCH 06/13] Creating card to new dialog Make entity picker --- .../editor/card-editor/hui-card-picker.ts | 341 ++++++----------- .../card-editor/hui-dialog-create-card.ts | 248 ++++++++++++ .../card-editor/hui-dialog-edit-card.ts | 359 +++++++----------- .../editor/card-editor/hui-entity-picker.ts | 131 +++++++ .../card-editor/show-create-card-dialog.ts | 25 ++ src/panels/lovelace/views/hui-view.ts | 4 +- 6 files changed, 670 insertions(+), 438 deletions(-) create mode 100644 src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts create mode 100644 src/panels/lovelace/editor/card-editor/hui-entity-picker.ts create mode 100644 src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 65df1a3a8837..5e060110e5c0 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -1,10 +1,7 @@ import "@material/mwc-tab-bar/mwc-tab-bar"; import "@material/mwc-tab/mwc-tab"; import Fuse from "fuse.js"; -// eslint-disable-next-line import/no-duplicates import memoizeOne from "memoize-one"; -// eslint-disable-next-line import/no-duplicates -import memoize from "memoize-one"; import { css, CSSResult, @@ -19,7 +16,8 @@ import { import { classMap } from "lit-html/directives/class-map"; import { styleMap } from "lit-html/directives/style-map"; import { until } from "lit-html/directives/until"; -import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; + +import { fireEvent } from "../../../../common/dom/fire_event"; import { UNAVAILABLE_STATES } from "../../../../data/entity"; import { CustomCardEntry, @@ -34,13 +32,7 @@ import { import { tryCreateCardElement } from "../../create-element/create-card-element"; import { getCardStubConfig } from "../get-card-stub-config"; import { coreCards } from "../lovelace-cards"; -import { computeStateName } from "../../../../common/entity/compute_state_name"; -import { computeDomain } from "../../../../common/entity/compute_domain"; -import { computeRTLDirection } from "../../../../common/util/compute_rtl"; -import type { - DataTableRowData, - SelectionChangedEvent, -} from "../../../../components/data-table/ha-data-table"; + import type { CardPickTarget, Card } from "../types"; import type { LovelaceCard } from "../../types"; import type { HomeAssistant } from "../../../../types"; @@ -48,9 +40,8 @@ import type { LovelaceCardConfig, LovelaceConfig, } from "../../../../data/lovelace"; -import "../../../../components/entity/state-badge"; + import "../../../../components/ha-circular-progress"; -import "../../../../components/data-table/ha-data-table"; import "../../../../common/search/search-input"; interface CardElement { @@ -62,8 +53,6 @@ interface CardElement { export class HuiCardPicker extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property({ attribute: false }) public tabIndex = 0; - @internalProperty() private _cards: CardElement[] = []; public lovelace?: LovelaceConfig; @@ -113,74 +102,45 @@ export class HuiCardPicker extends LitElement { } return html` - ${this.tabIndex === 0 - ? html` - +
+
+ ${this._filterCards(this._cards, this._filter).map( + (cardElement: CardElement) => cardElement.element + )} +
+
+
+
+ ${this.hass!.localize( + `ui.panel.lovelace.editor.card.generic.manual` )} - > -
-
- ${this._filterCards(this._cards, this._filter).map( - (cardElement: CardElement) => cardElement.element - )} -
-
-
-
- ${this.hass!.localize( - `ui.panel.lovelace.editor.card.generic.manual` - )} -
-
- ${this.hass!.localize( - `ui.panel.lovelace.editor.card.generic.manual_description` - )} -
-
-
- ` - : html` -
- { - const stateObj = this.hass!.states[entity]; - return { - icon: "", - entity_id: entity, - stateObj, - name: computeStateName(stateObj), - domain: computeDomain(entity), - last_changed: stateObj!.last_changed, - }; - }) as DataTableRowData[]} - .dir=${computeRTLDirection(this.hass)} - .searchLabel=${this.hass.localize( - "ui.panel.lovelace.unused_entities.search" - )} - @selection-changed=${this._handleSelectionChanged} - > +
+ ${this.hass!.localize( + `ui.panel.lovelace.editor.card.generic.manual_description` + )}
- `} +
+
+
`; } @@ -284,140 +244,6 @@ export class HuiCardPicker extends LitElement { this._filter = value; } - private _columns() { - return { - icon: { - title: "", - type: "icon", - template: (_icon, entity: any) => html` - - `, - }, - name: { - title: this.hass!.localize( - "ui.panel.lovelace.editor.cardpicker.entity" - ), - sortable: true, - filterable: true, - grows: true, - direction: "asc", - template: (name, entity: any) => html` -
- ${name} -
- ${entity.stateObj.entity_id} -
-
- `, - }, - domain: { - title: this.hass!.localize( - "ui.panel.lovelace.editor.cardpicker.domain" - ), - sortable: true, - filterable: true, - width: "25%", - }, - }; - } - - private _allEntities = memoize((hass) => Object.keys(hass.states)); - - static get styles(): CSSResult[] { - return [ - css` - .cards-container { - display: grid; - grid-gap: 8px 8px; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - margin-top: 20px; - } - - .card { - height: 100%; - max-width: 500px; - display: flex; - flex-direction: column; - border-radius: 4px; - border: 1px solid var(--divider-color); - background: var(--primary-background-color, #fafafa); - cursor: pointer; - box-sizing: border-box; - position: relative; - } - - .card-header { - color: var(--ha-card-header-color, --primary-text-color); - font-family: var(--ha-card-header-font-family, inherit); - font-size: 16px; - font-weight: bold; - letter-spacing: -0.012em; - line-height: 20px; - padding: 12px 16px; - display: block; - text-align: center; - background: var( - --ha-card-background, - var(--card-background-color, white) - ); - border-radius: 0 0 4px 4px; - border-bottom: 1px solid var(--divider-color); - } - - .preview { - pointer-events: none; - margin: 20px; - flex-grow: 1; - display: flex; - align-items: center; - justify-content: center; - } - - .preview > :first-child { - zoom: 0.6; - display: block; - width: 100%; - } - - .description { - text-align: center; - } - - .spinner { - align-items: center; - justify-content: center; - } - - .overlay { - position: absolute; - width: 100%; - height: 100%; - z-index: 1; - } - - .manual { - max-width: none; - } - - ha-data-table { - --data-table-border-width: 0; - flex-grow: 1; - margin-top: -20px; - } - - .container { - display: flex; - flex-direction: column; - height: 100%; - min-height: calc(100vh - 112px); - } - `, - ]; - } - private _cardPicked(ev: Event): void { const config: LovelaceCardConfig = (ev.currentTarget! as CardPickTarget) .config; @@ -425,14 +251,6 @@ export class HuiCardPicker extends LitElement { fireEvent(this, "config-changed", { config }); } - private _handleSelectionChanged( - ev: HASSDomEvent - ): void { - const selectedEntities = ev.detail.value; - - fireEvent(this, "selected-changed", { selectedEntities }); - } - private _tryCreateCardElement(cardConfig: LovelaceCardConfig) { const element = tryCreateCardElement(cardConfig) as LovelaceCard; element.hass = this.hass; @@ -521,6 +339,85 @@ export class HuiCardPicker extends LitElement {
`; } + + static get styles(): CSSResult[] { + return [ + css` + .cards-container { + display: grid; + grid-gap: 8px 8px; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + margin-top: 20px; + } + + .card { + height: 100%; + max-width: 500px; + display: flex; + flex-direction: column; + border-radius: 4px; + border: 1px solid var(--divider-color); + background: var(--primary-background-color, #fafafa); + cursor: pointer; + box-sizing: border-box; + position: relative; + } + + .card-header { + color: var(--ha-card-header-color, --primary-text-color); + font-family: var(--ha-card-header-font-family, inherit); + font-size: 16px; + font-weight: bold; + letter-spacing: -0.012em; + line-height: 20px; + padding: 12px 16px; + display: block; + text-align: center; + background: var( + --ha-card-background, + var(--card-background-color, white) + ); + border-radius: 0 0 4px 4px; + border-bottom: 1px solid var(--divider-color); + } + + .preview { + pointer-events: none; + margin: 20px; + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + } + + .preview > :first-child { + zoom: 0.6; + display: block; + width: 100%; + } + + .description { + text-align: center; + } + + .spinner { + align-items: center; + justify-content: center; + } + + .overlay { + position: absolute; + width: 100%; + height: 100%; + z-index: 1; + } + + .manual { + max-width: none; + } + `, + ]; + } } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts new file mode 100644 index 000000000000..a2ee5b4e7f48 --- /dev/null +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts @@ -0,0 +1,248 @@ +import { + css, + CSSResultArray, + customElement, + html, + LitElement, + property, + internalProperty, + TemplateResult, +} from "lit-element"; + +import { fireEvent } from "../../../../common/dom/fire_event"; +import { haStyleDialog } from "../../../../resources/styles"; +import { showSuggestCardDialog } from "./show-suggest-card-dialog"; + +import type { LovelaceViewConfig } from "../../../../data/lovelace"; +import type { HomeAssistant } from "../../../../types"; +import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; +import { + EditCardDialogParams, + showEditCardDialog, +} from "./show-edit-card-dialog"; + +import "./hui-card-picker"; +import "./hui-entity-picker"; +import "../../../../components/ha-dialog"; +import "../../../../components/ha-header-bar"; + +declare global { + interface HASSDomEvents { + "selected-changed": SelectedChangedEvent; + } +} + +interface SelectedChangedEvent { + selectedEntities: string[]; +} + +@customElement("hui-dialog-create-card") +export class HuiCreateDialogCard extends LitElement implements HassDialog { + @property({ attribute: false }) protected hass!: HomeAssistant; + + @internalProperty() private _params?: EditCardDialogParams; + + @internalProperty() private _viewConfig!: LovelaceViewConfig; + + @internalProperty() private _selectedEntities: string[] = []; + + @internalProperty() private _currTabIndex = 0; + + public async showDialog(params: EditCardDialogParams): Promise { + this._params = params; + const [view] = params.path; + this._viewConfig = params.lovelaceConfig.views[view]; + } + + public closeDialog(): boolean { + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + return true; + } + + protected render(): TemplateResult { + if (!this._params) { + return html``; + } + + return html` + +
+ +
+ ${this._viewConfig.title + ? this.hass!.localize( + "ui.panel.lovelace.editor.edit_card.pick_card_view_title", + "name", + `"${this._viewConfig.title}"` + ) + : this.hass!.localize( + "ui.panel.lovelace.editor.edit_card.pick_card" + )} +
+
+ + this._handleTabChanged(ev)} + > + + + +
+ ${this._currTabIndex === 0 + ? html` + + ` + : html` + + `} + +
+ + ${this.hass!.localize("ui.common.cancel")} + + ${this._currTabIndex === 1 + ? html` + + ${this.hass!.localize("ui.common.continue")} + + ` + : ""} +
+
+ `; + } + + private _ignoreKeydown(ev: KeyboardEvent) { + ev.stopPropagation(); + } + + static get styles(): CSSResultArray { + return [ + haStyleDialog, + css` + @media all and (max-width: 450px), all and (max-height: 500px) { + /* overrule the ha-style-dialog max-height on small screens */ + ha-dialog { + --mdc-dialog-max-height: 100%; + height: 100%; + } + } + + @media all and (min-width: 850px) { + ha-dialog { + --mdc-dialog-min-width: 845px; + } + } + + ha-dialog { + --mdc-dialog-max-width: 845px; + } + + ha-header-bar { + --mdc-theme-on-primary: var(--primary-text-color); + --mdc-theme-primary: var(--mdc-theme-surface); + flex-shrink: 0; + border-bottom: 1px solid + var(--mdc-dialog-scroll-divider-color, rgba(0, 0, 0, 0.12)); + } + + @media (min-width: 1200px) { + ha-dialog { + --mdc-dialog-max-width: calc(100% - 32px); + --mdc-dialog-min-width: 1000px; + } + } + + .header_button { + color: inherit; + text-decoration: none; + } + + mwc-tab-bar { + padding-top: 8px; + } + `, + ]; + } + + private _handleCardPicked(ev) { + const config = ev.detail.config; + if (this._params!.entities && this._params!.entities.length) { + if (Object.keys(config).includes("entities")) { + config.entities = this._params!.entities; + } else if (Object.keys(config).includes("entity")) { + config.entity = this._params!.entities[0]; + } + } + + showEditCardDialog(this, { + lovelaceConfig: this._params!.lovelaceConfig, + saveConfig: this._params!.saveConfig, + path: this._params!.path, + cardConfig: config, + }); + + this.closeDialog(); + } + + private _handleTabChanged(ev: CustomEvent): void { + const newTab = ev.detail.index; + if (newTab === this._currTabIndex) { + return; + } + + this._currTabIndex = ev.detail.index; + this._selectedEntities = []; + } + + private _handleSelectedChanged(ev: CustomEvent): void { + this._selectedEntities = ev.detail.selectedEntities; + } + + private _cancel(ev?: Event) { + if (ev) { + ev.stopPropagation(); + } + this.closeDialog(); + } + + private _suggestCards(): void { + showSuggestCardDialog(this, { + lovelaceConfig: this._params!.lovelaceConfig, + saveConfig: this._params!.saveConfig, + path: this._params!.path as [number], + entities: this._selectedEntities, + }); + + this.closeDialog(); + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-dialog-create-card": HuiCreateDialogCard; + } +} diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 9119cfb731d9..dd8f4b3f8238 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -11,36 +11,38 @@ import { TemplateResult, PropertyValues, } from "lit-element"; -import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event"; -import "../../../../components/ha-dialog"; -import type { - LovelaceCardConfig, - LovelaceViewConfig, -} from "../../../../data/lovelace"; +import { mdiHelpCircle } from "@mdi/js"; + +import { fireEvent } from "../../../../common/dom/fire_event"; import { haStyleDialog } from "../../../../resources/styles"; -import "../../../../components/ha-circular-progress"; -import type { HomeAssistant } from "../../../../types"; import { showSaveSuccessToast } from "../../../../util/toast-saved-success"; import { addCard, replaceCard } from "../config-util"; -import type { GUIModeChangedEvent } from "../types"; -import "./hui-card-editor"; -import type { ConfigChangedEvent, HuiCardEditor } from "./hui-card-editor"; -import "./hui-card-picker"; -import "./hui-card-preview"; -import type { EditCardDialogParams } from "./show-edit-card-dialog"; import { getCardDocumentationURL } from "../get-card-documentation-url"; -import { mdiHelpCircle } from "@mdi/js"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; -import { HassDialog } from "../../../../dialogs/make-dialog-manager"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import { showSuggestCardDialog } from "./show-suggest-card-dialog"; + +import type { HomeAssistant } from "../../../../types"; +import type { GUIModeChangedEvent } from "../types"; +import type { ConfigChangedEvent, HuiCardEditor } from "./hui-card-editor"; +import type { EditCardDialogParams } from "./show-edit-card-dialog"; +import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; +import type { HASSDomEvent } from "../../../../common/dom/fire_event"; +import type { + LovelaceCardConfig, + LovelaceViewConfig, +} from "../../../../data/lovelace"; + +import "./hui-card-editor"; +import "./hui-card-preview"; +import "../../../../components/ha-dialog"; import "../../../../components/ha-header-bar"; +import "../../../../components/ha-circular-progress"; declare global { // for fire event interface HASSDomEvents { "reload-lovelace": undefined; - "selected-changed": SelectedChangedEvent; } // for add event listener interface HTMLElementEventMap { @@ -48,13 +50,9 @@ declare global { } } -interface SelectedChangedEvent { - selectedEntities: string[]; -} - @customElement("hui-dialog-edit-card") export class HuiDialogEditCard extends LitElement implements HassDialog { - @property() protected hass!: HomeAssistant; + @property({ attribute: false }) protected hass!: HomeAssistant; @internalProperty() private _params?: EditCardDialogParams; @@ -78,8 +76,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @internalProperty() private _selectedEntities: string[] = []; - @internalProperty() private _tabIndex = 0; - public async showDialog(params: EditCardDialogParams): Promise { this._params = params; this._GUImode = true; @@ -184,67 +180,33 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { ` : ""} - ${!this._cardConfig - ? html` - - this._handleTabChanged(ev)} - > - - - - ` - : ""}
-
- ${this._cardConfig === undefined - ? html` - - ` - : html` -
-
- -
-
- - ${this._error - ? html` - - ` - : ``} -
-
- `} +
+
+ +
+
+ + ${this._error + ? html` + + ` + : ``} +
${this._cardConfig !== undefined ? html` @@ -302,6 +264,105 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { ev.stopPropagation(); } + private _handleConfigChanged(ev: HASSDomEvent) { + this._cardConfig = deepFreeze(ev.detail.config); + this._error = ev.detail.error; + this._guiModeAvailable = ev.detail.guiModeAvailable; + this._dirty = true; + } + + private _handleGUIModeChanged(ev: HASSDomEvent): void { + ev.stopPropagation(); + this._GUImode = ev.detail.guiMode; + this._guiModeAvailable = ev.detail.guiModeAvailable; + } + + private _toggleMode(): void { + this._cardEditorEl?.toggleMode(); + } + + private _opened() { + this._cardEditorEl?.refreshYamlEditor(); + } + + private get _canSave(): boolean { + if (this._saving) { + return false; + } + if (this._cardConfig === undefined) { + return false; + } + if (this._cardEditorEl && this._cardEditorEl.hasError) { + return false; + } + return true; + } + + private async _confirmCancel() { + // Make sure the open state of this dialog is handled before the open state of confirm dialog + await new Promise((resolve) => setTimeout(resolve, 0)); + const confirm = await showConfirmationDialog(this, { + title: this.hass!.localize( + "ui.panel.lovelace.editor.edit_card.unsaved_changes" + ), + text: this.hass!.localize( + "ui.panel.lovelace.editor.edit_card.confirm_cancel" + ), + dismissText: this.hass!.localize("ui.common.no"), + confirmText: this.hass!.localize("ui.common.yes"), + }); + if (confirm) { + this._cancel(); + } + } + + private _cancel(ev?: Event) { + if (ev) { + ev.stopPropagation(); + } + this._dirty = false; + this.closeDialog(); + } + + private async _save(): Promise { + if (!this._canSave) { + return; + } + if (!this._dirty) { + this.closeDialog(); + return; + } + this._saving = true; + await this._params!.saveConfig( + this._params!.path.length === 1 + ? addCard( + this._params!.lovelaceConfig, + this._params!.path as [number], + this._cardConfig! + ) + : replaceCard( + this._params!.lovelaceConfig, + this._params!.path as [number, number], + this._cardConfig! + ) + ); + this._saving = false; + this._dirty = false; + showSaveSuccessToast(this, this.hass); + this.closeDialog(); + } + + private _suggestCards(): void { + showSuggestCardDialog(this, { + lovelaceConfig: this._params!.lovelaceConfig, + saveConfig: this._params!.saveConfig, + path: this._params!.path as [number], + entities: this._selectedEntities, + }); + + this.closeDialog(); + } + static get styles(): CSSResultArray { return [ haStyleDialog, @@ -416,139 +477,9 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { color: inherit; text-decoration: none; } - mwc-tab-bar { - padding-top: 8px; - } `, ]; } - - private _handleCardPicked(ev) { - const config = ev.detail.config; - if (this._params!.entities && this._params!.entities.length) { - if (Object.keys(config).includes("entities")) { - config.entities = this._params!.entities; - } else if (Object.keys(config).includes("entity")) { - config.entity = this._params!.entities[0]; - } - } - this._cardConfig = deepFreeze(config); - this._error = ev.detail.error; - this._dirty = true; - } - - private _handleConfigChanged(ev: HASSDomEvent) { - this._cardConfig = deepFreeze(ev.detail.config); - this._error = ev.detail.error; - this._guiModeAvailable = ev.detail.guiModeAvailable; - this._dirty = true; - } - - private _handleTabChanged(ev: CustomEvent): void { - const newTab = ev.detail.index; - if (newTab === this._tabIndex) { - return; - } - - this._tabIndex = ev.detail.index; - this._selectedEntities = []; - } - - private _handleSelectedChanged(ev: CustomEvent): void { - this._selectedEntities = ev.detail.selectedEntities; - } - - private _handleGUIModeChanged(ev: HASSDomEvent): void { - ev.stopPropagation(); - this._GUImode = ev.detail.guiMode; - this._guiModeAvailable = ev.detail.guiModeAvailable; - } - - private _toggleMode(): void { - this._cardEditorEl?.toggleMode(); - } - - private _opened() { - this._cardEditorEl?.refreshYamlEditor(); - } - - private get _canSave(): boolean { - if (this._saving) { - return false; - } - if (this._cardConfig === undefined) { - return false; - } - if (this._cardEditorEl && this._cardEditorEl.hasError) { - return false; - } - return true; - } - - private async _confirmCancel() { - // Make sure the open state of this dialog is handled before the open state of confirm dialog - await new Promise((resolve) => setTimeout(resolve, 0)); - const confirm = await showConfirmationDialog(this, { - title: this.hass!.localize( - "ui.panel.lovelace.editor.edit_card.unsaved_changes" - ), - text: this.hass!.localize( - "ui.panel.lovelace.editor.edit_card.confirm_cancel" - ), - dismissText: this.hass!.localize("ui.common.no"), - confirmText: this.hass!.localize("ui.common.yes"), - }); - if (confirm) { - this._cancel(); - } - } - - private _cancel(ev?: Event) { - if (ev) { - ev.stopPropagation(); - } - this._dirty = false; - this.closeDialog(); - } - - private async _save(): Promise { - if (!this._canSave) { - return; - } - if (!this._dirty) { - this.closeDialog(); - return; - } - this._saving = true; - await this._params!.saveConfig( - this._params!.path.length === 1 - ? addCard( - this._params!.lovelaceConfig, - this._params!.path as [number], - this._cardConfig! - ) - : replaceCard( - this._params!.lovelaceConfig, - this._params!.path as [number, number], - this._cardConfig! - ) - ); - this._saving = false; - this._dirty = false; - showSaveSuccessToast(this, this.hass); - this.closeDialog(); - } - - private _suggestCards(): void { - showSuggestCardDialog(this, { - lovelaceConfig: this._params!.lovelaceConfig, - saveConfig: this._params!.saveConfig, - path: this._params!.path as [number], - entities: this._selectedEntities, - }); - - this.closeDialog(); - } } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts new file mode 100644 index 000000000000..e3cfe1cdf006 --- /dev/null +++ b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts @@ -0,0 +1,131 @@ +import memoize from "memoize-one"; +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, +} from "lit-element"; + +import { computeStateName } from "../../../../common/entity/compute_state_name"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { computeRTLDirection } from "../../../../common/util/compute_rtl"; +import { fireEvent } from "../../../../common/dom/fire_event"; + +import type { HASSDomEvent } from "../../../../common/dom/fire_event"; +import type { HomeAssistant } from "../../../../types"; +import type { + DataTableRowData, + SelectionChangedEvent, +} from "../../../../components/data-table/ha-data-table"; + +import "../../../../components/entity/state-badge"; + +@customElement("hui-entity-picker") +export class HuiEntityPicker extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + protected render(): TemplateResult { + return html` +
+ { + const stateObj = this.hass.states[entity]; + return { + icon: "", + entity_id: entity, + stateObj, + name: computeStateName(stateObj), + domain: computeDomain(entity), + last_changed: stateObj!.last_changed, + }; + }) as DataTableRowData[]} + .dir=${computeRTLDirection(this.hass)} + .searchLabel=${this.hass.localize( + "ui.panel.lovelace.unused_entities.search" + )} + @selection-changed=${this._handleSelectionChanged} + > +
+ `; + } + + private _columns() { + return { + icon: { + title: "", + type: "icon", + template: (_icon, entity: any) => html` + + `, + }, + name: { + title: this.hass!.localize( + "ui.panel.lovelace.editor.cardpicker.entity" + ), + sortable: true, + filterable: true, + grows: true, + direction: "asc", + template: (name, entity: any) => html` +
+ ${name} +
+ ${entity.stateObj.entity_id} +
+
+ `, + }, + domain: { + title: this.hass!.localize( + "ui.panel.lovelace.editor.cardpicker.domain" + ), + sortable: true, + filterable: true, + width: "25%", + }, + }; + } + + private _allEntities = memoize((hass) => Object.keys(hass.states)); + + private _handleSelectionChanged( + ev: HASSDomEvent + ): void { + const selectedEntities = ev.detail.value; + + fireEvent(this, "selected-changed", { selectedEntities }); + } + + static get styles(): CSSResult { + return css` + ha-data-table { + --data-table-border-width: 0; + flex-grow: 1; + margin-top: -20px; + } + + .container { + display: flex; + flex-direction: column; + height: 100%; + min-height: calc(100vh - 112px); + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-entity-picker": HuiEntityPicker; + } +} diff --git a/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts new file mode 100644 index 000000000000..fb16fb41dd35 --- /dev/null +++ b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts @@ -0,0 +1,25 @@ +import { fireEvent } from "../../../../common/dom/fire_event"; +import { LovelaceConfig } from "../../../../data/lovelace"; + +export interface ShowCardDialogParams { + lovelaceConfig: LovelaceConfig; + saveConfig: (config: LovelaceConfig) => void; + path: [number] | [number, number]; + entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked +} + +const importCreateCardDialog = () => + import( + /* webpackChunkName: "hui-dialog-edit-card" */ "./hui-dialog-create-card" + ); + +export const showCreateCardDialog = ( + element: HTMLElement, + createCardDialogParams: ShowCardDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "hui-dialog-create-card", + dialogImport: importCreateCardDialog, + dialogParams: createCardDialogParams, + }); +}; diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index cc96bae638f8..326fae20902e 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -23,11 +23,11 @@ import { computeCardSize } from "../common/compute-card-size"; import { processConfigEntities } from "../common/process-config-entities"; import { createBadgeElement } from "../create-element/create-badge-element"; import { createCardElement } from "../create-element/create-card-element"; -import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; import { Lovelace, LovelaceBadge, LovelaceCard } from "../types"; import "../../../components/ha-svg-icon"; import { mdiPlus } from "@mdi/js"; import { nextRender } from "../../../common/util/render-status"; +import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog"; let editCodeLoaded = false; @@ -186,7 +186,7 @@ export class HUIView extends LitElement { } private _addCard(): void { - showEditCardDialog(this, { + showCreateCardDialog(this, { lovelaceConfig: this.lovelace!.config, saveConfig: this.lovelace!.saveConfig, path: [this.index!], From 434e670e7a2dcda9d755f4a90beac1fdf2fface9 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 16:48:55 -0500 Subject: [PATCH 07/13] Remove un needed check --- src/panels/lovelace/editor/card-editor/hui-card-picker.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 5e060110e5c0..54e108a46f62 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -154,10 +154,6 @@ export class HuiCardPicker extends LitElement { return true; } - if (changedProps.has("tabIndex")) { - return true; - } - return false; } From 519092f27a40e9bfb0750ad7071888897321b447 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 16:50:42 -0500 Subject: [PATCH 08/13] Import data table --- src/panels/lovelace/editor/card-editor/hui-entity-picker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts index e3cfe1cdf006..2d79d68652f5 100644 --- a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts @@ -20,6 +20,7 @@ import type { DataTableRowData, SelectionChangedEvent, } from "../../../../components/data-table/ha-data-table"; +import "../../../../components/data-table/ha-data-table"; import "../../../../components/entity/state-badge"; From d8eee5445c36cd02627b9c3a760da6499f903c93 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 25 Aug 2020 16:50:55 -0500 Subject: [PATCH 09/13] style import --- src/panels/lovelace/editor/card-editor/hui-entity-picker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts index 2d79d68652f5..cd2a4e5b6e73 100644 --- a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts @@ -20,8 +20,8 @@ import type { DataTableRowData, SelectionChangedEvent, } from "../../../../components/data-table/ha-data-table"; -import "../../../../components/data-table/ha-data-table"; +import "../../../../components/data-table/ha-data-table"; import "../../../../components/entity/state-badge"; @customElement("hui-entity-picker") From 3c09613b3559af93166126bb13b6830a5037027e Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Wed, 26 Aug 2020 20:19:54 -0500 Subject: [PATCH 10/13] Cant get fab correct --- .../card-editor/hui-dialog-create-card.ts | 40 ++++- .../card-editor/hui-dialog-edit-card.ts | 22 +-- .../card-editor/hui-entity-picker-table.ts | 155 ++++++++++++++++++ .../editor/card-editor/hui-entity-picker.ts | 132 --------------- .../card-editor/show-create-card-dialog.ts | 6 +- .../unused-entities/hui-unused-entities.ts | 139 +++------------- 6 files changed, 215 insertions(+), 279 deletions(-) create mode 100644 src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts delete mode 100644 src/panels/lovelace/editor/card-editor/hui-entity-picker.ts diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts index a2ee5b4e7f48..a6672eb4c3df 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts @@ -1,3 +1,4 @@ +import memoize from "memoize-one"; import { css, CSSResultArray, @@ -22,9 +23,12 @@ import { } from "./show-edit-card-dialog"; import "./hui-card-picker"; -import "./hui-entity-picker"; +import "./hui-entity-picker-table"; import "../../../../components/ha-dialog"; import "../../../../components/ha-header-bar"; +import { computeStateName } from "../../../../common/entity/compute_state_name"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { DataTableRowData } from "../../../../components/data-table/ha-data-table"; declare global { interface HASSDomEvents { @@ -113,17 +117,31 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { > ` : html` - +
+ { + const stateObj = this.hass.states[entity]; + return { + icon: "", + entity_id: entity, + stateObj, + name: computeStateName(stateObj), + domain: computeDomain(entity), + last_changed: stateObj!.last_changed, + }; + }) as DataTableRowData[]} + @selected-changed=${this._handleSelectedChanged} + > +
`}
${this.hass!.localize("ui.common.cancel")} - ${this._currTabIndex === 1 + ${this._selectedEntities.length ? html` ${this.hass!.localize("ui.common.continue")} @@ -184,6 +202,14 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { mwc-tab-bar { padding-top: 8px; } + + .entity-picker-container { + display: flex; + flex-direction: column; + height: 100%; + min-height: calc(100vh - 112px); + margin-top: -20px; + } `, ]; } @@ -239,6 +265,8 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { this.closeDialog(); } + + private _allEntities = memoize(() => Object.keys(this.hass.states)); } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index dd8f4b3f8238..66c99fd0eccf 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -52,7 +52,7 @@ declare global { @customElement("hui-dialog-edit-card") export class HuiDialogEditCard extends LitElement implements HassDialog { - @property({ attribute: false }) protected hass!: HomeAssistant; + @property({ attribute: false }) public hass!: HomeAssistant; @internalProperty() private _params?: EditCardDialogParams; @@ -74,8 +74,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { @internalProperty() private _dirty = false; - @internalProperty() private _selectedEntities: string[] = []; - public async showDialog(params: EditCardDialogParams): Promise { this._params = params; this._GUImode = true; @@ -248,13 +246,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { ` : ``} - ${this._selectedEntities.length - ? html` - - ${this.hass!.localize("ui.common.continue")} - - ` - : ""}
`; @@ -352,17 +343,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog { this.closeDialog(); } - private _suggestCards(): void { - showSuggestCardDialog(this, { - lovelaceConfig: this._params!.lovelaceConfig, - saveConfig: this._params!.saveConfig, - path: this._params!.path as [number], - entities: this._selectedEntities, - }); - - this.closeDialog(); - } - static get styles(): CSSResultArray { return [ haStyleDialog, diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts new file mode 100644 index 000000000000..b20538fde9af --- /dev/null +++ b/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts @@ -0,0 +1,155 @@ +import memoizeOne from "memoize-one"; +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, +} from "lit-element"; + +import { computeRTLDirection } from "../../../../common/util/compute_rtl"; +import { fireEvent } from "../../../../common/dom/fire_event"; + +import type { HASSDomEvent } from "../../../../common/dom/fire_event"; +import type { HomeAssistant } from "../../../../types"; +import type { + DataTableRowData, + SelectionChangedEvent, + DataTableColumnContainer, +} from "../../../../components/data-table/ha-data-table"; + +import "../../../../components/data-table/ha-data-table"; +import "../../../../components/entity/state-badge"; +import "../../../../components/ha-relative-time"; + +@customElement("hui-entity-picker-table") +export class HuiEntityPickerTable extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ type: Boolean }) public narrow?: boolean; + + @property({ type: Array }) public entities!: DataTableRowData[]; + + protected render(): TemplateResult { + return html` + + `; + } + + private _columns = memoizeOne((narrow: boolean) => { + const columns: DataTableColumnContainer = { + icon: { + title: "", + type: "icon", + template: (_icon, entity: any) => html` + + `, + }, + name: { + title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity"), + sortable: true, + filterable: true, + grows: true, + direction: "asc", + template: (name, entity: any) => html` +
+ ${name} + ${narrow + ? html` +
+ ${entity.stateObj.entity_id} +
+ ` + : ""} +
+ `, + }, + }; + + if (narrow) { + return columns; + } + + columns.entity_id = { + title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity_id"), + sortable: true, + filterable: true, + width: "30%", + }; + + columns.domain = { + title: this.hass!.localize("ui.panel.lovelace.unused_entities.domain"), + sortable: true, + filterable: true, + width: "15%", + }; + + columns.last_changed = { + title: this.hass!.localize( + "ui.panel.lovelace.unused_entities.last_changed" + ), + type: "numeric", + sortable: true, + width: "15%", + template: (lastChanged: string) => html` + + `, + }; + + return columns; + }); + + private _handleSelectionChanged( + ev: HASSDomEvent + ): void { + const selectedEntities = ev.detail.value; + + fireEvent(this, "selected-changed", { selectedEntities }); + } + + private _handleEntityClicked(ev: Event) { + const entityId = ((ev.target as HTMLElement).closest( + ".mdc-data-table__row" + ) as any).rowId; + fireEvent(this, "hass-more-info", { + entityId, + }); + } + + static get styles(): CSSResult { + return css` + ha-data-table { + --data-table-border-width: 0; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-entity-picker-table": HuiEntityPickerTable; + } +} diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts deleted file mode 100644 index cd2a4e5b6e73..000000000000 --- a/src/panels/lovelace/editor/card-editor/hui-entity-picker.ts +++ /dev/null @@ -1,132 +0,0 @@ -import memoize from "memoize-one"; -import { - css, - CSSResult, - customElement, - html, - LitElement, - property, - TemplateResult, -} from "lit-element"; - -import { computeStateName } from "../../../../common/entity/compute_state_name"; -import { computeDomain } from "../../../../common/entity/compute_domain"; -import { computeRTLDirection } from "../../../../common/util/compute_rtl"; -import { fireEvent } from "../../../../common/dom/fire_event"; - -import type { HASSDomEvent } from "../../../../common/dom/fire_event"; -import type { HomeAssistant } from "../../../../types"; -import type { - DataTableRowData, - SelectionChangedEvent, -} from "../../../../components/data-table/ha-data-table"; - -import "../../../../components/data-table/ha-data-table"; -import "../../../../components/entity/state-badge"; - -@customElement("hui-entity-picker") -export class HuiEntityPicker extends LitElement { - @property({ attribute: false }) public hass!: HomeAssistant; - - protected render(): TemplateResult { - return html` -
- { - const stateObj = this.hass.states[entity]; - return { - icon: "", - entity_id: entity, - stateObj, - name: computeStateName(stateObj), - domain: computeDomain(entity), - last_changed: stateObj!.last_changed, - }; - }) as DataTableRowData[]} - .dir=${computeRTLDirection(this.hass)} - .searchLabel=${this.hass.localize( - "ui.panel.lovelace.unused_entities.search" - )} - @selection-changed=${this._handleSelectionChanged} - > -
- `; - } - - private _columns() { - return { - icon: { - title: "", - type: "icon", - template: (_icon, entity: any) => html` - - `, - }, - name: { - title: this.hass!.localize( - "ui.panel.lovelace.editor.cardpicker.entity" - ), - sortable: true, - filterable: true, - grows: true, - direction: "asc", - template: (name, entity: any) => html` -
- ${name} -
- ${entity.stateObj.entity_id} -
-
- `, - }, - domain: { - title: this.hass!.localize( - "ui.panel.lovelace.editor.cardpicker.domain" - ), - sortable: true, - filterable: true, - width: "25%", - }, - }; - } - - private _allEntities = memoize((hass) => Object.keys(hass.states)); - - private _handleSelectionChanged( - ev: HASSDomEvent - ): void { - const selectedEntities = ev.detail.value; - - fireEvent(this, "selected-changed", { selectedEntities }); - } - - static get styles(): CSSResult { - return css` - ha-data-table { - --data-table-border-width: 0; - flex-grow: 1; - margin-top: -20px; - } - - .container { - display: flex; - flex-direction: column; - height: 100%; - min-height: calc(100vh - 112px); - } - `; - } -} - -declare global { - interface HTMLElementTagNameMap { - "hui-entity-picker": HuiEntityPicker; - } -} diff --git a/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts index fb16fb41dd35..42192a467ebf 100644 --- a/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts +++ b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts @@ -1,7 +1,7 @@ import { fireEvent } from "../../../../common/dom/fire_event"; import { LovelaceConfig } from "../../../../data/lovelace"; -export interface ShowCardDialogParams { +export interface CreateCardDialogParams { lovelaceConfig: LovelaceConfig; saveConfig: (config: LovelaceConfig) => void; path: [number] | [number, number]; @@ -10,12 +10,12 @@ export interface ShowCardDialogParams { const importCreateCardDialog = () => import( - /* webpackChunkName: "hui-dialog-edit-card" */ "./hui-dialog-create-card" + /* webpackChunkName: "hui-dialog-create-card" */ "./hui-dialog-create-card" ); export const showCreateCardDialog = ( element: HTMLElement, - createCardDialogParams: ShowCardDialogParams + createCardDialogParams: CreateCardDialogParams ): void => { fireEvent(element, "show-dialog", { dialogTag: "hui-dialog-create-card", diff --git a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts index fdc35e7d84ad..fe2f745fa992 100644 --- a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts +++ b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts @@ -10,31 +10,23 @@ import { PropertyValues, TemplateResult, } from "lit-element"; +import { mdiPlus } from "@mdi/js"; import { classMap } from "lit-html/directives/class-map"; -import memoizeOne from "memoize-one"; -import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; + import { computeDomain } from "../../../../common/entity/compute_domain"; import { computeStateName } from "../../../../common/entity/compute_state_name"; -import { - computeRTL, - computeRTLDirection, -} from "../../../../common/util/compute_rtl"; -import "../../../../components/data-table/ha-data-table"; -import type { - DataTableColumnContainer, - SelectionChangedEvent, -} from "../../../../components/data-table/ha-data-table"; -import "../../../../components/entity/state-badge"; -import "../../../../components/ha-icon"; -import "../../../../components/ha-relative-time"; +import { computeRTL } from "../../../../common/util/compute_rtl"; +import { computeUnusedEntities } from "../../common/compute-unused-entities"; +import { showSuggestCardDialog } from "../card-editor/show-suggest-card-dialog"; +import { showSelectViewDialog } from "../select-view/show-select-view-dialog"; + +import type { DataTableRowData } from "../../../../components/data-table/ha-data-table"; import type { LovelaceConfig } from "../../../../data/lovelace"; import type { HomeAssistant } from "../../../../types"; -import { computeUnusedEntities } from "../../common/compute-unused-entities"; import type { Lovelace } from "../../types"; + +import "../card-editor/hui-entity-picker-table"; import "../../../../components/ha-svg-icon"; -import { mdiPlus } from "@mdi/js"; -import { showSuggestCardDialog } from "../card-editor/show-suggest-card-dialog"; -import { showSelectViewDialog } from "../select-view/show-select-view-dialog"; @customElement("hui-unused-entities") export class HuiUnusedEntities extends LitElement { @@ -42,7 +34,7 @@ export class HuiUnusedEntities extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow?: boolean; + @property({ type: Boolean }) public narrow?: boolean; @internalProperty() private _unusedEntities: string[] = []; @@ -52,74 +44,6 @@ export class HuiUnusedEntities extends LitElement { return this.lovelace.config; } - private _columns = memoizeOne((narrow: boolean) => { - const columns: DataTableColumnContainer = { - icon: { - title: "", - type: "icon", - template: (_icon, entity: any) => html` - - `, - }, - name: { - title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity"), - sortable: true, - filterable: true, - grows: true, - direction: "asc", - template: (name, entity: any) => html` -
- ${name} - ${narrow - ? html` -
- ${entity.stateObj.entity_id} -
- ` - : ""} -
- `, - }, - }; - - if (narrow) { - return columns; - } - - columns.entity_id = { - title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity_id"), - sortable: true, - filterable: true, - width: "30%", - }; - columns.domain = { - title: this.hass!.localize("ui.panel.lovelace.unused_entities.domain"), - sortable: true, - filterable: true, - width: "15%", - }; - columns.last_changed = { - title: this.hass!.localize( - "ui.panel.lovelace.unused_entities.last_changed" - ), - type: "numeric", - sortable: true, - width: "15%", - template: (lastChanged: string) => html` - - `, - }; - - return columns; - }); - protected updated(changedProperties: PropertyValues): void { super.updated(changedProperties); @@ -161,9 +85,10 @@ export class HuiUnusedEntities extends LitElement { ` : ""} - { + { const stateObj = this.hass!.states[entity]; return { icon: "", @@ -173,18 +98,9 @@ export class HuiUnusedEntities extends LitElement { domain: computeDomain(entity), last_changed: stateObj!.last_changed, }; - })} - .id=${"entity_id"} - selectable - @selection-changed=${this._handleSelectionChanged} - .dir=${computeRTLDirection(this.hass)} - .searchLabel=${this.hass.localize( - "ui.panel.lovelace.unused_entities.search" - )} - .noDataText=${this.hass.localize( - "ui.panel.lovelace.unused_entities.no_data" - )} - > + }) as DataTableRowData[]} + @selected-changed=${this._handleSelectedChanged} + >
Date: Wed, 26 Aug 2020 20:25:20 -0500 Subject: [PATCH 11/13] fix fab --- .../editor/card-editor/hui-dialog-edit-card.ts | 1 - .../editor/unused-entities/hui-unused-entities.ts | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 66c99fd0eccf..c8caba2a4821 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -20,7 +20,6 @@ import { addCard, replaceCard } from "../config-util"; import { getCardDocumentationURL } from "../get-card-documentation-url"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; -import { showSuggestCardDialog } from "./show-suggest-card-dialog"; import type { HomeAssistant } from "../../../../types"; import type { GUIModeChangedEvent } from "../types"; diff --git a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts index fe2f745fa992..1e81f187a550 100644 --- a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts +++ b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts @@ -175,13 +175,10 @@ export class HuiUnusedEntities extends LitElement { margin-top: -20px; } .fab { - overflow: hidden; - position: absolute; - right: 0; - bottom: 0; - padding: 16px; - padding-right: calc(16px + env(safe-area-inset-right)); - padding-bottom: calc(16px + env(safe-area-inset-bottom)); + position: sticky; + float: right; + right: calc(16px + env(safe-area-inset-right)); + bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 1; } .fab.rtl { From 7e96fcc6b9b2fa5615be909f3eb0007b7713b10d Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Thu, 3 Sep 2020 16:54:05 -0500 Subject: [PATCH 12/13] comments --- .../card-editor/hui-dialog-create-card.ts | 55 ++++++++++--------- .../card-editor/hui-entity-picker-table.ts | 20 +++---- 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts index a6672eb4c3df..4bd1a319c417 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts @@ -1,34 +1,33 @@ -import memoize from "memoize-one"; +import "@material/mwc-tab-bar/mwc-tab-bar"; +import "@material/mwc-tab/mwc-tab"; import { css, CSSResultArray, customElement, html, + internalProperty, LitElement, property, - internalProperty, TemplateResult, } from "lit-element"; - +import memoize from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { haStyleDialog } from "../../../../resources/styles"; -import { showSuggestCardDialog } from "./show-suggest-card-dialog"; - +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { computeStateName } from "../../../../common/entity/compute_state_name"; +import { DataTableRowData } from "../../../../components/data-table/ha-data-table"; +import "../../../../components/ha-dialog"; +import "../../../../components/ha-header-bar"; import type { LovelaceViewConfig } from "../../../../data/lovelace"; -import type { HomeAssistant } from "../../../../types"; import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; +import { haStyleDialog } from "../../../../resources/styles"; +import type { HomeAssistant } from "../../../../types"; +import "./hui-card-picker"; +import "./hui-entity-picker-table"; import { EditCardDialogParams, showEditCardDialog, } from "./show-edit-card-dialog"; - -import "./hui-card-picker"; -import "./hui-entity-picker-table"; -import "../../../../components/ha-dialog"; -import "../../../../components/ha-header-bar"; -import { computeStateName } from "../../../../common/entity/compute_state_name"; -import { computeDomain } from "../../../../common/entity/compute_domain"; -import { DataTableRowData } from "../../../../components/data-table/ha-data-table"; +import { showSuggestCardDialog } from "./show-suggest-card-dialog"; declare global { interface HASSDomEvents { @@ -121,17 +120,7 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { { - const stateObj = this.hass.states[entity]; - return { - icon: "", - entity_id: entity, - stateObj, - name: computeStateName(stateObj), - domain: computeDomain(entity), - last_changed: stateObj!.last_changed, - }; - }) as DataTableRowData[]} + .entities=${this._allEntities(this.hass.states)} @selected-changed=${this._handleSelectedChanged} >
@@ -266,7 +255,19 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { this.closeDialog(); } - private _allEntities = memoize(() => Object.keys(this.hass.states)); + private _allEntities = memoize((entities) => + Object.keys(entities).map((entity) => { + const stateObj = this.hass.states[entity]; + return { + icon: "", + entity_id: entity, + stateObj, + name: computeStateName(stateObj), + domain: computeDomain(entity), + last_changed: stateObj!.last_changed, + } as DataTableRowData; + }) + ); } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts b/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts index b20538fde9af..3a724fc6e2db 100644 --- a/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts +++ b/src/panels/lovelace/editor/card-editor/hui-entity-picker-table.ts @@ -1,4 +1,3 @@ -import memoizeOne from "memoize-one"; import { css, CSSResult, @@ -8,21 +7,19 @@ import { property, TemplateResult, } from "lit-element"; - -import { computeRTLDirection } from "../../../../common/util/compute_rtl"; +import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; - import type { HASSDomEvent } from "../../../../common/dom/fire_event"; -import type { HomeAssistant } from "../../../../types"; +import { computeRTLDirection } from "../../../../common/util/compute_rtl"; +import "../../../../components/data-table/ha-data-table"; import type { + DataTableColumnContainer, DataTableRowData, SelectionChangedEvent, - DataTableColumnContainer, } from "../../../../components/data-table/ha-data-table"; - -import "../../../../components/data-table/ha-data-table"; import "../../../../components/entity/state-badge"; import "../../../../components/ha-relative-time"; +import type { HomeAssistant } from "../../../../types"; @customElement("hui-entity-picker-table") export class HuiEntityPickerTable extends LitElement { @@ -86,15 +83,12 @@ export class HuiEntityPickerTable extends LitElement { }, }; - if (narrow) { - return columns; - } - columns.entity_id = { title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity_id"), sortable: true, filterable: true, width: "30%", + hidden: narrow, }; columns.domain = { @@ -102,6 +96,7 @@ export class HuiEntityPickerTable extends LitElement { sortable: true, filterable: true, width: "15%", + hidden: narrow, }; columns.last_changed = { @@ -111,6 +106,7 @@ export class HuiEntityPickerTable extends LitElement { type: "numeric", sortable: true, width: "15%", + hidden: narrow, template: (lastChanged: string) => html` Date: Thu, 3 Sep 2020 17:21:54 -0500 Subject: [PATCH 13/13] fix comment --- .../lovelace/editor/card-editor/hui-dialog-create-card.ts | 1 + .../lovelace/editor/card-editor/hui-dialog-suggest-card.ts | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts index 4bd1a319c417..c0fb354da9ad 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts @@ -59,6 +59,7 @@ export class HuiCreateDialogCard extends LitElement implements HassDialog { public closeDialog(): boolean { this._params = undefined; + this._currTabIndex = 0; fireEvent(this, "dialog-closed", { dialog: this.localName }); return true; } diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts index a4f222200c75..00e7d8b5a027 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts @@ -5,9 +5,9 @@ import { CSSResultArray, customElement, html, + internalProperty, LitElement, property, - internalProperty, query, TemplateResult, } from "lit-element"; @@ -21,7 +21,7 @@ import { showSaveSuccessToast } from "../../../../util/toast-saved-success"; import { computeCards } from "../../common/generate-lovelace-config"; import { addCards } from "../config-util"; import "./hui-card-preview"; -import { showEditCardDialog } from "./show-edit-card-dialog"; +import { showCreateCardDialog } from "./show-create-card-dialog"; import { SuggestCardDialogParams } from "./show-suggest-card-dialog"; @customElement("hui-dialog-suggest-card") @@ -179,7 +179,8 @@ export class HuiDialogSuggestCard extends LitElement { ) { return; } - showEditCardDialog(this, { + + showCreateCardDialog(this, { lovelaceConfig: this._params!.lovelaceConfig, saveConfig: this._params!.saveConfig, path: this._params!.path,