mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-12 10:49:25 +00:00
Compare commits
1 Commits
20220901.0
...
fix-entity
Author | SHA1 | Date | |
---|---|---|---|
![]() |
be6fef1824 |
@@ -61,7 +61,6 @@ class HaDemo extends HomeAssistantAppEl {
|
||||
area_id: null,
|
||||
disabled_by: null,
|
||||
entity_id: "sensor.co2_intensity",
|
||||
id: "sensor.co2_intensity",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "co2signal",
|
||||
@@ -75,7 +74,6 @@ class HaDemo extends HomeAssistantAppEl {
|
||||
area_id: null,
|
||||
disabled_by: null,
|
||||
entity_id: "sensor.grid_fossil_fuel_percentage",
|
||||
id: "sensor.co2_intensity",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "co2signal",
|
||||
|
@@ -3,7 +3,7 @@ title: Dialgos
|
||||
subtitle: Dialogs provide important prompts in a user flow.
|
||||
---
|
||||
|
||||
# Material Design 3
|
||||
# Material Desing 3
|
||||
|
||||
Our dialogs are based on the latest version of Material Design. Specs and guidelines can be found on it's [website](https://m3.material.io/components/dialogs/overview).
|
||||
|
||||
|
@@ -191,7 +191,6 @@ const createEntityRegistryEntries = (
|
||||
hidden_by: null,
|
||||
entity_category: null,
|
||||
entity_id: "binary_sensor.updater",
|
||||
id: "binary_sensor.updater",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "updater",
|
||||
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "home-assistant-frontend"
|
||||
version = "20220901.0"
|
||||
version = "20220816.0"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "The Home Assistant frontend"
|
||||
readme = "README.md"
|
||||
|
@@ -126,7 +126,6 @@ export const FIXED_DEVICE_CLASS_ICONS = {
|
||||
gas: mdiGasCylinder,
|
||||
humidity: mdiWaterPercent,
|
||||
illuminance: mdiBrightness5,
|
||||
moisture: mdiWaterPercent,
|
||||
monetary: mdiCash,
|
||||
nitrogen_dioxide: mdiMolecule,
|
||||
nitrogen_monoxide: mdiMolecule,
|
||||
|
@@ -1,28 +0,0 @@
|
||||
import { HaDurationData } from "../../components/ha-duration-input";
|
||||
|
||||
const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
|
||||
|
||||
export const formatDuration = (duration: HaDurationData) => {
|
||||
const d = duration.days || 0;
|
||||
const h = duration.hours || 0;
|
||||
const m = duration.minutes || 0;
|
||||
const s = duration.seconds || 0;
|
||||
const ms = duration.milliseconds || 0;
|
||||
|
||||
if (d > 0) {
|
||||
return `${d} days ${h}:${leftPad(m)}:${leftPad(s)}`;
|
||||
}
|
||||
if (h > 0) {
|
||||
return `${h}:${leftPad(m)}:${leftPad(s)}`;
|
||||
}
|
||||
if (m > 0) {
|
||||
return `${m}:${leftPad(s)}`;
|
||||
}
|
||||
if (s > 0) {
|
||||
return `${s} seconds`;
|
||||
}
|
||||
if (ms > 0) {
|
||||
return `${ms} milliseconds`;
|
||||
}
|
||||
return null;
|
||||
};
|
@@ -2,12 +2,6 @@ import secondsToDuration from "../common/datetime/seconds_to_duration";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { Condition, Trigger } from "./automation";
|
||||
import {
|
||||
DeviceCondition,
|
||||
DeviceTrigger,
|
||||
localizeDeviceAutomationCondition,
|
||||
localizeDeviceAutomationTrigger,
|
||||
} from "./device_automation";
|
||||
import { formatAttributeName } from "./entity_attributes";
|
||||
|
||||
export const describeTrigger = (
|
||||
@@ -298,19 +292,6 @@ export const describeTrigger = (
|
||||
if (trigger.platform === "webhook") {
|
||||
return "When a Webhook payload has been received";
|
||||
}
|
||||
|
||||
if (trigger.platform === "device") {
|
||||
const config = trigger as DeviceTrigger;
|
||||
const localized = localizeDeviceAutomationTrigger(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${stateObj ? computeStateName(stateObj) : config.entity_id} ${
|
||||
config.type
|
||||
}`;
|
||||
}
|
||||
|
||||
return `${trigger.platform || "Unknown"} trigger`;
|
||||
};
|
||||
|
||||
@@ -486,17 +467,5 @@ export const describeCondition = (
|
||||
}`;
|
||||
}
|
||||
|
||||
if (condition.condition === "device") {
|
||||
const config = condition as DeviceCondition;
|
||||
const localized = localizeDeviceAutomationCondition(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${stateObj ? computeStateName(stateObj) : config.entity_id} ${
|
||||
config.type
|
||||
}`;
|
||||
}
|
||||
|
||||
return `${condition.condition} condition`;
|
||||
};
|
||||
|
@@ -1,13 +1,11 @@
|
||||
import { Connection, createCollection } from "home-assistant-js-websocket";
|
||||
import { Store } from "home-assistant-js-websocket/dist/store";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import { caseInsensitiveStringCompare } from "../common/string/compare";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface EntityRegistryEntry {
|
||||
id: string;
|
||||
entity_id: string;
|
||||
name: string | null;
|
||||
icon: string | null;
|
||||
@@ -163,16 +161,6 @@ export const sortEntityRegistryByName = (entries: EntityRegistryEntry[]) =>
|
||||
caseInsensitiveStringCompare(entry1.name || "", entry2.name || "")
|
||||
);
|
||||
|
||||
export const entityRegistryById = memoizeOne(
|
||||
(entries: HomeAssistant["entities"]) => {
|
||||
const entities: HomeAssistant["entities"] = {};
|
||||
for (const entity of Object.values(entries)) {
|
||||
entities[entity.id] = entity;
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
);
|
||||
|
||||
export const getEntityPlatformLookup = (
|
||||
entities: EntityRegistryEntry[]
|
||||
): Record<string, string> => {
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import { formatDuration } from "../common/datetime/format_duration";
|
||||
import secondsToDuration from "../common/datetime/seconds_to_duration";
|
||||
import { ensureArray } from "../common/ensure-array";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
@@ -6,13 +5,6 @@ import { isTemplate } from "../common/string/has-template";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { Condition } from "./automation";
|
||||
import { describeCondition, describeTrigger } from "./automation_i18n";
|
||||
import { localizeDeviceAutomationAction } from "./device_automation";
|
||||
import { computeDeviceName } from "./device_registry";
|
||||
import {
|
||||
computeEntityRegistryName,
|
||||
entityRegistryById,
|
||||
} from "./entity_registry";
|
||||
import { domainToName } from "./integration";
|
||||
import {
|
||||
ActionType,
|
||||
ActionTypes,
|
||||
@@ -55,11 +47,7 @@ export const describeAction = <T extends ActionType>(
|
||||
) {
|
||||
base = "Call a service based on a template";
|
||||
} else if (config.service) {
|
||||
const [domain, serviceName] = config.service.split(".", 2);
|
||||
const service = hass.services[domain][serviceName];
|
||||
base = service
|
||||
? `${domainToName(hass.localize, domain)}: ${service.name}`
|
||||
: `Call service: ${config.service}`;
|
||||
base = `Call service ${config.service}`;
|
||||
} else {
|
||||
return actionType;
|
||||
}
|
||||
@@ -78,49 +66,26 @@ export const describeAction = <T extends ActionType>(
|
||||
? config.target[key]
|
||||
: [config.target[key]];
|
||||
|
||||
const values: string[] = [];
|
||||
|
||||
let renderValues = true;
|
||||
|
||||
for (const targetThing of keyConf) {
|
||||
if (isTemplate(targetThing)) {
|
||||
targets.push(`templated ${label}`);
|
||||
renderValues = false;
|
||||
break;
|
||||
} else if (key === "entity_id") {
|
||||
if (targetThing.includes(".")) {
|
||||
const state = hass.states[targetThing];
|
||||
if (state) {
|
||||
targets.push(computeStateName(state));
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
}
|
||||
} else {
|
||||
const entityReg = entityRegistryById(hass.entities)[targetThing];
|
||||
if (entityReg) {
|
||||
targets.push(
|
||||
computeEntityRegistryName(hass, entityReg) || targetThing
|
||||
);
|
||||
} else {
|
||||
targets.push("unknown entity");
|
||||
}
|
||||
}
|
||||
} else if (key === "device_id") {
|
||||
const device = hass.devices[targetThing];
|
||||
if (device) {
|
||||
targets.push(computeDeviceName(device, hass));
|
||||
} else {
|
||||
targets.push("unknown device");
|
||||
}
|
||||
} else if (key === "area_id") {
|
||||
const area = hass.areas[targetThing];
|
||||
if (area?.name) {
|
||||
targets.push(area.name);
|
||||
} else {
|
||||
targets.push("unknown area");
|
||||
}
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
values.push(targetThing);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderValues) {
|
||||
targets.push(`${label} ${values.join(", ")}`);
|
||||
}
|
||||
}
|
||||
if (targets.length > 0) {
|
||||
base += ` ${targets.join(", ")}`;
|
||||
base += ` on ${targets.join(", ")}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +104,7 @@ export const describeAction = <T extends ActionType>(
|
||||
? "based on a template"
|
||||
: `for ${config.delay}`;
|
||||
} else {
|
||||
duration = `for ${formatDuration(config.delay)}`;
|
||||
duration = `for ${JSON.stringify(config.delay)}`;
|
||||
}
|
||||
|
||||
return `Delay ${duration}`;
|
||||
@@ -210,15 +175,11 @@ export const describeAction = <T extends ActionType>(
|
||||
if (actionType === "if") {
|
||||
const config = action as IfAction;
|
||||
return `Perform an action if: ${
|
||||
!config.if
|
||||
? ""
|
||||
: typeof config.if === "string"
|
||||
typeof config.if === "string"
|
||||
? config.if
|
||||
: ensureArray(config.if).length > 1
|
||||
? `${ensureArray(config.if).length} conditions`
|
||||
: ensureArray(config.if).length
|
||||
? describeCondition(ensureArray(config.if)[0], hass)
|
||||
: ""
|
||||
: describeCondition(ensureArray(config.if)[0], hass)
|
||||
}${config.else ? " (or else!)" : ""}`;
|
||||
}
|
||||
|
||||
@@ -258,10 +219,6 @@ export const describeAction = <T extends ActionType>(
|
||||
|
||||
if (actionType === "device_action") {
|
||||
const config = action as DeviceAction;
|
||||
const localized = localizeDeviceAutomationAction(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${config.type || "Perform action with"} ${
|
||||
stateObj ? computeStateName(stateObj) : config.entity_id
|
||||
|
@@ -157,13 +157,13 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
</div>`
|
||||
: ""}
|
||||
<ha-expansion-panel leftChevron>
|
||||
<h3 slot="header">
|
||||
<div slot="header">
|
||||
<ha-svg-icon
|
||||
class="action-icon"
|
||||
.path=${ACTION_TYPES[type!]}
|
||||
></ha-svg-icon>
|
||||
${capitalizeFirstLetter(describeAction(this.hass, this.action))}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
${this.index !== 0
|
||||
? html`
|
||||
@@ -507,18 +507,13 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
--expansion-panel-summary-padding: 0 0 0 8px;
|
||||
--expansion-panel-content-padding: 0;
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.action-icon {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 870px) {
|
||||
.action-icon {
|
||||
display: inline-block;
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--primary-color);
|
||||
opacity: 0.9;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import "../../../components/entity/ha-entity-toggle";
|
||||
import "../../../components/ha-blueprint-picker";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-circular-progress";
|
||||
@@ -10,7 +11,10 @@ import "../../../components/ha-markdown";
|
||||
import "../../../components/ha-selector/ha-selector";
|
||||
import "../../../components/ha-settings-row";
|
||||
import "../../../components/ha-textfield";
|
||||
import { BlueprintAutomationConfig } from "../../../data/automation";
|
||||
import {
|
||||
BlueprintAutomationConfig,
|
||||
triggerAutomationActions,
|
||||
} from "../../../data/automation";
|
||||
import {
|
||||
BlueprintOrError,
|
||||
Blueprints,
|
||||
@@ -63,6 +67,9 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
const blueprint = this._blueprint;
|
||||
return html`
|
||||
<ha-config-section vertical .isWide=${this.isWide}>
|
||||
${!this.narrow
|
||||
? html` <span slot="header">${this.config.alias}</span> `
|
||||
: ""}
|
||||
<span slot="introduction">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.introduction"
|
||||
@@ -95,6 +102,36 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
${this.stateObj
|
||||
? html`
|
||||
<div class="card-actions layout horizontal justified center">
|
||||
<div class="layout horizontal center">
|
||||
<ha-entity-toggle
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj!}
|
||||
></ha-entity-toggle>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.enable_disable"
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<a href="/config/automation/trace/${this.config.id}">
|
||||
<mwc-button>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.show_trace"
|
||||
)}
|
||||
</mwc-button>
|
||||
</a>
|
||||
<mwc-button
|
||||
@click=${this._runActions}
|
||||
.stateObj=${this.stateObj}
|
||||
>
|
||||
${this.hass.localize("ui.card.automation.trigger")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</ha-card>
|
||||
</ha-config-section>
|
||||
|
||||
@@ -183,6 +220,10 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
this._blueprints = await fetchBlueprints(this.hass, "automation");
|
||||
}
|
||||
|
||||
private _runActions(ev: Event) {
|
||||
triggerAutomationActions(this.hass, (ev.target as any).stateObj.entity_id);
|
||||
}
|
||||
|
||||
private _blueprintChanged(ev) {
|
||||
ev.stopPropagation();
|
||||
if (this.config.use_blueprint.path === ev.detail.value) {
|
||||
@@ -278,6 +319,9 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ha-entity-toggle {
|
||||
margin-right: 8px;
|
||||
}
|
||||
ha-settings-row {
|
||||
--paper-time-input-justify-content: flex-end;
|
||||
--settings-row-content-width: 100%;
|
||||
|
@@ -93,7 +93,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
: ""}
|
||||
|
||||
<ha-expansion-panel leftChevron>
|
||||
<h3 slot="header">
|
||||
<div slot="header">
|
||||
<ha-svg-icon
|
||||
class="condition-icon"
|
||||
.path=${CONDITION_TYPES[this.condition.condition]}
|
||||
@@ -101,7 +101,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
${capitalizeFirstLetter(
|
||||
describeCondition(this.condition, this.hass)
|
||||
)}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<ha-button-menu
|
||||
slot="icons"
|
||||
@@ -423,18 +423,13 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
--expansion-panel-summary-padding: 0 0 0 8px;
|
||||
--expansion-panel-content-padding: 0;
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.condition-icon {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 870px) {
|
||||
.condition-icon {
|
||||
display: inline-block;
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--primary-color);
|
||||
opacity: 0.9;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@@ -230,14 +230,6 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
|
||||
${this._config
|
||||
? html`
|
||||
${this.narrow
|
||||
? html`<span slot="header"
|
||||
>${this._config!.alias ||
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.default_name"
|
||||
)}</span
|
||||
>`
|
||||
: ""}
|
||||
<div
|
||||
class="content ${classMap({
|
||||
"yaml-mode": this._mode === "yaml",
|
||||
@@ -250,7 +242,12 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
${this._mode === "gui"
|
||||
? html`
|
||||
${this.narrow
|
||||
? ""
|
||||
? html`<span slot="header"
|
||||
>${this._config!.alias ||
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.default_name"
|
||||
)}</span
|
||||
>`
|
||||
: html`
|
||||
<div class="header-name">
|
||||
<h1>
|
||||
@@ -681,6 +678,15 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
}
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-family: var(--paper-font-headline_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-headline_-_-webkit-font-smoothing
|
||||
);
|
||||
font-size: var(--paper-font-headline_-_font-size);
|
||||
font-weight: var(--paper-font-headline_-_font-weight);
|
||||
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||
line-height: var(--paper-font-headline_-_line-height);
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.header-name {
|
||||
display: flex;
|
||||
|
@@ -47,12 +47,12 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
: ""}
|
||||
|
||||
<ha-expansion-panel leftChevron>
|
||||
<h3 slot="header">
|
||||
<div slot="header">
|
||||
<ha-svg-icon class="settings-icon" .path=${mdiRobot}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.automation_settings"
|
||||
)}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<ha-textarea
|
||||
.label=${this.hass.localize(
|
||||
@@ -115,11 +115,11 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
</ha-card>
|
||||
|
||||
<div class="header">
|
||||
<h2 id="triggers-heading" class="name">
|
||||
<div class="name">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.header"
|
||||
)}
|
||||
</h2>
|
||||
</div>
|
||||
<a
|
||||
href=${documentationUrl(this.hass, "/docs/automation/trigger/")}
|
||||
target="_blank"
|
||||
@@ -135,19 +135,17 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
</div>
|
||||
|
||||
<ha-automation-trigger
|
||||
role="region"
|
||||
aria-labelledby="triggers-heading"
|
||||
.triggers=${this.config.trigger}
|
||||
@value-changed=${this._triggerChanged}
|
||||
.hass=${this.hass}
|
||||
></ha-automation-trigger>
|
||||
|
||||
<div class="header">
|
||||
<h2 id="conditions-heading" class="name">
|
||||
<div class="name">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.conditions.header"
|
||||
)}
|
||||
</h2>
|
||||
</div>
|
||||
<a
|
||||
href=${documentationUrl(this.hass, "/docs/automation/condition/")}
|
||||
target="_blank"
|
||||
@@ -163,19 +161,17 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
</div>
|
||||
|
||||
<ha-automation-condition
|
||||
role="region"
|
||||
aria-labelledby="conditions-heading"
|
||||
.conditions=${this.config.condition || []}
|
||||
@value-changed=${this._conditionChanged}
|
||||
.hass=${this.hass}
|
||||
></ha-automation-condition>
|
||||
|
||||
<div class="header">
|
||||
<h2 id="actions-heading" class="name">
|
||||
<div class="name">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.header"
|
||||
)}
|
||||
</h2>
|
||||
</div>
|
||||
<a
|
||||
href=${documentationUrl(this.hass, "/docs/automation/action/")}
|
||||
target="_blank"
|
||||
@@ -191,8 +187,6 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
</div>
|
||||
|
||||
<ha-automation-action
|
||||
role="region"
|
||||
aria-labelledby="actions-heading"
|
||||
.actions=${this.config.action}
|
||||
@value-changed=${this._actionChanged}
|
||||
.hass=${this.hass}
|
||||
@@ -298,6 +292,7 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
margin: 16px 0;
|
||||
align-items: center;
|
||||
}
|
||||
.header .name {
|
||||
@@ -308,11 +303,6 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
.header a {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
ha-expansion-panel {
|
||||
--expansion-panel-summary-padding: 0 0 0 8px;
|
||||
--expansion-panel-content-padding: 0;
|
||||
@@ -329,7 +319,7 @@ export class HaManualAutomationEditor extends LitElement {
|
||||
@media (min-width: 870px) {
|
||||
.settings-icon {
|
||||
display: inline-block;
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--primary-color);
|
||||
opacity: 0.9;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@@ -121,13 +121,13 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
: ""}
|
||||
|
||||
<ha-expansion-panel leftChevron>
|
||||
<h3 slot="header">
|
||||
<div slot="header">
|
||||
<ha-svg-icon
|
||||
class="trigger-icon"
|
||||
.path=${TRIGGER_TYPES[this.trigger.platform]}
|
||||
></ha-svg-icon>
|
||||
${capitalizeFirstLetter(describeTrigger(this.trigger, this.hass))}
|
||||
</h3>
|
||||
</div>
|
||||
<ha-button-menu
|
||||
slot="icons"
|
||||
fixed
|
||||
@@ -532,18 +532,13 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
--expansion-panel-summary-padding: 0 0 0 8px;
|
||||
--expansion-panel-content-padding: 0;
|
||||
}
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.trigger-icon {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 870px) {
|
||||
.trigger-icon {
|
||||
display: inline-block;
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--primary-color);
|
||||
opacity: 0.9;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
|
||||
|
||||
@property() public trigger!: TagTrigger;
|
||||
|
||||
@state() private _tags?: Tag[];
|
||||
@state() private _tags: Tag[] = [];
|
||||
|
||||
public static get defaultConfig() {
|
||||
return { tag_id: "" };
|
||||
@@ -27,16 +27,14 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._tags) {
|
||||
return html``;
|
||||
}
|
||||
const { tag_id } = this.trigger;
|
||||
return html`
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.type.tag.label"
|
||||
)}
|
||||
.disabled=${this._tags.length === 0}
|
||||
.value=${this.trigger.tag_id}
|
||||
.value=${tag_id}
|
||||
@selected=${this._tagChanged}
|
||||
>
|
||||
${this._tags.map(
|
||||
@@ -51,19 +49,13 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
|
||||
}
|
||||
|
||||
private async _fetchTags() {
|
||||
this._tags = (await fetchTags(this.hass)).sort((a, b) =>
|
||||
this._tags = await fetchTags(this.hass);
|
||||
this._tags.sort((a, b) =>
|
||||
caseInsensitiveStringCompare(a.name || a.id, b.name || b.id)
|
||||
);
|
||||
}
|
||||
|
||||
private _tagChanged(ev) {
|
||||
if (
|
||||
!ev.detail.value ||
|
||||
!this._tags ||
|
||||
this.trigger.tag_id === ev.detail.value
|
||||
) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.trigger,
|
||||
|
@@ -944,18 +944,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||
buttons.push({
|
||||
action: async () => {
|
||||
const confirmed = await showConfirmationDialog(this, {
|
||||
text:
|
||||
this._integrations(device, this.entries).length > 1
|
||||
? this.hass.localize(
|
||||
`ui.panel.config.devices.confirm_delete_integration`,
|
||||
{
|
||||
integration: domainToName(
|
||||
this.hass.localize,
|
||||
entry.domain
|
||||
),
|
||||
}
|
||||
)
|
||||
: this.hass.localize(`ui.panel.config.devices.confirm_delete`),
|
||||
text: this.hass.localize("ui.panel.config.devices.confirm_delete"),
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -971,7 +960,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||
classes: "warning",
|
||||
icon: mdiDelete,
|
||||
label:
|
||||
this._integrations(device, this.entries).length > 1
|
||||
buttons.length > 1
|
||||
? this.hass.localize(
|
||||
`ui.panel.config.devices.delete_device_integration`,
|
||||
{
|
||||
|
@@ -872,17 +872,10 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
name: this._name.trim() || null,
|
||||
icon: this._icon.trim() || null,
|
||||
area_id: this._areaId || null,
|
||||
device_class: this._deviceClass || null,
|
||||
new_entity_id: this._entityId.trim(),
|
||||
};
|
||||
|
||||
// Only update device class if changed by user
|
||||
if (
|
||||
this._deviceClass !==
|
||||
(this.entry.device_class || this.entry.original_device_class)
|
||||
) {
|
||||
params.device_class = this._deviceClass;
|
||||
}
|
||||
|
||||
const stateObj: HassEntity | undefined =
|
||||
this.hass.states[this.entry.entity_id];
|
||||
const domain = computeDomain(this.entry.entity_id);
|
||||
@@ -1058,10 +1051,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
.buttons {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: 24px;
|
||||
padding-top: 16px;
|
||||
padding: 8px 24px 24px 24px;
|
||||
justify-content: space-between;
|
||||
padding-bottom: max(env(safe-area-inset-bottom), 24px);
|
||||
padding-bottom: max(env(safe-area-inset-bottom), 16px);
|
||||
background-color: var(--mdc-theme-surface, #fff);
|
||||
border-top: 1px solid var(--divider-color);
|
||||
position: sticky;
|
||||
|
@@ -68,10 +68,9 @@ import type { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
|
||||
export interface StateEntity extends Omit<EntityRegistryEntry, "id"> {
|
||||
export interface StateEntity extends EntityRegistryEntry {
|
||||
readonly?: boolean;
|
||||
selectable?: boolean;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface EntityRow extends StateEntity {
|
||||
@@ -303,7 +302,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filteredEntitiesAndDomains = memoize(
|
||||
(
|
||||
entities: StateEntity[],
|
||||
entities: EntityRegistryEntry[],
|
||||
devices: DeviceRegistryEntry[] | undefined,
|
||||
areas: AreaRegistryEntry[] | undefined,
|
||||
stateEntities: StateEntity[],
|
||||
@@ -393,10 +392,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
result.push({
|
||||
...entry,
|
||||
entity,
|
||||
name: computeEntityRegistryName(
|
||||
this.hass!,
|
||||
entry as EntityRegistryEntry
|
||||
),
|
||||
name: computeEntityRegistryName(this.hass!, entry),
|
||||
unavailable,
|
||||
restored,
|
||||
area: area ? area.name : "—",
|
||||
|
@@ -36,6 +36,7 @@ const defaultFullCalendarConfig: CalendarOptions = {
|
||||
selectOverlap: false,
|
||||
eventOverlap: false,
|
||||
allDaySlot: false,
|
||||
slotMinTime: "00:00:59",
|
||||
height: "parent",
|
||||
locales: allLocales,
|
||||
firstDay: 1,
|
||||
@@ -177,7 +178,7 @@ class HaScheduleForm extends LitElement {
|
||||
},
|
||||
eventTimeFormat: {
|
||||
hour: useAmPm(this.hass.locale) ? "numeric" : "2-digit",
|
||||
minute: useAmPm(this.hass.locale) ? "numeric" : "2-digit",
|
||||
minute: undefined,
|
||||
hour12: useAmPm(this.hass.locale),
|
||||
meridiem: useAmPm(this.hass.locale) ? "narrow" : false,
|
||||
},
|
||||
@@ -213,8 +214,7 @@ class HaScheduleForm extends LitElement {
|
||||
}
|
||||
|
||||
this[`_${day}`].forEach((item: ScheduleDay, index: number) => {
|
||||
// Add 7 to 0 because we start the calendar on Monday
|
||||
const distance = i - currentDay + (i === 0 ? 7 : 0);
|
||||
const distance = i - currentDay;
|
||||
|
||||
const start = new Date();
|
||||
start.setDate(start.getDate() + distance);
|
||||
@@ -227,9 +227,7 @@ class HaScheduleForm extends LitElement {
|
||||
end.setDate(end.getDate() + distance);
|
||||
end.setHours(
|
||||
parseInt(item.to.slice(0, 2)),
|
||||
parseInt(item.to.slice(-2)),
|
||||
0,
|
||||
0
|
||||
parseInt(item.to.slice(-2))
|
||||
);
|
||||
|
||||
events.push({
|
||||
@@ -383,9 +381,6 @@ class HaScheduleForm extends LitElement {
|
||||
margin: 8px 0;
|
||||
height: 450px;
|
||||
width: 100%;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.fc-scroller {
|
||||
overflow-x: visible !important;
|
||||
|
@@ -331,11 +331,11 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
`
|
||||
: html`
|
||||
<div class="header">
|
||||
<h2 id="sequence-heading" class="name">
|
||||
<div class="name">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.script.editor.sequence"
|
||||
)}
|
||||
</h2>
|
||||
</div>
|
||||
<a
|
||||
href=${documentationUrl(
|
||||
this.hass,
|
||||
@@ -354,8 +354,6 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
</div>
|
||||
|
||||
<ha-automation-action
|
||||
role="region"
|
||||
aria-labelledby="sequence-heading"
|
||||
.actions=${this._config.sequence}
|
||||
@value-changed=${this._sequenceChanged}
|
||||
.hass=${this.hass}
|
||||
|
@@ -2576,7 +2576,7 @@
|
||||
"download_diagnostics": "Download diagnostics",
|
||||
"download_diagnostics_integration": "Download {integration} diagnostics",
|
||||
"delete_device": "Delete",
|
||||
"delete_device_integration": "Remove device from {integration}",
|
||||
"delete_device_integration": "Remove {integration} from device",
|
||||
"type": {
|
||||
"device_heading": "Device",
|
||||
"device": "device",
|
||||
@@ -2653,7 +2653,6 @@
|
||||
},
|
||||
"delete": "Delete",
|
||||
"confirm_delete": "Are you sure you want to delete this device?",
|
||||
"confirm_delete_integration": "Are you sure you want to remove this device from {integration}?",
|
||||
"picker": {
|
||||
"search": "Search devices",
|
||||
"filter": {
|
||||
|
Reference in New Issue
Block a user