diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-webhook.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-webhook.ts index a34f6936a5..cc5fee2405 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-webhook.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-webhook.ts @@ -1,15 +1,15 @@ -import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; +import "@home-assistant/webawesome/dist/components/divider/divider"; import { mdiCog, mdiContentCopy } from "@mdi/js"; import type { UnsubscribeFunc } from "home-assistant-js-websocket"; import type { PropertyValues } from "lit"; -import { css, html, LitElement } from "lit"; +import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../../../common/dom/fire_event"; import { slugify } from "../../../../../common/string/slugify"; import { copyToClipboard } from "../../../../../common/util/copy-clipboard"; -import { stopPropagation } from "../../../../../common/dom/stop_propagation"; -import "../../../../../components/ha-button-menu"; -import "../../../../../components/ha-check-list-item"; +import "../../../../../components/ha-dropdown"; +import "../../../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../../../components/ha-dropdown-item"; import "../../../../../components/ha-icon-button"; import "../../../../../components/ha-textfield"; import type { HaTextField } from "../../../../../components/ha-textfield"; @@ -125,7 +125,11 @@ export class HaWebhookTrigger extends LitElement { .path=${mdiContentCopy} > - + ${SUPPORTED_METHODS.map( (method) => html` - ${method} - + ` )} -
  • - ` + : nothing} + ${this.hass!.localize( "ui.panel.config.automation.editor.triggers.type.webhook.local_only" )} - -
    + + `; } @@ -164,23 +170,18 @@ export class HaWebhookTrigger extends LitElement { handleChangeEvent(this, ev); } - private _localOnlyChanged(ev: CustomEvent): void { - ev.stopPropagation(); - if (this.trigger.local_only === ev.detail.selected) { + private _localOnlyChanged(local_only: boolean): void { + if (this.trigger.local_only === local_only) { return; } const newTrigger = { ...this.trigger, - local_only: ev.detail.selected, + local_only, }; fireEvent(this, "value-changed", { value: newTrigger }); } - private _allowedMethodsChanged(ev: CustomEvent): void { - ev.stopPropagation(); - const method = (ev.target as any).value; - const selected = ev.detail.selected; - + private _allowedMethodsChanged(method: string, selected: boolean): void { if (selected === this.trigger.allowed_methods?.includes(method)) { return; } @@ -207,6 +208,22 @@ export class HaWebhookTrigger extends LitElement { }); } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + ev.preventDefault(); // don't close the dropdown to select multiple options + const action = ev.detail?.item?.value; + + if (!action) { + return; + } + + if (action === "local_only") { + this._localOnlyChanged(ev.detail.item.checked); + return; + } + + this._allowedMethodsChanged(ev.detail.item.value, ev.detail.item.checked); + } + static styles = css` .flex { display: flex; @@ -222,7 +239,7 @@ export class HaWebhookTrigger extends LitElement { color: var(--secondary-text-color); } - ha-button-menu { + ha-dropdown ha-icon-button { padding-top: 4px; } `; diff --git a/src/panels/config/backup/ha-config-backup-backups.ts b/src/panels/config/backup/ha-config-backup-backups.ts index dc460fe408..55b67917f3 100644 --- a/src/panels/config/backup/ha-config-backup-backups.ts +++ b/src/panels/config/backup/ha-config-backup-backups.ts @@ -16,7 +16,6 @@ import { relativeTime } from "../../../common/datetime/relative_time"; import { storage } from "../../../common/decorators/storage"; import { fireEvent, type HASSDomEvent } from "../../../common/dom/fire_event"; import { computeDomain } from "../../../common/entity/compute_domain"; -import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { navigate } from "../../../common/navigate"; import type { LocalizeFunc } from "../../../common/translations/localize"; import type { @@ -26,14 +25,18 @@ import type { SelectionChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; -import "../../../components/ha-spinner"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import "../../../components/ha-fab"; import "../../../components/ha-filter-states"; import "../../../components/ha-icon"; import "../../../components/ha-icon-next"; import "../../../components/ha-icon-overflow-menu"; -import "../../../components/ha-list-item"; +import "../../../components/ha-md-menu"; +import type { HaMdMenu } from "../../../components/ha-md-menu"; +import "../../../components/ha-md-menu-item"; +import "../../../components/ha-spinner"; import "../../../components/ha-svg-icon"; import type { BackupAgent, @@ -71,9 +74,6 @@ import { showGenerateBackupDialog } from "./dialogs/show-dialog-generate-backup" import { showNewBackupDialog } from "./dialogs/show-dialog-new-backup"; import { showUploadBackupDialog } from "./dialogs/show-dialog-upload-backup"; import { downloadBackup } from "./helper/download_backup"; -import type { HaMdMenu } from "../../../components/ha-md-menu"; -import "../../../components/ha-md-menu"; -import "../../../components/ha-md-menu-item"; interface BackupRow extends DataTableRowData, BackupContent { formatted_type: string; @@ -401,22 +401,22 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) { )} >
    - + - - + + ${this.hass.localize( "ui.panel.config.backup.backups.menu.upload_backup" )} - - + +
    @@ -447,7 +447,7 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) { { await showUploadBackupDialog(this, {}); - } + }; private async _newBackup(): Promise { const config = this.config!; @@ -635,6 +631,14 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) { this._dataTable.clearSelection(); } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item.value; + + if (action === "upload_backup") { + this._uploadBackup(); + } + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/backup/ha-config-backup-overview.ts b/src/panels/config/backup/ha-config-backup-overview.ts index d8bcf680bf..240d665c62 100644 --- a/src/panels/config/backup/ha-config-backup-overview.ts +++ b/src/panels/config/backup/ha-config-backup-overview.ts @@ -3,16 +3,16 @@ import type { CSSResultGroup, TemplateResult } from "lit"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../../common/dom/fire_event"; -import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; import "../../../components/ha-card"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import "../../../components/ha-fab"; -import "../../../components/ha-spinner"; import "../../../components/ha-icon"; import "../../../components/ha-icon-next"; import "../../../components/ha-icon-overflow-menu"; -import "../../../components/ha-list-item"; +import "../../../components/ha-spinner"; import "../../../components/ha-svg-icon"; import type { BackupAgent, @@ -63,13 +63,9 @@ class HaConfigBackupOverview extends LitElement { @property({ attribute: false }) public agents: BackupAgent[] = []; - private async _uploadBackup(ev) { - if (!shouldHandleRequestSelectedEvent(ev)) { - return; - } - + private _uploadBackup = async () => { await showUploadBackupDialog(this, {}); - } + }; private _handleOnboardingButtonClick(ev) { ev.stopPropagation(); @@ -143,19 +139,23 @@ class HaConfigBackupOverview extends LitElement { .narrow=${this.narrow} .header=${this.hass.localize("ui.panel.config.backup.overview.header")} > - + - - + + ${this.hass.localize( "ui.panel.config.backup.overview.menu.upload_backup" )} - - + +
    ${this.info && Object.keys(this.info.agent_errors).length ? html`${Object.entries(this.info.agent_errors).map( @@ -240,6 +240,14 @@ class HaConfigBackupOverview extends LitElement { `; } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item.value; + + if (action === "upload_backup") { + this._uploadBackup(); + } + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/backup/ha-config-backup-settings.ts b/src/panels/config/backup/ha-config-backup-settings.ts index 102833da5e..edab1c131f 100644 --- a/src/panels/config/backup/ha-config-backup-settings.ts +++ b/src/panels/config/backup/ha-config-backup-settings.ts @@ -4,16 +4,16 @@ import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { fireEvent } from "../../../common/dom/fire_event"; -import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { debounce } from "../../../common/util/debounce"; import { nextRender } from "../../../common/util/render-status"; import "../../../components/ha-alert"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; import "../../../components/ha-card"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import "../../../components/ha-icon-button"; import "../../../components/ha-icon-next"; -import "../../../components/ha-list-item"; import "../../../components/ha-password-field"; import "../../../components/ha-svg-icon"; import type { BackupAgent, BackupConfig } from "../../../data/backup"; @@ -26,6 +26,7 @@ import { } from "../../../data/supervisor/update"; import "../../../layouts/hass-subpage"; import type { HomeAssistant } from "../../../types"; +import { brandsUrl } from "../../../util/brands-url"; import { documentationUrl } from "../../../util/documentation-url"; import "./components/config/ha-backup-config-addon"; import "./components/config/ha-backup-config-agents"; @@ -35,7 +36,6 @@ import "./components/config/ha-backup-config-encryption-key"; import "./components/config/ha-backup-config-schedule"; import type { BackupConfigSchedule } from "./components/config/ha-backup-config-schedule"; import { showLocalBackupLocationDialog } from "./dialogs/show-dialog-local-backup-location"; -import { brandsUrl } from "../../../util/brands-url"; @customElement("ha-config-backup-settings") class HaConfigBackupSettings extends LitElement { @@ -140,25 +140,22 @@ class HaConfigBackupSettings extends LitElement { > ${supervisor ? html` - + - - + + ${this.hass.localize( "ui.panel.config.backup.settings.menu.change_default_location" )} - - + + ` : nothing} @@ -372,13 +369,9 @@ class HaConfigBackupSettings extends LitElement { `; } - private async _changeLocalLocation(ev) { - if (!shouldHandleRequestSelectedEvent(ev)) { - return; - } - + private _changeLocalLocation = () => { showLocalBackupLocationDialog(this, {}); - } + }; private async _supervisorUpdateConfigChanged(ev) { const config = ev.detail.value as SupervisorUpdateConfig; @@ -499,6 +492,14 @@ class HaConfigBackupSettings extends LitElement { fireEvent(this, "ha-refresh-backup-config"); } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item?.value; + + if (action === "change_local_location") { + this._changeLocalLocation(); + } + } + static styles = css` ha-card { scroll-margin-top: 16px; diff --git a/src/panels/config/integrations/ha-config-flow-card.ts b/src/panels/config/integrations/ha-config-flow-card.ts index 7f9e2f9cd5..94cab7c775 100644 --- a/src/panels/config/integrations/ha-config-flow-card.ts +++ b/src/panels/config/integrations/ha-config-flow-card.ts @@ -6,13 +6,14 @@ import { mdiOpenInNew, } from "@mdi/js"; import type { TemplateResult } from "lit"; -import { LitElement, css, html } from "lit"; +import { LitElement, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; -import "../../../components/ha-list-item"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import { deleteApplicationCredential, fetchApplicationCredentialsConfigEntry, @@ -53,7 +54,7 @@ export class HaConfigFlowCard extends LitElement { .hass=${this.hass} .manifest=${this.manifest} .domain=${this.flow.handler} - .label=${this.flow.localized_title} + .label=${this.flow.localized_title ?? ""} > ${DISCOVERY_SOURCES.includes(this.flow.context.source) && this.flow.context.unique_id @@ -62,7 +63,7 @@ export class HaConfigFlowCard extends LitElement { "ui.panel.config.integrations.ignore.ignore" )}` - : ""} + : nothing} ${this.flow.context.configuration_url || this.manifest || attention - ? html` + ? html` - + ${this.hass.localize( "ui.panel.config.integrations.config_entry.open_configuration_url" )} - + - + ` - : ""} + : nothing} ${this.manifest ? html` - + ${this.hass.localize( "ui.panel.config.integrations.config_entry.documentation" )} - + ` - : ""} + : nothing} ${attention - ? html` - + ? html` + ${this.hass.localize( "ui.panel.config.integrations.config_entry.delete" )} - ` - : ""} - ` - : ""} + ` + : nothing} + ` + : nothing} `; } @@ -263,7 +260,7 @@ export class HaConfigFlowCard extends LitElement { } } - private async _handleDelete() { + private _handleDelete = async () => { const entryId = this.flow.context.entry_id; if (!entryId) { @@ -306,6 +303,14 @@ export class HaConfigFlowCard extends LitElement { } this._handleFlowUpdated(); + }; + + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item?.value; + + if (action === "delete") { + this._handleDelete(); + } } static styles = css` @@ -313,7 +318,7 @@ export class HaConfigFlowCard extends LitElement { text-decoration: none; color: var(--primary-color); } - ha-button-menu { + ha-dropdown { color: var(--secondary-text-color); } ha-svg-icon[slot="meta"] { @@ -324,9 +329,6 @@ export class HaConfigFlowCard extends LitElement { --mdc-theme-primary: var(--error-color); --ha-card-border-color: var(--error-color); } - .warning { - --mdc-theme-text-primary-on-background: var(--error-color); - } `; } diff --git a/src/panels/config/network/supervisor-network.ts b/src/panels/config/network/supervisor-network.ts index 0f1d0ac7e5..e6493232e2 100644 --- a/src/panels/config/network/supervisor-network.ts +++ b/src/panels/config/network/supervisor-network.ts @@ -4,8 +4,10 @@ import { customElement, property, state } from "lit/decorators"; import { cache } from "lit/directives/cache"; import "../../../components/ha-alert"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; import "../../../components/ha-card"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import "../../../components/ha-expansion-panel"; import "../../../components/ha-formfield"; import "../../../components/ha-icon-button"; @@ -476,9 +478,9 @@ export class HassioNetwork extends LitElement {
    - ${this.hass.localize( @@ -519,27 +520,38 @@ export class HassioNetwork extends LitElement { ${Object.entries(PREDEFINED_DNS[version]).map( ([name, addresses]) => html` - ${name} - + ` )} - + ${this.hass.localize( "ui.panel.config.network.supervisor.custom_dns" )} - - + + ` : nothing} `; } + private _getPredefinedDnsName(nameserver: string, version: string) { + for (const [name, addresses] of Object.entries( + PREDEFINED_DNS[version as "ipv4" | "ipv6"] + )) { + if (addresses.includes(nameserver)) { + return ` - ${name}`; + } + } + return ""; + } + private async _updateNetwork() { this._processing = true; let interfaceOptions: Partial = {}; @@ -747,10 +759,7 @@ export class HassioNetwork extends LitElement { this._dnsMenuOpen = false; } - private _addPredefinedDNS(ev: Event) { - const source = ev.target as any; - const version = source.version as "ipv4" | "ipv6"; - const addresses = source.addresses as string[]; + private _addPredefinedDNS(version: "ipv4" | "ipv6", addresses: string[]) { if (!this._interface![version]!.nameservers) { this._interface![version]!.nameservers = []; } @@ -759,9 +768,7 @@ export class HassioNetwork extends LitElement { this.requestUpdate("_interface"); } - private _addCustomDNS(ev: Event) { - const source = ev.target as any; - const version = source.version as "ipv4" | "ipv6"; + private _addCustomDNS(version: "ipv4" | "ipv6") { if (!this._interface![version]!.nameservers) { this._interface![version]!.nameservers = []; } @@ -779,6 +786,22 @@ export class HassioNetwork extends LitElement { this.requestUpdate("_interface"); } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item?.value; + + if (action === "add_predefined") { + this._addPredefinedDNS( + (ev.detail.item as any).version, + (ev.detail.item as any).addresses + ); + return; + } + + if (action === "add_custom") { + this._addCustomDNS((ev.detail.item as any).version); + } + } + static get styles(): CSSResultGroup { return [ css` @@ -817,6 +840,10 @@ export class HassioNetwork extends LitElement { --mdc-icon-button-size: 36px; margin-top: 16px; } + ha-dropdown { + display: block; + } + .add-address, .add-nameserver { margin-top: 16px; diff --git a/src/panels/config/repairs/ha-config-repairs-dashboard.ts b/src/panels/config/repairs/ha-config-repairs-dashboard.ts index cbbe39f394..38c4f9a8f2 100644 --- a/src/panels/config/repairs/ha-config-repairs-dashboard.ts +++ b/src/panels/config/repairs/ha-config-repairs-dashboard.ts @@ -1,17 +1,17 @@ -import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item-base"; +import "@home-assistant/webawesome/dist/components/divider/divider"; import { mdiDotsVertical } from "@mdi/js"; import type { UnsubscribeFunc } from "home-assistant-js-websocket"; import type { TemplateResult } from "lit"; -import { css, html, LitElement } from "lit"; +import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; -import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { navigate } from "../../../common/navigate"; import { extractSearchParam } from "../../../common/url/search-params"; import "../../../components/ha-card"; -import "../../../components/ha-check-list-item"; -import "../../../components/ha-list-item"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import type { RepairsIssue } from "../../../data/repairs"; import { severitySort, @@ -81,40 +81,36 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) { .header=${this.hass.localize("ui.panel.config.repairs.caption")} >
    - + - ${this.hass.localize("ui.panel.config.repairs.show_ignored")} - -
  • + + ${isComponentLoaded(this.hass, "system_health") || isComponentLoaded(this.hass, "hassio") ? html` - + ${this.hass.localize( "ui.panel.config.repairs.system_information" )} - + ` - : ""} - + : nothing} + ${this.hass.localize( "ui.panel.config.repairs.integration_startup_time" )} - -
    + +
    @@ -141,34 +137,34 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) { `; } - private _showSystemInformationDialog( - ev: CustomEvent - ): void { - if (!shouldHandleRequestSelectedEvent(ev)) { - return; - } - + private _showSystemInformationDialog(): void { showSystemInformationDialog(this); } - private _showIntegrationStartupDialog( - ev: CustomEvent - ): void { - if (!shouldHandleRequestSelectedEvent(ev)) { - return; - } - + private _showIntegrationStartupDialog(): void { showIntegrationStartupDialog(this); } - private _toggleIgnored(ev: CustomEvent): void { - if (ev.detail.source !== "property") { - return; - } - + private _toggleIgnored(): void { this._showIgnored = !this._showIgnored; } + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item?.value; + + switch (action) { + case "toggle_ignored": + this._toggleIgnored(); + break; + case "system_information": + this._showSystemInformationDialog(); + break; + case "integration_startup_time": + this._showIntegrationStartupDialog(); + break; + } + } + static styles = css` .content { padding: 28px 20px 0; diff --git a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts index d044b45144..3b02541fda 100644 --- a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts +++ b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts @@ -4,12 +4,12 @@ import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; -import { stopPropagation } from "../../../common/dom/stop_propagation"; import { computeDomain } from "../../../common/entity/compute_domain"; import "../../../components/ha-button"; import "../../../components/ha-dialog-header"; +import "../../../components/ha-dropdown-item"; +import type { HaDropdownItem } from "../../../components/ha-dropdown-item"; import "../../../components/ha-form/ha-form"; -import "../../../components/ha-list-item"; import type { AssistPipeline, AssistPipelineMutableParams, @@ -152,22 +152,20 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement { this._params.hideWakeWord || !this._hasWakeWorkEntities(this.hass.states) ? nothing - : html` - + ${this.hass.localize( "ui.panel.config.voice_assistants.assistants.pipeline.detail.add_streaming_wake_word" )} - `}
    @@ -243,8 +241,12 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement { `; } - private _handleShowWakeWord() { - this._hideWakeWord = false; + private _handleDropdownSelect(ev: CustomEvent<{ item: HaDropdownItem }>) { + const action = ev.detail?.item?.value; + + if (action === "show_wake_word") { + this._hideWakeWord = false; + } } private _valueChanged(ev: CustomEvent) {