@dxos/plugin-routine 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PLUGIN.mdl +18 -13
- package/dist/lib/RoutinePlugin.mjs +2 -0
- package/dist/lib/RoutinePlugin.node.mjs +894 -0
- package/dist/lib/RoutinePlugin.node.mjs.map +1 -0
- package/dist/lib/RoutinePlugin.workerd.mjs +20 -0
- package/dist/lib/RoutinePlugin.workerd.mjs.map +1 -0
- package/dist/lib/capabilities/node.mjs +12 -0
- package/dist/lib/capabilities/node.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +14 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-RoutineArticle.mjs +79 -0
- package/dist/lib/chunk-RoutineArticle.mjs.map +1 -0
- package/dist/lib/chunk-RoutineCompanion.mjs +192 -0
- package/dist/lib/chunk-RoutineCompanion.mjs.map +1 -0
- package/dist/lib/chunk-RoutinePlugin.mjs +38 -0
- package/dist/lib/chunk-RoutinePlugin.mjs.map +1 -0
- package/dist/lib/chunk-RoutineSettings.mjs +50 -0
- package/dist/lib/chunk-RoutineSettings.mjs.map +1 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs +208 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs.map +1 -0
- package/dist/lib/chunk-SkillArticle.mjs +28 -0
- package/dist/lib/chunk-SkillArticle.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +71 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +23 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-create-routine.mjs +34 -0
- package/dist/lib/chunk-create-routine.mjs.map +1 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs +48 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs.map +1 -0
- package/dist/lib/chunk-layer-specs.mjs +179 -0
- package/dist/lib/chunk-layer-specs.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-HLO4LYXT.mjs → chunk-meta.mjs} +19 -27
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +11 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +11 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +64 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-registry-sync.mjs +104 -0
- package/dist/lib/chunk-registry-sync.mjs.map +1 -0
- package/dist/lib/chunk-run-routine.mjs +57 -0
- package/dist/lib/chunk-run-routine.mjs.map +1 -0
- package/dist/lib/chunk-templates.mjs +37 -0
- package/dist/lib/chunk-templates.mjs.map +1 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs +73 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +149 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/chunk-util.mjs +142 -0
- package/dist/lib/chunk-util.mjs.map +1 -0
- package/dist/lib/components.mjs +1645 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +11 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/hooks.mjs +37 -0
- package/dist/lib/hooks.mjs.map +1 -0
- package/dist/lib/index.mjs +5 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/testing.mjs +2 -0
- package/dist/lib/translations.mjs +110 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/RoutinePlugin.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.node.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/layer-specs.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/registry-sync.d.ts +1 -1
- package/dist/types/src/capabilities/templates.d.ts +1 -1
- package/dist/types/src/capabilities/trigger-runtime-controller.d.ts +1 -1
- package/dist/types/src/commands/trigger/create/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/create/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/update/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/util.d.ts +1 -1
- package/dist/types/src/commands/trigger/util.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts +7 -5
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts +3 -3
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts +9 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts +21 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/index.d.ts +2 -0
- package/dist/types/src/components/RoutineCard/index.d.ts.map +1 -0
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts +7 -2
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/Schedule.d.ts +2 -26
- package/dist/types/src/components/Schedule/Schedule.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/days.d.ts +24 -0
- package/dist/types/src/components/Schedule/days.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts +3 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/index.d.ts +2 -0
- package/dist/types/src/components/Schedule/index.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -2
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts +5 -2
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts +5 -0
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +5 -10
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts +6 -2
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts +4 -12
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts +4 -8
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts +5 -3
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts.map +1 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts +4 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts.map +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.test.d.ts +2 -0
- package/dist/types/src/operations/run-routine.test.d.ts.map +1 -0
- package/dist/types/src/paths.d.ts.map +1 -1
- package/dist/types/src/templates/index.d.ts +1 -1
- package/dist/types/src/templates/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-functions.d.ts +30 -6
- package/dist/types/src/testing/test-functions.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/RoutineCapabilities.d.ts +9 -3
- package/dist/types/src/types/RoutineCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/RoutineOperation.d.ts +2 -3
- package/dist/types/src/types/RoutineOperation.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +0 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/routines-for-object.d.ts +6 -3
- package/dist/types/src/util/routines-for-object.d.ts.map +1 -1
- package/dist/types/src/util/wire.d.ts +21 -0
- package/dist/types/src/util/wire.d.ts.map +1 -0
- package/dist/types/src/util/wire.test.d.ts +2 -0
- package/dist/types/src/util/wire.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +3 -2
- package/package.json +73 -71
- package/src/RoutinePlugin.node.ts +1 -2
- package/src/RoutinePlugin.tsx +2 -4
- package/src/RoutinePlugin.workerd.ts +1 -2
- package/src/capabilities/app-graph-builder.ts +9 -7
- package/src/capabilities/create-object.ts +2 -2
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/layer-specs.ts +78 -12
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +18 -22
- package/src/capabilities/trigger-runtime-controller.test.ts +12 -18
- package/src/capabilities/trigger-runtime-controller.ts +22 -25
- package/src/commands/trigger/create/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/create/index.ts +2 -2
- package/src/commands/trigger/update/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/update/index.ts +2 -2
- package/src/commands/trigger/util.ts +1 -2
- package/src/components/InstructionsEditor/InstructionsEditor.stories.tsx +7 -6
- package/src/components/InstructionsEditor/InstructionsEditor.tsx +31 -19
- package/src/components/RoutineCard/RoutineCard.stories.tsx +95 -0
- package/src/components/RoutineCard/RoutineCard.tsx +60 -0
- package/src/components/{MasterDetail → RoutineCard}/index.ts +1 -1
- package/src/components/RoutineForm/RoutineForm.tsx +60 -52
- package/src/components/Schedule/Schedule.stories.tsx +1 -1
- package/src/components/Schedule/Schedule.tsx +4 -73
- package/src/components/Schedule/days.ts +18 -0
- package/src/components/Schedule/describe-schedule.ts +64 -0
- package/src/components/Schedule/index.ts +2 -0
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +1 -1
- package/src/components/TemplateEditor/TemplateForm.tsx +1 -1
- package/src/components/TriggerEditor/TriggerEditor.stories.tsx +3 -3
- package/src/components/TriggerEditor/TriggerEditor.tsx +79 -66
- package/src/components/TriggerEditor/TriggerKindSelector.tsx +4 -30
- package/src/components/TriggerEditor/trigger-kind-icon.ts +38 -0
- package/src/components/index.ts +1 -1
- package/src/containers/RoutineArticle/RoutineArticle.stories.tsx +78 -19
- package/src/containers/RoutineArticle/RoutineArticle.tsx +8 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.stories.tsx +5 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.tsx +11 -7
- package/src/containers/RoutineSettings/RoutineSettings.tsx +22 -33
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.tsx +6 -5
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.tsx +3 -1
- package/src/containers/RoutineTraceCompanion/useRoutineRuns.ts +3 -5
- package/src/containers/SkillArticle/SkillArticle.tsx +2 -0
- package/src/hooks/useTriggerRuntimeControls.ts +2 -2
- package/src/index.ts +1 -0
- package/src/operations/create-routine.ts +1 -1
- package/src/operations/create-trigger-from-template.ts +2 -2
- package/src/operations/run-routine.test.ts +150 -0
- package/src/operations/run-routine.ts +18 -2
- package/src/paths.ts +5 -5
- package/src/templates/index.ts +5 -3
- package/src/translations.ts +5 -6
- package/src/types/RoutineCapabilities.ts +10 -4
- package/src/types/RoutineOperation.ts +7 -6
- package/src/types/index.ts +0 -1
- package/src/util/index.ts +1 -0
- package/src/util/routines-for-object.test.ts +37 -5
- package/src/util/routines-for-object.ts +33 -8
- package/src/util/wire.test.ts +77 -0
- package/src/util/wire.ts +76 -0
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs +0 -95
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs.map +0 -7
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs +0 -249
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.mjs +0 -10
- package/dist/lib/neutral/RoutinePlugin.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.node.mjs +0 -1133
- package/dist/lib/neutral/RoutinePlugin.node.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs +0 -36
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs +0 -48
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs.map +0 -7
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs +0 -236
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs.map +0 -7
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs +0 -27
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs +0 -90
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -25
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/node.mjs +0 -19
- package/dist/lib/neutral/capabilities/node.mjs.map +0 -7
- package/dist/lib/neutral/chunk-674LDIUJ.mjs +0 -9
- package/dist/lib/neutral/chunk-674LDIUJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HLO4LYXT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs +0 -8
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs +0 -263
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WLNL77C7.mjs +0 -14
- package/dist/lib/neutral/chunk-WLNL77C7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs +0 -65
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -1921
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -17
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs +0 -25
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs.map +0 -7
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs +0 -38
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs.map +0 -7
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs +0 -70
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs.map +0 -7
- package/dist/lib/neutral/hooks/index.mjs +0 -47
- package/dist/lib/neutral/hooks/index.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -27
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs +0 -135
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs +0 -13
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs +0 -67
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs.map +0 -7
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs +0 -86
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs.map +0 -7
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs +0 -37
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs.map +0 -7
- package/dist/lib/neutral/templates-IIUCEBAX.mjs +0 -49
- package/dist/lib/neutral/templates-IIUCEBAX.mjs.map +0 -7
- package/dist/lib/neutral/testing.mjs +0 -8
- package/dist/lib/neutral/testing.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -115
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs +0 -77
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -17
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/create/queue.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/update/queue.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts +0 -51
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts +0 -16
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/index.d.ts +0 -2
- package/dist/types/src/components/MasterDetail/index.d.ts.map +0 -1
- package/dist/types/src/types/Routine.d.ts +0 -55
- package/dist/types/src/types/Routine.d.ts.map +0 -1
- package/dist/types/src/types/Routine.test.d.ts +0 -2
- package/dist/types/src/types/Routine.test.d.ts.map +0 -1
- package/src/capabilities/navigation-resolver.ts +0 -21
- package/src/components/MasterDetail/MasterDetail.stories.tsx +0 -100
- package/src/components/MasterDetail/MasterDetail.tsx +0 -175
- package/src/types/Routine.test.ts +0 -51
- package/src/types/Routine.ts +0 -144
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import React, { type PropsWithChildren, useCallback, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import { Instructions, Operation, Trigger } from '@dxos/compute';
|
|
8
|
+
import { Instructions, Operation, Routine, Trigger } from '@dxos/compute';
|
|
9
9
|
import { type Database, DXN, Entity, Filter, Obj, Query, Ref, Scope, Type } from '@dxos/echo';
|
|
10
|
-
import { useObject, useQuery } from '@dxos/react
|
|
11
|
-
import { ToggleGroup, ToggleGroupItem, useTranslation } from '@dxos/react-ui';
|
|
10
|
+
import { useObject, useQuery } from '@dxos/echo-react';
|
|
11
|
+
import { ToggleGroup, ToggleGroupItem, composable, composableProps, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import { Form, type FormFieldMap, RefField } from '@dxos/react-ui-form';
|
|
13
13
|
|
|
14
14
|
import { meta } from '#meta';
|
|
15
|
-
import { Routine } from '#types';
|
|
16
15
|
|
|
16
|
+
import { wireTriggers } from '../../util';
|
|
17
17
|
import { InstructionsEditor } from '../InstructionsEditor';
|
|
18
18
|
import { TriggerEditor } from '../TriggerEditor';
|
|
19
19
|
|
|
@@ -45,59 +45,67 @@ export type RoutineFormProps = {
|
|
|
45
45
|
* The sub-forms read and autosave the routine's owned instructions and primary trigger directly off the
|
|
46
46
|
* `routine` graph (live editing); `readonly` displays them without edit affordances. The optional Save/Cancel
|
|
47
47
|
* row is used only by the companion's create-from-template flow.
|
|
48
|
+
*
|
|
49
|
+
* Created with `composable()` so it carries the COMPOSABLE marker and can be the child of
|
|
50
|
+
* `Panel.Content asChild` (forwards ref and merges layout props onto the scroll viewport).
|
|
48
51
|
*/
|
|
49
|
-
export const RoutineForm =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
export const RoutineForm = composable<HTMLDivElement, RoutineFormProps>(
|
|
53
|
+
({ db, routine, readonly = false, onSave, onCancel, ...props }, forwardedRef) => {
|
|
54
|
+
const { t } = useTranslation(meta.profile.key);
|
|
55
|
+
const [auto, updateAuto] = useObject(routine);
|
|
56
|
+
const trigger = usePrimaryTrigger(routine);
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const handleValuesChanged = useCallback(
|
|
60
|
-
(values: Partial<GeneralForm>) => {
|
|
61
|
-
updateAuto((routine) => {
|
|
62
|
-
routine.name = values.name;
|
|
63
|
-
routine.description = values.description;
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
[updateAuto],
|
|
67
|
-
);
|
|
58
|
+
// Read once per routine identity; the uncontrolled form owns edits after mount.
|
|
59
|
+
const defaultValues = useMemo<Partial<GeneralForm>>(
|
|
60
|
+
() => ({ name: auto.name, description: auto.description }),
|
|
61
|
+
[routine],
|
|
62
|
+
);
|
|
68
63
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<Form.Viewport scroll>
|
|
79
|
-
<Form.Content>
|
|
80
|
-
<Form.FieldSet />
|
|
64
|
+
const handleValuesChanged = useCallback(
|
|
65
|
+
(values: Partial<GeneralForm>) => {
|
|
66
|
+
updateAuto((routine) => {
|
|
67
|
+
routine.name = values.name;
|
|
68
|
+
routine.description = values.description;
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
[updateAuto],
|
|
72
|
+
);
|
|
81
73
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
// TODO(burdon): Could this be rewritten a single form with custom fields?
|
|
75
|
+
return (
|
|
76
|
+
<Form.Root
|
|
77
|
+
schema={GeneralForm}
|
|
78
|
+
readonly={readonly}
|
|
79
|
+
defaultValues={defaultValues}
|
|
80
|
+
onValuesChanged={handleValuesChanged}
|
|
81
|
+
onSave={onSave}
|
|
82
|
+
onCancel={onCancel}
|
|
83
|
+
>
|
|
84
|
+
<Form.Viewport scroll {...composableProps(props)} ref={forwardedRef}>
|
|
85
|
+
<Form.Content>
|
|
86
|
+
<Form.FieldSet />
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
<Section title={t('actions.title')}>
|
|
89
|
+
<ActionEditor db={db} routine={routine} readonly={readonly} />
|
|
90
|
+
</Section>
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
92
|
+
{/* TODO(burdon): Support multiple triggers. */}
|
|
93
|
+
<Section title={t('triggers.title')}>
|
|
94
|
+
<TriggerEditor db={db} routine={routine} trigger={trigger} readonly={readonly} />
|
|
95
|
+
</Section>
|
|
96
|
+
|
|
97
|
+
{/* Save/Cancel for the edit session (the sub-forms autosave to the in-memory clones as they change). */}
|
|
98
|
+
{onSave && <Form.Actions />}
|
|
99
|
+
</Form.Content>
|
|
100
|
+
</Form.Viewport>
|
|
101
|
+
</Form.Root>
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
);
|
|
97
105
|
|
|
98
106
|
/** Lightweight labelled grouping for a sub-form (no `Settings` chrome). */
|
|
99
107
|
const Section = ({ title, children }: PropsWithChildren<{ title: string }>) => (
|
|
100
|
-
<div
|
|
108
|
+
<div className='flex flex-col mbs-4'>
|
|
101
109
|
<Form.Label standalone label={title} />
|
|
102
110
|
{children}
|
|
103
111
|
</div>
|
|
@@ -111,7 +119,7 @@ const Section = ({ title, children }: PropsWithChildren<{ title: string }>) => (
|
|
|
111
119
|
* Single action: an Operation (the routine's `spec.runnable`) or an owned Instructions edited inline. The
|
|
112
120
|
* action kind is derived from the routine's `spec` — an absent spec means "operation, none chosen yet" (a
|
|
113
121
|
* scaffolded routine always carries an instructions spec, so the only way to clear it is switching to an
|
|
114
|
-
* operation). `
|
|
122
|
+
* operation). `makeRoutine` establishes the owned-instructions wiring when the routine is scaffolded.
|
|
115
123
|
*/
|
|
116
124
|
const ActionEditor = ({
|
|
117
125
|
db,
|
|
@@ -139,7 +147,7 @@ const ActionEditor = ({
|
|
|
139
147
|
routine.spec = operation ? { kind: 'runnable', runnable: operation } : undefined;
|
|
140
148
|
});
|
|
141
149
|
// Keep the owned trigger's `function`/`input` in sync with the new action.
|
|
142
|
-
|
|
150
|
+
wireTriggers(routineProp);
|
|
143
151
|
},
|
|
144
152
|
[updateRoutine, routineProp],
|
|
145
153
|
);
|
|
@@ -159,13 +167,13 @@ const ActionEditor = ({
|
|
|
159
167
|
}
|
|
160
168
|
});
|
|
161
169
|
// Re-wire the owned trigger to dispatch the new action (RunInstructions vs the operation).
|
|
162
|
-
|
|
170
|
+
wireTriggers(routineProp);
|
|
163
171
|
},
|
|
164
172
|
[updateRoutine, routineProp],
|
|
165
173
|
);
|
|
166
174
|
|
|
167
175
|
return (
|
|
168
|
-
<div
|
|
176
|
+
<div className='flex flex-col'>
|
|
169
177
|
{!readonly && <ActionKindToggle value={kind} onChange={handleKindChange} />}
|
|
170
178
|
{kind === 'runnable' ? (
|
|
171
179
|
<OperationEditor
|
|
@@ -17,7 +17,7 @@ const DefaultStory = ({ initial, minInterval }: { initial: ScheduleValue; minInt
|
|
|
17
17
|
return (
|
|
18
18
|
<div className='p-4 flex flex-col gap-3'>
|
|
19
19
|
<Schedule.Root
|
|
20
|
-
classNames='
|
|
20
|
+
classNames='dx-card-surface border border-separator rounded-sm p-2'
|
|
21
21
|
timezone='EDT'
|
|
22
22
|
minInterval={minInterval}
|
|
23
23
|
value={value}
|
|
@@ -18,14 +18,9 @@ import { mx } from '@dxos/ui-theme';
|
|
|
18
18
|
|
|
19
19
|
import { meta } from '#meta';
|
|
20
20
|
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
describeCron,
|
|
25
|
-
fromCron,
|
|
26
|
-
scheduleIntervalSeconds,
|
|
27
|
-
scheduleToCron,
|
|
28
|
-
} from './cron';
|
|
21
|
+
import { MAX_MIN_INTERVAL_SECONDS, clampSchedule, fromCron, scheduleIntervalSeconds, scheduleToCron } from './cron';
|
|
22
|
+
import { type Day, Days } from './days';
|
|
23
|
+
import { describeSchedule } from './describe-schedule';
|
|
29
24
|
|
|
30
25
|
//
|
|
31
26
|
// Value model.
|
|
@@ -40,21 +35,11 @@ export const ScheduleKinds = [
|
|
|
40
35
|
'monthly',
|
|
41
36
|
'custom',
|
|
42
37
|
] as const;
|
|
38
|
+
|
|
43
39
|
export type ScheduleKind = (typeof ScheduleKinds)[number];
|
|
44
40
|
|
|
45
41
|
const isScheduleKind = (value: string): value is ScheduleKind => (ScheduleKinds as readonly string[]).includes(value);
|
|
46
42
|
|
|
47
|
-
export const Days = [
|
|
48
|
-
{ value: 'mon', label: 'Mon' },
|
|
49
|
-
{ value: 'tue', label: 'Tue' },
|
|
50
|
-
{ value: 'wed', label: 'Wed' },
|
|
51
|
-
{ value: 'thu', label: 'Thu' },
|
|
52
|
-
{ value: 'fri', label: 'Fri' },
|
|
53
|
-
{ value: 'sat', label: 'Sat' },
|
|
54
|
-
{ value: 'sun', label: 'Sun' },
|
|
55
|
-
] as const;
|
|
56
|
-
export type Day = (typeof Days)[number]['value'];
|
|
57
|
-
|
|
58
43
|
/** Discriminated schedule value. Times are `HH:mm` (24h); `once.date` is `YYYY-MM-DDTHH:mm`. */
|
|
59
44
|
export type ScheduleValue =
|
|
60
45
|
// | { kind: 'once'; date?: string }
|
|
@@ -471,57 +456,3 @@ const ScheduleEditor = ({ value, onChange }: { value: ScheduleValue; onChange: (
|
|
|
471
456
|
//
|
|
472
457
|
// Summary.
|
|
473
458
|
//
|
|
474
|
-
|
|
475
|
-
const DAY_NAMES: Record<Day, string> = {
|
|
476
|
-
mon: 'Monday',
|
|
477
|
-
tue: 'Tuesday',
|
|
478
|
-
wed: 'Wednesday',
|
|
479
|
-
thu: 'Thursday',
|
|
480
|
-
fri: 'Friday',
|
|
481
|
-
sat: 'Saturday',
|
|
482
|
-
sun: 'Sunday',
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
/** Format a `HH:mm` (24h) time as a 12-hour clock string, e.g. `9:00 AM`. */
|
|
486
|
-
const formatTime = (time: string): string => {
|
|
487
|
-
const [h, m] = time.split(':').map(Number);
|
|
488
|
-
if (Number.isNaN(h) || Number.isNaN(m)) {
|
|
489
|
-
return time;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
const period = h < 12 ? 'AM' : 'PM';
|
|
493
|
-
const hour = h % 12 === 0 ? 12 : h % 12;
|
|
494
|
-
return `${hour}:${String(m).padStart(2, '0')} ${period}`;
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
const withZone = (text: string, timezone?: string): string => (timezone ? `${text} ${timezone}` : text);
|
|
498
|
-
|
|
499
|
-
/** Human-readable summary of the schedule, suitable for the header. */
|
|
500
|
-
// TODO(wittjosiah): Just use cronstrue for all cases?
|
|
501
|
-
export const describeSchedule = (value: ScheduleValue, timezone?: string): string => {
|
|
502
|
-
switch (value.kind) {
|
|
503
|
-
// case 'once':
|
|
504
|
-
// return value.date
|
|
505
|
-
// ? `Runs once at ${formatTime(value.date.slice(11))} on ${value.date.slice(0, 10)}`
|
|
506
|
-
// : 'Runs once';
|
|
507
|
-
case 'hourly':
|
|
508
|
-
return `Runs every hour at minute ${value.minute}`;
|
|
509
|
-
case 'daily':
|
|
510
|
-
return withZone(`Runs every day at ${formatTime(value.time)}`, timezone);
|
|
511
|
-
case 'weekly': {
|
|
512
|
-
const days =
|
|
513
|
-
value.days.length === 0
|
|
514
|
-
? 'no days'
|
|
515
|
-
: value.days.length === 1
|
|
516
|
-
? DAY_NAMES[value.days[0]]
|
|
517
|
-
: Days.filter((d) => value.days.includes(d.value))
|
|
518
|
-
.map((d) => d.label)
|
|
519
|
-
.join(', ');
|
|
520
|
-
return withZone(`Runs every ${days} at ${formatTime(value.time)}`, timezone);
|
|
521
|
-
}
|
|
522
|
-
case 'monthly':
|
|
523
|
-
return withZone(`Runs monthly on day ${value.day} at ${formatTime(value.time)}`, timezone);
|
|
524
|
-
case 'custom':
|
|
525
|
-
return withZone(describeCron(value.cron), timezone);
|
|
526
|
-
}
|
|
527
|
-
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// Shared by `Schedule.tsx` and `describe-schedule.ts`: a value import between those two would close a
|
|
6
|
+
// runtime cycle, and react-refresh only fast-refreshes a module whose exports are all components.
|
|
7
|
+
|
|
8
|
+
export const Days = [
|
|
9
|
+
{ value: 'mon', label: 'Mon' },
|
|
10
|
+
{ value: 'tue', label: 'Tue' },
|
|
11
|
+
{ value: 'wed', label: 'Wed' },
|
|
12
|
+
{ value: 'thu', label: 'Thu' },
|
|
13
|
+
{ value: 'fri', label: 'Fri' },
|
|
14
|
+
{ value: 'sat', label: 'Sat' },
|
|
15
|
+
{ value: 'sun', label: 'Sun' },
|
|
16
|
+
] as const;
|
|
17
|
+
|
|
18
|
+
export type Day = (typeof Days)[number]['value'];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describeCron } from './cron';
|
|
6
|
+
import { type Day, Days } from './days';
|
|
7
|
+
import { type ScheduleValue } from './Schedule';
|
|
8
|
+
|
|
9
|
+
// Kept out of `Schedule.tsx`: react-refresh only fast-refreshes a module whose
|
|
10
|
+
// exports are all components, so values exported beside them force a full page reload on
|
|
11
|
+
// every edit.
|
|
12
|
+
|
|
13
|
+
/** Human-readable summary of the schedule, suitable for the header. */
|
|
14
|
+
// TODO(wittjosiah): Just use cronstrue for all cases?
|
|
15
|
+
const DAY_NAMES: Record<Day, string> = {
|
|
16
|
+
mon: 'Monday',
|
|
17
|
+
tue: 'Tuesday',
|
|
18
|
+
wed: 'Wednesday',
|
|
19
|
+
thu: 'Thursday',
|
|
20
|
+
fri: 'Friday',
|
|
21
|
+
sat: 'Saturday',
|
|
22
|
+
sun: 'Sunday',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const withZone = (text: string, timezone?: string): string => (timezone ? `${text} ${timezone}` : text);
|
|
26
|
+
|
|
27
|
+
const formatTime = (time: string): string => {
|
|
28
|
+
const [h, m] = time.split(':').map(Number);
|
|
29
|
+
if (Number.isNaN(h) || Number.isNaN(m)) {
|
|
30
|
+
return time;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const period = h < 12 ? 'AM' : 'PM';
|
|
34
|
+
const hour = h % 12 === 0 ? 12 : h % 12;
|
|
35
|
+
return `${hour}:${String(m).padStart(2, '0')} ${period}`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const describeSchedule = (value: ScheduleValue, timezone?: string): string => {
|
|
39
|
+
switch (value.kind) {
|
|
40
|
+
// case 'once':
|
|
41
|
+
// return value.date
|
|
42
|
+
// ? `Runs once at ${formatTime(value.date.slice(11))} on ${value.date.slice(0, 10)}`
|
|
43
|
+
// : 'Runs once';
|
|
44
|
+
case 'hourly':
|
|
45
|
+
return `Runs every hour at minute ${value.minute}`;
|
|
46
|
+
case 'daily':
|
|
47
|
+
return withZone(`Runs every day at ${formatTime(value.time)}`, timezone);
|
|
48
|
+
case 'weekly': {
|
|
49
|
+
const days =
|
|
50
|
+
value.days.length === 0
|
|
51
|
+
? 'no days'
|
|
52
|
+
: value.days.length === 1
|
|
53
|
+
? DAY_NAMES[value.days[0]]
|
|
54
|
+
: Days.filter((d) => value.days.includes(d.value))
|
|
55
|
+
.map((d) => d.label)
|
|
56
|
+
.join(', ');
|
|
57
|
+
return withZone(`Runs every ${days} at ${formatTime(value.time)}`, timezone);
|
|
58
|
+
}
|
|
59
|
+
case 'monthly':
|
|
60
|
+
return withZone(`Runs monthly on day ${value.day} at ${formatTime(value.time)}`, timezone);
|
|
61
|
+
case 'custom':
|
|
62
|
+
return withZone(describeCron(value.cron), timezone);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
@@ -55,7 +55,7 @@ const DefaultStory = ({ source }: TemplateEditorProps & { source: string }) => {
|
|
|
55
55
|
);
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
return <TemplateEditor classNames='dx-document
|
|
58
|
+
return <TemplateEditor classNames='dx-document dx-base-surface' id={skill.id} source={skill.instructions.source} />;
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const meta = {
|
|
@@ -60,7 +60,7 @@ export const TemplateForm = ({ id, template, onChange }: TemplateFormProps) => {
|
|
|
60
60
|
|
|
61
61
|
return (
|
|
62
62
|
<div className='flex flex-col w-full overflow-hidden gap-4'>
|
|
63
|
-
<TemplateEditor id={id} source={template.source} classNames='
|
|
63
|
+
<TemplateEditor id={id} source={template.source} classNames='dx-base-surface min-h-[120px]' />
|
|
64
64
|
|
|
65
65
|
{(template.inputs?.length ?? 0) > 0 && (
|
|
66
66
|
<div className='grid grid-cols-[10rem_10rem_1fr] gap-1 items-center'>
|
|
@@ -6,14 +6,14 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { expect, userEvent, within } from 'storybook/test';
|
|
8
8
|
|
|
9
|
-
import { Trigger } from '@dxos/compute';
|
|
9
|
+
import { Routine, Trigger } from '@dxos/compute';
|
|
10
10
|
import { Feed, Filter, Obj } from '@dxos/echo';
|
|
11
|
-
import {
|
|
11
|
+
import { useQuery } from '@dxos/echo-react';
|
|
12
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
12
13
|
import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
|
|
13
14
|
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
14
15
|
|
|
15
16
|
import { translations } from '#translations';
|
|
16
|
-
import { Routine } from '#types';
|
|
17
17
|
|
|
18
18
|
import { TriggerEditor } from './TriggerEditor';
|
|
19
19
|
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import React, { useCallback, useMemo, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { Trigger } from '@dxos/compute';
|
|
8
|
+
import { Routine, Trigger } from '@dxos/compute';
|
|
9
9
|
import { type Database, DXN, Feed, Filter, Obj, Query, Ref, Scope, Type } from '@dxos/echo';
|
|
10
|
-
import { useQuery } from '@dxos/react
|
|
10
|
+
import { useQuery } from '@dxos/echo-react';
|
|
11
11
|
import { IconButton, Input, ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import { Form, type FormFieldMap, type FormFieldRendererProps, SelectField } from '@dxos/react-ui-form';
|
|
13
13
|
import { ParentLabelAnnotation } from '@dxos/schema';
|
|
14
14
|
import { mx } from '@dxos/ui-theme';
|
|
15
15
|
|
|
16
16
|
import { meta } from '#meta';
|
|
17
|
-
import { Routine } from '#types';
|
|
18
17
|
|
|
18
|
+
import { wireTriggers } from '../../util';
|
|
19
19
|
import {
|
|
20
20
|
FrequencyDefaults,
|
|
21
21
|
Schedule,
|
|
@@ -30,10 +30,8 @@ import { type TriggerKind, TriggerKindSelector } from './TriggerKindSelector';
|
|
|
30
30
|
// A recurring trigger fires on a cron, so the one-time `once` kind is not offered here.
|
|
31
31
|
const RECURRING_KINDS = ['hourly', 'daily', 'weekly', 'monthly', 'custom'] as const satisfies readonly ScheduleKind[];
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
// surfaces it once a kind is chosen; the value is written back to `trigger.enabled`, not the spec.
|
|
36
|
-
const EnabledForm = Type.getSchema(Trigger.Trigger).pipe(Schema.pick('enabled'));
|
|
33
|
+
// `enabled` is extended onto every spec form so it renders inline with the kind's fields.
|
|
34
|
+
const EnabledForm = Type.getSchema(Trigger.Trigger).pipe(Schema.pick('enabled', 'remote'));
|
|
37
35
|
|
|
38
36
|
// Scoped trigger form, modeled as a top-level discriminated union (one member per pluggable variant) so the
|
|
39
37
|
// Form renders the chosen kind's fields as one flat field set (no nested, bordered sub-fieldset). The kind
|
|
@@ -186,50 +184,51 @@ export type TriggerEditorProps = ThemedClassName<{
|
|
|
186
184
|
|
|
187
185
|
export const TriggerEditor = ({ classNames, db, routine, trigger, readonly }: TriggerEditorProps) => {
|
|
188
186
|
const { t } = useTranslation(meta.profile.key);
|
|
189
|
-
const { defaultValues, fieldMap, kind,
|
|
190
|
-
routine,
|
|
191
|
-
trigger,
|
|
192
|
-
);
|
|
187
|
+
const { defaultValues, fieldMap, kind, reset, handleValuesChanged } = useTriggerForm(routine, trigger);
|
|
193
188
|
|
|
194
|
-
// TODO(burdon): Not persistent; need to memo
|
|
195
189
|
return (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
{(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
190
|
+
<>
|
|
191
|
+
<Form.Root
|
|
192
|
+
// Remount when the bound trigger changes or its spec kind changes (including reset to no kind),
|
|
193
|
+
// so the uncontrolled form re-reads `defaultValues`; stable while editing fields within a kind.
|
|
194
|
+
key={`${trigger?.id ?? 'new'}:${trigger?.spec?.kind ?? 'none'}`}
|
|
195
|
+
schema={TriggerForm}
|
|
196
|
+
db={db}
|
|
197
|
+
readonly={readonly}
|
|
198
|
+
fieldMap={fieldMap}
|
|
199
|
+
defaultValues={defaultValues}
|
|
200
|
+
onValuesChanged={handleValuesChanged}
|
|
201
|
+
>
|
|
202
|
+
{/* TODO(burdon): Generalize Form handling (indented section) for discriminated unions. */}
|
|
203
|
+
<Form.Content classNames={mx(kind && 'pb-2 dx-card-surface border border-separator rounded-xs', classNames)}>
|
|
204
|
+
{kind ? (
|
|
205
|
+
<>
|
|
206
|
+
<div className='flex items-center'>
|
|
207
|
+
<Input.Root>
|
|
208
|
+
<Input.Label classNames='pl-2 grow truncate'>{t(`trigger-kind.${kind}.label`)}</Input.Label>
|
|
209
|
+
</Input.Root>
|
|
210
|
+
{!readonly && (
|
|
211
|
+
<IconButton
|
|
212
|
+
variant='ghost'
|
|
213
|
+
icon='ph--x--regular'
|
|
214
|
+
iconOnly
|
|
215
|
+
square
|
|
216
|
+
label={t('trigger-kind.clear.label')}
|
|
217
|
+
onClick={reset}
|
|
218
|
+
/>
|
|
219
|
+
)}
|
|
220
|
+
</div>
|
|
221
|
+
<Form.FieldSet classNames='px-2' />
|
|
222
|
+
</>
|
|
223
|
+
) : (
|
|
224
|
+
<Form.FieldSet />
|
|
225
|
+
)}
|
|
226
|
+
|
|
227
|
+
{/* Currently, email triggers have no configuration; surface an explanatory note instead of an empty body. */}
|
|
228
|
+
{kind === 'email' && <p className='px-2 text-sm text-description'>{t('trigger-kind.email-note.message')}</p>}
|
|
229
|
+
</Form.Content>
|
|
230
|
+
</Form.Root>
|
|
231
|
+
</>
|
|
233
232
|
);
|
|
234
233
|
};
|
|
235
234
|
|
|
@@ -301,22 +300,25 @@ const useTriggerForm = (routine: Routine.Routine, trigger?: Trigger.Trigger) =>
|
|
|
301
300
|
[methodOptions],
|
|
302
301
|
);
|
|
303
302
|
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
//
|
|
307
|
-
// `enabled` is a Trigger-level field, seeded alongside the spec-derived variant values.
|
|
303
|
+
// Seed from the trigger's current spec/enabled; a trigger with no spec starts with no kind (picker).
|
|
304
|
+
// Depend on `spec`/`enabled` (not just `trigger` identity) so an in-place clear/change recomputes the
|
|
305
|
+
// seed — the Form re-reads it on remount (keyed by `spec.kind`), reverting to the picker on reset.
|
|
308
306
|
const defaultValues = useMemo<Partial<TriggerFormValues>>(
|
|
309
|
-
() => ({
|
|
310
|
-
|
|
307
|
+
() => ({
|
|
308
|
+
...triggerFormValues(trigger?.spec),
|
|
309
|
+
enabled: trigger?.enabled,
|
|
310
|
+
remote: trigger?.remote,
|
|
311
|
+
}),
|
|
312
|
+
[trigger, trigger?.spec, trigger?.enabled, trigger?.remote],
|
|
311
313
|
);
|
|
312
314
|
|
|
313
315
|
// Mirror the active kind: gates the variant picker (shown only while unset) and the variant-specific notes.
|
|
314
316
|
const [kind, setKind] = useState<TriggerKind | undefined>(() => triggerFormValues(trigger?.spec).kind);
|
|
315
317
|
|
|
316
|
-
// Revert the kind selection: clear the trigger's spec
|
|
317
|
-
|
|
318
|
+
// Revert the kind selection: clear the trigger's spec. Clearing changes `spec.kind`, which is part of
|
|
319
|
+
// the Form's `key`, so the form remounts and re-reads `defaultValues` (picker reappears) — no nonce needed.
|
|
320
|
+
const reset = useCallback(() => {
|
|
318
321
|
setKind(undefined);
|
|
319
|
-
setResetNonce((nonce) => nonce + 1);
|
|
320
322
|
if (trigger) {
|
|
321
323
|
Obj.update(trigger, (trigger) => {
|
|
322
324
|
trigger.spec = undefined;
|
|
@@ -332,11 +334,15 @@ const useTriggerForm = (routine: Routine.Routine, trigger?: Trigger.Trigger) =>
|
|
|
332
334
|
}
|
|
333
335
|
|
|
334
336
|
const spec = triggerFormSpec(values);
|
|
335
|
-
|
|
337
|
+
// `triggerFormSpec` maps `values.kind` 1:1 onto `spec.kind`; use the already-narrowed form kind so
|
|
338
|
+
// the state stays typed as the selectable `TriggerKind` subset (the wider `Trigger.Spec` union now
|
|
339
|
+
// also carries the invoke-only `manual` kind, which the form never produces).
|
|
340
|
+
setKind(values.kind);
|
|
336
341
|
const enabled = values.enabled === true;
|
|
337
|
-
|
|
338
|
-
//
|
|
339
|
-
// `
|
|
342
|
+
const remote = values.remote;
|
|
343
|
+
// Edit the spec, `enabled`, and `remote` on the trigger directly from the form values.
|
|
344
|
+
// The trigger's `function` and `input` (including the instructions binding and any operation-specific
|
|
345
|
+
// bindings like `{ magazine }`) are wired once by `makeRoutine`, so they are not re-derived here.
|
|
340
346
|
if (trigger) {
|
|
341
347
|
Obj.update(trigger, (trigger) => {
|
|
342
348
|
// The subscription spec's QueryAST is deeply readonly while the live ECHO draft's `spec` is mutable;
|
|
@@ -344,22 +350,29 @@ const useTriggerForm = (routine: Routine.Routine, trigger?: Trigger.Trigger) =>
|
|
|
344
350
|
// (mirrors commands/trigger/update/subscription.ts).
|
|
345
351
|
trigger.spec = spec as typeof trigger.spec;
|
|
346
352
|
trigger.enabled = enabled;
|
|
353
|
+
trigger.remote = remote;
|
|
347
354
|
});
|
|
348
355
|
} else {
|
|
349
|
-
// Defensive: the draft normally carries an owned trigger already (see `
|
|
356
|
+
// Defensive: the draft normally carries an owned trigger already (see `makeRoutine`). If absent,
|
|
350
357
|
// create one in memory and attach it to the routine graph — nothing is persisted until save.
|
|
351
|
-
const created = Trigger.make({ spec, enabled });
|
|
358
|
+
const created = Trigger.make({ spec, enabled, remote });
|
|
352
359
|
Obj.setParent(created, routine);
|
|
353
360
|
Obj.update(routine, (routine) => {
|
|
354
361
|
routine.triggers.push(Ref.make(created));
|
|
355
362
|
});
|
|
356
363
|
// Wire the new trigger's `function`/`input` to dispatch the routine's action (RunInstructions binds the
|
|
357
364
|
// owned instructions; an operation binds directly).
|
|
358
|
-
|
|
365
|
+
wireTriggers(routine);
|
|
359
366
|
}
|
|
360
367
|
},
|
|
361
368
|
[routine, trigger],
|
|
362
369
|
);
|
|
363
370
|
|
|
364
|
-
return {
|
|
371
|
+
return {
|
|
372
|
+
defaultValues,
|
|
373
|
+
fieldMap,
|
|
374
|
+
kind,
|
|
375
|
+
reset,
|
|
376
|
+
handleValuesChanged,
|
|
377
|
+
};
|
|
365
378
|
};
|