@burdenoff/fluidgrids-fe-sdk 2026.1024.2 → 2026.1026.1
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-RF5NR2ND.js → ExecutionDetailPage-EQ6HXXNL.js} +7 -7
- package/dist/{ExecutionsListPage-L447L5LX.js → ExecutionsListPage-ADIHJTMM.js} +7 -7
- package/dist/{WorkflowBuilder-AWCE62C7.js → WorkflowBuilder-BHVJKRDQ.js} +9 -9
- package/dist/{WorkflowsList-QFVCVGRY.js → WorkflowsList-76GI5W5U.js} +7 -7
- package/dist/{chunk-GCOWR7J4.js → chunk-543CP5ZX.js} +1 -1
- package/dist/{chunk-PMQECGSD.js → chunk-54MTXYK7.js} +3 -3
- package/dist/{chunk-VZQSCUD4.js → chunk-75OEGB3L.js} +3 -3
- package/dist/{chunk-GV76OCBP.js → chunk-7ETY5Z7E.js} +4 -4
- package/dist/{chunk-IZMYI6QO.js → chunk-7LJ3DYEG.js} +884 -26
- package/dist/{chunk-L37ZAZE4.js → chunk-AVLMQJV2.js} +2 -2
- package/dist/{chunk-4H7MRDNX.js → chunk-B2KYIXMD.js} +18 -5
- package/dist/{chunk-XFVNTWM2.js → chunk-BNA2HFGB.js} +1 -1
- package/dist/{chunk-XXAVXVBW.js → chunk-BP4WGVSM.js} +1 -1
- package/dist/{chunk-GD7CSKFD.js → chunk-FLKTTSRJ.js} +9 -1
- package/dist/{chunk-S5ZKDRBV.js → chunk-FOBH2IH2.js} +2 -2
- package/dist/{chunk-T7X3HDNX.js → chunk-FWMFZKTI.js} +1 -1
- package/dist/{chunk-3GHYYFBA.js → chunk-L4XUHOOH.js} +5 -5
- package/dist/{chunk-I2DSSBIK.js → chunk-M5WJPAZM.js} +5 -5
- package/dist/{chunk-QIAXIFLW.js → chunk-NOEVRDDJ.js} +2 -2
- package/dist/{chunk-7PC3ZBYU.js → chunk-OAZNRMRR.js} +3 -3
- package/dist/{chunk-7ST3XB36.js → chunk-OIB44CIF.js} +1 -1
- package/dist/{chunk-65DVJILQ.js → chunk-QBHWMRCT.js} +2 -2
- package/dist/{chunk-OQEQ3AIA.js → chunk-RYNCNNTL.js} +1 -1
- package/dist/{chunk-INHBJPVE.js → chunk-VBZ62DJY.js} +1 -1
- package/dist/{chunk-DSBU5MH4.js → chunk-YJ25AFPK.js} +1 -1
- package/dist/executions.js +9 -9
- package/dist/history.js +4 -4
- package/dist/index.d.ts +360 -1
- 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.js +10 -10
- package/dist/workflows-list.js +7 -7
- package/package.json +11 -9
|
@@ -2,16 +2,16 @@ import { deepClone, applyTemplateInputs } from './chunk-GEMNVFPK.js';
|
|
|
2
2
|
import { Input as Input$1 } from './chunk-IEVSFCFS.js';
|
|
3
3
|
import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, DialogFooter } from './chunk-YXMFRQYV.js';
|
|
4
4
|
import { Badge as Badge$1, Button } from './chunk-BQXVT32O.js';
|
|
5
|
-
import { QuotaExhaustedDialog } from './chunk-
|
|
6
|
-
import { EntityTagPicker } from './chunk-
|
|
7
|
-
import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-
|
|
5
|
+
import { QuotaExhaustedDialog } from './chunk-543CP5ZX.js';
|
|
6
|
+
import { EntityTagPicker } from './chunk-BNA2HFGB.js';
|
|
7
|
+
import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-FOBH2IH2.js';
|
|
8
8
|
import { FluidGridsDocsLink } from './chunk-4VJ3MDOV.js';
|
|
9
|
-
import { RUNS_QUOTA_NAME, throwIfResultError, useFlowStore, BILLING_PLANS_PATH, emitUpgradeClicked, FluidGridsContext, emitWorkflowCreated, emitTemplateUsed, ensureNodeConfigsLoaded, NODE_CONFIGS, registerWorkflowNodeTypes, emitNodeInstalled, useNodeExecution, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useIsValidConnection, refetchStoreNodes, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, SdkPermissionButton, FLUIDGRIDS_PERMISSIONS, STICKY_NOTE_TYPE, fieldsFromValue, getNodeDetail, useFluidGridsAnalytics, buildOperationSeed, isNodeTrigger, buildStickyNode, fieldsFromIO, ConnectionSelector, structuredParameterType, nodeAccent, NodeTypeIcon, NODES_METADATA, resolveNodeOperation, declaredOutputFields, pathToExpression, ExpressionEditor, formatParameterValue, parseParameterValue, isNodeConfigsInitialized, resolveUiSpec, isImageIcon, NODES, synchronizeOperationUpdate, NodePropertyPanel, openRunQuotaUpgradePrompt, describeOperationError, isTriggerOperation, canRenderOperationPanel, resolveOperationName, resolveInputHandles } from './chunk-
|
|
9
|
+
import { RUNS_QUOTA_NAME, throwIfResultError, useFlowStore, BILLING_PLANS_PATH, emitUpgradeClicked, FluidGridsContext, emitWorkflowCreated, emitTemplateUsed, ensureNodeConfigsLoaded, NODE_CONFIGS, registerWorkflowNodeTypes, emitNodeInstalled, useNodeExecution, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useIsValidConnection, refetchStoreNodes, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, SdkPermissionButton, FLUIDGRIDS_PERMISSIONS, STICKY_NOTE_TYPE, fieldsFromValue, getNodeDetail, useFluidGridsAnalytics, buildOperationSeed, isNodeTrigger, buildStickyNode, fieldsFromIO, ConnectionSelector, structuredParameterType, nodeAccent, NodeTypeIcon, NODES_METADATA, resolveNodeOperation, declaredOutputFields, pathToExpression, ExpressionEditor, formatParameterValue, parseParameterValue, isNodeConfigsInitialized, resolveUiSpec, isImageIcon, NODES, synchronizeOperationUpdate, NodePropertyPanel, openRunQuotaUpgradePrompt, describeOperationError, isTriggerOperation, canRenderOperationPanel, resolveOperationName, resolveInputHandles } from './chunk-FWMFZKTI.js';
|
|
10
10
|
import { cn } from './chunk-JL7CASN5.js';
|
|
11
11
|
import { getGlobalStoreClient } from './chunk-PXIFUMLA.js';
|
|
12
12
|
import { getFluidGridsConfig } from './chunk-CY6KX4RG.js';
|
|
13
13
|
import { GetMyNodeInstallationsDocument, BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument, GetNodeInstallableVersionsDocument } from './chunk-WBH2XEWO.js';
|
|
14
|
-
import { WorkspaceRunsQuotaDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, WorkflowGenerationTemplatesDocument, WorkflowGenerationDocument, GenerateWorkflowFromPromptDocument, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-
|
|
14
|
+
import { WorkspaceRunsQuotaDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, WorkflowGenerationTemplatesDocument, WorkflowGenerationDocument, GenerateWorkflowFromPromptDocument, WorkflowEnvironmentsDocument, WorkflowPromotionRequestsDocument, DeployWorkflowVersionToDevDocument, RequestWorkflowPromotionDocument, ApproveWorkflowPromotionDocument, RejectWorkflowPromotionDocument, CancelWorkflowPromotionDocument, UpdateWorkflowEnvironmentPolicyDocument, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-FLKTTSRJ.js';
|
|
15
15
|
import { useTr } from './chunk-UULVIT25.js';
|
|
16
16
|
import { getFluidGridsClient, waitForFluidGridsClient, getFluidGridsClientSafe } from './chunk-NTWG3CJX.js';
|
|
17
17
|
import * as React3 from 'react';
|
|
@@ -19,13 +19,13 @@ import React3__default, { forwardRef, lazy, memo, createContext, useState, useRe
|
|
|
19
19
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
20
20
|
import { gql } from '@apollo/client';
|
|
21
21
|
import { cn as cn$1 } from '@burdenoff/fe-libs/utils';
|
|
22
|
-
import { Card as Card$1, Badge, CardContent as CardContent$1, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Button as Button$1, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, Label, Textarea, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, TooltipProvider, DropdownMenuItem, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, DropdownMenuLabel, DropdownMenuSeparator } from '@burdenoff/fe-libs/ui';
|
|
22
|
+
import { Card as Card$1, Badge, CardContent as CardContent$1, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Button as Button$1, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, Label, Textarea, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, TooltipProvider, Switch, DropdownMenuItem, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, DropdownMenuLabel, DropdownMenuSeparator } from '@burdenoff/fe-libs/ui';
|
|
23
23
|
import { Link, useNavigate, useParams } from 'react-router';
|
|
24
24
|
import { useEventBus } from '@burdenoff/fe-libs/shared/events';
|
|
25
25
|
import { useQuery, useMutation } from '@apollo/client/react';
|
|
26
26
|
import { gql as gql$1 } from '@apollo/client/core';
|
|
27
27
|
import 'jszip';
|
|
28
|
-
import { Sparkles, Star, Download, Eye, Loader2, History, GitCompareArrows, Play, RotateCcw, Trash2,
|
|
28
|
+
import { Sparkles, Star, Download, Eye, Loader2, History, GitCompareArrows, Play, RotateCcw, Trash2, Layers, Upload, Rocket, ArrowRight, Check, X, Undo2, Maximize2, Redo2, LayoutGrid, Keyboard, Plus, GitBranch, AlertCircle, Search, RefreshCw, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, Type, Code, Hash, List, Braces, Workflow, PlusCircle, ChevronDown, ChevronRight, AlertTriangle } from 'lucide-react';
|
|
29
29
|
import { Icon } from '@iconify/react';
|
|
30
30
|
import { toast } from 'sonner';
|
|
31
31
|
import { useShallow, shallow } from 'zustand/shallow';
|
|
@@ -6456,8 +6456,8 @@ var reducer = (state, action) => {
|
|
|
6456
6456
|
if (toastId) {
|
|
6457
6457
|
addToRemoveQueue(toastId);
|
|
6458
6458
|
} else {
|
|
6459
|
-
state.toasts.forEach((
|
|
6460
|
-
addToRemoveQueue(
|
|
6459
|
+
state.toasts.forEach((toast12) => {
|
|
6460
|
+
addToRemoveQueue(toast12.id);
|
|
6461
6461
|
});
|
|
6462
6462
|
}
|
|
6463
6463
|
return {
|
|
@@ -7833,7 +7833,7 @@ function VisualMapperContent({
|
|
|
7833
7833
|
mapping,
|
|
7834
7834
|
onMappingChange
|
|
7835
7835
|
}) {
|
|
7836
|
-
const { toast:
|
|
7836
|
+
const { toast: toast12 } = useToast();
|
|
7837
7837
|
const tr = useTr();
|
|
7838
7838
|
const reactFlowWrapper = useRef(null);
|
|
7839
7839
|
const [selectedSourceNode, setSelectedSourceNode] = useState(null);
|
|
@@ -7853,7 +7853,7 @@ function VisualMapperContent({
|
|
|
7853
7853
|
targetOperation
|
|
7854
7854
|
);
|
|
7855
7855
|
if (generatedNodes.length === 0) {
|
|
7856
|
-
|
|
7856
|
+
toast12({
|
|
7857
7857
|
title: tr(
|
|
7858
7858
|
"fluidgrids.builder.visualMapper.noFieldsFoundTitle",
|
|
7859
7859
|
"No fields found"
|
|
@@ -7879,7 +7879,7 @@ function VisualMapperContent({
|
|
|
7879
7879
|
targetNode,
|
|
7880
7880
|
targetOperation,
|
|
7881
7881
|
setNodes,
|
|
7882
|
-
|
|
7882
|
+
toast12,
|
|
7883
7883
|
tr
|
|
7884
7884
|
]);
|
|
7885
7885
|
useEffect(() => {
|
|
@@ -7986,7 +7986,7 @@ function VisualMapperContent({
|
|
|
7986
7986
|
}
|
|
7987
7987
|
onMappingChange(updatedMapping);
|
|
7988
7988
|
if (isCompatible) {
|
|
7989
|
-
|
|
7989
|
+
toast12({
|
|
7990
7990
|
title: tr(
|
|
7991
7991
|
"fluidgrids.builder.visualMapper.mappingCreatedTitle",
|
|
7992
7992
|
"Mapping created"
|
|
@@ -7994,7 +7994,7 @@ function VisualMapperContent({
|
|
|
7994
7994
|
description: `Mapped ${sourcePath} (${sourceType}) to ${targetPath} (${targetType})`
|
|
7995
7995
|
});
|
|
7996
7996
|
} else {
|
|
7997
|
-
|
|
7997
|
+
toast12({
|
|
7998
7998
|
title: tr(
|
|
7999
7999
|
"fluidgrids.builder.visualMapper.typeMismatchTitle",
|
|
8000
8000
|
"Type mismatch warning"
|
|
@@ -8004,7 +8004,7 @@ function VisualMapperContent({
|
|
|
8004
8004
|
});
|
|
8005
8005
|
}
|
|
8006
8006
|
} else {
|
|
8007
|
-
|
|
8007
|
+
toast12({
|
|
8008
8008
|
title: tr(
|
|
8009
8009
|
"fluidgrids.builder.visualMapper.invalidMappingTitle",
|
|
8010
8010
|
"Invalid mapping"
|
|
@@ -8017,7 +8017,7 @@ function VisualMapperContent({
|
|
|
8017
8017
|
});
|
|
8018
8018
|
}
|
|
8019
8019
|
},
|
|
8020
|
-
[nodes, mapping, onMappingChange,
|
|
8020
|
+
[nodes, mapping, onMappingChange, toast12, tr, setEdges]
|
|
8021
8021
|
);
|
|
8022
8022
|
const onEdgeDelete = useCallback(
|
|
8023
8023
|
(edge) => {
|
|
@@ -8074,7 +8074,7 @@ function VisualMapperContent({
|
|
|
8074
8074
|
const handleSaveMappingDialog = (expression, targetFieldName) => {
|
|
8075
8075
|
const targetPath = targetFieldName || selectedTargetNode?.data?.path;
|
|
8076
8076
|
if (!targetPath) {
|
|
8077
|
-
|
|
8077
|
+
toast12({
|
|
8078
8078
|
title: tr(
|
|
8079
8079
|
"fluidgrids.builder.visualMapper.noTargetFieldTitle",
|
|
8080
8080
|
"No target field specified"
|
|
@@ -8106,7 +8106,7 @@ function VisualMapperContent({
|
|
|
8106
8106
|
}
|
|
8107
8107
|
onMappingChange(updatedMapping);
|
|
8108
8108
|
const mappingType = detectMappingType(expression);
|
|
8109
|
-
|
|
8109
|
+
toast12({
|
|
8110
8110
|
title: `${mappingType.charAt(0).toUpperCase() + mappingType.slice(1)} mapping created`,
|
|
8111
8111
|
description: `${tr("fluidgrids.builder.visualMapper.appliedMappingTo", "Applied mapping to")} ${targetPath}`
|
|
8112
8112
|
});
|
|
@@ -8405,7 +8405,7 @@ function MappingEditor({
|
|
|
8405
8405
|
setEdges,
|
|
8406
8406
|
edgeId
|
|
8407
8407
|
}) {
|
|
8408
|
-
const { toast:
|
|
8408
|
+
const { toast: toast12 } = useToast();
|
|
8409
8409
|
const tr = useTr();
|
|
8410
8410
|
const [mappingJson, setMappingJson] = useState({});
|
|
8411
8411
|
const [jsonDataString, setJsonDataString] = useState(
|
|
@@ -8529,7 +8529,7 @@ function MappingEditor({
|
|
|
8529
8529
|
const handleSaveMapping = () => {
|
|
8530
8530
|
try {
|
|
8531
8531
|
checkJsonValidity();
|
|
8532
|
-
|
|
8532
|
+
toast12({
|
|
8533
8533
|
title: tr(
|
|
8534
8534
|
"fluidgrids.builder.mappingEditor.mappingSavedTitle",
|
|
8535
8535
|
"Mapping saved"
|
|
@@ -8540,7 +8540,7 @@ function MappingEditor({
|
|
|
8540
8540
|
)
|
|
8541
8541
|
});
|
|
8542
8542
|
} catch (error) {
|
|
8543
|
-
|
|
8543
|
+
toast12({
|
|
8544
8544
|
title: tr(
|
|
8545
8545
|
"fluidgrids.builder.mappingEditor.errorSavingTitle",
|
|
8546
8546
|
"Error saving mapping"
|
|
@@ -8559,7 +8559,7 @@ function MappingEditor({
|
|
|
8559
8559
|
const parsedData = checkJsonValidity();
|
|
8560
8560
|
const result = await applyMapping(parsedData, sampleInput);
|
|
8561
8561
|
setPreviewOutput(result);
|
|
8562
|
-
|
|
8562
|
+
toast12({
|
|
8563
8563
|
title: tr(
|
|
8564
8564
|
"fluidgrids.builder.mappingEditor.mappingTestedTitle",
|
|
8565
8565
|
"Mapping tested"
|
|
@@ -8571,7 +8571,7 @@ function MappingEditor({
|
|
|
8571
8571
|
});
|
|
8572
8572
|
} catch (error) {
|
|
8573
8573
|
console.error("Test mapping error:", error);
|
|
8574
|
-
|
|
8574
|
+
toast12({
|
|
8575
8575
|
title: tr(
|
|
8576
8576
|
"fluidgrids.builder.mappingEditor.mappingTestFailedTitle",
|
|
8577
8577
|
"Mapping test failed"
|
|
@@ -19726,6 +19726,862 @@ function VersionHistoryPanel({ className }) {
|
|
|
19726
19726
|
)
|
|
19727
19727
|
] });
|
|
19728
19728
|
}
|
|
19729
|
+
var HISTORY_LIMIT = 20;
|
|
19730
|
+
function messageOf(error) {
|
|
19731
|
+
return error instanceof Error ? error.message : String(error);
|
|
19732
|
+
}
|
|
19733
|
+
function useWorkflowEnvironments(workflowKey) {
|
|
19734
|
+
const [view, setView] = useState(null);
|
|
19735
|
+
const [history, setHistory] = useState([]);
|
|
19736
|
+
const [loading, setLoading] = useState(false);
|
|
19737
|
+
const [error, setError] = useState(null);
|
|
19738
|
+
const keyRef = useRef(workflowKey);
|
|
19739
|
+
keyRef.current = workflowKey;
|
|
19740
|
+
const refetch = useCallback(async () => {
|
|
19741
|
+
if (!workflowKey) return;
|
|
19742
|
+
setLoading(true);
|
|
19743
|
+
setError(null);
|
|
19744
|
+
try {
|
|
19745
|
+
const client = getFluidGridsClient();
|
|
19746
|
+
const [environments, promotions] = await Promise.all([
|
|
19747
|
+
client.query({
|
|
19748
|
+
query: WorkflowEnvironmentsDocument,
|
|
19749
|
+
variables: { workflowKey },
|
|
19750
|
+
fetchPolicy: "network-only"
|
|
19751
|
+
}),
|
|
19752
|
+
client.query({
|
|
19753
|
+
query: WorkflowPromotionRequestsDocument,
|
|
19754
|
+
variables: { workflowKey, limit: HISTORY_LIMIT },
|
|
19755
|
+
fetchPolicy: "network-only"
|
|
19756
|
+
})
|
|
19757
|
+
]);
|
|
19758
|
+
throwIfResultError(environments);
|
|
19759
|
+
throwIfResultError(promotions);
|
|
19760
|
+
if (keyRef.current !== workflowKey) return;
|
|
19761
|
+
setView(environments.data?.workflowEnvironments ?? null);
|
|
19762
|
+
setHistory(promotions.data?.workflowPromotionRequests ?? []);
|
|
19763
|
+
} catch (err) {
|
|
19764
|
+
if (keyRef.current === workflowKey) setError(messageOf(err));
|
|
19765
|
+
} finally {
|
|
19766
|
+
if (keyRef.current === workflowKey) setLoading(false);
|
|
19767
|
+
}
|
|
19768
|
+
}, [workflowKey]);
|
|
19769
|
+
useEffect(() => {
|
|
19770
|
+
setView(null);
|
|
19771
|
+
setHistory([]);
|
|
19772
|
+
}, [workflowKey]);
|
|
19773
|
+
const deployToDev = useCallback(
|
|
19774
|
+
async (version) => {
|
|
19775
|
+
const result = await getFluidGridsClient().mutate({
|
|
19776
|
+
mutation: DeployWorkflowVersionToDevDocument,
|
|
19777
|
+
variables: { workflowKey, version }
|
|
19778
|
+
});
|
|
19779
|
+
throwIfResultError(result);
|
|
19780
|
+
await refetch();
|
|
19781
|
+
},
|
|
19782
|
+
[workflowKey, refetch]
|
|
19783
|
+
);
|
|
19784
|
+
const requestPromotion = useCallback(
|
|
19785
|
+
async (target, note) => {
|
|
19786
|
+
const result = await getFluidGridsClient().mutate({
|
|
19787
|
+
mutation: RequestWorkflowPromotionDocument,
|
|
19788
|
+
variables: {
|
|
19789
|
+
input: {
|
|
19790
|
+
workflowKey,
|
|
19791
|
+
toEnvironment: target,
|
|
19792
|
+
note: note?.trim() || void 0
|
|
19793
|
+
}
|
|
19794
|
+
}
|
|
19795
|
+
});
|
|
19796
|
+
throwIfResultError(result);
|
|
19797
|
+
const request = result.data?.requestWorkflowPromotion;
|
|
19798
|
+
if (!request) throw new Error("The promotion request returned no result");
|
|
19799
|
+
await refetch();
|
|
19800
|
+
return request;
|
|
19801
|
+
},
|
|
19802
|
+
[workflowKey, refetch]
|
|
19803
|
+
);
|
|
19804
|
+
const approve = useCallback(
|
|
19805
|
+
async (id, note) => {
|
|
19806
|
+
const result = await getFluidGridsClient().mutate({
|
|
19807
|
+
mutation: ApproveWorkflowPromotionDocument,
|
|
19808
|
+
variables: { id, note: note?.trim() || void 0 }
|
|
19809
|
+
});
|
|
19810
|
+
throwIfResultError(result);
|
|
19811
|
+
await refetch();
|
|
19812
|
+
},
|
|
19813
|
+
[refetch]
|
|
19814
|
+
);
|
|
19815
|
+
const reject = useCallback(
|
|
19816
|
+
async (id, note) => {
|
|
19817
|
+
const result = await getFluidGridsClient().mutate({
|
|
19818
|
+
mutation: RejectWorkflowPromotionDocument,
|
|
19819
|
+
variables: { id, note: note?.trim() || void 0 }
|
|
19820
|
+
});
|
|
19821
|
+
throwIfResultError(result);
|
|
19822
|
+
await refetch();
|
|
19823
|
+
},
|
|
19824
|
+
[refetch]
|
|
19825
|
+
);
|
|
19826
|
+
const cancel = useCallback(
|
|
19827
|
+
async (id) => {
|
|
19828
|
+
const result = await getFluidGridsClient().mutate({
|
|
19829
|
+
mutation: CancelWorkflowPromotionDocument,
|
|
19830
|
+
variables: { id }
|
|
19831
|
+
});
|
|
19832
|
+
throwIfResultError(result);
|
|
19833
|
+
await refetch();
|
|
19834
|
+
},
|
|
19835
|
+
[refetch]
|
|
19836
|
+
);
|
|
19837
|
+
const updatePolicy = useCallback(
|
|
19838
|
+
async (changes) => {
|
|
19839
|
+
const result = await getFluidGridsClient().mutate({
|
|
19840
|
+
mutation: UpdateWorkflowEnvironmentPolicyDocument,
|
|
19841
|
+
variables: { input: changes }
|
|
19842
|
+
});
|
|
19843
|
+
throwIfResultError(result);
|
|
19844
|
+
await refetch();
|
|
19845
|
+
},
|
|
19846
|
+
[refetch]
|
|
19847
|
+
);
|
|
19848
|
+
return {
|
|
19849
|
+
view,
|
|
19850
|
+
history,
|
|
19851
|
+
loading,
|
|
19852
|
+
error,
|
|
19853
|
+
refetch,
|
|
19854
|
+
deployToDev,
|
|
19855
|
+
requestPromotion,
|
|
19856
|
+
approve,
|
|
19857
|
+
reject,
|
|
19858
|
+
cancel,
|
|
19859
|
+
updatePolicy
|
|
19860
|
+
};
|
|
19861
|
+
}
|
|
19862
|
+
|
|
19863
|
+
// src/builder/lib/workflow-environments.ts
|
|
19864
|
+
var ENVIRONMENT_ORDER = [
|
|
19865
|
+
"DEV",
|
|
19866
|
+
"STAGING",
|
|
19867
|
+
"PROD"
|
|
19868
|
+
];
|
|
19869
|
+
function promotionTargetOf(environment) {
|
|
19870
|
+
if (environment === "DEV") return "STAGING";
|
|
19871
|
+
if (environment === "STAGING") return "PROD";
|
|
19872
|
+
return null;
|
|
19873
|
+
}
|
|
19874
|
+
function promotionSourceOf(target) {
|
|
19875
|
+
return target === "STAGING" ? "DEV" : "STAGING";
|
|
19876
|
+
}
|
|
19877
|
+
function promotionNeedsApproval(policy, target) {
|
|
19878
|
+
return target === "PROD" ? policy.requireProdApproval : policy.requireStagingApproval;
|
|
19879
|
+
}
|
|
19880
|
+
function promotionBlocker(environments, pending, target) {
|
|
19881
|
+
const source = environments.find(
|
|
19882
|
+
(state) => state.environment === promotionSourceOf(target)
|
|
19883
|
+
);
|
|
19884
|
+
const current = environments.find((state) => state.environment === target);
|
|
19885
|
+
if (!source?.version || !source.workflowDefinitionId) return "sourceEmpty";
|
|
19886
|
+
if (!source.available) return "sourceUnavailable";
|
|
19887
|
+
if (current?.available && current.workflowDefinitionId === source.workflowDefinitionId) {
|
|
19888
|
+
return "alreadyDeployed";
|
|
19889
|
+
}
|
|
19890
|
+
if (pending.some((request) => request.toEnvironment === target)) {
|
|
19891
|
+
return "pending";
|
|
19892
|
+
}
|
|
19893
|
+
return null;
|
|
19894
|
+
}
|
|
19895
|
+
function orderEnvironments(environments) {
|
|
19896
|
+
return [...environments].sort(
|
|
19897
|
+
(a, b) => ENVIRONMENT_ORDER.indexOf(a.environment) - ENVIRONMENT_ORDER.indexOf(b.environment)
|
|
19898
|
+
);
|
|
19899
|
+
}
|
|
19900
|
+
var NOTE_MAX = 2e3;
|
|
19901
|
+
function EnvironmentsPanel({
|
|
19902
|
+
className,
|
|
19903
|
+
compact = false
|
|
19904
|
+
}) {
|
|
19905
|
+
const tr = useTr();
|
|
19906
|
+
const params = useParams();
|
|
19907
|
+
const workflowKey = params?.id ?? "";
|
|
19908
|
+
const currentVersion = params?.version ?? "";
|
|
19909
|
+
const setWorkflow = useFlowStore((s) => s.actions.setWorkflow);
|
|
19910
|
+
const openStatus = useFlowStore((s) => s.workflow.status);
|
|
19911
|
+
const {
|
|
19912
|
+
view,
|
|
19913
|
+
history,
|
|
19914
|
+
loading,
|
|
19915
|
+
error,
|
|
19916
|
+
refetch,
|
|
19917
|
+
deployToDev,
|
|
19918
|
+
requestPromotion,
|
|
19919
|
+
approve,
|
|
19920
|
+
reject,
|
|
19921
|
+
cancel,
|
|
19922
|
+
updatePolicy
|
|
19923
|
+
} = useWorkflowEnvironments(workflowKey);
|
|
19924
|
+
const [busy, setBusy] = useState(null);
|
|
19925
|
+
const [dialog, setDialog] = useState(null);
|
|
19926
|
+
const [note, setNote] = useState("");
|
|
19927
|
+
const envLabel = (environment) => {
|
|
19928
|
+
if (environment === "DEV")
|
|
19929
|
+
return tr("fluidgrids.builder.environments.dev", "Development");
|
|
19930
|
+
if (environment === "STAGING")
|
|
19931
|
+
return tr("fluidgrids.builder.environments.staging", "Staging");
|
|
19932
|
+
return tr("fluidgrids.builder.environments.prod", "Production");
|
|
19933
|
+
};
|
|
19934
|
+
const blockerText = (blocker, source) => {
|
|
19935
|
+
switch (blocker) {
|
|
19936
|
+
case "sourceEmpty":
|
|
19937
|
+
return `${tr("fluidgrids.builder.environments.blockedEmpty", "Nothing is deployed to")} ${envLabel(source)}`;
|
|
19938
|
+
case "sourceUnavailable":
|
|
19939
|
+
return tr(
|
|
19940
|
+
"fluidgrids.builder.environments.blockedDeleted",
|
|
19941
|
+
"The deployed version was deleted"
|
|
19942
|
+
);
|
|
19943
|
+
case "alreadyDeployed":
|
|
19944
|
+
return tr(
|
|
19945
|
+
"fluidgrids.builder.environments.blockedSame",
|
|
19946
|
+
"Already deployed there"
|
|
19947
|
+
);
|
|
19948
|
+
default:
|
|
19949
|
+
return tr(
|
|
19950
|
+
"fluidgrids.builder.environments.blockedPending",
|
|
19951
|
+
"A promotion is already waiting for approval"
|
|
19952
|
+
);
|
|
19953
|
+
}
|
|
19954
|
+
};
|
|
19955
|
+
const config = getFluidGridsConfig();
|
|
19956
|
+
const actorInputs = useMemo(() => {
|
|
19957
|
+
const ids = /* @__PURE__ */ new Set();
|
|
19958
|
+
for (const state of view?.environments ?? []) {
|
|
19959
|
+
if (state.deployedById) ids.add(state.deployedById);
|
|
19960
|
+
}
|
|
19961
|
+
for (const request of view?.pendingPromotions ?? []) {
|
|
19962
|
+
ids.add(request.requestedById);
|
|
19963
|
+
}
|
|
19964
|
+
for (const item of history) {
|
|
19965
|
+
ids.add(item.requestedById);
|
|
19966
|
+
if (item.reviewedById) ids.add(item.reviewedById);
|
|
19967
|
+
}
|
|
19968
|
+
return [...ids].map((actorId) => ({ actorId, actorType: "user" }));
|
|
19969
|
+
}, [view, history]);
|
|
19970
|
+
const actorProfiles = useActorProfiles(actorInputs, {
|
|
19971
|
+
workspaceId: config.workspaceId || void 0,
|
|
19972
|
+
orgId: config.organizationId,
|
|
19973
|
+
authToken: config.authToken
|
|
19974
|
+
});
|
|
19975
|
+
const nameOf = (actorId) => {
|
|
19976
|
+
if (!actorId) return null;
|
|
19977
|
+
return actorProfiles[actorId]?.displayName ?? buildActorFallback({ actorId, actorType: "user" }).displayName;
|
|
19978
|
+
};
|
|
19979
|
+
const environments = orderEnvironments(view?.environments ?? []);
|
|
19980
|
+
const pending = view?.pendingPromotions ?? [];
|
|
19981
|
+
const policy = view?.policy;
|
|
19982
|
+
const dev = environments.find((state) => state.environment === "DEV");
|
|
19983
|
+
const afterProdChange = (promotedVersion) => {
|
|
19984
|
+
if (promotedVersion === currentVersion) {
|
|
19985
|
+
setWorkflow({ status: "ACTIVE" });
|
|
19986
|
+
} else if (openStatus === "ACTIVE") {
|
|
19987
|
+
setWorkflow({ status: "ARCHIVED" });
|
|
19988
|
+
}
|
|
19989
|
+
};
|
|
19990
|
+
const run = async (key, action, errorTitle) => {
|
|
19991
|
+
setBusy(key);
|
|
19992
|
+
try {
|
|
19993
|
+
await action();
|
|
19994
|
+
} catch (err) {
|
|
19995
|
+
toast.error(errorTitle, {
|
|
19996
|
+
description: err instanceof Error ? err.message : String(err)
|
|
19997
|
+
});
|
|
19998
|
+
} finally {
|
|
19999
|
+
setBusy(null);
|
|
20000
|
+
}
|
|
20001
|
+
};
|
|
20002
|
+
const handleDeployToDev = () => run(
|
|
20003
|
+
"deploy",
|
|
20004
|
+
async () => {
|
|
20005
|
+
await deployToDev(currentVersion);
|
|
20006
|
+
toast.success(
|
|
20007
|
+
`${currentVersion} ${tr("fluidgrids.builder.environments.deployedToDev", "deployed to Development")}`,
|
|
20008
|
+
{ dismissible: true }
|
|
20009
|
+
);
|
|
20010
|
+
},
|
|
20011
|
+
tr(
|
|
20012
|
+
"fluidgrids.builder.environments.deployError",
|
|
20013
|
+
"Failed to deploy to Development"
|
|
20014
|
+
)
|
|
20015
|
+
);
|
|
20016
|
+
const handleConfirmDialog = async () => {
|
|
20017
|
+
if (!dialog) return;
|
|
20018
|
+
const current = dialog;
|
|
20019
|
+
const text = note;
|
|
20020
|
+
setDialog(null);
|
|
20021
|
+
setNote("");
|
|
20022
|
+
if (current.kind === "promote") {
|
|
20023
|
+
await run(
|
|
20024
|
+
`promote:${current.target}`,
|
|
20025
|
+
async () => {
|
|
20026
|
+
const request = await requestPromotion(current.target, text);
|
|
20027
|
+
if (request.status === "PENDING") {
|
|
20028
|
+
toast.success(
|
|
20029
|
+
tr(
|
|
20030
|
+
"fluidgrids.builder.environments.requested",
|
|
20031
|
+
"Promotion requested"
|
|
20032
|
+
),
|
|
20033
|
+
{
|
|
20034
|
+
description: `${request.version} \u2192 ${envLabel(current.target)} ${tr("fluidgrids.builder.environments.awaitingApproval", "is waiting for approval")}`,
|
|
20035
|
+
dismissible: true
|
|
20036
|
+
}
|
|
20037
|
+
);
|
|
20038
|
+
} else {
|
|
20039
|
+
toast.success(
|
|
20040
|
+
`${request.version} ${tr("fluidgrids.builder.environments.promotedTo", "promoted to")} ${envLabel(current.target)}`,
|
|
20041
|
+
{ dismissible: true }
|
|
20042
|
+
);
|
|
20043
|
+
if (current.target === "PROD") afterProdChange(request.version);
|
|
20044
|
+
}
|
|
20045
|
+
},
|
|
20046
|
+
tr("fluidgrids.builder.environments.promoteError", "Promotion failed")
|
|
20047
|
+
);
|
|
20048
|
+
return;
|
|
20049
|
+
}
|
|
20050
|
+
if (current.kind === "approve") {
|
|
20051
|
+
await run(
|
|
20052
|
+
`approve:${current.id}`,
|
|
20053
|
+
async () => {
|
|
20054
|
+
await approve(current.id, text);
|
|
20055
|
+
toast.success(
|
|
20056
|
+
`${current.label} ${tr("fluidgrids.builder.environments.approved", "approved and deployed")}`,
|
|
20057
|
+
{ dismissible: true }
|
|
20058
|
+
);
|
|
20059
|
+
if (current.target === "PROD") afterProdChange(current.version);
|
|
20060
|
+
},
|
|
20061
|
+
tr("fluidgrids.builder.environments.approveError", "Approval failed")
|
|
20062
|
+
);
|
|
20063
|
+
return;
|
|
20064
|
+
}
|
|
20065
|
+
await run(
|
|
20066
|
+
`reject:${current.id}`,
|
|
20067
|
+
async () => {
|
|
20068
|
+
await reject(current.id, text);
|
|
20069
|
+
toast.success(
|
|
20070
|
+
`${current.label} ${tr("fluidgrids.builder.environments.rejected", "rejected")}`,
|
|
20071
|
+
{ dismissible: true }
|
|
20072
|
+
);
|
|
20073
|
+
},
|
|
20074
|
+
tr("fluidgrids.builder.environments.rejectError", "Rejection failed")
|
|
20075
|
+
);
|
|
20076
|
+
};
|
|
20077
|
+
const handleCancel = (id) => run(
|
|
20078
|
+
`cancel:${id}`,
|
|
20079
|
+
async () => {
|
|
20080
|
+
await cancel(id);
|
|
20081
|
+
toast.success(
|
|
20082
|
+
tr(
|
|
20083
|
+
"fluidgrids.builder.environments.canceled",
|
|
20084
|
+
"Promotion request withdrawn"
|
|
20085
|
+
),
|
|
20086
|
+
{ dismissible: true }
|
|
20087
|
+
);
|
|
20088
|
+
},
|
|
20089
|
+
tr(
|
|
20090
|
+
"fluidgrids.builder.environments.cancelError",
|
|
20091
|
+
"Could not withdraw the request"
|
|
20092
|
+
)
|
|
20093
|
+
);
|
|
20094
|
+
const handlePolicy = (changes) => run(
|
|
20095
|
+
"policy",
|
|
20096
|
+
async () => {
|
|
20097
|
+
await updatePolicy(changes);
|
|
20098
|
+
toast.success(
|
|
20099
|
+
tr(
|
|
20100
|
+
"fluidgrids.builder.environments.policySaved",
|
|
20101
|
+
"Promotion policy saved"
|
|
20102
|
+
),
|
|
20103
|
+
{ dismissible: true }
|
|
20104
|
+
);
|
|
20105
|
+
},
|
|
20106
|
+
tr(
|
|
20107
|
+
"fluidgrids.builder.environments.policyError",
|
|
20108
|
+
"Could not save the promotion policy"
|
|
20109
|
+
)
|
|
20110
|
+
);
|
|
20111
|
+
const statusVariant = (status) => {
|
|
20112
|
+
if (status === "APPLIED") return "default";
|
|
20113
|
+
if (status === "PENDING") return "secondary";
|
|
20114
|
+
if (status === "REJECTED") return "destructive";
|
|
20115
|
+
return "outline";
|
|
20116
|
+
};
|
|
20117
|
+
const dialogTitle = (() => {
|
|
20118
|
+
if (!dialog) return "";
|
|
20119
|
+
if (dialog.kind === "promote") {
|
|
20120
|
+
const needsApproval = policy ? promotionNeedsApproval(policy, dialog.target) : true;
|
|
20121
|
+
return needsApproval ? `${tr("fluidgrids.builder.environments.requestTitle", "Request promotion to")} ${envLabel(dialog.target)}` : `${tr("fluidgrids.builder.environments.promoteTitle", "Promote to")} ${envLabel(dialog.target)}`;
|
|
20122
|
+
}
|
|
20123
|
+
return dialog.kind === "approve" ? `${tr("fluidgrids.builder.environments.approveTitle", "Approve")} ${dialog.label}` : `${tr("fluidgrids.builder.environments.rejectTitle", "Reject")} ${dialog.label}`;
|
|
20124
|
+
})();
|
|
20125
|
+
const dialogBody = (() => {
|
|
20126
|
+
if (!dialog) return "";
|
|
20127
|
+
if (dialog.kind === "promote") {
|
|
20128
|
+
const source = dialog.target === "PROD" ? "STAGING" : "DEV";
|
|
20129
|
+
const version = environments.find((state) => state.environment === source)?.version ?? "";
|
|
20130
|
+
const needsApproval = policy ? promotionNeedsApproval(policy, dialog.target) : true;
|
|
20131
|
+
const base = `${version} ${tr("fluidgrids.builder.environments.moves", "moves from")} ${envLabel(source)} ${tr("fluidgrids.builder.environments.to", "to")} ${envLabel(dialog.target)}.`;
|
|
20132
|
+
const prodNote = dialog.target === "PROD" ? ` ${tr("fluidgrids.builder.environments.prodNote", "In Production it becomes the active version that webhooks, schedules and other triggers run.")}` : "";
|
|
20133
|
+
const gate = needsApproval ? ` ${tr("fluidgrids.builder.environments.gateNote", "The workspace policy holds this promotion until someone with publish rights approves it.")}` : "";
|
|
20134
|
+
return base + prodNote + gate;
|
|
20135
|
+
}
|
|
20136
|
+
return dialog.kind === "approve" ? tr(
|
|
20137
|
+
"fluidgrids.builder.environments.approveBody",
|
|
20138
|
+
"Approving deploys the version to its target environment now. A production promotion makes it the active version."
|
|
20139
|
+
) : tr(
|
|
20140
|
+
"fluidgrids.builder.environments.rejectBody",
|
|
20141
|
+
"The version stays where it is. The requester can ask again later."
|
|
20142
|
+
);
|
|
20143
|
+
})();
|
|
20144
|
+
return /* @__PURE__ */ jsxs(Sheet, { onOpenChange: (open) => open && void refetch(), children: [
|
|
20145
|
+
/* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
20146
|
+
Button$1,
|
|
20147
|
+
{
|
|
20148
|
+
"data-tour": "fluidgrids-builder-environments",
|
|
20149
|
+
variant: "outline",
|
|
20150
|
+
size: compact ? "icon" : "sm",
|
|
20151
|
+
className: cn$1(!compact && "flex gap-1", className),
|
|
20152
|
+
"aria-label": tr(
|
|
20153
|
+
"fluidgrids.builder.environments.triggerButton",
|
|
20154
|
+
"Environments"
|
|
20155
|
+
),
|
|
20156
|
+
disabled: !workflowKey,
|
|
20157
|
+
children: [
|
|
20158
|
+
/* @__PURE__ */ jsx(Layers, { className: "size-4" }),
|
|
20159
|
+
!compact && tr("fluidgrids.builder.environments.triggerButton", "Environments")
|
|
20160
|
+
]
|
|
20161
|
+
}
|
|
20162
|
+
) }),
|
|
20163
|
+
/* @__PURE__ */ jsxs(
|
|
20164
|
+
SheetContent,
|
|
20165
|
+
{
|
|
20166
|
+
side: "right",
|
|
20167
|
+
className: "w-[380px] sm:w-[460px] overflow-y-auto",
|
|
20168
|
+
"data-testid": "fluidgrids-environments-panel",
|
|
20169
|
+
children: [
|
|
20170
|
+
/* @__PURE__ */ jsxs(SheetHeader, { children: [
|
|
20171
|
+
/* @__PURE__ */ jsxs(SheetTitle, { className: "flex items-center gap-2", children: [
|
|
20172
|
+
/* @__PURE__ */ jsx(Layers, { className: "size-5" }),
|
|
20173
|
+
tr("fluidgrids.builder.environments.title", "Environments")
|
|
20174
|
+
] }),
|
|
20175
|
+
/* @__PURE__ */ jsx(SheetDescription, { children: tr(
|
|
20176
|
+
"fluidgrids.builder.environments.description",
|
|
20177
|
+
"Move a version from Development to Staging to Production. Production is the active version that automatic triggers run."
|
|
20178
|
+
) })
|
|
20179
|
+
] }),
|
|
20180
|
+
loading && !view ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-8 text-sm text-muted-foreground", children: [
|
|
20181
|
+
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 size-4 animate-spin" }),
|
|
20182
|
+
tr("fluidgrids.builder.environments.loading", "Loading...")
|
|
20183
|
+
] }) : error && !view ? /* @__PURE__ */ jsxs("div", { className: "py-6 text-sm", children: [
|
|
20184
|
+
/* @__PURE__ */ jsx("p", { className: "text-[var(--color-status-error-text)]", children: error }),
|
|
20185
|
+
/* @__PURE__ */ jsx(
|
|
20186
|
+
Button$1,
|
|
20187
|
+
{
|
|
20188
|
+
variant: "outline",
|
|
20189
|
+
size: "sm",
|
|
20190
|
+
className: "mt-3",
|
|
20191
|
+
onClick: () => void refetch(),
|
|
20192
|
+
children: tr("fluidgrids.builder.environments.retry", "Retry")
|
|
20193
|
+
}
|
|
20194
|
+
)
|
|
20195
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-5 pb-6", children: [
|
|
20196
|
+
/* @__PURE__ */ jsx("ol", { className: "space-y-2", "aria-label": "Environments", children: environments.map((state) => {
|
|
20197
|
+
const target = promotionTargetOf(state.environment);
|
|
20198
|
+
const blocker = target ? promotionBlocker(environments, pending, target) : null;
|
|
20199
|
+
const needsApproval = target && policy ? promotionNeedsApproval(policy, target) : false;
|
|
20200
|
+
const deployer = nameOf(state.deployedById);
|
|
20201
|
+
return /* @__PURE__ */ jsxs(
|
|
20202
|
+
"li",
|
|
20203
|
+
{
|
|
20204
|
+
className: "rounded-lg border border-border p-3",
|
|
20205
|
+
"data-testid": `fluidgrids-env-${state.environment}`,
|
|
20206
|
+
children: [
|
|
20207
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between gap-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
20208
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: envLabel(state.environment) }),
|
|
20209
|
+
state.version ? /* @__PURE__ */ jsx(
|
|
20210
|
+
Badge,
|
|
20211
|
+
{
|
|
20212
|
+
variant: state.available ? "default" : "outline",
|
|
20213
|
+
className: "h-5 px-1.5 py-0 font-mono text-[10px]",
|
|
20214
|
+
children: state.version
|
|
20215
|
+
}
|
|
20216
|
+
) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: tr(
|
|
20217
|
+
"fluidgrids.builder.environments.empty",
|
|
20218
|
+
"Nothing deployed"
|
|
20219
|
+
) }),
|
|
20220
|
+
state.version === currentVersion && currentVersion !== "" && /* @__PURE__ */ jsx(
|
|
20221
|
+
Badge,
|
|
20222
|
+
{
|
|
20223
|
+
variant: "outline",
|
|
20224
|
+
className: "h-5 border-primary px-1.5 py-0 text-[10px] text-primary",
|
|
20225
|
+
children: tr(
|
|
20226
|
+
"fluidgrids.builder.environments.openVersion",
|
|
20227
|
+
"Open"
|
|
20228
|
+
)
|
|
20229
|
+
}
|
|
20230
|
+
)
|
|
20231
|
+
] }) }),
|
|
20232
|
+
state.version && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: !state.available ? tr(
|
|
20233
|
+
"fluidgrids.builder.environments.deleted",
|
|
20234
|
+
"This version was deleted after it was deployed."
|
|
20235
|
+
) : state.outOfBand ? tr(
|
|
20236
|
+
"fluidgrids.builder.environments.outOfBand",
|
|
20237
|
+
"Activated directly, not through a promotion."
|
|
20238
|
+
) : [
|
|
20239
|
+
state.promotedFrom ? `${tr("fluidgrids.builder.environments.from", "From")} ${envLabel(state.promotedFrom)}` : null,
|
|
20240
|
+
deployer,
|
|
20241
|
+
relativeTime(state.deployedAt)
|
|
20242
|
+
].filter(Boolean).join(" \xB7 ") }),
|
|
20243
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [
|
|
20244
|
+
state.environment === "DEV" && currentVersion && /* @__PURE__ */ jsxs(
|
|
20245
|
+
Button$1,
|
|
20246
|
+
{
|
|
20247
|
+
variant: "outline",
|
|
20248
|
+
size: "sm",
|
|
20249
|
+
className: "h-7 gap-1 text-xs",
|
|
20250
|
+
disabled: busy !== null || dev?.version === currentVersion && dev.available,
|
|
20251
|
+
onClick: () => void handleDeployToDev(),
|
|
20252
|
+
children: [
|
|
20253
|
+
busy === "deploy" ? /* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(Upload, { className: "size-3.5" }),
|
|
20254
|
+
tr(
|
|
20255
|
+
"fluidgrids.builder.environments.deployOpen",
|
|
20256
|
+
"Deploy"
|
|
20257
|
+
),
|
|
20258
|
+
" ",
|
|
20259
|
+
currentVersion
|
|
20260
|
+
]
|
|
20261
|
+
}
|
|
20262
|
+
),
|
|
20263
|
+
target && /* @__PURE__ */ jsxs(
|
|
20264
|
+
Button$1,
|
|
20265
|
+
{
|
|
20266
|
+
size: "sm",
|
|
20267
|
+
variant: target === "PROD" ? "default" : "secondary",
|
|
20268
|
+
className: "h-7 gap-1 text-xs",
|
|
20269
|
+
disabled: busy !== null || blocker !== null,
|
|
20270
|
+
title: blocker ? blockerText(blocker, state.environment) : void 0,
|
|
20271
|
+
onClick: () => {
|
|
20272
|
+
setNote("");
|
|
20273
|
+
setDialog({ kind: "promote", target });
|
|
20274
|
+
},
|
|
20275
|
+
children: [
|
|
20276
|
+
busy === `promote:${target}` ? /* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin" }) : target === "PROD" ? /* @__PURE__ */ jsx(Rocket, { className: "size-3.5" }) : /* @__PURE__ */ jsx(ArrowRight, { className: "size-3.5" }),
|
|
20277
|
+
needsApproval ? tr(
|
|
20278
|
+
"fluidgrids.builder.environments.requestTo",
|
|
20279
|
+
"Request"
|
|
20280
|
+
) : tr(
|
|
20281
|
+
"fluidgrids.builder.environments.promoteTo",
|
|
20282
|
+
"Promote to"
|
|
20283
|
+
),
|
|
20284
|
+
" ",
|
|
20285
|
+
envLabel(target)
|
|
20286
|
+
]
|
|
20287
|
+
}
|
|
20288
|
+
)
|
|
20289
|
+
] }),
|
|
20290
|
+
target && blocker && blocker !== "sourceEmpty" && /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-muted-foreground", children: blockerText(blocker, state.environment) })
|
|
20291
|
+
]
|
|
20292
|
+
},
|
|
20293
|
+
state.environment
|
|
20294
|
+
);
|
|
20295
|
+
}) }),
|
|
20296
|
+
/* @__PURE__ */ jsxs("section", { "aria-labelledby": "fg-env-pending", children: [
|
|
20297
|
+
/* @__PURE__ */ jsx(
|
|
20298
|
+
"h3",
|
|
20299
|
+
{
|
|
20300
|
+
id: "fg-env-pending",
|
|
20301
|
+
className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
20302
|
+
children: tr(
|
|
20303
|
+
"fluidgrids.builder.environments.pendingTitle",
|
|
20304
|
+
"Waiting for approval"
|
|
20305
|
+
)
|
|
20306
|
+
}
|
|
20307
|
+
),
|
|
20308
|
+
pending.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tr(
|
|
20309
|
+
"fluidgrids.builder.environments.pendingEmpty",
|
|
20310
|
+
"No promotions are waiting."
|
|
20311
|
+
) }) : /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: pending.map((request) => {
|
|
20312
|
+
const label = `${request.version} \u2192 ${envLabel(request.toEnvironment)}`;
|
|
20313
|
+
return /* @__PURE__ */ jsxs(
|
|
20314
|
+
"li",
|
|
20315
|
+
{
|
|
20316
|
+
className: "rounded-lg border border-border bg-muted/30 p-3",
|
|
20317
|
+
"data-testid": "fluidgrids-env-pending",
|
|
20318
|
+
children: [
|
|
20319
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-medium text-foreground", children: [
|
|
20320
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: request.version }),
|
|
20321
|
+
" ",
|
|
20322
|
+
envLabel(request.fromEnvironment),
|
|
20323
|
+
" \u2192",
|
|
20324
|
+
" ",
|
|
20325
|
+
envLabel(request.toEnvironment)
|
|
20326
|
+
] }),
|
|
20327
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
|
|
20328
|
+
nameOf(request.requestedById),
|
|
20329
|
+
" \xB7",
|
|
20330
|
+
" ",
|
|
20331
|
+
relativeTime(request.requestedAt)
|
|
20332
|
+
] }),
|
|
20333
|
+
request.note && /* @__PURE__ */ jsx("p", { className: "mt-1 whitespace-pre-wrap text-xs text-foreground", children: request.note }),
|
|
20334
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [
|
|
20335
|
+
/* @__PURE__ */ jsxs(
|
|
20336
|
+
Button$1,
|
|
20337
|
+
{
|
|
20338
|
+
size: "sm",
|
|
20339
|
+
className: "h-7 gap-1 text-xs",
|
|
20340
|
+
disabled: busy !== null,
|
|
20341
|
+
onClick: () => {
|
|
20342
|
+
setNote("");
|
|
20343
|
+
setDialog({
|
|
20344
|
+
kind: "approve",
|
|
20345
|
+
id: request.id,
|
|
20346
|
+
label,
|
|
20347
|
+
version: request.version,
|
|
20348
|
+
target: request.toEnvironment
|
|
20349
|
+
});
|
|
20350
|
+
},
|
|
20351
|
+
children: [
|
|
20352
|
+
/* @__PURE__ */ jsx(Check, { className: "size-3.5" }),
|
|
20353
|
+
tr(
|
|
20354
|
+
"fluidgrids.builder.environments.approve",
|
|
20355
|
+
"Approve"
|
|
20356
|
+
)
|
|
20357
|
+
]
|
|
20358
|
+
}
|
|
20359
|
+
),
|
|
20360
|
+
/* @__PURE__ */ jsxs(
|
|
20361
|
+
Button$1,
|
|
20362
|
+
{
|
|
20363
|
+
size: "sm",
|
|
20364
|
+
variant: "outline",
|
|
20365
|
+
className: "h-7 gap-1 text-xs",
|
|
20366
|
+
disabled: busy !== null,
|
|
20367
|
+
onClick: () => {
|
|
20368
|
+
setNote("");
|
|
20369
|
+
setDialog({
|
|
20370
|
+
kind: "reject",
|
|
20371
|
+
id: request.id,
|
|
20372
|
+
label
|
|
20373
|
+
});
|
|
20374
|
+
},
|
|
20375
|
+
children: [
|
|
20376
|
+
/* @__PURE__ */ jsx(X, { className: "size-3.5" }),
|
|
20377
|
+
tr(
|
|
20378
|
+
"fluidgrids.builder.environments.reject",
|
|
20379
|
+
"Reject"
|
|
20380
|
+
)
|
|
20381
|
+
]
|
|
20382
|
+
}
|
|
20383
|
+
),
|
|
20384
|
+
/* @__PURE__ */ jsxs(
|
|
20385
|
+
Button$1,
|
|
20386
|
+
{
|
|
20387
|
+
size: "sm",
|
|
20388
|
+
variant: "ghost",
|
|
20389
|
+
className: "h-7 gap-1 text-xs",
|
|
20390
|
+
disabled: busy !== null,
|
|
20391
|
+
onClick: () => void handleCancel(request.id),
|
|
20392
|
+
children: [
|
|
20393
|
+
busy === `cancel:${request.id}` ? /* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(Undo2, { className: "size-3.5" }),
|
|
20394
|
+
tr(
|
|
20395
|
+
"fluidgrids.builder.environments.withdraw",
|
|
20396
|
+
"Withdraw"
|
|
20397
|
+
)
|
|
20398
|
+
]
|
|
20399
|
+
}
|
|
20400
|
+
)
|
|
20401
|
+
] })
|
|
20402
|
+
]
|
|
20403
|
+
},
|
|
20404
|
+
request.id
|
|
20405
|
+
);
|
|
20406
|
+
}) })
|
|
20407
|
+
] }),
|
|
20408
|
+
policy && /* @__PURE__ */ jsxs("section", { "aria-labelledby": "fg-env-policy", children: [
|
|
20409
|
+
/* @__PURE__ */ jsx(
|
|
20410
|
+
"h3",
|
|
20411
|
+
{
|
|
20412
|
+
id: "fg-env-policy",
|
|
20413
|
+
className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
20414
|
+
children: tr(
|
|
20415
|
+
"fluidgrids.builder.environments.policyTitle",
|
|
20416
|
+
"Promotion policy (workspace)"
|
|
20417
|
+
)
|
|
20418
|
+
}
|
|
20419
|
+
),
|
|
20420
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-lg border border-border p-3", children: [
|
|
20421
|
+
[
|
|
20422
|
+
[
|
|
20423
|
+
"requireProdApproval",
|
|
20424
|
+
tr(
|
|
20425
|
+
"fluidgrids.builder.environments.policyProd",
|
|
20426
|
+
"Production promotions need approval"
|
|
20427
|
+
)
|
|
20428
|
+
],
|
|
20429
|
+
[
|
|
20430
|
+
"requireStagingApproval",
|
|
20431
|
+
tr(
|
|
20432
|
+
"fluidgrids.builder.environments.policyStaging",
|
|
20433
|
+
"Staging promotions need approval"
|
|
20434
|
+
)
|
|
20435
|
+
],
|
|
20436
|
+
[
|
|
20437
|
+
"allowSelfApproval",
|
|
20438
|
+
tr(
|
|
20439
|
+
"fluidgrids.builder.environments.policySelf",
|
|
20440
|
+
"Requesters may approve their own promotions"
|
|
20441
|
+
)
|
|
20442
|
+
],
|
|
20443
|
+
[
|
|
20444
|
+
"lockDirectActivation",
|
|
20445
|
+
tr(
|
|
20446
|
+
"fluidgrids.builder.environments.policyLock",
|
|
20447
|
+
"Change Production only through promotions"
|
|
20448
|
+
)
|
|
20449
|
+
]
|
|
20450
|
+
].map(([field, label]) => /* @__PURE__ */ jsxs(
|
|
20451
|
+
"div",
|
|
20452
|
+
{
|
|
20453
|
+
className: "flex items-center justify-between gap-3",
|
|
20454
|
+
children: [
|
|
20455
|
+
/* @__PURE__ */ jsx(
|
|
20456
|
+
Label,
|
|
20457
|
+
{
|
|
20458
|
+
htmlFor: `fg-env-policy-${field}`,
|
|
20459
|
+
className: "text-xs font-normal",
|
|
20460
|
+
children: label
|
|
20461
|
+
}
|
|
20462
|
+
),
|
|
20463
|
+
/* @__PURE__ */ jsx(
|
|
20464
|
+
Switch,
|
|
20465
|
+
{
|
|
20466
|
+
id: `fg-env-policy-${field}`,
|
|
20467
|
+
checked: policy[field],
|
|
20468
|
+
disabled: busy !== null,
|
|
20469
|
+
onCheckedChange: (checked) => void handlePolicy({ [field]: checked })
|
|
20470
|
+
}
|
|
20471
|
+
)
|
|
20472
|
+
]
|
|
20473
|
+
},
|
|
20474
|
+
field
|
|
20475
|
+
)),
|
|
20476
|
+
/* @__PURE__ */ jsx("p", { className: "pt-1 text-[11px] text-muted-foreground", children: tr(
|
|
20477
|
+
"fluidgrids.builder.environments.policyHint",
|
|
20478
|
+
"Only members with publish rights can approve promotions or change this policy."
|
|
20479
|
+
) })
|
|
20480
|
+
] })
|
|
20481
|
+
] }),
|
|
20482
|
+
/* @__PURE__ */ jsxs("section", { "aria-labelledby": "fg-env-history", children: [
|
|
20483
|
+
/* @__PURE__ */ jsx(
|
|
20484
|
+
"h3",
|
|
20485
|
+
{
|
|
20486
|
+
id: "fg-env-history",
|
|
20487
|
+
className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
20488
|
+
children: tr(
|
|
20489
|
+
"fluidgrids.builder.environments.historyTitle",
|
|
20490
|
+
"Promotion history"
|
|
20491
|
+
)
|
|
20492
|
+
}
|
|
20493
|
+
),
|
|
20494
|
+
history.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tr(
|
|
20495
|
+
"fluidgrids.builder.environments.historyEmpty",
|
|
20496
|
+
"No promotions yet."
|
|
20497
|
+
) }) : /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: history.map((item) => /* @__PURE__ */ jsxs(
|
|
20498
|
+
"li",
|
|
20499
|
+
{
|
|
20500
|
+
className: "flex items-start justify-between gap-2 text-xs",
|
|
20501
|
+
"data-testid": "fluidgrids-env-history",
|
|
20502
|
+
children: [
|
|
20503
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
20504
|
+
/* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
|
|
20505
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: item.version }),
|
|
20506
|
+
" ",
|
|
20507
|
+
envLabel(item.fromEnvironment),
|
|
20508
|
+
" \u2192",
|
|
20509
|
+
" ",
|
|
20510
|
+
envLabel(item.toEnvironment)
|
|
20511
|
+
] }),
|
|
20512
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-muted-foreground", children: [
|
|
20513
|
+
nameOf(item.requestedById),
|
|
20514
|
+
item.reviewedById && item.reviewedById !== item.requestedById ? `${tr("fluidgrids.builder.environments.reviewedBy", "reviewed by")} ${nameOf(item.reviewedById)}` : null,
|
|
20515
|
+
relativeTime(item.requestedAt)
|
|
20516
|
+
].filter(Boolean).join(" \xB7 ") })
|
|
20517
|
+
] }),
|
|
20518
|
+
/* @__PURE__ */ jsx(
|
|
20519
|
+
Badge,
|
|
20520
|
+
{
|
|
20521
|
+
variant: statusVariant(item.status),
|
|
20522
|
+
className: "h-5 shrink-0 px-1.5 py-0 text-[10px]",
|
|
20523
|
+
children: item.autoApplied ? tr(
|
|
20524
|
+
"fluidgrids.builder.environments.statusAuto",
|
|
20525
|
+
"Applied"
|
|
20526
|
+
) : item.status === "APPLIED" ? tr(
|
|
20527
|
+
"fluidgrids.builder.environments.statusApproved",
|
|
20528
|
+
"Approved"
|
|
20529
|
+
) : item.status === "PENDING" ? tr(
|
|
20530
|
+
"fluidgrids.builder.environments.statusPending",
|
|
20531
|
+
"Pending"
|
|
20532
|
+
) : item.status === "REJECTED" ? tr(
|
|
20533
|
+
"fluidgrids.builder.environments.statusRejected",
|
|
20534
|
+
"Rejected"
|
|
20535
|
+
) : tr(
|
|
20536
|
+
"fluidgrids.builder.environments.statusCanceled",
|
|
20537
|
+
"Withdrawn"
|
|
20538
|
+
)
|
|
20539
|
+
}
|
|
20540
|
+
)
|
|
20541
|
+
]
|
|
20542
|
+
},
|
|
20543
|
+
item.id
|
|
20544
|
+
)) })
|
|
20545
|
+
] })
|
|
20546
|
+
] })
|
|
20547
|
+
]
|
|
20548
|
+
}
|
|
20549
|
+
),
|
|
20550
|
+
/* @__PURE__ */ jsx(
|
|
20551
|
+
AlertDialog,
|
|
20552
|
+
{
|
|
20553
|
+
open: dialog !== null,
|
|
20554
|
+
onOpenChange: (open) => !open && setDialog(null),
|
|
20555
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, { className: "z-[120]", children: [
|
|
20556
|
+
/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
|
|
20557
|
+
/* @__PURE__ */ jsx(AlertDialogTitle, { children: dialogTitle }),
|
|
20558
|
+
/* @__PURE__ */ jsx(AlertDialogDescription, { children: dialogBody })
|
|
20559
|
+
] }),
|
|
20560
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
20561
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "fg-env-note", className: "text-xs", children: tr(
|
|
20562
|
+
"fluidgrids.builder.environments.noteLabel",
|
|
20563
|
+
"Note (optional)"
|
|
20564
|
+
) }),
|
|
20565
|
+
/* @__PURE__ */ jsx(
|
|
20566
|
+
Textarea,
|
|
20567
|
+
{
|
|
20568
|
+
id: "fg-env-note",
|
|
20569
|
+
value: note,
|
|
20570
|
+
maxLength: NOTE_MAX,
|
|
20571
|
+
rows: 3,
|
|
20572
|
+
onChange: (event) => setNote(event.target.value)
|
|
20573
|
+
}
|
|
20574
|
+
)
|
|
20575
|
+
] }),
|
|
20576
|
+
/* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
|
|
20577
|
+
/* @__PURE__ */ jsx(AlertDialogCancel, { children: tr("fluidgrids.builder.environments.dialogCancel", "Cancel") }),
|
|
20578
|
+
/* @__PURE__ */ jsx(AlertDialogAction, { onClick: () => void handleConfirmDialog(), children: dialog?.kind === "reject" ? tr("fluidgrids.builder.environments.reject", "Reject") : dialog?.kind === "approve" ? tr("fluidgrids.builder.environments.approve", "Approve") : tr("fluidgrids.builder.environments.confirm", "Confirm") })
|
|
20579
|
+
] })
|
|
20580
|
+
] })
|
|
20581
|
+
}
|
|
20582
|
+
)
|
|
20583
|
+
] });
|
|
20584
|
+
}
|
|
19729
20585
|
|
|
19730
20586
|
// src/builder/lib/ai-draft.ts
|
|
19731
20587
|
var AI_DRAFT_POLL_INTERVAL_MS = 2500;
|
|
@@ -19825,7 +20681,7 @@ function canvasHasWork(nodes) {
|
|
|
19825
20681
|
}
|
|
19826
20682
|
|
|
19827
20683
|
// src/builder/hooks/use-ai-workflow-draft.ts
|
|
19828
|
-
function
|
|
20684
|
+
function messageOf2(error) {
|
|
19829
20685
|
return error instanceof Error ? error.message : String(error);
|
|
19830
20686
|
}
|
|
19831
20687
|
function useAiWorkflowDraft() {
|
|
@@ -19882,7 +20738,7 @@ function useAiWorkflowDraft() {
|
|
|
19882
20738
|
setIsGenerating(false);
|
|
19883
20739
|
} catch (pollError) {
|
|
19884
20740
|
if (run !== runRef.current) return;
|
|
19885
|
-
setError(
|
|
20741
|
+
setError(messageOf2(pollError));
|
|
19886
20742
|
setIsGenerating(false);
|
|
19887
20743
|
}
|
|
19888
20744
|
},
|
|
@@ -19919,7 +20775,7 @@ function useAiWorkflowDraft() {
|
|
|
19919
20775
|
);
|
|
19920
20776
|
} catch (startError) {
|
|
19921
20777
|
if (run !== runRef.current) return;
|
|
19922
|
-
setError(
|
|
20778
|
+
setError(messageOf2(startError));
|
|
19923
20779
|
setIsGenerating(false);
|
|
19924
20780
|
}
|
|
19925
20781
|
},
|
|
@@ -20626,6 +21482,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
20626
21482
|
/* @__PURE__ */ jsxs("div", { className: "hidden shrink-0 lg:inline-flex items-center gap-2", children: [
|
|
20627
21483
|
!isReadOnly && /* @__PURE__ */ jsx(AiDraftPanel, {}),
|
|
20628
21484
|
/* @__PURE__ */ jsx(VersionHistoryPanel, {}),
|
|
21485
|
+
/* @__PURE__ */ jsx(EnvironmentsPanel, {}),
|
|
20629
21486
|
/* @__PURE__ */ jsx(SaveFlowButton, {}),
|
|
20630
21487
|
/* @__PURE__ */ jsx(ActivateWorkflowButton, {}),
|
|
20631
21488
|
/* @__PURE__ */ jsx(
|
|
@@ -20647,6 +21504,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
20647
21504
|
] }),
|
|
20648
21505
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1 lg:hidden", children: [
|
|
20649
21506
|
!isReadOnly && /* @__PURE__ */ jsx(AiDraftPanel, { compact: true }),
|
|
21507
|
+
/* @__PURE__ */ jsx(EnvironmentsPanel, { compact: true }),
|
|
20650
21508
|
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
20651
21509
|
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
20652
21510
|
Button$1,
|