mirror of
https://github.com/home-assistant/frontend.git
synced 2025-09-19 10:00:02 +00:00
Compare commits
9 Commits
auto-updat
...
20220401.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8e962fdecb | ||
![]() |
1f65193a97 | ||
![]() |
9557b604da | ||
![]() |
b45c355c9f | ||
![]() |
0b47d2c687 | ||
![]() |
8baa0b2a9b | ||
![]() |
c68a1d21ff | ||
![]() |
419d659311 | ||
![]() |
24484d0e74 |
@@ -18,7 +18,7 @@ import { LONG_TEXT } from "../../data/text";
|
||||
|
||||
const base_attributes = {
|
||||
title: "Awesome",
|
||||
current_version: "1.2.2",
|
||||
installed_version: "1.2.2",
|
||||
latest_version: "1.2.3",
|
||||
release_url: "https://home-assistant.io",
|
||||
supported_features: UPDATE_SUPPORT_INSTALL,
|
||||
@@ -50,7 +50,7 @@ const ENTITIES = [
|
||||
}),
|
||||
getEntity("update", "update5", "off", {
|
||||
...base_attributes,
|
||||
current_version: "1.2.3",
|
||||
installed_version: "1.2.3",
|
||||
friendly_name: "No update",
|
||||
}),
|
||||
getEntity("update", "update6", "off", {
|
||||
@@ -102,8 +102,8 @@ const ENTITIES = [
|
||||
}),
|
||||
getEntity("update", "update14", "off", {
|
||||
...base_attributes,
|
||||
current_version: null,
|
||||
friendly_name: "Update without current_version",
|
||||
installed_version: null,
|
||||
friendly_name: "Update without installed_version",
|
||||
}),
|
||||
getEntity("update", "update15", "off", {
|
||||
...base_attributes,
|
||||
@@ -128,6 +128,11 @@ const ENTITIES = [
|
||||
supported_features:
|
||||
base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES,
|
||||
}),
|
||||
getEntity("update", "update19", "on", {
|
||||
...base_attributes,
|
||||
friendly_name: "Update with auto update",
|
||||
auto_update: true,
|
||||
}),
|
||||
];
|
||||
|
||||
@customElement("demo-more-info-update")
|
||||
|
@@ -32,13 +32,6 @@ interface AddonCheckboxItem extends CheckboxItem {
|
||||
|
||||
const _computeFolders = (folders): CheckboxItem[] => {
|
||||
const list: CheckboxItem[] = [];
|
||||
if (folders.includes("homeassistant")) {
|
||||
list.push({
|
||||
slug: "homeassistant",
|
||||
name: "Home Assistant configuration",
|
||||
checked: false,
|
||||
});
|
||||
}
|
||||
if (folders.includes("ssl")) {
|
||||
list.push({ slug: "ssl", name: "SSL", checked: false });
|
||||
}
|
||||
@@ -100,7 +93,7 @@ export class SupervisorBackupContent extends LitElement {
|
||||
this.folders = _computeFolders(
|
||||
this.backup
|
||||
? this.backup.folders
|
||||
: ["homeassistant", "ssl", "share", "media", "addons/local"]
|
||||
: ["ssl", "share", "media", "addons/local"]
|
||||
);
|
||||
this.addons = _computeAddons(
|
||||
this.backup ? this.backup.addons : this.supervisor?.supervisor.addons
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = home-assistant-frontend
|
||||
version = 20220330.0
|
||||
version = 20220401.0
|
||||
author = The Home Assistant Authors
|
||||
author_email = hello@home-assistant.io
|
||||
license = Apache-2.0
|
||||
|
@@ -68,7 +68,7 @@ class HaDevicesPicker extends LitElement {
|
||||
.excludeDomains=${this.excludeDomains}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.label=${this.pickDeviceLabel}
|
||||
.required=${this.required}
|
||||
.required=${this.required && !currentDevices.length}
|
||||
@value-changed=${this._addDevice}
|
||||
></ha-device-picker>
|
||||
</div>
|
||||
|
@@ -110,7 +110,7 @@ class HaEntitiesPickerLight extends LitElement {
|
||||
.includeUnitOfMeasurement=${this.includeUnitOfMeasurement}
|
||||
.entityFilter=${this._entityFilter}
|
||||
.label=${this.pickEntityLabel}
|
||||
.required=${this.required}
|
||||
.required=${this.required && !currentEntities.length}
|
||||
@value-changed=${this._addEntity}
|
||||
></ha-entity-picker>
|
||||
</div>
|
||||
|
@@ -97,7 +97,7 @@ export class HaAreasPicker extends SubscribeMixin(LitElement) {
|
||||
.entityFilter=${this.entityFilter}
|
||||
.disabled=${this.disabled}
|
||||
.placeholder=${this.placeholder}
|
||||
.required=${this.required}
|
||||
.required=${this.required && !currentAreas.length}
|
||||
@value-changed=${this._addArea}
|
||||
></ha-area-picker>
|
||||
</div>
|
||||
|
@@ -108,7 +108,7 @@ export class HaSelectSelector extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.label=${this.label}
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.required}
|
||||
.required=${this.required && !value.length}
|
||||
.value=${this._filter}
|
||||
.items=${options.filter((item) => !this.value?.includes(item.value))}
|
||||
@filter-changed=${this._filterChanged}
|
||||
|
@@ -13,7 +13,8 @@ export const UPDATE_SUPPORT_BACKUP = 8;
|
||||
export const UPDATE_SUPPORT_RELEASE_NOTES = 16;
|
||||
|
||||
interface UpdateEntityAttributes extends HassEntityAttributeBase {
|
||||
current_version: string | null;
|
||||
auto_update: boolean | null;
|
||||
installed_version: string | null;
|
||||
in_progress: boolean | number;
|
||||
latest_version: string | null;
|
||||
release_summary: string | null;
|
||||
|
@@ -66,11 +66,11 @@ class MoreInfoUpdate extends LitElement {
|
||||
<div class="row">
|
||||
<div class="key">
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.update.current_version"
|
||||
"ui.dialogs.more_info_control.update.installed_version"
|
||||
)}
|
||||
</div>
|
||||
<div class="value">
|
||||
${this.stateObj.attributes.current_version ??
|
||||
${this.stateObj.attributes.installed_version ??
|
||||
this.hass.localize("state.default.unavailable")}
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,14 +130,20 @@ class MoreInfoUpdate extends LitElement {
|
||||
: ""}
|
||||
<hr />
|
||||
<div class="actions">
|
||||
<mwc-button
|
||||
@click=${this._handleSkip}
|
||||
.disabled=${skippedVersion ||
|
||||
this.stateObj.state === "off" ||
|
||||
updateIsInstalling(this.stateObj)}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.more_info_control.update.skip")}
|
||||
</mwc-button>
|
||||
${this.stateObj.attributes.auto_update
|
||||
? ""
|
||||
: html`
|
||||
<mwc-button
|
||||
@click=${this._handleSkip}
|
||||
.disabled=${skippedVersion ||
|
||||
this.stateObj.state === "off" ||
|
||||
updateIsInstalling(this.stateObj)}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.update.skip"
|
||||
)}
|
||||
</mwc-button>
|
||||
`}
|
||||
${supportsFeature(this.stateObj, UPDATE_SUPPORT_INSTALL)
|
||||
? html`
|
||||
<mwc-button
|
||||
|
@@ -13,6 +13,7 @@ import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/ha-select";
|
||||
import { UNAVAILABLE } from "../../../data/entity";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
import type { InputSelectEntity } from "../../../data/input_select";
|
||||
import { SelectEntity, setSelectOption } from "../../../data/select";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { EntitiesCardEntityConfig } from "../cards/types";
|
||||
@@ -106,9 +107,14 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
|
||||
}
|
||||
|
||||
private _selectedChanged(ev): void {
|
||||
const stateObj = this.hass!.states[this._config!.entity];
|
||||
const stateObj = this.hass!.states[
|
||||
this._config!.entity
|
||||
] as InputSelectEntity;
|
||||
const option = ev.target.value;
|
||||
if (option === stateObj.state) {
|
||||
if (
|
||||
option === stateObj.state ||
|
||||
!stateObj.attributes.options.includes(option)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -12,158 +12,172 @@ import "../../layouts/hass-error-screen";
|
||||
import { HomeAssistant, Route } from "../../types";
|
||||
import { documentationUrl } from "../../util/documentation-url";
|
||||
|
||||
const REDIRECTS: Redirects = {
|
||||
developer_states: {
|
||||
redirect: "/developer-tools/state",
|
||||
},
|
||||
developer_services: {
|
||||
redirect: "/developer-tools/service",
|
||||
},
|
||||
developer_call_service: {
|
||||
redirect: "/developer-tools/service",
|
||||
params: {
|
||||
service: "string",
|
||||
},
|
||||
},
|
||||
developer_template: {
|
||||
redirect: "/developer-tools/template",
|
||||
},
|
||||
developer_events: {
|
||||
redirect: "/developer-tools/event",
|
||||
},
|
||||
developer_statistics: {
|
||||
redirect: "/developer-tools/statistics",
|
||||
},
|
||||
config: {
|
||||
redirect: "/config",
|
||||
},
|
||||
cloud: {
|
||||
component: "cloud",
|
||||
redirect: "/config/cloud",
|
||||
},
|
||||
integrations: {
|
||||
redirect: "/config/integrations",
|
||||
},
|
||||
config_flow_start: {
|
||||
redirect: "/config/integrations/add",
|
||||
params: {
|
||||
domain: "string",
|
||||
},
|
||||
},
|
||||
config_mqtt: {
|
||||
component: "mqtt",
|
||||
redirect: "/config/mqtt",
|
||||
},
|
||||
config_zha: {
|
||||
component: "zha",
|
||||
redirect: "/config/zha/dashboard",
|
||||
},
|
||||
config_zwave_js: {
|
||||
component: "zwave_js",
|
||||
redirect: "/config/zwave_js/dashboard",
|
||||
},
|
||||
config_energy: {
|
||||
component: "energy",
|
||||
redirect: "/config/energy/dashboard",
|
||||
},
|
||||
devices: {
|
||||
redirect: "/config/devices/dashboard",
|
||||
},
|
||||
entities: {
|
||||
redirect: "/config/entities",
|
||||
},
|
||||
energy: {
|
||||
component: "energy",
|
||||
redirect: "/energy",
|
||||
},
|
||||
areas: {
|
||||
redirect: "/config/areas/dashboard",
|
||||
},
|
||||
blueprints: {
|
||||
component: "blueprint",
|
||||
redirect: "/config/blueprint/dashboard",
|
||||
},
|
||||
blueprint_import: {
|
||||
component: "blueprint",
|
||||
redirect: "/config/blueprint/dashboard/import",
|
||||
params: {
|
||||
blueprint_url: "url",
|
||||
},
|
||||
},
|
||||
automations: {
|
||||
component: "automation",
|
||||
redirect: "/config/automation/dashboard",
|
||||
},
|
||||
scenes: {
|
||||
component: "scene",
|
||||
redirect: "/config/scene/dashboard",
|
||||
},
|
||||
scripts: {
|
||||
component: "script",
|
||||
redirect: "/config/script/dashboard",
|
||||
},
|
||||
helpers: {
|
||||
redirect: "/config/helpers",
|
||||
},
|
||||
tags: {
|
||||
component: "tag",
|
||||
redirect: "/config/tags",
|
||||
},
|
||||
lovelace_dashboards: {
|
||||
component: "lovelace",
|
||||
redirect: "/config/lovelace/dashboards",
|
||||
},
|
||||
lovelace_resources: {
|
||||
component: "lovelace",
|
||||
redirect: "/config/lovelace/resources",
|
||||
},
|
||||
backup: {
|
||||
component: "backup",
|
||||
redirect: "/config/backup",
|
||||
},
|
||||
people: {
|
||||
component: "person",
|
||||
redirect: "/config/person",
|
||||
},
|
||||
zones: {
|
||||
component: "zone",
|
||||
redirect: "/config/zone",
|
||||
},
|
||||
users: {
|
||||
redirect: "/config/users",
|
||||
},
|
||||
general: {
|
||||
redirect: "/config/core",
|
||||
},
|
||||
server_controls: {
|
||||
redirect: "/config/server_control",
|
||||
},
|
||||
logs: {
|
||||
redirect: "/config/logs",
|
||||
},
|
||||
info: {
|
||||
redirect: "/config/info",
|
||||
},
|
||||
customize: {
|
||||
// customize was removed in 2021.12, fallback to dashboard
|
||||
redirect: "/config/dashboard",
|
||||
},
|
||||
profile: {
|
||||
redirect: "/profile/dashboard",
|
||||
},
|
||||
logbook: {
|
||||
component: "logbook",
|
||||
redirect: "/logbook",
|
||||
},
|
||||
history: {
|
||||
component: "history",
|
||||
redirect: "/history",
|
||||
},
|
||||
media_browser: {
|
||||
component: "media_source",
|
||||
redirect: "/media-browser",
|
||||
},
|
||||
};
|
||||
const getRedirect = (
|
||||
path: string,
|
||||
hasSupervisor: boolean
|
||||
): Redirect | undefined =>
|
||||
((
|
||||
{
|
||||
developer_states: {
|
||||
redirect: "/developer-tools/state",
|
||||
},
|
||||
developer_services: {
|
||||
redirect: "/developer-tools/service",
|
||||
},
|
||||
developer_call_service: {
|
||||
redirect: "/developer-tools/service",
|
||||
params: {
|
||||
service: "string",
|
||||
},
|
||||
},
|
||||
developer_template: {
|
||||
redirect: "/developer-tools/template",
|
||||
},
|
||||
developer_events: {
|
||||
redirect: "/developer-tools/event",
|
||||
},
|
||||
developer_statistics: {
|
||||
redirect: "/developer-tools/statistics",
|
||||
},
|
||||
config: {
|
||||
redirect: "/config",
|
||||
},
|
||||
cloud: {
|
||||
component: "cloud",
|
||||
redirect: "/config/cloud",
|
||||
},
|
||||
integrations: {
|
||||
redirect: "/config/integrations",
|
||||
},
|
||||
config_flow_start: {
|
||||
redirect: "/config/integrations/add",
|
||||
params: {
|
||||
domain: "string",
|
||||
},
|
||||
},
|
||||
config_mqtt: {
|
||||
component: "mqtt",
|
||||
redirect: "/config/mqtt",
|
||||
},
|
||||
config_zha: {
|
||||
component: "zha",
|
||||
redirect: "/config/zha/dashboard",
|
||||
},
|
||||
config_zwave_js: {
|
||||
component: "zwave_js",
|
||||
redirect: "/config/zwave_js/dashboard",
|
||||
},
|
||||
config_energy: {
|
||||
component: "energy",
|
||||
redirect: "/config/energy/dashboard",
|
||||
},
|
||||
devices: {
|
||||
redirect: "/config/devices/dashboard",
|
||||
},
|
||||
entities: {
|
||||
redirect: "/config/entities",
|
||||
},
|
||||
energy: {
|
||||
component: "energy",
|
||||
redirect: "/energy",
|
||||
},
|
||||
areas: {
|
||||
redirect: "/config/areas/dashboard",
|
||||
},
|
||||
blueprints: {
|
||||
component: "blueprint",
|
||||
redirect: "/config/blueprint/dashboard",
|
||||
},
|
||||
blueprint_import: {
|
||||
component: "blueprint",
|
||||
redirect: "/config/blueprint/dashboard/import",
|
||||
params: {
|
||||
blueprint_url: "url",
|
||||
},
|
||||
},
|
||||
automations: {
|
||||
component: "automation",
|
||||
redirect: "/config/automation/dashboard",
|
||||
},
|
||||
scenes: {
|
||||
component: "scene",
|
||||
redirect: "/config/scene/dashboard",
|
||||
},
|
||||
scripts: {
|
||||
component: "script",
|
||||
redirect: "/config/script/dashboard",
|
||||
},
|
||||
helpers: {
|
||||
redirect: "/config/helpers",
|
||||
},
|
||||
tags: {
|
||||
component: "tag",
|
||||
redirect: "/config/tags",
|
||||
},
|
||||
lovelace_dashboards: {
|
||||
component: "lovelace",
|
||||
redirect: "/config/lovelace/dashboards",
|
||||
},
|
||||
lovelace_resources: {
|
||||
component: "lovelace",
|
||||
redirect: "/config/lovelace/resources",
|
||||
},
|
||||
people: {
|
||||
component: "person",
|
||||
redirect: "/config/person",
|
||||
},
|
||||
zones: {
|
||||
component: "zone",
|
||||
redirect: "/config/zone",
|
||||
},
|
||||
users: {
|
||||
redirect: "/config/users",
|
||||
},
|
||||
general: {
|
||||
redirect: "/config/core",
|
||||
},
|
||||
server_controls: {
|
||||
redirect: "/config/server_control",
|
||||
},
|
||||
logs: {
|
||||
redirect: "/config/logs",
|
||||
},
|
||||
info: {
|
||||
redirect: "/config/info",
|
||||
},
|
||||
customize: {
|
||||
// customize was removed in 2021.12, fallback to dashboard
|
||||
redirect: "/config/dashboard",
|
||||
},
|
||||
profile: {
|
||||
redirect: "/profile/dashboard",
|
||||
},
|
||||
logbook: {
|
||||
component: "logbook",
|
||||
redirect: "/logbook",
|
||||
},
|
||||
history: {
|
||||
component: "history",
|
||||
redirect: "/history",
|
||||
},
|
||||
media_browser: {
|
||||
component: "media_source",
|
||||
redirect: "/media-browser",
|
||||
},
|
||||
backup: {
|
||||
component: hasSupervisor ? "hassio" : "backup",
|
||||
redirect: hasSupervisor ? "/hassio/backups" : "/config/backup",
|
||||
},
|
||||
supervisor_snapshots: {
|
||||
component: hasSupervisor ? "hassio" : "backup",
|
||||
redirect: hasSupervisor ? "/hassio/backups" : "/config/backup",
|
||||
},
|
||||
supervisor_backups: {
|
||||
component: hasSupervisor ? "hassio" : "backup",
|
||||
redirect: hasSupervisor ? "/hassio/backups" : "/config/backup",
|
||||
},
|
||||
} as Redirects
|
||||
)[path]);
|
||||
|
||||
export type ParamType = "url" | "string";
|
||||
|
||||
@@ -184,19 +198,17 @@ class HaPanelMy extends LitElement {
|
||||
|
||||
@state() public _error?: string;
|
||||
|
||||
private _redirect?: Redirect;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
const path = this.route.path.substring(1);
|
||||
const hasSupervisor = isComponentLoaded(this.hass, "hassio");
|
||||
|
||||
if (path === "backup" && isComponentLoaded(this.hass, "hassio")) {
|
||||
navigate("/hassio/backups", {
|
||||
replace: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._redirect = getRedirect(path, hasSupervisor);
|
||||
|
||||
if (path.startsWith("supervisor")) {
|
||||
if (!isComponentLoaded(this.hass, "hassio")) {
|
||||
if (path.startsWith("supervisor") && this._redirect === undefined) {
|
||||
if (!hasSupervisor) {
|
||||
this._error = "no_supervisor";
|
||||
return;
|
||||
}
|
||||
@@ -206,16 +218,14 @@ class HaPanelMy extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const redirect = REDIRECTS[path];
|
||||
|
||||
if (!redirect) {
|
||||
if (!this._redirect) {
|
||||
this._error = "not_supported";
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
redirect.component &&
|
||||
!isComponentLoaded(this.hass, redirect.component)
|
||||
this._redirect.component &&
|
||||
!isComponentLoaded(this.hass, this._redirect.component)
|
||||
) {
|
||||
this._error = "no_component";
|
||||
return;
|
||||
@@ -223,7 +233,7 @@ class HaPanelMy extends LitElement {
|
||||
|
||||
let url: string;
|
||||
try {
|
||||
url = this._createRedirectUrl(redirect);
|
||||
url = this._createRedirectUrl();
|
||||
} catch (err: any) {
|
||||
this._error = "url_error";
|
||||
return;
|
||||
@@ -254,10 +264,16 @@ class HaPanelMy extends LitElement {
|
||||
this.hass.localize(
|
||||
"ui.panel.my.component_not_loaded",
|
||||
"integration",
|
||||
domainToName(
|
||||
this.hass.localize,
|
||||
REDIRECTS[this.route.path.substr(1)].component!
|
||||
)
|
||||
html`<a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href=${documentationUrl(
|
||||
this.hass,
|
||||
`/integrations/${this._redirect!.component!}`
|
||||
)}
|
||||
>
|
||||
${domainToName(this.hass.localize, this._redirect!.component!)}
|
||||
</a>`
|
||||
) || "This redirect is not supported.";
|
||||
break;
|
||||
case "no_supervisor":
|
||||
@@ -280,18 +296,18 @@ class HaPanelMy extends LitElement {
|
||||
return html``;
|
||||
}
|
||||
|
||||
private _createRedirectUrl(redirect: Redirect): string {
|
||||
const params = this._createRedirectParams(redirect);
|
||||
return `${redirect.redirect}${params}`;
|
||||
private _createRedirectUrl(): string {
|
||||
const params = this._createRedirectParams();
|
||||
return `${this._redirect!.redirect}${params}`;
|
||||
}
|
||||
|
||||
private _createRedirectParams(redirect: Redirect): string {
|
||||
private _createRedirectParams(): string {
|
||||
const params = extractSearchParamsObject();
|
||||
if (!redirect.params && !Object.keys(params).length) {
|
||||
if (!this._redirect!.params && !Object.keys(params).length) {
|
||||
return "";
|
||||
}
|
||||
const resultParams = {};
|
||||
Object.entries(redirect.params || {}).forEach(([key, type]) => {
|
||||
Object.entries(this._redirect!.params || {}).forEach(([key, type]) => {
|
||||
if (!params[key] || !this._checkParamType(type, params[key])) {
|
||||
throw Error();
|
||||
}
|
||||
|
@@ -731,7 +731,7 @@
|
||||
"setting": "Setting"
|
||||
},
|
||||
"update": {
|
||||
"current_version": "Current version",
|
||||
"installed_version": "Installed version",
|
||||
"latest_version": "Latest version",
|
||||
"release_announcement": "Read release announcement",
|
||||
"skip": "Skip",
|
||||
|
Reference in New Issue
Block a user