@burdenoff/fluidgrids-fe-sdk 2026.1027.3 → 2026.1027.4
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/{ExecutionDetailPage-HCCSFEVV.js → ExecutionDetailPage-3CSVGEQS.js} +7 -7
- package/dist/{ExecutionsListPage-XGYAHD6Q.js → ExecutionsListPage-M67JKEW4.js} +7 -7
- package/dist/{WorkflowBuilder-KZMGKXS5.js → WorkflowBuilder-IFRXDZUI.js} +9 -9
- package/dist/{WorkflowsList-Z275RPOC.js → WorkflowsList-53WA4UXO.js} +7 -7
- package/dist/{chunk-QRJ7SYR2.js → chunk-2NUE2X74.js} +1 -1
- package/dist/{chunk-HUOYVYXB.js → chunk-3MLOFJW3.js} +5 -5
- package/dist/{chunk-KEURSYHK.js → chunk-4E66IUF6.js} +1 -1
- package/dist/{chunk-IAPF6NJG.js → chunk-4JPNZ3M6.js} +3 -3
- package/dist/{chunk-HPRB4IIQ.js → chunk-5RZAO2ZF.js} +4 -4
- package/dist/{chunk-AQWX7PG2.js → chunk-5TRLB2QS.js} +2 -2
- package/dist/{chunk-PW7JSGQ2.js → chunk-72LNGKWQ.js} +29 -5
- package/dist/{chunk-53HVTSVI.js → chunk-B2FNI7YZ.js} +5 -5
- package/dist/{chunk-ABZDOQHY.js → chunk-BAPA4FLZ.js} +1 -1
- package/dist/{chunk-NBSNQ6I2.js → chunk-E5OMG6SN.js} +2 -2
- package/dist/{chunk-2FMJYM76.js → chunk-HDQZGCUY.js} +501 -50
- package/dist/{chunk-LMDB57LK.js → chunk-IONVLVGN.js} +3 -3
- package/dist/{chunk-CSJ47PYB.js → chunk-JF3VJKHF.js} +4 -4
- package/dist/{chunk-3UA5H5CT.js → chunk-LON27G5P.js} +1 -1
- package/dist/{chunk-MRL6QLBD.js → chunk-MFCT3PVR.js} +1 -1
- package/dist/{chunk-GI7OMVXM.js → chunk-ROG5NACW.js} +1 -1
- package/dist/{chunk-WXYF5RS5.js → chunk-SCPH5T5I.js} +1 -1
- package/dist/{chunk-SJL25YTY.js → chunk-SPJ4WF7V.js} +1 -1
- package/dist/{chunk-TXHY6QE4.js → chunk-SRIK33ZQ.js} +2 -2
- package/dist/{chunk-UNDHEXY4.js → chunk-UA6EZLBP.js} +2 -2
- package/dist/{chunk-VWWKBNTP.js → chunk-V7LANF6T.js} +1 -1
- package/dist/executions.js +9 -9
- package/dist/history.js +4 -4
- package/dist/index.d.ts +45 -3
- package/dist/index.js +31 -31
- package/dist/nodes.js +2 -2
- package/dist/observability.js +4 -4
- package/dist/settings.js +4 -4
- package/dist/templates.js +8 -8
- package/dist/{workflow-builder-Uhk2DIB6.d.ts → workflow-builder-hl-BbuPF.d.ts} +20 -16
- package/dist/workflow-builder.d.ts +1 -1
- package/dist/workflow-builder.js +10 -10
- package/dist/workflows-list.js +7 -7
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useFluidGridsFlag, FLUIDGRIDS_FLAGS, LogStreamingTab } from './chunk-
|
|
1
|
+
import { useFluidGridsFlag, FLUIDGRIDS_FLAGS, LogStreamingTab } from './chunk-BAPA4FLZ.js';
|
|
2
2
|
import { FluidGridsDocsLink } from './chunk-4VJ3MDOV.js';
|
|
3
|
-
import { useFlowStore } from './chunk-
|
|
4
|
-
import { useWorkflowDefinitionQuery, useUpdateWorkflowDefinitionMutation, useWorkflowDefinitionsQuery } from './chunk-
|
|
3
|
+
import { useFlowStore, useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, throwIfResultError } from './chunk-SCPH5T5I.js';
|
|
4
|
+
import { useWorkflowDefinitionQuery, useUpdateWorkflowDefinitionMutation, useWorkflowDefinitionsQuery } from './chunk-2NUE2X74.js';
|
|
5
5
|
import { useTr } from './chunk-UULVIT25.js';
|
|
6
|
+
import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
6
7
|
import { useState, useMemo, useEffect, useCallback } from 'react';
|
|
7
8
|
import { useNavigate, useParams } from 'react-router';
|
|
8
9
|
import { Icon } from '@iconify/react';
|
|
@@ -10,6 +11,336 @@ import { Button } from '@burdenoff/fe-libs/button';
|
|
|
10
11
|
import { Tabs, TabsList, TabsTrigger, TabsContent, Input, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Card, CardHeader, Label, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@burdenoff/fe-libs/ui';
|
|
11
12
|
import { toast } from 'sonner';
|
|
12
13
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
14
|
+
import { gql } from '@apollo/client';
|
|
15
|
+
|
|
16
|
+
function SettingRow({
|
|
17
|
+
label,
|
|
18
|
+
description,
|
|
19
|
+
children
|
|
20
|
+
}) {
|
|
21
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 py-4", children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-text-primary", children: label }),
|
|
24
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary mt-0.5", children: description })
|
|
25
|
+
] }),
|
|
26
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0", children })
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
var FIELDS = `
|
|
30
|
+
saveSuccessfulRuns
|
|
31
|
+
saveFailedRuns
|
|
32
|
+
saveManualRuns
|
|
33
|
+
retentionDays
|
|
34
|
+
retentionMaxRunsPerWorkflow
|
|
35
|
+
customized
|
|
36
|
+
updatedAt
|
|
37
|
+
`;
|
|
38
|
+
var RUN_DATA_SETTINGS_QUERY = gql`
|
|
39
|
+
query WorkflowExecutionSettings {
|
|
40
|
+
workflowExecutionSettings {
|
|
41
|
+
${FIELDS}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
var UPDATE_RUN_DATA_SETTINGS = gql`
|
|
46
|
+
mutation UpdateWorkflowExecutionSettings($input: UpdateWorkflowExecutionSettingsInput!) {
|
|
47
|
+
updateWorkflowExecutionSettings(input: $input) {
|
|
48
|
+
${FIELDS}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
function useRunDataSettings() {
|
|
53
|
+
const [settings, setSettings] = useState(null);
|
|
54
|
+
const [loading, setLoading] = useState(true);
|
|
55
|
+
const [error, setError] = useState(null);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
let cancelled = false;
|
|
58
|
+
getFluidGridsClient().query({
|
|
59
|
+
query: RUN_DATA_SETTINGS_QUERY,
|
|
60
|
+
fetchPolicy: "network-only"
|
|
61
|
+
}).then((result) => {
|
|
62
|
+
throwIfResultError(result);
|
|
63
|
+
if (!cancelled)
|
|
64
|
+
setSettings(result.data?.workflowExecutionSettings ?? null);
|
|
65
|
+
}).catch((err) => {
|
|
66
|
+
if (!cancelled)
|
|
67
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
68
|
+
}).finally(() => {
|
|
69
|
+
if (!cancelled) setLoading(false);
|
|
70
|
+
});
|
|
71
|
+
return () => {
|
|
72
|
+
cancelled = true;
|
|
73
|
+
};
|
|
74
|
+
}, []);
|
|
75
|
+
const save = useCallback(async (changes) => {
|
|
76
|
+
const result = await getFluidGridsClient().mutate({ mutation: UPDATE_RUN_DATA_SETTINGS, variables: { input: changes } });
|
|
77
|
+
throwIfResultError(result);
|
|
78
|
+
const saved = result.data?.updateWorkflowExecutionSettings;
|
|
79
|
+
if (!saved) throw new Error("No settings returned");
|
|
80
|
+
setSettings(saved);
|
|
81
|
+
return saved;
|
|
82
|
+
}, []);
|
|
83
|
+
return { settings, loading, error, save };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/modules/settings/utils/run-data.ts
|
|
87
|
+
function toSavingChoice(value) {
|
|
88
|
+
if (value === void 0) return "default";
|
|
89
|
+
return value ? "save" : "skip";
|
|
90
|
+
}
|
|
91
|
+
function fromSavingChoice(choice) {
|
|
92
|
+
if (choice === "save") return true;
|
|
93
|
+
if (choice === "skip") return false;
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
function compactOverrides(value) {
|
|
97
|
+
if (!value) return void 0;
|
|
98
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0);
|
|
99
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
100
|
+
}
|
|
101
|
+
var RETENTION_DAYS_RANGE = { min: 1, max: 3650 };
|
|
102
|
+
var RETENTION_MAX_RUNS_RANGE = { min: 1, max: 1e6 };
|
|
103
|
+
function parseBoundedInt(value, range) {
|
|
104
|
+
if (value.trim() === "") return void 0;
|
|
105
|
+
const parsed = Number(value);
|
|
106
|
+
if (!Number.isFinite(parsed)) return void 0;
|
|
107
|
+
return Math.min(range.max, Math.max(range.min, Math.trunc(parsed)));
|
|
108
|
+
}
|
|
109
|
+
function RunDataTab() {
|
|
110
|
+
const tr = useTr();
|
|
111
|
+
const { settings, loading, error, save } = useRunDataSettings();
|
|
112
|
+
const [form, setForm] = useState(null);
|
|
113
|
+
const [saving, setSaving] = useState(false);
|
|
114
|
+
const { allowed: canEdit } = useFluidGridsPermission(
|
|
115
|
+
FLUIDGRIDS_PERMISSIONS.WORKFLOW_DELETE
|
|
116
|
+
);
|
|
117
|
+
const locked = loading || !form || saving || !canEdit;
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!settings) return;
|
|
120
|
+
setForm({
|
|
121
|
+
saveSuccessfulRuns: settings.saveSuccessfulRuns,
|
|
122
|
+
saveFailedRuns: settings.saveFailedRuns,
|
|
123
|
+
saveManualRuns: settings.saveManualRuns,
|
|
124
|
+
retentionDays: String(settings.retentionDays),
|
|
125
|
+
retentionMaxRunsPerWorkflow: String(settings.retentionMaxRunsPerWorkflow)
|
|
126
|
+
});
|
|
127
|
+
}, [settings]);
|
|
128
|
+
const handleSave = async () => {
|
|
129
|
+
if (!form) return;
|
|
130
|
+
const retentionDays = parseBoundedInt(
|
|
131
|
+
form.retentionDays,
|
|
132
|
+
RETENTION_DAYS_RANGE
|
|
133
|
+
);
|
|
134
|
+
const retentionMaxRunsPerWorkflow = parseBoundedInt(
|
|
135
|
+
form.retentionMaxRunsPerWorkflow,
|
|
136
|
+
RETENTION_MAX_RUNS_RANGE
|
|
137
|
+
);
|
|
138
|
+
if (retentionDays === void 0 || retentionMaxRunsPerWorkflow === void 0) {
|
|
139
|
+
toast.error(
|
|
140
|
+
tr(
|
|
141
|
+
"fluidgrids.settings.runData.numbersRequired",
|
|
142
|
+
"Enter a number of days and a number of runs."
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
setSaving(true);
|
|
148
|
+
try {
|
|
149
|
+
await save({
|
|
150
|
+
saveSuccessfulRuns: form.saveSuccessfulRuns,
|
|
151
|
+
saveFailedRuns: form.saveFailedRuns,
|
|
152
|
+
saveManualRuns: form.saveManualRuns,
|
|
153
|
+
retentionDays,
|
|
154
|
+
retentionMaxRunsPerWorkflow
|
|
155
|
+
});
|
|
156
|
+
toast.success(
|
|
157
|
+
tr("fluidgrids.settings.runData.savedToast", "Run data settings saved")
|
|
158
|
+
);
|
|
159
|
+
} catch (err) {
|
|
160
|
+
toast.error(
|
|
161
|
+
tr(
|
|
162
|
+
"fluidgrids.settings.runData.saveFailedToast",
|
|
163
|
+
"Failed to save settings"
|
|
164
|
+
),
|
|
165
|
+
{ description: err instanceof Error ? err.message : void 0 }
|
|
166
|
+
);
|
|
167
|
+
} finally {
|
|
168
|
+
setSaving(false);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
if (error) {
|
|
172
|
+
return /* @__PURE__ */ jsx("p", { className: "text-sm text-status-error-text", role: "alert", children: tr(
|
|
173
|
+
"fluidgrids.settings.runData.loadFailed",
|
|
174
|
+
"Could not load the run data settings."
|
|
175
|
+
) });
|
|
176
|
+
}
|
|
177
|
+
const setFlag = (key) => (checked) => setForm((f) => f ? { ...f, [key]: checked } : f);
|
|
178
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": "run-data-settings", children: [
|
|
179
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 p-3 rounded-lg bg-background-secondary border border-border-secondary mb-6", children: [
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
Icon,
|
|
182
|
+
{
|
|
183
|
+
icon: "mdi:database-clock-outline",
|
|
184
|
+
width: 18,
|
|
185
|
+
className: "text-text-secondary shrink-0 mt-0.5"
|
|
186
|
+
}
|
|
187
|
+
),
|
|
188
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary", children: tr(
|
|
189
|
+
"fluidgrids.settings.runData.intro",
|
|
190
|
+
"These apply to every workflow in this workspace unless its own Execution settings say otherwise. A run whose data is not kept still shows its status, timings and error."
|
|
191
|
+
) })
|
|
192
|
+
] }),
|
|
193
|
+
!canEdit && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary mb-4", role: "note", children: tr(
|
|
194
|
+
"fluidgrids.settings.runData.readOnly",
|
|
195
|
+
"You can see these settings but not change them: changing them needs permission to delete workflows."
|
|
196
|
+
) }),
|
|
197
|
+
/* @__PURE__ */ jsxs("div", { className: "divide-y divide-border-secondary", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
SettingRow,
|
|
200
|
+
{
|
|
201
|
+
label: tr(
|
|
202
|
+
"fluidgrids.settings.runData.saveSuccessfulLabel",
|
|
203
|
+
"Keep data of successful runs"
|
|
204
|
+
),
|
|
205
|
+
description: tr(
|
|
206
|
+
"fluidgrids.settings.runData.saveSuccessfulDescription",
|
|
207
|
+
"Trigger data, node inputs and outputs, and logs of runs that finished successfully."
|
|
208
|
+
),
|
|
209
|
+
children: /* @__PURE__ */ jsx(
|
|
210
|
+
Switch,
|
|
211
|
+
{
|
|
212
|
+
"aria-label": tr(
|
|
213
|
+
"fluidgrids.settings.runData.saveSuccessfulLabel",
|
|
214
|
+
"Keep data of successful runs"
|
|
215
|
+
),
|
|
216
|
+
checked: form?.saveSuccessfulRuns ?? true,
|
|
217
|
+
onCheckedChange: setFlag("saveSuccessfulRuns"),
|
|
218
|
+
disabled: locked
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
/* @__PURE__ */ jsx(
|
|
224
|
+
SettingRow,
|
|
225
|
+
{
|
|
226
|
+
label: tr(
|
|
227
|
+
"fluidgrids.settings.runData.saveFailedLabel",
|
|
228
|
+
"Keep data of failed runs"
|
|
229
|
+
),
|
|
230
|
+
description: tr(
|
|
231
|
+
"fluidgrids.settings.runData.saveFailedDescription",
|
|
232
|
+
"Runs that failed, were cancelled or were stopped."
|
|
233
|
+
),
|
|
234
|
+
children: /* @__PURE__ */ jsx(
|
|
235
|
+
Switch,
|
|
236
|
+
{
|
|
237
|
+
"aria-label": tr(
|
|
238
|
+
"fluidgrids.settings.runData.saveFailedLabel",
|
|
239
|
+
"Keep data of failed runs"
|
|
240
|
+
),
|
|
241
|
+
checked: form?.saveFailedRuns ?? true,
|
|
242
|
+
onCheckedChange: setFlag("saveFailedRuns"),
|
|
243
|
+
disabled: locked
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
/* @__PURE__ */ jsx(
|
|
249
|
+
SettingRow,
|
|
250
|
+
{
|
|
251
|
+
label: tr(
|
|
252
|
+
"fluidgrids.settings.runData.saveManualLabel",
|
|
253
|
+
"Keep data of test runs"
|
|
254
|
+
),
|
|
255
|
+
description: tr(
|
|
256
|
+
"fluidgrids.settings.runData.saveManualDescription",
|
|
257
|
+
"Runs started from the editor to test a workflow."
|
|
258
|
+
),
|
|
259
|
+
children: /* @__PURE__ */ jsx(
|
|
260
|
+
Switch,
|
|
261
|
+
{
|
|
262
|
+
"aria-label": tr(
|
|
263
|
+
"fluidgrids.settings.runData.saveManualLabel",
|
|
264
|
+
"Keep data of test runs"
|
|
265
|
+
),
|
|
266
|
+
checked: form?.saveManualRuns ?? true,
|
|
267
|
+
onCheckedChange: setFlag("saveManualRuns"),
|
|
268
|
+
disabled: locked
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
/* @__PURE__ */ jsx(
|
|
274
|
+
SettingRow,
|
|
275
|
+
{
|
|
276
|
+
label: tr(
|
|
277
|
+
"fluidgrids.settings.runData.retentionDaysLabel",
|
|
278
|
+
"Delete runs after"
|
|
279
|
+
),
|
|
280
|
+
description: tr(
|
|
281
|
+
"fluidgrids.settings.runData.retentionDaysDescription",
|
|
282
|
+
"Finished runs older than this are deleted, with their data. If your plan keeps run history for less time, the plan's limit applies."
|
|
283
|
+
),
|
|
284
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
285
|
+
/* @__PURE__ */ jsx(
|
|
286
|
+
Input,
|
|
287
|
+
{
|
|
288
|
+
type: "number",
|
|
289
|
+
min: RETENTION_DAYS_RANGE.min,
|
|
290
|
+
max: RETENTION_DAYS_RANGE.max,
|
|
291
|
+
"aria-label": tr(
|
|
292
|
+
"fluidgrids.settings.runData.retentionDaysLabel",
|
|
293
|
+
"Delete runs after"
|
|
294
|
+
),
|
|
295
|
+
value: form?.retentionDays ?? "",
|
|
296
|
+
onChange: (e) => {
|
|
297
|
+
const retentionDays = e.target.value;
|
|
298
|
+
setForm((f) => f ? { ...f, retentionDays } : f);
|
|
299
|
+
},
|
|
300
|
+
disabled: locked,
|
|
301
|
+
className: "w-[100px] text-right"
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: tr("fluidgrids.settings.runData.daysUnit", "days") })
|
|
305
|
+
] })
|
|
306
|
+
}
|
|
307
|
+
),
|
|
308
|
+
/* @__PURE__ */ jsx(
|
|
309
|
+
SettingRow,
|
|
310
|
+
{
|
|
311
|
+
label: tr(
|
|
312
|
+
"fluidgrids.settings.runData.maxRunsLabel",
|
|
313
|
+
"Runs kept per workflow"
|
|
314
|
+
),
|
|
315
|
+
description: tr(
|
|
316
|
+
"fluidgrids.settings.runData.maxRunsDescription",
|
|
317
|
+
"Beyond this many finished runs, the oldest are deleted."
|
|
318
|
+
),
|
|
319
|
+
children: /* @__PURE__ */ jsx(
|
|
320
|
+
Input,
|
|
321
|
+
{
|
|
322
|
+
type: "number",
|
|
323
|
+
min: RETENTION_MAX_RUNS_RANGE.min,
|
|
324
|
+
max: RETENTION_MAX_RUNS_RANGE.max,
|
|
325
|
+
"aria-label": tr(
|
|
326
|
+
"fluidgrids.settings.runData.maxRunsLabel",
|
|
327
|
+
"Runs kept per workflow"
|
|
328
|
+
),
|
|
329
|
+
value: form?.retentionMaxRunsPerWorkflow ?? "",
|
|
330
|
+
onChange: (e) => {
|
|
331
|
+
const retentionMaxRunsPerWorkflow = e.target.value;
|
|
332
|
+
setForm((f) => f ? { ...f, retentionMaxRunsPerWorkflow } : f);
|
|
333
|
+
},
|
|
334
|
+
disabled: locked,
|
|
335
|
+
className: "w-[120px] text-right"
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
)
|
|
340
|
+
] }),
|
|
341
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsx(Button, { onClick: () => void handleSave(), disabled: locked, children: saving ? tr("fluidgrids.settings.runData.saving", "Saving\u2026") : tr("fluidgrids.settings.runData.save", "Save") }) })
|
|
342
|
+
] });
|
|
343
|
+
}
|
|
13
344
|
|
|
14
345
|
// src/modules/settings/utils/error-trigger.ts
|
|
15
346
|
var ERROR_TRIGGER_NODE_TYPE = "internal:error-trigger";
|
|
@@ -26,24 +357,45 @@ function hasErrorTriggerNode(definitionJson) {
|
|
|
26
357
|
// src/modules/settings/utils/optional-positive-int.ts
|
|
27
358
|
function parseOptionalPositiveInt(value) {
|
|
28
359
|
if (value.trim() === "") return void 0;
|
|
29
|
-
const parsed = Number
|
|
30
|
-
return Number.isFinite(parsed) ? Math.max(1, parsed) : void 0;
|
|
360
|
+
const parsed = Number(value);
|
|
361
|
+
return Number.isFinite(parsed) ? Math.max(1, Math.trunc(parsed)) : void 0;
|
|
31
362
|
}
|
|
32
363
|
|
|
33
364
|
// src/modules/settings/utils/workflow-settings-persistence.ts
|
|
365
|
+
var DATA_SAVING_KEYS = [
|
|
366
|
+
"saveSuccessExecutions",
|
|
367
|
+
"saveFailedExecutions",
|
|
368
|
+
"saveManualExecutions"
|
|
369
|
+
];
|
|
370
|
+
var RETENTION_KEYS = [
|
|
371
|
+
"maxAgeDays",
|
|
372
|
+
"maxRuns"
|
|
373
|
+
];
|
|
34
374
|
function mergeWorkflowExecutionSettings(existing, next) {
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
375
|
+
const merged = { ...existing, ...next };
|
|
376
|
+
for (const [key, editable] of [
|
|
377
|
+
["dataSaving", DATA_SAVING_KEYS],
|
|
378
|
+
["retention", RETENTION_KEYS]
|
|
379
|
+
]) {
|
|
380
|
+
const nested = mergeNested(existing[key], next[key], editable);
|
|
381
|
+
if (nested) merged[key] = nested;
|
|
382
|
+
else delete merged[key];
|
|
383
|
+
}
|
|
384
|
+
return merged;
|
|
385
|
+
}
|
|
386
|
+
function mergeNested(existing, next, editable) {
|
|
387
|
+
const editableKeys = new Set(editable);
|
|
388
|
+
const kept = Object.fromEntries(
|
|
389
|
+
Object.entries(isRecord(existing) ? existing : {}).filter(
|
|
390
|
+
([key]) => !editableKeys.has(key)
|
|
391
|
+
)
|
|
392
|
+
);
|
|
393
|
+
const result = Object.fromEntries(
|
|
394
|
+
Object.entries({ ...kept, ...next ?? {} }).filter(
|
|
395
|
+
([, value]) => value !== void 0
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
47
399
|
}
|
|
48
400
|
function isRecord(value) {
|
|
49
401
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -120,19 +472,6 @@ function CopyButton({ value, label }) {
|
|
|
120
472
|
] })
|
|
121
473
|
] }) });
|
|
122
474
|
}
|
|
123
|
-
function SettingRow({
|
|
124
|
-
label,
|
|
125
|
-
description,
|
|
126
|
-
children
|
|
127
|
-
}) {
|
|
128
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 py-4", children: [
|
|
129
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
130
|
-
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-text-primary", children: label }),
|
|
131
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary mt-0.5", children: description })
|
|
132
|
-
] }),
|
|
133
|
-
/* @__PURE__ */ jsx("div", { className: "shrink-0", children })
|
|
134
|
-
] });
|
|
135
|
-
}
|
|
136
475
|
function GeneralTab() {
|
|
137
476
|
const tr = useTr();
|
|
138
477
|
const settings = DEFAULT_SETTINGS.general;
|
|
@@ -206,6 +545,10 @@ function ExecutionTab({ workflowKey }) {
|
|
|
206
545
|
fetchPolicy: "cache-and-network"
|
|
207
546
|
});
|
|
208
547
|
const [updateWorkflowDefinition, { loading: saving }] = useUpdateWorkflowDefinitionMutation();
|
|
548
|
+
const { allowed: canEdit } = useFluidGridsPermission(
|
|
549
|
+
FLUIDGRIDS_PERMISSIONS.WORKFLOW_UPDATE
|
|
550
|
+
);
|
|
551
|
+
const locked = loading || saving || !canEdit;
|
|
209
552
|
const { data: otherWorkflowsData, loading: otherWorkflowsLoading } = useWorkflowDefinitionsQuery({
|
|
210
553
|
variables: { input: { latestOnly: true, limit: 100 } }
|
|
211
554
|
});
|
|
@@ -218,6 +561,7 @@ function ExecutionTab({ workflowKey }) {
|
|
|
218
561
|
}, [workflow?.definitionJson]);
|
|
219
562
|
const [form, setForm] = useState(persistedConfig);
|
|
220
563
|
useEffect(() => setForm(persistedConfig), [persistedConfig]);
|
|
564
|
+
const runData = useRunDataSettings();
|
|
221
565
|
const selectedErrorWorkflowKey = form.errorWorkflowKey;
|
|
222
566
|
const { data: errorWorkflowData } = useWorkflowDefinitionQuery({
|
|
223
567
|
variables: { workflowKey: selectedErrorWorkflowKey ?? "" },
|
|
@@ -335,7 +679,7 @@ function ExecutionTab({ workflowKey }) {
|
|
|
335
679
|
...f,
|
|
336
680
|
timeout: parseOptionalPositiveInt(e.target.value)
|
|
337
681
|
})),
|
|
338
|
-
disabled:
|
|
682
|
+
disabled: locked,
|
|
339
683
|
className: "w-[100px] text-right"
|
|
340
684
|
}
|
|
341
685
|
),
|
|
@@ -375,7 +719,7 @@ function ExecutionTab({ workflowKey }) {
|
|
|
375
719
|
...f,
|
|
376
720
|
maxParallelism: parseOptionalPositiveInt(e.target.value)
|
|
377
721
|
})),
|
|
378
|
-
disabled:
|
|
722
|
+
disabled: locked,
|
|
379
723
|
className: "w-[100px] text-right"
|
|
380
724
|
}
|
|
381
725
|
)
|
|
@@ -400,7 +744,7 @@ function ExecutionTab({ workflowKey }) {
|
|
|
400
744
|
...f,
|
|
401
745
|
onError: e.target.value
|
|
402
746
|
})),
|
|
403
|
-
disabled:
|
|
747
|
+
disabled: locked,
|
|
404
748
|
className: "w-[160px] rounded-md border border-border-secondary bg-background-secondary px-2 py-1.5 text-sm text-text-primary",
|
|
405
749
|
children: [
|
|
406
750
|
/* @__PURE__ */ jsx("option", { value: "stop", children: tr("fluidgrids.settings.execution.onErrorStop", "Stop") }),
|
|
@@ -431,7 +775,7 @@ function ExecutionTab({ workflowKey }) {
|
|
|
431
775
|
...f,
|
|
432
776
|
errorWorkflowKey: val === "__none__" ? void 0 : val
|
|
433
777
|
})),
|
|
434
|
-
disabled:
|
|
778
|
+
disabled: locked || otherWorkflowsLoading,
|
|
435
779
|
children: [
|
|
436
780
|
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-[220px] bg-background-secondary border-border-secondary", children: /* @__PURE__ */ jsx(
|
|
437
781
|
SelectValue,
|
|
@@ -466,22 +810,104 @@ function ExecutionTab({ workflowKey }) {
|
|
|
466
810
|
] })
|
|
467
811
|
}
|
|
468
812
|
),
|
|
813
|
+
[
|
|
814
|
+
{
|
|
815
|
+
key: "saveSuccessExecutions",
|
|
816
|
+
workspaceKey: "saveSuccessfulRuns",
|
|
817
|
+
labelKey: "fluidgrids.settings.execution.saveSuccessLabel",
|
|
818
|
+
label: "Keep data of successful runs"
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
key: "saveFailedExecutions",
|
|
822
|
+
workspaceKey: "saveFailedRuns",
|
|
823
|
+
labelKey: "fluidgrids.settings.execution.saveFailedLabel",
|
|
824
|
+
label: "Keep data of failed runs"
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
key: "saveManualExecutions",
|
|
828
|
+
workspaceKey: "saveManualRuns",
|
|
829
|
+
labelKey: "fluidgrids.settings.execution.saveManualLabel",
|
|
830
|
+
label: "Keep data of test runs"
|
|
831
|
+
}
|
|
832
|
+
].map((row) => {
|
|
833
|
+
const inherited = runData.settings?.[row.workspaceKey];
|
|
834
|
+
return /* @__PURE__ */ jsx(SettingRow, { label: tr(row.labelKey, row.label), children: /* @__PURE__ */ jsxs(
|
|
835
|
+
Select,
|
|
836
|
+
{
|
|
837
|
+
value: toSavingChoice(form.dataSaving?.[row.key]),
|
|
838
|
+
onValueChange: (choice) => setForm((f) => ({
|
|
839
|
+
...f,
|
|
840
|
+
dataSaving: compactOverrides({
|
|
841
|
+
...f.dataSaving,
|
|
842
|
+
[row.key]: fromSavingChoice(choice)
|
|
843
|
+
})
|
|
844
|
+
})),
|
|
845
|
+
disabled: locked,
|
|
846
|
+
children: [
|
|
847
|
+
/* @__PURE__ */ jsx(
|
|
848
|
+
SelectTrigger,
|
|
849
|
+
{
|
|
850
|
+
"aria-label": tr(row.labelKey, row.label),
|
|
851
|
+
className: "w-[220px] bg-background-secondary border-border-secondary",
|
|
852
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
853
|
+
}
|
|
854
|
+
),
|
|
855
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
856
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "default", children: inherited === void 0 ? tr(
|
|
857
|
+
"fluidgrids.settings.execution.savingDefault",
|
|
858
|
+
"Workspace default"
|
|
859
|
+
) : inherited ? tr(
|
|
860
|
+
"fluidgrids.settings.execution.savingDefaultOn",
|
|
861
|
+
"Workspace default (keep)"
|
|
862
|
+
) : tr(
|
|
863
|
+
"fluidgrids.settings.execution.savingDefaultOff",
|
|
864
|
+
"Workspace default (don't keep)"
|
|
865
|
+
) }),
|
|
866
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "save", children: tr("fluidgrids.settings.execution.savingKeep", "Keep") }),
|
|
867
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "skip", children: tr(
|
|
868
|
+
"fluidgrids.settings.execution.savingDontKeep",
|
|
869
|
+
"Don't keep"
|
|
870
|
+
) })
|
|
871
|
+
] })
|
|
872
|
+
]
|
|
873
|
+
}
|
|
874
|
+
) }, row.key);
|
|
875
|
+
}),
|
|
469
876
|
/* @__PURE__ */ jsx(
|
|
470
877
|
SettingRow,
|
|
471
878
|
{
|
|
472
879
|
label: tr(
|
|
473
|
-
"fluidgrids.settings.execution.
|
|
474
|
-
"
|
|
880
|
+
"fluidgrids.settings.execution.retentionDaysLabel",
|
|
881
|
+
"Delete runs after (days)"
|
|
882
|
+
),
|
|
883
|
+
description: tr(
|
|
884
|
+
"fluidgrids.settings.execution.retentionDaysDescription",
|
|
885
|
+
"Leave empty to follow the workspace's Run data settings."
|
|
475
886
|
),
|
|
476
887
|
children: /* @__PURE__ */ jsx(
|
|
477
|
-
|
|
888
|
+
Input,
|
|
478
889
|
{
|
|
479
|
-
|
|
480
|
-
|
|
890
|
+
type: "number",
|
|
891
|
+
min: RETENTION_DAYS_RANGE.min,
|
|
892
|
+
max: RETENTION_DAYS_RANGE.max,
|
|
893
|
+
"aria-label": tr(
|
|
894
|
+
"fluidgrids.settings.execution.retentionDaysLabel",
|
|
895
|
+
"Delete runs after (days)"
|
|
896
|
+
),
|
|
897
|
+
value: form.retention?.maxAgeDays ?? "",
|
|
898
|
+
placeholder: runData.settings ? String(runData.settings.retentionDays) : "",
|
|
899
|
+
onChange: (e) => setForm((f) => ({
|
|
481
900
|
...f,
|
|
482
|
-
|
|
901
|
+
retention: compactOverrides({
|
|
902
|
+
...f.retention,
|
|
903
|
+
maxAgeDays: parseBoundedInt(
|
|
904
|
+
e.target.value,
|
|
905
|
+
RETENTION_DAYS_RANGE
|
|
906
|
+
)
|
|
907
|
+
})
|
|
483
908
|
})),
|
|
484
|
-
disabled:
|
|
909
|
+
disabled: locked,
|
|
910
|
+
className: "w-[100px] text-right"
|
|
485
911
|
}
|
|
486
912
|
)
|
|
487
913
|
}
|
|
@@ -489,25 +915,45 @@ function ExecutionTab({ workflowKey }) {
|
|
|
489
915
|
/* @__PURE__ */ jsx(
|
|
490
916
|
SettingRow,
|
|
491
917
|
{
|
|
492
|
-
label: tr(
|
|
493
|
-
|
|
494
|
-
"
|
|
918
|
+
label: tr("fluidgrids.settings.execution.maxRunsLabel", "Runs kept"),
|
|
919
|
+
description: tr(
|
|
920
|
+
"fluidgrids.settings.execution.maxRunsDescription",
|
|
921
|
+
"Leave empty to follow the workspace's Run data settings."
|
|
495
922
|
),
|
|
496
923
|
children: /* @__PURE__ */ jsx(
|
|
497
|
-
|
|
924
|
+
Input,
|
|
498
925
|
{
|
|
499
|
-
|
|
500
|
-
|
|
926
|
+
type: "number",
|
|
927
|
+
min: RETENTION_MAX_RUNS_RANGE.min,
|
|
928
|
+
max: RETENTION_MAX_RUNS_RANGE.max,
|
|
929
|
+
"aria-label": tr(
|
|
930
|
+
"fluidgrids.settings.execution.maxRunsLabel",
|
|
931
|
+
"Runs kept"
|
|
932
|
+
),
|
|
933
|
+
value: form.retention?.maxRuns ?? "",
|
|
934
|
+
placeholder: runData.settings ? String(runData.settings.retentionMaxRunsPerWorkflow) : "",
|
|
935
|
+
onChange: (e) => setForm((f) => ({
|
|
501
936
|
...f,
|
|
502
|
-
|
|
937
|
+
retention: compactOverrides({
|
|
938
|
+
...f.retention,
|
|
939
|
+
maxRuns: parseBoundedInt(
|
|
940
|
+
e.target.value,
|
|
941
|
+
RETENTION_MAX_RUNS_RANGE
|
|
942
|
+
)
|
|
943
|
+
})
|
|
503
944
|
})),
|
|
504
|
-
disabled:
|
|
945
|
+
disabled: locked,
|
|
946
|
+
className: "w-[120px] text-right"
|
|
505
947
|
}
|
|
506
948
|
)
|
|
507
949
|
}
|
|
508
950
|
)
|
|
509
951
|
] }),
|
|
510
|
-
/* @__PURE__ */ jsx("
|
|
952
|
+
!canEdit && /* @__PURE__ */ jsx("p", { className: "mt-4 text-xs text-text-secondary", role: "note", children: tr(
|
|
953
|
+
"fluidgrids.settings.execution.readOnly",
|
|
954
|
+
"You can see these settings but not change them: changing them needs permission to edit workflows."
|
|
955
|
+
) }),
|
|
956
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsx(Button, { onClick: () => void handleSave(), disabled: locked, children: saving ? tr("fluidgrids.settings.execution.saving", "Saving\u2026") : tr("fluidgrids.settings.execution.save", "Save") }) })
|
|
511
957
|
] });
|
|
512
958
|
}
|
|
513
959
|
function NotificationsTab() {
|
|
@@ -760,6 +1206,10 @@ function SettingsPage({
|
|
|
760
1206
|
]
|
|
761
1207
|
}
|
|
762
1208
|
),
|
|
1209
|
+
/* @__PURE__ */ jsxs(TabsTrigger, { value: "run-data", className: "gap-1.5", children: [
|
|
1210
|
+
/* @__PURE__ */ jsx(Icon, { icon: "mdi:database-clock-outline", width: 16 }),
|
|
1211
|
+
tr("fluidgrids.settings.page.runDataTab", "Run data")
|
|
1212
|
+
] }),
|
|
763
1213
|
/* @__PURE__ */ jsxs(TabsTrigger, { value: "notifications", className: "gap-1.5", children: [
|
|
764
1214
|
/* @__PURE__ */ jsx(Icon, { icon: "mdi:bell-outline", width: 16 }),
|
|
765
1215
|
tr("fluidgrids.settings.page.notificationsTab", "Notifications")
|
|
@@ -785,6 +1235,7 @@ function SettingsPage({
|
|
|
785
1235
|
),
|
|
786
1236
|
/* @__PURE__ */ jsx(TabsContent, { value: "general", children: /* @__PURE__ */ jsx(GeneralTab, {}) }),
|
|
787
1237
|
/* @__PURE__ */ jsx(TabsContent, { value: "execution", children: /* @__PURE__ */ jsx(ExecutionTab, { workflowKey }) }),
|
|
1238
|
+
/* @__PURE__ */ jsx(TabsContent, { value: "run-data", children: /* @__PURE__ */ jsx(RunDataTab, {}) }),
|
|
788
1239
|
/* @__PURE__ */ jsx(TabsContent, { value: "notifications", children: /* @__PURE__ */ jsx(NotificationsTab, {}) }),
|
|
789
1240
|
logStreamsEnabled ? /* @__PURE__ */ jsx(TabsContent, { value: "log-streaming", children: /* @__PURE__ */ jsx(LogStreamingTab, {}) }) : null,
|
|
790
1241
|
/* @__PURE__ */ jsx(TabsContent, { value: "api", children: /* @__PURE__ */ jsx(ApiTab, {}) })
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Card, FluidGridsMark } from './chunk-
|
|
1
|
+
import { Card, FluidGridsMark } from './chunk-3MLOFJW3.js';
|
|
2
2
|
import { Input } from './chunk-IEVSFCFS.js';
|
|
3
3
|
import { Button } from './chunk-BQXVT32O.js';
|
|
4
|
-
import { useWorkflowDefinition } from './chunk-
|
|
5
|
-
import { FluidGridsProvider, useFlowStore } from './chunk-
|
|
4
|
+
import { useWorkflowDefinition } from './chunk-5TRLB2QS.js';
|
|
5
|
+
import { FluidGridsProvider, useFlowStore } from './chunk-SCPH5T5I.js';
|
|
6
6
|
import { cn } from './chunk-JL7CASN5.js';
|
|
7
7
|
import { useTr } from './chunk-UULVIT25.js';
|
|
8
8
|
import { useState, useRef, useEffect, useCallback } from 'react';
|