diff --git a/webclient-vue/src/features/areas/pages/AreaDetailPage.vue b/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
index 306f65e..192c87a 100644
--- a/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
+++ b/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
@@ -56,6 +56,45 @@
+
+
Actions ({{ areaActionScripts.length }})
+
+
+
+
+
+ {{ script.description }}
+
+ {{ script.state }}
+ {{ script.scope }}
+
+ {{ script.created_by || script.author }}
+
+
+
+ Run
+
+
+
+
+
+
Scripts ({{ areasStore.currentAreaScripts.length }})
+ areasStore.currentAreaScripts.filter((s) => s.type === "action")
+);
+
const isLastRoot = computed(() => {
if (!area.value) return false;
const isRoot = !area.value.parent_id || area.value.parent_id <= 0;
@@ -290,6 +336,22 @@
const unassignLoading = ref(false);
const unassignError = ref("");
+function goToScriptDetail(alias) {
+ router.push({ name: "script-detail", params: { type: "actions", id: alias } });
+}
+
+async function runAction(alias) {
+ const result = await scriptsStore.runScript(alias);
+ if (result?.ok) {
+ toast.success({
+ title: `Ran ${alias}`,
+ text: scriptsStore.lastRunResult?.execTime ? `Exec time: ${scriptsStore.lastRunResult.execTime}` : undefined,
+ });
+ } else {
+ toast.error({ title: `Failed ${alias}`, text: result?.error?.message || "Unknown error" });
+ }
+}
+
function openRename() {
if (!area.value) return;
renameForm.areaId = area.value.id;
@@ -413,7 +475,8 @@
color: var(--color-muted);
}
-.devices-panel {
+.devices-panel,
+.actions-panel {
margin-bottom: 24px;
}
@@ -424,6 +487,17 @@
color: var(--color-primary);
}
+.script-icon {
+ font-size: 32px;
+}
+
+.script-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+}
+
.form-group {
margin-bottom: 16px;
}