diff --git a/hassio/src/dialogs/network/dialog-hassio-network.ts b/hassio/src/dialogs/network/dialog-hassio-network.ts index 103669b18b..05f6569df9 100644 --- a/hassio/src/dialogs/network/dialog-hassio-network.ts +++ b/hassio/src/dialogs/network/dialog-hassio-network.ts @@ -17,7 +17,6 @@ import "../../../../src/components/ha-formfield"; import "../../../../src/components/ha-header-bar"; import "../../../../src/components/ha-icon-button"; import "../../../../src/components/ha-radio"; -import "../../../../src/components/ha-related-items"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; import { AccessPoints, diff --git a/src/components/ha-header-bar.ts b/src/components/ha-header-bar.ts index 68111455af..c778b00331 100644 --- a/src/components/ha-header-bar.ts +++ b/src/components/ha-header-bar.ts @@ -36,6 +36,12 @@ export class HaHeaderBar extends LitElement { position: static; color: var(--mdc-theme-on-primary, #fff); } + .mdc-top-app-bar__section.mdc-top-app-bar__section--align-start { + flex: 1; + } + .mdc-top-app-bar__section.mdc-top-app-bar__section--align-end { + flex: none; + } `, ]; } diff --git a/src/dialogs/more-info/ha-more-info-dialog.ts b/src/dialogs/more-info/ha-more-info-dialog.ts index cc282e5e1d..77adbfff55 100644 --- a/src/dialogs/more-info/ha-more-info-dialog.ts +++ b/src/dialogs/more-info/ha-more-info-dialog.ts @@ -1,41 +1,54 @@ +import { + mdiChartBoxOutline, + mdiClose, + mdiCogOutline, + mdiDevices, + mdiDotsVertical, + mdiInformationOutline, + mdiPencilOutline, +} from "@mdi/js"; import type { HassEntity } from "home-assistant-js-websocket"; -import "@material/mwc-button"; -import "@material/mwc-tab"; -import "@material/mwc-tab-bar"; -import { mdiClose, mdiPencil } from "@mdi/js"; import { css, html, LitElement, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators"; import { cache } from "lit/directives/cache"; import { fireEvent } from "../../common/dom/fire_event"; +import { stopPropagation } from "../../common/dom/stop_propagation"; import { computeDomain } from "../../common/entity/compute_domain"; import { computeStateName } from "../../common/entity/compute_state_name"; +import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event"; import { navigate } from "../../common/navigate"; +import "../../components/ha-button-menu"; import "../../components/ha-dialog"; import "../../components/ha-header-bar"; import "../../components/ha-icon-button"; +import "../../components/ha-icon-button-prev"; +import "../../components/ha-list-item"; import "../../components/ha-related-items"; +import { EntityRegistryEntry } from "../../data/entity_registry"; import { haStyleDialog } from "../../resources/styles"; import "../../state-summary/state-card-content"; import { HomeAssistant } from "../../types"; import { - EDITABLE_DOMAINS_WITH_ID, - EDITABLE_DOMAINS_WITH_UNIQUE_ID, - DOMAINS_WITH_MORE_INFO, computeShowHistoryComponent, computeShowLogBookComponent, + DOMAINS_WITH_MORE_INFO, + EDITABLE_DOMAINS_WITH_ID, + EDITABLE_DOMAINS_WITH_UNIQUE_ID, } from "./const"; import "./controls/more-info-default"; +import "./ha-more-info-history-and-logbook"; import "./ha-more-info-info"; import "./ha-more-info-settings"; -import "./ha-more-info-history-and-logbook"; import "./more-info-content"; export interface MoreInfoDialogParams { entityId: string | null; - tab?: Tab; + view?: View; + /** @deprecated Use `view` instead */ + tab?: View; } -type Tab = "info" | "history" | "settings" | "related"; +type View = "info" | "history" | "settings" | "related"; @customElement("ha-more-info-dialog") export class MoreInfoDialog extends LitElement { @@ -45,7 +58,7 @@ export class MoreInfoDialog extends LitElement { @state() private _entityId?: string | null; - @state() private _currTab: Tab = "info"; + @state() private _currView: View = "info"; public showDialog(params: MoreInfoDialogParams) { this._entityId = params.entityId; @@ -53,7 +66,7 @@ export class MoreInfoDialog extends LitElement { this.closeDialog(); return; } - this._currTab = params.tab || "info"; + this._currView = params.view || "info"; this.large = false; } @@ -62,7 +75,7 @@ export class MoreInfoDialog extends LitElement { fireEvent(this, "dialog-closed", { dialog: this.localName }); } - protected shouldShowEditIcon( + private shouldShowEditIcon( domain: string, stateObj: HassEntity | undefined ): boolean { @@ -82,16 +95,77 @@ export class MoreInfoDialog extends LitElement { return false; } + private shouldShowHistory(domain: string): boolean { + return ( + DOMAINS_WITH_MORE_INFO.includes(domain) && + (computeShowHistoryComponent(this.hass, this._entityId!) || + computeShowLogBookComponent(this.hass, this._entityId!)) + ); + } + + private _getDeviceId(): string | null { + const entity = this.hass.entities[this._entityId!] as + | EntityRegistryEntry + | undefined; + return entity?.device_id ?? null; + } + + private back() { + this._currView = "info"; + } + + private _goToHistory() { + this._currView = "history"; + } + + private _goToSettings(): void { + this._currView = "settings"; + } + + private _goToDevice(ev): void { + if (!shouldHandleRequestSelectedEvent(ev)) return; + const deviceId = this._getDeviceId(); + + if (!deviceId) return; + + navigate(`/config/devices/device/${deviceId}`); + this.closeDialog(); + } + + private _goToEdit(ev) { + if (!shouldHandleRequestSelectedEvent(ev)) return; + const stateObj = this.hass.states[this._entityId!]; + const domain = computeDomain(this._entityId!); + let idToPassThroughUrl = stateObj.entity_id; + if (EDITABLE_DOMAINS_WITH_ID.includes(domain) || domain === "person") { + idToPassThroughUrl = stateObj.attributes.id; + } + if (EDITABLE_DOMAINS_WITH_UNIQUE_ID.includes(domain)) { + idToPassThroughUrl = this.hass.entities[this._entityId!].unique_id; + } + + navigate(`/config/${domain}/edit/${idToPassThroughUrl}`); + this.closeDialog(); + } + + private _goToRelated(ev): void { + if (!shouldHandleRequestSelectedEvent(ev)) return; + this._currView = "related"; + } + protected render() { if (!this._entityId) { - return html``; + return null; } const entityId = this._entityId; const stateObj = this.hass.states[entityId]; const domain = computeDomain(entityId); const name = (stateObj && computeStateName(stateObj)) || entityId; - const tabs = this._getTabs(entityId, this.hass.user!.is_admin); + + const isAdmin = this.hass.user!.is_admin; + + const deviceId = this._getDeviceId(); return html`
- + ${this._currView === "info" + ? html` + + ` + : html` + + `}
${name}
- ${this.shouldShowEditIcon(domain, stateObj) + ${this._currView === "info" ? html` + ${this.shouldShowHistory(domain) + ? html` + + ` + : null} - ` - : ""} -
+ ${isAdmin + ? html` + - ${tabs.length > 1 - ? html` - - ${tabs.map( - (tab) => html` - - ` - )} - - ` - : ""} + ${deviceId + ? html` + + ${this.hass.localize( + "ui.dialogs.more_info_control.device_info" + )} + + + ` + : null} + ${this.shouldShowEditIcon(domain, stateObj) + ? html` + + ${this.hass.localize( + "ui.dialogs.more_info_control.edit" + )} + + + ` + : null} + + ${this.hass.localize( + "ui.dialogs.more_info_control.related" + )} + + + ` + : null} + ` + : null} +
${cache( - this._currTab === "info" + this._currView === "info" ? html` ` - : this._currTab === "history" + : this._currView === "history" ? html` ` - : this._currTab === "settings" + : this._currView === "settings" ? html` this.closeDialog()); } - protected willUpdate(changedProps: PropertyValues) { - super.willUpdate(changedProps); - if (!this._entityId) { - return; - } - const tabs = this._getTabs(this._entityId, this.hass.user!.is_admin); - if (!tabs.includes(this._currTab)) { - this._currTab = tabs[0]; - } - } - protected updated(changedProps: PropertyValues) { super.updated(changedProps); - if (changedProps.has("_currTab")) { - this.setAttribute("tab", this._currTab); + if (changedProps.has("_currView")) { + this.setAttribute("view", this._currView); } } - private _getTabs(entityId: string, isAdmin: boolean): Tab[] { - const domain = computeDomain(entityId); - const tabs: Tab[] = ["info"]; - - // Info and history are combined in info when there are no - // dedicated more-info controls. If not combined, add a history tab. - if ( - DOMAINS_WITH_MORE_INFO.includes(domain) && - (computeShowHistoryComponent(this.hass, entityId) || - computeShowLogBookComponent(this.hass, entityId)) - ) { - tabs.push("history"); - } - - if (isAdmin) { - tabs.push("settings"); - tabs.push("related"); - } - - return tabs; - } - private _enlarge() { this.large = !this.large; } - private _gotoEdit() { - const stateObj = this.hass.states[this._entityId!]; - const domain = computeDomain(this._entityId!); - let idToPassThroughUrl = stateObj.entity_id; - if (EDITABLE_DOMAINS_WITH_ID.includes(domain) || domain === "person") { - idToPassThroughUrl = stateObj.attributes.id; - } - if (EDITABLE_DOMAINS_WITH_UNIQUE_ID.includes(domain)) { - idToPassThroughUrl = this.hass.entities[this._entityId!].unique_id; - } - - navigate(`/config/${domain}/edit/${idToPassThroughUrl}`); - this.closeDialog(); - } - - private _handleTabChanged(ev: CustomEvent): void { - const newTab = this._getTabs(this._entityId!, this.hass.user!.is_admin)[ - ev.detail.index - ]; - if (newTab === this._currTab) { - return; - } - - this._currTab = newTab; - } - static get styles() { return [ haStyleDialog, css` ha-dialog { --dialog-surface-position: static; - --dialog-content-position: static; + --dialog-content-position: relative; --vertical-align-dialog: flex-start; --dialog-content-padding: 0; --content-padding: 24px; @@ -282,17 +362,11 @@ export class MoreInfoDialog extends LitElement { --mdc-theme-primary: var(--mdc-theme-surface); flex-shrink: 0; display: block; + border-bottom: none; } .content { outline: none; } - @media all and (max-width: 450px), all and (max-height: 500px) { - ha-header-bar { - --mdc-theme-primary: var(--app-header-background-color); - --mdc-theme-on-primary: var(--app-header-text-color, white); - border-bottom: none; - } - } .heading { border-bottom: 1px solid @@ -303,14 +377,19 @@ export class MoreInfoDialog extends LitElement { padding: var(--content-padding); } - :host([tab="settings"]) ha-dialog { + :host([view="settings"]) ha-dialog { --content-padding: 0; } - :host([tab="info"]) ha-dialog[data-domain="camera"] { + :host([view="info"]) ha-dialog[data-domain="camera"] { --content-padding: 0; /* max height of the video is full screen, minus the height of the header of the dialog and the padding of the dialog (mdc-dialog-max-height: calc(100% - 72px)) */ - --video-max-height: calc(100vh - 113px - 72px); + --video-max-height: calc(100vh - 65px - 72px); + } + + .main-title { + overflow: hidden; + text-overflow: ellipsis; } @media all and (min-width: 600px) and (min-height: 501px) { @@ -322,8 +401,6 @@ export class MoreInfoDialog extends LitElement { } .main-title { - overflow: hidden; - text-overflow: ellipsis; cursor: default; } diff --git a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts index 48beb15d12..74918de7ca 100644 --- a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts +++ b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts @@ -482,14 +482,13 @@ class CloudGoogleAssistant extends LitElement { private _showMoreInfo(ev) { const entityId = ev.currentTarget.stateObj.entity_id; - const moreInfoTab = ev.currentTarget.moreInfoTab; - fireEvent(this, "hass-more-info", { entityId, tab: moreInfoTab }); + fireEvent(this, "hass-more-info", { entityId }); } private _showMoreInfoSettings(ev) { ev.stopPropagation(); const entityId = ev.currentTarget.stateObj.entity_id; - fireEvent(this, "hass-more-info", { entityId, tab: "settings" }); + fireEvent(this, "hass-more-info", { entityId, view: "settings" }); } private async _exposeChanged(ev: CustomEvent) { diff --git a/src/panels/config/devices/device-detail/ha-device-entities-card.ts b/src/panels/config/devices/device-detail/ha-device-entities-card.ts index e0aeffd445..c6c2a2abe2 100644 --- a/src/panels/config/devices/device-detail/ha-device-entities-card.ts +++ b/src/panels/config/devices/device-detail/ha-device-entities-card.ts @@ -223,10 +223,7 @@ export class HaDeviceEntitiesCard extends LitElement { private _openEditEntry(ev: Event): void { const entry = (ev.currentTarget! as any).entry; - showMoreInfoDialog(this, { - entityId: entry.entity_id, - tab: "settings", - }); + showMoreInfoDialog(this, { entityId: entry.entity_id }); } private _addToLovelaceView(): void { diff --git a/src/panels/config/entities/entity-registry-settings.ts b/src/panels/config/entities/entity-registry-settings.ts index db7fbf479b..ffbf968507 100644 --- a/src/panels/config/entities/entity-registry-settings.ts +++ b/src/panels/config/entities/entity-registry-settings.ts @@ -1247,10 +1247,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) { if (!entity) { return; } - showMoreInfoDialog(parent, { - entityId: entity.entity_id, - tab: "settings", - }); + showMoreInfoDialog(parent, { entityId: entity.entity_id }); }); }, "entity_registry_updated"); } diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index a84aea822d..733a53747e 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -916,10 +916,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { private _openEditEntry(ev: CustomEvent): void { const entityId = (ev.detail as RowClickedEvent).id; - showMoreInfoDialog(this, { - entityId, - tab: "settings", - }); + showMoreInfoDialog(this, { entityId }); } private async _loadConfigEntries() { diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index 8e8c8268fe..f7138bfd97 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -358,10 +358,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { private async _openEditDialog(ev: CustomEvent): Promise { const entityId = (ev.detail as RowClickedEvent).id; - showMoreInfoDialog(this, { - entityId, - tab: "settings", - }); + showMoreInfoDialog(this, { entityId }); } private _createHelpler() { diff --git a/src/panels/config/network/supervisor-hostname.ts b/src/panels/config/network/supervisor-hostname.ts index 45a42ff711..fab91f5524 100644 --- a/src/panels/config/network/supervisor-hostname.ts +++ b/src/panels/config/network/supervisor-hostname.ts @@ -13,7 +13,6 @@ import "../../../components/ha-formfield"; import "../../../components/ha-header-bar"; import "../../../components/ha-icon-button"; import "../../../components/ha-radio"; -import "../../../components/ha-related-items"; import "../../../components/ha-settings-row"; import "../../../components/ha-textfield"; import { extractApiErrorMessage } from "../../../data/hassio/common"; diff --git a/src/panels/config/network/supervisor-network.ts b/src/panels/config/network/supervisor-network.ts index bcab99e48a..3ab1b73ef7 100644 --- a/src/panels/config/network/supervisor-network.ts +++ b/src/panels/config/network/supervisor-network.ts @@ -17,7 +17,6 @@ import "../../../components/ha-formfield"; import "../../../components/ha-header-bar"; import "../../../components/ha-icon-button"; import "../../../components/ha-radio"; -import "../../../components/ha-related-items"; import { extractApiErrorMessage } from "../../../data/hassio/common"; import { AccessPoints, diff --git a/src/state/more-info-mixin.ts b/src/state/more-info-mixin.ts index 509c1a4b7a..7b14098279 100644 --- a/src/state/more-info-mixin.ts +++ b/src/state/more-info-mixin.ts @@ -29,7 +29,7 @@ export default >(superClass: T) => "ha-more-info-dialog", { entityId: ev.detail.entityId, - tab: ev.detail.tab, + view: ev.detail.view || ev.detail.tab, }, () => import("../dialogs/more-info/ha-more-info-dialog") ); diff --git a/src/translations/en.json b/src/translations/en.json index 68853ec791..7330da095f 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -832,10 +832,11 @@ "settings": "Settings", "edit": "Edit entity", "details": "Details", - "info": "Info", + "back_to_info": "Back to info", "related": "Related", "history": "History", "logbook": "Logbook", + "device_info": "Device info", "last_changed": "Last changed", "last_updated": "Last updated", "show_more": "Show more",