@burdenoff/fluidgrids-fe-sdk 2026.1029.6 → 2026.1029.8
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-H6R3ZIXN.js +22 -0
- package/dist/{WorkflowsList-VA2HRYFG.js → ExecutionsListPage-TLD2E442.js} +9 -9
- package/dist/{WorkflowBuilder-PORH3H6P.js → WorkflowBuilder-XVHY7XWJ.js} +12 -12
- package/dist/{ExecutionsListPage-SCPWUXUL.js → WorkflowsList-3GXXXURR.js} +9 -8
- package/dist/{chunk-MNY2UNQH.js → chunk-2NG5VZWI.js} +1 -1
- package/dist/{chunk-CY6KX4RG.js → chunk-6AMNEX2Y.js} +6 -1
- package/dist/{chunk-LPGQTSI2.js → chunk-6CKDGT2N.js} +3 -3
- package/dist/{chunk-U6KI4AKI.js → chunk-6TMLIQHB.js} +199 -1
- package/dist/{chunk-LTVAUZ3M.js → chunk-G3KZOX52.js} +3 -3
- package/dist/{chunk-7PP6CRXS.js → chunk-GQTEHWWY.js} +26 -8
- package/dist/{chunk-LB62TAF7.js → chunk-H4AZBUWM.js} +1 -1
- package/dist/{chunk-57RS7DXZ.js → chunk-HWEKWYXQ.js} +117 -8
- package/dist/{chunk-7B2GRTUL.js → chunk-LJGC7RAL.js} +164 -101
- package/dist/{chunk-4TGUNOQQ.js → chunk-NAYPOEYM.js} +391 -112
- package/dist/{chunk-BWAUFSHC.js → chunk-NNPXN4DI.js} +5 -5
- package/dist/{chunk-QZM6EDGK.js → chunk-NUBPALBK.js} +1 -1
- package/dist/{chunk-YSUSSIWU.js → chunk-R7VHURPQ.js} +1 -1
- package/dist/{chunk-7SSZUX6E.js → chunk-S4JYBJ4X.js} +2 -2
- package/dist/{chunk-WTGBHE3J.js → chunk-T22LICGX.js} +118 -96
- package/dist/{chunk-63ZMEHZ4.js → chunk-TJ6RUV4R.js} +937 -26
- package/dist/{chunk-H364USFF.js → chunk-UIDJT3YK.js} +1 -1
- package/dist/{chunk-4XAPSIHY.js → chunk-UWNCFMHV.js} +183 -26
- package/dist/{chunk-MDPBO52Q.js → chunk-V5PA5KGV.js} +2 -2
- package/dist/{chunk-MQI7NH4Z.js → chunk-VEZ7G2FE.js} +145 -8
- package/dist/{chunk-YHTRCQ5M.js → chunk-WEXO3KAY.js} +4 -4
- package/dist/{chunk-7LFAWWVF.js → chunk-WTP343PG.js} +2 -2
- package/dist/{chunk-Z6EWB5ZG.js → chunk-X2J4ZXKD.js} +1492 -98
- package/dist/{chunk-6XZCYLAQ.js → chunk-XJBCRDWZ.js} +3 -3
- package/dist/{chunk-AVMI3XLM.js → chunk-XMKYZP6Q.js} +282 -18
- package/dist/{chunk-5GD6OXYW.js → chunk-Z6I6A47T.js} +1 -1
- package/dist/{config-T7BQ7AO2.js → config-VM7FTHMZ.js} +1 -1
- package/dist/executions.js +13 -13
- package/dist/history.js +5 -5
- package/dist/index.d.ts +2588 -26
- package/dist/index.js +36 -36
- package/dist/nodes.js +2 -2
- package/dist/observability.js +7 -7
- package/dist/settings.js +7 -7
- package/dist/templates.js +11 -11
- package/dist/{workflow-builder-CZFczcE7.d.ts → workflow-builder-BMGVSwpy.d.ts} +7 -0
- package/dist/workflow-builder.d.ts +1 -1
- package/dist/workflow-builder.js +13 -13
- package/dist/workflows-list.js +9 -9
- package/package.json +1 -1
- package/dist/ExecutionDetailPage-M6JAWY4Q.js +0 -21
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NodeEndpointConfigsDocument, NodeEndpointConfigDocument, NodeManifestDocument, fetchAllNodeEndpointConfigs } from './chunk-
|
|
1
|
+
import { NodeEndpointConfigsDocument, NodeEndpointConfigDocument, NodeManifestDocument, fetchAllNodeEndpointConfigs } from './chunk-GQTEHWWY.js';
|
|
2
2
|
import { useTr } from './chunk-UULVIT25.js';
|
|
3
3
|
import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
4
4
|
import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { REPLAY_WORKFLOW_RUN, RETRY_WORKFLOW_RUNS } from './chunk-5ERAJC2I.js';
|
|
2
|
-
import { useFluidGridsAnalytics, throwIfResultError, emitRunStarted, openRunQuotaUpgradePrompt } from './chunk-
|
|
3
|
-
import { useExecutionsStore } from './chunk-
|
|
4
|
-
import { ExecutionsListDocument, ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument } from './chunk-
|
|
2
|
+
import { useFluidGridsAnalytics, throwIfResultError, emitRunStarted, openRunQuotaUpgradePrompt } from './chunk-NAYPOEYM.js';
|
|
3
|
+
import { useExecutionsStore } from './chunk-6AMNEX2Y.js';
|
|
4
|
+
import { ExecutionsListDocument, ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument } from './chunk-GQTEHWWY.js';
|
|
5
5
|
import { useTr } from './chunk-UULVIT25.js';
|
|
6
6
|
import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
7
7
|
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
@@ -75,6 +75,107 @@ function dateRangeToInput(start, end) {
|
|
|
75
75
|
return input;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// src/modules/executions/utils/run-parity.ts
|
|
79
|
+
function isRecord(value) {
|
|
80
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
81
|
+
}
|
|
82
|
+
function text(value) {
|
|
83
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
84
|
+
}
|
|
85
|
+
function runChainLinks(run) {
|
|
86
|
+
const candidates = [
|
|
87
|
+
["previous", run.continuedFromRunId],
|
|
88
|
+
["next", run.continuedToRunId],
|
|
89
|
+
["first", run.firstRunId],
|
|
90
|
+
["root", run.rootRunId === run.parentRunId ? null : run.rootRunId]
|
|
91
|
+
];
|
|
92
|
+
const seen = /* @__PURE__ */ new Set([run.id]);
|
|
93
|
+
const links = [];
|
|
94
|
+
for (const [kind, runId] of candidates) {
|
|
95
|
+
if (!runId || seen.has(runId)) continue;
|
|
96
|
+
seen.add(runId);
|
|
97
|
+
links.push({ kind, runId });
|
|
98
|
+
}
|
|
99
|
+
return links;
|
|
100
|
+
}
|
|
101
|
+
function shortRunId(runId, length = 12) {
|
|
102
|
+
return runId.length > length ? `${runId.slice(0, length)}\u2026` : runId;
|
|
103
|
+
}
|
|
104
|
+
function handlersOf(value) {
|
|
105
|
+
const entries = Array.isArray(value) ? value.map((entry) => [void 0, entry]) : isRecord(value) ? Object.entries(value) : [];
|
|
106
|
+
const handlers = [];
|
|
107
|
+
for (const [key, entry] of entries) {
|
|
108
|
+
if (typeof entry === "string") {
|
|
109
|
+
handlers.push({ name: entry });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (!isRecord(entry)) continue;
|
|
113
|
+
const name = text(entry.name) ?? key;
|
|
114
|
+
if (!name) continue;
|
|
115
|
+
const description = text(entry.description);
|
|
116
|
+
handlers.push(description ? { name, description } : { name });
|
|
117
|
+
}
|
|
118
|
+
return handlers;
|
|
119
|
+
}
|
|
120
|
+
function parseMetadataDefinition(definition) {
|
|
121
|
+
const value = isRecord(definition) ? definition : {};
|
|
122
|
+
return {
|
|
123
|
+
name: text(value.name),
|
|
124
|
+
signals: handlersOf(value.signals),
|
|
125
|
+
queries: handlersOf(value.queries),
|
|
126
|
+
updates: handlersOf(value.updates)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
var WORKFLOW_ID_MAX_LENGTH = 256;
|
|
130
|
+
function withWorkflowIdFilter(input, workflowId, parityEnabled) {
|
|
131
|
+
const value = workflowId.trim();
|
|
132
|
+
if (!parityEnabled || !value) return input;
|
|
133
|
+
return { ...input, businessId: value.slice(0, WORKFLOW_ID_MAX_LENGTH) };
|
|
134
|
+
}
|
|
135
|
+
function statusCountFilter(input) {
|
|
136
|
+
const rest = { ...input };
|
|
137
|
+
delete rest.limit;
|
|
138
|
+
delete rest.offset;
|
|
139
|
+
delete rest.status;
|
|
140
|
+
return rest;
|
|
141
|
+
}
|
|
142
|
+
var STATUS_COUNT_GROUP_BY = ["STATUS" /* Status */];
|
|
143
|
+
function statusCountsOf(groups) {
|
|
144
|
+
const counts = /* @__PURE__ */ new Map();
|
|
145
|
+
for (const group of groups) {
|
|
146
|
+
const status = group.values[0] ?? group.key;
|
|
147
|
+
if (!status) continue;
|
|
148
|
+
counts.set(status, (counts.get(status) ?? 0) + group.count);
|
|
149
|
+
}
|
|
150
|
+
return [...counts.entries()].map(([status, count]) => ({ status, count })).sort((a, b) => b.count - a.count || a.status.localeCompare(b.status));
|
|
151
|
+
}
|
|
152
|
+
function overrideRequestOf(choice, version) {
|
|
153
|
+
if (choice === "remove") return { ok: true, override: null };
|
|
154
|
+
if (choice === "autoUpgrade")
|
|
155
|
+
return {
|
|
156
|
+
ok: true,
|
|
157
|
+
override: { behavior: "AUTO_UPGRADE" /* AutoUpgrade */ }
|
|
158
|
+
};
|
|
159
|
+
const pinned = version.trim();
|
|
160
|
+
if (!pinned) return { ok: false, reason: "versionRequired" };
|
|
161
|
+
return {
|
|
162
|
+
ok: true,
|
|
163
|
+
override: { behavior: "PINNED" /* Pinned */, version: pinned }
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function callbackTone(status) {
|
|
167
|
+
switch (status) {
|
|
168
|
+
case "DELIVERED":
|
|
169
|
+
return "success";
|
|
170
|
+
case "FAILED":
|
|
171
|
+
return "error";
|
|
172
|
+
case "DELIVERING":
|
|
173
|
+
return "info";
|
|
174
|
+
default:
|
|
175
|
+
return "neutral";
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
78
179
|
// src/modules/executions/utils/retry.ts
|
|
79
180
|
var NON_REPLAYABLE_CONTEXT_KEYS = ["isScheduled", "workspaceId"];
|
|
80
181
|
function buildRetryTriggerInput(run) {
|
|
@@ -443,7 +544,9 @@ function useExecutionActions() {
|
|
|
443
544
|
};
|
|
444
545
|
}
|
|
445
546
|
var EXECUTIONS_SEARCH_DEBOUNCE_MS = 350;
|
|
446
|
-
function useExecutionsWithStore(
|
|
547
|
+
function useExecutionsWithStore({
|
|
548
|
+
durableParity = false
|
|
549
|
+
} = {}) {
|
|
447
550
|
const { filter, pagination, setTotal } = useExecutionsStore();
|
|
448
551
|
const [debouncedSearch, setDebouncedSearch] = useState(filter.search);
|
|
449
552
|
useEffect(() => {
|
|
@@ -490,15 +593,21 @@ function useExecutionsWithStore() {
|
|
|
490
593
|
if (filter.tagId) {
|
|
491
594
|
baseInput.tagIds = [filter.tagId];
|
|
492
595
|
}
|
|
493
|
-
return baseInput;
|
|
494
|
-
}, [
|
|
596
|
+
return withWorkflowIdFilter(baseInput, filter.workflowId, durableParity);
|
|
597
|
+
}, [
|
|
598
|
+
filter,
|
|
599
|
+
debouncedSearch,
|
|
600
|
+
pagination.page,
|
|
601
|
+
pagination.pageSize,
|
|
602
|
+
durableParity
|
|
603
|
+
]);
|
|
495
604
|
const result = useExecutions(input);
|
|
496
605
|
useEffect(() => {
|
|
497
606
|
if (result.total !== pagination.total) {
|
|
498
607
|
setTotal(result.total);
|
|
499
608
|
}
|
|
500
609
|
}, [result.total, pagination.total, setTotal]);
|
|
501
|
-
return result;
|
|
610
|
+
return { ...result, input };
|
|
502
611
|
}
|
|
503
612
|
function useAutoRefresh(refetchFn, enabled = true, interval = 5e3) {
|
|
504
613
|
useEffect(() => {
|
|
@@ -510,4 +619,4 @@ function useAutoRefresh(refetchFn, enabled = true, interval = 5e3) {
|
|
|
510
619
|
}, [enabled, interval, refetchFn]);
|
|
511
620
|
}
|
|
512
621
|
|
|
513
|
-
export { useAutoRefresh, useExecution, useExecutionActions, useExecutionStats, useExecutions, useExecutionsWithStore, validateDateRange };
|
|
622
|
+
export { STATUS_COUNT_GROUP_BY, WORKFLOW_ID_MAX_LENGTH, callbackTone, overrideRequestOf, parseMetadataDefinition, runChainLinks, shortRunId, statusCountFilter, statusCountsOf, useAutoRefresh, useExecution, useExecutionActions, useExecutionStats, useExecutions, useExecutionsWithStore, validateDateRange };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-
|
|
1
|
+
import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-2NG5VZWI.js';
|
|
2
2
|
import { registerLiveCanvasHandler } from './chunk-PIKYQE7P.js';
|
|
3
|
-
import { useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-
|
|
4
|
-
import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-
|
|
5
|
-
import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes, throwIfResultError } from './chunk-
|
|
6
|
-
import { getFluidGridsConfig } from './chunk-
|
|
7
|
-
import { WorkflowDefinitionDocument } from './chunk-
|
|
3
|
+
import { useWorkflowReloadStore, releaseLeaseKeptForReload, useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-X2J4ZXKD.js';
|
|
4
|
+
import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-G3KZOX52.js';
|
|
5
|
+
import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, rememberRevision, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes, throwIfResultError } from './chunk-NAYPOEYM.js';
|
|
6
|
+
import { getFluidGridsConfig } from './chunk-6AMNEX2Y.js';
|
|
7
|
+
import { WorkflowDefinitionDocument } from './chunk-GQTEHWWY.js';
|
|
8
8
|
import { useTr } from './chunk-UULVIT25.js';
|
|
9
9
|
import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
10
10
|
import { useLocation, useNavigate, useParams } from 'react-router';
|
|
11
11
|
import { toast } from 'sonner';
|
|
12
12
|
import { Icon } from '@iconify/react';
|
|
13
13
|
import { lazy, useRef, useEffect, useState, useCallback, useMemo, Suspense } from 'react';
|
|
14
|
-
import { useSafeToursContext, usePlayTour } from '@burdenoff/fe-libs/shared/tours';
|
|
15
14
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
15
|
+
import { useSafeToursContext, usePlayTour } from '@burdenoff/fe-libs/shared/tours';
|
|
16
16
|
import { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';
|
|
17
17
|
import '@xyflow/react/dist/style.css';
|
|
18
18
|
|
|
@@ -653,7 +653,11 @@ function AssistantLiveCanvasHost() {
|
|
|
653
653
|
fetchDefinition,
|
|
654
654
|
registerNodeTypes: registerWorkflowNodeTypes,
|
|
655
655
|
notify,
|
|
656
|
-
workspaceId: () => getFluidGridsConfig().workspaceId || null
|
|
656
|
+
workspaceId: () => getFluidGridsConfig().workspaceId || null,
|
|
657
|
+
// The merged canvas now holds the stored version, assistant write
|
|
658
|
+
// included, so the next save is based on its revision (BOFF-9725)
|
|
659
|
+
// rather than refused as stale over a change already on screen.
|
|
660
|
+
onSynced: (remote) => rememberRevision(remote.id, remote.revision)
|
|
657
661
|
});
|
|
658
662
|
const stopWatching = watchCanvasBase();
|
|
659
663
|
const unregister = registerLiveCanvasHandler(sync.handle);
|
|
@@ -664,6 +668,48 @@ function AssistantLiveCanvasHost() {
|
|
|
664
668
|
}, []);
|
|
665
669
|
return null;
|
|
666
670
|
}
|
|
671
|
+
function LoadProblem({
|
|
672
|
+
title,
|
|
673
|
+
description,
|
|
674
|
+
retryLabel,
|
|
675
|
+
onRetry,
|
|
676
|
+
backLabel,
|
|
677
|
+
onBack,
|
|
678
|
+
testId
|
|
679
|
+
}) {
|
|
680
|
+
return /* @__PURE__ */ jsxs(
|
|
681
|
+
"div",
|
|
682
|
+
{
|
|
683
|
+
role: "alert",
|
|
684
|
+
"data-testid": testId,
|
|
685
|
+
className: "flex h-full min-h-[60vh] w-full flex-col items-center justify-center gap-3 p-6 text-center",
|
|
686
|
+
children: [
|
|
687
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-medium text-foreground", children: title }),
|
|
688
|
+
/* @__PURE__ */ jsx("p", { className: "max-w-md text-sm text-foreground/60", children: description }),
|
|
689
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
690
|
+
/* @__PURE__ */ jsx(
|
|
691
|
+
"button",
|
|
692
|
+
{
|
|
693
|
+
type: "button",
|
|
694
|
+
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
|
|
695
|
+
onClick: onRetry,
|
|
696
|
+
children: retryLabel
|
|
697
|
+
}
|
|
698
|
+
),
|
|
699
|
+
/* @__PURE__ */ jsx(
|
|
700
|
+
"button",
|
|
701
|
+
{
|
|
702
|
+
type: "button",
|
|
703
|
+
className: "rounded-md border px-4 py-2 text-sm font-medium text-foreground",
|
|
704
|
+
onClick: onBack,
|
|
705
|
+
children: backLabel
|
|
706
|
+
}
|
|
707
|
+
)
|
|
708
|
+
] })
|
|
709
|
+
]
|
|
710
|
+
}
|
|
711
|
+
);
|
|
712
|
+
}
|
|
667
713
|
var START_DELAY_MS = 800;
|
|
668
714
|
function StartGuidedTour() {
|
|
669
715
|
const location = useLocation();
|
|
@@ -736,11 +782,17 @@ function WorkflowItem({
|
|
|
736
782
|
const [createRefusal, setCreateRefusal] = useState(null);
|
|
737
783
|
const upgradingRef = useRef(false);
|
|
738
784
|
const resetWorkflow = useFlowStore((s) => s.actions.resetWorkflow);
|
|
785
|
+
const reloadNonce = useWorkflowReloadStore((s) => s.nonce);
|
|
786
|
+
useEffect(() => () => releaseLeaseKeptForReload(), [id, version]);
|
|
787
|
+
const seenReloadNonceRef = useRef(reloadNonce);
|
|
788
|
+
const pendingReloadRef = useRef(null);
|
|
789
|
+
const [reloadFailed, setReloadFailed] = useState(false);
|
|
739
790
|
const { getWorkflow } = useLazyWorkflowDefinition();
|
|
740
791
|
const { createWorkflow } = useCreateWorkflow();
|
|
741
792
|
const creatingRef = useRef(false);
|
|
742
793
|
const fromSharedLoadedRef = useRef(false);
|
|
743
794
|
const fetchedWorkflowRef = useRef(null);
|
|
795
|
+
const loadSeqRef = useRef(0);
|
|
744
796
|
const { installedAppIds } = useInstalledNodes();
|
|
745
797
|
const [pendingWorkflow, setPendingWorkflow] = useState(null);
|
|
746
798
|
const [nodeCheck, setNodeCheck] = useState(
|
|
@@ -770,7 +822,7 @@ function WorkflowItem({
|
|
|
770
822
|
try {
|
|
771
823
|
const { getGlobalStoreClient } = await import('./global-client-KLOVTVPP.js');
|
|
772
824
|
const { InstallWorkflowNodeDocument } = await import('./global-operations-D2USVOPM.js');
|
|
773
|
-
const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-
|
|
825
|
+
const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-VM7FTHMZ.js');
|
|
774
826
|
const storeClient = getGlobalStoreClient();
|
|
775
827
|
const cfg = getFluidGridsConfig2();
|
|
776
828
|
for (let i = 0; i < nodesToInstall.length; i++) {
|
|
@@ -843,11 +895,27 @@ function WorkflowItem({
|
|
|
843
895
|
);
|
|
844
896
|
useEffect(() => {
|
|
845
897
|
let mounted = true;
|
|
898
|
+
const target = `${id ?? ""}@${version ?? ""}`;
|
|
899
|
+
loadSeqRef.current += 1;
|
|
900
|
+
const loadSeq = loadSeqRef.current;
|
|
901
|
+
if (reloadNonce !== seenReloadNonceRef.current) {
|
|
902
|
+
seenReloadNonceRef.current = reloadNonce;
|
|
903
|
+
pendingReloadRef.current = target;
|
|
904
|
+
}
|
|
905
|
+
const reloadPending = () => pendingReloadRef.current === target;
|
|
906
|
+
const fetchedCopy = () => fetchedWorkflowRef.current?.target === target ? fetchedWorkflowRef.current.workflow : null;
|
|
907
|
+
const recordFetched = (workflow2) => {
|
|
908
|
+
if (loadSeqRef.current !== loadSeq) return false;
|
|
909
|
+
fetchedWorkflowRef.current = { target, workflow: workflow2 };
|
|
910
|
+
if (pendingReloadRef.current === target) pendingReloadRef.current = null;
|
|
911
|
+
return true;
|
|
912
|
+
};
|
|
846
913
|
const loadWorkflow = async () => {
|
|
847
914
|
try {
|
|
848
915
|
resetWorkflow();
|
|
849
916
|
if (mounted) setNotFound(false);
|
|
850
917
|
if (mounted) setLoadError(null);
|
|
918
|
+
if (mounted) setReloadFailed(false);
|
|
851
919
|
if (version && mounted) {
|
|
852
920
|
setIsLoading(true);
|
|
853
921
|
}
|
|
@@ -904,7 +972,7 @@ function WorkflowItem({
|
|
|
904
972
|
}
|
|
905
973
|
return;
|
|
906
974
|
}
|
|
907
|
-
const freshCreate = createIntentRef.current && !creatingRef.current && !
|
|
975
|
+
const freshCreate = createIntentRef.current && !creatingRef.current && !fetchedCopy() && !loadRunId;
|
|
908
976
|
const result = freshCreate ? null : await getWorkflow(id, void 0, version);
|
|
909
977
|
const definitionJson = result?.definitionJson;
|
|
910
978
|
const defData = definitionJson?.data ?? (definitionJson?.nodes ? definitionJson : void 0);
|
|
@@ -925,7 +993,9 @@ function WorkflowItem({
|
|
|
925
993
|
// new version (spec code-first 06 §1).
|
|
926
994
|
codeBuildId: codeBuildIdOf(result?.definitionJson)
|
|
927
995
|
};
|
|
928
|
-
|
|
996
|
+
if (recordFetched(workflowState)) {
|
|
997
|
+
rememberRevision(result?.id, result?.revision);
|
|
998
|
+
}
|
|
929
999
|
let requiredNodeTypes = [];
|
|
930
1000
|
try {
|
|
931
1001
|
requiredNodeTypes = await buildRequiredNodeTypes(
|
|
@@ -949,8 +1019,14 @@ function WorkflowItem({
|
|
|
949
1019
|
return;
|
|
950
1020
|
}
|
|
951
1021
|
if (mounted) {
|
|
952
|
-
if (
|
|
953
|
-
|
|
1022
|
+
if (reloadPending()) {
|
|
1023
|
+
setReloadFailed(true);
|
|
1024
|
+
releaseLeaseKeptForReload();
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const earlier = fetchedCopy();
|
|
1028
|
+
if (earlier) {
|
|
1029
|
+
setWorkflow(earlier);
|
|
954
1030
|
return;
|
|
955
1031
|
}
|
|
956
1032
|
if (loadRunId) {
|
|
@@ -999,16 +1075,18 @@ function WorkflowItem({
|
|
|
999
1075
|
if (mounted) setCreateRefusal(classifyCreateRefusal(reported));
|
|
1000
1076
|
return;
|
|
1001
1077
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1078
|
+
const createdWorkflow = {
|
|
1079
|
+
...newWorkflow,
|
|
1080
|
+
id: created.workflowKey,
|
|
1081
|
+
workflowKey: created.workflowKey,
|
|
1082
|
+
version: created.version,
|
|
1083
|
+
dbId: created.id,
|
|
1084
|
+
status: created.status ?? "DRAFT"
|
|
1085
|
+
};
|
|
1086
|
+
if (recordFetched(createdWorkflow)) {
|
|
1087
|
+
rememberRevision(created.id, created.revision);
|
|
1011
1088
|
}
|
|
1089
|
+
if (mounted) setWorkflow(createdWorkflow);
|
|
1012
1090
|
}
|
|
1013
1091
|
}
|
|
1014
1092
|
} catch (error) {
|
|
@@ -1018,8 +1096,11 @@ function WorkflowItem({
|
|
|
1018
1096
|
setLoadError(
|
|
1019
1097
|
"The workflow version for this TEST run could not be loaded."
|
|
1020
1098
|
);
|
|
1099
|
+
} else if (reloadPending()) {
|
|
1100
|
+
setReloadFailed(true);
|
|
1101
|
+
releaseLeaseKeptForReload();
|
|
1021
1102
|
} else {
|
|
1022
|
-
setWorkflow(
|
|
1103
|
+
setWorkflow(fetchedCopy() ?? newWorkflow);
|
|
1023
1104
|
}
|
|
1024
1105
|
}
|
|
1025
1106
|
} finally {
|
|
@@ -1042,7 +1123,8 @@ function WorkflowItem({
|
|
|
1042
1123
|
resetWorkflow,
|
|
1043
1124
|
navigate,
|
|
1044
1125
|
loadRunId,
|
|
1045
|
-
retryNonce
|
|
1126
|
+
retryNonce,
|
|
1127
|
+
reloadNonce
|
|
1046
1128
|
// doNodeCheckRef is intentionally omitted — it's a ref (stable by definition)
|
|
1047
1129
|
// and including doNodeCheck here caused infinite re-runs because installedAppIds
|
|
1048
1130
|
// produces a new Set reference on every render.
|
|
@@ -1083,89 +1165,70 @@ function WorkflowItem({
|
|
|
1083
1165
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-foreground/60", children: "Loading workflow..." })
|
|
1084
1166
|
] }) })
|
|
1085
1167
|
);
|
|
1168
|
+
const retryLabel = tr(
|
|
1169
|
+
"fluidgrids.builder.workflowNotFound.retry",
|
|
1170
|
+
"Try again"
|
|
1171
|
+
);
|
|
1172
|
+
const backLabel = tr(
|
|
1173
|
+
"fluidgrids.builder.workflowNotFound.back",
|
|
1174
|
+
"Back to Workflows"
|
|
1175
|
+
);
|
|
1086
1176
|
if (createRefusal?.kind === "failed")
|
|
1087
|
-
return /* @__PURE__ */
|
|
1088
|
-
|
|
1177
|
+
return /* @__PURE__ */ jsx(
|
|
1178
|
+
LoadProblem,
|
|
1089
1179
|
{
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
)
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
type: "button",
|
|
1106
|
-
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
|
|
1107
|
-
onClick: () => {
|
|
1108
|
-
setCreateRefusal(null);
|
|
1109
|
-
setRetryNonce((n) => n + 1);
|
|
1110
|
-
},
|
|
1111
|
-
children: tr("fluidgrids.builder.workflowNotFound.retry", "Try again")
|
|
1112
|
-
}
|
|
1113
|
-
),
|
|
1114
|
-
/* @__PURE__ */ jsx(
|
|
1115
|
-
"button",
|
|
1116
|
-
{
|
|
1117
|
-
type: "button",
|
|
1118
|
-
className: "rounded-md border px-4 py-2 text-sm font-medium text-foreground",
|
|
1119
|
-
onClick: () => navigate("../list", { replace: true }),
|
|
1120
|
-
children: tr(
|
|
1121
|
-
"fluidgrids.builder.workflowNotFound.back",
|
|
1122
|
-
"Back to Workflows"
|
|
1123
|
-
)
|
|
1124
|
-
}
|
|
1125
|
-
)
|
|
1126
|
-
] })
|
|
1127
|
-
]
|
|
1180
|
+
title: tr(
|
|
1181
|
+
"fluidgrids.builder.workflowNotCreated.title",
|
|
1182
|
+
"Workflow not created"
|
|
1183
|
+
),
|
|
1184
|
+
description: tr(
|
|
1185
|
+
"fluidgrids.builder.workflowNotCreated.description",
|
|
1186
|
+
"The new workflow could not be created, so there is nothing to edit yet."
|
|
1187
|
+
),
|
|
1188
|
+
retryLabel,
|
|
1189
|
+
onRetry: () => {
|
|
1190
|
+
setCreateRefusal(null);
|
|
1191
|
+
setRetryNonce((n) => n + 1);
|
|
1192
|
+
},
|
|
1193
|
+
backLabel,
|
|
1194
|
+
onBack: () => navigate("../list", { replace: true })
|
|
1128
1195
|
}
|
|
1129
1196
|
);
|
|
1130
1197
|
if (notFound)
|
|
1131
|
-
return /* @__PURE__ */
|
|
1132
|
-
|
|
1198
|
+
return /* @__PURE__ */ jsx(
|
|
1199
|
+
LoadProblem,
|
|
1133
1200
|
{
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
1166
|
-
)
|
|
1167
|
-
] })
|
|
1168
|
-
]
|
|
1201
|
+
title: tr(
|
|
1202
|
+
"fluidgrids.builder.workflowNotFound.title",
|
|
1203
|
+
"Workflow not found"
|
|
1204
|
+
),
|
|
1205
|
+
description: tr(
|
|
1206
|
+
"fluidgrids.builder.workflowNotFound.description",
|
|
1207
|
+
"No workflow with this key exists in this workspace, or it could not be loaded. Nothing was created."
|
|
1208
|
+
),
|
|
1209
|
+
retryLabel,
|
|
1210
|
+
onRetry: () => setRetryNonce((n) => n + 1),
|
|
1211
|
+
backLabel,
|
|
1212
|
+
onBack: () => navigate("../list")
|
|
1213
|
+
}
|
|
1214
|
+
);
|
|
1215
|
+
if (reloadFailed)
|
|
1216
|
+
return /* @__PURE__ */ jsx(
|
|
1217
|
+
LoadProblem,
|
|
1218
|
+
{
|
|
1219
|
+
testId: "fluidgrids-builder-reload-failed",
|
|
1220
|
+
title: tr(
|
|
1221
|
+
"fluidgrids.builder.reloadFailed.title",
|
|
1222
|
+
"The latest version did not load"
|
|
1223
|
+
),
|
|
1224
|
+
description: tr(
|
|
1225
|
+
"fluidgrids.builder.reloadFailed.description",
|
|
1226
|
+
"The latest saved version of this workflow could not be loaded, so nothing older is shown in its place. Check your connection and try again."
|
|
1227
|
+
),
|
|
1228
|
+
retryLabel,
|
|
1229
|
+
onRetry: () => setRetryNonce((n) => n + 1),
|
|
1230
|
+
backLabel,
|
|
1231
|
+
onBack: () => navigate("../list")
|
|
1169
1232
|
}
|
|
1170
1233
|
);
|
|
1171
1234
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|