@burdenoff/fluidgrids-fe-sdk 2026.922.13 → 2026.923.2
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-BD7CS4KL.js +12 -0
- package/dist/{ExecutionDetailPage-OSDL7NDT.js.map → ExecutionDetailPage-BD7CS4KL.js.map} +1 -1
- package/dist/ExecutionsListPage-VOGSLA7T.js +11 -0
- package/dist/{ExecutionsListPage-AATDFFIH.js.map → ExecutionsListPage-VOGSLA7T.js.map} +1 -1
- package/dist/{WorkflowBuilder-D7RKU4UK.js → WorkflowBuilder-WLJBVVHS.js} +8 -8
- package/dist/{WorkflowBuilder-D7RKU4UK.js.map → WorkflowBuilder-WLJBVVHS.js.map} +1 -1
- package/dist/{WorkflowsList-JHM7Q5HE.js → WorkflowsList-QREUMT55.js} +6 -6
- package/dist/{WorkflowsList-JHM7Q5HE.js.map → WorkflowsList-QREUMT55.js.map} +1 -1
- package/dist/{chunk-5IAMVAGX.js → chunk-4C6UYNC5.js} +43 -5
- package/dist/chunk-4C6UYNC5.js.map +1 -0
- package/dist/chunk-5A7GP6O7.js +729 -0
- package/dist/chunk-5A7GP6O7.js.map +1 -0
- package/dist/{chunk-MTWEYC2W.js → chunk-5PZDLMC4.js} +4 -4
- package/dist/{chunk-MTWEYC2W.js.map → chunk-5PZDLMC4.js.map} +1 -1
- package/dist/chunk-FKOUPL6Z.js +753 -0
- package/dist/chunk-FKOUPL6Z.js.map +1 -0
- package/dist/{chunk-EUZZLC3N.js → chunk-HNVWIVJH.js} +202 -6
- package/dist/chunk-HNVWIVJH.js.map +1 -0
- package/dist/{chunk-PTGKDQ5K.js → chunk-LH2YML5F.js} +8 -2
- package/dist/chunk-LH2YML5F.js.map +1 -0
- package/dist/chunk-NK32XOQN.js +248 -0
- package/dist/chunk-NK32XOQN.js.map +1 -0
- package/dist/{chunk-CVVNQCFM.js → chunk-Q4RPP67K.js} +4 -4
- package/dist/{chunk-CVVNQCFM.js.map → chunk-Q4RPP67K.js.map} +1 -1
- package/dist/{chunk-UNW4I442.js → chunk-Q7RJYGQK.js} +3 -3
- package/dist/{chunk-UNW4I442.js.map → chunk-Q7RJYGQK.js.map} +1 -1
- package/dist/{chunk-RJQJAN6J.js → chunk-TEZV7I6A.js} +4 -4
- package/dist/{chunk-RJQJAN6J.js.map → chunk-TEZV7I6A.js.map} +1 -1
- package/dist/{chunk-XQYAM47Y.js → chunk-TOHTP3BT.js} +4 -4
- package/dist/{chunk-XQYAM47Y.js.map → chunk-TOHTP3BT.js.map} +1 -1
- package/dist/{chunk-IPVHC2DM.js → chunk-TVLE7GNH.js} +374 -7
- package/dist/chunk-TVLE7GNH.js.map +1 -0
- package/dist/{chunk-ISS73LG3.js → chunk-VPWQN7KV.js} +3 -3
- package/dist/{chunk-ISS73LG3.js.map → chunk-VPWQN7KV.js.map} +1 -1
- package/dist/{chunk-R6JFXZXN.js → chunk-VTPBYPDV.js} +47 -5
- package/dist/chunk-VTPBYPDV.js.map +1 -0
- package/dist/{chunk-GWRX2T3K.js → chunk-XF7QA3QT.js} +417 -155
- package/dist/chunk-XF7QA3QT.js.map +1 -0
- package/dist/executions.js +7 -6
- package/dist/history.js +4 -4
- package/dist/index.d.ts +71 -1
- package/dist/index.js +26 -23
- package/dist/index.js.map +1 -1
- package/dist/nodes.js +2 -2
- package/dist/observability-5ShR4Phm.d.ts +134 -0
- package/dist/observability.d.ts +2 -0
- package/dist/observability.js +8 -0
- package/dist/observability.js.map +1 -0
- package/dist/settings.js +5 -1
- package/dist/templates.js +6 -6
- package/dist/workflow-builder.js +7 -7
- package/dist/workflows-list.js +4 -4
- package/package.json +5 -1
- package/dist/ExecutionDetailPage-OSDL7NDT.js +0 -11
- package/dist/ExecutionsListPage-AATDFFIH.js +0 -10
- package/dist/chunk-5IAMVAGX.js.map +0 -1
- package/dist/chunk-EUZZLC3N.js.map +0 -1
- package/dist/chunk-GWRX2T3K.js.map +0 -1
- package/dist/chunk-IPVHC2DM.js.map +0 -1
- package/dist/chunk-PTGKDQ5K.js.map +0 -1
- package/dist/chunk-R6JFXZXN.js.map +0 -1
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
import { LOG_STREAM_DESTINATIONS, CREATE_LOG_STREAM_DESTINATION, UPDATE_LOG_STREAM_DESTINATION, DELETE_LOG_STREAM_DESTINATION, TEST_LOG_STREAM_DESTINATION, REPLAY_WORKFLOW_RUN, RETRY_WORKFLOW_RUNS, OBSERVABILITY_DASHBOARD_SUMMARY, OBSERVABILITY_FAILED_RUNS, OBSERVABILITY_DATA_SINKS, OBSERVABILITY_DATA_SINK_DATA } from './chunk-NK32XOQN.js';
|
|
2
|
+
import { throwIfResultError, describeOperationError } from './chunk-LMO5ASOE.js';
|
|
3
|
+
import { useTr } from './chunk-7YWBH2A5.js';
|
|
4
|
+
import { getFluidGridsClient } from './chunk-5BDQNSP3.js';
|
|
5
|
+
import { useCallback, useState, useMemo, useEffect } from 'react';
|
|
6
|
+
import { Icon } from '@iconify/react';
|
|
7
|
+
import { toast } from 'sonner';
|
|
8
|
+
import { Button } from '@burdenoff/fe-libs/button';
|
|
9
|
+
import { Card, CardHeader, CardContent, Label, Input } from '@burdenoff/fe-libs/ui';
|
|
10
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
function useAsyncRefresh(fetcher, initial) {
|
|
13
|
+
const [data, setData] = useState(initial);
|
|
14
|
+
const [loading, setLoading] = useState(true);
|
|
15
|
+
const [error, setError] = useState(null);
|
|
16
|
+
const refetch = useCallback(async () => {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
setError(null);
|
|
19
|
+
try {
|
|
20
|
+
const next = await fetcher();
|
|
21
|
+
setData(next);
|
|
22
|
+
return next;
|
|
23
|
+
} catch (cause) {
|
|
24
|
+
const nextError = new Error(describeOperationError(cause));
|
|
25
|
+
setError(nextError);
|
|
26
|
+
return null;
|
|
27
|
+
} finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, [fetcher]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
void refetch();
|
|
33
|
+
}, [refetch]);
|
|
34
|
+
return { data, loading, error, refetch };
|
|
35
|
+
}
|
|
36
|
+
function useLogStreamDestinations() {
|
|
37
|
+
const fetchDestinations = useCallback(async () => {
|
|
38
|
+
const result = throwIfResultError(
|
|
39
|
+
await getFluidGridsClient().query({
|
|
40
|
+
query: LOG_STREAM_DESTINATIONS,
|
|
41
|
+
fetchPolicy: "network-only"
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
return result.data?.logStreamDestinations ?? [];
|
|
45
|
+
}, []);
|
|
46
|
+
const state = useAsyncRefresh(fetchDestinations, []);
|
|
47
|
+
return { destinations: state.data ?? [], ...state, refetch: state.refetch };
|
|
48
|
+
}
|
|
49
|
+
function useLogStreamDestinationActions() {
|
|
50
|
+
const [loading, setLoading] = useState(false);
|
|
51
|
+
const [error, setError] = useState(null);
|
|
52
|
+
const run = useCallback(
|
|
53
|
+
async (operation) => {
|
|
54
|
+
setLoading(true);
|
|
55
|
+
setError(null);
|
|
56
|
+
try {
|
|
57
|
+
return await operation();
|
|
58
|
+
} catch (cause) {
|
|
59
|
+
const nextError = new Error(describeOperationError(cause));
|
|
60
|
+
setError(nextError);
|
|
61
|
+
return null;
|
|
62
|
+
} finally {
|
|
63
|
+
setLoading(false);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
[]
|
|
67
|
+
);
|
|
68
|
+
const create = useCallback(
|
|
69
|
+
(input) => run(async () => {
|
|
70
|
+
const result = throwIfResultError(
|
|
71
|
+
await getFluidGridsClient().mutate({
|
|
72
|
+
mutation: CREATE_LOG_STREAM_DESTINATION,
|
|
73
|
+
variables: { input }
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
return result.data?.createLogStreamDestination ?? null;
|
|
77
|
+
}),
|
|
78
|
+
[run]
|
|
79
|
+
);
|
|
80
|
+
const update = useCallback(
|
|
81
|
+
(id, input) => run(async () => {
|
|
82
|
+
const result = throwIfResultError(
|
|
83
|
+
await getFluidGridsClient().mutate({
|
|
84
|
+
mutation: UPDATE_LOG_STREAM_DESTINATION,
|
|
85
|
+
variables: { id, input }
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
return result.data?.updateLogStreamDestination ?? null;
|
|
89
|
+
}),
|
|
90
|
+
[run]
|
|
91
|
+
);
|
|
92
|
+
const remove = useCallback(
|
|
93
|
+
(id) => run(async () => {
|
|
94
|
+
const result = throwIfResultError(
|
|
95
|
+
await getFluidGridsClient().mutate({
|
|
96
|
+
mutation: DELETE_LOG_STREAM_DESTINATION,
|
|
97
|
+
variables: { id }
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
return result.data?.deleteLogStreamDestination ?? null;
|
|
101
|
+
}),
|
|
102
|
+
[run]
|
|
103
|
+
);
|
|
104
|
+
const test = useCallback(
|
|
105
|
+
(id) => run(async () => {
|
|
106
|
+
const result = throwIfResultError(
|
|
107
|
+
await getFluidGridsClient().mutate({
|
|
108
|
+
mutation: TEST_LOG_STREAM_DESTINATION,
|
|
109
|
+
variables: { id }
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
return result.data?.testLogStreamDestination ?? null;
|
|
113
|
+
}),
|
|
114
|
+
[run]
|
|
115
|
+
);
|
|
116
|
+
return { create, update, remove, test, loading, error };
|
|
117
|
+
}
|
|
118
|
+
function useRunReplayActions() {
|
|
119
|
+
const [loading, setLoading] = useState(false);
|
|
120
|
+
const [error, setError] = useState(null);
|
|
121
|
+
const replay = useCallback(async (runId) => {
|
|
122
|
+
setLoading(true);
|
|
123
|
+
setError(null);
|
|
124
|
+
try {
|
|
125
|
+
const result = throwIfResultError(
|
|
126
|
+
await getFluidGridsClient().mutate({
|
|
127
|
+
mutation: REPLAY_WORKFLOW_RUN,
|
|
128
|
+
variables: { runId }
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
return result.data?.replayWorkflowRun ?? null;
|
|
132
|
+
} catch (cause) {
|
|
133
|
+
const nextError = new Error(describeOperationError(cause));
|
|
134
|
+
setError(nextError);
|
|
135
|
+
return null;
|
|
136
|
+
} finally {
|
|
137
|
+
setLoading(false);
|
|
138
|
+
}
|
|
139
|
+
}, []);
|
|
140
|
+
const retryMany = useCallback(async (runIds) => {
|
|
141
|
+
setLoading(true);
|
|
142
|
+
setError(null);
|
|
143
|
+
try {
|
|
144
|
+
const result = throwIfResultError(
|
|
145
|
+
await getFluidGridsClient().mutate({
|
|
146
|
+
mutation: RETRY_WORKFLOW_RUNS,
|
|
147
|
+
variables: { runIds }
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
return result.data?.retryWorkflowRuns ?? [];
|
|
151
|
+
} catch (cause) {
|
|
152
|
+
const nextError = new Error(describeOperationError(cause));
|
|
153
|
+
setError(nextError);
|
|
154
|
+
return [];
|
|
155
|
+
} finally {
|
|
156
|
+
setLoading(false);
|
|
157
|
+
}
|
|
158
|
+
}, []);
|
|
159
|
+
return { replay, retryMany, loading, error };
|
|
160
|
+
}
|
|
161
|
+
function useInsightsData() {
|
|
162
|
+
const fetchInsights = useCallback(async () => {
|
|
163
|
+
const client = getFluidGridsClient();
|
|
164
|
+
const [summaryResult, failedResult] = await Promise.all([
|
|
165
|
+
client.query({
|
|
166
|
+
query: OBSERVABILITY_DASHBOARD_SUMMARY,
|
|
167
|
+
fetchPolicy: "network-only"
|
|
168
|
+
}),
|
|
169
|
+
client.query({
|
|
170
|
+
query: OBSERVABILITY_FAILED_RUNS,
|
|
171
|
+
variables: {
|
|
172
|
+
input: {
|
|
173
|
+
status: "FAILED",
|
|
174
|
+
limit: 100,
|
|
175
|
+
offset: 0
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
fetchPolicy: "network-only"
|
|
179
|
+
})
|
|
180
|
+
]);
|
|
181
|
+
throwIfResultError(summaryResult);
|
|
182
|
+
throwIfResultError(failedResult);
|
|
183
|
+
return {
|
|
184
|
+
summary: summaryResult.data?.dashboardSummary ?? null,
|
|
185
|
+
failedRuns: failedResult.data?.workflowRuns.items ?? []
|
|
186
|
+
};
|
|
187
|
+
}, []);
|
|
188
|
+
const state = useAsyncRefresh(fetchInsights, null);
|
|
189
|
+
return {
|
|
190
|
+
summary: state.data?.summary ?? null,
|
|
191
|
+
failedRuns: state.data?.failedRuns ?? [],
|
|
192
|
+
loading: state.loading,
|
|
193
|
+
error: state.error,
|
|
194
|
+
refetch: state.refetch
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function useDataSinks(search) {
|
|
198
|
+
const fetchSinks = useCallback(async () => {
|
|
199
|
+
const result = throwIfResultError(
|
|
200
|
+
await getFluidGridsClient().query({
|
|
201
|
+
query: OBSERVABILITY_DATA_SINKS,
|
|
202
|
+
variables: { first: 50, isActive: true, search: search || void 0 },
|
|
203
|
+
fetchPolicy: "network-only"
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
return result.data?.listDataSinks ?? null;
|
|
207
|
+
}, [search]);
|
|
208
|
+
const state = useAsyncRefresh(fetchSinks, null);
|
|
209
|
+
return {
|
|
210
|
+
sinks: state.data?.edges.map((edge) => edge.node) ?? [],
|
|
211
|
+
totalCount: state.data?.totalCount ?? 0,
|
|
212
|
+
hasNextPage: state.data?.pageInfo.hasNextPage ?? false,
|
|
213
|
+
...state
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function useDataSinkData(sink) {
|
|
217
|
+
const fetchData = useCallback(async () => {
|
|
218
|
+
if (!sink) return null;
|
|
219
|
+
const result = throwIfResultError(
|
|
220
|
+
await getFluidGridsClient().query({
|
|
221
|
+
query: OBSERVABILITY_DATA_SINK_DATA,
|
|
222
|
+
variables: { id: sink.id, limit: 100, offset: 0 },
|
|
223
|
+
fetchPolicy: "network-only"
|
|
224
|
+
})
|
|
225
|
+
);
|
|
226
|
+
return result.data?.getDataSinkData ?? null;
|
|
227
|
+
}, [sink]);
|
|
228
|
+
const state = useAsyncRefresh(fetchData, null);
|
|
229
|
+
return { sinkData: state.data, ...state };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/modules/observability/types.ts
|
|
233
|
+
var LOG_STREAM_EVENT_TYPES = [
|
|
234
|
+
"LOG_ERROR",
|
|
235
|
+
"LOG_WARN",
|
|
236
|
+
"NODE_FAILED",
|
|
237
|
+
"NODE_RETRIED",
|
|
238
|
+
"RUN_CANCELLED",
|
|
239
|
+
"RUN_COMPLETED",
|
|
240
|
+
"RUN_FAILED",
|
|
241
|
+
"RUN_STARTED"
|
|
242
|
+
];
|
|
243
|
+
var DEFAULT_EVENT_FILTERS = [
|
|
244
|
+
"RUN_FAILED",
|
|
245
|
+
"NODE_FAILED",
|
|
246
|
+
"LOG_ERROR"
|
|
247
|
+
];
|
|
248
|
+
var PROVIDERS = ["WEBHOOK", "SYSLOG", "SENTRY"];
|
|
249
|
+
function emptyForm() {
|
|
250
|
+
return {
|
|
251
|
+
name: "",
|
|
252
|
+
provider: "WEBHOOK",
|
|
253
|
+
endpoint: "",
|
|
254
|
+
eventFilters: DEFAULT_EVENT_FILTERS,
|
|
255
|
+
isEnabled: true,
|
|
256
|
+
secret: "",
|
|
257
|
+
configText: "{}"
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function formFromDestination(destination) {
|
|
261
|
+
return {
|
|
262
|
+
name: destination.name,
|
|
263
|
+
provider: destination.provider,
|
|
264
|
+
endpoint: destination.endpoint,
|
|
265
|
+
eventFilters: destination.eventFilters,
|
|
266
|
+
isEnabled: destination.isEnabled,
|
|
267
|
+
secret: "",
|
|
268
|
+
configText: JSON.stringify(destination.config ?? {}, null, 2)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function eventLabel(event) {
|
|
272
|
+
return event.toLowerCase().split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
273
|
+
}
|
|
274
|
+
function endpointPlaceholder(provider) {
|
|
275
|
+
switch (provider) {
|
|
276
|
+
case "SYSLOG":
|
|
277
|
+
return "logs.example.com:514";
|
|
278
|
+
case "SENTRY":
|
|
279
|
+
return "https://public@sentry.example/1";
|
|
280
|
+
case "WEBHOOK":
|
|
281
|
+
return "https://hooks.example.com/workflows";
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function parseConfig(configText) {
|
|
285
|
+
try {
|
|
286
|
+
const parsed = JSON.parse(configText || "{}");
|
|
287
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
return parsed;
|
|
291
|
+
} catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function formToInput(form) {
|
|
296
|
+
const config = parseConfig(form.configText);
|
|
297
|
+
if (!config || !form.name.trim() || !form.endpoint.trim()) return null;
|
|
298
|
+
return {
|
|
299
|
+
name: form.name.trim(),
|
|
300
|
+
provider: form.provider,
|
|
301
|
+
endpoint: form.endpoint.trim(),
|
|
302
|
+
eventFilters: form.eventFilters,
|
|
303
|
+
isEnabled: form.isEnabled,
|
|
304
|
+
config,
|
|
305
|
+
...form.secret ? { secret: form.secret } : {}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function LogStreamingTab() {
|
|
309
|
+
const tr = useTr();
|
|
310
|
+
const { destinations, loading, error, refetch } = useLogStreamDestinations();
|
|
311
|
+
const actions = useLogStreamDestinationActions();
|
|
312
|
+
const [form, setForm] = useState(emptyForm);
|
|
313
|
+
const [editingId, setEditingId] = useState(null);
|
|
314
|
+
const [showForm, setShowForm] = useState(false);
|
|
315
|
+
const editingDestination = useMemo(
|
|
316
|
+
() => destinations.find((destination) => destination.id === editingId),
|
|
317
|
+
[destinations, editingId]
|
|
318
|
+
);
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
if (editingDestination) setForm(formFromDestination(editingDestination));
|
|
321
|
+
}, [editingDestination]);
|
|
322
|
+
const resetForm = useCallback(() => {
|
|
323
|
+
setForm(emptyForm());
|
|
324
|
+
setEditingId(null);
|
|
325
|
+
setShowForm(false);
|
|
326
|
+
}, []);
|
|
327
|
+
const save = useCallback(async () => {
|
|
328
|
+
const input = formToInput(form);
|
|
329
|
+
if (!input) {
|
|
330
|
+
toast.error(
|
|
331
|
+
tr(
|
|
332
|
+
"fluidgrids.settings.logStreaming.invalidForm",
|
|
333
|
+
"Enter a name, endpoint, and valid JSON configuration."
|
|
334
|
+
)
|
|
335
|
+
);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const result = editingId ? await actions.update(editingId, input) : await actions.create(input);
|
|
339
|
+
if (!result?.success) {
|
|
340
|
+
toast.error(
|
|
341
|
+
result?.message || tr(
|
|
342
|
+
"fluidgrids.settings.logStreaming.saveFailed",
|
|
343
|
+
"Could not save log streaming destination."
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
toast.success(
|
|
349
|
+
tr(
|
|
350
|
+
"fluidgrids.settings.logStreaming.saved",
|
|
351
|
+
"Log streaming destination saved."
|
|
352
|
+
)
|
|
353
|
+
);
|
|
354
|
+
resetForm();
|
|
355
|
+
await refetch();
|
|
356
|
+
}, [actions, editingId, form, refetch, resetForm, tr]);
|
|
357
|
+
const remove = useCallback(
|
|
358
|
+
async (destination) => {
|
|
359
|
+
if (!window.confirm(`Delete \u201C${destination.name}\u201D?`)) return;
|
|
360
|
+
const result = await actions.remove(destination.id);
|
|
361
|
+
if (!result?.success) {
|
|
362
|
+
toast.error(
|
|
363
|
+
result?.message || tr(
|
|
364
|
+
"fluidgrids.settings.logStreaming.deleteFailed",
|
|
365
|
+
"Could not delete destination."
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
toast.success(
|
|
371
|
+
tr(
|
|
372
|
+
"fluidgrids.settings.logStreaming.deleted",
|
|
373
|
+
"Log streaming destination deleted."
|
|
374
|
+
)
|
|
375
|
+
);
|
|
376
|
+
if (editingId === destination.id) resetForm();
|
|
377
|
+
await refetch();
|
|
378
|
+
},
|
|
379
|
+
[actions, editingId, refetch, resetForm, tr]
|
|
380
|
+
);
|
|
381
|
+
const sendTest = useCallback(
|
|
382
|
+
async (destination) => {
|
|
383
|
+
const result = await actions.test(destination.id);
|
|
384
|
+
if (!result) return;
|
|
385
|
+
if (result.success) {
|
|
386
|
+
toast.success(
|
|
387
|
+
tr(
|
|
388
|
+
"fluidgrids.settings.logStreaming.testSucceeded",
|
|
389
|
+
"Test event delivered."
|
|
390
|
+
)
|
|
391
|
+
);
|
|
392
|
+
} else {
|
|
393
|
+
toast.error(
|
|
394
|
+
result.message || tr(
|
|
395
|
+
"fluidgrids.settings.logStreaming.testFailed",
|
|
396
|
+
"Test event could not be delivered."
|
|
397
|
+
)
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
await refetch();
|
|
401
|
+
},
|
|
402
|
+
[actions, refetch, tr]
|
|
403
|
+
);
|
|
404
|
+
const toggleEvent = (event) => {
|
|
405
|
+
setForm((current) => ({
|
|
406
|
+
...current,
|
|
407
|
+
eventFilters: current.eventFilters.includes(event) ? current.eventFilters.filter((item) => item !== event) : [...current.eventFilters, event]
|
|
408
|
+
}));
|
|
409
|
+
};
|
|
410
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
411
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
412
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
413
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-text-primary", children: tr("fluidgrids.settings.logStreaming.title", "Log streaming") }),
|
|
414
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 max-w-2xl text-sm text-text-secondary", children: tr(
|
|
415
|
+
"fluidgrids.settings.logStreaming.description",
|
|
416
|
+
"Send workflow run and node events to workspace-managed observability destinations. Secrets are write-only and never returned."
|
|
417
|
+
) })
|
|
418
|
+
] }),
|
|
419
|
+
/* @__PURE__ */ jsxs(
|
|
420
|
+
Button,
|
|
421
|
+
{
|
|
422
|
+
onClick: () => {
|
|
423
|
+
setForm(emptyForm());
|
|
424
|
+
setEditingId(null);
|
|
425
|
+
setShowForm(true);
|
|
426
|
+
},
|
|
427
|
+
disabled: actions.loading,
|
|
428
|
+
children: [
|
|
429
|
+
/* @__PURE__ */ jsx(Icon, { icon: "mdi:plus", className: "mr-1", width: 16 }),
|
|
430
|
+
tr("fluidgrids.settings.logStreaming.add", "Add destination")
|
|
431
|
+
]
|
|
432
|
+
}
|
|
433
|
+
)
|
|
434
|
+
] }),
|
|
435
|
+
error && /* @__PURE__ */ jsxs(
|
|
436
|
+
"div",
|
|
437
|
+
{
|
|
438
|
+
role: "alert",
|
|
439
|
+
className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-4 text-sm text-status-error-text",
|
|
440
|
+
children: [
|
|
441
|
+
error.message,
|
|
442
|
+
/* @__PURE__ */ jsx(
|
|
443
|
+
Button,
|
|
444
|
+
{
|
|
445
|
+
variant: "outline",
|
|
446
|
+
size: "sm",
|
|
447
|
+
className: "ml-3",
|
|
448
|
+
onClick: () => void refetch(),
|
|
449
|
+
children: tr("fluidgrids.settings.logStreaming.retry", "Retry")
|
|
450
|
+
}
|
|
451
|
+
)
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
),
|
|
455
|
+
showForm && /* @__PURE__ */ jsxs(Card, { className: "border-border-secondary bg-background-secondary", children: [
|
|
456
|
+
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
457
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium text-text-primary", children: editingId ? tr(
|
|
458
|
+
"fluidgrids.settings.logStreaming.edit",
|
|
459
|
+
"Edit destination"
|
|
460
|
+
) : tr(
|
|
461
|
+
"fluidgrids.settings.logStreaming.new",
|
|
462
|
+
"New destination"
|
|
463
|
+
) }),
|
|
464
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: resetForm, children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", width: 18 }) })
|
|
465
|
+
] }) }),
|
|
466
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-5", children: [
|
|
467
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
468
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
469
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "log-stream-name", children: tr("fluidgrids.settings.logStreaming.name", "Name") }),
|
|
470
|
+
/* @__PURE__ */ jsx(
|
|
471
|
+
Input,
|
|
472
|
+
{
|
|
473
|
+
id: "log-stream-name",
|
|
474
|
+
value: form.name,
|
|
475
|
+
onChange: (event) => setForm((current) => ({
|
|
476
|
+
...current,
|
|
477
|
+
name: event.target.value
|
|
478
|
+
})),
|
|
479
|
+
placeholder: "Production error stream"
|
|
480
|
+
}
|
|
481
|
+
)
|
|
482
|
+
] }),
|
|
483
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
484
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "log-stream-provider", children: tr("fluidgrids.settings.logStreaming.provider", "Provider") }),
|
|
485
|
+
/* @__PURE__ */ jsx(
|
|
486
|
+
"select",
|
|
487
|
+
{
|
|
488
|
+
id: "log-stream-provider",
|
|
489
|
+
value: form.provider,
|
|
490
|
+
onChange: (event) => setForm((current) => ({
|
|
491
|
+
...current,
|
|
492
|
+
provider: event.target.value,
|
|
493
|
+
endpoint: ""
|
|
494
|
+
})),
|
|
495
|
+
className: "w-full rounded-md border border-border-secondary bg-background-primary px-3 py-2 text-sm text-text-primary",
|
|
496
|
+
children: PROVIDERS.map((provider) => /* @__PURE__ */ jsx("option", { value: provider, children: provider }, provider))
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
] })
|
|
500
|
+
] }),
|
|
501
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
502
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "log-stream-endpoint", children: tr("fluidgrids.settings.logStreaming.endpoint", "Endpoint") }),
|
|
503
|
+
/* @__PURE__ */ jsx(
|
|
504
|
+
Input,
|
|
505
|
+
{
|
|
506
|
+
id: "log-stream-endpoint",
|
|
507
|
+
value: form.endpoint,
|
|
508
|
+
onChange: (event) => setForm((current) => ({
|
|
509
|
+
...current,
|
|
510
|
+
endpoint: event.target.value
|
|
511
|
+
})),
|
|
512
|
+
placeholder: endpointPlaceholder(form.provider),
|
|
513
|
+
type: form.provider === "WEBHOOK" || form.provider === "SENTRY" ? "url" : "text"
|
|
514
|
+
}
|
|
515
|
+
)
|
|
516
|
+
] }),
|
|
517
|
+
form.provider === "WEBHOOK" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
518
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "log-stream-secret", children: tr(
|
|
519
|
+
"fluidgrids.settings.logStreaming.secret",
|
|
520
|
+
"Signing secret"
|
|
521
|
+
) }),
|
|
522
|
+
/* @__PURE__ */ jsx(
|
|
523
|
+
Input,
|
|
524
|
+
{
|
|
525
|
+
id: "log-stream-secret",
|
|
526
|
+
value: form.secret,
|
|
527
|
+
onChange: (event) => setForm((current) => ({
|
|
528
|
+
...current,
|
|
529
|
+
secret: event.target.value
|
|
530
|
+
})),
|
|
531
|
+
placeholder: editingId ? "Leave blank to keep the current secret" : "Enter a signing secret",
|
|
532
|
+
type: "password",
|
|
533
|
+
autoComplete: "new-password"
|
|
534
|
+
}
|
|
535
|
+
)
|
|
536
|
+
] }),
|
|
537
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
538
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "log-stream-config", children: tr(
|
|
539
|
+
"fluidgrids.settings.logStreaming.config",
|
|
540
|
+
"Provider configuration (JSON)"
|
|
541
|
+
) }),
|
|
542
|
+
/* @__PURE__ */ jsx(
|
|
543
|
+
"textarea",
|
|
544
|
+
{
|
|
545
|
+
id: "log-stream-config",
|
|
546
|
+
value: form.configText,
|
|
547
|
+
onChange: (event) => setForm((current) => ({
|
|
548
|
+
...current,
|
|
549
|
+
configText: event.target.value
|
|
550
|
+
})),
|
|
551
|
+
className: "min-h-24 w-full rounded-md border border-border-secondary bg-background-primary px-3 py-2 font-mono text-xs text-text-primary",
|
|
552
|
+
spellCheck: false
|
|
553
|
+
}
|
|
554
|
+
)
|
|
555
|
+
] }),
|
|
556
|
+
/* @__PURE__ */ jsxs("fieldset", { className: "space-y-2", children: [
|
|
557
|
+
/* @__PURE__ */ jsx("legend", { className: "text-sm font-medium text-text-primary", children: tr(
|
|
558
|
+
"fluidgrids.settings.logStreaming.events",
|
|
559
|
+
"Events to stream"
|
|
560
|
+
) }),
|
|
561
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-4", children: LOG_STREAM_EVENT_TYPES.map((event) => /* @__PURE__ */ jsxs(
|
|
562
|
+
"label",
|
|
563
|
+
{
|
|
564
|
+
className: "flex items-center gap-2 text-sm text-text-secondary",
|
|
565
|
+
children: [
|
|
566
|
+
/* @__PURE__ */ jsx(
|
|
567
|
+
"input",
|
|
568
|
+
{
|
|
569
|
+
type: "checkbox",
|
|
570
|
+
checked: form.eventFilters.includes(event),
|
|
571
|
+
onChange: () => toggleEvent(event),
|
|
572
|
+
className: "size-4 rounded border-border-secondary accent-action-primary-bg"
|
|
573
|
+
}
|
|
574
|
+
),
|
|
575
|
+
eventLabel(event)
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
event
|
|
579
|
+
)) })
|
|
580
|
+
] }),
|
|
581
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm text-text-secondary", children: [
|
|
582
|
+
/* @__PURE__ */ jsx(
|
|
583
|
+
"input",
|
|
584
|
+
{
|
|
585
|
+
type: "checkbox",
|
|
586
|
+
checked: form.isEnabled,
|
|
587
|
+
onChange: (event) => setForm((current) => ({
|
|
588
|
+
...current,
|
|
589
|
+
isEnabled: event.target.checked
|
|
590
|
+
})),
|
|
591
|
+
className: "size-4 rounded border-border-secondary accent-action-primary-bg"
|
|
592
|
+
}
|
|
593
|
+
),
|
|
594
|
+
tr(
|
|
595
|
+
"fluidgrids.settings.logStreaming.enabled",
|
|
596
|
+
"Destination enabled"
|
|
597
|
+
)
|
|
598
|
+
] }),
|
|
599
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
600
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: resetForm, children: tr("fluidgrids.settings.logStreaming.cancel", "Cancel") }),
|
|
601
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => void save(), disabled: actions.loading, children: actions.loading ? tr("fluidgrids.settings.logStreaming.saving", "Saving\u2026") : tr(
|
|
602
|
+
"fluidgrids.settings.logStreaming.save",
|
|
603
|
+
"Save destination"
|
|
604
|
+
) })
|
|
605
|
+
] })
|
|
606
|
+
] })
|
|
607
|
+
] }),
|
|
608
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
609
|
+
loading && destinations.length === 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border-secondary bg-background-secondary p-6 text-sm text-text-secondary", children: tr(
|
|
610
|
+
"fluidgrids.settings.logStreaming.loading",
|
|
611
|
+
"Loading destinations\u2026"
|
|
612
|
+
) }),
|
|
613
|
+
!loading && destinations.length === 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-border-secondary bg-background-secondary p-8 text-center", children: [
|
|
614
|
+
/* @__PURE__ */ jsx(
|
|
615
|
+
Icon,
|
|
616
|
+
{
|
|
617
|
+
icon: "mdi:transit-connection-variant",
|
|
618
|
+
className: "mx-auto mb-3 text-text-secondary",
|
|
619
|
+
width: 32
|
|
620
|
+
}
|
|
621
|
+
),
|
|
622
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-text-primary", children: tr(
|
|
623
|
+
"fluidgrids.settings.logStreaming.emptyTitle",
|
|
624
|
+
"No log destinations yet"
|
|
625
|
+
) }),
|
|
626
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-text-secondary", children: tr(
|
|
627
|
+
"fluidgrids.settings.logStreaming.emptyDescription",
|
|
628
|
+
"Add a webhook, syslog target, or Sentry DSN to start streaming events."
|
|
629
|
+
) })
|
|
630
|
+
] }),
|
|
631
|
+
destinations.map((destination) => /* @__PURE__ */ jsx(
|
|
632
|
+
Card,
|
|
633
|
+
{
|
|
634
|
+
className: "border-border-secondary bg-background-secondary",
|
|
635
|
+
children: /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
636
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
637
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
638
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium text-text-primary", children: destination.name }),
|
|
639
|
+
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary", children: destination.provider }),
|
|
640
|
+
/* @__PURE__ */ jsx(
|
|
641
|
+
"span",
|
|
642
|
+
{
|
|
643
|
+
className: destination.isEnabled ? "text-xs text-status-success-text" : "text-xs text-text-secondary",
|
|
644
|
+
children: destination.isEnabled ? tr(
|
|
645
|
+
"fluidgrids.settings.logStreaming.enabledBadge",
|
|
646
|
+
"Enabled"
|
|
647
|
+
) : tr(
|
|
648
|
+
"fluidgrids.settings.logStreaming.disabledBadge",
|
|
649
|
+
"Disabled"
|
|
650
|
+
)
|
|
651
|
+
}
|
|
652
|
+
)
|
|
653
|
+
] }),
|
|
654
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 truncate text-sm text-text-secondary", children: destination.endpoint }),
|
|
655
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-text-secondary", children: [
|
|
656
|
+
destination.eventFilters.length > 0 ? destination.eventFilters.map(eventLabel).join(", ") : tr(
|
|
657
|
+
"fluidgrids.settings.logStreaming.allEvents",
|
|
658
|
+
"All events"
|
|
659
|
+
),
|
|
660
|
+
destination.hasSecret && " \xB7 Secret configured"
|
|
661
|
+
] }),
|
|
662
|
+
destination.lastDispatchError && /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-status-error-text", children: destination.lastDispatchError })
|
|
663
|
+
] }),
|
|
664
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-wrap gap-2", children: [
|
|
665
|
+
/* @__PURE__ */ jsxs(
|
|
666
|
+
Button,
|
|
667
|
+
{
|
|
668
|
+
variant: "outline",
|
|
669
|
+
size: "sm",
|
|
670
|
+
onClick: () => void sendTest(destination),
|
|
671
|
+
disabled: actions.loading,
|
|
672
|
+
children: [
|
|
673
|
+
/* @__PURE__ */ jsx(
|
|
674
|
+
Icon,
|
|
675
|
+
{
|
|
676
|
+
icon: "mdi:send-check-outline",
|
|
677
|
+
className: "mr-1",
|
|
678
|
+
width: 15
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
tr("fluidgrids.settings.logStreaming.test", "Send test")
|
|
682
|
+
]
|
|
683
|
+
}
|
|
684
|
+
),
|
|
685
|
+
/* @__PURE__ */ jsx(
|
|
686
|
+
Button,
|
|
687
|
+
{
|
|
688
|
+
variant: "outline",
|
|
689
|
+
size: "sm",
|
|
690
|
+
onClick: () => {
|
|
691
|
+
setEditingId(destination.id);
|
|
692
|
+
setShowForm(true);
|
|
693
|
+
},
|
|
694
|
+
disabled: actions.loading,
|
|
695
|
+
children: tr("fluidgrids.settings.logStreaming.editButton", "Edit")
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
/* @__PURE__ */ jsxs(
|
|
699
|
+
Button,
|
|
700
|
+
{
|
|
701
|
+
variant: "ghost",
|
|
702
|
+
size: "sm",
|
|
703
|
+
onClick: () => void remove(destination),
|
|
704
|
+
disabled: actions.loading,
|
|
705
|
+
children: [
|
|
706
|
+
/* @__PURE__ */ jsx(
|
|
707
|
+
Icon,
|
|
708
|
+
{
|
|
709
|
+
icon: "mdi:trash-can-outline",
|
|
710
|
+
className: "text-status-error-text",
|
|
711
|
+
width: 17
|
|
712
|
+
}
|
|
713
|
+
),
|
|
714
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: tr("fluidgrids.settings.logStreaming.delete", "Delete") })
|
|
715
|
+
]
|
|
716
|
+
}
|
|
717
|
+
)
|
|
718
|
+
] })
|
|
719
|
+
] })
|
|
720
|
+
},
|
|
721
|
+
destination.id
|
|
722
|
+
))
|
|
723
|
+
] })
|
|
724
|
+
] });
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export { LogStreamingTab, useDataSinkData, useDataSinks, useInsightsData, useLogStreamDestinationActions, useLogStreamDestinations, useRunReplayActions };
|
|
728
|
+
//# sourceMappingURL=chunk-5A7GP6O7.js.map
|
|
729
|
+
//# sourceMappingURL=chunk-5A7GP6O7.js.map
|