mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Merge branch 'rc'
This commit is contained in:
commit
7f6ce97199
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20250507.0"
|
version = "20250509.0"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
license-files = ["LICENSE*"]
|
license-files = ["LICENSE*"]
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
|
@ -90,7 +90,7 @@ export class HaDialog extends DialogBase {
|
|||||||
}
|
}
|
||||||
.mdc-dialog__actions {
|
.mdc-dialog__actions {
|
||||||
justify-content: var(--justify-action-buttons, flex-end);
|
justify-content: var(--justify-action-buttons, flex-end);
|
||||||
padding-bottom: max(env(safe-area-inset-bottom), 24px);
|
padding: 12px 24px max(env(safe-area-inset-bottom), 12px) 24px;
|
||||||
}
|
}
|
||||||
.mdc-dialog__actions span:nth-child(1) {
|
.mdc-dialog__actions span:nth-child(1) {
|
||||||
flex: var(--secondary-action-button-flex, unset);
|
flex: var(--secondary-action-button-flex, unset);
|
||||||
@ -107,9 +107,6 @@ export class HaDialog extends DialogBase {
|
|||||||
.mdc-dialog__title:has(span) {
|
.mdc-dialog__title:has(span) {
|
||||||
padding: 12px 12px 0;
|
padding: 12px 12px 0;
|
||||||
}
|
}
|
||||||
.mdc-dialog__actions {
|
|
||||||
padding: 12px 24px 12px 24px;
|
|
||||||
}
|
|
||||||
.mdc-dialog__title::before {
|
.mdc-dialog__title::before {
|
||||||
content: unset;
|
content: unset;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public narrow = false;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: "show-advanced", type: Boolean }) public showAdvanced =
|
@property({ attribute: "show-advanced", type: Boolean }) public showAdvanced =
|
||||||
false;
|
false;
|
||||||
@ -895,6 +895,9 @@ export class HaServiceControl extends LitElement {
|
|||||||
ha-settings-row {
|
ha-settings-row {
|
||||||
padding: var(--service-control-padding, 0 16px);
|
padding: var(--service-control-padding, 0 16px);
|
||||||
}
|
}
|
||||||
|
ha-settings-row[narrow] {
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
ha-settings-row {
|
ha-settings-row {
|
||||||
--settings-row-content-width: 100%;
|
--settings-row-content-width: 100%;
|
||||||
--settings-row-prefix-display: contents;
|
--settings-row-prefix-display: contents;
|
||||||
@ -916,7 +919,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
margin: var(--service-control-padding, 0 16px);
|
margin: var(--service-control-padding, 0 16px);
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
:host([hidePicker]) p {
|
:host([hide-picker]) p {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
.checkbox-spacer {
|
.checkbox-spacer {
|
||||||
|
@ -24,9 +24,10 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
eventOptions,
|
eventOptions,
|
||||||
property,
|
property,
|
||||||
state,
|
|
||||||
query,
|
query,
|
||||||
|
state,
|
||||||
} from "lit/decorators";
|
} from "lit/decorators";
|
||||||
|
import { classMap } from "lit/directives/class-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { storage } from "../common/decorators/storage";
|
import { storage } from "../common/decorators/storage";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
@ -45,13 +46,13 @@ import { haStyleScrollbar } from "../resources/styles";
|
|||||||
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
import "./ha-icon-button";
|
import "./ha-icon-button";
|
||||||
|
import "./ha-md-list";
|
||||||
|
import "./ha-md-list-item";
|
||||||
|
import type { HaMdListItem } from "./ha-md-list-item";
|
||||||
import "./ha-menu-button";
|
import "./ha-menu-button";
|
||||||
import "./ha-sortable";
|
import "./ha-sortable";
|
||||||
import "./ha-svg-icon";
|
import "./ha-svg-icon";
|
||||||
import "./user/ha-user-badge";
|
import "./user/ha-user-badge";
|
||||||
import "./ha-md-list";
|
|
||||||
import "./ha-md-list-item";
|
|
||||||
import type { HaMdListItem } from "./ha-md-list-item";
|
|
||||||
|
|
||||||
const SHOW_AFTER_SPACER = ["config", "developer-tools"];
|
const SHOW_AFTER_SPACER = ["config", "developer-tools"];
|
||||||
|
|
||||||
@ -407,6 +408,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return html`
|
return html`
|
||||||
|
<ha-sortable .disabled=${!this.editMode} draggable-selector=".draggable" @item-moved=${this._panelMoved}>
|
||||||
<ha-md-list
|
<ha-md-list
|
||||||
class="ha-scrollbar"
|
class="ha-scrollbar"
|
||||||
@focusin=${this._listboxFocusIn}
|
@focusin=${this._listboxFocusIn}
|
||||||
@ -421,10 +423,15 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
|||||||
${this._renderPanels(afterSpacer, selectedPanel)}
|
${this._renderPanels(afterSpacer, selectedPanel)}
|
||||||
${this._renderExternalConfiguration()}
|
${this._renderExternalConfiguration()}
|
||||||
</ha-md-list>
|
</ha-md-list>
|
||||||
|
</ha-sortable>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderPanels(panels: PanelInfo[], selectedPanel: string) {
|
private _renderPanels(
|
||||||
|
panels: PanelInfo[],
|
||||||
|
selectedPanel: string,
|
||||||
|
sortable = false
|
||||||
|
) {
|
||||||
return panels.map((panel) =>
|
return panels.map((panel) =>
|
||||||
this._renderPanel(
|
this._renderPanel(
|
||||||
panel.url_path,
|
panel.url_path,
|
||||||
@ -437,17 +444,26 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
|||||||
: panel.url_path in PANEL_ICONS
|
: panel.url_path in PANEL_ICONS
|
||||||
? PANEL_ICONS[panel.url_path]
|
? PANEL_ICONS[panel.url_path]
|
||||||
: undefined,
|
: undefined,
|
||||||
selectedPanel
|
selectedPanel,
|
||||||
|
sortable
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _renderPanelsEdit(beforeSpacer: PanelInfo[], selectedPanel: string) {
|
||||||
|
return html`
|
||||||
|
${this._renderPanels(beforeSpacer, selectedPanel, true)}
|
||||||
|
${this._renderSpacer()}${this._renderHiddenPanels()}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
private _renderPanel(
|
private _renderPanel(
|
||||||
urlPath: string,
|
urlPath: string,
|
||||||
title: string | null,
|
title: string | null,
|
||||||
icon: string | null | undefined,
|
icon: string | null | undefined,
|
||||||
iconPath: string | null | undefined,
|
iconPath: string | null | undefined,
|
||||||
selectedPanel: string
|
selectedPanel: string,
|
||||||
|
sortable = false
|
||||||
) {
|
) {
|
||||||
return urlPath === "config"
|
return urlPath === "config"
|
||||||
? this._renderConfiguration(title, selectedPanel)
|
? this._renderConfiguration(title, selectedPanel)
|
||||||
@ -455,7 +471,10 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
|||||||
<ha-md-list-item
|
<ha-md-list-item
|
||||||
.href=${this.editMode ? undefined : `/${urlPath}`}
|
.href=${this.editMode ? undefined : `/${urlPath}`}
|
||||||
type="link"
|
type="link"
|
||||||
class=${selectedPanel === urlPath ? "selected" : ""}
|
class=${classMap({
|
||||||
|
selected: selectedPanel === urlPath,
|
||||||
|
draggable: this.editMode && sortable,
|
||||||
|
})}
|
||||||
@mouseenter=${this._itemMouseEnter}
|
@mouseenter=${this._itemMouseEnter}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
@mouseleave=${this._itemMouseLeave}
|
||||||
>
|
>
|
||||||
@ -496,15 +515,6 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
|||||||
this._panelOrder = panelOrder;
|
this._panelOrder = panelOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderPanelsEdit(beforeSpacer: PanelInfo[], selectedPanel: string) {
|
|
||||||
return html`
|
|
||||||
<ha-sortable .disabled=${!this.editMode} @item-moved=${this._panelMoved}
|
|
||||||
><div>${this._renderPanels(beforeSpacer, selectedPanel)}</div>
|
|
||||||
</ha-sortable>
|
|
||||||
${this._renderSpacer()}${this._renderHiddenPanels()}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderHiddenPanels() {
|
private _renderHiddenPanels() {
|
||||||
return html`${this._hiddenPanels.length
|
return html`${this._hiddenPanels.length
|
||||||
? html`${this._hiddenPanels.map((url) => {
|
? html`${this._hiddenPanels.map((url) => {
|
||||||
|
@ -316,6 +316,12 @@ class StepFlowCreateEntry extends LitElement {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
.devices {
|
||||||
|
/* header - margin content - footer */
|
||||||
|
max-height: calc(100vh - 52px - 20px - 52px);
|
||||||
|
}
|
||||||
|
}
|
||||||
.device {
|
.device {
|
||||||
border: 1px solid var(--divider-color);
|
border: 1px solid var(--divider-color);
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
@ -352,11 +358,6 @@ class StepFlowCreateEntry extends LitElement {
|
|||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
margin-inline-end: initial;
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
|
||||||
.device {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.error {
|
.error {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ const DEFAULT_AGENTS = [];
|
|||||||
class HaBackupConfigAgents extends LitElement {
|
class HaBackupConfigAgents extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public cloudStatus!: CloudStatus;
|
@property({ attribute: false }) public cloudStatus?: CloudStatus;
|
||||||
|
|
||||||
@property({ attribute: false }) public agents: BackupAgent[] = [];
|
@property({ attribute: false }) public agents: BackupAgent[] = [];
|
||||||
|
|
||||||
@ -48,7 +48,10 @@ class HaBackupConfigAgents extends LitElement {
|
|||||||
|
|
||||||
private _description(agentId: string) {
|
private _description(agentId: string) {
|
||||||
if (agentId === CLOUD_AGENT) {
|
if (agentId === CLOUD_AGENT) {
|
||||||
if (this.cloudStatus.logged_in && !this.cloudStatus.active_subscription) {
|
if (
|
||||||
|
this.cloudStatus?.logged_in &&
|
||||||
|
!this.cloudStatus.active_subscription
|
||||||
|
) {
|
||||||
return this.hass.localize(
|
return this.hass.localize(
|
||||||
"ui.panel.config.backup.agents.cloud_agent_no_subcription"
|
"ui.panel.config.backup.agents.cloud_agent_no_subcription"
|
||||||
);
|
);
|
||||||
@ -106,17 +109,17 @@ class HaBackupConfigAgents extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _availableAgents = memoizeOne(
|
private _availableAgents = memoizeOne(
|
||||||
(agents: BackupAgent[], cloudStatus: CloudStatus) =>
|
(agents: BackupAgent[], cloudStatus?: CloudStatus) =>
|
||||||
agents.filter(
|
agents.filter(
|
||||||
(agent) => agent.agent_id !== CLOUD_AGENT || cloudStatus.logged_in
|
(agent) => agent.agent_id !== CLOUD_AGENT || cloudStatus?.logged_in
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
private _unavailableAgents = memoizeOne(
|
private _unavailableAgents = memoizeOne(
|
||||||
(
|
(
|
||||||
agents: BackupAgent[],
|
agents: BackupAgent[],
|
||||||
cloudStatus: CloudStatus,
|
selectedAgentIds: string[],
|
||||||
selectedAgentIds: string[]
|
cloudStatus?: CloudStatus
|
||||||
) => {
|
) => {
|
||||||
const availableAgentIds = this._availableAgents(agents, cloudStatus).map(
|
const availableAgentIds = this._availableAgents(agents, cloudStatus).map(
|
||||||
(agent) => agent.agent_id
|
(agent) => agent.agent_id
|
||||||
@ -167,8 +170,8 @@ class HaBackupConfigAgents extends LitElement {
|
|||||||
);
|
);
|
||||||
const unavailableAgents = this._unavailableAgents(
|
const unavailableAgents = this._unavailableAgents(
|
||||||
this.agents,
|
this.agents,
|
||||||
this.cloudStatus,
|
this._value,
|
||||||
this._value
|
this.cloudStatus
|
||||||
);
|
);
|
||||||
|
|
||||||
const allAgents = [...availableAgents, ...unavailableAgents];
|
const allAgents = [...availableAgents, ...unavailableAgents];
|
||||||
@ -187,7 +190,7 @@ class HaBackupConfigAgents extends LitElement {
|
|||||||
const description = this._description(agentId);
|
const description = this._description(agentId);
|
||||||
const noCloudSubscription =
|
const noCloudSubscription =
|
||||||
agentId === CLOUD_AGENT &&
|
agentId === CLOUD_AGENT &&
|
||||||
this.cloudStatus.logged_in &&
|
this.cloudStatus?.logged_in &&
|
||||||
!this.cloudStatus.active_subscription;
|
!this.cloudStatus.active_subscription;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css, html, LitElement, nothing, type PropertyValues } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { clamp } from "../../../../../common/number/clamp";
|
import { clamp } from "../../../../../common/number/clamp";
|
||||||
import "../../../../../components/ha-expansion-panel";
|
import "../../../../../components/ha-expansion-panel";
|
||||||
@ -8,6 +8,7 @@ import "../../../../../components/ha-md-select";
|
|||||||
import type { HaMdSelect } from "../../../../../components/ha-md-select";
|
import type { HaMdSelect } from "../../../../../components/ha-md-select";
|
||||||
import "../../../../../components/ha-md-select-option";
|
import "../../../../../components/ha-md-select-option";
|
||||||
import "../../../../../components/ha-md-textfield";
|
import "../../../../../components/ha-md-textfield";
|
||||||
|
import type { HaMdTextfield } from "../../../../../components/ha-md-textfield";
|
||||||
import type { BackupConfig, Retention } from "../../../../../data/backup";
|
import type { BackupConfig, Retention } from "../../../../../data/backup";
|
||||||
import type { HomeAssistant } from "../../../../../types";
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
|
|
||||||
@ -54,16 +55,21 @@ class HaBackupConfigRetention extends LitElement {
|
|||||||
|
|
||||||
@state() private _value = 3;
|
@state() private _value = 3;
|
||||||
|
|
||||||
|
@query("#value") private _customValueField?: HaMdTextfield;
|
||||||
|
|
||||||
|
@query("#type") private _customTypeField?: HaMdSelect;
|
||||||
|
|
||||||
|
private _configLoaded = false;
|
||||||
|
|
||||||
private presetOptions = [
|
private presetOptions = [
|
||||||
RetentionPreset.COPIES_3,
|
RetentionPreset.COPIES_3,
|
||||||
RetentionPreset.FOREVER,
|
RetentionPreset.FOREVER,
|
||||||
RetentionPreset.CUSTOM,
|
RetentionPreset.CUSTOM,
|
||||||
];
|
];
|
||||||
|
|
||||||
public willUpdate(properties: PropertyValues) {
|
public willUpdate() {
|
||||||
super.willUpdate(properties);
|
if (!this._configLoaded && this.retention !== undefined) {
|
||||||
|
this._configLoaded = true;
|
||||||
if (!this.hasUpdated) {
|
|
||||||
if (!this.retention) {
|
if (!this.retention) {
|
||||||
this._preset = RetentionPreset.GLOBAL;
|
this._preset = RetentionPreset.GLOBAL;
|
||||||
} else if (
|
} else if (
|
||||||
@ -94,6 +100,10 @@ class HaBackupConfigRetention extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
if (!this._configLoaded) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-md-list-item>
|
<ha-md-list-item>
|
||||||
<span slot="headline">
|
<span slot="headline">
|
||||||
@ -206,10 +216,12 @@ class HaBackupConfigRetention extends LitElement {
|
|||||||
const clamped = clamp(value, MIN_VALUE, MAX_VALUE);
|
const clamped = clamp(value, MIN_VALUE, MAX_VALUE);
|
||||||
target.value = clamped.toString();
|
target.value = clamped.toString();
|
||||||
|
|
||||||
|
const type = this._customTypeField?.value;
|
||||||
|
|
||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
value: {
|
value: {
|
||||||
copies: this._type === "copies" ? clamped : null,
|
copies: type === "copies" ? clamped : null,
|
||||||
days: this._type === "days" ? clamped : null,
|
days: type === "days" ? clamped : null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -219,10 +231,12 @@ class HaBackupConfigRetention extends LitElement {
|
|||||||
const target = ev.currentTarget as HaMdSelect;
|
const target = ev.currentTarget as HaMdSelect;
|
||||||
const type = target.value as "copies" | "days";
|
const type = target.value as "copies" | "days";
|
||||||
|
|
||||||
|
const value = this._customValueField?.value;
|
||||||
|
|
||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
value: {
|
value: {
|
||||||
copies: type === "copies" ? this._value : null,
|
copies: type === "copies" ? Number(value) : null,
|
||||||
days: type === "days" ? this._value : null,
|
days: type === "days" ? Number(value) : null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,8 +125,10 @@ class HaConfigBackupDetails extends LitElement {
|
|||||||
{ location: agentName }
|
{ location: agentName }
|
||||||
)}
|
)}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.retention=${this.config?.agents[this.agentId]
|
.retention=${!this.config
|
||||||
?.retention}
|
? undefined
|
||||||
|
: this.config.agents[this.agentId]?.retention ||
|
||||||
|
null}
|
||||||
@value-changed=${this._retentionChanged}
|
@value-changed=${this._retentionChanged}
|
||||||
></ha-backup-config-retention>`}
|
></ha-backup-config-retention>`}
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
@ -41,7 +41,7 @@ import { brandsUrl } from "../../../util/brands-url";
|
|||||||
class HaConfigBackupSettings extends LitElement {
|
class HaConfigBackupSettings extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public cloudStatus!: CloudStatus;
|
@property({ attribute: false }) public cloudStatus?: CloudStatus;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow = false;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ class HaConfigBackupSettings extends LitElement {
|
|||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${!this.cloudStatus.logged_in
|
${!this.cloudStatus?.logged_in
|
||||||
? html`<ha-card class="cloud-info">
|
? html`<ha-card class="cloud-info">
|
||||||
<div class="cloud-header">
|
<div class="cloud-header">
|
||||||
<img
|
<img
|
||||||
|
@ -29,9 +29,8 @@ class DialogBluetoothDeviceInfo extends LitElement implements HassDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public showDataAsHex(bytestring: string): string {
|
public showDataAsHex(bytestring: string): string {
|
||||||
return Array.from(new TextEncoder().encode(bytestring))
|
const bytes = bytestring.match(/.{2}/g) ?? [];
|
||||||
.map((byte) => byte.toString(16).toUpperCase().padStart(2, "0"))
|
return bytes.map((byte) => `0x${byte.toUpperCase()}`).join(" ");
|
||||||
.join(" ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _copyToClipboard(): Promise<void> {
|
private async _copyToClipboard(): Promise<void> {
|
||||||
|
@ -9,6 +9,7 @@ import type { SSDPDiscoveryInfoDialogParams } from "./show-dialog-ssdp-discovery
|
|||||||
import "../../../../../components/ha-button";
|
import "../../../../../components/ha-button";
|
||||||
import { showToast } from "../../../../../util/toast";
|
import { showToast } from "../../../../../util/toast";
|
||||||
import { copyToClipboard } from "../../../../../common/util/copy-clipboard";
|
import { copyToClipboard } from "../../../../../common/util/copy-clipboard";
|
||||||
|
import { showSSDPRawDataDialog } from "./show-dialog-ssdp-raw-data";
|
||||||
|
|
||||||
@customElement("dialog-ssdp-device-info")
|
@customElement("dialog-ssdp-device-info")
|
||||||
class DialogSSDPDiscoveryInfo extends LitElement implements HassDialog {
|
class DialogSSDPDiscoveryInfo extends LitElement implements HassDialog {
|
||||||
@ -39,6 +40,16 @@ class DialogSSDPDiscoveryInfo extends LitElement implements HassDialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _showRawData(key: string, data: Record<string, unknown>) {
|
||||||
|
return (e: Event) => {
|
||||||
|
e.preventDefault();
|
||||||
|
showSSDPRawDataDialog(this, {
|
||||||
|
key,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | typeof nothing {
|
protected render(): TemplateResult | typeof nothing {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return nothing;
|
return nothing;
|
||||||
@ -83,7 +94,20 @@ class DialogSSDPDiscoveryInfo extends LitElement implements HassDialog {
|
|||||||
([key, value]) => html`
|
([key, value]) => html`
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>${key}</b></td>
|
<td><b>${key}</b></td>
|
||||||
<td>${value}</td>
|
<td>
|
||||||
|
${typeof value === "object" && value !== null
|
||||||
|
? html`<a
|
||||||
|
href="#"
|
||||||
|
@click=${this._showRawData(
|
||||||
|
key,
|
||||||
|
value as Record<string, unknown>
|
||||||
|
)}
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.ssdp.show_raw_data"
|
||||||
|
)}</a
|
||||||
|
>`
|
||||||
|
: value}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
import { LitElement, html, nothing, css } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import type { TemplateResult } from "lit";
|
||||||
|
import { dump } from "js-yaml";
|
||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import type { HassDialog } from "../../../../../dialogs/make-dialog-manager";
|
||||||
|
import { createCloseHeading } from "../../../../../components/ha-dialog";
|
||||||
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
|
import "../../../../../components/ha-code-editor";
|
||||||
|
|
||||||
|
export interface SSDPRawDataDialogParams {
|
||||||
|
key: string;
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("dialog-ssdp-raw-data")
|
||||||
|
class DialogSSDPRawData extends LitElement implements HassDialog {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _params?: SSDPRawDataDialogParams;
|
||||||
|
|
||||||
|
public async showDialog(params: SSDPRawDataDialogParams): Promise<void> {
|
||||||
|
this._params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): boolean {
|
||||||
|
this._params = undefined;
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | typeof nothing {
|
||||||
|
if (!this._params) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
.heading=${createCloseHeading(
|
||||||
|
this.hass,
|
||||||
|
`${this.hass.localize("ui.panel.config.ssdp.raw_data_title")}: ${this._params.key}`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-code-editor
|
||||||
|
mode="yaml"
|
||||||
|
.value=${dump(this._params.data)}
|
||||||
|
readonly
|
||||||
|
autofocus
|
||||||
|
></ha-code-editor>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
ha-code-editor {
|
||||||
|
--code-mirror-max-height: 60vh;
|
||||||
|
--code-mirror-height: auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-ssdp-raw-data": DialogSSDPRawData;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
|
||||||
|
export interface SSDPRawDataDialogParams {
|
||||||
|
key: string;
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadSSDPRawDataDialog = () => import("./dialog-ssdp-raw-data");
|
||||||
|
|
||||||
|
export const showSSDPRawDataDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
ssdpRawDataDialogParams: SSDPRawDataDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-ssdp-raw-data",
|
||||||
|
dialogImport: loadSSDPRawDataDialog,
|
||||||
|
dialogParams: ssdpRawDataDialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import { css } from "lit";
|
import { css } from "lit";
|
||||||
|
|
||||||
export const sidebarEditStyle = css`
|
export const sidebarEditStyle = css`
|
||||||
ha-sortable ha-md-list-item:nth-child(2n) {
|
ha-sortable ha-md-list-item.draggable:nth-child(2n) {
|
||||||
animation-name: keyframes1;
|
animation-name: keyframes1;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
transform-origin: 50% 10%;
|
transform-origin: 50% 10%;
|
||||||
@ -9,7 +9,7 @@ export const sidebarEditStyle = css`
|
|||||||
animation-duration: 0.25s;
|
animation-duration: 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-sortable ha-md-list-item:nth-child(2n-1) {
|
ha-sortable ha-md-list-item.draggable:nth-child(2n-1) {
|
||||||
animation-name: keyframes2;
|
animation-name: keyframes2;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-direction: alternate;
|
animation-direction: alternate;
|
||||||
@ -18,8 +18,7 @@ export const sidebarEditStyle = css`
|
|||||||
animation-duration: 0.33s;
|
animation-duration: 0.33s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-sortable ha-md-list-item {
|
ha-sortable ha-md-list-item.draggable {
|
||||||
height: 48px;
|
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5586,7 +5586,9 @@
|
|||||||
"upnp": "Universal Plug and Play (UPnP)",
|
"upnp": "Universal Plug and Play (UPnP)",
|
||||||
"discovery_information": "Discovery information",
|
"discovery_information": "Discovery information",
|
||||||
"copy_to_clipboard": "Copy to clipboard",
|
"copy_to_clipboard": "Copy to clipboard",
|
||||||
"no_devices_found": "No matching SSDP/UPnP discoveries found"
|
"no_devices_found": "No matching SSDP/UPnP discoveries found",
|
||||||
|
"show_raw_data": "Show raw data",
|
||||||
|
"raw_data_title": "Raw data"
|
||||||
},
|
},
|
||||||
"zeroconf": {
|
"zeroconf": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user