Bump babel and eslint (#9049)
This commit is contained in:
parent
d4118ade0f
commit
5754f4463d
@ -4,8 +4,7 @@
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:wc/recommended",
|
||||
"plugin:lit/recommended",
|
||||
"prettier",
|
||||
"prettier/@typescript-eslint"
|
||||
"prettier"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
@ -85,6 +84,25 @@
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||
"@typescript-eslint/no-shadow": ["error"],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
0,
|
||||
{
|
||||
"selector": "default",
|
||||
"format": ["camelCase", "snake_case"],
|
||||
"leadingUnderscore": "allow",
|
||||
"trailingUnderscore": "allow"
|
||||
},
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"format": ["camelCase", "snake_case", "UPPER_CASE"],
|
||||
"leadingUnderscore": "allow",
|
||||
"trailingUnderscore": "allow"
|
||||
},
|
||||
{
|
||||
"selector": "typeLike",
|
||||
"format": ["PascalCase"]
|
||||
}
|
||||
],
|
||||
"lit/attribute-value-entities": 0
|
||||
},
|
||||
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
|
||||
|
||||
6
.github/workflows/ci.yaml
vendored
6
.github/workflows/ci.yaml
vendored
@ -37,9 +37,11 @@ jobs:
|
||||
- name: Build resources
|
||||
run: ./node_modules/.bin/gulp gen-icons-json build-translations gather-gallery-demos
|
||||
- name: Run eslint
|
||||
run: ./node_modules/.bin/eslint '{**/src,src}/**/*.{js,ts,html}' --ignore-path .gitignore
|
||||
run: yarn run lint:eslint
|
||||
- name: Run tsc
|
||||
run: ./node_modules/.bin/tsc
|
||||
run: yarn run lint:types
|
||||
- name: Run prettier
|
||||
run: yarn run lint:prettier
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@ -54,9 +54,7 @@ class HcCast extends LitElement {
|
||||
const error =
|
||||
this.castManager.castState === "NO_DEVICES_AVAILABLE"
|
||||
? html`
|
||||
<p>
|
||||
There were no suitable Chromecast devices to cast to found.
|
||||
</p>
|
||||
<p>There were no suitable Chromecast devices to cast to found.</p>
|
||||
`
|
||||
: undefined;
|
||||
|
||||
|
||||
@ -86,9 +86,7 @@ export class HcConnect extends LitElement {
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<a href="/">
|
||||
<mwc-button>
|
||||
Retry
|
||||
</mwc-button>
|
||||
<mwc-button> Retry </mwc-button>
|
||||
</a>
|
||||
<div class="spacer"></div>
|
||||
<mwc-button @click=${this._handleLogout}>Log out</mwc-button>
|
||||
|
||||
@ -3,8 +3,6 @@ import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
export const mockTranslations = (hass: MockHomeAssistant) => {
|
||||
hass.mockWS(
|
||||
"frontend/get_translations",
|
||||
(/* msg: {language: string, category: string} */) => {
|
||||
return { resources: {} };
|
||||
}
|
||||
(/* msg: {language: string, category: string} */) => ({ resources: {} })
|
||||
);
|
||||
};
|
||||
|
||||
@ -47,9 +47,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
const repo = this.repo;
|
||||
let _addons = this.addons;
|
||||
if (!this.hass.userData?.showAdvanced) {
|
||||
_addons = _addons.filter((addon) => {
|
||||
return !addon.advanced;
|
||||
});
|
||||
_addons = _addons.filter((addon) => !addon.advanced);
|
||||
}
|
||||
const addons = this._getAddons(_addons, this.filter);
|
||||
|
||||
@ -68,9 +66,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
}
|
||||
return html`
|
||||
<div class="content">
|
||||
<h1>
|
||||
${repo.name}
|
||||
</h1>
|
||||
<h1>${repo.name}</h1>
|
||||
<div class="card-group">
|
||||
${addons.map(
|
||||
(addon) => html`
|
||||
|
||||
@ -86,9 +86,7 @@ class HassioAddonStore extends LitElement {
|
||||
main-page
|
||||
supervisor
|
||||
>
|
||||
<span slot="header">
|
||||
${this.supervisor.localize("panel.store")}
|
||||
</span>
|
||||
<span slot="header"> ${this.supervisor.localize("panel.store")} </span>
|
||||
<ha-button-menu
|
||||
corner="BOTTOM_START"
|
||||
slot="toolbar-icon"
|
||||
@ -154,8 +152,8 @@ class HassioAddonStore extends LitElement {
|
||||
repositories: HassioAddonRepository[],
|
||||
addons: HassioAddonInfo[],
|
||||
filter?: string
|
||||
) => {
|
||||
return repositories.sort(sortRepos).map((repo) => {
|
||||
) =>
|
||||
repositories.sort(sortRepos).map((repo) => {
|
||||
const filteredAddons = addons.filter(
|
||||
(addon) => addon.repository === repo.slug
|
||||
);
|
||||
@ -171,8 +169,7 @@ class HassioAddonStore extends LitElement {
|
||||
></hassio-addon-repository>
|
||||
`
|
||||
: html``;
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||
|
||||
@ -69,13 +69,13 @@ class HassioAddonAudio extends LitElement {
|
||||
.selected=${this._selectedInput!}
|
||||
>
|
||||
${this._inputDevices &&
|
||||
this._inputDevices.map((item) => {
|
||||
return html`
|
||||
this._inputDevices.map(
|
||||
(item) => html`
|
||||
<paper-item device=${item.device || ""}>
|
||||
${item.name}
|
||||
</paper-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu
|
||||
@ -90,13 +90,13 @@ class HassioAddonAudio extends LitElement {
|
||||
.selected=${this._selectedOutput!}
|
||||
>
|
||||
${this._outputDevices &&
|
||||
this._outputDevices.map((item) => {
|
||||
return html`
|
||||
this._outputDevices.map(
|
||||
(item) => html`
|
||||
<paper-item device=${item.device || ""}
|
||||
>${item.name}</paper-item
|
||||
>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
@ -65,19 +65,15 @@ class HassioAddonConfig extends LitElement {
|
||||
|
||||
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
|
||||
|
||||
public computeLabel = (entry: HaFormSchema): string => {
|
||||
return (
|
||||
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
|
||||
?.name ||
|
||||
this.addon.translations.en?.configuration?.[entry.name].name ||
|
||||
entry.name
|
||||
);
|
||||
};
|
||||
public computeLabel = (entry: HaFormSchema): string =>
|
||||
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
|
||||
?.name ||
|
||||
this.addon.translations.en?.configuration?.[entry.name].name ||
|
||||
entry.name;
|
||||
|
||||
private _filteredShchema = memoizeOne(
|
||||
(options: Record<string, unknown>, schema: HaFormSchema[]) => {
|
||||
return schema.filter((entry) => entry.name in options || entry.required);
|
||||
}
|
||||
(options: Record<string, unknown>, schema: HaFormSchema[]) =>
|
||||
schema.filter((entry) => entry.name in options || entry.required)
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
||||
@ -79,12 +79,10 @@ class HassioAddonNetwork extends LitElement {
|
||||
"addon.configuration.network.host"
|
||||
)}
|
||||
</th>
|
||||
<th>
|
||||
${this.supervisor.localize("common.description")}
|
||||
</th>
|
||||
<th>${this.supervisor.localize("common.description")}</th>
|
||||
</tr>
|
||||
${this._config!.map((item) => {
|
||||
return html`
|
||||
${this._config!.map(
|
||||
(item) => html`
|
||||
<tr>
|
||||
<td>${item.container}</td>
|
||||
<td>
|
||||
@ -100,8 +98,8 @@ class HassioAddonNetwork extends LitElement {
|
||||
</td>
|
||||
<td>${this._computeDescription(item)}</td>
|
||||
</tr>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -124,25 +122,20 @@ class HassioAddonNetwork extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _computeDescription = (item: NetworkItem): string => {
|
||||
return (
|
||||
this.addon.translations[this.hass.language]?.network?.[item.container]
|
||||
?.description ||
|
||||
this.addon.translations.en?.network?.[item.container]?.description ||
|
||||
item.description
|
||||
);
|
||||
};
|
||||
private _computeDescription = (item: NetworkItem): string =>
|
||||
this.addon.translations[this.hass.language]?.network?.[item.container]
|
||||
?.description ||
|
||||
this.addon.translations.en?.network?.[item.container]?.description ||
|
||||
item.description;
|
||||
|
||||
private _setNetworkConfig(): void {
|
||||
const network = this.addon.network || {};
|
||||
const description = this.addon.network_description || {};
|
||||
const items: NetworkItem[] = Object.keys(network).map((key) => {
|
||||
return {
|
||||
container: key,
|
||||
host: network[key],
|
||||
description: description[key],
|
||||
};
|
||||
});
|
||||
const items: NetworkItem[] = Object.keys(network).map((key) => ({
|
||||
container: key,
|
||||
host: network[key],
|
||||
description: description[key],
|
||||
}));
|
||||
this._config = items.sort((a, b) => (a.container > b.container ? 1 : -1));
|
||||
}
|
||||
|
||||
|
||||
@ -566,9 +566,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<span slot="heading">
|
||||
${this.supervisor.localize("addon.dashboard.hostname")}
|
||||
</span>
|
||||
<code slot="description">
|
||||
${this.addon.hostname}
|
||||
</code>
|
||||
<code slot="description"> ${this.addon.hostname} </code>
|
||||
</ha-settings-row>
|
||||
${metrics.map(
|
||||
(metric) =>
|
||||
@ -997,7 +995,7 @@ class HassioAddonInfo extends LitElement {
|
||||
addons: [this.addon.slug],
|
||||
homeassistant: false,
|
||||
},
|
||||
updateHandler: async () => await this._updateAddon(),
|
||||
updateHandler: async () => this._updateAddon(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -56,13 +56,13 @@ class HassioCardContent extends LitElement {
|
||||
></ha-svg-icon>
|
||||
`}
|
||||
<div>
|
||||
<div class="title">
|
||||
${this.title}
|
||||
</div>
|
||||
<div class="title">${this.title}</div>
|
||||
<div class="addition">
|
||||
${this.description}
|
||||
${/* treat as available when undefined */
|
||||
this.available === false ? " (Not available)" : ""}
|
||||
${
|
||||
/* treat as available when undefined */
|
||||
this.available === false ? " (Not available)" : ""
|
||||
}
|
||||
${this.datetime
|
||||
? html`
|
||||
<ha-relative-time
|
||||
|
||||
@ -23,13 +23,9 @@ class SupervisorMetric extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
const roundedValue = roundWithOneDecimal(this.value);
|
||||
return html`<ha-settings-row>
|
||||
<span slot="heading">
|
||||
${this.description}
|
||||
</span>
|
||||
<span slot="heading"> ${this.description} </span>
|
||||
<div slot="description" .title=${this.tooltip ?? ""}>
|
||||
<span class="value">
|
||||
${roundedValue} %
|
||||
</span>
|
||||
<span class="value"> ${roundedValue} % </span>
|
||||
<ha-bar
|
||||
class="${classMap({
|
||||
"target-warning": roundedValue > 50,
|
||||
|
||||
@ -40,9 +40,8 @@ import { HomeAssistant } from "../../../src/types";
|
||||
import { showDialogSupervisorUpdate } from "../dialogs/update/show-dialog-update";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
|
||||
const computeVersion = (key: string, version: string): string => {
|
||||
return key === "os" ? version : `${key}-${version}`;
|
||||
};
|
||||
const computeVersion = (key: string, version: string): string =>
|
||||
key === "os" ? version : `${key}-${version}`;
|
||||
|
||||
@customElement("hassio-update")
|
||||
export class HassioUpdate extends LitElement {
|
||||
@ -50,11 +49,12 @@ export class HassioUpdate extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||
|
||||
private _pendingUpdates = memoizeOne((supervisor: Supervisor): number => {
|
||||
return Object.keys(supervisor).filter(
|
||||
(value) => supervisor[value].update_available
|
||||
).length;
|
||||
});
|
||||
private _pendingUpdates = memoizeOne(
|
||||
(supervisor: Supervisor): number =>
|
||||
Object.keys(supervisor).filter(
|
||||
(value) => supervisor[value].update_available
|
||||
).length
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.supervisor) {
|
||||
|
||||
@ -47,7 +47,8 @@ import { HassioNetworkDialogParams } from "./show-dialog-network";
|
||||
const IP_VERSIONS = ["ipv4", "ipv6"];
|
||||
|
||||
@customElement("dialog-hassio-network")
|
||||
export class DialogHassioNetwork extends LitElement
|
||||
export class DialogHassioNetwork
|
||||
extends LitElement
|
||||
implements HassDialog<HassioNetworkDialogParams> {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@ -76,9 +77,9 @@ export class DialogHassioNetwork extends LitElement
|
||||
this._dirty = false;
|
||||
this._curTabIndex = 0;
|
||||
this.supervisor = params.supervisor;
|
||||
this._interfaces = params.supervisor.network.interfaces.sort((a, b) => {
|
||||
return a.primary > b.primary ? -1 : 1;
|
||||
});
|
||||
this._interfaces = params.supervisor.network.interfaces.sort((a, b) =>
|
||||
a.primary > b.primary ? -1 : 1
|
||||
);
|
||||
this._interface = { ...this._interfaces[this._curTabIndex] };
|
||||
|
||||
await this.updateComplete;
|
||||
|
||||
@ -108,8 +108,8 @@ class HassioRegistriesDialog extends LitElement {
|
||||
</mwc-button>
|
||||
`
|
||||
: html`${this._registries?.length
|
||||
? this._registries.map((entry) => {
|
||||
return html`
|
||||
? this._registries.map(
|
||||
(entry) => html`
|
||||
<mwc-list-item class="option" hasMeta twoline>
|
||||
<span>${entry.registry}</span>
|
||||
<span slot="secondary"
|
||||
@ -129,8 +129,8 @@ class HassioRegistriesDialog extends LitElement {
|
||||
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</mwc-list-item>
|
||||
`;
|
||||
})
|
||||
`
|
||||
)
|
||||
: html`
|
||||
<mwc-list-item>
|
||||
<span
|
||||
|
||||
@ -87,8 +87,8 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
||||
<div class="form">
|
||||
${repositories.length
|
||||
? repositories.map((repo) => {
|
||||
return html`
|
||||
? repositories.map(
|
||||
(repo) => html`
|
||||
<paper-item class="option">
|
||||
<paper-item-body three-line>
|
||||
<div>${repo.name}</div>
|
||||
@ -105,13 +105,9 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</paper-item>
|
||||
`;
|
||||
})
|
||||
: html`
|
||||
<paper-item>
|
||||
No repositories
|
||||
</paper-item>
|
||||
`}
|
||||
`
|
||||
)
|
||||
: html` <paper-item> No repositories </paper-item> `}
|
||||
<div class="layout horizontal bottom">
|
||||
<paper-input
|
||||
class="flex-auto"
|
||||
@ -207,9 +203,7 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
}
|
||||
this._prosessing = true;
|
||||
const repositories = this._filteredRepositories(this._repositories!);
|
||||
const newRepositories = repositories.map((repo) => {
|
||||
return repo.source;
|
||||
});
|
||||
const newRepositories = repositories.map((repo) => repo.source);
|
||||
newRepositories.push(input.value);
|
||||
|
||||
try {
|
||||
@ -228,19 +222,13 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
private async _removeRepository(ev: Event) {
|
||||
const slug = (ev.currentTarget as any).slug;
|
||||
const repositories = this._filteredRepositories(this._repositories!);
|
||||
const repository = repositories.find((repo) => {
|
||||
return repo.slug === slug;
|
||||
});
|
||||
const repository = repositories.find((repo) => repo.slug === slug);
|
||||
if (!repository) {
|
||||
return;
|
||||
}
|
||||
const newRepositories = repositories
|
||||
.map((repo) => {
|
||||
return repo.source;
|
||||
})
|
||||
.filter((repo) => {
|
||||
return repo !== repository.source;
|
||||
});
|
||||
.map((repo) => repo.source)
|
||||
.filter((repo) => repo !== repository.source);
|
||||
|
||||
try {
|
||||
await setSupervisorOption(this.hass, {
|
||||
|
||||
@ -18,7 +18,8 @@ import "../../components/hassio-upload-snapshot";
|
||||
import { HassioSnapshotUploadDialogParams } from "./show-dialog-snapshot-upload";
|
||||
|
||||
@customElement("dialog-hassio-snapshot-upload")
|
||||
export class DialogHassioSnapshotUpload extends LitElement
|
||||
export class DialogHassioSnapshotUpload
|
||||
extends LitElement
|
||||
implements HassDialog<HassioSnapshotUploadDialogParams> {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@ -57,9 +58,7 @@ export class DialogHassioSnapshotUpload extends LitElement
|
||||
>
|
||||
<div slot="heading">
|
||||
<ha-header-bar>
|
||||
<span slot="title">
|
||||
Upload snapshot
|
||||
</span>
|
||||
<span slot="title"> Upload snapshot </span>
|
||||
<mwc-icon-button slot="actionItems" dialogAction="cancel">
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
|
||||
@ -53,14 +53,13 @@ const _computeFolders = (folders) => {
|
||||
return list;
|
||||
};
|
||||
|
||||
const _computeAddons = (addons) => {
|
||||
return addons.map((addon) => ({
|
||||
const _computeAddons = (addons) =>
|
||||
addons.map((addon) => ({
|
||||
slug: addon.slug,
|
||||
name: addon.name,
|
||||
version: addon.version,
|
||||
checked: true,
|
||||
}));
|
||||
};
|
||||
|
||||
interface AddonItem {
|
||||
slug: string;
|
||||
@ -122,9 +121,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
<ha-dialog open @closing=${this._closeDialog} .heading=${true}>
|
||||
<div slot="heading">
|
||||
<ha-header-bar>
|
||||
<span slot="title">
|
||||
${this._computeName}
|
||||
</span>
|
||||
<span slot="title"> ${this._computeName} </span>
|
||||
<mwc-icon-button slot="actionItems" dialogAction="cancel">
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
@ -152,8 +149,8 @@ class HassioSnapshotDialog extends LitElement {
|
||||
? html`
|
||||
<div>Folders:</div>
|
||||
<paper-dialog-scrollable class="no-margin-top">
|
||||
${this._folders.map((item) => {
|
||||
return html`
|
||||
${this._folders.map(
|
||||
(item) => html`
|
||||
<paper-checkbox
|
||||
.checked=${item.checked}
|
||||
@change="${(ev: Event) =>
|
||||
@ -164,8 +161,8 @@ class HassioSnapshotDialog extends LitElement {
|
||||
>
|
||||
${item.name}
|
||||
</paper-checkbox>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-dialog-scrollable>
|
||||
`
|
||||
: ""}
|
||||
@ -173,8 +170,8 @@ class HassioSnapshotDialog extends LitElement {
|
||||
? html`
|
||||
<div>Add-on:</div>
|
||||
<paper-dialog-scrollable class="no-margin-top">
|
||||
${this._addons.map((item) => {
|
||||
return html`
|
||||
${this._addons.map(
|
||||
(item) => html`
|
||||
<paper-checkbox
|
||||
.checked=${item.checked}
|
||||
@change="${(ev: Event) =>
|
||||
@ -185,8 +182,8 @@ class HassioSnapshotDialog extends LitElement {
|
||||
>
|
||||
${item.name}
|
||||
</paper-checkbox>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-dialog-scrollable>
|
||||
`
|
||||
: ""}
|
||||
|
||||
@ -132,9 +132,7 @@ class HassioSnapshots extends LitElement {
|
||||
</ha-button-menu>
|
||||
|
||||
<div class="content">
|
||||
<h1>
|
||||
${this.supervisor.localize("snapshot.create_snapshot")}
|
||||
</h1>
|
||||
<h1>${this.supervisor.localize("snapshot.create_snapshot")}</h1>
|
||||
<p class="description">
|
||||
${this.supervisor.localize("snapshot.description")}
|
||||
</p>
|
||||
|
||||
@ -178,7 +178,7 @@ class HassioCoreInfo extends LitElement {
|
||||
folders: ["homeassistant"],
|
||||
homeassistant: true,
|
||||
},
|
||||
updateHandler: async () => await this._updateCore(),
|
||||
updateHandler: async () => this._updateCore(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -97,9 +97,7 @@ class HassioHostInfo extends LitElement {
|
||||
<span slot="heading">
|
||||
${this.supervisor.localize("system.host.ip_address")}
|
||||
</span>
|
||||
<span slot="description">
|
||||
${primaryIpAddress}
|
||||
</span>
|
||||
<span slot="description"> ${primaryIpAddress} </span>
|
||||
<mwc-button
|
||||
.label=${this.supervisor.localize("system.host.change")}
|
||||
@click=${this._changeNetworkClicked}
|
||||
|
||||
@ -264,9 +264,7 @@ class HassioSupervisorInfo extends LitElement {
|
||||
title: this.supervisor.localize("system.supervisor.warning"),
|
||||
text: html`${this.supervisor.localize("system.supervisor.beta_warning")}
|
||||
<br />
|
||||
<b>
|
||||
${this.supervisor.localize("system.supervisor.beta_backup")}
|
||||
</b>
|
||||
<b> ${this.supervisor.localize("system.supervisor.beta_backup")} </b>
|
||||
<br /><br />
|
||||
${this.supervisor.localize("system.supervisor.beta_release_items")}
|
||||
<ul>
|
||||
|
||||
@ -87,13 +87,13 @@ class HassioSupervisorLog extends LitElement {
|
||||
attr-for-selected="provider"
|
||||
.selected=${this._selectedLogProvider}
|
||||
>
|
||||
${logProviders.map((provider) => {
|
||||
return html`
|
||||
${logProviders.map(
|
||||
(provider) => html`
|
||||
<paper-item provider=${provider.key}>
|
||||
${provider.name}
|
||||
</paper-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
`
|
||||
|
||||
@ -39,9 +39,7 @@ class HassioSystem extends LitElement {
|
||||
main-page
|
||||
supervisor
|
||||
>
|
||||
<span slot="header">
|
||||
${this.supervisor.localize("panel.system")}
|
||||
</span>
|
||||
<span slot="header"> ${this.supervisor.localize("panel.system")} </span>
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<hassio-core-info
|
||||
|
||||
42
package.json
42
package.json
@ -14,10 +14,10 @@
|
||||
"format:prettier": "prettier \"**/src/**/*.{js,ts,json,css,md}\" --write",
|
||||
"lint:types": "tsc",
|
||||
"lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md",
|
||||
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:types",
|
||||
"format": "npm run format:eslint && npm run format:prettier",
|
||||
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types",
|
||||
"format": "yarn run format:eslint && yarn run format:prettier",
|
||||
"mocha": "node_modules/.bin/ts-mocha -p test-mocha/tsconfig.test.json --opts test-mocha/mocha.opts",
|
||||
"test": "npm run lint && npm run mocha"
|
||||
"test": "yarn run lint && yarn run mocha"
|
||||
},
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
@ -147,17 +147,17 @@
|
||||
"xss": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@babel/plugin-external-helpers": "^7.10.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||
"@babel/plugin-proposal-decorators": "^7.10.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.11.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
|
||||
"@babel/core": "^7.14.0",
|
||||
"@babel/plugin-external-helpers": "^7.12.13",
|
||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.13.15",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.13.8",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"@babel/preset-typescript": "^7.10.4",
|
||||
"@babel/preset-env": "^7.14.0",
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"@koa/cors": "^3.1.0",
|
||||
"@open-wc/dev-server-hmr": "^0.0.2",
|
||||
"@rollup/plugin-babel": "^5.2.1",
|
||||
@ -177,23 +177,23 @@
|
||||
"@types/resize-observer-browser": "^0.1.3",
|
||||
"@types/sortablejs": "^1.10.6",
|
||||
"@types/webspeechapi": "^0.0.29",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.0",
|
||||
"@typescript-eslint/parser": "^4.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"@web/dev-server": "^0.0.24",
|
||||
"@web/dev-server-rollup": "^0.2.11",
|
||||
"babel-loader": "^8.1.0",
|
||||
"chai": "^4.2.0",
|
||||
"cpx": "^1.5.0",
|
||||
"del": "^4.0.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-airbnb-typescript": "^7.2.1",
|
||||
"eslint-config-prettier": "^6.10.1",
|
||||
"eslint": "^7.25.0",
|
||||
"eslint-config-airbnb-typescript": "^12.3.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-import-resolver-webpack": "^0.13.0",
|
||||
"eslint-plugin-disable": "^2.0.1",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-lit": "^1.2.0",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-wc": "^1.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-lit": "^1.3.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-wc": "^1.3.0",
|
||||
"fancy-log": "^1.3.3",
|
||||
"fs-extra": "^7.0.1",
|
||||
"gulp": "^4.0.0",
|
||||
|
||||
@ -38,11 +38,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
||||
@internalProperty() private _errorMessage?: string;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<form>
|
||||
${this._renderForm()}
|
||||
</form>
|
||||
`;
|
||||
return html` <form>${this._renderForm()}</form> `;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
|
||||
@ -17,9 +17,8 @@ export const hex2rgb = (hex: string): [number, number, number] => {
|
||||
];
|
||||
};
|
||||
|
||||
export const rgb2hex = (rgb: [number, number, number]): string => {
|
||||
return `#${rgb_hex(rgb[0])}${rgb_hex(rgb[1])}${rgb_hex(rgb[2])}`;
|
||||
};
|
||||
export const rgb2hex = (rgb: [number, number, number]): string =>
|
||||
`#${rgb_hex(rgb[0])}${rgb_hex(rgb[1])}${rgb_hex(rgb[2])}`;
|
||||
|
||||
// Conversion between LAB, XYZ and RGB from https://github.com/gka/chroma.js
|
||||
// Copyright (c) 2011-2019, Gregor Aisch
|
||||
@ -49,13 +48,10 @@ const xyz_lab = (t: number) => {
|
||||
return t / t2 + t0;
|
||||
};
|
||||
|
||||
const xyz_rgb = (r: number) => {
|
||||
return 255 * (r <= 0.00304 ? 12.92 * r : 1.055 * r ** (1 / 2.4) - 0.055);
|
||||
};
|
||||
const xyz_rgb = (r: number) =>
|
||||
255 * (r <= 0.00304 ? 12.92 * r : 1.055 * r ** (1 / 2.4) - 0.055);
|
||||
|
||||
const lab_xyz = (t: number) => {
|
||||
return t > t1 ? t * t * t : t2 * (t - t0);
|
||||
};
|
||||
const lab_xyz = (t: number) => (t > t1 ? t * t * t : t2 * (t - t0));
|
||||
|
||||
// Conversions between RGB and LAB
|
||||
|
||||
@ -114,6 +110,5 @@ export const rgb2hsv = (
|
||||
return [60 * (h < 0 ? h + 6 : h), v && c / v, v];
|
||||
};
|
||||
|
||||
export const rgb2hs = (rgb: [number, number, number]): [number, number] => {
|
||||
return rgb2hsv(rgb).slice(0, 2) as [number, number];
|
||||
};
|
||||
export const rgb2hs = (rgb: [number, number, number]): [number, number] =>
|
||||
rgb2hsv(rgb).slice(0, 2) as [number, number];
|
||||
|
||||
@ -4,13 +4,9 @@
|
||||
export const labDarken = (
|
||||
lab: [number, number, number],
|
||||
amount = 1
|
||||
): [number, number, number] => {
|
||||
return [lab[0] - 18 * amount, lab[1], lab[2]];
|
||||
};
|
||||
): [number, number, number] => [lab[0] - 18 * amount, lab[1], lab[2]];
|
||||
|
||||
export const labBrighten = (
|
||||
lab: [number, number, number],
|
||||
amount = 1
|
||||
): [number, number, number] => {
|
||||
return labDarken(lab, -amount);
|
||||
};
|
||||
): [number, number, number] => labDarken(lab, -amount);
|
||||
|
||||
@ -2,12 +2,9 @@ import { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { isComponentLoaded } from "./is_component_loaded";
|
||||
|
||||
export const canShowPage = (hass: HomeAssistant, page: PageNavigation) => {
|
||||
return (
|
||||
(isCore(page) || isLoadedIntegration(hass, page)) &&
|
||||
!hideAdvancedPage(hass, page)
|
||||
);
|
||||
};
|
||||
export const canShowPage = (hass: HomeAssistant, page: PageNavigation) =>
|
||||
(isCore(page) || isLoadedIntegration(hass, page)) &&
|
||||
!hideAdvancedPage(hass, page);
|
||||
|
||||
const isLoadedIntegration = (hass: HomeAssistant, page: PageNavigation) =>
|
||||
!page.component || isComponentLoaded(hass, page.component);
|
||||
|
||||
@ -86,70 +86,63 @@ export const LocalStorage = (
|
||||
storageKey?: string,
|
||||
property?: boolean,
|
||||
propertyOptions?: PropertyDeclaration
|
||||
): any => {
|
||||
return (clsElement: ClassElement) => {
|
||||
const key = String(clsElement.key);
|
||||
storageKey = storageKey || String(clsElement.key);
|
||||
const initVal = clsElement.initializer
|
||||
? clsElement.initializer()
|
||||
: undefined;
|
||||
): any => (clsElement: ClassElement) => {
|
||||
const key = String(clsElement.key);
|
||||
storageKey = storageKey || String(clsElement.key);
|
||||
const initVal = clsElement.initializer ? clsElement.initializer() : undefined;
|
||||
|
||||
storage.addFromStorage(storageKey);
|
||||
storage.addFromStorage(storageKey);
|
||||
|
||||
const subscribe = (el: UpdatingElement): UnsubscribeFunc =>
|
||||
storage.subscribeChanges(storageKey!, (oldValue) => {
|
||||
el.requestUpdate(clsElement.key, oldValue);
|
||||
});
|
||||
const subscribe = (el: UpdatingElement): UnsubscribeFunc =>
|
||||
storage.subscribeChanges(storageKey!, (oldValue) => {
|
||||
el.requestUpdate(clsElement.key, oldValue);
|
||||
});
|
||||
|
||||
const getValue = (): any => {
|
||||
return storage.hasKey(storageKey!)
|
||||
? storage.getValue(storageKey!)
|
||||
: initVal;
|
||||
};
|
||||
const getValue = (): any =>
|
||||
storage.hasKey(storageKey!) ? storage.getValue(storageKey!) : initVal;
|
||||
|
||||
const setValue = (el: UpdatingElement, value: any) => {
|
||||
let oldValue: unknown | undefined;
|
||||
if (property) {
|
||||
oldValue = getValue();
|
||||
}
|
||||
storage.setValue(storageKey!, value);
|
||||
if (property) {
|
||||
el.requestUpdate(clsElement.key, oldValue);
|
||||
}
|
||||
};
|
||||
const setValue = (el: UpdatingElement, value: any) => {
|
||||
let oldValue: unknown | undefined;
|
||||
if (property) {
|
||||
oldValue = getValue();
|
||||
}
|
||||
storage.setValue(storageKey!, value);
|
||||
if (property) {
|
||||
el.requestUpdate(clsElement.key, oldValue);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
kind: "method",
|
||||
placement: "prototype",
|
||||
key: clsElement.key,
|
||||
descriptor: {
|
||||
set(this: UpdatingElement, value: unknown) {
|
||||
setValue(this, value);
|
||||
},
|
||||
get() {
|
||||
return getValue();
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
return {
|
||||
kind: "method",
|
||||
placement: "prototype",
|
||||
key: clsElement.key,
|
||||
descriptor: {
|
||||
set(this: UpdatingElement, value: unknown) {
|
||||
setValue(this, value);
|
||||
},
|
||||
finisher(cls: typeof UpdatingElement) {
|
||||
if (property) {
|
||||
const connectedCallback = cls.prototype.connectedCallback;
|
||||
const disconnectedCallback = cls.prototype.disconnectedCallback;
|
||||
cls.prototype.connectedCallback = function () {
|
||||
connectedCallback.call(this);
|
||||
this[`__unbsubLocalStorage${key}`] = subscribe(this);
|
||||
};
|
||||
cls.prototype.disconnectedCallback = function () {
|
||||
disconnectedCallback.call(this);
|
||||
this[`__unbsubLocalStorage${key}`]();
|
||||
};
|
||||
cls.createProperty(clsElement.key, {
|
||||
noAccessor: true,
|
||||
...propertyOptions,
|
||||
});
|
||||
}
|
||||
get() {
|
||||
return getValue();
|
||||
},
|
||||
};
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
},
|
||||
finisher(cls: typeof UpdatingElement) {
|
||||
if (property) {
|
||||
const connectedCallback = cls.prototype.connectedCallback;
|
||||
const disconnectedCallback = cls.prototype.disconnectedCallback;
|
||||
cls.prototype.connectedCallback = function () {
|
||||
connectedCallback.call(this);
|
||||
this[`__unbsubLocalStorage${key}`] = subscribe(this);
|
||||
};
|
||||
cls.prototype.disconnectedCallback = function () {
|
||||
disconnectedCallback.call(this);
|
||||
this[`__unbsubLocalStorage${key}`]();
|
||||
};
|
||||
cls.createProperty(clsElement.key, {
|
||||
noAccessor: true,
|
||||
...propertyOptions,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
import type { LitElement } from "lit-element";
|
||||
import type { ClassElement } from "../../types";
|
||||
|
||||
export const restoreScroll = (selector: string): any => {
|
||||
return (element: ClassElement) => ({
|
||||
kind: "method",
|
||||
placement: "prototype",
|
||||
key: element.key,
|
||||
descriptor: {
|
||||
set(this: LitElement, value: number) {
|
||||
this[`__${String(element.key)}`] = value;
|
||||
},
|
||||
get(this: LitElement) {
|
||||
return this[`__${String(element.key)}`];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
export const restoreScroll = (selector: string): any => (
|
||||
element: ClassElement
|
||||
) => ({
|
||||
kind: "method",
|
||||
placement: "prototype",
|
||||
key: element.key,
|
||||
descriptor: {
|
||||
set(this: LitElement, value: number) {
|
||||
this[`__${String(element.key)}`] = value;
|
||||
},
|
||||
finisher(cls: typeof LitElement) {
|
||||
const connectedCallback = cls.prototype.connectedCallback;
|
||||
cls.prototype.connectedCallback = function () {
|
||||
connectedCallback.call(this);
|
||||
if (this[element.key]) {
|
||||
const target = this.renderRoot.querySelector(selector);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
target.scrollTop = this[element.key];
|
||||
get(this: LitElement) {
|
||||
return this[`__${String(element.key)}`];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
},
|
||||
finisher(cls: typeof LitElement) {
|
||||
const connectedCallback = cls.prototype.connectedCallback;
|
||||
cls.prototype.connectedCallback = function () {
|
||||
connectedCallback.call(this);
|
||||
if (this[element.key]) {
|
||||
const target = this.renderRoot.querySelector(selector);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
||||
target.scrollTop = this[element.key];
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
// Load a resource and get a promise when loading done.
|
||||
// From: https://davidwalsh.name/javascript-loader
|
||||
|
||||
const _load = (
|
||||
tag: "link" | "script" | "img",
|
||||
url: string,
|
||||
type?: "module"
|
||||
) => {
|
||||
const _load = (tag: "link" | "script" | "img", url: string, type?: "module") =>
|
||||
// This promise will be used by Promise.all to determine success or failure
|
||||
return new Promise((resolve, reject) => {
|
||||
new Promise((resolve, reject) => {
|
||||
const element = document.createElement(tag);
|
||||
let attr = "src";
|
||||
let parent = "body";
|
||||
@ -35,8 +31,6 @@ const _load = (
|
||||
element[attr] = url;
|
||||
document[parent].appendChild(element);
|
||||
});
|
||||
};
|
||||
|
||||
export const loadCSS = (url: string) => _load("link", url);
|
||||
export const loadJS = (url: string) => _load("script", url);
|
||||
export const loadImg = (url: string) => _load("img", url);
|
||||
|
||||
@ -48,8 +48,8 @@ export const replaceTileLayer = (
|
||||
const createTileLayer = (
|
||||
leaflet: LeafletModuleType,
|
||||
darkMode: boolean
|
||||
): TileLayer => {
|
||||
return leaflet.tileLayer(
|
||||
): TileLayer =>
|
||||
leaflet.tileLayer(
|
||||
`https://{s}.basemaps.cartocdn.com/${
|
||||
darkMode ? "dark_all" : "light_all"
|
||||
}/{z}/{x}/{y}${leaflet.Browser.retina ? "@2x.png" : ".png"}`,
|
||||
@ -61,4 +61,3 @@ const createTileLayer = (
|
||||
maxZoom: 20,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
export const computeDomain = (entityId: string): string => {
|
||||
return entityId.substr(0, entityId.indexOf("."));
|
||||
};
|
||||
export const computeDomain = (entityId: string): string =>
|
||||
entityId.substr(0, entityId.indexOf("."));
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/** Compute the object ID of a state. */
|
||||
export const computeObjectId = (entityId: string): string => {
|
||||
return entityId.substr(entityId.indexOf(".") + 1);
|
||||
};
|
||||
export const computeObjectId = (entityId: string): string =>
|
||||
entityId.substr(entityId.indexOf(".") + 1);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { computeDomain } from "./compute_domain";
|
||||
|
||||
export const computeStateDomain = (stateObj: HassEntity) => {
|
||||
return computeDomain(stateObj.entity_id);
|
||||
};
|
||||
export const computeStateDomain = (stateObj: HassEntity) =>
|
||||
computeDomain(stateObj.entity_id);
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { computeObjectId } from "./compute_object_id";
|
||||
|
||||
export const computeStateName = (stateObj: HassEntity): string => {
|
||||
return stateObj.attributes.friendly_name === undefined
|
||||
export const computeStateName = (stateObj: HassEntity): string =>
|
||||
stateObj.attributes.friendly_name === undefined
|
||||
? computeObjectId(stateObj.entity_id).replace(/_/g, " ")
|
||||
: stateObj.attributes.friendly_name || "";
|
||||
};
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
export const hasLocation = (stateObj: HassEntity) => {
|
||||
return (
|
||||
"latitude" in stateObj.attributes && "longitude" in stateObj.attributes
|
||||
);
|
||||
};
|
||||
export const hasLocation = (stateObj: HassEntity) =>
|
||||
"latitude" in stateObj.attributes && "longitude" in stateObj.attributes;
|
||||
|
||||
@ -3,7 +3,6 @@ import { HassEntity } from "home-assistant-js-websocket";
|
||||
export const supportsFeature = (
|
||||
stateObj: HassEntity,
|
||||
feature: number
|
||||
): boolean => {
|
||||
): boolean =>
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return (stateObj.attributes.supported_features! & feature) !== 0;
|
||||
};
|
||||
(stateObj.attributes.supported_features! & feature) !== 0;
|
||||
|
||||
@ -119,6 +119,7 @@ export const extractColors = (url: string, downsampleColors = 16) =>
|
||||
colorCount: downsampleColors,
|
||||
})
|
||||
.getPalette()
|
||||
.then(({ foreground, background }) => {
|
||||
return { background: background!, foreground: foreground! };
|
||||
});
|
||||
.then(({ foreground, background }) => ({
|
||||
background: background!,
|
||||
foreground: foreground!,
|
||||
}));
|
||||
|
||||
@ -71,8 +71,8 @@ type FuzzyFilterSort = <T extends ScorableTextItem>(
|
||||
items: T[]
|
||||
) => T[];
|
||||
|
||||
export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) => {
|
||||
return items
|
||||
export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) =>
|
||||
items
|
||||
.map((item) => {
|
||||
item.score = fuzzySequentialMatch(filter, item);
|
||||
return item;
|
||||
@ -81,4 +81,3 @@ export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) => {
|
||||
.sort(({ score: scoreA = 0 }, { score: scoreB = 0 }) =>
|
||||
scoreA > scoreB ? -1 : scoreA < scoreB ? 1 : 0
|
||||
);
|
||||
};
|
||||
|
||||
@ -2,8 +2,7 @@ export const afterNextRender = (cb: (value: unknown) => void): void => {
|
||||
requestAnimationFrame(() => setTimeout(cb, 0));
|
||||
};
|
||||
|
||||
export const nextRender = () => {
|
||||
return new Promise((resolve) => {
|
||||
export const nextRender = () =>
|
||||
new Promise((resolve) => {
|
||||
afterNextRender(resolve);
|
||||
});
|
||||
};
|
||||
|
||||
@ -485,9 +485,7 @@ export class HaDataTable extends LitElement {
|
||||
data: DataTableRowData[],
|
||||
columns: SortableColumnContainer,
|
||||
filter: string
|
||||
): Promise<DataTableRowData[]> => {
|
||||
return filterData(data, columns, filter);
|
||||
}
|
||||
): Promise<DataTableRowData[]> => filterData(data, columns, filter)
|
||||
);
|
||||
|
||||
private _handleHeaderClick(ev: Event) {
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { wrap } from "comlink";
|
||||
import type { api } from "./sort_filter_worker";
|
||||
import { Remote, wrap } from "comlink";
|
||||
import type { Api } from "./sort_filter_worker";
|
||||
|
||||
type FilterDataType = api["filterData"];
|
||||
type FilterDataType = Api["filterData"];
|
||||
type FilterDataParamTypes = Parameters<FilterDataType>;
|
||||
|
||||
type SortDataType = api["sortData"];
|
||||
type SortDataType = Api["sortData"];
|
||||
type SortDataParamTypes = Parameters<SortDataType>;
|
||||
|
||||
let worker: any | undefined;
|
||||
let worker: Remote<Api> | undefined;
|
||||
|
||||
export const filterData = async (
|
||||
data: FilterDataParamTypes[0],
|
||||
@ -18,7 +18,7 @@ export const filterData = async (
|
||||
worker = wrap(new Worker(new URL("./sort_filter_worker", import.meta.url)));
|
||||
}
|
||||
|
||||
return await worker.filterData(data, columns, filter);
|
||||
return worker.filterData(data, columns, filter);
|
||||
};
|
||||
|
||||
export const sortData = async (
|
||||
@ -31,5 +31,5 @@ export const sortData = async (
|
||||
worker = wrap(new Worker(new URL("./sort_filter_worker", import.meta.url)));
|
||||
}
|
||||
|
||||
return await worker.sortData(data, columns, direction, sortColumn);
|
||||
return worker.sortData(data, columns, direction, sortColumn);
|
||||
};
|
||||
|
||||
@ -14,8 +14,8 @@ const filterData = (
|
||||
filter: string
|
||||
) => {
|
||||
filter = filter.toUpperCase();
|
||||
return data.filter((row) => {
|
||||
return Object.entries(columns).some((columnEntry) => {
|
||||
return data.filter((row) =>
|
||||
Object.entries(columns).some((columnEntry) => {
|
||||
const [key, column] = columnEntry;
|
||||
if (column.filterable) {
|
||||
if (
|
||||
@ -27,8 +27,8 @@ const filterData = (
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const sortData = (
|
||||
@ -80,6 +80,6 @@ const api = {
|
||||
sortData,
|
||||
};
|
||||
|
||||
export type api = typeof api;
|
||||
export type Api = typeof api;
|
||||
|
||||
expose(api);
|
||||
|
||||
@ -64,12 +64,8 @@ export abstract class HaDeviceAutomationPicker<
|
||||
private _createNoAutomation: (deviceId?: string) => T;
|
||||
|
||||
constructor(
|
||||
localizeDeviceAutomation: HaDeviceAutomationPicker<
|
||||
T
|
||||
>["_localizeDeviceAutomation"],
|
||||
fetchDeviceAutomations: HaDeviceAutomationPicker<
|
||||
T
|
||||
>["_fetchDeviceAutomations"],
|
||||
localizeDeviceAutomation: HaDeviceAutomationPicker<T>["_localizeDeviceAutomation"],
|
||||
fetchDeviceAutomations: HaDeviceAutomationPicker<T>["_fetchDeviceAutomations"],
|
||||
createNoAutomation: HaDeviceAutomationPicker<T>["_createNoAutomation"]
|
||||
) {
|
||||
super();
|
||||
|
||||
@ -8,9 +8,7 @@ import "../ha-paper-dropdown-menu";
|
||||
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
||||
|
||||
@customElement("ha-device-condition-picker")
|
||||
class HaDeviceConditionPicker extends HaDeviceAutomationPicker<
|
||||
DeviceCondition
|
||||
> {
|
||||
class HaDeviceConditionPicker extends HaDeviceAutomationPicker<DeviceCondition> {
|
||||
protected get NO_AUTOMATION_TEXT() {
|
||||
return this.hass.localize(
|
||||
"ui.panel.config.devices.automation.conditions.no_conditions"
|
||||
|
||||
@ -212,19 +212,17 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
);
|
||||
}
|
||||
|
||||
const outputDevices = inputDevices.map((device) => {
|
||||
return {
|
||||
id: device.id,
|
||||
name: computeDeviceName(
|
||||
device,
|
||||
this.hass,
|
||||
deviceEntityLookup[device.id]
|
||||
),
|
||||
area: device.area_id
|
||||
? areaLookup[device.area_id].name
|
||||
: this.hass.localize("ui.components.device-picker.no_area"),
|
||||
};
|
||||
});
|
||||
const outputDevices = inputDevices.map((device) => ({
|
||||
id: device.id,
|
||||
name: computeDeviceName(
|
||||
device,
|
||||
this.hass,
|
||||
deviceEntityLookup[device.id]
|
||||
),
|
||||
area: device.area_id
|
||||
? areaLookup[device.area_id].name
|
||||
: this.hass.localize("ui.components.device-picker.no_area"),
|
||||
}));
|
||||
if (!outputDevices.length) {
|
||||
return [
|
||||
{
|
||||
|
||||
@ -4,9 +4,9 @@ import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class";
|
||||
import type { Constructor } from "../../types";
|
||||
import { HaIronFocusablesHelper } from "./ha-iron-focusables-helper";
|
||||
|
||||
const paperDialogClass = customElements.get("paper-dialog") as Constructor<
|
||||
PaperDialogElement
|
||||
>;
|
||||
const paperDialogClass = customElements.get(
|
||||
"paper-dialog"
|
||||
) as Constructor<PaperDialogElement>;
|
||||
|
||||
// behavior that will override existing iron-overlay-behavior and call the fixed implementation
|
||||
const haTabFixBehaviorImpl = {
|
||||
|
||||
@ -57,9 +57,7 @@ export class HaAnalytics extends LitElement {
|
||||
>
|
||||
</ha-checkbox>
|
||||
</span>
|
||||
<span slot="heading" data-for="base">
|
||||
Basic analytics
|
||||
</span>
|
||||
<span slot="heading" data-for="base"> Basic analytics </span>
|
||||
<span slot="description" data-for="base">
|
||||
This includes information about your system.
|
||||
</span>
|
||||
@ -101,9 +99,7 @@ export class HaAnalytics extends LitElement {
|
||||
>
|
||||
</ha-checkbox>
|
||||
</span>
|
||||
<span slot="heading" data-for="diagnostics">
|
||||
Diagnostics
|
||||
</span>
|
||||
<span slot="heading" data-for="diagnostics"> Diagnostics </span>
|
||||
<span slot="description" data-for="diagnostics">
|
||||
Share crash reports when unexpected errors occur.
|
||||
</span>
|
||||
|
||||
@ -391,11 +391,9 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
`;
|
||||
}
|
||||
|
||||
private _area = memoizeOne((areaId: string):
|
||||
| AreaRegistryEntry
|
||||
| undefined => {
|
||||
return this._areas?.find((area) => area.area_id === areaId);
|
||||
});
|
||||
private _area = memoizeOne((areaId: string): AreaRegistryEntry | undefined =>
|
||||
this._areas?.find((area) => area.area_id === areaId)
|
||||
);
|
||||
|
||||
private _clearValue(ev: Event) {
|
||||
ev.stopPropagation();
|
||||
|
||||
@ -36,12 +36,8 @@ class HaAttributes extends LitElement {
|
||||
).map(
|
||||
(attribute) => html`
|
||||
<div class="data-entry">
|
||||
<div class="key">
|
||||
${formatAttributeName(attribute)}
|
||||
</div>
|
||||
<div class="value">
|
||||
${this.formatAttribute(attribute)}
|
||||
</div>
|
||||
<div class="key">${formatAttributeName(attribute)}</div>
|
||||
<div class="value">${this.formatAttribute(attribute)}</div>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
@ -92,9 +88,9 @@ class HaAttributes extends LitElement {
|
||||
if (!this.stateObj) {
|
||||
return [];
|
||||
}
|
||||
return Object.keys(this.stateObj.attributes).filter((key) => {
|
||||
return filtersArray.indexOf(key) === -1;
|
||||
});
|
||||
return Object.keys(this.stateObj.attributes).filter(
|
||||
(key) => filtersArray.indexOf(key) === -1
|
||||
);
|
||||
}
|
||||
|
||||
private formatAttribute(attribute: string): string | TemplateResult {
|
||||
|
||||
@ -45,16 +45,13 @@ const i18n = {
|
||||
clear: "Clear",
|
||||
today: "Today",
|
||||
cancel: "Cancel",
|
||||
formatTitle: (monthName, fullYear) => {
|
||||
return monthName + " " + fullYear;
|
||||
},
|
||||
formatDate: (d: { day: number; month: number; year: number }) => {
|
||||
return [
|
||||
formatTitle: (monthName, fullYear) => monthName + " " + fullYear,
|
||||
formatDate: (d: { day: number; month: number; year: number }) =>
|
||||
[
|
||||
("0000" + String(d.year)).slice(-4),
|
||||
("0" + String(d.month + 1)).slice(-2),
|
||||
("0" + String(d.day)).slice(-2),
|
||||
].join("-");
|
||||
},
|
||||
].join("-"),
|
||||
parseDate: (text: string) => {
|
||||
const parts = text.split("-");
|
||||
const today = new Date();
|
||||
|
||||
@ -88,9 +88,7 @@ export class HaDateRangePicker extends LitElement {
|
||||
>
|
||||
<mwc-list @action=${this._setDateRange} activatable>
|
||||
${Object.keys(this.ranges).map(
|
||||
(name) => html`<mwc-list-item>
|
||||
${name}
|
||||
</mwc-list-item>`
|
||||
(name) => html`<mwc-list-item> ${name} </mwc-list-item>`
|
||||
)}
|
||||
</mwc-list>
|
||||
</div>`
|
||||
|
||||
@ -28,9 +28,7 @@ export class HaDialog extends MwcDialog {
|
||||
}
|
||||
|
||||
protected renderHeading() {
|
||||
return html`<slot name="heading">
|
||||
${super.renderHeading()}
|
||||
</slot>`;
|
||||
return html`<slot name="heading"> ${super.renderHeading()} </slot>`;
|
||||
}
|
||||
|
||||
protected static get styles(): CSSResult[] {
|
||||
|
||||
@ -79,9 +79,7 @@ export class HaFileUpload extends LitElement {
|
||||
dragged: this._drag,
|
||||
})}
|
||||
>
|
||||
<label for="input" slot="label">
|
||||
${this.label}
|
||||
</label>
|
||||
<label for="input" slot="label"> ${this.label} </label>
|
||||
<iron-input slot="input">
|
||||
<input
|
||||
id="input"
|
||||
|
||||
@ -80,20 +80,22 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
@selected-items-changed=${this._valueChanged}
|
||||
@iron-select=${this._onSelect}
|
||||
>
|
||||
${// TS doesn't work with union array types https://github.com/microsoft/TypeScript/issues/36390
|
||||
// @ts-ignore
|
||||
options.map((item: string | [string, string]) => {
|
||||
const value = this._optionValue(item);
|
||||
return html`
|
||||
<paper-icon-item .itemValue=${value}>
|
||||
<paper-checkbox
|
||||
.checked=${data.includes(value)}
|
||||
slot="item-icon"
|
||||
></paper-checkbox>
|
||||
${this._optionLabel(item)}
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})}
|
||||
${
|
||||
// TS doesn't work with union array types https://github.com/microsoft/TypeScript/issues/36390
|
||||
// @ts-ignore
|
||||
options.map((item: string | [string, string]) => {
|
||||
const value = this._optionValue(item);
|
||||
return html`
|
||||
<paper-icon-item .itemValue=${value}>
|
||||
<paper-checkbox
|
||||
.checked=${data.includes(value)}
|
||||
slot="item-icon"
|
||||
></paper-checkbox>
|
||||
${this._optionLabel(item)}
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})
|
||||
}
|
||||
</paper-listbox>
|
||||
</paper-menu-button>
|
||||
`;
|
||||
|
||||
@ -41,15 +41,17 @@ export class HaFormSelect extends LitElement implements HaFormElement {
|
||||
.selected=${this.data}
|
||||
@selected-item-changed=${this._valueChanged}
|
||||
>
|
||||
${// TS doesn't work with union array types https://github.com/microsoft/TypeScript/issues/36390
|
||||
// @ts-ignore
|
||||
this.schema.options!.map(
|
||||
(item: string | [string, string]) => html`
|
||||
<paper-item .itemValue=${this._optionValue(item)}>
|
||||
${this._optionLabel(item)}
|
||||
</paper-item>
|
||||
`
|
||||
)}
|
||||
${
|
||||
// TS doesn't work with union array types https://github.com/microsoft/TypeScript/issues/36390
|
||||
// @ts-ignore
|
||||
this.schema.options!.map(
|
||||
(item: string | [string, string]) => html`
|
||||
<paper-item .itemValue=${this._optionValue(item)}>
|
||||
${this._optionLabel(item)}
|
||||
</paper-item>
|
||||
`
|
||||
)
|
||||
}
|
||||
</paper-listbox>
|
||||
</ha-paper-dropdown-menu>
|
||||
`;
|
||||
|
||||
@ -4,9 +4,9 @@ import { style } from "@material/mwc-formfield/mwc-formfield-css";
|
||||
import { css, CSSResult, customElement } from "lit-element";
|
||||
import { Constructor } from "../types";
|
||||
|
||||
const MwcFormfield = customElements.get("mwc-formfield") as Constructor<
|
||||
Formfield
|
||||
>;
|
||||
const MwcFormfield = customElements.get(
|
||||
"mwc-formfield"
|
||||
) as Constructor<Formfield>;
|
||||
|
||||
@customElement("ha-formfield")
|
||||
export class HaFormfield extends MwcFormfield {
|
||||
|
||||
@ -36,9 +36,7 @@ export class HaSelectSelector extends LitElement {
|
||||
>
|
||||
${this.selector.select.options.map(
|
||||
(item: string) => html`
|
||||
<paper-item .itemValue=${item}>
|
||||
${item}
|
||||
</paper-item>
|
||||
<paper-item .itemValue=${item}> ${item} </paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
|
||||
@ -140,13 +140,11 @@ export class HaServiceControl extends LitElement {
|
||||
|
||||
const fields = Object.entries(
|
||||
serviceDomains[domain][serviceName].fields
|
||||
).map(([key, value]) => {
|
||||
return {
|
||||
key,
|
||||
...value,
|
||||
selector: value.selector as Selector | undefined,
|
||||
};
|
||||
});
|
||||
).map(([key, value]) => ({
|
||||
key,
|
||||
...value,
|
||||
selector: value.selector as Selector | undefined,
|
||||
}));
|
||||
return {
|
||||
...serviceDomains[domain][serviceName],
|
||||
fields,
|
||||
|
||||
@ -5,9 +5,9 @@ import type { PaperTabsElement } from "@polymer/paper-tabs/paper-tabs";
|
||||
import { customElement } from "lit-element";
|
||||
import { Constructor } from "../types";
|
||||
|
||||
const PaperTabs = customElements.get("paper-tabs") as Constructor<
|
||||
PaperTabsElement
|
||||
>;
|
||||
const PaperTabs = customElements.get(
|
||||
"paper-tabs"
|
||||
) as Constructor<PaperTabsElement>;
|
||||
|
||||
let subTemplate: HTMLTemplateElement;
|
||||
|
||||
|
||||
@ -2,9 +2,9 @@ import "@polymer/paper-toast/paper-toast";
|
||||
import type { PaperToastElement } from "@polymer/paper-toast/paper-toast";
|
||||
import type { Constructor } from "../types";
|
||||
|
||||
const PaperToast = customElements.get("paper-toast") as Constructor<
|
||||
PaperToastElement
|
||||
>;
|
||||
const PaperToast = customElements.get(
|
||||
"paper-toast"
|
||||
) as Constructor<PaperToastElement>;
|
||||
|
||||
export class HaToast extends PaperToast {
|
||||
private _resizeListener?: (obj: { matches: boolean }) => unknown;
|
||||
|
||||
@ -122,9 +122,7 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
});
|
||||
} else {
|
||||
return html`
|
||||
<div class="container">
|
||||
${this._renderError(this._error)}
|
||||
</div>
|
||||
<div class="container">${this._renderError(this._error)}</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@ -202,13 +200,7 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
`
|
||||
: ""}
|
||||
<h1 class="title">${currentItem.title}</h1>
|
||||
${subtitle
|
||||
? html`
|
||||
<h2 class="subtitle">
|
||||
${subtitle}
|
||||
</h2>
|
||||
`
|
||||
: ""}
|
||||
${subtitle ? html` <h2 class="subtitle">${subtitle}</h2> ` : ""}
|
||||
</div>
|
||||
${currentItem.can_play && (!currentItem.thumbnail || !this._narrow)
|
||||
? html`
|
||||
@ -247,9 +239,7 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
<div class="content" @scroll=${this._scroll} @touchmove=${this._scroll}>
|
||||
${this._error
|
||||
? html`
|
||||
<div class="container">
|
||||
${this._renderError(this._error)}
|
||||
</div>
|
||||
<div class="container">${this._renderError(this._error)}</div>
|
||||
`
|
||||
: currentItem.children?.length
|
||||
? childrenMediaClass.layout === "grid"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { Trigger, Condition } from "./automation";
|
||||
|
||||
export const describeTrigger = (trigger: Trigger) => {
|
||||
return `${trigger.platform} trigger`;
|
||||
};
|
||||
export const describeTrigger = (trigger: Trigger) =>
|
||||
`${trigger.platform} trigger`;
|
||||
|
||||
export const describeCondition = (condition: Condition) => {
|
||||
if (condition.alias) {
|
||||
|
||||
@ -6,11 +6,12 @@ export const subscribeBootstrapIntegrations = (
|
||||
hass: HomeAssistant,
|
||||
callback: (message: BootstrapIntegrationsTimings) => void
|
||||
) => {
|
||||
const unsubProm = hass.connection.subscribeMessage<
|
||||
BootstrapIntegrationsTimings
|
||||
>((message) => callback(message), {
|
||||
type: "subscribe_bootstrap_integrations",
|
||||
});
|
||||
const unsubProm = hass.connection.subscribeMessage<BootstrapIntegrationsTimings>(
|
||||
(message) => callback(message),
|
||||
{
|
||||
type: "subscribe_bootstrap_integrations",
|
||||
}
|
||||
);
|
||||
|
||||
return unsubProm;
|
||||
};
|
||||
|
||||
@ -74,8 +74,8 @@ const getCalendarDate = (dateObj: any): string | undefined => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getCalendars = (hass: HomeAssistant): Calendar[] => {
|
||||
return Object.keys(hass.states)
|
||||
export const getCalendars = (hass: HomeAssistant): Calendar[] =>
|
||||
Object.keys(hass.states)
|
||||
.filter((eid) => computeDomain(eid) === "calendar")
|
||||
.sort()
|
||||
.map((eid, idx) => ({
|
||||
@ -83,4 +83,3 @@ export const getCalendars = (hass: HomeAssistant): Calendar[] => {
|
||||
name: computeStateName(hass.states[eid]),
|
||||
backgroundColor: `#${HA_COLOR_PALETTE[idx % HA_COLOR_PALETTE.length]}`,
|
||||
}));
|
||||
};
|
||||
|
||||
@ -48,14 +48,11 @@ export const computeDeviceName = (
|
||||
device: DeviceRegistryEntry,
|
||||
hass: HomeAssistant,
|
||||
entities?: EntityRegistryEntry[] | string[]
|
||||
) => {
|
||||
return (
|
||||
device.name_by_user ||
|
||||
device.name ||
|
||||
(entities && fallbackDeviceName(hass, entities)) ||
|
||||
hass.localize("ui.panel.config.devices.unnamed_device")
|
||||
);
|
||||
};
|
||||
) =>
|
||||
device.name_by_user ||
|
||||
device.name ||
|
||||
(entities && fallbackDeviceName(hass, entities)) ||
|
||||
hass.localize("ui.panel.config.devices.unnamed_device");
|
||||
|
||||
export const devicesInArea = (devices: DeviceRegistryEntry[], areaId: string) =>
|
||||
devices.filter((device) => device.area_id === areaId);
|
||||
|
||||
@ -9,9 +9,7 @@ export interface DiscoveryInformation {
|
||||
version: string;
|
||||
}
|
||||
|
||||
export const fetchDiscoveryInformation = async (): Promise<
|
||||
DiscoveryInformation
|
||||
> => {
|
||||
export const fetchDiscoveryInformation = async (): Promise<DiscoveryInformation> => {
|
||||
const response = await fetch("/api/discovery_info", { method: "GET" });
|
||||
return await response.json();
|
||||
return response.json();
|
||||
};
|
||||
|
||||
@ -135,7 +135,7 @@ export const fetchHassioAddonsInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioAddonsInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/addons",
|
||||
method: "get",
|
||||
@ -152,7 +152,7 @@ export const fetchHassioAddonInfo = async (
|
||||
slug: string
|
||||
): Promise<HassioAddonDetails> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/addons/${slug}/info`,
|
||||
method: "get",
|
||||
@ -170,23 +170,15 @@ export const fetchHassioAddonInfo = async (
|
||||
export const fetchHassioAddonChangelog = async (
|
||||
hass: HomeAssistant,
|
||||
slug: string
|
||||
) => {
|
||||
return hass.callApi<string>("GET", `hassio/addons/${slug}/changelog`);
|
||||
};
|
||||
) => hass.callApi<string>("GET", `hassio/addons/${slug}/changelog`);
|
||||
|
||||
export const fetchHassioAddonLogs = async (
|
||||
hass: HomeAssistant,
|
||||
slug: string
|
||||
) => {
|
||||
return hass.callApi<string>("GET", `hassio/addons/${slug}/logs`);
|
||||
};
|
||||
export const fetchHassioAddonLogs = async (hass: HomeAssistant, slug: string) =>
|
||||
hass.callApi<string>("GET", `hassio/addons/${slug}/logs`);
|
||||
|
||||
export const fetchHassioAddonDocumentation = async (
|
||||
hass: HomeAssistant,
|
||||
slug: string
|
||||
) => {
|
||||
return hass.callApi<string>("GET", `hassio/addons/${slug}/documentation`);
|
||||
};
|
||||
) => hass.callApi<string>("GET", `hassio/addons/${slug}/documentation`);
|
||||
|
||||
export const setHassioAddonOption = async (
|
||||
hass: HomeAssistant,
|
||||
@ -215,7 +207,7 @@ export const validateHassioAddonOption = async (
|
||||
slug: string
|
||||
): Promise<{ message: string; valid: boolean }> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/addons/${slug}/options/validate`,
|
||||
method: "post",
|
||||
@ -232,7 +224,7 @@ export const validateHassioAddonOption = async (
|
||||
|
||||
export const startHassioAddon = async (hass: HomeAssistant, slug: string) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/addons/${slug}/start`,
|
||||
method: "post",
|
||||
@ -245,7 +237,7 @@ export const startHassioAddon = async (hass: HomeAssistant, slug: string) => {
|
||||
|
||||
export const stopHassioAddon = async (hass: HomeAssistant, slug: string) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/addons/${slug}/stop`,
|
||||
method: "post",
|
||||
|
||||
@ -20,13 +20,12 @@ export interface HassioStats {
|
||||
export const hassioApiResultExtractor = <T>(response: HassioResponse<T>) =>
|
||||
response.data;
|
||||
|
||||
export const extractApiErrorMessage = (error: any): string => {
|
||||
return typeof error === "object"
|
||||
export const extractApiErrorMessage = (error: any): string =>
|
||||
typeof error === "object"
|
||||
? typeof error.body === "object"
|
||||
? error.body.message || "Unknown error, see supervisor logs"
|
||||
: error.body || error.message || "Unknown error, see supervisor logs"
|
||||
: error;
|
||||
};
|
||||
|
||||
const ignoredStatusCodes = new Set([502, 503, 504]);
|
||||
|
||||
@ -50,7 +49,7 @@ export const fetchHassioStats = async (
|
||||
container: string
|
||||
): Promise<HassioStats> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/${container}/stats`,
|
||||
method: "get",
|
||||
|
||||
@ -10,7 +10,7 @@ export const fetchHassioDockerRegistries = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioDockerRegistries> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/docker/registries`,
|
||||
method: "get",
|
||||
|
||||
@ -26,7 +26,7 @@ export const fetchHassioHardwareAudio = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioHardwareAudioList> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/hardware/audio`,
|
||||
method: "get",
|
||||
@ -45,7 +45,7 @@ export const fetchHassioHardwareInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioHardwareInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/hardware/info`,
|
||||
method: "get",
|
||||
|
||||
@ -28,7 +28,7 @@ export const fetchHassioHostInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioHostInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/host/info",
|
||||
method: "get",
|
||||
@ -46,7 +46,7 @@ export const fetchHassioHassOsInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioHassOSInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/os/info",
|
||||
method: "get",
|
||||
@ -63,7 +63,7 @@ export const fetchHassioHassOsInfo = async (
|
||||
|
||||
export const rebootHost = async (hass: HomeAssistant) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/host/reboot",
|
||||
method: "post",
|
||||
@ -76,7 +76,7 @@ export const rebootHost = async (hass: HomeAssistant) => {
|
||||
|
||||
export const shutdownHost = async (hass: HomeAssistant) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/host/shutdown",
|
||||
method: "post",
|
||||
@ -89,7 +89,7 @@ export const shutdownHost = async (hass: HomeAssistant) => {
|
||||
|
||||
export const updateOS = async (hass: HomeAssistant) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/os/update",
|
||||
method: "post",
|
||||
@ -102,7 +102,7 @@ export const updateOS = async (hass: HomeAssistant) => {
|
||||
|
||||
export const configSyncOS = async (hass: HomeAssistant) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/os/config/sync",
|
||||
method: "post",
|
||||
@ -115,7 +115,7 @@ export const configSyncOS = async (hass: HomeAssistant) => {
|
||||
|
||||
export const changeHostOptions = async (hass: HomeAssistant, options: any) => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/host/options",
|
||||
method: "post",
|
||||
|
||||
@ -56,7 +56,7 @@ export const fetchNetworkInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<NetworkInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/network/info",
|
||||
method: "get",
|
||||
@ -99,7 +99,7 @@ export const accesspointScan = async (
|
||||
network_interface: string
|
||||
): Promise<AccessPoints> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/network/interface/${network_interface}/accesspoints`,
|
||||
method: "get",
|
||||
|
||||
@ -13,7 +13,7 @@ export const fetchHassioResolution = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioResolution> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/resolution/info",
|
||||
method: "get",
|
||||
|
||||
@ -61,7 +61,7 @@ export const fetchHassioSnapshotInfo = async (
|
||||
): Promise<HassioSnapshotDetail> => {
|
||||
if (hass) {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: `/snapshots/${snapshot}/info`,
|
||||
method: "get",
|
||||
@ -163,5 +163,5 @@ export const uploadSnapshot = async (
|
||||
} else if (resp.status !== 200) {
|
||||
throw new Error(`${resp.status} ${resp.statusText}`);
|
||||
}
|
||||
return await resp.json();
|
||||
return resp.json();
|
||||
};
|
||||
|
||||
@ -128,7 +128,7 @@ export const fetchHassioHomeAssistantInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioHomeAssistantInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/core/info",
|
||||
method: "get",
|
||||
@ -147,7 +147,7 @@ export const fetchHassioSupervisorInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioSupervisorInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/supervisor/info",
|
||||
method: "get",
|
||||
@ -166,7 +166,7 @@ export const fetchHassioInfo = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<HassioInfo> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/info",
|
||||
method: "get",
|
||||
@ -178,12 +178,8 @@ export const fetchHassioInfo = async (
|
||||
);
|
||||
};
|
||||
|
||||
export const fetchHassioLogs = async (
|
||||
hass: HomeAssistant,
|
||||
provider: string
|
||||
) => {
|
||||
return hass.callApi<string>("GET", `hassio/${provider}/logs`);
|
||||
};
|
||||
export const fetchHassioLogs = async (hass: HomeAssistant, provider: string) =>
|
||||
hass.callApi<string>("GET", `hassio/${provider}/logs`);
|
||||
|
||||
export const setSupervisorOption = async (
|
||||
hass: HomeAssistant,
|
||||
|
||||
@ -88,14 +88,13 @@ export const fetchDate = (
|
||||
startTime: Date,
|
||||
endTime: Date,
|
||||
entityId
|
||||
): Promise<HassEntity[][]> => {
|
||||
return hass.callApi(
|
||||
): Promise<HassEntity[][]> =>
|
||||
hass.callApi(
|
||||
"GET",
|
||||
`history/period/${startTime.toISOString()}?end_time=${endTime.toISOString()}&minimal_response${
|
||||
entityId ? `&filter_entity_id=${entityId}` : ``
|
||||
}`
|
||||
);
|
||||
};
|
||||
|
||||
const equalState = (obj1: LineChartState, obj2: LineChartState) =>
|
||||
obj1.state === obj2.state &&
|
||||
|
||||
@ -33,7 +33,7 @@ export const createImage = async (
|
||||
} else if (resp.status !== 200) {
|
||||
throw new Error("Unknown error");
|
||||
}
|
||||
return await resp.json();
|
||||
return resp.json();
|
||||
};
|
||||
|
||||
export const updateImage = (
|
||||
|
||||
@ -36,25 +36,20 @@ export const SUPPORT_TRANSITION = 32;
|
||||
export const lightSupportsColorMode = (
|
||||
entity: LightEntity,
|
||||
mode: LightColorModes
|
||||
) => {
|
||||
return entity.attributes.supported_color_modes?.includes(mode);
|
||||
};
|
||||
) => entity.attributes.supported_color_modes?.includes(mode);
|
||||
|
||||
export const lightIsInColorMode = (entity: LightEntity) => {
|
||||
return modesSupportingColor.includes(entity.attributes.color_mode);
|
||||
};
|
||||
export const lightIsInColorMode = (entity: LightEntity) =>
|
||||
modesSupportingColor.includes(entity.attributes.color_mode);
|
||||
|
||||
export const lightSupportsColor = (entity: LightEntity) => {
|
||||
return entity.attributes.supported_color_modes?.some((mode) =>
|
||||
export const lightSupportsColor = (entity: LightEntity) =>
|
||||
entity.attributes.supported_color_modes?.some((mode) =>
|
||||
modesSupportingColor.includes(mode)
|
||||
);
|
||||
};
|
||||
|
||||
export const lightSupportsDimming = (entity: LightEntity) => {
|
||||
return entity.attributes.supported_color_modes?.some((mode) =>
|
||||
export const lightSupportsDimming = (entity: LightEntity) =>
|
||||
entity.attributes.supported_color_modes?.some((mode) =>
|
||||
modesSupportingDimming.includes(mode)
|
||||
);
|
||||
};
|
||||
|
||||
export const getLightCurrentModeRgbColor = (
|
||||
entity: LightEntity
|
||||
|
||||
@ -37,12 +37,11 @@ export const subscribeMQTTTopic = (
|
||||
hass: HomeAssistant,
|
||||
topic: string,
|
||||
callback: (message: MQTTMessage) => void
|
||||
) => {
|
||||
return hass.connection.subscribeMessage<MQTTMessage>(callback, {
|
||||
) =>
|
||||
hass.connection.subscribeMessage<MQTTMessage>(callback, {
|
||||
type: "mqtt/subscribe",
|
||||
topic,
|
||||
});
|
||||
};
|
||||
|
||||
export const removeMQTTDeviceEntry = (
|
||||
hass: HomeAssistant,
|
||||
|
||||
@ -38,7 +38,7 @@ export const fetchSupervisorStore = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<SupervisorStore> => {
|
||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||
return await hass.callWS({
|
||||
return hass.callWS({
|
||||
type: "supervisor/api",
|
||||
endpoint: "/store",
|
||||
method: "get",
|
||||
|
||||
@ -280,8 +280,7 @@ export const weatherSVGStyles = css`
|
||||
const getWeatherStateSVG = (
|
||||
state: string,
|
||||
nightTime?: boolean
|
||||
): SVGTemplateResult => {
|
||||
return svg`
|
||||
): SVGTemplateResult => svg`
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 17 17"
|
||||
@ -416,7 +415,6 @@ const getWeatherStateSVG = (
|
||||
: ""
|
||||
}
|
||||
</svg>`;
|
||||
};
|
||||
|
||||
export const getWeatherStateIcon = (
|
||||
state: string,
|
||||
|
||||
@ -21,9 +21,8 @@ export const subscribeRenderTemplate = (
|
||||
variables?: Record<string, unknown>;
|
||||
timeout?: number;
|
||||
}
|
||||
): Promise<UnsubscribeFunc> => {
|
||||
return conn.subscribeMessage((msg: RenderTemplateResult) => onChange(msg), {
|
||||
): Promise<UnsubscribeFunc> =>
|
||||
conn.subscribeMessage((msg: RenderTemplateResult) => onChange(msg), {
|
||||
type: "render_template",
|
||||
...params,
|
||||
});
|
||||
};
|
||||
|
||||
@ -136,15 +136,14 @@ export const reconfigureNode = (
|
||||
hass: HomeAssistant,
|
||||
ieeeAddress: string,
|
||||
callbackFunction: (message: ClusterConfigurationEvent) => void
|
||||
) => {
|
||||
return hass.connection.subscribeMessage(
|
||||
) =>
|
||||
hass.connection.subscribeMessage(
|
||||
(message: ClusterConfigurationEvent) => callbackFunction(message),
|
||||
{
|
||||
type: "zha/devices/reconfigure",
|
||||
ieee: ieeeAddress,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const refreshTopology = (hass: HomeAssistant): Promise<void> =>
|
||||
hass.callWS({
|
||||
@ -240,12 +239,11 @@ export const unbindDeviceFromGroup = (
|
||||
export const readAttributeValue = (
|
||||
hass: HomeAssistant,
|
||||
data: ReadAttributeServiceData
|
||||
): Promise<string> => {
|
||||
return hass.callWS({
|
||||
): Promise<string> =>
|
||||
hass.callWS({
|
||||
...data,
|
||||
type: "zha/devices/clusters/attributes/value",
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchCommandsForCluster = (
|
||||
hass: HomeAssistant,
|
||||
|
||||
@ -162,8 +162,8 @@ export const reinterviewNode = (
|
||||
entry_id: string,
|
||||
node_id: number,
|
||||
callbackFunction: (message: ZWaveJSRefreshNodeStatusMessage) => void
|
||||
): Promise<UnsubscribeFunc> => {
|
||||
return hass.connection.subscribeMessage(
|
||||
): Promise<UnsubscribeFunc> =>
|
||||
hass.connection.subscribeMessage(
|
||||
(message: any) => callbackFunction(message),
|
||||
{
|
||||
type: "zwave_js/refresh_node_info",
|
||||
@ -171,7 +171,6 @@ export const reinterviewNode = (
|
||||
node_id: node_id,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getIdentifiersFromDevice = (
|
||||
device: DeviceRegistryEntry
|
||||
|
||||
@ -27,9 +27,7 @@ class StepFlowExternal extends LitElement {
|
||||
const localize = this.hass.localize;
|
||||
|
||||
return html`
|
||||
<h2>
|
||||
${this.flowConfig.renderExternalStepHeader(this.hass, this.step)}
|
||||
</h2>
|
||||
<h2>${this.flowConfig.renderExternalStepHeader(this.hass, this.step)}</h2>
|
||||
<div class="content">
|
||||
${this.flowConfig.renderExternalStepDescription(this.hass, this.step)}
|
||||
<div class="open-button">
|
||||
|
||||
@ -55,9 +55,7 @@ class StepFlowForm extends LitElement {
|
||||
);
|
||||
|
||||
return html`
|
||||
<h2>
|
||||
${this.flowConfig.renderShowFormStepHeader(this.hass, this.step)}
|
||||
</h2>
|
||||
<h2>${this.flowConfig.renderShowFormStepHeader(this.hass, this.step)}</h2>
|
||||
<div class="content">
|
||||
${this._errorMsg
|
||||
? html` <div class="error">${this._errorMsg}</div> `
|
||||
|
||||
@ -54,12 +54,10 @@ class StepFlowPickHandler extends LitElement {
|
||||
|
||||
private _getHandlers = memoizeOne(
|
||||
(h: string[], filter?: string, _localize?: LocalizeFunc) => {
|
||||
const handlers: HandlerObj[] = h.map((handler) => {
|
||||
return {
|
||||
name: domainToName(this.hass.localize, handler),
|
||||
slug: handler,
|
||||
};
|
||||
});
|
||||
const handlers: HandlerObj[] = h.map((handler) => ({
|
||||
name: domainToName(this.hass.localize, handler),
|
||||
slug: handler,
|
||||
}));
|
||||
|
||||
if (filter) {
|
||||
const options: Fuse.IFuseOptions<HandlerObj> = {
|
||||
@ -113,9 +111,7 @@ class StepFlowPickHandler extends LitElement {
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
|
||||
<paper-item-body>
|
||||
${handler.name}
|
||||
</paper-item-body>
|
||||
<paper-item-body> ${handler.name} </paper-item-body>
|
||||
<ha-icon-next></ha-icon-next>
|
||||
</paper-icon-item>
|
||||
`
|
||||
|
||||
@ -19,7 +19,8 @@ import { HassDialog } from "../make-dialog-manager";
|
||||
import { HaDomainTogglerDialogParams } from "./show-dialog-domain-toggler";
|
||||
|
||||
@customElement("dialog-domain-toggler")
|
||||
class DomainTogglerDialog extends LitElement
|
||||
class DomainTogglerDialog
|
||||
extends LitElement
|
||||
implements HassDialog<HaDomainTogglerDialogParams> {
|
||||
public hass!: HomeAssistant;
|
||||
|
||||
|
||||
@ -78,9 +78,9 @@ export const showConfirmationDialog = (
|
||||
element: HTMLElement,
|
||||
dialogParams: ConfirmationDialogParams
|
||||
) =>
|
||||
showDialogHelper(element, dialogParams, { confirmation: true }) as Promise<
|
||||
boolean
|
||||
>;
|
||||
showDialogHelper(element, dialogParams, {
|
||||
confirmation: true,
|
||||
}) as Promise<boolean>;
|
||||
|
||||
export const showPromptDialog = (
|
||||
element: HTMLElement,
|
||||
|
||||
@ -51,9 +51,7 @@ class MoreInfoHumidifier extends LitElement {
|
||||
<div class="container-humidity">
|
||||
<div>${hass.localize("ui.card.humidifier.humidity")}</div>
|
||||
<div class="single-row">
|
||||
<div class="target-humidity">
|
||||
${stateObj.attributes.humidity} %
|
||||
</div>
|
||||
<div class="target-humidity">${stateObj.attributes.humidity} %</div>
|
||||
<ha-slider
|
||||
class="humidity"
|
||||
step="1"
|
||||
|
||||
@ -46,9 +46,7 @@ class MoreInfoRemote extends LitElement {
|
||||
>
|
||||
${stateObj.attributes.activity_list!.map(
|
||||
(activity) => html`
|
||||
<paper-item .itemName=${activity}>
|
||||
${activity}
|
||||
</paper-item>
|
||||
<paper-item .itemName=${activity}> ${activity} </paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
|
||||
@ -29,8 +29,8 @@ class MoreInfoSun extends LitElement {
|
||||
const order = risingDate > settingDate ? ["set", "ris"] : ["ris", "set"];
|
||||
|
||||
return html`
|
||||
${order.map((item) => {
|
||||
return html`
|
||||
${order.map(
|
||||
(item) => html`
|
||||
<div class="row">
|
||||
<div class="key">
|
||||
<span
|
||||
@ -54,8 +54,8 @@ class MoreInfoSun extends LitElement {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
<div class="row">
|
||||
<div class="key">
|
||||
${this.hass.localize("ui.dialogs.more_info_control.sun.elevation")}
|
||||
|
||||
@ -177,9 +177,7 @@ class MoreInfoVacuum extends LitElement {
|
||||
>
|
||||
${stateObj.attributes.fan_speed_list!.map(
|
||||
(mode) => html`
|
||||
<paper-item .itemName=${mode}>
|
||||
${mode}
|
||||
</paper-item>
|
||||
<paper-item .itemName=${mode}> ${mode} </paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
|
||||
@ -169,8 +169,8 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="section">
|
||||
${this.hass.localize("ui.card.weather.forecast")}:
|
||||
</div>
|
||||
${this.stateObj.attributes.forecast.map((item) => {
|
||||
return html`
|
||||
${this.stateObj.attributes.forecast.map(
|
||||
(item) => html`
|
||||
<div class="flex">
|
||||
${item.condition
|
||||
? html`
|
||||
@ -210,8 +210,8 @@ class MoreInfoWeather extends LitElement {
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.attribution
|
||||
|
||||
@ -29,9 +29,7 @@ export class HuiPersistentNotificationItem extends LitElement {
|
||||
|
||||
return html`
|
||||
<notification-item-template>
|
||||
<span slot="header">
|
||||
${this.notification.title}
|
||||
</span>
|
||||
<span slot="header"> ${this.notification.title} </span>
|
||||
|
||||
<ha-markdown
|
||||
breaks
|
||||
|
||||
@ -70,9 +70,8 @@ interface EntityItem extends QuickBarItem {
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
const isCommandItem = (item: QuickBarItem): item is CommandItem => {
|
||||
return (item as CommandItem).categoryKey !== undefined;
|
||||
};
|
||||
const isCommandItem = (item: QuickBarItem): item is CommandItem =>
|
||||
(item as CommandItem).categoryKey !== undefined;
|
||||
|
||||
interface QuickBarNavigationItem extends CommandItem {
|
||||
path: string;
|
||||
@ -579,9 +578,8 @@ export class QuickBar extends LitElement {
|
||||
}
|
||||
|
||||
private _filterItems = memoizeOne(
|
||||
(items: QuickBarItem[], filter: string): QuickBarItem[] => {
|
||||
return fuzzyFilterSort<QuickBarItem>(filter.trimLeft(), items);
|
||||
}
|
||||
(items: QuickBarItem[], filter: string): QuickBarItem[] =>
|
||||
fuzzyFilterSort<QuickBarItem>(filter.trimLeft(), items)
|
||||
);
|
||||
|
||||
static get styles() {
|
||||
|
||||
@ -197,9 +197,7 @@ export class HaTabsSubpageDataTable extends LitElement {
|
||||
? html`
|
||||
<div slot="header">
|
||||
<slot name="header">
|
||||
<div class="search-toolbar">
|
||||
${headerToolbar}
|
||||
</div>
|
||||
<div class="search-toolbar">${headerToolbar}</div>
|
||||
</slot>
|
||||
</div>
|
||||
`
|
||||
@ -220,9 +218,7 @@ export class HaTabsSubpageDataTable extends LitElement {
|
||||
? html`
|
||||
<div slot="header">
|
||||
<slot name="header">
|
||||
<div class="table-header">
|
||||
${headerToolbar}
|
||||
</div>
|
||||
<div class="table-header">${headerToolbar}</div>
|
||||
</slot>
|
||||
</div>
|
||||
`
|
||||
|
||||
@ -47,9 +47,7 @@ class SupervisorErrorScreen extends LitElement {
|
||||
<ha-card header="Troubleshooting">
|
||||
<div class="card-content">
|
||||
<ol>
|
||||
<li>
|
||||
${this.hass.localize("ui.errors.supervisor.wait")}
|
||||
</li>
|
||||
<li>${this.hass.localize("ui.errors.supervisor.wait")}</li>
|
||||
<li>
|
||||
<a
|
||||
class="supervisor_error-link"
|
||||
@ -60,9 +58,7 @@ class SupervisorErrorScreen extends LitElement {
|
||||
${this.hass.localize("ui.errors.supervisor.observer")}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
${this.hass.localize("ui.errors.supervisor.reboot")}
|
||||
</li>
|
||||
<li>${this.hass.localize("ui.errors.supervisor.reboot")}</li>
|
||||
<li>
|
||||
<a href="/config/info" target="_parent">
|
||||
${this.hass.localize("ui.errors.supervisor.system_health")}
|
||||
|
||||
@ -132,9 +132,7 @@ export class HAFullCalendar extends LitElement {
|
||||
>
|
||||
</ha-icon-button>
|
||||
</div>
|
||||
<h1>
|
||||
${this.calendar.view.title}
|
||||
</h1>
|
||||
<h1>${this.calendar.view.title}</h1>
|
||||
<ha-button-toggle-group
|
||||
.buttons=${viewToggleButtons}
|
||||
.active=${this._activeView}
|
||||
@ -143,9 +141,7 @@ export class HAFullCalendar extends LitElement {
|
||||
`
|
||||
: html`
|
||||
<div class="controls">
|
||||
<h1>
|
||||
${this.calendar.view.title}
|
||||
</h1>
|
||||
<h1>${this.calendar.view.title}</h1>
|
||||
<div>
|
||||
<ha-icon-button
|
||||
label=${this.hass.localize("ui.common.previous")}
|
||||
@ -368,7 +364,7 @@ export class HAFullCalendar extends LitElement {
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.fc-theme-standard .fc-scrollgrid {
|
||||
@ -387,7 +383,7 @@ export class HAFullCalendar extends LitElement {
|
||||
}
|
||||
|
||||
.fc-daygrid-dot-event:hover {
|
||||
background-color: inherit
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.fc-daygrid-day-top {
|
||||
@ -409,7 +405,7 @@ export class HAFullCalendar extends LitElement {
|
||||
}
|
||||
|
||||
.fc .fc-daygrid-day-number {
|
||||
padding: 3px !important;
|
||||
padding: 3px !important;
|
||||
}
|
||||
|
||||
.fc .fc-daygrid-day.fc-day-today {
|
||||
@ -494,17 +490,22 @@ export class HAFullCalendar extends LitElement {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
:host([narrow]) .fc-dayGridMonth-view
|
||||
:host([narrow])
|
||||
.fc-dayGridMonth-view
|
||||
.fc-daygrid-dot-event
|
||||
.fc-event-time,
|
||||
:host([narrow]) .fc-dayGridMonth-view
|
||||
:host([narrow])
|
||||
.fc-dayGridMonth-view
|
||||
.fc-daygrid-dot-event
|
||||
.fc-event-title,
|
||||
:host([narrow]) .fc-dayGridMonth-view .fc-daygrid-day-bottom {
|
||||
:host([narrow]) .fc-dayGridMonth-view .fc-daygrid-day-bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host([narrow]) .fc .fc-dayGridMonth-view .fc-daygrid-event-harness-abs {
|
||||
:host([narrow])
|
||||
.fc
|
||||
.fc-dayGridMonth-view
|
||||
.fc-daygrid-event-harness-abs {
|
||||
visibility: visible !important;
|
||||
position: static;
|
||||
}
|
||||
|
||||
@ -136,13 +136,7 @@ class HaConfigAreaPage extends LitElement {
|
||||
.tabs=${configSections.integrations}
|
||||
.route=${this.route}
|
||||
>
|
||||
${this.narrow
|
||||
? html`
|
||||
<span slot="header">
|
||||
${area.name}
|
||||
</span>
|
||||
`
|
||||
: ""}
|
||||
${this.narrow ? html` <span slot="header"> ${area.name} </span> ` : ""}
|
||||
|
||||
<ha-icon-button
|
||||
slot="toolbar-icon"
|
||||
|
||||
@ -58,8 +58,8 @@ export class HaConfigAreasDashboard extends LitElement {
|
||||
areas: AreaRegistryEntry[],
|
||||
devices: DeviceRegistryEntry[],
|
||||
entities: EntityRegistryEntry[]
|
||||
) => {
|
||||
return areas.map((area) => {
|
||||
) =>
|
||||
areas.map((area) => {
|
||||
const devicesInArea = new Set();
|
||||
|
||||
for (const device of devices) {
|
||||
@ -85,8 +85,7 @@ export class HaConfigAreasDashboard extends LitElement {
|
||||
devices: devicesInArea.size,
|
||||
entities: entitiesInArea,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
private _columns = memoizeOne(
|
||||
|
||||
@ -52,9 +52,7 @@ const OPTIONS = [
|
||||
"device_id",
|
||||
];
|
||||
|
||||
const getType = (action: Action) => {
|
||||
return OPTIONS.find((option) => option in action);
|
||||
};
|
||||
const getType = (action: Action) => OPTIONS.find((option) => option in action);
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
|
||||
@ -19,9 +19,7 @@ import { ActionElement } from "../ha-automation-action-row";
|
||||
|
||||
const OPTIONS = ["count", "while", "until"];
|
||||
|
||||
const getType = (action) => {
|
||||
return OPTIONS.find((option) => option in action);
|
||||
};
|
||||
const getType = (action) => OPTIONS.find((option) => option in action);
|
||||
|
||||
@customElement("ha-automation-action-repeat")
|
||||
export class HaRepeatAction extends LitElement implements ActionElement {
|
||||
|
||||
@ -10,7 +10,8 @@ import "../../trigger/ha-automation-trigger";
|
||||
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
||||
|
||||
@customElement("ha-automation-action-wait_for_trigger")
|
||||
export class HaWaitForTriggerAction extends LitElement
|
||||
export class HaWaitForTriggerAction
|
||||
extends LitElement
|
||||
implements ActionElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
|
||||
@ -73,13 +73,11 @@ class HaAutomationPicker extends LitElement {
|
||||
filteredAutomations!.includes(automation.entity_id)
|
||||
)
|
||||
: automations
|
||||
).map((automation) => {
|
||||
return {
|
||||
...automation,
|
||||
name: computeStateName(automation),
|
||||
last_triggered: automation.attributes.last_triggered || undefined,
|
||||
};
|
||||
});
|
||||
).map((automation) => ({
|
||||
...automation,
|
||||
name: computeStateName(automation),
|
||||
last_triggered: automation.attributes.last_triggered || undefined,
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -56,11 +56,10 @@ class HaConfigAutomation extends HassRouterPage {
|
||||
};
|
||||
|
||||
private _getAutomations = memoizeOne(
|
||||
(states: HassEntities): AutomationEntity[] => {
|
||||
return Object.values(states).filter(
|
||||
(states: HassEntities): AutomationEntity[] =>
|
||||
Object.values(states).filter(
|
||||
(entity) => computeStateDomain(entity) === "automation"
|
||||
) as AutomationEntity[];
|
||||
}
|
||||
) as AutomationEntity[]
|
||||
);
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
|
||||
@ -90,12 +90,8 @@ export class HaAutomationTrace extends LitElement {
|
||||
let devButtons: TemplateResult | string = "";
|
||||
if (__DEV__) {
|
||||
devButtons = html`<div style="position: absolute; right: 0;">
|
||||
<button @click=${this._importTrace}>
|
||||
Import trace
|
||||
</button>
|
||||
<button @click=${this._loadLocalStorageTrace}>
|
||||
Load stored trace
|
||||
</button>
|
||||
<button @click=${this._importTrace}>Import trace</button>
|
||||
<button @click=${this._loadLocalStorageTrace}>Load stored trace</button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@ -121,12 +117,8 @@ export class HaAutomationTrace extends LitElement {
|
||||
.tabs=${configSections.automation}
|
||||
>
|
||||
${this.narrow
|
||||
? html`<span slot="header">
|
||||
${title}
|
||||
</span>
|
||||
<div slot="toolbar-icon">
|
||||
${actionButtons}
|
||||
</div>`
|
||||
? html`<span slot="header"> ${title} </span>
|
||||
<div slot="toolbar-icon">${actionButtons}</div>`
|
||||
: ""}
|
||||
<div class="toolbar">
|
||||
${!this.narrow
|
||||
@ -158,12 +150,12 @@ export class HaAutomationTrace extends LitElement {
|
||||
this._traces,
|
||||
(trace) => trace.run_id,
|
||||
(trace) =>
|
||||
html`<option value=${trace.run_id}
|
||||
>${formatDateTimeWithSeconds(
|
||||
html`<option value=${trace.run_id}>
|
||||
${formatDateTimeWithSeconds(
|
||||
new Date(trace.timestamp.start),
|
||||
this.hass.locale
|
||||
)}</option
|
||||
>`
|
||||
)}
|
||||
</option>`
|
||||
)}
|
||||
</select>
|
||||
<mwc-icon-button
|
||||
|
||||
@ -102,9 +102,7 @@ class HaBlueprintOverview extends LitElement {
|
||||
? (name, entity: any) =>
|
||||
html`
|
||||
${name}<br />
|
||||
<div class="secondary">
|
||||
${entity.path}
|
||||
</div>
|
||||
<div class="secondary">${entity.path}</div>
|
||||
`
|
||||
: undefined,
|
||||
},
|
||||
|
||||
@ -94,9 +94,7 @@ class CloudLogin extends LocalizeMixin(
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Home Assistant Cloud</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
[[localize('ui.panel.config.cloud.login.introduction')]]
|
||||
</p>
|
||||
<p>[[localize('ui.panel.config.cloud.login.introduction')]]</p>
|
||||
<p>
|
||||
[[localize('ui.panel.config.cloud.login.introduction2')]]
|
||||
<a
|
||||
@ -107,9 +105,7 @@ class CloudLogin extends LocalizeMixin(
|
||||
Nabu Casa, Inc</a
|
||||
>[[localize('ui.panel.config.cloud.login.introduction2a')]]
|
||||
</p>
|
||||
<p>
|
||||
[[localize('ui.panel.config.cloud.login.introduction3')]]
|
||||
</p>
|
||||
<p>[[localize('ui.panel.config.cloud.login.introduction3')]]</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://www.nabucasa.com"
|
||||
|
||||
@ -41,9 +41,7 @@ class HaConfigDashboard extends LitElement {
|
||||
.narrow=${this.narrow}
|
||||
.isWide=${this.isWide}
|
||||
>
|
||||
<div slot="header">
|
||||
${this.hass.localize("ui.panel.config.header")}
|
||||
</div>
|
||||
<div slot="header">${this.hass.localize("ui.panel.config.header")}</div>
|
||||
|
||||
<div slot="introduction">
|
||||
${this.hass.localize("ui.panel.config.introduction")}
|
||||
|
||||
@ -37,9 +37,7 @@ export abstract class HaDeviceAutomationCard<
|
||||
) => string;
|
||||
|
||||
constructor(
|
||||
localizeDeviceAutomation: HaDeviceAutomationCard<
|
||||
T
|
||||
>["_localizeDeviceAutomation"]
|
||||
localizeDeviceAutomation: HaDeviceAutomationCard<T>["_localizeDeviceAutomation"]
|
||||
) {
|
||||
super();
|
||||
this._localizeDeviceAutomation = localizeDeviceAutomation;
|
||||
@ -61,9 +59,7 @@ export abstract class HaDeviceAutomationCard<
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize(this.headerKey)}
|
||||
</h3>
|
||||
<h3>${this.hass.localize(this.headerKey)}</h3>
|
||||
<div class="content">
|
||||
<ha-chip-set
|
||||
@chip-clicked=${this._handleAutomationClicked}
|
||||
|
||||
@ -7,9 +7,7 @@ import {
|
||||
import { HaDeviceAutomationCard } from "./ha-device-automation-card";
|
||||
|
||||
@customElement("ha-device-conditions-card")
|
||||
export class HaDeviceConditionsCard extends HaDeviceAutomationCard<
|
||||
DeviceCondition
|
||||
> {
|
||||
export class HaDeviceConditionsCard extends HaDeviceAutomationCard<DeviceCondition> {
|
||||
protected type = "condition";
|
||||
|
||||
protected headerKey = "ui.panel.config.devices.automation.conditions.caption";
|
||||
|
||||
@ -140,9 +140,7 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
.icon=${domainIcon(computeDomain(entry.entity_id))}
|
||||
></ha-icon>
|
||||
<paper-item-body>
|
||||
<div class="name">
|
||||
${entry.stateName || entry.entity_id}
|
||||
</div>
|
||||
<div class="name">${entry.stateName || entry.entity_id}</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
`;
|
||||
|
||||
@ -6,9 +6,7 @@ import {
|
||||
import { HaDeviceAutomationCard } from "./ha-device-automation-card";
|
||||
|
||||
@customElement("ha-device-triggers-card")
|
||||
export class HaDeviceTriggersCard extends HaDeviceAutomationCard<
|
||||
DeviceTrigger
|
||||
> {
|
||||
export class HaDeviceTriggersCard extends HaDeviceAutomationCard<DeviceTrigger> {
|
||||
protected type = "trigger";
|
||||
|
||||
protected headerKey = "ui.panel.config.devices.automation.triggers.caption";
|
||||
|
||||
@ -22,9 +22,7 @@ export class HaDeviceActionsMqtt extends LitElement {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<mwc-button @click=${this._showDebugInfo}>
|
||||
MQTT Info
|
||||
</mwc-button>
|
||||
<mwc-button @click=${this._showDebugInfo}> MQTT Info </mwc-button>
|
||||
<mwc-button class="warning" @click="${this._confirmDeleteEntry}">
|
||||
${this.hass.localize("ui.panel.config.devices.delete")}
|
||||
</mwc-button>
|
||||
|
||||
@ -30,9 +30,7 @@ class MQTTDiscoveryPayload extends LitElement {
|
||||
${this.summary}
|
||||
</div>
|
||||
${this._open
|
||||
? html` <div class="payload">
|
||||
${this._renderPayload()}
|
||||
</div>`
|
||||
? html` <div class="payload">${this._renderPayload()}</div>`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -80,9 +80,7 @@ class MQTTMessages extends LitElement {
|
||||
<ul class="message-with-topic">
|
||||
${this._showTopic ? html` <li>Topic: <code>${topic}</code></li> ` : ""}
|
||||
<li>QoS: ${message.qos}${message.retain ? ", Retained" : ""}</li>
|
||||
<li>
|
||||
Payload: ${this._renderSinglePayload(message)}
|
||||
</li>
|
||||
<li>Payload: ${this._renderSinglePayload(message)}</li>
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -99,9 +99,10 @@ export class HaConfigDevicePage extends LitElement {
|
||||
): EntityRegistryStateEntry[] =>
|
||||
entities
|
||||
.filter((entity) => entity.device_id === deviceId)
|
||||
.map((entity) => {
|
||||
return { ...entity, stateName: this._computeEntityName(entity) };
|
||||
})
|
||||
.map((entity) => ({
|
||||
...entity,
|
||||
stateName: this._computeEntityName(entity),
|
||||
}))
|
||||
.sort((ent1, ent2) =>
|
||||
compare(
|
||||
ent1.stateName || `zzz${ent1.entity_id}`,
|
||||
|
||||
@ -179,33 +179,31 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
outputDevices = outputDevices.filter((device) => !device.disabled_by);
|
||||
}
|
||||
|
||||
outputDevices = outputDevices.map((device) => {
|
||||
return {
|
||||
...device,
|
||||
name: computeDeviceName(
|
||||
device,
|
||||
this.hass,
|
||||
deviceEntityLookup[device.id]
|
||||
),
|
||||
model: device.model || "<unknown>",
|
||||
manufacturer: device.manufacturer || "<unknown>",
|
||||
area: device.area_id ? areaLookup[device.area_id].name : undefined,
|
||||
integration: device.config_entries.length
|
||||
? device.config_entries
|
||||
.filter((entId) => entId in entryLookup)
|
||||
.map(
|
||||
(entId) =>
|
||||
localize(`component.${entryLookup[entId].domain}.title`) ||
|
||||
entryLookup[entId].domain
|
||||
)
|
||||
.join(", ")
|
||||
: "No integration",
|
||||
battery_entity: [
|
||||
this._batteryEntity(device.id, deviceEntityLookup),
|
||||
this._batteryChargingEntity(device.id, deviceEntityLookup),
|
||||
],
|
||||
};
|
||||
});
|
||||
outputDevices = outputDevices.map((device) => ({
|
||||
...device,
|
||||
name: computeDeviceName(
|
||||
device,
|
||||
this.hass,
|
||||
deviceEntityLookup[device.id]
|
||||
),
|
||||
model: device.model || "<unknown>",
|
||||
manufacturer: device.manufacturer || "<unknown>",
|
||||
area: device.area_id ? areaLookup[device.area_id].name : undefined,
|
||||
integration: device.config_entries.length
|
||||
? device.config_entries
|
||||
.filter((entId) => entId in entryLookup)
|
||||
.map(
|
||||
(entId) =>
|
||||
localize(`component.${entryLookup[entId].domain}.title`) ||
|
||||
entryLookup[entId].domain
|
||||
)
|
||||
.join(", ")
|
||||
: "No integration",
|
||||
battery_entity: [
|
||||
this._batteryEntity(device.id, deviceEntityLookup),
|
||||
this._batteryChargingEntity(device.id, deviceEntityLookup),
|
||||
],
|
||||
}));
|
||||
|
||||
this._numHiddenDevices = startLength - outputDevices.length;
|
||||
return { devicesOutput: outputDevices, filteredDomains: filterDomains };
|
||||
@ -224,14 +222,12 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
template: (name, device: DataTableRowData) => {
|
||||
return html`
|
||||
${name}
|
||||
<div class="secondary">
|
||||
${device.area} | ${device.integration}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
template: (name, device: DataTableRowData) => html`
|
||||
${name}
|
||||
<div class="secondary">
|
||||
${device.area} | ${device.integration}
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
}
|
||||
: {
|
||||
|
||||
@ -148,9 +148,7 @@ export class DialogEntityEditor extends LitElement {
|
||||
</mwc-tab>
|
||||
</mwc-tab-bar>
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
${cache(this._renderTab())}
|
||||
</div>
|
||||
<div class="wrapper">${cache(this._renderTab())}</div>
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -314,9 +314,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
entities.forEach((entity) => {
|
||||
return entity;
|
||||
});
|
||||
entities.forEach((entity) => entity);
|
||||
|
||||
let filteredEntities = showReadOnly
|
||||
? entities.concat(stateEntities)
|
||||
|
||||
@ -10,13 +10,12 @@ export interface EntityRegistryDetailDialogParams {
|
||||
|
||||
export const loadEntityEditorDialog = () => import("./dialog-entity-editor");
|
||||
|
||||
const getDialog = () => {
|
||||
return document
|
||||
const getDialog = () =>
|
||||
document
|
||||
.querySelector("home-assistant")!
|
||||
.shadowRoot!.querySelector("dialog-entity-editor") as
|
||||
| DialogEntityEditor
|
||||
| undefined;
|
||||
};
|
||||
|
||||
export const showEntityEditorDialog = (
|
||||
element: HTMLElement,
|
||||
|
||||
@ -92,8 +92,8 @@ class HaInputSelectForm extends LitElement {
|
||||
"ui.dialogs.helper_settings.input_select.options"
|
||||
)}:
|
||||
${this._options.length
|
||||
? this._options.map((option, index) => {
|
||||
return html`
|
||||
? this._options.map(
|
||||
(option, index) => html`
|
||||
<paper-item class="option">
|
||||
<paper-item-body> ${option} </paper-item-body>
|
||||
<ha-icon-button
|
||||
@ -105,8 +105,8 @@ class HaInputSelectForm extends LitElement {
|
||||
icon="hass:delete"
|
||||
></ha-icon-button>
|
||||
</paper-item>
|
||||
`;
|
||||
})
|
||||
`
|
||||
)
|
||||
: html`
|
||||
<paper-item>
|
||||
${this.hass!.localize(
|
||||
|
||||
@ -67,11 +67,7 @@ export class HaConfigHelpers extends LitElement {
|
||||
html`
|
||||
${name}
|
||||
${narrow
|
||||
? html`
|
||||
<div class="secondary">
|
||||
${item.entity_id}
|
||||
</div>
|
||||
`
|
||||
? html` <div class="secondary">${item.entity_id}</div> `
|
||||
: ""}
|
||||
`,
|
||||
},
|
||||
@ -124,18 +120,16 @@ export class HaConfigHelpers extends LitElement {
|
||||
}
|
||||
);
|
||||
|
||||
private _getItems = memoize((stateItems: HassEntity[]) => {
|
||||
return stateItems.map((state) => {
|
||||
return {
|
||||
id: state.entity_id,
|
||||
icon: state.attributes.icon,
|
||||
name: state.attributes.friendly_name || "",
|
||||
entity_id: state.entity_id,
|
||||
editable: state.attributes.editable,
|
||||
type: computeStateDomain(state),
|
||||
};
|
||||
});
|
||||
});
|
||||
private _getItems = memoize((stateItems: HassEntity[]) =>
|
||||
stateItems.map((state) => ({
|
||||
id: state.entity_id,
|
||||
icon: state.attributes.icon,
|
||||
name: state.attributes.friendly_name || "",
|
||||
entity_id: state.entity_id,
|
||||
editable: state.attributes.editable,
|
||||
type: computeStateDomain(state),
|
||||
}))
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.hass || this._stateItems === undefined) {
|
||||
|
||||
@ -35,15 +35,15 @@ class IntegrationsCard extends LitElement {
|
||||
[domain: string]: IntegrationSetup;
|
||||
};
|
||||
|
||||
private _sortedIntegrations = memoizeOne((components: string[]) => {
|
||||
return Array.from(
|
||||
private _sortedIntegrations = memoizeOne((components: string[]) =>
|
||||
Array.from(
|
||||
new Set(
|
||||
components.map((comp) =>
|
||||
comp.includes(".") ? comp.split(".")[1] : comp
|
||||
)
|
||||
)
|
||||
).sort();
|
||||
});
|
||||
).sort()
|
||||
);
|
||||
|
||||
firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
@ -120,12 +120,8 @@ class IntegrationsCard extends LitElement {
|
||||
${this.narrow
|
||||
? ""
|
||||
: html`
|
||||
<td>
|
||||
${docLink}
|
||||
</td>
|
||||
<td>
|
||||
${issueLink}
|
||||
</td>
|
||||
<td>${docLink}</td>
|
||||
<td>${issueLink}</td>
|
||||
<td class="setup">
|
||||
${setupSeconds ? html`${setupSeconds}s` : ""}
|
||||
</td>
|
||||
|
||||
@ -122,9 +122,7 @@ class SystemHealthCard extends LitElement {
|
||||
sections.push(
|
||||
html`
|
||||
<div class="card-header">
|
||||
<h3>
|
||||
${domainToName(this.hass.localize, domain)}
|
||||
</h3>
|
||||
<h3>${domainToName(this.hass.localize, domain)}</h3>
|
||||
${!domainInfo.manage_url
|
||||
? ""
|
||||
: html`
|
||||
|
||||
@ -222,9 +222,7 @@ export class HaIntegrationCard extends LitElement {
|
||||
? html`
|
||||
<div class="message">
|
||||
<ha-svg-icon .path=${mdiAlertCircle}></ha-svg-icon>
|
||||
<div>
|
||||
${this.hass.localize(...stateText)}${stateTextExtra}
|
||||
</div>
|
||||
<div>${this.hass.localize(...stateText)}${stateTextExtra}</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
|
||||
@ -68,11 +68,7 @@ export class HaIntegrationHeader extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
${!this.banner
|
||||
? ""
|
||||
: html`<div class="banner">
|
||||
${this.banner}
|
||||
</div>`}
|
||||
${!this.banner ? "" : html`<div class="banner">${this.banner}</div>`}
|
||||
<slot name="above-header"></slot>
|
||||
<div class="header">
|
||||
<img
|
||||
|
||||
@ -64,9 +64,7 @@ class HaPanelDevMqtt extends LitElement {
|
||||
@value-changed=${this._handleTopic}
|
||||
></paper-input>
|
||||
|
||||
<p>
|
||||
${this.hass.localize("ui.panel.config.mqtt.payload")}
|
||||
</p>
|
||||
<p>${this.hass.localize("ui.panel.config.mqtt.payload")}</p>
|
||||
<ha-code-editor
|
||||
mode="jinja2"
|
||||
.value="${this.payload}"
|
||||
|
||||
@ -49,52 +49,48 @@ class OZWNetworkNodes extends LitElement {
|
||||
@internalProperty() private _nodes: OZWDevice[] = [];
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(narrow: boolean): DataTableColumnContainer => {
|
||||
return {
|
||||
node_id: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.id"),
|
||||
sortable: true,
|
||||
type: "numeric",
|
||||
width: "72px",
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
},
|
||||
node_product_name: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.model"),
|
||||
sortable: true,
|
||||
width: narrow ? "75%" : "25%",
|
||||
},
|
||||
node_manufacturer_name: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.ozw.nodes_table.manufacturer"
|
||||
),
|
||||
sortable: true,
|
||||
hidden: narrow,
|
||||
width: "25%",
|
||||
},
|
||||
node_query_stage: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.ozw.nodes_table.query_stage"
|
||||
),
|
||||
sortable: true,
|
||||
width: narrow ? "25%" : "15%",
|
||||
},
|
||||
is_zwave_plus: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.ozw.nodes_table.zwave_plus"
|
||||
),
|
||||
hidden: narrow,
|
||||
template: (value: boolean) =>
|
||||
value ? html` <ha-svg-icon .path=${mdiCheck}></ha-svg-icon>` : "",
|
||||
},
|
||||
is_failed: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.failed"),
|
||||
hidden: narrow,
|
||||
template: (value: boolean) =>
|
||||
value ? html` <ha-svg-icon .path=${mdiAlert}></ha-svg-icon>` : "",
|
||||
},
|
||||
};
|
||||
}
|
||||
(narrow: boolean): DataTableColumnContainer => ({
|
||||
node_id: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.id"),
|
||||
sortable: true,
|
||||
type: "numeric",
|
||||
width: "72px",
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
},
|
||||
node_product_name: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.model"),
|
||||
sortable: true,
|
||||
width: narrow ? "75%" : "25%",
|
||||
},
|
||||
node_manufacturer_name: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.ozw.nodes_table.manufacturer"
|
||||
),
|
||||
sortable: true,
|
||||
hidden: narrow,
|
||||
width: "25%",
|
||||
},
|
||||
node_query_stage: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.ozw.nodes_table.query_stage"
|
||||
),
|
||||
sortable: true,
|
||||
width: narrow ? "25%" : "15%",
|
||||
},
|
||||
is_zwave_plus: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.zwave_plus"),
|
||||
hidden: narrow,
|
||||
template: (value: boolean) =>
|
||||
value ? html` <ha-svg-icon .path=${mdiCheck}></ha-svg-icon>` : "",
|
||||
},
|
||||
is_failed: {
|
||||
title: this.hass.localize("ui.panel.config.ozw.nodes_table.failed"),
|
||||
hidden: narrow,
|
||||
template: (value: boolean) =>
|
||||
value ? html` <ha-svg-icon .path=${mdiAlert}></ha-svg-icon>` : "",
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
protected firstUpdated() {
|
||||
|
||||
@ -8,20 +8,18 @@ import { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { computeTail } from "./ozw-config-router";
|
||||
|
||||
export const ozwNetworkTabs = (instance: number): PageNavigation[] => {
|
||||
return [
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.network",
|
||||
path: `/config/ozw/network/${instance}/dashboard`,
|
||||
iconPath: mdiServerNetwork,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.nodes",
|
||||
path: `/config/ozw/network/${instance}/nodes`,
|
||||
iconPath: mdiNetwork,
|
||||
},
|
||||
];
|
||||
};
|
||||
export const ozwNetworkTabs = (instance: number): PageNavigation[] => [
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.network",
|
||||
path: `/config/ozw/network/${instance}/dashboard`,
|
||||
iconPath: mdiServerNetwork,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.nodes",
|
||||
path: `/config/ozw/network/${instance}/nodes`,
|
||||
iconPath: mdiNetwork,
|
||||
},
|
||||
];
|
||||
|
||||
@customElement("ozw-network-router")
|
||||
class OZWNetworkRouter extends HassRouterPage {
|
||||
|
||||
@ -152,9 +152,7 @@ class OZWNodeConfig extends LitElement {
|
||||
"ui.panel.config.ozw.node_config.wakeup_help"
|
||||
)}
|
||||
</span>
|
||||
<p>
|
||||
${this._metadata.metadata.WakeupHelp}
|
||||
</p>
|
||||
<p>${this._metadata.metadata.WakeupHelp}</p>
|
||||
</div>
|
||||
</ha-card>
|
||||
`
|
||||
|
||||
@ -77,9 +77,7 @@ class OZWNodeDashboard extends LitElement {
|
||||
.tabs=${ozwNodeTabs(this.ozwInstance, this.nodeId)}
|
||||
>
|
||||
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
||||
<div slot="header">
|
||||
Node Management
|
||||
</div>
|
||||
<div slot="header">Node Management</div>
|
||||
|
||||
<div slot="introduction">
|
||||
View the status of a node and manage its configuration.
|
||||
|
||||
@ -11,20 +11,18 @@ import { HomeAssistant } from "../../../../../types";
|
||||
export const ozwNodeTabs = (
|
||||
instance: number,
|
||||
node: number
|
||||
): PageNavigation[] => {
|
||||
return [
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.node.dashboard",
|
||||
path: `/config/ozw/network/${instance}/node/${node}/dashboard`,
|
||||
iconPath: mdiNetwork,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.node.config",
|
||||
path: `/config/ozw/network/${instance}/node/${node}/config`,
|
||||
iconPath: mdiWrench,
|
||||
},
|
||||
];
|
||||
};
|
||||
): PageNavigation[] => [
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.node.dashboard",
|
||||
path: `/config/ozw/network/${instance}/node/${node}/dashboard`,
|
||||
iconPath: mdiNetwork,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.panel.config.ozw.navigation.node.config",
|
||||
path: `/config/ozw/network/${instance}/node/${node}/config`,
|
||||
iconPath: mdiWrench,
|
||||
},
|
||||
];
|
||||
|
||||
@customElement("ozw-node-router")
|
||||
class OZWNodeRouter extends HassRouterPage {
|
||||
|
||||
@ -23,8 +23,7 @@ export const sortZHAGroups = (a: ZHAGroup, b: ZHAGroup): number => {
|
||||
return nameA.localeCompare(nameb);
|
||||
};
|
||||
|
||||
export const computeClusterKey = (cluster: Cluster): string => {
|
||||
return `${cluster.name} (Endpoint id: ${
|
||||
export const computeClusterKey = (cluster: Cluster): string =>
|
||||
`${cluster.name} (Endpoint id: ${
|
||||
cluster.endpoint_id
|
||||
}, Id: ${formatAsPaddedHex(cluster.id)}, Type: ${cluster.type})`;
|
||||
};
|
||||
|
||||
@ -206,9 +206,7 @@ export class ZHAClusterAttributes extends LitElement {
|
||||
this.selectedCluster!.id,
|
||||
this.selectedCluster!.type
|
||||
);
|
||||
this._attributes.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
this._attributes.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -171,9 +171,7 @@ export class ZHAClusterCommands extends LitElement {
|
||||
this.selectedCluster!.id,
|
||||
this.selectedCluster!.type
|
||||
);
|
||||
this._commands.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
this._commands.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,12 +35,10 @@ export class ZHAClustersDataTable extends LitElement {
|
||||
private _clusters = memoizeOne((clusters: Cluster[]) => {
|
||||
let outputClusters: ClusterRowData[] = clusters;
|
||||
|
||||
outputClusters = outputClusters.map((cluster) => {
|
||||
return {
|
||||
...cluster,
|
||||
cluster_id: cluster.endpoint_id + "-" + cluster.id,
|
||||
};
|
||||
});
|
||||
outputClusters = outputClusters.map((cluster) => ({
|
||||
...cluster,
|
||||
cluster_id: cluster.endpoint_id + "-" + cluster.id,
|
||||
}));
|
||||
|
||||
return outputClusters;
|
||||
});
|
||||
@ -65,9 +63,7 @@ export class ZHAClustersDataTable extends LitElement {
|
||||
},
|
||||
id: {
|
||||
title: "ID",
|
||||
template: (id: number) => {
|
||||
return html` ${formatAsPaddedHex(id)} `;
|
||||
},
|
||||
template: (id: number) => html` ${formatAsPaddedHex(id)} `,
|
||||
sortable: true,
|
||||
width: "15%",
|
||||
},
|
||||
|
||||
@ -117,9 +117,7 @@ export class ZHAClusters extends LitElement {
|
||||
this.hass,
|
||||
this.selectedDevice!.ieee
|
||||
);
|
||||
this._clusters.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
this._clusters.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -94,11 +94,7 @@ export class ZHADeviceBindingControl extends LitElement {
|
||||
>Bind</mwc-button
|
||||
>
|
||||
${this._showHelp
|
||||
? html`
|
||||
<div class="helpText">
|
||||
Bind devices.
|
||||
</div>
|
||||
`
|
||||
? html` <div class="helpText">Bind devices.</div> `
|
||||
: ""}
|
||||
<mwc-button
|
||||
@click="${this._onUnbindDevicesClick}"
|
||||
@ -106,11 +102,7 @@ export class ZHADeviceBindingControl extends LitElement {
|
||||
>Unbind</mwc-button
|
||||
>
|
||||
${this._showHelp
|
||||
? html`
|
||||
<div class="helpText">
|
||||
Unbind devices.
|
||||
</div>
|
||||
`
|
||||
? html` <div class="helpText">Unbind devices.</div> `
|
||||
: ""}
|
||||
</div>
|
||||
</ha-card>
|
||||
|
||||
@ -52,9 +52,10 @@ class ZHADeviceCard extends SubscribeMixin(LitElement) {
|
||||
): EntityRegistryStateEntry[] =>
|
||||
entities
|
||||
.filter((entity) => entity.device_id === deviceId)
|
||||
.map((entity) => {
|
||||
return { ...entity, stateName: this._computeEntityName(entity) };
|
||||
})
|
||||
.map((entity) => ({
|
||||
...entity,
|
||||
stateName: this._computeEntityName(entity),
|
||||
}))
|
||||
.sort((ent1, ent2) =>
|
||||
compare(
|
||||
ent1.stateName || `zzz${ent1.entity_id}`,
|
||||
|
||||
@ -113,14 +113,16 @@ export class ZHADeviceEndpointDataTable extends LitElement {
|
||||
template: (entities) => html`
|
||||
${entities.length
|
||||
? entities.length > 3
|
||||
? html`${entities.slice(0, 2).map(
|
||||
(entity) =>
|
||||
html`<div
|
||||
style="overflow: hidden; text-overflow: ellipsis;"
|
||||
>
|
||||
${entity.name || entity.original_name}
|
||||
</div>`
|
||||
)}
|
||||
? html`${entities
|
||||
.slice(0, 2)
|
||||
.map(
|
||||
(entity) =>
|
||||
html`<div
|
||||
style="overflow: hidden; text-overflow: ellipsis;"
|
||||
>
|
||||
${entity.name || entity.original_name}
|
||||
</div>`
|
||||
)}
|
||||
<div>And ${entities.length - 2} more...</div>`
|
||||
: entities.map(
|
||||
(entity) =>
|
||||
|
||||
@ -222,9 +222,9 @@ export class ZHAGroupBindingControl extends LitElement {
|
||||
|
||||
this._clustersToBind = [];
|
||||
for (const clusterIndex of this._selectedClusters) {
|
||||
const selectedCluster = this._clusters.find((cluster) => {
|
||||
return clusterIndex === cluster.endpoint_id + "-" + cluster.id;
|
||||
});
|
||||
const selectedCluster = this._clusters.find(
|
||||
(cluster) => clusterIndex === cluster.endpoint_id + "-" + cluster.id
|
||||
);
|
||||
this._clustersToBind.push(selectedCluster!);
|
||||
}
|
||||
}
|
||||
@ -236,12 +236,8 @@ export class ZHAGroupBindingControl extends LitElement {
|
||||
this.selectedDevice!.ieee
|
||||
);
|
||||
this._clusters = this._clusters
|
||||
.filter((cluster) => {
|
||||
return cluster.type.toLowerCase() === "out";
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
.filter((cluster) => cluster.type.toLowerCase() === "out")
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -142,11 +142,7 @@ export class ZHAGroupPage extends LitElement {
|
||||
>
|
||||
</a>`
|
||||
)
|
||||
: html`
|
||||
<paper-item>
|
||||
This group has no members
|
||||
</paper-item>
|
||||
`}
|
||||
: html` <paper-item> This group has no members </paper-item> `}
|
||||
</ha-card>
|
||||
${this.group.members.length
|
||||
? html`
|
||||
@ -237,13 +233,12 @@ export class ZHAGroupPage extends LitElement {
|
||||
private _filterDevices() {
|
||||
// filter the groupable devices so we only show devices that aren't already in the group
|
||||
this._filteredDeviceEndpoints = this.deviceEndpoints.filter(
|
||||
(deviceEndpoint) => {
|
||||
return !this.group!.members.some(
|
||||
(deviceEndpoint) =>
|
||||
!this.group!.members.some(
|
||||
(member) =>
|
||||
member.device.ieee === deviceEndpoint.device.ieee &&
|
||||
member.endpoint_id === deviceEndpoint.endpoint_id
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -63,12 +63,10 @@ export class ZHAGroupsDashboard extends LitElement {
|
||||
private _formattedGroups = memoizeOne((groups: ZHAGroup[]) => {
|
||||
let outputGroups: GroupRowData[] = groups;
|
||||
|
||||
outputGroups = outputGroups.map((group) => {
|
||||
return {
|
||||
...group,
|
||||
id: String(group.group_id),
|
||||
};
|
||||
});
|
||||
outputGroups = outputGroups.map((group) => ({
|
||||
...group,
|
||||
id: String(group.group_id),
|
||||
}));
|
||||
|
||||
return outputGroups;
|
||||
});
|
||||
@ -97,18 +95,15 @@ export class ZHAGroupsDashboard extends LitElement {
|
||||
title: this.hass.localize("ui.panel.config.zha.groups.group_id"),
|
||||
type: "numeric",
|
||||
width: "15%",
|
||||
template: (groupId: number) => {
|
||||
return html` ${formatAsPaddedHex(groupId)} `;
|
||||
},
|
||||
template: (groupId: number) =>
|
||||
html` ${formatAsPaddedHex(groupId)} `,
|
||||
sortable: true,
|
||||
},
|
||||
members: {
|
||||
title: this.hass.localize("ui.panel.config.zha.groups.members"),
|
||||
type: "numeric",
|
||||
width: "15%",
|
||||
template: (members: ZHADevice[]) => {
|
||||
return html` ${members.length} `;
|
||||
},
|
||||
template: (members: ZHADevice[]) => html` ${members.length} `,
|
||||
sortable: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -96,9 +96,7 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
hass="[[hass]]"
|
||||
on-click="_backTapped"
|
||||
></ha-icon-button-arrow-prev>
|
||||
<div main-title="">
|
||||
[[localize('component.zwave.title')]]
|
||||
</div>
|
||||
<div main-title="">[[localize('component.zwave.title')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
|
||||
@ -180,9 +180,7 @@ export class ZwaveMigration extends LitElement {
|
||||
? html`
|
||||
<ha-card class="content" header="Set up OZWDaemon">
|
||||
<div class="card-content">
|
||||
<p>
|
||||
Now it's time to set up the OZW integration.
|
||||
</p>
|
||||
<p>Now it's time to set up the OZW integration.</p>
|
||||
${isComponentLoaded(this.hass, "hassio")
|
||||
? html`
|
||||
<p>
|
||||
|
||||
@ -43,9 +43,7 @@ export class ZwaveValues extends LitElement {
|
||||
>
|
||||
${this.values.map(
|
||||
(item) => html`
|
||||
<paper-item>
|
||||
${this._computeCaption(item)}
|
||||
</paper-item>
|
||||
<paper-item> ${this._computeCaption(item)} </paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
|
||||
@ -27,9 +27,7 @@ class ErrorLogCard extends LitElement {
|
||||
icon="hass:refresh"
|
||||
@click=${this._refreshErrorLog}
|
||||
></ha-icon-button>
|
||||
<div class="card-content error-log">
|
||||
${this._errorHTML}
|
||||
</div>
|
||||
<div class="card-content error-log">${this._errorHTML}</div>
|
||||
</ha-card>
|
||||
`
|
||||
: html`
|
||||
|
||||
@ -63,9 +63,7 @@ export class SystemLogCard extends LitElement {
|
||||
(item, idx) => html`
|
||||
<paper-item @click=${this._openLog} .logItem=${item}>
|
||||
<paper-item-body two-line>
|
||||
<div class="row">
|
||||
${item.message[0]}
|
||||
</div>
|
||||
<div class="row">${item.message[0]}</div>
|
||||
<div secondary>
|
||||
${formatSystemLogTime(
|
||||
item.timestamp,
|
||||
|
||||
@ -190,13 +190,11 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
mode: defaultMode,
|
||||
filename: defaultMode === "yaml" ? "ui-lovelace.yaml" : "",
|
||||
},
|
||||
...dashboards.map((dashboard) => {
|
||||
return {
|
||||
filename: "",
|
||||
...dashboard,
|
||||
default: defaultUrlPath === dashboard.url_path,
|
||||
};
|
||||
}),
|
||||
...dashboards.map((dashboard) => ({
|
||||
filename: "",
|
||||
...dashboard,
|
||||
default: defaultUrlPath === dashboard.url_path,
|
||||
})),
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
@ -52,34 +52,32 @@ export class HaConfigLovelaceRescources extends LitElement {
|
||||
@internalProperty() private _resources: LovelaceResource[] = [];
|
||||
|
||||
private _columns = memoize(
|
||||
(_language): DataTableColumnContainer => {
|
||||
return {
|
||||
url: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.lovelace.resources.picker.headers.url"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
forceLTR: true,
|
||||
},
|
||||
type: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.lovelace.resources.picker.headers.type"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "30%",
|
||||
template: (type) =>
|
||||
html`
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.lovelace.resources.types.${type}`
|
||||
) || type}
|
||||
`,
|
||||
},
|
||||
};
|
||||
}
|
||||
(_language): DataTableColumnContainer => ({
|
||||
url: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.lovelace.resources.picker.headers.url"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
forceLTR: true,
|
||||
},
|
||||
type: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.lovelace.resources.picker.headers.type"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "30%",
|
||||
template: (type) =>
|
||||
html`
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.lovelace.resources.types.${type}`
|
||||
) || type}
|
||||
`,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
||||
@ -70,12 +70,12 @@ class DialogPersonDetail extends LitElement {
|
||||
|
||||
@internalProperty() private _personExists = false;
|
||||
|
||||
private _deviceTrackersAvailable = memoizeOne((hass) => {
|
||||
return Object.keys(hass.states).some(
|
||||
private _deviceTrackersAvailable = memoizeOne((hass) =>
|
||||
Object.keys(hass.states).some(
|
||||
(entityId) =>
|
||||
entityId.substr(0, entityId.indexOf(".")) === "device_tracker"
|
||||
);
|
||||
});
|
||||
)
|
||||
);
|
||||
|
||||
public async showDialog(params: PersonDetailDialogParams): Promise<void> {
|
||||
this._params = params;
|
||||
|
||||
@ -75,9 +75,7 @@ class HaConfigPerson extends LitElement {
|
||||
>${hass.localize("ui.panel.config.person.caption")}</span
|
||||
>
|
||||
<span slot="introduction">
|
||||
<p>
|
||||
${hass.localize("ui.panel.config.person.introduction")}
|
||||
</p>
|
||||
<p>${hass.localize("ui.panel.config.person.introduction")}</p>
|
||||
${this._configItems.length > 0
|
||||
? html`
|
||||
<p>
|
||||
@ -98,19 +96,17 @@ class HaConfigPerson extends LitElement {
|
||||
</span>
|
||||
|
||||
<ha-card class="storage">
|
||||
${this._storageItems.map((entry) => {
|
||||
return html`
|
||||
${this._storageItems.map(
|
||||
(entry) => html`
|
||||
<paper-icon-item @click=${this._openEditEntry} .entry=${entry}>
|
||||
<ha-person-badge
|
||||
slot="item-icon"
|
||||
.person=${entry}
|
||||
></ha-person-badge>
|
||||
<paper-item-body>
|
||||
${entry.name}
|
||||
</paper-item-body>
|
||||
<paper-item-body> ${entry.name} </paper-item-body>
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
${this._storageItems.length === 0
|
||||
? html`
|
||||
<div class="empty">
|
||||
@ -129,19 +125,17 @@ class HaConfigPerson extends LitElement {
|
||||
${this._configItems.length > 0
|
||||
? html`
|
||||
<ha-card header="Configuration.yaml persons">
|
||||
${this._configItems.map((entry) => {
|
||||
return html`
|
||||
${this._configItems.map(
|
||||
(entry) => html`
|
||||
<paper-icon-item>
|
||||
<ha-person-badge
|
||||
slot="item-icon"
|
||||
.person=${entry}
|
||||
></ha-person-badge>
|
||||
<paper-item-body>
|
||||
${entry.name}
|
||||
</paper-item-body>
|
||||
<paper-item-body> ${entry.name} </paper-item-body>
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</ha-card>
|
||||
`
|
||||
: ""}
|
||||
|
||||
@ -51,11 +51,12 @@ class HaConfigScene extends HassRouterPage {
|
||||
}
|
||||
}, 10);
|
||||
|
||||
private _getScenes = memoizeOne((states: HassEntities): SceneEntity[] => {
|
||||
return Object.values(states).filter(
|
||||
(entity) => computeStateDomain(entity) === "scene"
|
||||
) as SceneEntity[];
|
||||
});
|
||||
private _getScenes = memoizeOne(
|
||||
(states: HassEntities): SceneEntity[] =>
|
||||
Object.values(states).filter(
|
||||
(entity) => computeStateDomain(entity) === "scene"
|
||||
) as SceneEntity[]
|
||||
);
|
||||
|
||||
protected updatePageEl(pageEl, changedProps: PropertyValues) {
|
||||
pageEl.hass = this.hass;
|
||||
|
||||
@ -64,99 +64,93 @@ class HaSceneDashboard extends LitElement {
|
||||
return (filteredScenes
|
||||
? scenes.filter((scene) => filteredScenes!.includes(scene.entity_id))
|
||||
: scenes
|
||||
).map((scene) => {
|
||||
return {
|
||||
...scene,
|
||||
name: computeStateName(scene),
|
||||
icon: stateIcon(scene),
|
||||
};
|
||||
});
|
||||
).map((scene) => ({
|
||||
...scene,
|
||||
name: computeStateName(scene),
|
||||
icon: stateIcon(scene),
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(_language): DataTableColumnContainer => {
|
||||
return {
|
||||
activate: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_toggle, scene) =>
|
||||
html`
|
||||
<mwc-icon-button
|
||||
.scene=${scene}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.activate_scene"
|
||||
)}"
|
||||
@click=${(ev: Event) => this._activateScene(ev)}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiPlay}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`,
|
||||
},
|
||||
icon: {
|
||||
title: "",
|
||||
type: "icon",
|
||||
template: (icon) => html` <ha-icon .icon=${icon}></ha-icon> `,
|
||||
},
|
||||
name: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.scene.picker.headers.name"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
},
|
||||
info: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_info, scene) => html`
|
||||
(_language): DataTableColumnContainer => ({
|
||||
activate: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_toggle, scene) =>
|
||||
html`
|
||||
<mwc-icon-button
|
||||
.scene=${scene}
|
||||
@click=${this._showInfo}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.show_info_scene"
|
||||
"ui.panel.config.scene.picker.activate_scene"
|
||||
)}"
|
||||
@click=${(ev: Event) => this._activateScene(ev)}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiInformationOutline}></ha-svg-icon>
|
||||
<ha-svg-icon .path=${mdiPlay}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`,
|
||||
},
|
||||
edit: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_info, scene: any) => html`
|
||||
<a
|
||||
href=${ifDefined(
|
||||
scene.attributes.id
|
||||
? `/config/scene/edit/${scene.attributes.id}`
|
||||
: undefined
|
||||
)}
|
||||
},
|
||||
icon: {
|
||||
title: "",
|
||||
type: "icon",
|
||||
template: (icon) => html` <ha-icon .icon=${icon}></ha-icon> `,
|
||||
},
|
||||
name: {
|
||||
title: this.hass.localize("ui.panel.config.scene.picker.headers.name"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
},
|
||||
info: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_info, scene) => html`
|
||||
<mwc-icon-button
|
||||
.scene=${scene}
|
||||
@click=${this._showInfo}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.show_info_scene"
|
||||
)}"
|
||||
>
|
||||
<ha-svg-icon .path=${mdiInformationOutline}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`,
|
||||
},
|
||||
edit: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_info, scene: any) => html`
|
||||
<a
|
||||
href=${ifDefined(
|
||||
scene.attributes.id
|
||||
? `/config/scene/edit/${scene.attributes.id}`
|
||||
: undefined
|
||||
)}
|
||||
>
|
||||
<mwc-icon-button
|
||||
.disabled=${!scene.attributes.id}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.edit_scene"
|
||||
)}"
|
||||
>
|
||||
<mwc-icon-button
|
||||
.disabled=${!scene.attributes.id}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.edit_scene"
|
||||
)}"
|
||||
>
|
||||
<ha-svg-icon
|
||||
.path=${scene.attributes.id ? mdiPencil : mdiPencilOff}
|
||||
></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</a>
|
||||
${!scene.attributes.id
|
||||
? html`
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.only_editable"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
`
|
||||
: ""}
|
||||
`,
|
||||
},
|
||||
};
|
||||
}
|
||||
<ha-svg-icon
|
||||
.path=${scene.attributes.id ? mdiPencil : mdiPencilOff}
|
||||
></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</a>
|
||||
${!scene.attributes.id
|
||||
? html`
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.only_editable"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
`
|
||||
: ""}
|
||||
`,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
||||
@ -489,9 +489,10 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
this._scene = scene;
|
||||
const { context } = await activateScene(this.hass, this._scene.entity_id);
|
||||
this._activateContextId = context.id;
|
||||
this._unsubscribeEvents = await this.hass!.connection.subscribeEvents<
|
||||
HassEvent
|
||||
>((event) => this._stateChanged(event), "state_changed");
|
||||
this._unsubscribeEvents = await this.hass!.connection.subscribeEvents<HassEvent>(
|
||||
(event) => this._stateChanged(event),
|
||||
"state_changed"
|
||||
);
|
||||
}
|
||||
|
||||
private _showMoreInfo(ev: Event) {
|
||||
|
||||
@ -51,11 +51,12 @@ class HaConfigScript extends HassRouterPage {
|
||||
}
|
||||
}, 10);
|
||||
|
||||
private _getScripts = memoizeOne((states: HassEntities): ScriptEntity[] => {
|
||||
return Object.values(states).filter(
|
||||
(entity) => computeStateDomain(entity) === "script"
|
||||
) as ScriptEntity[];
|
||||
});
|
||||
private _getScripts = memoizeOne(
|
||||
(states: HassEntities): ScriptEntity[] =>
|
||||
Object.values(states).filter(
|
||||
(entity) => computeStateDomain(entity) === "script"
|
||||
) as ScriptEntity[]
|
||||
);
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
@ -357,9 +357,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
${!this.narrow
|
||||
? html`
|
||||
<ha-card
|
||||
><div class="card-header">
|
||||
${this._config?.alias}
|
||||
</div>
|
||||
><div class="card-header">${this._config?.alias}</div>
|
||||
<div
|
||||
class="card-actions layout horizontal justified center"
|
||||
>
|
||||
|
||||
@ -64,14 +64,12 @@ class HaScriptPicker extends LitElement {
|
||||
filteredScripts!.includes(script.entity_id)
|
||||
)
|
||||
: scripts
|
||||
).map((script) => {
|
||||
return {
|
||||
...script,
|
||||
name: computeStateName(script),
|
||||
icon: stateIcon(script),
|
||||
last_triggered: script.attributes.last_triggered || undefined,
|
||||
};
|
||||
});
|
||||
).map((script) => ({
|
||||
...script,
|
||||
name: computeStateName(script),
|
||||
icon: stateIcon(script),
|
||||
last_triggered: script.attributes.last_triggered || undefined,
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -24,7 +24,8 @@ import { TagDetailDialogParams } from "./show-dialog-tag-detail";
|
||||
const QR_LOGO_URL = "/static/icons/favicon-192x192.png";
|
||||
|
||||
@customElement("dialog-tag-detail")
|
||||
class DialogTagDetail extends LitElement
|
||||
class DialogTagDetail
|
||||
extends LitElement
|
||||
implements HassDialog<TagDetailDialogParams> {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
|
||||
@ -149,17 +149,15 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
);
|
||||
|
||||
private _data = memoizeOne((tags: Tag[]): TagRowData[] => {
|
||||
return tags.map((tag) => {
|
||||
return {
|
||||
...tag,
|
||||
display_name: tag.name || tag.id,
|
||||
last_scanned_datetime: tag.last_scanned
|
||||
? new Date(tag.last_scanned)
|
||||
: null,
|
||||
};
|
||||
});
|
||||
});
|
||||
private _data = memoizeOne((tags: Tag[]): TagRowData[] =>
|
||||
tags.map((tag) => ({
|
||||
...tag,
|
||||
display_name: tag.name || tag.id,
|
||||
last_scanned_datetime: tag.last_scanned
|
||||
? new Date(tag.last_scanned)
|
||||
: null,
|
||||
}))
|
||||
);
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues) {
|
||||
super.firstUpdated(changedProperties);
|
||||
|
||||
@ -76,33 +76,28 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _getZones = memoizeOne(
|
||||
(storageItems: Zone[], stateItems: HassEntity[]): MarkerLocation[] => {
|
||||
const stateLocations: MarkerLocation[] = stateItems.map((state) => {
|
||||
return {
|
||||
id: state.entity_id,
|
||||
icon: state.attributes.icon,
|
||||
name: state.attributes.friendly_name || state.entity_id,
|
||||
latitude: state.attributes.latitude,
|
||||
longitude: state.attributes.longitude,
|
||||
radius: state.attributes.radius,
|
||||
radius_color:
|
||||
state.entity_id === "zone.home"
|
||||
? homeRadiusColor
|
||||
: state.attributes.passive
|
||||
? passiveRadiusColor
|
||||
: defaultRadiusColor,
|
||||
location_editable:
|
||||
state.entity_id === "zone.home" && this._canEditCore,
|
||||
radius_editable: false,
|
||||
};
|
||||
});
|
||||
const storageLocations: MarkerLocation[] = storageItems.map((zone) => {
|
||||
return {
|
||||
...zone,
|
||||
radius_color: zone.passive ? passiveRadiusColor : defaultRadiusColor,
|
||||
location_editable: true,
|
||||
radius_editable: true,
|
||||
};
|
||||
});
|
||||
const stateLocations: MarkerLocation[] = stateItems.map((state) => ({
|
||||
id: state.entity_id,
|
||||
icon: state.attributes.icon,
|
||||
name: state.attributes.friendly_name || state.entity_id,
|
||||
latitude: state.attributes.latitude,
|
||||
longitude: state.attributes.longitude,
|
||||
radius: state.attributes.radius,
|
||||
radius_color:
|
||||
state.entity_id === "zone.home"
|
||||
? homeRadiusColor
|
||||
: state.attributes.passive
|
||||
? passiveRadiusColor
|
||||
: defaultRadiusColor,
|
||||
location_editable: state.entity_id === "zone.home" && this._canEditCore,
|
||||
radius_editable: false,
|
||||
}));
|
||||
const storageLocations: MarkerLocation[] = storageItems.map((zone) => ({
|
||||
...zone,
|
||||
radius_color: zone.passive ? passiveRadiusColor : defaultRadiusColor,
|
||||
location_editable: true,
|
||||
radius_editable: true,
|
||||
}));
|
||||
return storageLocations.concat(stateLocations);
|
||||
}
|
||||
);
|
||||
@ -143,17 +138,15 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
||||
attr-for-selected="data-id"
|
||||
.selected=${this._activeEntry || ""}
|
||||
>
|
||||
${this._storageItems.map((entry) => {
|
||||
return html`
|
||||
${this._storageItems.map(
|
||||
(entry) => html`
|
||||
<paper-icon-item
|
||||
data-id=${entry.id}
|
||||
@click=${this._itemClicked}
|
||||
.entry=${entry}
|
||||
>
|
||||
<ha-icon .icon=${entry.icon} slot="item-icon"></ha-icon>
|
||||
<paper-item-body>
|
||||
${entry.name}
|
||||
</paper-item-body>
|
||||
<paper-item-body> ${entry.name} </paper-item-body>
|
||||
${!this.narrow
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
@ -165,10 +158,10 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
||||
`
|
||||
: ""}
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})}
|
||||
${this._stateItems.map((state) => {
|
||||
return html`
|
||||
`
|
||||
)}
|
||||
${this._stateItems.map(
|
||||
(state) => html`
|
||||
<paper-icon-item
|
||||
data-id=${state.entity_id}
|
||||
@click=${this._stateItemClicked}
|
||||
@ -213,8 +206,8 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
||||
</paper-tooltip>
|
||||
</div>
|
||||
</paper-icon-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
`;
|
||||
|
||||
@ -249,9 +242,7 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
||||
@radius-updated=${this._radiusUpdated}
|
||||
@marker-clicked=${this._markerClicked}
|
||||
></ha-locations-editor>
|
||||
<div class="overflow">
|
||||
${listBox}
|
||||
</div>
|
||||
<div class="overflow">${listBox}</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
|
||||
@ -86,9 +86,7 @@ class HaPanelDevEvent extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
required
|
||||
value="{{eventType}}"
|
||||
></paper-input>
|
||||
<p>
|
||||
[[localize( 'ui.panel.developer-tools.tabs.events.data' )]]
|
||||
</p>
|
||||
<p>[[localize( 'ui.panel.developer-tools.tabs.events.data' )]]</p>
|
||||
</div>
|
||||
<div class="code-editor">
|
||||
<ha-code-editor
|
||||
|
||||
@ -291,9 +291,10 @@ class HaPanelDevService extends LitElement {
|
||||
}
|
||||
const target = "target" in serviceDomains[domain][service];
|
||||
const fields = serviceDomains[domain][service].fields;
|
||||
const result = Object.keys(fields).map((field) => {
|
||||
return { key: field, ...fields[field] };
|
||||
});
|
||||
const result = Object.keys(fields).map((field) => ({
|
||||
key: field,
|
||||
...fields[field],
|
||||
}));
|
||||
|
||||
return {
|
||||
target,
|
||||
|
||||
@ -220,9 +220,7 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
></ha-svg-icon>
|
||||
<a href="#" on-click="entitySelected">[[entity.entity_id]]</a>
|
||||
</td>
|
||||
<td>
|
||||
[[entity.state]]
|
||||
</td>
|
||||
<td>[[entity.state]]</td>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[computeShowAttributes(narrow, _showAttributes)]]"
|
||||
|
||||
@ -172,8 +172,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
||||
${(stateObj.state === "disarmed"
|
||||
? this._config.states!
|
||||
: ["disarm"]
|
||||
).map((state) => {
|
||||
return html`
|
||||
).map(
|
||||
(state) => html`
|
||||
<mwc-button
|
||||
.action="${state}"
|
||||
@click="${this._handleActionClick}"
|
||||
@ -181,8 +181,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
||||
>
|
||||
${this._actionDisplay(state)}
|
||||
</mwc-button>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
${!stateObj.attributes.code_format
|
||||
? html``
|
||||
@ -200,8 +200,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
||||
? html``
|
||||
: html`
|
||||
<div id="keypad">
|
||||
${BUTTONS.map((value) => {
|
||||
return value === ""
|
||||
${BUTTONS.map((value) =>
|
||||
value === ""
|
||||
? html` <mwc-button disabled></mwc-button> `
|
||||
: html`
|
||||
<mwc-button
|
||||
@ -218,8 +218,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
||||
)
|
||||
: value}
|
||||
</mwc-button>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`}
|
||||
</ha-card>
|
||||
|
||||
@ -87,12 +87,10 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
|
||||
throw new Error("Entities need to be an array");
|
||||
}
|
||||
|
||||
this._calendars = config!.entities.map((entity, idx) => {
|
||||
return {
|
||||
entity_id: entity,
|
||||
backgroundColor: `#${HA_COLOR_PALETTE[idx % HA_COLOR_PALETTE.length]}`,
|
||||
};
|
||||
});
|
||||
this._calendars = config!.entities.map((entity, idx) => ({
|
||||
entity_id: entity,
|
||||
backgroundColor: `#${HA_COLOR_PALETTE[idx % HA_COLOR_PALETTE.length]}`,
|
||||
}));
|
||||
|
||||
if (this._config?.entities !== config.entities) {
|
||||
this._fetchCalendarEvents();
|
||||
|
||||
@ -181,9 +181,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
return html`
|
||||
<ha-card>
|
||||
${this._headerElement
|
||||
? html`<div class="header-footer header">
|
||||
${this._headerElement}
|
||||
</div>`
|
||||
? html`<div class="header-footer header">${this._headerElement}</div>`
|
||||
: ""}
|
||||
${!this._config.title && !this._showHeaderToggle && !this._config.icon
|
||||
? ""
|
||||
@ -219,9 +217,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
</div>
|
||||
|
||||
${this._footerElement
|
||||
? html`<div class="header-footer footer">
|
||||
${this._footerElement}
|
||||
</div>`
|
||||
? html`<div class="header-footer footer">${this._footerElement}</div>`
|
||||
: ""}
|
||||
</ha-card>
|
||||
`;
|
||||
|
||||
@ -46,9 +46,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
): GaugeCardConfig {
|
||||
const includeDomains = ["sensor"];
|
||||
const maxEntities = 1;
|
||||
const entityFilter = (stateObj: HassEntity): boolean => {
|
||||
return !isNaN(Number(stateObj.state));
|
||||
};
|
||||
const entityFilter = (stateObj: HassEntity): boolean =>
|
||||
!isNaN(Number(stateObj.state));
|
||||
|
||||
const foundEntities = findEntities(
|
||||
hass,
|
||||
|
||||
@ -91,12 +91,10 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
};
|
||||
const entities = processConfigEntities<GlanceConfigEntity>(
|
||||
config.entities
|
||||
).map((entityConf) => {
|
||||
return {
|
||||
hold_action: { action: "more-info" } as MoreInfoActionConfig,
|
||||
...entityConf,
|
||||
};
|
||||
});
|
||||
).map((entityConf) => ({
|
||||
hold_action: { action: "more-info" } as MoreInfoActionConfig,
|
||||
...entityConf,
|
||||
}));
|
||||
|
||||
for (const entity of entities) {
|
||||
if (
|
||||
|
||||
@ -171,15 +171,11 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {
|
||||
<div id="slider">
|
||||
${slider}
|
||||
<div id="slider-center">
|
||||
<div id="humidity">
|
||||
${setValues}
|
||||
</div>
|
||||
<div id="humidity">${setValues}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="info">
|
||||
${name}
|
||||
</div>
|
||||
<div id="info">${name}</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
|
||||
@ -158,11 +158,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
<div class="brightness">
|
||||
%
|
||||
</div>
|
||||
`}
|
||||
: html` <div class="brightness">%</div> `}
|
||||
${this._config.name || computeStateName(stateObj)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -21,12 +21,9 @@ class HuiSensorCard extends HuiEntityCard {
|
||||
): SensorCardConfig {
|
||||
const includeDomains = ["sensor"];
|
||||
const maxEntities = 1;
|
||||
const entityFilter = (stateObj: HassEntity): boolean => {
|
||||
return (
|
||||
!isNaN(Number(stateObj.state)) &&
|
||||
!!stateObj.attributes.unit_of_measurement
|
||||
);
|
||||
};
|
||||
const entityFilter = (stateObj: HassEntity): boolean =>
|
||||
!isNaN(Number(stateObj.state)) &&
|
||||
!!stateObj.attributes.unit_of_measurement;
|
||||
|
||||
const foundEntities = findEntities(
|
||||
hass,
|
||||
|
||||
@ -36,7 +36,8 @@ import { SensorCardConfig, ShoppingListCardConfig } from "./types";
|
||||
let Sortable;
|
||||
|
||||
@customElement("hui-shopping-list-card")
|
||||
class HuiShoppingListCard extends SubscribeMixin(LitElement)
|
||||
class HuiShoppingListCard
|
||||
extends SubscribeMixin(LitElement)
|
||||
implements LovelaceCard {
|
||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||
await import("../editor/config-elements/hui-shopping-list-editor");
|
||||
|
||||
@ -250,9 +250,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
<div id="slider">
|
||||
${slider}
|
||||
<div id="slider-center">
|
||||
<div id="temperature">
|
||||
${currentTemperature} ${setValues}
|
||||
</div>
|
||||
<div id="temperature">${currentTemperature} ${setValues}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -177,18 +177,14 @@ export const computeCards = (
|
||||
return cards;
|
||||
};
|
||||
|
||||
const hasUpperCase = (str: string): boolean => {
|
||||
return str.toLowerCase() !== str;
|
||||
};
|
||||
const hasUpperCase = (str: string): boolean => str.toLowerCase() !== str;
|
||||
|
||||
const adjustName = (name: string): string => {
|
||||
const adjustName = (name: string): string =>
|
||||
// If first word already has an upper case letter (e.g. from brand name)
|
||||
// leave as-is, otherwise capitalize the first word.
|
||||
return hasUpperCase(name.substr(0, name.indexOf(" ")))
|
||||
hasUpperCase(name.substr(0, name.indexOf(" ")))
|
||||
? name
|
||||
: name[0].toUpperCase() + name.slice(1);
|
||||
};
|
||||
|
||||
const computeDefaultViewStates = (
|
||||
entities: HassEntities,
|
||||
entityEntries: EntityRegistryEntry[]
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
import { strokeWidth } from "../../../../data/graph";
|
||||
|
||||
const average = (items: any[]): number => {
|
||||
return (
|
||||
items.reduce((sum, entry) => sum + parseFloat(entry.state), 0) /
|
||||
items.length
|
||||
);
|
||||
};
|
||||
const average = (items: any[]): number =>
|
||||
items.reduce((sum, entry) => sum + parseFloat(entry.state), 0) / items.length;
|
||||
|
||||
const lastValue = (items: any[]): number => {
|
||||
return parseFloat(items[items.length - 1].state) || 0;
|
||||
};
|
||||
const lastValue = (items: any[]): number =>
|
||||
parseFloat(items[items.length - 1].state) || 0;
|
||||
|
||||
const calcPoints = (
|
||||
history: any,
|
||||
|
||||
@ -55,13 +55,11 @@ export class HuiActionEditor extends LitElement {
|
||||
}
|
||||
|
||||
private _serviceAction = memoizeOne(
|
||||
(config: CallServiceActionConfig): ServiceAction => {
|
||||
return {
|
||||
service: this._service,
|
||||
data: config.service_data,
|
||||
target: config.target,
|
||||
};
|
||||
}
|
||||
(config: CallServiceActionConfig): ServiceAction => ({
|
||||
service: this._service,
|
||||
data: config.service_data,
|
||||
target: config.target,
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@ -86,15 +84,15 @@ export class HuiActionEditor extends LitElement {
|
||||
"ui.panel.lovelace.editor.action-editor.actions.default_action"
|
||||
)}</paper-item
|
||||
>
|
||||
${this.actions.map((action) => {
|
||||
return html`
|
||||
${this.actions.map(
|
||||
(action) => html`
|
||||
<paper-item .value=${action}
|
||||
>${this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.action-editor.actions.${action}`
|
||||
)}</paper-item
|
||||
>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
${this.tooltipText
|
||||
|
||||
@ -65,8 +65,8 @@ export class HuiEntityEditor extends LitElement {
|
||||
${guard([this.entities, this._renderEmptySortable], () =>
|
||||
this._renderEmptySortable
|
||||
? ""
|
||||
: this.entities!.map((entityConf, index) => {
|
||||
return html`
|
||||
: this.entities!.map(
|
||||
(entityConf, index) => html`
|
||||
<div class="entity" data-entity-id=${entityConf.entity}>
|
||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||
<ha-entity-picker
|
||||
@ -77,8 +77,8 @@ export class HuiEntityEditor extends LitElement {
|
||||
allow-custom-entity
|
||||
></ha-entity-picker>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
`
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<ha-entity-picker
|
||||
|
||||
@ -27,8 +27,8 @@ export class HuiInputListEditor extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
${this.value.map((listEntry, index) => {
|
||||
return html`
|
||||
${this.value.map(
|
||||
(listEntry, index) => html`
|
||||
<paper-input
|
||||
label="${this.inputLabel}"
|
||||
.value=${listEntry}
|
||||
@ -45,8 +45,8 @@ export class HuiInputListEditor extends LitElement {
|
||||
>Clear</ha-icon-button
|
||||
></paper-input
|
||||
>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
<paper-input
|
||||
label="${this.inputLabel}"
|
||||
@change=${this._addEntry}
|
||||
|
||||
@ -46,9 +46,10 @@ export class HuiThemeSelectEditor extends LitElement {
|
||||
>
|
||||
${Object.keys(this.hass!.themes.themes)
|
||||
.sort()
|
||||
.map((theme) => {
|
||||
return html` <paper-item theme=${theme}>${theme}</paper-item> `;
|
||||
})}
|
||||
.map(
|
||||
(theme) =>
|
||||
html` <paper-item theme=${theme}>${theme}</paper-item> `
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
`;
|
||||
|
||||
@ -12,15 +12,14 @@ import { HomeAssistant } from "../../../types";
|
||||
export const createEntityNotFoundWarning = (
|
||||
hass: HomeAssistant,
|
||||
entityId: string
|
||||
) => {
|
||||
return hass.config.state !== STATE_NOT_RUNNING
|
||||
) =>
|
||||
hass.config.state !== STATE_NOT_RUNNING
|
||||
? hass.localize(
|
||||
"ui.panel.lovelace.warning.entity_not_found",
|
||||
"entity",
|
||||
entityId || "[empty]"
|
||||
)
|
||||
: hass.localize("ui.panel.lovelace.warning.starting");
|
||||
};
|
||||
|
||||
@customElement("hui-warning")
|
||||
export class HuiWarning extends LitElement {
|
||||
|
||||
@ -89,11 +89,5 @@ export const createRowElement = (config: LovelaceRowConfig) =>
|
||||
undefined
|
||||
);
|
||||
|
||||
export const getRowElementClass = (type: string) => {
|
||||
return getLovelaceElementClass(
|
||||
type,
|
||||
"row",
|
||||
ALWAYS_LOADED_TYPES,
|
||||
LAZY_LOAD_TYPES
|
||||
);
|
||||
};
|
||||
export const getRowElementClass = (type: string) =>
|
||||
getLovelaceElementClass(type, "row", ALWAYS_LOADED_TYPES, LAZY_LOAD_TYPES);
|
||||
|
||||
@ -14,11 +14,10 @@ const LAZY_LOAD_LAYOUTS = {
|
||||
|
||||
export const createViewElement = (
|
||||
config: LovelaceViewConfig
|
||||
): LovelaceViewElement | HuiErrorCard => {
|
||||
return createLovelaceElement(
|
||||
): LovelaceViewElement | HuiErrorCard =>
|
||||
createLovelaceElement(
|
||||
"view",
|
||||
config,
|
||||
ALWAYS_LOADED_LAYOUTS,
|
||||
LAZY_LOAD_LAYOUTS
|
||||
);
|
||||
};
|
||||
|
||||
@ -40,7 +40,8 @@ interface SelectedChangedEvent {
|
||||
}
|
||||
|
||||
@customElement("hui-dialog-create-card")
|
||||
export class HuiCreateDialogCard extends LitElement
|
||||
export class HuiCreateDialogCard
|
||||
extends LitElement
|
||||
implements HassDialog<CreateCardDialogParams> {
|
||||
@property({ attribute: false }) protected hass!: HomeAssistant;
|
||||
|
||||
|
||||
@ -47,9 +47,7 @@ export class HuiDialogDeleteCard extends LitElement {
|
||||
|
||||
return html`
|
||||
<ha-paper-dialog with-backdrop opened modal>
|
||||
<h2>
|
||||
${this.hass.localize("ui.panel.lovelace.cards.confirm_delete")}
|
||||
</h2>
|
||||
<h2>${this.hass.localize("ui.panel.lovelace.cards.confirm_delete")}</h2>
|
||||
<paper-dialog-scrollable>
|
||||
${this._cardConfig
|
||||
? html`
|
||||
|
||||
@ -48,7 +48,8 @@ declare global {
|
||||
}
|
||||
|
||||
@customElement("hui-dialog-edit-card")
|
||||
export class HuiDialogEditCard extends LitElement
|
||||
export class HuiDialogEditCard
|
||||
extends LitElement
|
||||
implements HassDialog<EditCardDialogParams> {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
|
||||
@ -76,9 +76,7 @@ export class HuiEntityPickerTable extends LitElement {
|
||||
${name}
|
||||
${narrow
|
||||
? html`
|
||||
<div class="secondary">
|
||||
${entity.stateObj.entity_id}
|
||||
</div>
|
||||
<div class="secondary">${entity.stateObj.entity_id}</div>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
|
||||
@ -33,7 +33,8 @@ const cardConfigStruct = object({
|
||||
const includeDomains = ["alarm_control_panel"];
|
||||
|
||||
@customElement("hui-alarm-panel-card-editor")
|
||||
export class HuiAlarmPanelCardEditor extends LitElement
|
||||
export class HuiAlarmPanelCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@ -92,8 +93,8 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
||||
.configValue="${"name"}"
|
||||
@value-changed="${this._valueChanged}"
|
||||
></paper-input>
|
||||
<span>Used States</span> ${this._states.map((state, index) => {
|
||||
return html`
|
||||
<span>Used States</span> ${this._states.map(
|
||||
(state, index) => html`
|
||||
<div class="states">
|
||||
<paper-item>${state}</paper-item>
|
||||
<ha-icon
|
||||
@ -103,8 +104,8 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
||||
@click=${this._stateRemoved}
|
||||
></ha-icon>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
<paper-dropdown-menu
|
||||
.label="${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.alarm-panel.available_states"
|
||||
@ -112,9 +113,7 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
||||
@value-changed="${this._stateAdded}"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content">
|
||||
${states.map((state) => {
|
||||
return html` <paper-item>${state}</paper-item> `;
|
||||
})}
|
||||
${states.map((state) => html` <paper-item>${state}</paper-item> `)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<hui-theme-select-editor
|
||||
|
||||
@ -49,7 +49,8 @@ const actions = [
|
||||
];
|
||||
|
||||
@customElement("hui-button-card-editor")
|
||||
export class HuiButtonCardEditor extends LitElement
|
||||
export class HuiButtonCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
|
||||
@ -37,7 +37,8 @@ const cardConfigStruct = object({
|
||||
const views = ["dayGridMonth", "dayGridDay", "listWeek"];
|
||||
|
||||
@customElement("hui-calendar-card-editor")
|
||||
export class HuiCalendarCardEditor extends LitElement
|
||||
export class HuiCalendarCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@ -93,15 +94,15 @@ export class HuiCalendarCardEditor extends LitElement
|
||||
.configValue=${"initial_view"}
|
||||
@iron-select=${this._viewChanged}
|
||||
>
|
||||
${views.map((view) => {
|
||||
return html`
|
||||
${views.map(
|
||||
(view) => html`
|
||||
<paper-item .view=${view}
|
||||
>${this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.calendar.views.${view}`
|
||||
)}
|
||||
</paper-item>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
@ -39,7 +39,8 @@ const cardConfigStruct = object({
|
||||
});
|
||||
|
||||
@customElement("hui-conditional-card-editor")
|
||||
export class HuiConditionalCardEditor extends LitElement
|
||||
export class HuiConditionalCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@ -131,8 +132,8 @@ export class HuiConditionalCardEditor extends LitElement
|
||||
${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.conditional.condition_explanation"
|
||||
)}
|
||||
${this._config.conditions.map((cond, idx) => {
|
||||
return html`
|
||||
${this._config.conditions.map(
|
||||
(cond, idx) => html`
|
||||
<div class="condition">
|
||||
<div class="entity">
|
||||
<ha-entity-picker
|
||||
@ -180,8 +181,8 @@ export class HuiConditionalCardEditor extends LitElement
|
||||
></paper-input>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
)}
|
||||
<div class="condition">
|
||||
<ha-entity-picker
|
||||
.hass=${this.hass}
|
||||
|
||||
@ -58,7 +58,8 @@ const cardConfigStruct = object({
|
||||
});
|
||||
|
||||
@customElement("hui-entities-card-editor")
|
||||
export class HuiEntitiesCardEditor extends LitElement
|
||||
export class HuiEntitiesCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
|
||||
@ -35,7 +35,8 @@ const cardConfigStruct = object({
|
||||
});
|
||||
|
||||
@customElement("hui-entity-card-editor")
|
||||
export class HuiEntityCardEditor extends LitElement
|
||||
export class HuiEntityCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
|
||||
@ -36,7 +36,8 @@ const cardConfigStruct = object({
|
||||
const includeDomains = ["sensor"];
|
||||
|
||||
@customElement("hui-gauge-card-editor")
|
||||
export class HuiGaugeCardEditor extends LitElement
|
||||
export class HuiGaugeCardEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardEditor {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user