@burdenoff/fluidgrids-fe-sdk 2026.1114.5 → 2026.1114.7
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/{AiStudioPage-C2SBRqab.js → AiStudioPage-DLl4ld32.js} +2 -2
- package/dist/{ExecutionDetailPage-heD4wBjg.js → ExecutionDetailPage-DxeySgR3.js} +110 -13
- package/dist/{ExecutionsListPage-Ky3TAL9U.js → ExecutionsListPage-CMrOaFKQ.js} +2 -2
- package/dist/FileDownloadUrlDocument-CVOYKcL5.js +92 -0
- package/dist/NodeUsageStatusDocument-B-XguSjm.js +531 -0
- package/dist/{OpenTemplateAsCodeButton-pepQUqje.js → OpenTemplateAsCodeButton-Cjnagq9H.js} +2 -2
- package/dist/{PaidTemplateConfirm-BJCcJh5t.js → PaidTemplateConfirm-IWOHVR6s.js} +1 -1
- package/dist/{SettingsPage-BSucNHrq.js → SettingsPage-DwA2ZjyH.js} +4 -4
- package/dist/{TaskQueuesPage-WMJz9imi.js → TaskQueuesPage-BuWQwT5I.js} +2 -2
- package/dist/{TemplateCard-Cx_eZr9q.js → TemplateCard-9Beuqm5_.js} +19 -3
- package/dist/{TemplateConfigurationModal-D2i7ZXOM.js → TemplateConfigurationModal-B_ME8M-1.js} +1 -1
- package/dist/{TemplatePreview-DwdGa8bH.js → TemplatePreview-Bi6LSeH8.js} +5 -5
- package/dist/{TemplatesPage-DF5PK7CB.js → TemplatesPage-D9fOKAn4.js} +355 -13
- package/dist/{WorkflowBuilder-CjsO7i-D.js → WorkflowBuilder-Bzx-e5lX.js} +2 -2
- package/dist/{WorkflowBuilder-DkzzbrNn.js → WorkflowBuilder-CdcGE0Mf.js} +3 -3
- package/dist/{WorkflowsList-4VADoiz_.js → WorkflowsList-CBqxxI44.js} +3 -4
- package/dist/{api-DKfMt0IX.js → api-CEzqoN5H.js} +1 -1
- package/dist/{api-CEnNq15C.js → api-o5UUDbr8.js} +1 -1
- package/dist/executions.js +2 -2
- package/dist/{flow-builder-CIV6u8y-.js → flow-builder-CbF9P7cI.js} +9 -24
- package/dist/{index-BY0V255h.d.ts → index-D10JzNP1.d.ts} +4 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -27
- package/dist/{node-detail-view-DkajTGfb.js → node-detail-view-CP6sq02c.js} +7 -217
- package/dist/{node-editor-tab-body-ChLrBfKp.js → node-editor-tab-body-B6kxLf6Q.js} +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/{popover-CCJlf41J.js → popover-9gY3-2dY.js} +2 -2
- package/dist/{quick-config-panel-Bq_uF9XF.js → quick-config-panel-TGCW64qe.js} +2 -2
- package/dist/{schedule-panel-7TtPt1t_.js → schedule-panel-zrFYGtkx.js} +4 -4
- package/dist/settings.js +1 -1
- package/dist/{shared-C0LCTtyh.js → shared-mbyvDPde.js} +2 -24
- package/dist/{sidebar-node-editor-n-7ux5IN.js → sidebar-node-editor-BPg2NKzJ.js} +2 -2
- package/dist/{template-code-B3cMigJS.js → template-code-B7x-XMAm.js} +9 -2
- package/dist/templates.js +2 -2
- package/dist/typed-calls-BqokR321.js +26 -0
- package/dist/{WorkflowEditLeaseStatusDocument-Dp62med3.js → use-workflow-code-editor-CBOkjntt.js} +216 -90
- package/dist/{useAgentDefinitions-Daa3fGVg.js → useAgentDefinitions-9pmnEpb8.js} +1 -1
- package/dist/useConnections-CmnwGk09.js +439 -0
- package/dist/{useWorkflowCodeExport-lRmbjY49.js → useWorkflowCodeExport-ChAzmhi6.js} +78 -114
- package/dist/workflow-builder.js +2 -2
- package/dist/workflow-description-ReGwCZXS.js +123 -0
- package/dist/workflow-pages.d.ts +1 -1
- package/dist/workflow-pages.js +9 -9
- package/dist/{workflow-code-transfer-BsLPUrKP.js → workflow-transfer-CktP7o1c.js} +103 -1
- package/dist/workflows-list.js +1 -1
- package/package.json +1 -1
- package/dist/QuotaExhaustedDialog-YjKgRTmu.js +0 -55
- package/dist/useConnections-BlB0gbOB.js +0 -931
- package/dist/workflow-transfer-CQnQC-ke.js +0 -104
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { n as getFluidGridsClient } from "./client-Ctl4jmY3.js";
|
|
3
|
+
import { o as throwIfResultError } from "./errors-xPZ-IbQd.js";
|
|
4
|
+
import { useCallback, useEffect, useState } from "react";
|
|
5
|
+
import { gql } from "@apollo/client";
|
|
6
|
+
|
|
7
|
+
// src/modules/connections/hooks/useConnections.ts
|
|
8
|
+
/**
|
|
9
|
+
* Custom hooks for fetching connections from the integrations service.
|
|
10
|
+
*
|
|
11
|
+
* These hooks query the wspace-integrations-svc via the federated GraphQL gateway.
|
|
12
|
+
* Connections replace the legacy credentials system for third-party authentication.
|
|
13
|
+
*/
|
|
14
|
+
const PROVIDER_FIELDS = gql`
|
|
15
|
+
fragment ProviderFields on IntegrationProvider {
|
|
16
|
+
id
|
|
17
|
+
key
|
|
18
|
+
name
|
|
19
|
+
description
|
|
20
|
+
category
|
|
21
|
+
authType
|
|
22
|
+
icon
|
|
23
|
+
color
|
|
24
|
+
website
|
|
25
|
+
docsUrl
|
|
26
|
+
isBuiltIn
|
|
27
|
+
isEnabled
|
|
28
|
+
availableScopes
|
|
29
|
+
# How this provider can be authenticated, as data. The builder renders the
|
|
30
|
+
# form from this rather than from a per-provider React component, so a
|
|
31
|
+
# provider or a new method added by an administrator shows up here with no
|
|
32
|
+
# frontend change.
|
|
33
|
+
authMethods {
|
|
34
|
+
key
|
|
35
|
+
displayName
|
|
36
|
+
description
|
|
37
|
+
flow
|
|
38
|
+
authType
|
|
39
|
+
configSchema
|
|
40
|
+
availableScopes
|
|
41
|
+
defaultScopes
|
|
42
|
+
isConfigured
|
|
43
|
+
isEnabled
|
|
44
|
+
displayOrder
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
const CONNECTION_FIELDS = gql`
|
|
49
|
+
${PROVIDER_FIELDS}
|
|
50
|
+
fragment ConnectionFields on IntegrationConnection {
|
|
51
|
+
id
|
|
52
|
+
name
|
|
53
|
+
description
|
|
54
|
+
providerId
|
|
55
|
+
provider {
|
|
56
|
+
...ProviderFields
|
|
57
|
+
}
|
|
58
|
+
status
|
|
59
|
+
lastHealthCheck
|
|
60
|
+
lastUsedAt
|
|
61
|
+
errorMessage
|
|
62
|
+
externalAccountId
|
|
63
|
+
externalAccountEmail
|
|
64
|
+
externalAccountName
|
|
65
|
+
grantedScopes
|
|
66
|
+
createdBy
|
|
67
|
+
createdAt
|
|
68
|
+
updatedAt
|
|
69
|
+
visibility
|
|
70
|
+
myAccess
|
|
71
|
+
canUse
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
const GET_CONNECTIONS = gql`
|
|
75
|
+
${CONNECTION_FIELDS}
|
|
76
|
+
query GetConnections(
|
|
77
|
+
$filter: ConnectionFilterInput
|
|
78
|
+
$pagination: IntegrationsPaginationInput
|
|
79
|
+
) {
|
|
80
|
+
getConnections(filter: $filter, pagination: $pagination) {
|
|
81
|
+
items {
|
|
82
|
+
...ConnectionFields
|
|
83
|
+
}
|
|
84
|
+
total
|
|
85
|
+
hasMore
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
/** Ids and names only: what a code export needs to name connections. */
|
|
90
|
+
const GET_CONNECTION_NAMES = gql`
|
|
91
|
+
query GetConnectionNames($pagination: IntegrationsPaginationInput) {
|
|
92
|
+
getConnections(pagination: $pagination) {
|
|
93
|
+
items {
|
|
94
|
+
id
|
|
95
|
+
name
|
|
96
|
+
}
|
|
97
|
+
total
|
|
98
|
+
hasMore
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
const GET_CONNECTION = gql`
|
|
103
|
+
${CONNECTION_FIELDS}
|
|
104
|
+
query GetConnection($id: ID!) {
|
|
105
|
+
getConnection(id: $id) {
|
|
106
|
+
...ConnectionFields
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
const GET_CONNECTIONS_BY_PROVIDER = gql`
|
|
111
|
+
${CONNECTION_FIELDS}
|
|
112
|
+
query GetConnectionsByProvider(
|
|
113
|
+
$providerId: ID!
|
|
114
|
+
$pagination: IntegrationsPaginationInput
|
|
115
|
+
) {
|
|
116
|
+
getConnectionsByProvider(providerId: $providerId, pagination: $pagination) {
|
|
117
|
+
items {
|
|
118
|
+
...ConnectionFields
|
|
119
|
+
}
|
|
120
|
+
total
|
|
121
|
+
hasMore
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
`;
|
|
125
|
+
const GET_PROVIDERS = gql`
|
|
126
|
+
${PROVIDER_FIELDS}
|
|
127
|
+
query GetProviders(
|
|
128
|
+
$filter: ProviderFilterInput
|
|
129
|
+
$pagination: IntegrationsPaginationInput
|
|
130
|
+
) {
|
|
131
|
+
getProviders(filter: $filter, pagination: $pagination) {
|
|
132
|
+
items {
|
|
133
|
+
...ProviderFields
|
|
134
|
+
}
|
|
135
|
+
total
|
|
136
|
+
hasMore
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
const INITIATE_OAUTH = gql`
|
|
141
|
+
mutation InitiateOAuth($input: InitiateOAuthInput!) {
|
|
142
|
+
initiateOAuth(input: $input) {
|
|
143
|
+
redirectUrl
|
|
144
|
+
state
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
const CREATE_CONNECTION = gql`
|
|
149
|
+
${CONNECTION_FIELDS}
|
|
150
|
+
mutation CreateConnection($input: CreateConnectionInput!) {
|
|
151
|
+
createConnection(input: $input) {
|
|
152
|
+
...ConnectionFields
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
`;
|
|
156
|
+
/** Page size the integrations service allows; it clamps larger limits to 100. */
|
|
157
|
+
const CONNECTIONS_PAGE_SIZE = 100;
|
|
158
|
+
/**
|
|
159
|
+
* Every page of a connection list. A picker that accepts any provider (the
|
|
160
|
+
* HTTP Request node) must offer every saved connection, not the first 100.
|
|
161
|
+
*
|
|
162
|
+
* Reads until the server says there is no more, the reported total is reached,
|
|
163
|
+
* or a page adds no connection it has not already returned, so a server that
|
|
164
|
+
* keeps answering `hasMore` without progressing cannot loop forever.
|
|
165
|
+
*/
|
|
166
|
+
async function fetchAllConnectionPages(fetchPage) {
|
|
167
|
+
const items = [];
|
|
168
|
+
const seen = /* @__PURE__ */ new Set();
|
|
169
|
+
let total = 0;
|
|
170
|
+
let hasMore = false;
|
|
171
|
+
for (let offset = 0;; offset += 100) {
|
|
172
|
+
const result = await fetchPage(offset);
|
|
173
|
+
const fresh = (result?.items ?? []).filter((item) => !seen.has(item.id));
|
|
174
|
+
for (const item of fresh) {
|
|
175
|
+
seen.add(item.id);
|
|
176
|
+
items.push(item);
|
|
177
|
+
}
|
|
178
|
+
total = result?.total ?? items.length;
|
|
179
|
+
hasMore = result?.hasMore ?? false;
|
|
180
|
+
if (!hasMore || fresh.length === 0 || items.length >= total) break;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
items,
|
|
184
|
+
total,
|
|
185
|
+
hasMore: hasMore && items.length < total
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Names of the workspace's saved connections, by id, for the ids asked for.
|
|
190
|
+
* Code exports use them to write `connection: '<name>'` instead of an id
|
|
191
|
+
* (`ExportOptionsInput.connectionNameMap`). Ids without a saved connection
|
|
192
|
+
* are left out.
|
|
193
|
+
*/
|
|
194
|
+
async function fetchConnectionNames(ids) {
|
|
195
|
+
const wanted = new Set(ids);
|
|
196
|
+
if (wanted.size === 0) return {};
|
|
197
|
+
const client = getFluidGridsClient();
|
|
198
|
+
const list = await fetchAllConnectionPages(async (offset) => {
|
|
199
|
+
return throwIfResultError(await client.query({
|
|
200
|
+
query: GET_CONNECTION_NAMES,
|
|
201
|
+
variables: { pagination: {
|
|
202
|
+
limit: 100,
|
|
203
|
+
offset
|
|
204
|
+
} },
|
|
205
|
+
fetchPolicy: "network-only"
|
|
206
|
+
})).data?.getConnections;
|
|
207
|
+
});
|
|
208
|
+
const names = {};
|
|
209
|
+
for (const connection of list.items) if (wanted.has(connection.id) && connection.name.trim()) names[connection.id] = connection.name;
|
|
210
|
+
return names;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Hook to fetch list of connections from the integrations service.
|
|
214
|
+
*/
|
|
215
|
+
function useConnections(filter) {
|
|
216
|
+
const [connections, setConnections] = useState([]);
|
|
217
|
+
const [total, setTotal] = useState(0);
|
|
218
|
+
const [hasMore, setHasMore] = useState(false);
|
|
219
|
+
const [loading, setLoading] = useState(true);
|
|
220
|
+
const [error, setError] = useState(null);
|
|
221
|
+
const filterKey = JSON.stringify(filter);
|
|
222
|
+
const fetchData = useCallback(async () => {
|
|
223
|
+
setLoading(true);
|
|
224
|
+
setError(null);
|
|
225
|
+
try {
|
|
226
|
+
const client = getFluidGridsClient();
|
|
227
|
+
const parsedFilter = filterKey ? JSON.parse(filterKey) : void 0;
|
|
228
|
+
const list = await fetchAllConnectionPages(async (offset) => {
|
|
229
|
+
return (await client.query({
|
|
230
|
+
query: GET_CONNECTIONS,
|
|
231
|
+
variables: {
|
|
232
|
+
filter: parsedFilter,
|
|
233
|
+
pagination: {
|
|
234
|
+
limit: 100,
|
|
235
|
+
offset
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
fetchPolicy: "network-only"
|
|
239
|
+
})).data?.getConnections;
|
|
240
|
+
});
|
|
241
|
+
setConnections(list.items);
|
|
242
|
+
setTotal(list.total);
|
|
243
|
+
setHasMore(list.hasMore);
|
|
244
|
+
} catch (err) {
|
|
245
|
+
setError(err);
|
|
246
|
+
} finally {
|
|
247
|
+
setLoading(false);
|
|
248
|
+
}
|
|
249
|
+
}, [filterKey]);
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
fetchData();
|
|
252
|
+
}, [fetchData]);
|
|
253
|
+
return {
|
|
254
|
+
connections,
|
|
255
|
+
total,
|
|
256
|
+
hasMore,
|
|
257
|
+
loading,
|
|
258
|
+
error,
|
|
259
|
+
refetch: fetchData
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Hook to fetch a single connection by ID.
|
|
264
|
+
*/
|
|
265
|
+
function useConnection(connectionId) {
|
|
266
|
+
const [connection, setConnection] = useState(null);
|
|
267
|
+
const [loading, setLoading] = useState(true);
|
|
268
|
+
const [error, setError] = useState(null);
|
|
269
|
+
const fetchData = useCallback(async () => {
|
|
270
|
+
if (!connectionId) {
|
|
271
|
+
setLoading(false);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
setLoading(true);
|
|
275
|
+
setError(null);
|
|
276
|
+
try {
|
|
277
|
+
const result = await getFluidGridsClient().query({
|
|
278
|
+
query: GET_CONNECTION,
|
|
279
|
+
variables: { id: connectionId },
|
|
280
|
+
fetchPolicy: "cache-first"
|
|
281
|
+
});
|
|
282
|
+
setConnection(result.data?.getConnection ?? null);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
setError(err);
|
|
285
|
+
} finally {
|
|
286
|
+
setLoading(false);
|
|
287
|
+
}
|
|
288
|
+
}, [connectionId]);
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
fetchData();
|
|
291
|
+
}, [fetchData]);
|
|
292
|
+
return {
|
|
293
|
+
connection,
|
|
294
|
+
loading,
|
|
295
|
+
error,
|
|
296
|
+
refetch: fetchData
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Hook to fetch connections for a specific provider.
|
|
301
|
+
*/
|
|
302
|
+
function useConnectionsByProvider(providerId) {
|
|
303
|
+
const [connections, setConnections] = useState([]);
|
|
304
|
+
const [total, setTotal] = useState(0);
|
|
305
|
+
const [loading, setLoading] = useState(true);
|
|
306
|
+
const [error, setError] = useState(null);
|
|
307
|
+
const fetchData = useCallback(async () => {
|
|
308
|
+
if (!providerId) {
|
|
309
|
+
setLoading(false);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
setLoading(true);
|
|
313
|
+
setError(null);
|
|
314
|
+
try {
|
|
315
|
+
const result = await getFluidGridsClient().query({
|
|
316
|
+
query: GET_CONNECTIONS_BY_PROVIDER,
|
|
317
|
+
variables: {
|
|
318
|
+
providerId,
|
|
319
|
+
pagination: { limit: 100 }
|
|
320
|
+
},
|
|
321
|
+
fetchPolicy: "network-only"
|
|
322
|
+
});
|
|
323
|
+
setConnections(result.data?.getConnectionsByProvider?.items ?? []);
|
|
324
|
+
setTotal(result.data?.getConnectionsByProvider?.total ?? 0);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
setError(err);
|
|
327
|
+
} finally {
|
|
328
|
+
setLoading(false);
|
|
329
|
+
}
|
|
330
|
+
}, [providerId]);
|
|
331
|
+
useEffect(() => {
|
|
332
|
+
fetchData();
|
|
333
|
+
}, [fetchData]);
|
|
334
|
+
return {
|
|
335
|
+
connections,
|
|
336
|
+
total,
|
|
337
|
+
loading,
|
|
338
|
+
error,
|
|
339
|
+
refetch: fetchData
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Hook to fetch available integration providers.
|
|
344
|
+
*/
|
|
345
|
+
function useProviders(filter) {
|
|
346
|
+
const [providers, setProviders] = useState([]);
|
|
347
|
+
const [total, setTotal] = useState(0);
|
|
348
|
+
const [loading, setLoading] = useState(true);
|
|
349
|
+
const [error, setError] = useState(null);
|
|
350
|
+
const filterKey = JSON.stringify(filter);
|
|
351
|
+
const fetchData = useCallback(async () => {
|
|
352
|
+
setLoading(true);
|
|
353
|
+
setError(null);
|
|
354
|
+
try {
|
|
355
|
+
const client = getFluidGridsClient();
|
|
356
|
+
const parsedFilter = filterKey ? JSON.parse(filterKey) : void 0;
|
|
357
|
+
const result = await client.query({
|
|
358
|
+
query: GET_PROVIDERS,
|
|
359
|
+
variables: {
|
|
360
|
+
filter: parsedFilter,
|
|
361
|
+
pagination: { limit: 100 }
|
|
362
|
+
},
|
|
363
|
+
fetchPolicy: "cache-first"
|
|
364
|
+
});
|
|
365
|
+
setProviders(result.data?.getProviders?.items ?? []);
|
|
366
|
+
setTotal(result.data?.getProviders?.total ?? 0);
|
|
367
|
+
} catch (err) {
|
|
368
|
+
setError(err);
|
|
369
|
+
} finally {
|
|
370
|
+
setLoading(false);
|
|
371
|
+
}
|
|
372
|
+
}, [filterKey]);
|
|
373
|
+
useEffect(() => {
|
|
374
|
+
fetchData();
|
|
375
|
+
}, [fetchData]);
|
|
376
|
+
return {
|
|
377
|
+
providers,
|
|
378
|
+
total,
|
|
379
|
+
loading,
|
|
380
|
+
error,
|
|
381
|
+
refetch: fetchData
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Hook to create a new connection.
|
|
386
|
+
*/
|
|
387
|
+
function useCreateConnection() {
|
|
388
|
+
const [loading, setLoading] = useState(false);
|
|
389
|
+
const [error, setError] = useState(null);
|
|
390
|
+
return {
|
|
391
|
+
createConnection: useCallback(async (input) => {
|
|
392
|
+
setLoading(true);
|
|
393
|
+
setError(null);
|
|
394
|
+
try {
|
|
395
|
+
const client = getFluidGridsClient();
|
|
396
|
+
return throwIfResultError(await client.mutate({
|
|
397
|
+
mutation: CREATE_CONNECTION,
|
|
398
|
+
variables: { input }
|
|
399
|
+
})).data?.createConnection ?? null;
|
|
400
|
+
} catch (err) {
|
|
401
|
+
setError(err);
|
|
402
|
+
return null;
|
|
403
|
+
} finally {
|
|
404
|
+
setLoading(false);
|
|
405
|
+
}
|
|
406
|
+
}, []),
|
|
407
|
+
loading,
|
|
408
|
+
error
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Hook to initiate OAuth flow for a connection.
|
|
413
|
+
*/
|
|
414
|
+
function useInitiateOAuth() {
|
|
415
|
+
const [loading, setLoading] = useState(false);
|
|
416
|
+
const [error, setError] = useState(null);
|
|
417
|
+
return {
|
|
418
|
+
initiateOAuth: useCallback(async (input) => {
|
|
419
|
+
setLoading(true);
|
|
420
|
+
setError(null);
|
|
421
|
+
try {
|
|
422
|
+
const client = getFluidGridsClient();
|
|
423
|
+
return throwIfResultError(await client.mutate({
|
|
424
|
+
mutation: INITIATE_OAUTH,
|
|
425
|
+
variables: { input }
|
|
426
|
+
})).data?.initiateOAuth ?? null;
|
|
427
|
+
} catch (err) {
|
|
428
|
+
setError(err);
|
|
429
|
+
return null;
|
|
430
|
+
} finally {
|
|
431
|
+
setLoading(false);
|
|
432
|
+
}
|
|
433
|
+
}, []),
|
|
434
|
+
loading,
|
|
435
|
+
error
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export { useCreateConnection as a, useConnectionsByProvider as i, useConnection as n, useInitiateOAuth as o, useConnections as r, useProviders as s, fetchConnectionNames as t };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { o as throwIfResultError, t as describeOperationError } from "./errors-xPZ-IbQd.js";
|
|
3
3
|
import { n as getFluidGridsClient } from "./client-Ctl4jmY3.js";
|
|
4
|
+
import { un as useFluidGridsAnalytics } from "./FluidGridsProvider-C-WGQwuT.js";
|
|
4
5
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as downloadBlob } from "./workflow-transfer-CQnQC-ke.js";
|
|
6
|
+
import { i as WORKFLOWS_QUOTA_NAME } from "./quota-Cdt8yz7N.js";
|
|
7
|
+
import { c as emitWorkflowLimitHit, o as emitUpgradeClicked } from "./fluidgridsEvents-Dm5CaHtr.js";
|
|
8
|
+
import { l as buildExportDownload, t as downloadBlob } from "./workflow-transfer-CktP7o1c.js";
|
|
9
9
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
-
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
|
|
12
13
|
// src/generated/documents/wspace/ExportWorkflowCodeDocument.ts
|
|
13
14
|
const ExportWorkflowCodeDocument = {
|
|
@@ -79,6 +80,24 @@ const ExportWorkflowCodeDocument = {
|
|
|
79
80
|
}
|
|
80
81
|
},
|
|
81
82
|
"directives": []
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"kind": "VariableDefinition",
|
|
86
|
+
"variable": {
|
|
87
|
+
"kind": "Variable",
|
|
88
|
+
"name": {
|
|
89
|
+
"kind": "Name",
|
|
90
|
+
"value": "options"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"type": {
|
|
94
|
+
"kind": "NamedType",
|
|
95
|
+
"name": {
|
|
96
|
+
"kind": "Name",
|
|
97
|
+
"value": "ExportOptionsInput"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"directives": []
|
|
82
101
|
}
|
|
83
102
|
],
|
|
84
103
|
"directives": [],
|
|
@@ -132,6 +151,20 @@ const ExportWorkflowCodeDocument = {
|
|
|
132
151
|
"value": "format"
|
|
133
152
|
}
|
|
134
153
|
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"kind": "Argument",
|
|
157
|
+
"name": {
|
|
158
|
+
"kind": "Name",
|
|
159
|
+
"value": "options"
|
|
160
|
+
},
|
|
161
|
+
"value": {
|
|
162
|
+
"kind": "Variable",
|
|
163
|
+
"name": {
|
|
164
|
+
"kind": "Name",
|
|
165
|
+
"value": "options"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
135
168
|
}
|
|
136
169
|
],
|
|
137
170
|
"directives": [],
|
|
@@ -292,121 +325,51 @@ const ExportWorkflowCodeDocument = {
|
|
|
292
325
|
}]
|
|
293
326
|
};
|
|
294
327
|
|
|
295
|
-
// src/components/shared/
|
|
328
|
+
// src/components/shared/QuotaExhaustedDialog.tsx
|
|
296
329
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
* - `quota-not-provisioned`: the workspace has no plan that includes FluidGrids
|
|
303
|
-
* workflows. Nothing is used up; choosing a plan for the workspace is the way
|
|
304
|
-
* past it, so the dialog still offers View plans (round-3 verification: the
|
|
305
|
-
* refusal toast vanished and nothing pointed at billing).
|
|
306
|
-
* - `failed`: no dialog. The shell's backend-error toast already shows the
|
|
307
|
-
* server's message, and nothing navigated.
|
|
330
|
+
* Alert shown when a workflow-creating action (save/duplicate/import) is
|
|
331
|
+
* rejected with `QUOTA_EXHAUSTED` for `fluidgrids.workflows.count`. Mirrors
|
|
332
|
+
* the "Folder Limit Reached" dialog in microfe-files' BrowserPage.tsx, built
|
|
333
|
+
* on the same `AlertDialog` primitives already used elsewhere in this SDK
|
|
334
|
+
* (see card-workflow.tsx's delete-confirmation dialog).
|
|
308
335
|
*/
|
|
309
|
-
function
|
|
336
|
+
function QuotaExhaustedDialog({ open, onOpenChange, onUpgrade, title, description, surface, limitHit = true }) {
|
|
310
337
|
const tr = useTr();
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
|
|
338
|
+
const { bus, workspaceId } = useFluidGridsAnalytics();
|
|
339
|
+
const wasOpen = useRef(false);
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
if (open && !wasOpen.current && limitHit) emitWorkflowLimitHit(bus, {
|
|
342
|
+
workspaceId,
|
|
343
|
+
surface
|
|
344
|
+
});
|
|
345
|
+
wasOpen.current = open;
|
|
346
|
+
}, [
|
|
347
|
+
open,
|
|
348
|
+
bus,
|
|
349
|
+
workspaceId,
|
|
314
350
|
surface,
|
|
351
|
+
limitHit
|
|
352
|
+
]);
|
|
353
|
+
const handleUpgrade = () => {
|
|
354
|
+
emitUpgradeClicked(bus, {
|
|
355
|
+
workspaceId,
|
|
356
|
+
surface: "quota-dialog",
|
|
357
|
+
quotaKey: WORKFLOWS_QUOTA_NAME
|
|
358
|
+
});
|
|
359
|
+
onUpgrade();
|
|
360
|
+
};
|
|
361
|
+
const resolvedTitle = title ?? tr("fluidgrids.components.quotaExhaustedDialog.title", "Workflow Limit Reached");
|
|
362
|
+
const resolvedDescription = description ?? tr("fluidgrids.components.quotaExhaustedDialog.description", "You've reached the workflow limit for your plan. Upgrade your plan to create more workflows.");
|
|
363
|
+
return /* @__PURE__ */ jsx(AlertDialog, {
|
|
315
364
|
open,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
onUpgrade();
|
|
322
|
-
onClose();
|
|
323
|
-
},
|
|
324
|
-
...notProvisioned ? {
|
|
325
|
-
title: tr("fluidgrids.components.createRefusal.notProvisionedTitle", "Workflows aren't in this workspace's plan"),
|
|
326
|
-
description: tr("fluidgrids.components.createRefusal.notProvisionedDescription", "This workspace has no plan that includes FluidGrids workflows, so no workflow was created. Choose a plan for this workspace, or ask a workspace admin to add one.")
|
|
327
|
-
} : {}
|
|
365
|
+
onOpenChange,
|
|
366
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: resolvedTitle }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: resolvedDescription })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, { children: tr("fluidgrids.components.quotaExhaustedDialog.dismiss", "Dismiss") }), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
367
|
+
onClick: handleUpgrade,
|
|
368
|
+
children: tr("fluidgrids.components.quotaExhaustedDialog.viewPlans", "View plans")
|
|
369
|
+
})] })] })
|
|
328
370
|
});
|
|
329
371
|
}
|
|
330
372
|
|
|
331
|
-
// src/utils/workflow-description.ts
|
|
332
|
-
/** The longest description the editors accept. */
|
|
333
|
-
const WORKFLOW_DESCRIPTION_MAX_LENGTH = 500;
|
|
334
|
-
/**
|
|
335
|
-
* Descriptions older builder saves wrote in place of a real one: every save
|
|
336
|
-
* copied the workflow's name into its description, with these fallbacks for an
|
|
337
|
-
* unnamed workflow. A description that only repeats the name says nothing.
|
|
338
|
-
*/
|
|
339
|
-
const LEGACY_PLACEHOLDERS = /* @__PURE__ */ new Set([
|
|
340
|
-
"Untitled Workflow",
|
|
341
|
-
"Workflow update",
|
|
342
|
-
"Workflow Description"
|
|
343
|
-
]);
|
|
344
|
-
/** The description as it is stored: surrounding whitespace removed. */
|
|
345
|
-
function normalizeWorkflowDescription(text) {
|
|
346
|
-
return text.trim();
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* The description worth showing for a workflow: empty when there is none, or
|
|
350
|
-
* when it is a placeholder an older builder save wrote (the name again, or one
|
|
351
|
-
* of the unnamed-workflow fallbacks).
|
|
352
|
-
*/
|
|
353
|
-
function visibleWorkflowDescription(description, name) {
|
|
354
|
-
const text = normalizeWorkflowDescription(description ?? "");
|
|
355
|
-
if (!text) return "";
|
|
356
|
-
if (text === (name ?? "").trim()) return "";
|
|
357
|
-
if (LEGACY_PLACEHOLDERS.has(text)) return "";
|
|
358
|
-
return text;
|
|
359
|
-
}
|
|
360
|
-
/** Decide what to do with `draft`, given the description shown before editing. */
|
|
361
|
-
function commitWorkflowDescription(shown, draft) {
|
|
362
|
-
const description = normalizeWorkflowDescription(draft);
|
|
363
|
-
if (description.length > 500) return {
|
|
364
|
-
kind: "too-long",
|
|
365
|
-
length: description.length
|
|
366
|
-
};
|
|
367
|
-
if (description === normalizeWorkflowDescription(shown)) return { kind: "unchanged" };
|
|
368
|
-
return {
|
|
369
|
-
kind: "save",
|
|
370
|
-
description
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
/** The characters left for a draft; negative once it is too long. */
|
|
374
|
-
function workflowDescriptionCharactersLeft(draft) {
|
|
375
|
-
return 500 - normalizeWorkflowDescription(draft).length;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* The `updateWorkflowDefinition` input that changes only the description. An
|
|
379
|
-
* empty description is sent as "" (not null), which is what clears it.
|
|
380
|
-
*/
|
|
381
|
-
function workflowDescriptionUpdateInput(description, guard = {}) {
|
|
382
|
-
return {
|
|
383
|
-
description: normalizeWorkflowDescription(description),
|
|
384
|
-
...guard.expectedRevision !== void 0 ? { expectedRevision: guard.expectedRevision } : {},
|
|
385
|
-
...guard.editSessionId ? { editSessionId: guard.editSessionId } : {}
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Save `description` on the version `id`, in place. Throws the service's
|
|
390
|
-
* refusal (permission, a conflict, a viewer of a shared workflow) so the
|
|
391
|
-
* caller can roll its optimistic copy back and say why.
|
|
392
|
-
*/
|
|
393
|
-
async function saveWorkflowDescription(client, id, description, guard = {}) {
|
|
394
|
-
const { data } = throwIfResultError(await client.mutate({
|
|
395
|
-
mutation: UpdateWorkflowDefinitionDocument,
|
|
396
|
-
variables: {
|
|
397
|
-
id,
|
|
398
|
-
input: workflowDescriptionUpdateInput(description, guard)
|
|
399
|
-
}
|
|
400
|
-
}));
|
|
401
|
-
const saved = data?.updateWorkflowDefinition;
|
|
402
|
-
if (!saved) throw new Error("The description was not saved");
|
|
403
|
-
return {
|
|
404
|
-
id: saved.id,
|
|
405
|
-
description: saved.description ?? "",
|
|
406
|
-
revision: saved.revision
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
|
|
410
373
|
// src/hooks/useWorkflowCodeExport.ts
|
|
411
374
|
/**
|
|
412
375
|
* Code-first export (BOFF-9904): read a workflow version lifted to
|
|
@@ -424,7 +387,8 @@ async function fetchWorkflowCodeExport(target) {
|
|
|
424
387
|
variables: {
|
|
425
388
|
workflowKey: target.workflowKey,
|
|
426
389
|
version: target.version || null,
|
|
427
|
-
format: target.format
|
|
390
|
+
format: target.format,
|
|
391
|
+
...target.options ? { options: target.options } : {}
|
|
428
392
|
},
|
|
429
393
|
fetchPolicy: "network-only"
|
|
430
394
|
});
|
|
@@ -508,4 +472,4 @@ function useExportWorkflowAs(save = downloadBlob) {
|
|
|
508
472
|
};
|
|
509
473
|
}
|
|
510
474
|
|
|
511
|
-
export {
|
|
475
|
+
export { ExportWorkflowCodeDocument as a, QuotaExhaustedDialog as i, useExportWorkflowAs as n, useWorkflowCodeExport as r, fetchWorkflowCodeExport as t };
|
package/dist/workflow-builder.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { n as WorkflowBuilderCore, t as WorkflowBuilder } from "./WorkflowBuilder-
|
|
3
|
-
import { t as WorkflowBuilder$1 } from "./WorkflowBuilder-
|
|
2
|
+
import { n as WorkflowBuilderCore, t as WorkflowBuilder } from "./WorkflowBuilder-Bzx-e5lX.js";
|
|
3
|
+
import { t as WorkflowBuilder$1 } from "./WorkflowBuilder-CdcGE0Mf.js";
|
|
4
4
|
import { A as useFlowStore } from "./node-operation-selection-DHbtGNrG.js";
|
|
5
5
|
import { m as refetchStoreNodes } from "./FluidGridsProvider-C-WGQwuT.js";
|
|
6
6
|
import { t as WorkflowSearchRedirect } from "./WorkflowSearchRedirect-0MLrCjDn.js";
|