Merge branch 'dev' of github.com:home-assistant/frontend into auto-jsdoc-markdown
commit
fe37f8fad5
|
@ -155,14 +155,14 @@
|
||||||
"@babel/helper-define-polyfill-provider": "0.6.4",
|
"@babel/helper-define-polyfill-provider": "0.6.4",
|
||||||
"@babel/plugin-transform-runtime": "7.27.1",
|
"@babel/plugin-transform-runtime": "7.27.1",
|
||||||
"@babel/preset-env": "7.27.2",
|
"@babel/preset-env": "7.27.2",
|
||||||
"@bundle-stats/plugin-webpack-filter": "4.20.0",
|
"@bundle-stats/plugin-webpack-filter": "4.20.1",
|
||||||
"@custom-elements-manifest/analyzer": "0.10.4",
|
"@custom-elements-manifest/analyzer": "0.10.4",
|
||||||
"@custom-elements-manifest/to-markdown": "0.1.0",
|
"@custom-elements-manifest/to-markdown": "0.1.0",
|
||||||
"@lokalise/node-api": "14.6.0",
|
"@lokalise/node-api": "14.7.0",
|
||||||
"@octokit/auth-oauth-device": "7.1.5",
|
"@octokit/auth-oauth-device": "7.1.5",
|
||||||
"@octokit/plugin-retry": "7.2.1",
|
"@octokit/plugin-retry": "7.2.1",
|
||||||
"@octokit/rest": "21.1.1",
|
"@octokit/rest": "21.1.1",
|
||||||
"@rsdoctor/rspack-plugin": "1.1.1",
|
"@rsdoctor/rspack-plugin": "1.1.2",
|
||||||
"@rspack/cli": "1.3.9",
|
"@rspack/cli": "1.3.9",
|
||||||
"@rspack/core": "1.3.9",
|
"@rspack/core": "1.3.9",
|
||||||
"@types/babel__plugin-transform-runtime": "7.9.5",
|
"@types/babel__plugin-transform-runtime": "7.9.5",
|
||||||
|
|
|
@ -164,6 +164,8 @@ export class HaDataTable extends LitElement {
|
||||||
|
|
||||||
@state() private _collapsedGroups: string[] = [];
|
@state() private _collapsedGroups: string[] = [];
|
||||||
|
|
||||||
|
@state() private _lastSelectedRowId: string | null = null;
|
||||||
|
|
||||||
private _checkableRowsCount?: number;
|
private _checkableRowsCount?: number;
|
||||||
|
|
||||||
private _checkedRows: string[] = [];
|
private _checkedRows: string[] = [];
|
||||||
|
@ -187,6 +189,7 @@ export class HaDataTable extends LitElement {
|
||||||
|
|
||||||
public clearSelection(): void {
|
public clearSelection(): void {
|
||||||
this._checkedRows = [];
|
this._checkedRows = [];
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +197,7 @@ export class HaDataTable extends LitElement {
|
||||||
this._checkedRows = this._filteredData
|
this._checkedRows = this._filteredData
|
||||||
.filter((data) => data.selectable !== false)
|
.filter((data) => data.selectable !== false)
|
||||||
.map((data) => data[this.id]);
|
.map((data) => data[this.id]);
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +211,7 @@ export class HaDataTable extends LitElement {
|
||||||
this._checkedRows.push(id);
|
this._checkedRows.push(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +222,7 @@ export class HaDataTable extends LitElement {
|
||||||
this._checkedRows.splice(index, 1);
|
this._checkedRows.splice(index, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +267,7 @@ export class HaDataTable extends LitElement {
|
||||||
if (this.columns[columnId].direction) {
|
if (this.columns[columnId].direction) {
|
||||||
this.sortDirection = this.columns[columnId].direction!;
|
this.sortDirection = this.columns[columnId].direction!;
|
||||||
this.sortColumn = columnId;
|
this.sortColumn = columnId;
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
|
|
||||||
fireEvent(this, "sorting-changed", {
|
fireEvent(this, "sorting-changed", {
|
||||||
column: columnId,
|
column: columnId,
|
||||||
|
@ -286,6 +293,7 @@ export class HaDataTable extends LitElement {
|
||||||
|
|
||||||
if (properties.has("filter")) {
|
if (properties.has("filter")) {
|
||||||
this._debounceSearch(this.filter);
|
this._debounceSearch(this.filter);
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.has("data")) {
|
if (properties.has("data")) {
|
||||||
|
@ -296,9 +304,11 @@ export class HaDataTable extends LitElement {
|
||||||
|
|
||||||
if (!this.hasUpdated && this.initialCollapsedGroups) {
|
if (!this.hasUpdated && this.initialCollapsedGroups) {
|
||||||
this._collapsedGroups = this.initialCollapsedGroups;
|
this._collapsedGroups = this.initialCollapsedGroups;
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||||
} else if (properties.has("groupColumn")) {
|
} else if (properties.has("groupColumn")) {
|
||||||
this._collapsedGroups = [];
|
this._collapsedGroups = [];
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +322,14 @@ export class HaDataTable extends LitElement {
|
||||||
this._sortFilterData();
|
this._sortFilterData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
properties.has("_filter") ||
|
||||||
|
properties.has("sortColumn") ||
|
||||||
|
properties.has("sortDirection")
|
||||||
|
) {
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.has("selectable") || properties.has("hiddenColumns")) {
|
if (properties.has("selectable") || properties.has("hiddenColumns")) {
|
||||||
this._filteredData = [...this._filteredData];
|
this._filteredData = [...this._filteredData];
|
||||||
}
|
}
|
||||||
|
@ -542,7 +560,7 @@ export class HaDataTable extends LitElement {
|
||||||
>
|
>
|
||||||
<ha-checkbox
|
<ha-checkbox
|
||||||
class="mdc-data-table__row-checkbox"
|
class="mdc-data-table__row-checkbox"
|
||||||
@change=${this._handleRowCheckboxClick}
|
@click=${this._handleRowCheckboxClicked}
|
||||||
.rowId=${row[this.id]}
|
.rowId=${row[this.id]}
|
||||||
.disabled=${row.selectable === false}
|
.disabled=${row.selectable === false}
|
||||||
.checked=${this._checkedRows.includes(String(row[this.id]))}
|
.checked=${this._checkedRows.includes(String(row[this.id]))}
|
||||||
|
@ -724,6 +742,7 @@ export class HaDataTable extends LitElement {
|
||||||
Object.entries(sorted).forEach(([groupName, rows]) => {
|
Object.entries(sorted).forEach(([groupName, rows]) => {
|
||||||
groupedItems.push({
|
groupedItems.push({
|
||||||
append: true,
|
append: true,
|
||||||
|
selectable: false,
|
||||||
content: html`<div
|
content: html`<div
|
||||||
class="mdc-data-table__cell group-header"
|
class="mdc-data-table__cell group-header"
|
||||||
role="cell"
|
role="cell"
|
||||||
|
@ -750,7 +769,7 @@ export class HaDataTable extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appendRow) {
|
if (appendRow) {
|
||||||
items.push({ append: true, content: appendRow });
|
items.push({ append: true, selectable: false, content: appendRow });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFab) {
|
if (hasFab) {
|
||||||
|
@ -800,23 +819,84 @@ export class HaDataTable extends LitElement {
|
||||||
this._checkedRows = [];
|
this._checkedRows = [];
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
}
|
}
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleRowCheckboxClick = (ev: Event) => {
|
private _handleRowCheckboxClicked = (ev: Event) => {
|
||||||
const checkbox = ev.currentTarget as HaCheckbox;
|
const checkbox = ev.currentTarget as HaCheckbox;
|
||||||
const rowId = (checkbox as any).rowId;
|
const rowId = (checkbox as any).rowId;
|
||||||
|
|
||||||
if (checkbox.checked) {
|
const groupedData = this._groupData(
|
||||||
if (this._checkedRows.includes(rowId)) {
|
this._filteredData,
|
||||||
return;
|
this.localizeFunc || this.hass.localize,
|
||||||
|
this.appendRow,
|
||||||
|
this.hasFab,
|
||||||
|
this.groupColumn,
|
||||||
|
this.groupOrder,
|
||||||
|
this._collapsedGroups
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
groupedData.find((data) => data[this.id] === rowId)?.selectable === false
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowIndex = groupedData.findIndex((data) => data[this.id] === rowId);
|
||||||
|
|
||||||
|
if (
|
||||||
|
ev instanceof MouseEvent &&
|
||||||
|
ev.shiftKey &&
|
||||||
|
this._lastSelectedRowId !== null
|
||||||
|
) {
|
||||||
|
const lastSelectedRowIndex = groupedData.findIndex(
|
||||||
|
(data) => data[this.id] === this._lastSelectedRowId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lastSelectedRowIndex > -1 && rowIndex > -1) {
|
||||||
|
this._checkedRows = [
|
||||||
|
...this._checkedRows,
|
||||||
|
...this._selectRange(groupedData, lastSelectedRowIndex, rowIndex),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else if (!checkbox.checked) {
|
||||||
|
if (!this._checkedRows.includes(rowId)) {
|
||||||
|
this._checkedRows = [...this._checkedRows, rowId];
|
||||||
}
|
}
|
||||||
this._checkedRows = [...this._checkedRows, rowId];
|
|
||||||
} else {
|
} else {
|
||||||
this._checkedRows = this._checkedRows.filter((row) => row !== rowId);
|
this._checkedRows = this._checkedRows.filter((row) => row !== rowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rowIndex > -1) {
|
||||||
|
this._lastSelectedRowId = rowId;
|
||||||
|
}
|
||||||
this._checkedRowsChanged();
|
this._checkedRowsChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private _selectRange(
|
||||||
|
groupedData: DataTableRowData[],
|
||||||
|
startIndex: number,
|
||||||
|
endIndex: number
|
||||||
|
) {
|
||||||
|
const start = Math.min(startIndex, endIndex);
|
||||||
|
const end = Math.max(startIndex, endIndex);
|
||||||
|
|
||||||
|
const checkedRows: string[] = [];
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
const row = groupedData[i];
|
||||||
|
if (
|
||||||
|
row &&
|
||||||
|
row.selectable !== false &&
|
||||||
|
!this._checkedRows.includes(row[this.id])
|
||||||
|
) {
|
||||||
|
checkedRows.push(row[this.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkedRows;
|
||||||
|
}
|
||||||
|
|
||||||
private _handleRowClick = (ev: Event) => {
|
private _handleRowClick = (ev: Event) => {
|
||||||
if (
|
if (
|
||||||
ev
|
ev
|
||||||
|
@ -858,6 +938,7 @@ export class HaDataTable extends LitElement {
|
||||||
if (this.filter) {
|
if (this.filter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
this._debounceSearch(ev.detail.value);
|
this._debounceSearch(ev.detail.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,11 +975,13 @@ export class HaDataTable extends LitElement {
|
||||||
} else {
|
} else {
|
||||||
this._collapsedGroups = [...this._collapsedGroups, groupName];
|
this._collapsedGroups = [...this._collapsedGroups, groupName];
|
||||||
}
|
}
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||||
};
|
};
|
||||||
|
|
||||||
public expandAllGroups() {
|
public expandAllGroups() {
|
||||||
this._collapsedGroups = [];
|
this._collapsedGroups = [];
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,6 +999,7 @@ export class HaDataTable extends LitElement {
|
||||||
delete grouped.undefined;
|
delete grouped.undefined;
|
||||||
}
|
}
|
||||||
this._collapsedGroups = Object.keys(grouped);
|
this._collapsedGroups = Object.keys(grouped);
|
||||||
|
this._lastSelectedRowId = null;
|
||||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import { mdiClose, mdiMenuDown, mdiShape } from "@mdi/js";
|
import { mdiClose, mdiMenuDown, mdiShape } from "@mdi/js";
|
||||||
import type { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light";
|
import type { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light";
|
||||||
import { css, html, LitElement, nothing, type CSSResultGroup } from "lit";
|
import {
|
||||||
|
css,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
nothing,
|
||||||
|
type CSSResultGroup,
|
||||||
|
type PropertyValues,
|
||||||
|
} from "lit";
|
||||||
import { customElement, property, query, 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 { stopPropagation } from "../../common/dom/stop_propagation";
|
import { stopPropagation } from "../../common/dom/stop_propagation";
|
||||||
|
@ -106,6 +113,12 @@ export class HaEntityPicker extends LitElement {
|
||||||
|
|
||||||
@state() private _opened = false;
|
@state() private _opened = false;
|
||||||
|
|
||||||
|
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||||
|
super.firstUpdated(changedProperties);
|
||||||
|
// Load title translations so it is available when the combo-box opens
|
||||||
|
this.hass.loadBackendTranslation("title");
|
||||||
|
}
|
||||||
|
|
||||||
private _renderContent() {
|
private _renderContent() {
|
||||||
const entityId = this.value || "";
|
const entityId = this.value || "";
|
||||||
|
|
||||||
|
|
|
@ -201,25 +201,6 @@ class HaWebRtcPlayer extends LitElement {
|
||||||
|
|
||||||
let candidates = "";
|
let candidates = "";
|
||||||
|
|
||||||
if (this._clientConfig?.getCandidatesUpfront) {
|
|
||||||
await new Promise<void>((resolve) => {
|
|
||||||
this._peerConnection!.onicegatheringstatechange = (ev: Event) => {
|
|
||||||
const iceGatheringState = (ev.target as RTCPeerConnection)
|
|
||||||
.iceGatheringState;
|
|
||||||
if (iceGatheringState === "complete") {
|
|
||||||
this._peerConnection!.onicegatheringstatechange = null;
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._logEvent("Ice gathering state changed", iceGatheringState);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this._peerConnection || !this.entityid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (this._candidatesList.length) {
|
while (this._candidatesList.length) {
|
||||||
const candidate = this._candidatesList.pop();
|
const candidate = this._candidatesList.pop();
|
||||||
if (candidate) {
|
if (candidate) {
|
||||||
|
|
|
@ -190,7 +190,6 @@ export const fetchCameraCapabilities = async (
|
||||||
export interface WebRTCClientConfiguration {
|
export interface WebRTCClientConfiguration {
|
||||||
configuration: RTCConfiguration;
|
configuration: RTCConfiguration;
|
||||||
dataChannel?: string;
|
dataChannel?: string;
|
||||||
getCandidatesUpfront: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchWebRtcClientConfiguration = async (
|
export const fetchWebRtcClientConfiguration = async (
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import type { Connection } from "home-assistant-js-websocket";
|
import type { Connection } from "home-assistant-js-websocket";
|
||||||
import { getOptimisticCollection } from "./collection";
|
|
||||||
|
|
||||||
export interface CoreFrontendUserData {
|
export interface CoreFrontendUserData {
|
||||||
showAdvanced?: boolean;
|
showAdvanced?: boolean;
|
||||||
|
@ -42,30 +41,15 @@ export const saveFrontendUserData = async <
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getOptimisticFrontendUserDataCollection = <
|
|
||||||
UserDataKey extends ValidUserDataKey,
|
|
||||||
>(
|
|
||||||
conn: Connection,
|
|
||||||
userDataKey: UserDataKey
|
|
||||||
) =>
|
|
||||||
getOptimisticCollection(
|
|
||||||
(_conn, data) =>
|
|
||||||
saveFrontendUserData(
|
|
||||||
conn,
|
|
||||||
userDataKey,
|
|
||||||
// @ts-ignore
|
|
||||||
data
|
|
||||||
),
|
|
||||||
conn,
|
|
||||||
`_frontendUserData-${userDataKey}`,
|
|
||||||
() => fetchFrontendUserData(conn, userDataKey)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const subscribeFrontendUserData = <UserDataKey extends ValidUserDataKey>(
|
export const subscribeFrontendUserData = <UserDataKey extends ValidUserDataKey>(
|
||||||
conn: Connection,
|
conn: Connection,
|
||||||
userDataKey: UserDataKey,
|
userDataKey: UserDataKey,
|
||||||
onChange: (state: FrontendUserData[UserDataKey] | null) => void
|
onChange: (data: { value: FrontendUserData[UserDataKey] | null }) => void
|
||||||
) =>
|
) =>
|
||||||
getOptimisticFrontendUserDataCollection(conn, userDataKey).subscribe(
|
conn.subscribeMessage<{ value: FrontendUserData[UserDataKey] | null }>(
|
||||||
onChange
|
onChange,
|
||||||
|
{
|
||||||
|
type: "frontend/subscribe_user_data",
|
||||||
|
key: userDataKey,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { fetchFrontendUserData, saveFrontendUserData } from "./frontend";
|
import {
|
||||||
|
fetchFrontendUserData,
|
||||||
|
saveFrontendUserData,
|
||||||
|
subscribeFrontendUserData,
|
||||||
|
} from "./frontend";
|
||||||
|
|
||||||
export enum NumberFormat {
|
export enum NumberFormat {
|
||||||
language = "language",
|
language = "language",
|
||||||
|
@ -77,6 +81,11 @@ export type TranslationCategory =
|
||||||
export const fetchTranslationPreferences = (hass: HomeAssistant) =>
|
export const fetchTranslationPreferences = (hass: HomeAssistant) =>
|
||||||
fetchFrontendUserData(hass.connection, "language");
|
fetchFrontendUserData(hass.connection, "language");
|
||||||
|
|
||||||
|
export const subscribeTranslationPreferences = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
callback: (data: { value: FrontendLocaleData | null }) => void
|
||||||
|
) => subscribeFrontendUserData(hass.connection, "language", callback);
|
||||||
|
|
||||||
export const saveTranslationPreferences = (
|
export const saveTranslationPreferences = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
data: FrontendLocaleData
|
data: FrontendLocaleData
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import { mdiClose, mdiHelpCircle } from "@mdi/js";
|
import { mdiClose, mdiHelpCircle } from "@mdi/js";
|
||||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import type { HASSDomEvent } from "../../common/dom/fire_event";
|
import type { HASSDomEvent } from "../../common/dom/fire_event";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import "../../components/ha-dialog";
|
import "../../components/ha-dialog";
|
||||||
|
import "../../components/ha-dialog-header";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
import type { DataEntryFlowStep } from "../../data/data_entry_flow";
|
import type { DataEntryFlowStep } from "../../data/data_entry_flow";
|
||||||
import {
|
import {
|
||||||
subscribeDataEntryFlowProgress,
|
subscribeDataEntryFlowProgress,
|
||||||
subscribeDataEntryFlowProgressed,
|
subscribeDataEntryFlowProgressed,
|
||||||
} from "../../data/data_entry_flow";
|
} from "../../data/data_entry_flow";
|
||||||
|
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
||||||
import { haStyleDialog } from "../../resources/styles";
|
import { haStyleDialog } from "../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { documentationUrl } from "../../util/documentation-url";
|
import { documentationUrl } from "../../util/documentation-url";
|
||||||
|
@ -171,6 +174,92 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _devices = memoizeOne(
|
||||||
|
(
|
||||||
|
showDevices: boolean,
|
||||||
|
devices: DeviceRegistryEntry[],
|
||||||
|
entry_id?: string
|
||||||
|
) =>
|
||||||
|
showDevices && entry_id
|
||||||
|
? devices.filter((device) => device.config_entries.includes(entry_id))
|
||||||
|
: []
|
||||||
|
);
|
||||||
|
|
||||||
|
private _getDialogTitle(): string {
|
||||||
|
if (this._loading || !this._step || !this._params) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this._step.type) {
|
||||||
|
case "form":
|
||||||
|
return this._params.flowConfig.renderShowFormStepHeader(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
case "abort":
|
||||||
|
return this._params.flowConfig.renderAbortHeader
|
||||||
|
? this._params.flowConfig.renderAbortHeader(this.hass, this._step)
|
||||||
|
: this.hass.localize(
|
||||||
|
`component.${this._params.domain ?? this._step.handler}.title`
|
||||||
|
);
|
||||||
|
case "progress":
|
||||||
|
return this._params.flowConfig.renderShowFormProgressHeader(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
case "menu":
|
||||||
|
return this._params.flowConfig.renderMenuHeader(this.hass, this._step);
|
||||||
|
case "create_entry": {
|
||||||
|
const devicesLength = this._devices(
|
||||||
|
this._params.flowConfig.showDevices,
|
||||||
|
Object.values(this.hass.devices),
|
||||||
|
this._step.result?.entry_id
|
||||||
|
).length;
|
||||||
|
return this.hass.localize(
|
||||||
|
`ui.panel.config.integrations.config_flow.${
|
||||||
|
devicesLength ? "device_created" : "success"
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
number: devicesLength,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getDialogSubtitle(): string | TemplateResult | undefined {
|
||||||
|
if (this._loading || !this._step || !this._params) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this._step.type) {
|
||||||
|
case "form":
|
||||||
|
return this._params.flowConfig.renderShowFormStepSubheader?.(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
case "abort":
|
||||||
|
return this._params.flowConfig.renderAbortSubheader?.(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
case "progress":
|
||||||
|
return this._params.flowConfig.renderShowFormProgressSubheader?.(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
case "menu":
|
||||||
|
return this._params.flowConfig.renderMenuSubheader?.(
|
||||||
|
this.hass,
|
||||||
|
this._step
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return nothing;
|
return nothing;
|
||||||
|
@ -187,6 +276,9 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
this._params.manifest?.is_built_in) ||
|
this._params.manifest?.is_built_in) ||
|
||||||
!!this._params.manifest?.documentation;
|
!!this._params.manifest?.documentation;
|
||||||
|
|
||||||
|
const dialogTitle = this._getDialogTitle();
|
||||||
|
const dialogSubtitle = this._getDialogSubtitle();
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-dialog
|
||||||
open
|
open
|
||||||
|
@ -194,7 +286,50 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
scrimClickAction
|
scrimClickAction
|
||||||
escapeKeyAction
|
escapeKeyAction
|
||||||
hideActions
|
hideActions
|
||||||
|
.heading=${dialogTitle}
|
||||||
>
|
>
|
||||||
|
<ha-dialog-header slot="heading">
|
||||||
|
<ha-icon-button
|
||||||
|
.label=${this.hass.localize("ui.common.close")}
|
||||||
|
.path=${mdiClose}
|
||||||
|
dialogAction="close"
|
||||||
|
slot="navigationIcon"
|
||||||
|
></ha-icon-button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
slot="title"
|
||||||
|
class="dialog-title${this._step?.type === "form" ? " form" : ""}"
|
||||||
|
title=${dialogTitle}
|
||||||
|
>
|
||||||
|
${dialogTitle}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${dialogSubtitle
|
||||||
|
? html` <div slot="subtitle">${dialogSubtitle}</div>`
|
||||||
|
: nothing}
|
||||||
|
${showDocumentationLink && !this._loading && this._step
|
||||||
|
? html`
|
||||||
|
<a
|
||||||
|
slot="actionItems"
|
||||||
|
class="help"
|
||||||
|
href=${this._params.manifest!.is_built_in
|
||||||
|
? documentationUrl(
|
||||||
|
this.hass,
|
||||||
|
`/integrations/${this._params.manifest!.domain}`
|
||||||
|
)
|
||||||
|
: this._params.manifest!.documentation}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
.label=${this.hass.localize("ui.common.help")}
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
>
|
||||||
|
</ha-icon-button
|
||||||
|
></a>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
</ha-dialog-header>
|
||||||
<div>
|
<div>
|
||||||
${this._loading || this._step === null
|
${this._loading || this._step === null
|
||||||
? html`
|
? html`
|
||||||
|
@ -211,40 +346,12 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
// to reset the element.
|
// to reset the element.
|
||||||
nothing
|
nothing
|
||||||
: html`
|
: html`
|
||||||
<div class="dialog-actions">
|
|
||||||
${showDocumentationLink
|
|
||||||
? html`
|
|
||||||
<a
|
|
||||||
href=${this._params.manifest!.is_built_in
|
|
||||||
? documentationUrl(
|
|
||||||
this.hass,
|
|
||||||
`/integrations/${this._params.manifest!.domain}`
|
|
||||||
)
|
|
||||||
: this._params.manifest!.documentation}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
|
||||||
.label=${this.hass.localize("ui.common.help")}
|
|
||||||
.path=${mdiHelpCircle}
|
|
||||||
>
|
|
||||||
</ha-icon-button
|
|
||||||
></a>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
<ha-icon-button
|
|
||||||
.label=${this.hass.localize("ui.common.close")}
|
|
||||||
.path=${mdiClose}
|
|
||||||
dialogAction="close"
|
|
||||||
></ha-icon-button>
|
|
||||||
</div>
|
|
||||||
${this._step.type === "form"
|
${this._step.type === "form"
|
||||||
? html`
|
? html`
|
||||||
<step-flow-form
|
<step-flow-form
|
||||||
.flowConfig=${this._params.flowConfig}
|
.flowConfig=${this._params.flowConfig}
|
||||||
.step=${this._step}
|
.step=${this._step}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
|
||||||
></step-flow-form>
|
></step-flow-form>
|
||||||
`
|
`
|
||||||
: this._step.type === "external"
|
: this._step.type === "external"
|
||||||
|
@ -253,7 +360,6 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
.flowConfig=${this._params.flowConfig}
|
.flowConfig=${this._params.flowConfig}
|
||||||
.step=${this._step}
|
.step=${this._step}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
|
||||||
></step-flow-external>
|
></step-flow-external>
|
||||||
`
|
`
|
||||||
: this._step.type === "abort"
|
: this._step.type === "abort"
|
||||||
|
@ -265,7 +371,6 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
.handler=${this._step.handler}
|
.handler=${this._step.handler}
|
||||||
.domain=${this._params.domain ??
|
.domain=${this._params.domain ??
|
||||||
this._step.handler}
|
this._step.handler}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
|
||||||
></step-flow-abort>
|
></step-flow-abort>
|
||||||
`
|
`
|
||||||
: this._step.type === "progress"
|
: this._step.type === "progress"
|
||||||
|
@ -275,7 +380,6 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
.step=${this._step}
|
.step=${this._step}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.progress=${this._progress}
|
.progress=${this._progress}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
|
||||||
></step-flow-progress>
|
></step-flow-progress>
|
||||||
`
|
`
|
||||||
: this._step.type === "menu"
|
: this._step.type === "menu"
|
||||||
|
@ -284,7 +388,6 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
.flowConfig=${this._params.flowConfig}
|
.flowConfig=${this._params.flowConfig}
|
||||||
.step=${this._step}
|
.step=${this._step}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
|
||||||
></step-flow-menu>
|
></step-flow-menu>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
|
@ -294,7 +397,11 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.navigateToResult=${this._params
|
.navigateToResult=${this._params
|
||||||
.navigateToResult ?? false}
|
.navigateToResult ?? false}
|
||||||
.increasePaddingEnd=${showDocumentationLink}
|
.devices=${this._devices(
|
||||||
|
this._params.flowConfig.showDevices,
|
||||||
|
Object.values(this.hass.devices),
|
||||||
|
this._step.result?.entry_id
|
||||||
|
)}
|
||||||
></step-flow-create-entry>
|
></step-flow-create-entry>
|
||||||
`}
|
`}
|
||||||
`}
|
`}
|
||||||
|
@ -384,16 +491,14 @@ class DataEntryFlowDialog extends LitElement {
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
--dialog-content-padding: 0;
|
--dialog-content-padding: 0;
|
||||||
}
|
}
|
||||||
.dialog-actions {
|
.dialog-title {
|
||||||
padding: 16px;
|
overflow: hidden;
|
||||||
position: absolute;
|
text-overflow: ellipsis;
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
inset-inline-start: initial;
|
|
||||||
inset-inline-end: 0px;
|
|
||||||
direction: var(--direction);
|
|
||||||
}
|
}
|
||||||
.dialog-actions > * {
|
.dialog-title.form {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
.help {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
|
|
@ -31,10 +31,12 @@ export interface FlowConfig {
|
||||||
|
|
||||||
deleteFlow(hass: HomeAssistant, flowId: string): Promise<unknown>;
|
deleteFlow(hass: HomeAssistant, flowId: string): Promise<unknown>;
|
||||||
|
|
||||||
renderAbortHeader?(
|
renderAbortHeader?(hass: HomeAssistant, step: DataEntryFlowStepAbort): string;
|
||||||
|
|
||||||
|
renderAbortSubheader?(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
step: DataEntryFlowStepAbort
|
step: DataEntryFlowStepAbort
|
||||||
): TemplateResult | string;
|
): string | TemplateResult;
|
||||||
|
|
||||||
renderAbortDescription(
|
renderAbortDescription(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -44,6 +46,11 @@ export interface FlowConfig {
|
||||||
renderShowFormStepHeader(
|
renderShowFormStepHeader(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
step: DataEntryFlowStepForm
|
step: DataEntryFlowStepForm
|
||||||
|
): string;
|
||||||
|
|
||||||
|
renderShowFormStepSubheader?(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
step: DataEntryFlowStepForm
|
||||||
): string | TemplateResult;
|
): string | TemplateResult;
|
||||||
|
|
||||||
renderShowFormStepDescription(
|
renderShowFormStepDescription(
|
||||||
|
@ -100,6 +107,11 @@ export interface FlowConfig {
|
||||||
renderShowFormProgressHeader(
|
renderShowFormProgressHeader(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
step: DataEntryFlowStepProgress
|
step: DataEntryFlowStepProgress
|
||||||
|
): string;
|
||||||
|
|
||||||
|
renderShowFormProgressSubheader?(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
step: DataEntryFlowStepProgress
|
||||||
): string | TemplateResult;
|
): string | TemplateResult;
|
||||||
|
|
||||||
renderShowFormProgressDescription(
|
renderShowFormProgressDescription(
|
||||||
|
@ -107,7 +119,9 @@ export interface FlowConfig {
|
||||||
step: DataEntryFlowStepProgress
|
step: DataEntryFlowStepProgress
|
||||||
): TemplateResult | "";
|
): TemplateResult | "";
|
||||||
|
|
||||||
renderMenuHeader(
|
renderMenuHeader(hass: HomeAssistant, step: DataEntryFlowStepMenu): string;
|
||||||
|
|
||||||
|
renderMenuSubheader?(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
step: DataEntryFlowStepMenu
|
step: DataEntryFlowStepMenu
|
||||||
): string | TemplateResult;
|
): string | TemplateResult;
|
||||||
|
|
|
@ -22,9 +22,6 @@ class StepFlowAbort extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public handler!: string;
|
@property({ attribute: false }) public handler!: string;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
protected firstUpdated(changed: PropertyValues) {
|
protected firstUpdated(changed: PropertyValues) {
|
||||||
super.firstUpdated(changed);
|
super.firstUpdated(changed);
|
||||||
if (this.step.reason === "missing_credentials") {
|
if (this.step.reason === "missing_credentials") {
|
||||||
|
@ -37,11 +34,6 @@ class StepFlowAbort extends LitElement {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${this.params.flowConfig.renderAbortHeader
|
|
||||||
? this.params.flowConfig.renderAbortHeader(this.hass, this.step)
|
|
||||||
: this.hass.localize(`component.${this.domain}.title`)}
|
|
||||||
</h2>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${this.params.flowConfig.renderAbortDescription(this.hass, this.step)}
|
${this.params.flowConfig.renderAbortDescription(this.hass, this.step)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,8 +36,7 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public step!: DataEntryFlowStepCreateEntry;
|
@property({ attribute: false }) public step!: DataEntryFlowStepCreateEntry;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
@property({ attribute: false }) public devices!: DeviceRegistryEntry[];
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
public navigateToResult = false;
|
public navigateToResult = false;
|
||||||
|
|
||||||
|
@ -46,17 +45,6 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
{ name?: string; area?: string }
|
{ name?: string; area?: string }
|
||||||
> = {};
|
> = {};
|
||||||
|
|
||||||
private _devices = memoizeOne(
|
|
||||||
(
|
|
||||||
showDevices: boolean,
|
|
||||||
devices: DeviceRegistryEntry[],
|
|
||||||
entry_id?: string
|
|
||||||
) =>
|
|
||||||
showDevices && entry_id
|
|
||||||
? devices.filter((device) => device.config_entries.includes(entry_id))
|
|
||||||
: []
|
|
||||||
);
|
|
||||||
|
|
||||||
private _deviceEntities = memoizeOne(
|
private _deviceEntities = memoizeOne(
|
||||||
(
|
(
|
||||||
deviceId: string,
|
deviceId: string,
|
||||||
|
@ -75,22 +63,16 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const devices = this._devices(
|
|
||||||
this.flowConfig.showDevices,
|
|
||||||
Object.values(this.hass.devices),
|
|
||||||
this.step.result?.entry_id
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
devices.length !== 1 ||
|
this.devices.length !== 1 ||
|
||||||
devices[0].primary_config_entry !== this.step.result?.entry_id ||
|
this.devices[0].primary_config_entry !== this.step.result?.entry_id ||
|
||||||
this.step.result.domain === "voip"
|
this.step.result.domain === "voip"
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assistSatellites = this._deviceEntities(
|
const assistSatellites = this._deviceEntities(
|
||||||
devices[0].id,
|
this.devices[0].id,
|
||||||
Object.values(this.hass.entities),
|
Object.values(this.hass.entities),
|
||||||
"assist_satellite"
|
"assist_satellite"
|
||||||
);
|
);
|
||||||
|
@ -103,26 +85,14 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
this.navigateToResult = false;
|
this.navigateToResult = false;
|
||||||
this._flowDone();
|
this._flowDone();
|
||||||
showVoiceAssistantSetupDialog(this, {
|
showVoiceAssistantSetupDialog(this, {
|
||||||
deviceId: devices[0].id,
|
deviceId: this.devices[0].id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const localize = this.hass.localize;
|
const localize = this.hass.localize;
|
||||||
const devices = this._devices(
|
|
||||||
this.flowConfig.showDevices,
|
|
||||||
Object.values(this.hass.devices),
|
|
||||||
this.step.result?.entry_id
|
|
||||||
);
|
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${devices.length
|
|
||||||
? localize("ui.panel.config.integrations.config_flow.assign_area", {
|
|
||||||
number: devices.length,
|
|
||||||
})
|
|
||||||
: `${localize("ui.panel.config.integrations.config_flow.success")}!`}
|
|
||||||
</h2>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${this.flowConfig.renderCreateEntryDescription(this.hass, this.step)}
|
${this.flowConfig.renderCreateEntryDescription(this.hass, this.step)}
|
||||||
${this.step.result?.state === "not_loaded"
|
${this.step.result?.state === "not_loaded"
|
||||||
|
@ -132,10 +102,10 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
)}</span
|
)}</span
|
||||||
>`
|
>`
|
||||||
: nothing}
|
: nothing}
|
||||||
${devices.length === 0 &&
|
${this.devices.length === 0 &&
|
||||||
["options_flow", "repair_flow"].includes(this.flowConfig.flowType)
|
["options_flow", "repair_flow"].includes(this.flowConfig.flowType)
|
||||||
? nothing
|
? nothing
|
||||||
: devices.length === 0
|
: this.devices.length === 0
|
||||||
? html`<p>
|
? html`<p>
|
||||||
${localize(
|
${localize(
|
||||||
"ui.panel.config.integrations.config_flow.created_config",
|
"ui.panel.config.integrations.config_flow.created_config",
|
||||||
|
@ -144,7 +114,7 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
</p>`
|
</p>`
|
||||||
: html`
|
: html`
|
||||||
<div class="devices">
|
<div class="devices">
|
||||||
${devices.map(
|
${this.devices.map(
|
||||||
(device) => html`
|
(device) => html`
|
||||||
<div class="device">
|
<div class="device">
|
||||||
<div class="device-info">
|
<div class="device-info">
|
||||||
|
@ -203,7 +173,7 @@ class StepFlowCreateEntry extends LitElement {
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<mwc-button @click=${this._flowDone}
|
<mwc-button @click=${this._flowDone}
|
||||||
>${localize(
|
>${localize(
|
||||||
`ui.panel.config.integrations.config_flow.${!devices.length || Object.keys(this._deviceUpdate).length ? "finish" : "finish_skip"}`
|
`ui.panel.config.integrations.config_flow.${!this.devices.length || Object.keys(this._deviceUpdate).length ? "finish" : "finish_skip"}`
|
||||||
)}</mwc-button
|
)}</mwc-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,16 +15,10 @@ class StepFlowExternal extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public step!: DataEntryFlowStepExternal;
|
@property({ attribute: false }) public step!: DataEntryFlowStepExternal;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const localize = this.hass.localize;
|
const localize = this.hass.localize;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${this.flowConfig.renderExternalStepHeader(this.hass, this.step)}
|
|
||||||
</h2>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${this.flowConfig.renderExternalStepDescription(this.hass, this.step)}
|
${this.flowConfig.renderExternalStepDescription(this.hass, this.step)}
|
||||||
<div class="open-button">
|
<div class="open-button">
|
||||||
|
@ -56,9 +50,6 @@ class StepFlowExternal extends LitElement {
|
||||||
.open-button a {
|
.open-button a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
h2.end-space {
|
|
||||||
padding-inline-end: 72px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,18 @@ import { dynamicElement } from "../../common/dom/dynamic-element-directive";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { isNavigationClick } from "../../common/dom/is-navigation-click";
|
import { isNavigationClick } from "../../common/dom/is-navigation-click";
|
||||||
import "../../components/ha-alert";
|
import "../../components/ha-alert";
|
||||||
import "../../components/ha-spinner";
|
|
||||||
import { computeInitialHaFormData } from "../../components/ha-form/compute-initial-ha-form-data";
|
import { computeInitialHaFormData } from "../../components/ha-form/compute-initial-ha-form-data";
|
||||||
import "../../components/ha-form/ha-form";
|
import "../../components/ha-form/ha-form";
|
||||||
import type { HaFormSchema } from "../../components/ha-form/types";
|
import type { HaFormSchema } from "../../components/ha-form/types";
|
||||||
import "../../components/ha-markdown";
|
import "../../components/ha-markdown";
|
||||||
|
import "../../components/ha-spinner";
|
||||||
import { autocompleteLoginFields } from "../../data/auth";
|
import { autocompleteLoginFields } from "../../data/auth";
|
||||||
import type { DataEntryFlowStepForm } from "../../data/data_entry_flow";
|
import type { DataEntryFlowStepForm } from "../../data/data_entry_flow";
|
||||||
|
import { previewModule } from "../../data/preview";
|
||||||
|
import { haStyle } from "../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
||||||
import { configFlowContentStyles } from "./styles";
|
import { configFlowContentStyles } from "./styles";
|
||||||
import { haStyle } from "../../resources/styles";
|
|
||||||
import { previewModule } from "../../data/preview";
|
|
||||||
|
|
||||||
@customElement("step-flow-form")
|
@customElement("step-flow-form")
|
||||||
class StepFlowForm extends LitElement {
|
class StepFlowForm extends LitElement {
|
||||||
|
@ -27,9 +27,6 @@ class StepFlowForm extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
@state() private _loading = false;
|
@state() private _loading = false;
|
||||||
|
|
||||||
@state() private _stepData?: Record<string, any>;
|
@state() private _stepData?: Record<string, any>;
|
||||||
|
@ -46,9 +43,6 @@ class StepFlowForm extends LitElement {
|
||||||
const stepData = this._stepDataProcessed;
|
const stepData = this._stepDataProcessed;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${this.flowConfig.renderShowFormStepHeader(this.hass, this.step)}
|
|
||||||
</h2>
|
|
||||||
<div class="content" @click=${this._clickHandler}>
|
<div class="content" @click=${this._clickHandler}>
|
||||||
${this.flowConfig.renderShowFormStepDescription(this.hass, this.step)}
|
${this.flowConfig.renderShowFormStepDescription(this.hass, this.step)}
|
||||||
${this._errorMsg
|
${this._errorMsg
|
||||||
|
@ -281,9 +275,6 @@ class StepFlowForm extends LitElement {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
h2 {
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ class StepFlowMenu extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public step!: DataEntryFlowStepMenu;
|
@property({ attribute: false }) public step!: DataEntryFlowStepMenu;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
let options: string[];
|
let options: string[];
|
||||||
let translations: Record<string, string>;
|
let translations: Record<string, string>;
|
||||||
|
@ -45,9 +42,6 @@ class StepFlowMenu extends LitElement {
|
||||||
);
|
);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${this.flowConfig.renderMenuHeader(this.hass, this.step)}
|
|
||||||
</h2>
|
|
||||||
${description ? html`<div class="content">${description}</div>` : ""}
|
${description ? html`<div class="content">${description}</div>` : ""}
|
||||||
<div class="options">
|
<div class="options">
|
||||||
${options.map(
|
${options.map(
|
||||||
|
|
|
@ -2,13 +2,13 @@ import "@material/mwc-button";
|
||||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { blankBeforePercent } from "../../common/translations/blank_before_percent";
|
||||||
import "../../components/ha-progress-ring";
|
import "../../components/ha-progress-ring";
|
||||||
import "../../components/ha-spinner";
|
import "../../components/ha-spinner";
|
||||||
import type { DataEntryFlowStepProgress } from "../../data/data_entry_flow";
|
import type { DataEntryFlowStepProgress } from "../../data/data_entry_flow";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
||||||
import { configFlowContentStyles } from "./styles";
|
import { configFlowContentStyles } from "./styles";
|
||||||
import { blankBeforePercent } from "../../common/translations/blank_before_percent";
|
|
||||||
|
|
||||||
@customElement("step-flow-progress")
|
@customElement("step-flow-progress")
|
||||||
class StepFlowProgress extends LitElement {
|
class StepFlowProgress extends LitElement {
|
||||||
|
@ -24,14 +24,8 @@ class StepFlowProgress extends LitElement {
|
||||||
@property({ type: Number })
|
@property({ type: Number })
|
||||||
public progress?: number;
|
public progress?: number;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "increase-padding-end" })
|
|
||||||
public increasePaddingEnd = false;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<h2 class=${this.increasePaddingEnd ? "end-space" : ""}>
|
|
||||||
${this.flowConfig.renderShowFormProgressHeader(this.hass, this.step)}
|
|
||||||
</h2>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${this.progress
|
${this.progress
|
||||||
? html`
|
? html`
|
||||||
|
|
|
@ -25,9 +25,6 @@ export const configFlowContentStyles = css`
|
||||||
text-transform: var(--mdc-typography-headline6-text-transform, inherit);
|
text-transform: var(--mdc-typography-headline6-text-transform, inherit);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
h2.end-space {
|
|
||||||
padding-inline-end: 72px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content,
|
.content,
|
||||||
.preview {
|
.preview {
|
||||||
|
|
|
@ -9,50 +9,50 @@ import {
|
||||||
mdiReload,
|
mdiReload,
|
||||||
mdiServerNetwork,
|
mdiServerNetwork,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
|
import Fuse from "fuse.js";
|
||||||
import type { TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { ifDefined } from "lit/directives/if-defined";
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import Fuse from "fuse.js";
|
|
||||||
import { canShowPage } from "../../common/config/can_show_page";
|
import { canShowPage } from "../../common/config/can_show_page";
|
||||||
import { componentsWithService } from "../../common/config/components_with_service";
|
import { componentsWithService } from "../../common/config/components_with_service";
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { computeAreaName } from "../../common/entity/compute_area_name";
|
||||||
import {
|
import {
|
||||||
computeDeviceName,
|
computeDeviceName,
|
||||||
computeDeviceNameDisplay,
|
computeDeviceNameDisplay,
|
||||||
} from "../../common/entity/compute_device_name";
|
} from "../../common/entity/compute_device_name";
|
||||||
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
|
import { computeEntityName } from "../../common/entity/compute_entity_name";
|
||||||
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { getEntityContext } from "../../common/entity/context/get_entity_context";
|
||||||
import { navigate } from "../../common/navigate";
|
import { navigate } from "../../common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
|
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
|
||||||
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
import { debounce } from "../../common/util/debounce";
|
import { debounce } from "../../common/util/debounce";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
import "../../components/ha-label";
|
import "../../components/ha-label";
|
||||||
import "../../components/ha-list";
|
import "../../components/ha-list";
|
||||||
|
import "../../components/ha-md-list-item";
|
||||||
import "../../components/ha-spinner";
|
import "../../components/ha-spinner";
|
||||||
import "../../components/ha-textfield";
|
import "../../components/ha-textfield";
|
||||||
import "../../components/ha-tip";
|
import "../../components/ha-tip";
|
||||||
import "../../components/ha-md-list-item";
|
|
||||||
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
|
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
|
||||||
import { domainToName } from "../../data/integration";
|
import { domainToName } from "../../data/integration";
|
||||||
import { getPanelNameTranslationKey } from "../../data/panel";
|
import { getPanelNameTranslationKey } from "../../data/panel";
|
||||||
import type { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
import type { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||||
import { configSections } from "../../panels/config/ha-panel-config";
|
import { configSections } from "../../panels/config/ha-panel-config";
|
||||||
|
import { HaFuse } from "../../resources/fuse";
|
||||||
import { haStyleDialog, haStyleScrollbar } from "../../resources/styles";
|
import { haStyleDialog, haStyleScrollbar } from "../../resources/styles";
|
||||||
import { loadVirtualizer } from "../../resources/virtualizer";
|
import { loadVirtualizer } from "../../resources/virtualizer";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { showConfirmationDialog } from "../generic/show-dialog-box";
|
import { showConfirmationDialog } from "../generic/show-dialog-box";
|
||||||
import { showShortcutsDialog } from "../shortcuts/show-shortcuts-dialog";
|
import { showShortcutsDialog } from "../shortcuts/show-shortcuts-dialog";
|
||||||
import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar";
|
import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar";
|
||||||
import { getEntityContext } from "../../common/entity/context/get_entity_context";
|
|
||||||
import { computeEntityName } from "../../common/entity/compute_entity_name";
|
|
||||||
import { computeAreaName } from "../../common/entity/compute_area_name";
|
|
||||||
import { computeRTL } from "../../common/util/compute_rtl";
|
|
||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
|
||||||
import { HaFuse } from "../../resources/fuse";
|
|
||||||
|
|
||||||
interface QuickBarItem extends ScorableTextItem {
|
interface QuickBarItem extends ScorableTextItem {
|
||||||
primaryText: string;
|
primaryText: string;
|
||||||
|
@ -152,11 +152,6 @@ export class QuickBar extends LitElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProps) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
this.hass.loadBackendTranslation("title");
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getItems = memoizeOne(
|
private _getItems = memoizeOne(
|
||||||
(
|
(
|
||||||
mode: QuickBarMode,
|
mode: QuickBarMode,
|
||||||
|
@ -304,7 +299,8 @@ export class QuickBar extends LitElement {
|
||||||
} else if (this._mode === QuickBarMode.Device) {
|
} else if (this._mode === QuickBarMode.Device) {
|
||||||
this._deviceItems = this._deviceItems || this._generateDeviceItems();
|
this._deviceItems = this._deviceItems || this._generateDeviceItems();
|
||||||
} else {
|
} else {
|
||||||
this._entityItems = this._entityItems || this._generateEntityItems();
|
this._entityItems =
|
||||||
|
this._entityItems || (await this._generateEntityItems());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,9 +577,11 @@ export class QuickBar extends LitElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _generateEntityItems(): EntityItem[] {
|
private async _generateEntityItems(): Promise<EntityItem[]> {
|
||||||
const isRTL = computeRTL(this.hass);
|
const isRTL = computeRTL(this.hass);
|
||||||
|
|
||||||
|
await this.hass.loadBackendTranslation("title");
|
||||||
|
|
||||||
return Object.keys(this.hass.states)
|
return Object.keys(this.hass.states)
|
||||||
.map((entityId) => {
|
.map((entityId) => {
|
||||||
const stateObj = this.hass.states[entityId];
|
const stateObj = this.hass.states[entityId];
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import type { ReactiveElement } from "lit";
|
||||||
|
import type { Constructor } from "../types";
|
||||||
|
|
||||||
|
export const WakeLockMixin = <T extends Constructor<ReactiveElement>>(
|
||||||
|
superClass: T
|
||||||
|
) =>
|
||||||
|
class WakeLockClass extends superClass {
|
||||||
|
private _wakeLock?: Promise<WakeLockSentinel>;
|
||||||
|
|
||||||
|
public connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if ("wakeLock" in navigator) {
|
||||||
|
this._wakeLock = navigator.wakeLock.request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._wakeLock?.then((wakeLock) => wakeLock.release());
|
||||||
|
}
|
||||||
|
};
|
|
@ -107,6 +107,8 @@ export interface DeviceAlert {
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEVICE_ALERTS_INTERVAL = 30000;
|
||||||
|
|
||||||
@customElement("ha-config-device-page")
|
@customElement("ha-config-device-page")
|
||||||
export class HaConfigDevicePage extends LitElement {
|
export class HaConfigDevicePage extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
@ -134,6 +136,8 @@ export class HaConfigDevicePage extends LitElement {
|
||||||
|
|
||||||
@state() private _deviceAlerts?: DeviceAlert[];
|
@state() private _deviceAlerts?: DeviceAlert[];
|
||||||
|
|
||||||
|
private _deviceAlertsTimeout?: number;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||||
_entityReg!: EntityRegistryEntry[];
|
_entityReg!: EntityRegistryEntry[];
|
||||||
|
@ -280,6 +284,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||||
this._getDiagnosticButtons(this._diagnosticDownloadLinks);
|
this._getDiagnosticButtons(this._diagnosticDownloadLinks);
|
||||||
this._getDeleteActions();
|
this._getDeleteActions();
|
||||||
this._getDeviceActions();
|
this._getDeviceActions();
|
||||||
|
clearTimeout(this._deviceAlertsTimeout);
|
||||||
this._getDeviceAlerts();
|
this._getDeviceAlerts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +300,11 @@ export class HaConfigDevicePage extends LitElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
clearTimeout(this._deviceAlertsTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this.deviceId) {
|
if (!this.hass || !this.deviceId) {
|
||||||
return nothing;
|
return nothing;
|
||||||
|
@ -1153,6 +1163,10 @@ export class HaConfigDevicePage extends LitElement {
|
||||||
|
|
||||||
if (deviceAlerts.length) {
|
if (deviceAlerts.length) {
|
||||||
this._deviceAlerts = deviceAlerts;
|
this._deviceAlerts = deviceAlerts;
|
||||||
|
this._deviceAlertsTimeout = window.setTimeout(
|
||||||
|
() => this._getDeviceAlerts(),
|
||||||
|
DEVICE_ALERTS_INTERVAL
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,11 @@ import {
|
||||||
mdiNetwork,
|
mdiNetwork,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
mdiPencil,
|
mdiPencil,
|
||||||
|
mdiCheckCircle,
|
||||||
|
mdiAlertCircle,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import type { ConfigEntry } from "../../../../../data/config_entries";
|
import type { ConfigEntry } from "../../../../../data/config_entries";
|
||||||
import { getConfigEntries } from "../../../../../data/config_entries";
|
import { getConfigEntries } from "../../../../../data/config_entries";
|
||||||
|
@ -25,6 +27,8 @@ import "../../../ha-config-section";
|
||||||
import "../../../../../components/ha-form/ha-form";
|
import "../../../../../components/ha-form/ha-form";
|
||||||
import "../../../../../components/buttons/ha-progress-button";
|
import "../../../../../components/buttons/ha-progress-button";
|
||||||
import "../../../../../components/ha-settings-row";
|
import "../../../../../components/ha-settings-row";
|
||||||
|
import "../../../../../components/ha-svg-icon";
|
||||||
|
import "../../../../../components/ha-alert";
|
||||||
import { showZHAChangeChannelDialog } from "./show-dialog-zha-change-channel";
|
import { showZHAChangeChannelDialog } from "./show-dialog-zha-change-channel";
|
||||||
import type {
|
import type {
|
||||||
ZHAConfiguration,
|
ZHAConfiguration,
|
||||||
|
@ -36,6 +40,7 @@ import {
|
||||||
updateZHAConfiguration,
|
updateZHAConfiguration,
|
||||||
fetchZHANetworkSettings,
|
fetchZHANetworkSettings,
|
||||||
createZHANetworkBackup,
|
createZHANetworkBackup,
|
||||||
|
fetchDevices,
|
||||||
} from "../../../../../data/zha";
|
} from "../../../../../data/zha";
|
||||||
import { showAlertDialog } from "../../../../../dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../../../../../dialogs/generic/show-dialog-box";
|
||||||
|
|
||||||
|
@ -75,18 +80,27 @@ class ZHAConfigDashboard extends LitElement {
|
||||||
|
|
||||||
@state() private _networkSettings?: ZHANetworkSettings;
|
@state() private _networkSettings?: ZHANetworkSettings;
|
||||||
|
|
||||||
|
@state() private _totalDevices = 0;
|
||||||
|
|
||||||
|
@state() private _offlineDevices = 0;
|
||||||
|
|
||||||
|
@state() private _error?: string;
|
||||||
|
|
||||||
@state() private _generatingBackup = false;
|
@state() private _generatingBackup = false;
|
||||||
|
|
||||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
protected firstUpdated(changedProperties: PropertyValues) {
|
||||||
super.firstUpdated(changedProperties);
|
super.firstUpdated(changedProperties);
|
||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
this.hass.loadBackendTranslation("config_panel", "zha", false);
|
this.hass.loadBackendTranslation("config_panel", "zha", false);
|
||||||
this._fetchConfiguration();
|
this._fetchConfiguration();
|
||||||
this._fetchSettings();
|
this._fetchSettings();
|
||||||
|
this._fetchDevicesAndUpdateStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
const deviceOnline =
|
||||||
|
this._offlineDevices < this._totalDevices || this._totalDevices === 0;
|
||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
@ -95,11 +109,43 @@ class ZHAConfigDashboard extends LitElement {
|
||||||
.tabs=${zhaTabs}
|
.tabs=${zhaTabs}
|
||||||
back-path="/config/integrations"
|
back-path="/config/integrations"
|
||||||
>
|
>
|
||||||
<ha-card
|
<ha-card class="content network-status">
|
||||||
header=${this.hass.localize(
|
${this._error
|
||||||
"ui.panel.config.zha.configuration_page.shortcuts_title"
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
)}
|
: nothing}
|
||||||
>
|
<div class="card-content">
|
||||||
|
<div class="heading">
|
||||||
|
<div class="icon">
|
||||||
|
<ha-svg-icon
|
||||||
|
.path=${deviceOnline ? mdiCheckCircle : mdiAlertCircle}
|
||||||
|
class=${deviceOnline ? "online" : "offline"}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</div>
|
||||||
|
<div class="details">
|
||||||
|
ZHA
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zha.configuration_page.status_title"
|
||||||
|
)}:
|
||||||
|
${this.hass.localize(
|
||||||
|
`ui.panel.config.zha.configuration_page.status_${deviceOnline ? "online" : "offline"}`
|
||||||
|
)}<br />
|
||||||
|
<small>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zha.configuration_page.devices",
|
||||||
|
{ count: this._totalDevices }
|
||||||
|
)}
|
||||||
|
</small>
|
||||||
|
<small class="offline">
|
||||||
|
${this._offlineDevices > 0
|
||||||
|
? html`(${this.hass.localize(
|
||||||
|
"ui.panel.config.zha.configuration_page.devices_offline",
|
||||||
|
{ count: this._offlineDevices }
|
||||||
|
)})`
|
||||||
|
: nothing}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
${this.configEntryId
|
${this.configEntryId
|
||||||
? html`<div class="card-actions">
|
? html`<div class="card-actions">
|
||||||
<a
|
<a
|
||||||
|
@ -268,6 +314,17 @@ class ZHAConfigDashboard extends LitElement {
|
||||||
this._networkSettings = await fetchZHANetworkSettings(this.hass!);
|
this._networkSettings = await fetchZHANetworkSettings(this.hass!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _fetchDevicesAndUpdateStatus(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const devices = await fetchDevices(this.hass);
|
||||||
|
this._totalDevices = devices.length;
|
||||||
|
this._offlineDevices =
|
||||||
|
this._totalDevices - devices.filter((d) => d.available).length;
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = err.message || err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async _showChannelMigrationDialog(): Promise<void> {
|
private async _showChannelMigrationDialog(): Promise<void> {
|
||||||
if (this._networkSettings!.device.path === MULTIPROTOCOL_ADDON_URL) {
|
if (this._networkSettings!.device.path === MULTIPROTOCOL_ADDON_URL) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
|
@ -388,6 +445,43 @@ class ZHAConfigDashboard extends LitElement {
|
||||||
margin-top: -16px;
|
margin-top: -16px;
|
||||||
margin-bottom: -16px;
|
margin-bottom: -16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status div.heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status div.heading .icon {
|
||||||
|
margin-inline-end: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status div.heading ha-svg-icon {
|
||||||
|
--mdc-icon-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status div.heading .details {
|
||||||
|
font-size: var(--ha-font-size-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status small {
|
||||||
|
font-size: var(--ha-font-size-m);
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status small.offline {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status .online {
|
||||||
|
color: var(--state-on-color, var(--success-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-status .offline {
|
||||||
|
color: var(--error-color, var(--error-color));
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ import "../../../../../../components/ha-dialog-header";
|
||||||
import "../../../../../../components/ha-fade-in";
|
import "../../../../../../components/ha-fade-in";
|
||||||
import "../../../../../../components/ha-icon-button";
|
import "../../../../../../components/ha-icon-button";
|
||||||
import "../../../../../../components/ha-qr-scanner";
|
import "../../../../../../components/ha-qr-scanner";
|
||||||
import "../../../../../../components/ha-spinner";
|
|
||||||
|
|
||||||
import { computeStateName } from "../../../../../../common/entity/compute_state_name";
|
import { computeStateName } from "../../../../../../common/entity/compute_state_name";
|
||||||
import { navigate } from "../../../../../../common/navigate";
|
import { navigate } from "../../../../../../common/navigate";
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { css, html, LitElement, nothing } from "lit";
|
||||||
|
|
||||||
import "../../../../../../components/ha-fade-in";
|
import "../../../../../../components/ha-fade-in";
|
||||||
import "../../../../../../components/ha-spinner";
|
import "../../../../../../components/ha-spinner";
|
||||||
|
import { WakeLockMixin } from "../../../../../../mixins/wakelock-mixin";
|
||||||
|
|
||||||
@customElement("zwave-js-add-node-loading")
|
@customElement("zwave-js-add-node-loading")
|
||||||
export class ZWaveJsAddNodeLoading extends LitElement {
|
export class ZWaveJsAddNodeLoading extends WakeLockMixin(LitElement) {
|
||||||
@property() public description?: string;
|
@property() public description?: string;
|
||||||
|
|
||||||
@property({ type: Number }) public delay = 0;
|
@property({ type: Number }) public delay = 0;
|
||||||
|
|
|
@ -10,9 +10,10 @@ import { InclusionStrategy } from "../../../../../../data/zwave_js";
|
||||||
import "../../../../../../components/ha-spinner";
|
import "../../../../../../components/ha-spinner";
|
||||||
import "../../../../../../components/ha-button";
|
import "../../../../../../components/ha-button";
|
||||||
import "../../../../../../components/ha-alert";
|
import "../../../../../../components/ha-alert";
|
||||||
|
import { WakeLockMixin } from "../../../../../../mixins/wakelock-mixin";
|
||||||
|
|
||||||
@customElement("zwave-js-add-node-searching-devices")
|
@customElement("zwave-js-add-node-searching-devices")
|
||||||
export class ZWaveJsAddNodeSearchingDevices extends LitElement {
|
export class ZWaveJsAddNodeSearchingDevices extends WakeLockMixin(LitElement) {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "smart-start" })
|
@property({ type: Boolean, attribute: "smart-start" })
|
||||||
|
|
|
@ -468,7 +468,7 @@ class ZWaveJSConfigDashboard extends SubscribeMixin(LitElement) {
|
||||||
.value=${this._backupProgress}
|
.value=${this._backupProgress}
|
||||||
></ha-progress-ring>
|
></ha-progress-ring>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.zwave_js.dashboard.nvm_backup.downloading"
|
"ui.panel.config.zwave_js.dashboard.nvm_backup.creating"
|
||||||
)}
|
)}
|
||||||
${this._backupProgress}%`
|
${this._backupProgress}%`
|
||||||
: this._restoreProgress !== undefined
|
: this._restoreProgress !== undefined
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { html, nothing } from "lit";
|
import { html, nothing } from "lit";
|
||||||
import type { DataEntryFlowStep } from "../../../data/data_entry_flow";
|
import type { DataEntryFlowStep } from "../../../data/data_entry_flow";
|
||||||
import { domainToName } from "../../../data/integration";
|
import { domainToName } from "../../../data/integration";
|
||||||
import "./dialog-repairs-issue-subtitle";
|
|
||||||
import type { RepairsIssue } from "../../../data/repairs";
|
import type { RepairsIssue } from "../../../data/repairs";
|
||||||
import {
|
import {
|
||||||
createRepairsFlow,
|
createRepairsFlow,
|
||||||
|
@ -14,6 +13,7 @@ import {
|
||||||
showFlowDialog,
|
showFlowDialog,
|
||||||
} from "../../../dialogs/config-flow/show-dialog-data-entry-flow";
|
} from "../../../dialogs/config-flow/show-dialog-data-entry-flow";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import "./dialog-repairs-issue-subtitle";
|
||||||
|
|
||||||
const mergePlaceholders = (issue: RepairsIssue, step: DataEntryFlowStep) =>
|
const mergePlaceholders = (issue: RepairsIssue, step: DataEntryFlowStep) =>
|
||||||
step.description_placeholders && issue.translation_placeholders
|
step.description_placeholders && issue.translation_placeholders
|
||||||
|
@ -68,8 +68,11 @@ export const showRepairsFlowDialog = (
|
||||||
deleteFlow: deleteRepairsFlow,
|
deleteFlow: deleteRepairsFlow,
|
||||||
|
|
||||||
renderAbortHeader(hass) {
|
renderAbortHeader(hass) {
|
||||||
|
return hass.localize("ui.dialogs.repair_flow.form.header");
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAbortSubheader(hass) {
|
||||||
return html`
|
return html`
|
||||||
${hass.localize("ui.dialogs.repair_flow.form.header")}
|
|
||||||
<dialog-repairs-issue-subtitle
|
<dialog-repairs-issue-subtitle
|
||||||
.hass=${hass}
|
.hass=${hass}
|
||||||
.issue=${issue}
|
.issue=${issue}
|
||||||
|
@ -98,13 +101,18 @@ export const showRepairsFlowDialog = (
|
||||||
},
|
},
|
||||||
|
|
||||||
renderShowFormStepHeader(hass, step) {
|
renderShowFormStepHeader(hass, step) {
|
||||||
return html`
|
return (
|
||||||
${hass.localize(
|
hass.localize(
|
||||||
`component.${issue.domain}.issues.${
|
`component.${issue.domain}.issues.${
|
||||||
issue.translation_key || issue.issue_id
|
issue.translation_key || issue.issue_id
|
||||||
}.fix_flow.step.${step.step_id}.title`,
|
}.fix_flow.step.${step.step_id}.title`,
|
||||||
mergePlaceholders(issue, step)
|
mergePlaceholders(issue, step)
|
||||||
) || hass.localize("ui.dialogs.repair_flow.form.header")}
|
) || hass.localize("ui.dialogs.repair_flow.form.header")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderShowFormStepSubheader(hass) {
|
||||||
|
return html`
|
||||||
<dialog-repairs-issue-subtitle
|
<dialog-repairs-issue-subtitle
|
||||||
.hass=${hass}
|
.hass=${hass}
|
||||||
.issue=${issue}
|
.issue=${issue}
|
||||||
|
@ -196,13 +204,18 @@ export const showRepairsFlowDialog = (
|
||||||
},
|
},
|
||||||
|
|
||||||
renderShowFormProgressHeader(hass, step) {
|
renderShowFormProgressHeader(hass, step) {
|
||||||
return html`
|
return (
|
||||||
${hass.localize(
|
hass.localize(
|
||||||
`component.${issue.domain}.issues.step.${
|
`component.${issue.domain}.issues.step.${
|
||||||
issue.translation_key || issue.issue_id
|
issue.translation_key || issue.issue_id
|
||||||
}.fix_flow.${step.step_id}.title`,
|
}.fix_flow.${step.step_id}.title`,
|
||||||
mergePlaceholders(issue, step)
|
mergePlaceholders(issue, step)
|
||||||
) || hass.localize(`component.${issue.domain}.title`)}
|
) || hass.localize(`component.${issue.domain}.title`)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderShowFormProgressSubheader(hass) {
|
||||||
|
return html`
|
||||||
<dialog-repairs-issue-subtitle
|
<dialog-repairs-issue-subtitle
|
||||||
.hass=${hass}
|
.hass=${hass}
|
||||||
.issue=${issue}
|
.issue=${issue}
|
||||||
|
@ -229,13 +242,18 @@ export const showRepairsFlowDialog = (
|
||||||
},
|
},
|
||||||
|
|
||||||
renderMenuHeader(hass, step) {
|
renderMenuHeader(hass, step) {
|
||||||
return html`
|
return (
|
||||||
${hass.localize(
|
hass.localize(
|
||||||
`component.${issue.domain}.issues.${
|
`component.${issue.domain}.issues.${
|
||||||
issue.translation_key || issue.issue_id
|
issue.translation_key || issue.issue_id
|
||||||
}.fix_flow.step.${step.step_id}.title`,
|
}.fix_flow.step.${step.step_id}.title`,
|
||||||
mergePlaceholders(issue, step)
|
mergePlaceholders(issue, step)
|
||||||
) || hass.localize(`component.${issue.domain}.title`)}
|
) || hass.localize(`component.${issue.domain}.title`)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderMenuSubheader(hass) {
|
||||||
|
return html`
|
||||||
<dialog-repairs-issue-subtitle
|
<dialog-repairs-issue-subtitle
|
||||||
.hass=${hass}
|
.hass=${hass}
|
||||||
.issue=${issue}
|
.issue=${issue}
|
||||||
|
|
|
@ -139,6 +139,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||||
? processConfigEntities<MapEntityConfig>(this._config.entities)
|
? processConfigEntities<MapEntityConfig>(this._config.entities)
|
||||||
: [];
|
: [];
|
||||||
this._mapEntities = this._getMapEntities();
|
this._mapEntities = this._getMapEntities();
|
||||||
|
this._clusterMarkers = this._config.cluster ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
|
@ -215,17 +216,21 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||||
render-passive
|
render-passive
|
||||||
></ha-map>
|
></ha-map>
|
||||||
<div id="buttons">
|
<div id="buttons">
|
||||||
<ha-icon-button
|
${this._mapEntities.length > 1
|
||||||
.label=${this.hass!.localize(
|
? html`
|
||||||
"ui.panel.lovelace.cards.map.toggle_grouping"
|
<ha-icon-button
|
||||||
)}
|
.label=${this.hass!.localize(
|
||||||
.path=${this._clusterMarkers
|
"ui.panel.lovelace.cards.map.toggle_grouping"
|
||||||
? mdiGoogleCirclesCommunities
|
)}
|
||||||
: mdiDotsHexagon}
|
.path=${this._clusterMarkers
|
||||||
style=${isDarkMode ? "color:#ffffff" : "color:#000000"}
|
? mdiGoogleCirclesCommunities
|
||||||
@click=${this._toggleClusterMarkers}
|
: mdiDotsHexagon}
|
||||||
tabindex="0"
|
style=${isDarkMode ? "color:#ffffff" : "color:#000000"}
|
||||||
></ha-icon-button>
|
@click=${this._toggleClusterMarkers}
|
||||||
|
tabindex="0"
|
||||||
|
></ha-icon-button>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.label=${this.hass!.localize(
|
.label=${this.hass!.localize(
|
||||||
"ui.panel.lovelace.cards.map.reset_focus"
|
"ui.panel.lovelace.cards.map.reset_focus"
|
||||||
|
|
|
@ -337,6 +337,7 @@ export interface MapCardConfig extends LovelaceCardConfig {
|
||||||
geo_location_sources?: (GeoLocationSourceConfig | string)[];
|
geo_location_sources?: (GeoLocationSourceConfig | string)[];
|
||||||
dark_mode?: boolean;
|
dark_mode?: boolean;
|
||||||
theme_mode?: ThemeMode;
|
theme_mode?: ThemeMode;
|
||||||
|
cluster?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarkdownCardConfig extends LovelaceCardConfig {
|
export interface MarkdownCardConfig extends LovelaceCardConfig {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import type { TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import "../../components/ha-alert";
|
||||||
import "../../components/ha-card";
|
import "../../components/ha-card";
|
||||||
import "../../components/ha-settings-row";
|
import "../../components/ha-settings-row";
|
||||||
import "../../components/ha-switch";
|
import "../../components/ha-switch";
|
||||||
import type { CoreFrontendUserData } from "../../data/frontend";
|
import type { CoreFrontendUserData } from "../../data/frontend";
|
||||||
import { getOptimisticFrontendUserDataCollection } from "../../data/frontend";
|
import { saveFrontendUserData } from "../../data/frontend";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
@customElement("ha-advanced-mode-row")
|
@customElement("ha-advanced-mode-row")
|
||||||
|
@ -16,8 +17,13 @@ class AdvancedModeRow extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public coreUserData?: CoreFrontendUserData;
|
@property({ attribute: false }) public coreUserData?: CoreFrontendUserData;
|
||||||
|
|
||||||
|
@state() private _error?: string;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: nothing}
|
||||||
<ha-settings-row .narrow=${this.narrow}>
|
<ha-settings-row .narrow=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.hass.localize("ui.panel.profile.advanced_mode.title")}
|
${this.hass.localize("ui.panel.profile.advanced_mode.title")}
|
||||||
|
@ -41,16 +47,24 @@ class AdvancedModeRow extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _advancedToggled(ev) {
|
private async _advancedToggled(ev) {
|
||||||
getOptimisticFrontendUserDataCollection(this.hass.connection, "core").save({
|
try {
|
||||||
...this.coreUserData,
|
saveFrontendUserData(this.hass.connection, "core", {
|
||||||
showAdvanced: ev.currentTarget.checked,
|
...this.coreUserData,
|
||||||
});
|
showAdvanced: ev.currentTarget.checked,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = err.message || err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
a {
|
a {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
ha-alert {
|
||||||
|
margin: 0 16px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import type { TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import "../../components/ha-alert";
|
||||||
import "../../components/ha-card";
|
import "../../components/ha-card";
|
||||||
import "../../components/ha-settings-row";
|
import "../../components/ha-settings-row";
|
||||||
import "../../components/ha-switch";
|
import "../../components/ha-switch";
|
||||||
import type { CoreFrontendUserData } from "../../data/frontend";
|
import type { CoreFrontendUserData } from "../../data/frontend";
|
||||||
import { getOptimisticFrontendUserDataCollection } from "../../data/frontend";
|
import { saveFrontendUserData } from "../../data/frontend";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
@customElement("ha-entity-id-picker-row")
|
@customElement("ha-entity-id-picker-row")
|
||||||
|
@ -16,8 +17,13 @@ class EntityIdPickerRow extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public coreUserData?: CoreFrontendUserData;
|
@property({ attribute: false }) public coreUserData?: CoreFrontendUserData;
|
||||||
|
|
||||||
|
@state() private _error?: string;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: nothing}
|
||||||
<ha-settings-row .narrow=${this.narrow}>
|
<ha-settings-row .narrow=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.hass.localize("ui.panel.profile.entity_id_picker.title")}</span
|
${this.hass.localize("ui.panel.profile.entity_id_picker.title")}</span
|
||||||
|
@ -35,16 +41,24 @@ class EntityIdPickerRow extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _toggled(ev) {
|
private async _toggled(ev) {
|
||||||
getOptimisticFrontendUserDataCollection(this.hass.connection, "core").save({
|
try {
|
||||||
...this.coreUserData,
|
saveFrontendUserData(this.hass.connection, "core", {
|
||||||
showEntityIdPicker: ev.currentTarget.checked,
|
...this.coreUserData,
|
||||||
});
|
showEntityIdPicker: ev.currentTarget.checked,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = err.message || err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
a {
|
a {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
ha-alert {
|
||||||
|
margin: 0 16px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,32 +4,32 @@ import type { CSSResultGroup, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { nextRender } from "../../common/util/render-status";
|
||||||
import "../../components/ha-card";
|
import "../../components/ha-card";
|
||||||
import "../../layouts/hass-tabs-subpage";
|
|
||||||
import { profileSections } from "./ha-panel-profile";
|
|
||||||
import { isExternal } from "../../data/external";
|
import { isExternal } from "../../data/external";
|
||||||
import type { CoreFrontendUserData } from "../../data/frontend";
|
import type { CoreFrontendUserData } from "../../data/frontend";
|
||||||
import { getOptimisticFrontendUserDataCollection } from "../../data/frontend";
|
import { subscribeFrontendUserData } from "../../data/frontend";
|
||||||
import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
|
||||||
import { isMobileClient } from "../../util/is_mobile";
|
import "../../layouts/hass-tabs-subpage";
|
||||||
import { haStyle } from "../../resources/styles";
|
import { haStyle } from "../../resources/styles";
|
||||||
import type { HomeAssistant, Route } from "../../types";
|
import type { HomeAssistant, Route } from "../../types";
|
||||||
|
import { isMobileClient } from "../../util/is_mobile";
|
||||||
import "./ha-advanced-mode-row";
|
import "./ha-advanced-mode-row";
|
||||||
import "./ha-enable-shortcuts-row";
|
import "./ha-enable-shortcuts-row";
|
||||||
import "./ha-entity-id-picker-row";
|
import "./ha-entity-id-picker-row";
|
||||||
import "./ha-force-narrow-row";
|
import "./ha-force-narrow-row";
|
||||||
|
import { profileSections } from "./ha-panel-profile";
|
||||||
import "./ha-pick-dashboard-row";
|
import "./ha-pick-dashboard-row";
|
||||||
|
import "./ha-pick-date-format-row";
|
||||||
import "./ha-pick-first-weekday-row";
|
import "./ha-pick-first-weekday-row";
|
||||||
import "./ha-pick-language-row";
|
import "./ha-pick-language-row";
|
||||||
import "./ha-pick-number-format-row";
|
import "./ha-pick-number-format-row";
|
||||||
import "./ha-pick-theme-row";
|
import "./ha-pick-theme-row";
|
||||||
import "./ha-pick-time-format-row";
|
import "./ha-pick-time-format-row";
|
||||||
import "./ha-pick-date-format-row";
|
|
||||||
import "./ha-pick-time-zone-row";
|
import "./ha-pick-time-zone-row";
|
||||||
import "./ha-push-notifications-row";
|
import "./ha-push-notifications-row";
|
||||||
import "./ha-set-suspend-row";
|
import "./ha-set-suspend-row";
|
||||||
import "./ha-set-vibrate-row";
|
import "./ha-set-vibrate-row";
|
||||||
import { nextRender } from "../../common/util/render-status";
|
|
||||||
|
|
||||||
@customElement("ha-profile-section-general")
|
@customElement("ha-profile-section-general")
|
||||||
class HaProfileSectionGeneral extends LitElement {
|
class HaProfileSectionGeneral extends LitElement {
|
||||||
|
@ -41,15 +41,16 @@ class HaProfileSectionGeneral extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
private _unsubCoreData?: UnsubscribeFunc;
|
private _unsubCoreData?: Promise<UnsubscribeFunc>;
|
||||||
|
|
||||||
private _getCoreData() {
|
private _getCoreData() {
|
||||||
this._unsubCoreData = getOptimisticFrontendUserDataCollection(
|
this._unsubCoreData = subscribeFrontendUserData(
|
||||||
this.hass.connection,
|
this.hass.connection,
|
||||||
"core"
|
"core",
|
||||||
).subscribe((coreUserData) => {
|
({ value }) => {
|
||||||
this._coreUserData = coreUserData;
|
this._coreUserData = value;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
|
@ -70,7 +71,7 @@ class HaProfileSectionGeneral extends LitElement {
|
||||||
public disconnectedCallback() {
|
public disconnectedCallback() {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
if (this._unsubCoreData) {
|
if (this._unsubCoreData) {
|
||||||
this._unsubCoreData();
|
this._unsubCoreData.then((unsub) => unsub());
|
||||||
this._unsubCoreData = undefined;
|
this._unsubCoreData = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
subscribeServices,
|
subscribeServices,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { promiseTimeout } from "../common/util/promise-timeout";
|
||||||
import { subscribeAreaRegistry } from "../data/area_registry";
|
import { subscribeAreaRegistry } from "../data/area_registry";
|
||||||
import { broadcastConnectionStatus } from "../data/connection-status";
|
import { broadcastConnectionStatus } from "../data/connection-status";
|
||||||
import { subscribeDeviceRegistry } from "../data/device_registry";
|
import { subscribeDeviceRegistry } from "../data/device_registry";
|
||||||
|
@ -22,6 +23,8 @@ import {
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../data/translation";
|
} from "../data/translation";
|
||||||
|
import { subscribeEntityRegistryDisplay } from "../data/ws-entity_registry_display";
|
||||||
|
import { subscribeFloorRegistry } from "../data/ws-floor_registry";
|
||||||
import { subscribePanels } from "../data/ws-panels";
|
import { subscribePanels } from "../data/ws-panels";
|
||||||
import { translationMetadata } from "../resources/translations-metadata";
|
import { translationMetadata } from "../resources/translations-metadata";
|
||||||
import type { Constructor, HomeAssistant, ServiceCallResponse } from "../types";
|
import type { Constructor, HomeAssistant, ServiceCallResponse } from "../types";
|
||||||
|
@ -30,9 +33,6 @@ import { fetchWithAuth } from "../util/fetch-with-auth";
|
||||||
import { getState } from "../util/ha-pref-storage";
|
import { getState } from "../util/ha-pref-storage";
|
||||||
import hassCallApi, { hassCallApiRaw } from "../util/hass-call-api";
|
import hassCallApi, { hassCallApiRaw } from "../util/hass-call-api";
|
||||||
import type { HassBaseEl } from "./hass-base-mixin";
|
import type { HassBaseEl } from "./hass-base-mixin";
|
||||||
import { promiseTimeout } from "../common/util/promise-timeout";
|
|
||||||
import { subscribeFloorRegistry } from "../data/ws-floor_registry";
|
|
||||||
import { subscribeEntityRegistryDisplay } from "../data/ws-entity_registry_display";
|
|
||||||
|
|
||||||
export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
||||||
superClass: T
|
superClass: T
|
||||||
|
@ -280,9 +280,9 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
||||||
subscribeConfig(conn, (config) => this._updateHass({ config }));
|
subscribeConfig(conn, (config) => this._updateHass({ config }));
|
||||||
subscribeServices(conn, (services) => this._updateHass({ services }));
|
subscribeServices(conn, (services) => this._updateHass({ services }));
|
||||||
subscribePanels(conn, (panels) => this._updateHass({ panels }));
|
subscribePanels(conn, (panels) => this._updateHass({ panels }));
|
||||||
subscribeFrontendUserData(conn, "core", (userData) =>
|
subscribeFrontendUserData(conn, "core", ({ value: userData }) => {
|
||||||
this._updateHass({ userData })
|
this._updateHass({ userData });
|
||||||
);
|
});
|
||||||
|
|
||||||
clearInterval(this.__backendPingInterval);
|
clearInterval(this.__backendPingInterval);
|
||||||
this.__backendPingInterval = setInterval(() => {
|
this.__backendPingInterval = setInterval(() => {
|
||||||
|
|
|
@ -8,17 +8,18 @@ import {
|
||||||
} from "../common/util/compute_rtl";
|
} from "../common/util/compute_rtl";
|
||||||
import { debounce } from "../common/util/debounce";
|
import { debounce } from "../common/util/debounce";
|
||||||
import type {
|
import type {
|
||||||
|
DateFormat,
|
||||||
FirstWeekday,
|
FirstWeekday,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
TranslationCategory,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
|
TranslationCategory,
|
||||||
} from "../data/translation";
|
} from "../data/translation";
|
||||||
import {
|
import {
|
||||||
getHassTranslations,
|
getHassTranslations,
|
||||||
getHassTranslationsPre109,
|
getHassTranslationsPre109,
|
||||||
saveTranslationPreferences,
|
saveTranslationPreferences,
|
||||||
|
subscribeTranslationPreferences,
|
||||||
} from "../data/translation";
|
} from "../data/translation";
|
||||||
import { translationMetadata } from "../resources/translations-metadata";
|
import { translationMetadata } from "../resources/translations-metadata";
|
||||||
import type { Constructor, HomeAssistant } from "../types";
|
import type { Constructor, HomeAssistant } from "../types";
|
||||||
|
@ -119,7 +120,10 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||||
|
|
||||||
protected hassConnected() {
|
protected hassConnected() {
|
||||||
super.hassConnected();
|
super.hassConnected();
|
||||||
getUserLocale(this.hass!).then((locale) => {
|
|
||||||
|
subscribeTranslationPreferences(this.hass!, async ({ value }) => {
|
||||||
|
const locale = await getUserLocale(value);
|
||||||
|
|
||||||
if (locale?.language && this.hass!.language !== locale.language) {
|
if (locale?.language && this.hass!.language !== locale.language) {
|
||||||
// We just got language from backend, no need to save back
|
// We just got language from backend, no need to save back
|
||||||
this._selectLanguage(locale.language, false);
|
this._selectLanguage(locale.language, false);
|
||||||
|
|
|
@ -4725,7 +4725,7 @@
|
||||||
"check_your_email": "Check your email for instructions on how to reset your password."
|
"check_your_email": "Check your email for instructions on how to reset your password."
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Register Account",
|
"title": "Register account",
|
||||||
"headline": "Start your free trial",
|
"headline": "Start your free trial",
|
||||||
"information": "Create an account to start your free one month trial with Home Assistant Cloud. No payment information necessary.",
|
"information": "Create an account to start your free one month trial with Home Assistant Cloud. No payment information necessary.",
|
||||||
"information2": "The trial will give you access to all the benefits of Home Assistant Cloud, including:",
|
"information2": "The trial will give you access to all the benefits of Home Assistant Cloud, including:",
|
||||||
|
@ -5340,7 +5340,7 @@
|
||||||
},
|
},
|
||||||
"config_flow": {
|
"config_flow": {
|
||||||
"success": "Success",
|
"success": "Success",
|
||||||
"assign_area": "Assign {number, plural,\n one {device}\n other {devices}\n} to area",
|
"device_created": "{number, plural,\n one {Device}\n other {Devices}\n} created",
|
||||||
"device_name": "Device name",
|
"device_name": "Device name",
|
||||||
"aborted": "Aborted",
|
"aborted": "Aborted",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
@ -5610,7 +5610,11 @@
|
||||||
"value": "Value"
|
"value": "Value"
|
||||||
},
|
},
|
||||||
"configuration_page": {
|
"configuration_page": {
|
||||||
"shortcuts_title": "Shortcuts",
|
"status_title": "status",
|
||||||
|
"status_online": "online",
|
||||||
|
"status_offline": "offline",
|
||||||
|
"devices": "{count} {count, plural,\n one {device}\n other {devices}\n}",
|
||||||
|
"devices_offline": "{count} offline",
|
||||||
"update_button": "Update configuration",
|
"update_button": "Update configuration",
|
||||||
"download_backup": "Download backup",
|
"download_backup": "Download backup",
|
||||||
"migrate_radio": "Migrate radio",
|
"migrate_radio": "Migrate radio",
|
||||||
|
@ -5761,7 +5765,7 @@
|
||||||
"backup_failed": "Failed to download backup",
|
"backup_failed": "Failed to download backup",
|
||||||
"restore_complete": "Backup restored",
|
"restore_complete": "Backup restored",
|
||||||
"restore_failed": "Failed to restore backup",
|
"restore_failed": "Failed to restore backup",
|
||||||
"downloading": "Downloading backup",
|
"creating": "Creating backup",
|
||||||
"restoring": "Restoring backup",
|
"restoring": "Restoring backup",
|
||||||
"migrate": "Migrate controller"
|
"migrate": "Migrate controller"
|
||||||
},
|
},
|
||||||
|
@ -6419,7 +6423,7 @@
|
||||||
"zeroconf_info": "Show services discovered using mDNS. Does not include services unknown to Home Assistant."
|
"zeroconf_info": "Show services discovered using mDNS. Does not include services unknown to Home Assistant."
|
||||||
},
|
},
|
||||||
"network_adapter": "Network adapter",
|
"network_adapter": "Network adapter",
|
||||||
"network_adapter_info": "Configure which network adapters integrations will use. Currently this setting only affects multicast traffic. A restart is required for these settings to apply.",
|
"network_adapter_info": "Configure which network adapters integrations will use. A restart is required for these settings to apply.",
|
||||||
"ip_information": "IP Information",
|
"ip_information": "IP Information",
|
||||||
"adapter": {
|
"adapter": {
|
||||||
"auto_configure": "Auto configure",
|
"auto_configure": "Auto configure",
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import type { FrontendLocaleData } from "../data/translation";
|
import type { FrontendLocaleData } from "../data/translation";
|
||||||
import { fetchTranslationPreferences } from "../data/translation";
|
|
||||||
import { translationMetadata } from "../resources/translations-metadata";
|
import { translationMetadata } from "../resources/translations-metadata";
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
|
|
||||||
const BASE_URL = `${__STATIC_PATH__}translations`;
|
const BASE_URL = `${__STATIC_PATH__}translations`;
|
||||||
const STORAGE = window.localStorage || {};
|
const STORAGE = window.localStorage || {};
|
||||||
|
@ -68,15 +66,14 @@ export function findAvailableLanguage(language: string) {
|
||||||
* Get user selected locale data from backend
|
* Get user selected locale data from backend
|
||||||
*/
|
*/
|
||||||
export async function getUserLocale(
|
export async function getUserLocale(
|
||||||
hass: HomeAssistant
|
data: FrontendLocaleData | null
|
||||||
): Promise<Partial<FrontendLocaleData>> {
|
): Promise<Partial<FrontendLocaleData>> {
|
||||||
const result = await fetchTranslationPreferences(hass);
|
const language = data?.language;
|
||||||
const language = result?.language;
|
const number_format = data?.number_format;
|
||||||
const number_format = result?.number_format;
|
const time_format = data?.time_format;
|
||||||
const time_format = result?.time_format;
|
const date_format = data?.date_format;
|
||||||
const date_format = result?.date_format;
|
const time_zone = data?.time_zone;
|
||||||
const time_zone = result?.time_zone;
|
const first_weekday = data?.first_weekday;
|
||||||
const first_weekday = result?.first_weekday;
|
|
||||||
if (language) {
|
if (language) {
|
||||||
const availableLanguage = findAvailableLanguage(language);
|
const availableLanguage = findAvailableLanguage(language);
|
||||||
if (availableLanguage) {
|
if (availableLanguage) {
|
||||||
|
|
110
yarn.lock
110
yarn.lock
|
@ -1165,14 +1165,14 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@bundle-stats/plugin-webpack-filter@npm:4.20.0":
|
"@bundle-stats/plugin-webpack-filter@npm:4.20.1":
|
||||||
version: 4.20.0
|
version: 4.20.1
|
||||||
resolution: "@bundle-stats/plugin-webpack-filter@npm:4.20.0"
|
resolution: "@bundle-stats/plugin-webpack-filter@npm:4.20.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: "npm:2.8.1"
|
tslib: "npm:2.8.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
core-js: ^3.0.0
|
core-js: ^3.0.0
|
||||||
checksum: 10/b20479bb5f5964d8fa3b8be0b31665521681cfa7b0b5c2f3752476d36507332270e454592632a793c2579b98c036d6946eaa54caf984fcd3a649ccd1802492aa
|
checksum: 10/ba05af0d690010ad4e98cfe3b36f7b6d60f86b0faae4bed4a844f1a0f9ccc57ecee8085abc31dde2f1f290384580565b97086a5f79639553a54e49e712ce4261
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -2274,10 +2274,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@lokalise/node-api@npm:14.6.0":
|
"@lokalise/node-api@npm:14.7.0":
|
||||||
version: 14.6.0
|
version: 14.7.0
|
||||||
resolution: "@lokalise/node-api@npm:14.6.0"
|
resolution: "@lokalise/node-api@npm:14.7.0"
|
||||||
checksum: 10/b715a58f1a66cb8a8cfe2f3759b8a1bc25eb4c80a3ea52e800716758939a9430e4e3698958e58591999c2363cdfac4ad75294dd80788e93d6671f30ecb630deb
|
checksum: 10/77a1348c2a95215b924c2489136f5d8fc501f59fc8ff4b2d197716aca544db4d19928b005789a55fde0a0ea40830cda5ed8b7ef0895b97c458ca1fb1aa03d9bd
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -3825,22 +3825,22 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/client@npm:1.1.1":
|
"@rsdoctor/client@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/client@npm:1.1.1"
|
resolution: "@rsdoctor/client@npm:1.1.2"
|
||||||
checksum: 10/cd53a42e4c4f987c539e5235f532da4cfdf716aa2f0168c1c58224bf64970714dc90c4155ef4f9b915298d23c0154a07ac17a4f5926af0c60751e1ff2a6f305c
|
checksum: 10/600aadee4fd2fd176a232a0ecbdc62eada7f5aed5aa623983f2652633b487db541ec52fed666b7f7ada69440fb54ec12e7753e7519c8e0ebc9d11ad614fbbbd6
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/core@npm:1.1.1":
|
"@rsdoctor/core@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/core@npm:1.1.1"
|
resolution: "@rsdoctor/core@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rsbuild/plugin-check-syntax": "npm:1.3.0"
|
"@rsbuild/plugin-check-syntax": "npm:1.3.0"
|
||||||
"@rsdoctor/graph": "npm:1.1.1"
|
"@rsdoctor/graph": "npm:1.1.2"
|
||||||
"@rsdoctor/sdk": "npm:1.1.1"
|
"@rsdoctor/sdk": "npm:1.1.2"
|
||||||
"@rsdoctor/types": "npm:1.1.1"
|
"@rsdoctor/types": "npm:1.1.2"
|
||||||
"@rsdoctor/utils": "npm:1.1.1"
|
"@rsdoctor/utils": "npm:1.1.2"
|
||||||
axios: "npm:^1.8.4"
|
axios: "npm:^1.8.4"
|
||||||
browserslist-load-config: "npm:^1.0.0"
|
browserslist-load-config: "npm:^1.0.0"
|
||||||
enhanced-resolve: "npm:5.12.0"
|
enhanced-resolve: "npm:5.12.0"
|
||||||
|
@ -3851,47 +3851,47 @@ __metadata:
|
||||||
semver: "npm:^7.6.3"
|
semver: "npm:^7.6.3"
|
||||||
source-map: "npm:^0.7.4"
|
source-map: "npm:^0.7.4"
|
||||||
webpack-bundle-analyzer: "npm:^4.10.2"
|
webpack-bundle-analyzer: "npm:^4.10.2"
|
||||||
checksum: 10/378c50296c482ffa98f906c3a02bf83783f1a524062ca4c5302dfac04e2219216c488d7ab1164ad6dbeb629e33b8e9892a67c755f30fe5caae12a8141a051597
|
checksum: 10/f2535e434145f9b267c43acdcec1482ad7747600eb8438ca357700648096b22ee0697005bf58cd2b9180b69a06117a1909cec0923702594336ccc75f3040a3e7
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/graph@npm:1.1.1":
|
"@rsdoctor/graph@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/graph@npm:1.1.1"
|
resolution: "@rsdoctor/graph@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rsdoctor/types": "npm:1.1.1"
|
"@rsdoctor/types": "npm:1.1.2"
|
||||||
"@rsdoctor/utils": "npm:1.1.1"
|
"@rsdoctor/utils": "npm:1.1.2"
|
||||||
lodash.unionby: "npm:^4.8.0"
|
lodash.unionby: "npm:^4.8.0"
|
||||||
socket.io: "npm:4.8.1"
|
socket.io: "npm:4.8.1"
|
||||||
source-map: "npm:^0.7.4"
|
source-map: "npm:^0.7.4"
|
||||||
checksum: 10/b0bd4e77070bacf7340bf8450eee540c6565d61b7636328fe9ba23ab4ad770eef09a4e7a6a148b006546d1f43feabd014c8fc6e4daac79c23424165f54323efb
|
checksum: 10/b1cc511602305c36f95e524c6f2e60d32c3cea4a7328f67c068317a98c719ca8d69256e50d8dfad4641f8291cb32d487a041f62e3995d8841f8e5d4b2bb09319
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/rspack-plugin@npm:1.1.1":
|
"@rsdoctor/rspack-plugin@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/rspack-plugin@npm:1.1.1"
|
resolution: "@rsdoctor/rspack-plugin@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rsdoctor/core": "npm:1.1.1"
|
"@rsdoctor/core": "npm:1.1.2"
|
||||||
"@rsdoctor/graph": "npm:1.1.1"
|
"@rsdoctor/graph": "npm:1.1.2"
|
||||||
"@rsdoctor/sdk": "npm:1.1.1"
|
"@rsdoctor/sdk": "npm:1.1.2"
|
||||||
"@rsdoctor/types": "npm:1.1.1"
|
"@rsdoctor/types": "npm:1.1.2"
|
||||||
"@rsdoctor/utils": "npm:1.1.1"
|
"@rsdoctor/utils": "npm:1.1.2"
|
||||||
lodash: "npm:^4.17.21"
|
lodash: "npm:^4.17.21"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@rspack/core": "*"
|
"@rspack/core": "*"
|
||||||
checksum: 10/fb5ece5bfd583e097a4e4caf62e2a2cb30986824cbfe5b9a313a8db8b04f680291319bf4949278269589a5b12aceb26d514003045a5819101c8a6febd05fd226
|
checksum: 10/44107db8159c14273356fa5733341b01192e59ecdcca516632354a67321193ed40485c868a20488839dcbee12b6b07f22264c5080e9ddbf06ac6cf1a49b30ce3
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/sdk@npm:1.1.1":
|
"@rsdoctor/sdk@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/sdk@npm:1.1.1"
|
resolution: "@rsdoctor/sdk@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rsdoctor/client": "npm:1.1.1"
|
"@rsdoctor/client": "npm:1.1.2"
|
||||||
"@rsdoctor/graph": "npm:1.1.1"
|
"@rsdoctor/graph": "npm:1.1.2"
|
||||||
"@rsdoctor/types": "npm:1.1.1"
|
"@rsdoctor/types": "npm:1.1.2"
|
||||||
"@rsdoctor/utils": "npm:1.1.1"
|
"@rsdoctor/utils": "npm:1.1.2"
|
||||||
"@types/fs-extra": "npm:^11.0.4"
|
"@types/fs-extra": "npm:^11.0.4"
|
||||||
body-parser: "npm:1.20.3"
|
body-parser: "npm:1.20.3"
|
||||||
cors: "npm:2.8.5"
|
cors: "npm:2.8.5"
|
||||||
|
@ -3904,13 +3904,13 @@ __metadata:
|
||||||
socket.io: "npm:4.8.1"
|
socket.io: "npm:4.8.1"
|
||||||
source-map: "npm:^0.7.4"
|
source-map: "npm:^0.7.4"
|
||||||
tapable: "npm:2.2.1"
|
tapable: "npm:2.2.1"
|
||||||
checksum: 10/971a422e301961a74f64da56866b50a9d5773769aa0341d8a64ea14a0c940a16db77dbf8bb0a2c56b868f63d2fa00425709bb5eb28ac630171fb2817fbb2604e
|
checksum: 10/28baf794ee34fc46548a10fdce99a8ed207df2c74bb47ac50683ea23a81a52e5f0b50d07b7ad9f36348a0b4bfb9bad34613a2bde9f3b4dd988fe250ac7587b28
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/types@npm:1.1.1":
|
"@rsdoctor/types@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/types@npm:1.1.1"
|
resolution: "@rsdoctor/types@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/connect": "npm:3.4.38"
|
"@types/connect": "npm:3.4.38"
|
||||||
"@types/estree": "npm:1.0.5"
|
"@types/estree": "npm:1.0.5"
|
||||||
|
@ -3924,16 +3924,16 @@ __metadata:
|
||||||
optional: true
|
optional: true
|
||||||
webpack:
|
webpack:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10/578b18139cd66ba1a07d5ff9862050b9ed66a3883987b95d4764ebd392bc7538dfc3a20408048661201e73e3a4d46231d77ce36b4e2f1f56b528d75c8cc8e6f1
|
checksum: 10/37254be48d434cdb4663451fdc120cbba31f871072886eea0c84d8913177deab7eee88a22ce457764b2c432c2aaa0902234f6606244812d26f91921591a2b0dc
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rsdoctor/utils@npm:1.1.1":
|
"@rsdoctor/utils@npm:1.1.2":
|
||||||
version: 1.1.1
|
version: 1.1.2
|
||||||
resolution: "@rsdoctor/utils@npm:1.1.1"
|
resolution: "@rsdoctor/utils@npm:1.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame": "npm:7.26.2"
|
"@babel/code-frame": "npm:7.26.2"
|
||||||
"@rsdoctor/types": "npm:1.1.1"
|
"@rsdoctor/types": "npm:1.1.2"
|
||||||
"@types/estree": "npm:1.0.5"
|
"@types/estree": "npm:1.0.5"
|
||||||
acorn: "npm:^8.10.0"
|
acorn: "npm:^8.10.0"
|
||||||
acorn-import-attributes: "npm:^1.9.5"
|
acorn-import-attributes: "npm:^1.9.5"
|
||||||
|
@ -3949,7 +3949,7 @@ __metadata:
|
||||||
picocolors: "npm:^1.1.1"
|
picocolors: "npm:^1.1.1"
|
||||||
rslog: "npm:^1.2.3"
|
rslog: "npm:^1.2.3"
|
||||||
strip-ansi: "npm:^6.0.1"
|
strip-ansi: "npm:^6.0.1"
|
||||||
checksum: 10/30d21c1bb0a389b98a723e5ebc1b897d10ce23edda161edb3ab75f7b2614650c0f48955649a5e768d513236a694ff25f9a38dae2f05de43b4f493808742340ae
|
checksum: 10/d8435f149e4252c6e6eaca6e4f6e82352b3d3d0642b120b8b12323bc222c185ccb902fd7adc03ee2b5a2c52cb9d7cebbad388c6fdce319f2d3b7fbfc6bfd6287
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -9628,7 +9628,7 @@ __metadata:
|
||||||
"@babel/preset-env": "npm:7.27.2"
|
"@babel/preset-env": "npm:7.27.2"
|
||||||
"@babel/runtime": "npm:7.27.1"
|
"@babel/runtime": "npm:7.27.1"
|
||||||
"@braintree/sanitize-url": "npm:7.1.1"
|
"@braintree/sanitize-url": "npm:7.1.1"
|
||||||
"@bundle-stats/plugin-webpack-filter": "npm:4.20.0"
|
"@bundle-stats/plugin-webpack-filter": "npm:4.20.1"
|
||||||
"@codemirror/autocomplete": "npm:6.18.6"
|
"@codemirror/autocomplete": "npm:6.18.6"
|
||||||
"@codemirror/commands": "npm:6.8.1"
|
"@codemirror/commands": "npm:6.8.1"
|
||||||
"@codemirror/language": "npm:6.11.0"
|
"@codemirror/language": "npm:6.11.0"
|
||||||
|
@ -9660,7 +9660,7 @@ __metadata:
|
||||||
"@lit-labs/virtualizer": "npm:2.1.0"
|
"@lit-labs/virtualizer": "npm:2.1.0"
|
||||||
"@lit/context": "npm:1.1.5"
|
"@lit/context": "npm:1.1.5"
|
||||||
"@lit/reactive-element": "npm:2.1.0"
|
"@lit/reactive-element": "npm:2.1.0"
|
||||||
"@lokalise/node-api": "npm:14.6.0"
|
"@lokalise/node-api": "npm:14.7.0"
|
||||||
"@material/chips": "npm:=14.0.0-canary.53b3cad2f.0"
|
"@material/chips": "npm:=14.0.0-canary.53b3cad2f.0"
|
||||||
"@material/data-table": "npm:=14.0.0-canary.53b3cad2f.0"
|
"@material/data-table": "npm:=14.0.0-canary.53b3cad2f.0"
|
||||||
"@material/mwc-base": "npm:0.27.0"
|
"@material/mwc-base": "npm:0.27.0"
|
||||||
|
@ -9691,7 +9691,7 @@ __metadata:
|
||||||
"@octokit/plugin-retry": "npm:7.2.1"
|
"@octokit/plugin-retry": "npm:7.2.1"
|
||||||
"@octokit/rest": "npm:21.1.1"
|
"@octokit/rest": "npm:21.1.1"
|
||||||
"@replit/codemirror-indentation-markers": "npm:6.5.3"
|
"@replit/codemirror-indentation-markers": "npm:6.5.3"
|
||||||
"@rsdoctor/rspack-plugin": "npm:1.1.1"
|
"@rsdoctor/rspack-plugin": "npm:1.1.2"
|
||||||
"@rspack/cli": "npm:1.3.9"
|
"@rspack/cli": "npm:1.3.9"
|
||||||
"@rspack/core": "npm:1.3.9"
|
"@rspack/core": "npm:1.3.9"
|
||||||
"@shoelace-style/shoelace": "npm:2.20.1"
|
"@shoelace-style/shoelace": "npm:2.20.1"
|
||||||
|
|
Loading…
Reference in New Issue