+
+
+ ${ensureArray(node.sequence).map((action, i) =>
+ this.render_action_node(
+ action,
+ `${path}/sequence/${i}`,
+ false,
+ disabled || node.enabled === false
+ )
+ )}
+
+
+ `;
+ }
+
private render_parallel_node(
node: ParallelAction,
path: string,
diff --git a/src/components/trace/hat-trace-timeline.ts b/src/components/trace/hat-trace-timeline.ts
index 9a440e6ed1..e6be959c92 100644
--- a/src/components/trace/hat-trace-timeline.ts
+++ b/src/components/trace/hat-trace-timeline.ts
@@ -37,6 +37,7 @@ import {
IfAction,
ParallelAction,
RepeatAction,
+ SequenceAction,
getActionType,
} from "../../data/script";
import { describeAction } from "../../data/script_i18n";
@@ -310,6 +311,10 @@ class ActionRenderer {
return this._handleIf(index);
}
+ if (actionType === "sequence") {
+ return this._handleSequence(index);
+ }
+
if (actionType === "parallel") {
return this._handleParallel(index);
}
@@ -579,6 +584,37 @@ class ActionRenderer {
return i;
}
+ private _handleSequence(index: number): number {
+ const sequencePath = this.keys[index];
+ const sequenceConfig = this._getDataFromPath(
+ this.keys[index]
+ ) as SequenceAction;
+
+ this._renderEntry(
+ sequencePath,
+ sequenceConfig.alias ||
+ describeAction(
+ this.hass,
+ this.entityReg,
+ this.labelReg,
+ this.floorReg,
+ sequenceConfig,
+ "sequence"
+ ),
+ undefined,
+ sequenceConfig.enabled === false
+ );
+
+ let i: number;
+
+ for (i = index + 1; i < this.keys.length; i++) {
+ const path = this.keys[i];
+ this._renderItem(i, getActionType(this._getDataFromPath(path)));
+ }
+
+ return i;
+ }
+
private _handleParallel(index: number): number {
const parallelPath = this.keys[index];
const startLevel = parallelPath.split("/").length;
diff --git a/src/data/action.ts b/src/data/action.ts
index c85d5226c8..69a5f9a869 100644
--- a/src/data/action.ts
+++ b/src/data/action.ts
@@ -8,6 +8,7 @@ import {
mdiDevices,
mdiDotsHorizontal,
mdiExcavator,
+ mdiFormatListNumbered,
mdiGestureDoubleTap,
mdiHandBackRight,
mdiPalette,
@@ -35,6 +36,7 @@ export const ACTION_ICONS = {
if: mdiCallSplit,
device_id: mdiDevices,
stop: mdiHandBackRight,
+ sequence: mdiFormatListNumbered,
parallel: mdiShuffleDisabled,
variables: mdiApplicationVariableOutline,
set_conversation_response: mdiBullhorn,
@@ -61,6 +63,7 @@ export const ACTION_GROUPS: AutomationElementGroup = {
choose: {},
if: {},
stop: {},
+ sequence: {},
parallel: {},
variables: {},
},
diff --git a/src/data/script.ts b/src/data/script.ts
index 28aff64dcb..f70ca2d338 100644
--- a/src/data/script.ts
+++ b/src/data/script.ts
@@ -248,6 +248,10 @@ export interface StopAction extends BaseAction {
error?: boolean;
}
+export interface SequenceAction extends BaseAction {
+ sequence: (ManualScriptConfig | Action)[];
+}
+
export interface ParallelAction extends BaseAction {
parallel: ManualScriptConfig | Action | (ManualScriptConfig | Action)[];
}
@@ -274,6 +278,7 @@ export type NonConditionAction =
| VariablesAction
| PlayMediaAction
| StopAction
+ | SequenceAction
| ParallelAction
| UnknownAction;
@@ -299,6 +304,7 @@ export interface ActionTypes {
service: ServiceAction;
play_media: PlayMediaAction;
stop: StopAction;
+ sequence: SequenceAction;
parallel: ParallelAction;
set_conversation_response: SetConversationResponseAction;
unknown: UnknownAction;
@@ -389,6 +395,9 @@ export const getActionType = (action: Action): ActionType => {
if ("stop" in action) {
return "stop";
}
+ if ("sequence" in action) {
+ return "sequence";
+ }
if ("parallel" in action) {
return "parallel";
}
diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts
index 686b52438e..4d518bd57c 100644
--- a/src/data/script_i18n.ts
+++ b/src/data/script_i18n.ts
@@ -29,6 +29,7 @@ import {
PlayMediaAction,
RepeatAction,
SceneAction,
+ SequenceAction,
SetConversationResponseAction,
StopAction,
VariablesAction,
@@ -478,6 +479,15 @@ const tryDescribeAction =