@dxos/plugin-automation 0.8.4-main.b97322e → 0.8.4-main.c4373fc
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/dist/lib/browser/AutomationPanel-PNBH5L5C.mjs +11 -0
- package/dist/lib/browser/AutomationSettings-3LABN6ER.mjs +69 -0
- package/dist/lib/browser/AutomationSettings-3LABN6ER.mjs.map +7 -0
- package/dist/lib/browser/{FunctionsContainer-IOB333TX.mjs → FunctionsContainer-HHBMPUOD.mjs} +9 -12
- package/dist/lib/browser/FunctionsContainer-HHBMPUOD.mjs.map +7 -0
- package/dist/lib/browser/{FunctionsPanel-56ZKRVM5.mjs → FunctionsPanel-NRIKAPQV.mjs} +3 -3
- package/dist/lib/browser/{app-graph-builder-ZTAUTFI4.mjs → app-graph-builder-DV5HMFX4.mjs} +11 -10
- package/dist/lib/browser/app-graph-builder-DV5HMFX4.mjs.map +7 -0
- package/dist/lib/browser/chunk-5ARH77PV.mjs +15 -0
- package/dist/lib/browser/chunk-5ARH77PV.mjs.map +7 -0
- package/dist/lib/browser/chunk-AY67OUDA.mjs +14 -0
- package/dist/lib/browser/chunk-AY67OUDA.mjs.map +7 -0
- package/dist/lib/browser/{chunk-LYJVTIVD.mjs → chunk-DLLE4FKP.mjs} +6 -6
- package/dist/lib/browser/chunk-DLLE4FKP.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ERTIGJYE.mjs → chunk-LC3QQU47.mjs} +52 -28
- package/dist/lib/browser/chunk-LC3QQU47.mjs.map +7 -0
- package/dist/lib/browser/chunk-MVPRI3DB.mjs +53 -0
- package/dist/lib/browser/chunk-MVPRI3DB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FSJZXTS2.mjs → chunk-NIJWEQRD.mjs} +84 -31
- package/dist/lib/browser/chunk-NIJWEQRD.mjs.map +7 -0
- package/dist/lib/browser/chunk-QT3YWUOT.mjs +14 -0
- package/dist/lib/browser/chunk-QT3YWUOT.mjs.map +7 -0
- package/dist/lib/browser/{chunk-HN7OHFCB.mjs → chunk-VGBZKM3O.mjs} +3 -3
- package/dist/lib/browser/chunk-VGBZKM3O.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GW5U2DGT.mjs → chunk-WWURMV25.mjs} +2 -4
- package/dist/lib/browser/chunk-WWURMV25.mjs.map +7 -0
- package/dist/lib/browser/compute-runtime-YJREH6WP.mjs +160 -0
- package/dist/lib/browser/compute-runtime-YJREH6WP.mjs.map +7 -0
- package/dist/lib/browser/hooks/index.mjs +12 -0
- package/dist/lib/browser/index.mjs +36 -16
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/{intent-resolver-U3ZAQEFW.mjs → intent-resolver-D2OHKQRR.mjs} +11 -10
- package/dist/lib/browser/intent-resolver-D2OHKQRR.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-4DFSM7OX.mjs → react-surface-JXFO46V4.mjs} +18 -19
- package/dist/lib/browser/react-surface-JXFO46V4.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -2
- package/dist/lib/node-esm/{AutomationPanel-YYUMSK2W.mjs → AutomationPanel-GHK5UG4K.mjs} +4 -4
- package/dist/lib/node-esm/AutomationSettings-XENNIIZM.mjs +70 -0
- package/dist/lib/node-esm/AutomationSettings-XENNIIZM.mjs.map +7 -0
- package/dist/lib/node-esm/{FunctionsContainer-DJWB6WFH.mjs → FunctionsContainer-ZKVOBUHV.mjs} +9 -12
- package/dist/lib/node-esm/FunctionsContainer-ZKVOBUHV.mjs.map +7 -0
- package/dist/lib/node-esm/{FunctionsPanel-KGIOZSPZ.mjs → FunctionsPanel-SAMRTELO.mjs} +3 -3
- package/dist/lib/node-esm/FunctionsPanel-SAMRTELO.mjs.map +7 -0
- package/dist/lib/node-esm/{app-graph-builder-3FP63ZSG.mjs → app-graph-builder-TR2WXPX2.mjs} +11 -10
- package/dist/lib/node-esm/app-graph-builder-TR2WXPX2.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-HIMYPGHF.mjs → chunk-3EWMZAU6.mjs} +52 -28
- package/dist/lib/node-esm/chunk-3EWMZAU6.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-NK5N3QKD.mjs → chunk-5MQJPJR2.mjs} +2 -4
- package/dist/lib/node-esm/chunk-5MQJPJR2.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-OEZNHUL2.mjs → chunk-CJUI6AKX.mjs} +3 -3
- package/dist/lib/node-esm/chunk-CJUI6AKX.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-AZH66CED.mjs → chunk-EX74SIDO.mjs} +84 -31
- package/dist/lib/node-esm/chunk-EX74SIDO.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-LWASMQIF.mjs +16 -0
- package/dist/lib/node-esm/chunk-LWASMQIF.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-QCA543ZR.mjs +54 -0
- package/dist/lib/node-esm/chunk-QCA543ZR.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-U7LJXQS4.mjs +16 -0
- package/dist/lib/node-esm/chunk-U7LJXQS4.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-WHCSOUNN.mjs +16 -0
- package/dist/lib/node-esm/chunk-WHCSOUNN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ZGPUV5VS.mjs → chunk-YQXW3JXD.mjs} +6 -6
- package/dist/lib/node-esm/chunk-YQXW3JXD.mjs.map +7 -0
- package/dist/lib/node-esm/compute-runtime-CMEPAYND.mjs +161 -0
- package/dist/lib/node-esm/compute-runtime-CMEPAYND.mjs.map +7 -0
- package/dist/lib/node-esm/hooks/index.mjs +13 -0
- package/dist/lib/node-esm/hooks/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +36 -16
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/{intent-resolver-3QWXEBPX.mjs → intent-resolver-2LGBVXT5.mjs} +11 -10
- package/dist/lib/node-esm/intent-resolver-2LGBVXT5.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-3PNW7NDW.mjs → react-surface-YDJ43B3N.mjs} +18 -19
- package/dist/lib/node-esm/react-surface-YDJ43B3N.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -2
- package/dist/types/src/AutomationPlugin.d.ts +1 -1
- package/dist/types/src/AutomationPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +19 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/compute-runtime.d.ts +5 -0
- package/dist/types/src/capabilities/compute-runtime.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +5 -3
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +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/components/AutomationPanel/AutomationPanel.d.ts +6 -5
- package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts.map +1 -1
- package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts +45 -4
- package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts.map +1 -1
- package/dist/types/src/components/AutomationSettings.d.ts +5 -0
- package/dist/types/src/components/AutomationSettings.d.ts.map +1 -0
- package/dist/types/src/components/FunctionsContainer.d.ts.map +1 -1
- package/dist/types/src/components/FunctionsPanel/FunctionsPanel.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +4 -3
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +47 -4
- package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TriggerSettings.d.ts +6 -0
- package/dist/types/src/components/TriggerSettings.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +4 -0
- package/dist/types/src/events.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts +8 -0
- package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts.map +1 -0
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +11 -0
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +0 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +1 -1
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +59 -37
- package/src/AutomationPlugin.tsx +37 -31
- package/src/capabilities/app-graph-builder.ts +10 -9
- package/src/capabilities/capabilities.ts +48 -0
- package/src/capabilities/compute-runtime.ts +138 -0
- package/src/capabilities/index.ts +3 -0
- package/src/capabilities/intent-resolver.ts +7 -7
- package/src/capabilities/react-surface.tsx +13 -14
- package/src/components/AutomationPanel/AutomationPanel.stories.tsx +13 -13
- package/src/components/AutomationPanel/AutomationPanel.tsx +84 -38
- package/src/components/AutomationSettings.tsx +30 -0
- package/src/components/FunctionsContainer.tsx +11 -13
- package/src/components/FunctionsPanel/FunctionsPanel.tsx +5 -5
- package/src/components/TriggerEditor/FunctionInputEditor.tsx +8 -2
- package/src/components/TriggerEditor/SpecSelector.tsx +23 -16
- package/src/components/TriggerEditor/TriggerEditor.stories.tsx +41 -19
- package/src/components/TriggerEditor/TriggerEditor.tsx +68 -18
- package/src/components/TriggerSettings.tsx +25 -0
- package/src/components/index.ts +1 -1
- package/src/events.ts +11 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useComputeRuntimeCallback.ts +30 -0
- package/src/hooks/useTriggerRuntimeControls.ts +52 -0
- package/src/index.ts +2 -0
- package/src/meta.ts +1 -3
- package/src/testing/test-functions.ts +1 -1
- package/src/translations.ts +4 -0
- package/src/types/schema.ts +1 -1
- package/dist/lib/browser/AutomationContainer-VZNV2ZQF.mjs +0 -38
- package/dist/lib/browser/AutomationContainer-VZNV2ZQF.mjs.map +0 -7
- package/dist/lib/browser/AutomationPanel-ZWA6GOFY.mjs +0 -11
- package/dist/lib/browser/FunctionsContainer-IOB333TX.mjs.map +0 -7
- package/dist/lib/browser/app-graph-builder-ZTAUTFI4.mjs.map +0 -7
- package/dist/lib/browser/chunk-ECSTS2UI.mjs +0 -14
- package/dist/lib/browser/chunk-ECSTS2UI.mjs.map +0 -7
- package/dist/lib/browser/chunk-ERTIGJYE.mjs.map +0 -7
- package/dist/lib/browser/chunk-FSJZXTS2.mjs.map +0 -7
- package/dist/lib/browser/chunk-GW5U2DGT.mjs.map +0 -7
- package/dist/lib/browser/chunk-HN7OHFCB.mjs.map +0 -7
- package/dist/lib/browser/chunk-LYJVTIVD.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-U3ZAQEFW.mjs.map +0 -7
- package/dist/lib/browser/react-surface-4DFSM7OX.mjs.map +0 -7
- package/dist/lib/node-esm/AutomationContainer-WMIH3F4V.mjs +0 -39
- package/dist/lib/node-esm/AutomationContainer-WMIH3F4V.mjs.map +0 -7
- package/dist/lib/node-esm/FunctionsContainer-DJWB6WFH.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-3FP63ZSG.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AZH66CED.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HIMYPGHF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NK5N3QKD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OEZNHUL2.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SGZPTJ47.mjs +0 -16
- package/dist/lib/node-esm/chunk-SGZPTJ47.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZGPUV5VS.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-3QWXEBPX.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-3PNW7NDW.mjs.map +0 -7
- package/dist/types/src/components/AutomationContainer.d.ts +0 -5
- package/dist/types/src/components/AutomationContainer.d.ts.map +0 -1
- package/src/components/AutomationContainer.tsx +0 -30
- /package/dist/lib/browser/{AutomationPanel-ZWA6GOFY.mjs.map → AutomationPanel-PNBH5L5C.mjs.map} +0 -0
- /package/dist/lib/browser/{FunctionsPanel-56ZKRVM5.mjs.map → FunctionsPanel-NRIKAPQV.mjs.map} +0 -0
- /package/dist/lib/{node-esm/AutomationPanel-YYUMSK2W.mjs.map → browser/hooks/index.mjs.map} +0 -0
- /package/dist/lib/node-esm/{FunctionsPanel-KGIOZSPZ.mjs.map → AutomationPanel-GHK5UG4K.mjs.map} +0 -0
|
@@ -2,56 +2,54 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import * as Array from 'effect/Array';
|
|
6
|
+
import * as Function from 'effect/Function';
|
|
7
|
+
import * as Match from 'effect/Match';
|
|
8
|
+
import * as Schema from 'effect/Schema';
|
|
9
|
+
import React, { useMemo, useState } from 'react';
|
|
7
10
|
|
|
8
11
|
import { Filter, Obj } from '@dxos/echo';
|
|
9
|
-
import {
|
|
10
|
-
FunctionType,
|
|
11
|
-
FunctionTrigger,
|
|
12
|
-
FunctionTriggerSchema,
|
|
13
|
-
type FunctionTriggerType,
|
|
14
|
-
ScriptType,
|
|
15
|
-
TriggerKind,
|
|
16
|
-
} from '@dxos/functions';
|
|
12
|
+
import { FunctionTrigger, FunctionType, ScriptType } from '@dxos/functions';
|
|
17
13
|
import { type Client, useClient } from '@dxos/react-client';
|
|
18
|
-
import {
|
|
19
|
-
import { Clipboard, IconButton, Input, Separator, useTranslation } from '@dxos/react-ui';
|
|
14
|
+
import { type Space, getSpace, useQuery } from '@dxos/react-client/echo';
|
|
15
|
+
import { Clipboard, IconButton, Input, Separator, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
20
16
|
import { ControlItem, controlItemClasses } from '@dxos/react-ui-form';
|
|
21
17
|
import { List } from '@dxos/react-ui-list';
|
|
22
18
|
import { ghostHover, mx } from '@dxos/react-ui-theme';
|
|
19
|
+
import { DataType } from '@dxos/schema';
|
|
23
20
|
|
|
24
|
-
import {
|
|
21
|
+
import { meta } from '../../meta';
|
|
25
22
|
import { TriggerEditor, type TriggerEditorProps } from '../TriggerEditor';
|
|
26
23
|
|
|
27
24
|
const grid = 'grid grid-cols-[40px_1fr_32px] min-bs-[2.5rem]';
|
|
28
25
|
|
|
29
|
-
export type AutomationPanelProps = {
|
|
26
|
+
export type AutomationPanelProps = ThemedClassName<{
|
|
30
27
|
space: Space;
|
|
31
28
|
object?: Obj.Any;
|
|
32
|
-
initialTrigger?:
|
|
29
|
+
initialTrigger?: FunctionTrigger;
|
|
33
30
|
onDone?: () => void;
|
|
34
|
-
}
|
|
31
|
+
}>;
|
|
35
32
|
|
|
36
33
|
// TODO(burdon): Factor out common layout with ViewEditor.
|
|
37
|
-
export const AutomationPanel = ({ space, object, initialTrigger, onDone }: AutomationPanelProps) => {
|
|
38
|
-
const { t } = useTranslation(
|
|
34
|
+
export const AutomationPanel = ({ classNames, space, object, initialTrigger, onDone }: AutomationPanelProps) => {
|
|
35
|
+
const { t } = useTranslation(meta.id);
|
|
39
36
|
const client = useClient();
|
|
40
|
-
const triggers = useQuery(space, Filter.type(FunctionTrigger));
|
|
41
37
|
const functions = useQuery(space, Filter.type(FunctionType));
|
|
42
|
-
const
|
|
38
|
+
const triggers = useQuery(space, Filter.type(FunctionTrigger));
|
|
39
|
+
const filteredTriggers = useMemo(() => {
|
|
40
|
+
return object ? triggers.filter(triggerMatch(object)) : triggers;
|
|
41
|
+
}, [object, triggers]);
|
|
43
42
|
|
|
44
|
-
const [trigger, setTrigger] = useState<
|
|
43
|
+
const [trigger, setTrigger] = useState<FunctionTrigger | undefined>(initialTrigger);
|
|
45
44
|
const [selected, setSelected] = useState<FunctionTrigger>();
|
|
46
45
|
|
|
47
46
|
const handleSelect = (trigger: FunctionTrigger) => {
|
|
48
|
-
|
|
49
|
-
setTrigger(values);
|
|
47
|
+
setTrigger(trigger);
|
|
50
48
|
setSelected(trigger);
|
|
51
49
|
};
|
|
52
50
|
|
|
53
51
|
const handleAdd = () => {
|
|
54
|
-
setTrigger(Obj.make(
|
|
52
|
+
setTrigger(Obj.make(FunctionTrigger, {}));
|
|
55
53
|
setSelected(undefined);
|
|
56
54
|
};
|
|
57
55
|
|
|
@@ -81,18 +79,28 @@ export const AutomationPanel = ({ space, object, initialTrigger, onDone }: Autom
|
|
|
81
79
|
if (trigger) {
|
|
82
80
|
return (
|
|
83
81
|
<ControlItem title={t('trigger editor title')}>
|
|
84
|
-
<TriggerEditor
|
|
82
|
+
<TriggerEditor
|
|
83
|
+
space={space}
|
|
84
|
+
trigger={trigger}
|
|
85
|
+
readonlySpec={Boolean(object)}
|
|
86
|
+
onSave={handleSave}
|
|
87
|
+
onCancel={handleCancel}
|
|
88
|
+
/>
|
|
85
89
|
</ControlItem>
|
|
86
90
|
);
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
return (
|
|
90
|
-
<div className={controlItemClasses}>
|
|
91
|
-
{
|
|
92
|
-
<List.Root<FunctionTrigger>
|
|
93
|
-
{
|
|
94
|
+
<div className={mx(controlItemClasses, classNames)}>
|
|
95
|
+
{filteredTriggers.length > 0 && (
|
|
96
|
+
<List.Root<FunctionTrigger>
|
|
97
|
+
items={filteredTriggers}
|
|
98
|
+
isItem={Schema.is(FunctionTrigger)}
|
|
99
|
+
getId={(field) => field.id}
|
|
100
|
+
>
|
|
101
|
+
{({ items: filteredTriggers }) => (
|
|
94
102
|
<div role='list' className='flex flex-col w-full'>
|
|
95
|
-
{
|
|
103
|
+
{filteredTriggers?.map((trigger) => {
|
|
96
104
|
const copyAction = getCopyAction(client, trigger);
|
|
97
105
|
return (
|
|
98
106
|
<List.Item<FunctionTrigger>
|
|
@@ -112,7 +120,7 @@ export const AutomationPanel = ({ space, object, initialTrigger, onDone }: Autom
|
|
|
112
120
|
classNames='px-1 cursor-pointer w-0 shrink truncate'
|
|
113
121
|
onClick={() => handleSelect(trigger)}
|
|
114
122
|
>
|
|
115
|
-
{getFunctionName(
|
|
123
|
+
{getFunctionName(functions, trigger) ?? '∅'}
|
|
116
124
|
</List.ItemTitle>
|
|
117
125
|
|
|
118
126
|
{/* TODO: a better way to expose copy action */}
|
|
@@ -132,18 +140,18 @@ export const AutomationPanel = ({ space, object, initialTrigger, onDone }: Autom
|
|
|
132
140
|
)}
|
|
133
141
|
</List.Root>
|
|
134
142
|
)}
|
|
135
|
-
{
|
|
143
|
+
{filteredTriggers.length > 0 && <Separator classNames='mlb-4' />}
|
|
136
144
|
<IconButton icon='ph--plus--regular' label={t('new trigger label')} onClick={handleAdd} />
|
|
137
145
|
</div>
|
|
138
146
|
);
|
|
139
147
|
};
|
|
140
148
|
|
|
141
149
|
const getCopyAction = (client: Client, trigger: FunctionTrigger | undefined) => {
|
|
142
|
-
if (trigger?.spec?.kind ===
|
|
150
|
+
if (trigger?.spec?.kind === 'email') {
|
|
143
151
|
return { translationKey: 'trigger copy email', contentProvider: () => `${getSpace(trigger)!.id}@dxos.network` };
|
|
144
152
|
}
|
|
145
153
|
|
|
146
|
-
if (trigger?.spec?.kind ===
|
|
154
|
+
if (trigger?.spec?.kind === 'webhook') {
|
|
147
155
|
return { translationKey: 'trigger copy url', contentProvider: () => getWebhookUrl(client, trigger) };
|
|
148
156
|
}
|
|
149
157
|
|
|
@@ -158,14 +166,52 @@ const getWebhookUrl = (client: Client, trigger: FunctionTrigger) => {
|
|
|
158
166
|
return new URL(`/webhook/${spaceId}:${trigger.id}`, edgeUrl).toString();
|
|
159
167
|
};
|
|
160
168
|
|
|
161
|
-
const getFunctionName = (
|
|
169
|
+
const getFunctionName = (functions: FunctionType[], trigger: FunctionTrigger) => {
|
|
162
170
|
// TODO(wittjosiah): Truncation should be done in the UI.
|
|
163
171
|
// Warning that the List component is currently a can of worms.
|
|
164
172
|
const shortId = trigger.function && `${trigger.function.dxn.toString().slice(0, 16)}…`;
|
|
165
173
|
const functionObject = functions.find((fn) => fn === trigger.function?.target);
|
|
166
|
-
|
|
167
|
-
|
|
174
|
+
return functionObject?.name ?? shortId;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const scriptMatch = (script: ScriptType) => (trigger: FunctionTrigger) => {
|
|
178
|
+
const fn = trigger.function?.target;
|
|
179
|
+
if (!Obj.instanceOf(FunctionType, fn)) {
|
|
180
|
+
return false;
|
|
168
181
|
}
|
|
169
182
|
|
|
170
|
-
return
|
|
183
|
+
return fn.source?.target === script;
|
|
171
184
|
};
|
|
185
|
+
|
|
186
|
+
const projectMatch = (project: DataType.Project) => {
|
|
187
|
+
const viewQueries = Function.pipe(
|
|
188
|
+
project.collections,
|
|
189
|
+
Array.map((collection) => collection.target),
|
|
190
|
+
Array.filter(Schema.is(DataType.View)),
|
|
191
|
+
Array.map((view) => Obj.getSnapshot(view).query.ast),
|
|
192
|
+
Array.map((ast) => JSON.stringify(ast)),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
return (trigger: FunctionTrigger) => {
|
|
196
|
+
const spec = Obj.getSnapshot(trigger).spec;
|
|
197
|
+
if (spec?.kind !== 'subscription') {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// TODO(wittjosiah): Implement better way of comparing query ASTs.
|
|
202
|
+
return viewQueries.some((query) => JSON.stringify(spec.query) === query);
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const triggerMatch = Match.type<Obj.Any>().pipe(
|
|
207
|
+
Match.withReturnType<(trigger: FunctionTrigger) => boolean>(),
|
|
208
|
+
Match.when(
|
|
209
|
+
(obj) => Obj.instanceOf(ScriptType, obj),
|
|
210
|
+
(obj) => scriptMatch(obj),
|
|
211
|
+
),
|
|
212
|
+
Match.when(
|
|
213
|
+
(obj) => Obj.instanceOf(DataType.Project, obj),
|
|
214
|
+
(obj) => projectMatch(obj),
|
|
215
|
+
),
|
|
216
|
+
Match.orElse((_obj) => () => true),
|
|
217
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { ControlPage, ControlSection } from '@dxos/react-ui-form';
|
|
9
|
+
|
|
10
|
+
import { meta } from '../meta';
|
|
11
|
+
|
|
12
|
+
import { AutomationPanel, type AutomationPanelProps } from './AutomationPanel';
|
|
13
|
+
import { TriggersSettings } from './TriggerSettings';
|
|
14
|
+
|
|
15
|
+
export const AutomationSettings = (props: AutomationPanelProps) => {
|
|
16
|
+
const { t } = useTranslation(meta.id);
|
|
17
|
+
return (
|
|
18
|
+
<ControlPage>
|
|
19
|
+
<ControlSection
|
|
20
|
+
title={t('automation verbose label', { ns: meta.id })}
|
|
21
|
+
description={t('automation description', { ns: meta.id })}
|
|
22
|
+
>
|
|
23
|
+
<AutomationPanel {...props} />
|
|
24
|
+
<TriggersSettings space={props.space} />
|
|
25
|
+
</ControlSection>
|
|
26
|
+
</ControlPage>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default AutomationSettings;
|
|
@@ -7,24 +7,22 @@ import React from 'react';
|
|
|
7
7
|
import { type Space } from '@dxos/react-client/echo';
|
|
8
8
|
import { useTranslation } from '@dxos/react-ui';
|
|
9
9
|
import { ControlPage, ControlSection } from '@dxos/react-ui-form';
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
import { meta } from '../meta';
|
|
11
12
|
|
|
12
13
|
import { FunctionsPanel } from './FunctionsPanel';
|
|
13
|
-
import { AUTOMATION_PLUGIN } from '../meta';
|
|
14
14
|
|
|
15
15
|
export const FunctionsContainer = ({ space }: { space: Space }) => {
|
|
16
|
-
const { t } = useTranslation(
|
|
16
|
+
const { t } = useTranslation(meta.id);
|
|
17
17
|
return (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</ControlPage>
|
|
27
|
-
</StackItem.Content>
|
|
18
|
+
<ControlPage>
|
|
19
|
+
<ControlSection
|
|
20
|
+
title={t('functions verbose label', { ns: meta.id })}
|
|
21
|
+
description={t('functions description', { ns: meta.id })}
|
|
22
|
+
>
|
|
23
|
+
<FunctionsPanel space={space} />
|
|
24
|
+
</ControlSection>
|
|
25
|
+
</ControlPage>
|
|
28
26
|
);
|
|
29
27
|
};
|
|
30
28
|
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
6
|
import React, { useCallback, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { LayoutAction, createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
9
9
|
import { FunctionType, ScriptType } from '@dxos/functions';
|
|
10
|
-
import { Filter, fullyQualifiedId, useQuery
|
|
10
|
+
import { Filter, type Space, fullyQualifiedId, useQuery } from '@dxos/react-client/echo';
|
|
11
11
|
import { Button, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import { controlItemClasses } from '@dxos/react-ui-form';
|
|
13
13
|
import { List } from '@dxos/react-ui-list';
|
|
14
14
|
import { ghostHover, mx } from '@dxos/react-ui-theme';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import { meta } from '../../meta';
|
|
17
17
|
|
|
18
18
|
const grid = 'grid grid-cols-[1fr_auto] min-bs-[2.5rem]';
|
|
19
19
|
|
|
@@ -22,7 +22,7 @@ export type FunctionsPanelProps = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
|
|
25
|
-
const { t } = useTranslation(
|
|
25
|
+
const { t } = useTranslation(meta.id);
|
|
26
26
|
const functions = useQuery(space, Filter.type(FunctionType));
|
|
27
27
|
const scripts = useQuery(space, Filter.type(ScriptType));
|
|
28
28
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { Ref, Type } from '@dxos/echo';
|
|
8
|
-
import { type JsonPath } from '@dxos/echo
|
|
8
|
+
import { type JsonPath } from '@dxos/echo/internal';
|
|
9
9
|
import { type FunctionType } from '@dxos/functions';
|
|
10
10
|
import { useOnTransition } from '@dxos/react-ui';
|
|
11
11
|
import { Form, type FormInputStateProps, type QueryRefOptions, useFormValues } from '@dxos/react-ui-form';
|
|
@@ -39,7 +39,13 @@ export const FunctionInputEditor = ({
|
|
|
39
39
|
useOnTransition(
|
|
40
40
|
// Clear function parameter input when the function changes.
|
|
41
41
|
selectedFunctionValue,
|
|
42
|
-
(prevValue) =>
|
|
42
|
+
(prevValue) => {
|
|
43
|
+
if (!Ref.isRef(prevValue) || !Ref.isRef(selectedFunctionValue)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return prevValue.dxn.toString() !== selectedFunctionValue.dxn.toString();
|
|
48
|
+
},
|
|
43
49
|
(currValue) => currValue !== undefined,
|
|
44
50
|
() => onValueChange('object', {}),
|
|
45
51
|
);
|
|
@@ -4,32 +4,39 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Filter, Query } from '@dxos/echo';
|
|
8
|
+
import { type FunctionTrigger, TriggerKinds, type TriggerType } from '@dxos/functions';
|
|
8
9
|
import { useTranslation } from '@dxos/react-ui';
|
|
9
|
-
import {
|
|
10
|
+
import { type InputProps, SelectInput, useInputProps } from '@dxos/react-ui-form';
|
|
10
11
|
|
|
11
|
-
import {
|
|
12
|
+
import { meta } from '../../meta';
|
|
12
13
|
|
|
13
14
|
export type SpecSelectorProps = InputProps;
|
|
14
15
|
|
|
15
16
|
export const SpecSelector = (props: SpecSelectorProps) => {
|
|
16
|
-
const { t } = useTranslation(
|
|
17
|
-
const specProps = useInputProps(['spec' satisfies keyof
|
|
17
|
+
const { t } = useTranslation(meta.id);
|
|
18
|
+
const specProps = useInputProps(['spec' satisfies keyof FunctionTrigger]);
|
|
18
19
|
|
|
19
20
|
const handleTypeChange = useCallback(
|
|
20
21
|
(_type: any, value: string): TriggerType | undefined => {
|
|
21
22
|
const getDefaultTriggerSpec = (kind: string) => {
|
|
22
23
|
switch (kind) {
|
|
23
|
-
case
|
|
24
|
-
return { kind:
|
|
25
|
-
case
|
|
26
|
-
return {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
case 'timer':
|
|
25
|
+
return { kind: 'timer', cron: '' };
|
|
26
|
+
case 'subscription':
|
|
27
|
+
return {
|
|
28
|
+
kind: 'subscription',
|
|
29
|
+
query: {
|
|
30
|
+
string: 'Query.select(Filter.nothing())',
|
|
31
|
+
ast: Query.select(Filter.nothing()).ast,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
case 'queue':
|
|
35
|
+
return { kind: 'queue', queue: 'dxn:' };
|
|
36
|
+
case 'email':
|
|
37
|
+
return { kind: 'email' };
|
|
38
|
+
case 'webhook':
|
|
39
|
+
return { kind: 'webhook' };
|
|
33
40
|
default:
|
|
34
41
|
return undefined;
|
|
35
42
|
}
|
|
@@ -48,7 +55,7 @@ export const SpecSelector = (props: SpecSelectorProps) => {
|
|
|
48
55
|
|
|
49
56
|
const options = useMemo(
|
|
50
57
|
() =>
|
|
51
|
-
|
|
58
|
+
TriggerKinds.map((kind) => ({
|
|
52
59
|
value: kind,
|
|
53
60
|
label: t(`trigger type ${kind}`),
|
|
54
61
|
})),
|
|
@@ -2,32 +2,46 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useState } from 'react';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
import { Obj } from '@dxos/echo';
|
|
11
|
-
import { FunctionType, FunctionTrigger, TriggerKind } from '@dxos/functions';
|
|
8
|
+
import { Filter, Obj, Ref } from '@dxos/echo';
|
|
9
|
+
import { FunctionTrigger, FunctionType } from '@dxos/functions';
|
|
10
|
+
import { invariant } from '@dxos/invariant';
|
|
12
11
|
import { faker } from '@dxos/random';
|
|
13
12
|
import { useSpaces } from '@dxos/react-client/echo';
|
|
14
13
|
import { ContactType, withClientProvider } from '@dxos/react-client/testing';
|
|
15
|
-
import {
|
|
14
|
+
import { useAsyncEffect } from '@dxos/react-ui';
|
|
15
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
16
16
|
|
|
17
|
-
import { TriggerEditor } from './TriggerEditor';
|
|
18
17
|
import { functions } from '../../testing';
|
|
19
18
|
import { translations } from '../../translations';
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
import { TriggerEditor, type TriggerEditorProps } from './TriggerEditor';
|
|
21
|
+
|
|
22
|
+
const DefaultStory = (props: Partial<TriggerEditorProps>) => {
|
|
22
23
|
const spaces = useSpaces();
|
|
23
24
|
const space = spaces[1];
|
|
24
25
|
const [trigger, setTrigger] = useState<FunctionTrigger>();
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
useAsyncEffect(async () => {
|
|
26
28
|
if (!space) {
|
|
27
29
|
return;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
const
|
|
32
|
+
const result = await space.db.query(Filter.type(FunctionType)).run();
|
|
33
|
+
const fn = result.objects.find((fn) => fn.name === 'example.com/function/forex');
|
|
34
|
+
invariant(fn);
|
|
35
|
+
const trigger = space.db.add(
|
|
36
|
+
Obj.make(FunctionTrigger, {
|
|
37
|
+
function: Ref.make(fn),
|
|
38
|
+
spec: { kind: 'webhook' },
|
|
39
|
+
input: {
|
|
40
|
+
from: 'USD',
|
|
41
|
+
to: 'JPY',
|
|
42
|
+
},
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
31
45
|
setTrigger(trigger);
|
|
32
46
|
}, [space]);
|
|
33
47
|
|
|
@@ -37,21 +51,22 @@ const DefaultStory = () => {
|
|
|
37
51
|
|
|
38
52
|
return (
|
|
39
53
|
<div role='none' className='w-[32rem] bs-fit border border-separator rounded-sm'>
|
|
40
|
-
<TriggerEditor space={space} trigger={trigger} onSave={(values) => console.log('on save', values)} />
|
|
54
|
+
<TriggerEditor space={space} trigger={trigger} onSave={(values) => console.log('on save', values)} {...props} />
|
|
41
55
|
</div>
|
|
42
56
|
);
|
|
43
57
|
};
|
|
44
58
|
|
|
45
|
-
const meta
|
|
59
|
+
const meta = {
|
|
46
60
|
title: 'plugins/plugin-automation/TriggerEditor',
|
|
47
|
-
component: TriggerEditor,
|
|
61
|
+
component: TriggerEditor as any,
|
|
48
62
|
render: DefaultStory,
|
|
49
63
|
decorators: [
|
|
64
|
+
withTheme,
|
|
50
65
|
withClientProvider({
|
|
51
66
|
createIdentity: true,
|
|
52
67
|
createSpace: true,
|
|
53
68
|
types: [FunctionType, FunctionTrigger, ContactType],
|
|
54
|
-
|
|
69
|
+
onCreateSpace: ({ space }) => {
|
|
55
70
|
for (const fn of functions) {
|
|
56
71
|
space.db.add(Obj.make(FunctionType, fn));
|
|
57
72
|
}
|
|
@@ -65,14 +80,21 @@ const meta: Meta = {
|
|
|
65
80
|
});
|
|
66
81
|
},
|
|
67
82
|
}),
|
|
68
|
-
withLayout({ fullscreen: true, classNames: 'flex justify-center m-2' }),
|
|
69
|
-
withTheme,
|
|
70
83
|
],
|
|
71
84
|
parameters: {
|
|
85
|
+
layout: 'column',
|
|
72
86
|
translations,
|
|
73
87
|
},
|
|
74
|
-
}
|
|
88
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
75
89
|
|
|
76
90
|
export default meta;
|
|
77
91
|
|
|
78
|
-
|
|
92
|
+
type Story = StoryObj<typeof meta>;
|
|
93
|
+
|
|
94
|
+
export const Default: Story = {};
|
|
95
|
+
|
|
96
|
+
export const ReadonlySpec: Story = {
|
|
97
|
+
args: {
|
|
98
|
+
readonlySpec: true,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
@@ -6,39 +6,40 @@ import React, { useCallback, useMemo } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { ComputeGraph } from '@dxos/conductor';
|
|
8
8
|
import { Type } from '@dxos/echo';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
import { type CustomInputMap, Form, SelectInput, useRefQueryLookupHandler } from '@dxos/react-ui-form';
|
|
9
|
+
import { FunctionTrigger, FunctionType, ScriptType } from '@dxos/functions';
|
|
10
|
+
import { Filter, Ref, type Space, useQuery } from '@dxos/react-client/echo';
|
|
11
|
+
import { Input, useDensityContext, useElevationContext, useThemeContext, useTranslation } from '@dxos/react-ui';
|
|
12
|
+
import { Editor, createBasicExtensions, createThemeExtensions } from '@dxos/react-ui-editor';
|
|
13
|
+
import { type CustomInputMap, Form, InputHeader, SelectInput, useRefQueryLookupHandler } from '@dxos/react-ui-form';
|
|
14
|
+
import { inputTheme, mx } from '@dxos/react-ui-theme';
|
|
15
|
+
|
|
16
|
+
import { meta } from '../../meta';
|
|
18
17
|
|
|
19
18
|
import { FunctionInputEditor, type FunctionInputEditorProps } from './FunctionInputEditor';
|
|
20
19
|
import { SpecSelector } from './SpecSelector';
|
|
21
20
|
|
|
22
21
|
export type TriggerEditorProps = {
|
|
23
22
|
space: Space;
|
|
24
|
-
trigger:
|
|
23
|
+
trigger: FunctionTrigger;
|
|
24
|
+
// TODO(wittjosiah): This needs to apply to whole spec but currently only applies to spec.kind & spec.query.
|
|
25
|
+
readonlySpec?: boolean;
|
|
25
26
|
onSave?: (trigger: Omit<FunctionTrigger, 'id'>) => void;
|
|
26
27
|
onCancel?: () => void;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
export const TriggerEditor = ({ space, trigger, onSave, onCancel }: TriggerEditorProps) => {
|
|
30
|
-
const handleSave = (values:
|
|
30
|
+
export const TriggerEditor = ({ space, trigger, readonlySpec, onSave, onCancel }: TriggerEditorProps) => {
|
|
31
|
+
const handleSave = (values: FunctionTrigger) => {
|
|
31
32
|
onSave?.(values);
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const handleRefQueryLookup = useRefQueryLookupHandler({ space });
|
|
35
|
-
const Custom = useCustomInputs(space, handleRefQueryLookup);
|
|
36
|
+
const Custom = useCustomInputs({ space, readonlySpec, onQueryRefOptions: handleRefQueryLookup });
|
|
36
37
|
|
|
37
38
|
return (
|
|
38
39
|
<Form
|
|
39
40
|
outerSpacing={false}
|
|
40
41
|
Custom={Custom}
|
|
41
|
-
schema={
|
|
42
|
+
schema={FunctionTrigger}
|
|
42
43
|
values={trigger}
|
|
43
44
|
onSave={handleSave}
|
|
44
45
|
onCancel={onCancel}
|
|
@@ -47,7 +48,16 @@ export const TriggerEditor = ({ space, trigger, onSave, onCancel }: TriggerEdito
|
|
|
47
48
|
);
|
|
48
49
|
};
|
|
49
50
|
|
|
50
|
-
const useCustomInputs = (
|
|
51
|
+
const useCustomInputs = ({
|
|
52
|
+
space,
|
|
53
|
+
readonlySpec,
|
|
54
|
+
onQueryRefOptions,
|
|
55
|
+
}: {
|
|
56
|
+
space: Space;
|
|
57
|
+
readonlySpec?: boolean;
|
|
58
|
+
onQueryRefOptions: FunctionInputEditorProps['onQueryRefOptions'];
|
|
59
|
+
}) => {
|
|
60
|
+
const { t } = useTranslation(meta.id);
|
|
51
61
|
const functions = useQuery(space, Filter.type(FunctionType));
|
|
52
62
|
const workflows = useQuery(space, Filter.type(ComputeGraph));
|
|
53
63
|
const scripts = useQuery(space, Filter.type(ScriptType));
|
|
@@ -55,7 +65,7 @@ const useCustomInputs = (space: Space, onQueryRefOptions: FunctionInputEditorPro
|
|
|
55
65
|
return useMemo(
|
|
56
66
|
(): CustomInputMap => ({
|
|
57
67
|
// Function selector.
|
|
58
|
-
['function' satisfies keyof
|
|
68
|
+
['function' satisfies keyof FunctionTrigger]: (props) => {
|
|
59
69
|
const getValue = useCallback(() => {
|
|
60
70
|
const formValue = props.getValue();
|
|
61
71
|
if (Ref.isRef(formValue)) {
|
|
@@ -86,14 +96,54 @@ const useCustomInputs = (space: Space, onQueryRefOptions: FunctionInputEditorPro
|
|
|
86
96
|
},
|
|
87
97
|
|
|
88
98
|
// Spec selector.
|
|
89
|
-
['spec.kind' as const]: SpecSelector
|
|
99
|
+
['spec.kind' as const]: (props) => <SpecSelector {...props} readonly={readonlySpec ? 'disabled-input' : false} />,
|
|
100
|
+
|
|
101
|
+
// TODO(wittjosiah): Copied from ViewEditor.
|
|
102
|
+
// Query input editor.
|
|
103
|
+
['spec.query' as const]: (props) => {
|
|
104
|
+
const { themeMode } = useThemeContext();
|
|
105
|
+
const density = useDensityContext();
|
|
106
|
+
const elevation = useElevationContext();
|
|
107
|
+
const value = props.getValue() as any;
|
|
108
|
+
|
|
109
|
+
// TODO(wittjosiah): Including props.onValueChange in deps causes infinite loop.
|
|
110
|
+
const handleChange = useCallback(
|
|
111
|
+
(text: string) => props.onValueChange('object', { ...value, string: text }),
|
|
112
|
+
[],
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const extensions = useMemo(
|
|
116
|
+
() => [
|
|
117
|
+
createBasicExtensions({ readOnly: readonlySpec, placeholder: t('query placeholder') }),
|
|
118
|
+
createThemeExtensions({ themeMode }),
|
|
119
|
+
],
|
|
120
|
+
[],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// TODO(wittjosiah): This is probably not the right way to do these styles.
|
|
124
|
+
return (
|
|
125
|
+
<Input.Root>
|
|
126
|
+
<InputHeader label={props.label} />
|
|
127
|
+
<Editor
|
|
128
|
+
classNames={mx(
|
|
129
|
+
inputTheme.input({ density, elevation }),
|
|
130
|
+
'flex items-center',
|
|
131
|
+
'focus-within:bg-focusSurface focus-within:border-separator focus-within:hover:bg-focusSurface',
|
|
132
|
+
)}
|
|
133
|
+
extensions={extensions}
|
|
134
|
+
value={value.string}
|
|
135
|
+
onChange={handleChange}
|
|
136
|
+
/>
|
|
137
|
+
</Input.Root>
|
|
138
|
+
);
|
|
139
|
+
},
|
|
90
140
|
|
|
91
141
|
// Function input editor.
|
|
92
142
|
['input' as const]: (props) => (
|
|
93
143
|
<FunctionInputEditor {...props} functions={functions} onQueryRefOptions={onQueryRefOptions} />
|
|
94
144
|
),
|
|
95
145
|
}),
|
|
96
|
-
[workflows, scripts, functions],
|
|
146
|
+
[workflows, scripts, functions, readonlySpec],
|
|
97
147
|
);
|
|
98
148
|
};
|
|
99
149
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
8
|
+
import { Input, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
import { ControlItemInput } from '@dxos/react-ui-form';
|
|
10
|
+
|
|
11
|
+
import { useTriggerRuntimeControls } from '../hooks';
|
|
12
|
+
import { meta } from '../meta';
|
|
13
|
+
|
|
14
|
+
export const TriggersSettings = ({ space }: { space: Space }) => {
|
|
15
|
+
const { triggers, isRunning, start, stop } = useTriggerRuntimeControls(space);
|
|
16
|
+
const { t } = useTranslation(meta.id);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className='container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content]'>
|
|
20
|
+
<ControlItemInput title={t('runtime label')} description={t('runtime description')}>
|
|
21
|
+
<Input.Switch classNames='justify-self-end' checked={isRunning} onCheckedChange={isRunning ? stop : start} />
|
|
22
|
+
</ControlItemInput>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
};
|