Compare commits

...

2 Commits

Author SHA1 Message Date
Paul Bottein
e642c80003 Fix device automations 2024-10-09 19:28:50 +02:00
Paul Bottein
cc07d51613 Add sequence support to dashboard action 2024-10-09 18:53:41 +02:00
7 changed files with 86 additions and 5 deletions

View File

@@ -3,6 +3,7 @@ import "@material/mwc-list/mwc-list-item";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { property, state } from "lit/decorators"; import { property, state } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { stopPropagation } from "../../common/dom/stop_propagation";
import { fullEntitiesContext } from "../../data/context"; import { fullEntitiesContext } from "../../data/context";
import { import {
DeviceAutomation, DeviceAutomation,
@@ -103,6 +104,7 @@ export abstract class HaDeviceAutomationPicker<
.label=${this.label} .label=${this.label}
.value=${value} .value=${value}
@selected=${this._automationChanged} @selected=${this._automationChanged}
@closed=${stopPropagation}
.disabled=${this._automations.length === 0} .disabled=${this._automations.length === 0}
> >
${value === NO_AUTOMATION_KEY ${value === NO_AUTOMATION_KEY

View File

@@ -174,6 +174,7 @@ export class HaServiceControl extends LitElement {
if (this._value && serviceData) { if (this._value && serviceData) {
const loadDefaults = this.value && !("data" in this.value); const loadDefaults = this.value && !("data" in this.value);
// Set mandatory bools without a default value to false // Set mandatory bools without a default value to false
this._value = { ...this._value };
if (!this._value.data) { if (!this._value.data) {
this._value.data = {}; this._value.data = {};
} }

View File

@@ -1,4 +1,5 @@
import type { HassServiceTarget } from "home-assistant-js-websocket"; import type { HassServiceTarget } from "home-assistant-js-websocket";
import { Action } from "../../script";
export interface ToggleActionConfig extends BaseActionConfig { export interface ToggleActionConfig extends BaseActionConfig {
action: "toggle"; action: "toggle";
@@ -31,6 +32,11 @@ export interface MoreInfoActionConfig extends BaseActionConfig {
entity_id?: string; entity_id?: string;
} }
export interface SequenceActionConfig extends BaseActionConfig {
action: "sequence";
actions?: Action[];
}
export interface AssistActionConfig extends BaseActionConfig { export interface AssistActionConfig extends BaseActionConfig {
action: "assist"; action: "assist";
pipeline_id?: string; pipeline_id?: string;
@@ -67,4 +73,5 @@ export type ActionConfig =
| MoreInfoActionConfig | MoreInfoActionConfig
| AssistActionConfig | AssistActionConfig
| NoActionConfig | NoActionConfig
| CustomActionConfig; | CustomActionConfig
| SequenceActionConfig;

View File

@@ -3,6 +3,7 @@ import { navigate } from "../../../common/navigate";
import { forwardHaptic } from "../../../data/haptics"; import { forwardHaptic } from "../../../data/haptics";
import { domainToName } from "../../../data/integration"; import { domainToName } from "../../../data/integration";
import { ActionConfig } from "../../../data/lovelace/config/action"; import { ActionConfig } from "../../../data/lovelace/config/action";
import { callExecuteScript } from "../../../data/service";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { showVoiceCommandDialog } from "../../../dialogs/voice-command-dialog/show-ha-voice-command-dialog"; import { showVoiceCommandDialog } from "../../../dialogs/voice-command-dialog/show-ha-voice-command-dialog";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@@ -177,6 +178,13 @@ export const handleAction = async (
}); });
break; break;
} }
case "sequence": {
if (!actionConfig.actions) {
return;
}
callExecuteScript(hass, actionConfig.actions);
break;
}
case "fire-dom-event": { case "fire-dom-event": {
fireEvent(node, "ll-custom", actionConfig); fireEvent(node, "ll-custom", actionConfig);
} }

View File

@@ -1,3 +1,5 @@
import { ContextProvider } from "@lit-labs/context";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { import {
css, css,
CSSResultGroup, CSSResultGroup,
@@ -14,7 +16,10 @@ import "../../../components/ha-assist-pipeline-picker";
import { HaFormSchema, SchemaUnion } from "../../../components/ha-form/types"; import { HaFormSchema, SchemaUnion } from "../../../components/ha-form/types";
import "../../../components/ha-help-tooltip"; import "../../../components/ha-help-tooltip";
import "../../../components/ha-navigation-picker"; import "../../../components/ha-navigation-picker";
import { HaSelect } from "../../../components/ha-select";
import "../../../components/ha-service-control"; import "../../../components/ha-service-control";
import { fullEntitiesContext } from "../../../data/context";
import { subscribeEntityRegistry } from "../../../data/entity_registry";
import { import {
ActionConfig, ActionConfig,
CallServiceActionConfig, CallServiceActionConfig,
@@ -22,9 +27,9 @@ import {
UrlActionConfig, UrlActionConfig,
} from "../../../data/lovelace/config/action"; } from "../../../data/lovelace/config/action";
import { ServiceAction } from "../../../data/script"; import { ServiceAction } from "../../../data/script";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EditorTarget } from "../editor/types"; import { EditorTarget } from "../editor/types";
import { HaSelect } from "../../../components/ha-select";
export type UiAction = Exclude<ActionConfig["action"], "fire-dom-event">; export type UiAction = Exclude<ActionConfig["action"], "fire-dom-event">;
@@ -34,6 +39,7 @@ const DEFAULT_ACTIONS: UiAction[] = [
"navigate", "navigate",
"url", "url",
"perform-action", "perform-action",
"sequence",
"assist", "assist",
"none", "none",
]; ];
@@ -70,8 +76,17 @@ const ASSIST_SCHEMA = [
}, },
] as const satisfies readonly HaFormSchema[]; ] as const satisfies readonly HaFormSchema[];
const SEQUENCE_SCHEMA = [
{
name: "actions",
selector: {
action: {},
},
},
] as const satisfies readonly HaFormSchema[];
@customElement("hui-action-editor") @customElement("hui-action-editor")
export class HuiActionEditor extends LitElement { export class HuiActionEditor extends SubscribeMixin(LitElement) {
@property({ attribute: false }) public config?: ActionConfig; @property({ attribute: false }) public config?: ActionConfig;
@property() public label?: string; @property() public label?: string;
@@ -86,6 +101,19 @@ export class HuiActionEditor extends LitElement {
@query("ha-select") private _select!: HaSelect; @query("ha-select") private _select!: HaSelect;
private _entitiesContext = new ContextProvider(this, {
context: fullEntitiesContext,
initialValue: [],
});
public hassSubscribe(): UnsubscribeFunc[] {
return [
subscribeEntityRegistry(this.hass!.connection!, (entities) => {
this._entitiesContext.setValue(entities);
}),
];
}
get _navigation_path(): string { get _navigation_path(): string {
const config = this.config as NavigateActionConfig | undefined; const config = this.config as NavigateActionConfig | undefined;
return config?.navigation_path || ""; return config?.navigation_path || "";
@@ -120,6 +148,11 @@ export class HuiActionEditor extends LitElement {
} }
} }
protected firstUpdated(_changedProperties: PropertyValues): void {
this.hass!.loadFragmentTranslation("config");
this.hass!.loadBackendTranslation("device_automation");
}
protected render() { protected render() {
if (!this.hass) { if (!this.hass) {
return nothing; return nothing;
@@ -218,6 +251,17 @@ export class HuiActionEditor extends LitElement {
</ha-form> </ha-form>
` `
: nothing} : nothing}
${this.config?.action === "sequence"
? html`
<ha-form
.hass=${this.hass}
.schema=${SEQUENCE_SCHEMA}
.data=${this.config}
.computeLabel=${this._computeFormLabel}
@value-changed=${this._formValueChanged}
></ha-form>
`
: nothing}
`; `;
} }
@@ -289,7 +333,15 @@ export class HuiActionEditor extends LitElement {
}); });
} }
private _computeFormLabel(schema: SchemaUnion<typeof ASSIST_SCHEMA>) { private _computeFormLabel(
schema:
| SchemaUnion<typeof ASSIST_SCHEMA>
| SchemaUnion<typeof NAVIGATE_SCHEMA>
| SchemaUnion<typeof SEQUENCE_SCHEMA>
) {
if (schema.name === "actions") {
return "";
}
return this.hass?.localize( return this.hass?.localize(
`ui.panel.lovelace.editor.action-editor.${schema.name}` `ui.panel.lovelace.editor.action-editor.${schema.name}`
); );

View File

@@ -48,6 +48,12 @@ const actionConfigStructService = object({
confirmation: optional(actionConfigStructConfirmation), confirmation: optional(actionConfigStructConfirmation),
}); });
const actionConfigStructSequence = object({
action: literal("sequence"),
actions: optional(array(object())),
confirmation: optional(actionConfigStructConfirmation),
});
const actionConfigStructNavigate = object({ const actionConfigStructNavigate = object({
action: literal("navigate"), action: literal("navigate"),
navigation_path: string(), navigation_path: string(),
@@ -101,6 +107,9 @@ export const actionConfigStruct = dynamic<any>((value) => {
case "more-info": { case "more-info": {
return actionConfigStructMoreInfo; return actionConfigStructMoreInfo;
} }
case "sequence": {
return actionConfigStructSequence;
}
} }
} }

View File

@@ -5752,10 +5752,12 @@
"more-info": "More info", "more-info": "More info",
"toggle": "Toggle", "toggle": "Toggle",
"navigate": "Navigate", "navigate": "Navigate",
"sequence": "Sequence",
"assist": "Assist", "assist": "Assist",
"url": "URL", "url": "URL",
"none": "Nothing" "none": "Nothing"
} },
"sequence_actions": "Actions"
}, },
"condition-editor": { "condition-editor": {
"explanation": "The card will be shown when ALL conditions below are fulfilled.", "explanation": "The card will be shown when ALL conditions below are fulfilled.",