mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-16 01:19:50 +00:00
feat: release and discard workflow changes
This commit is contained in:
parent
9c4831fa3f
commit
7cf96d7d7e
@ -45,7 +45,7 @@ type WorkflowNode struct {
|
|||||||
Type WorkflowNodeType `json:"type"`
|
Type WorkflowNodeType `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
Config map[string]any `json:"config"`
|
Config map[string]any `json:"data"`
|
||||||
Inputs []WorkflowNodeIO `json:"inputs"`
|
Inputs []WorkflowNodeIO `json:"inputs"`
|
||||||
Outputs []WorkflowNodeIO `json:"outputs"`
|
Outputs []WorkflowNodeIO `json:"outputs"`
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"workflow.detail.baseinfo.form.description.label": "Description",
|
"workflow.detail.baseinfo.form.description.label": "Description",
|
||||||
"workflow.detail.baseinfo.form.description.placeholder": "Please enter workflow description",
|
"workflow.detail.baseinfo.form.description.placeholder": "Please enter workflow description",
|
||||||
"workflow.detail.orchestration.tab": "Orchestration",
|
"workflow.detail.orchestration.tab": "Orchestration",
|
||||||
|
"workflow.detail.orchestration.draft.alert": "The orchestration is not released yet.",
|
||||||
"workflow.detail.orchestration.action.discard": "Discard changes",
|
"workflow.detail.orchestration.action.discard": "Discard changes",
|
||||||
"workflow.detail.orchestration.action.discard.confirm": "Are you sure to discard your changes?",
|
"workflow.detail.orchestration.action.discard.confirm": "Are you sure to discard your changes?",
|
||||||
"workflow.detail.orchestration.action.release": "Release",
|
"workflow.detail.orchestration.action.release": "Release",
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"workflow.detail.baseinfo.form.description.label": "描述",
|
"workflow.detail.baseinfo.form.description.label": "描述",
|
||||||
"workflow.detail.baseinfo.form.description.placeholder": "请输入工作流描述",
|
"workflow.detail.baseinfo.form.description.placeholder": "请输入工作流描述",
|
||||||
"workflow.detail.orchestration.tab": "流程编排",
|
"workflow.detail.orchestration.tab": "流程编排",
|
||||||
|
"workflow.detail.orchestration.draft.alert": "当前编排有未发布的更改。",
|
||||||
"workflow.detail.orchestration.action.discard": "撤销更改",
|
"workflow.detail.orchestration.action.discard": "撤销更改",
|
||||||
"workflow.detail.orchestration.action.discard.confirm": "确定要撤销更改并回退到最近一次发布的版本吗?",
|
"workflow.detail.orchestration.action.discard.confirm": "确定要撤销更改并回退到最近一次发布的版本吗?",
|
||||||
"workflow.detail.orchestration.action.release": "发布更改",
|
"workflow.detail.orchestration.action.release": "发布更改",
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { PageHeader } from "@ant-design/pro-components";
|
import { PageHeader } from "@ant-design/pro-components";
|
||||||
import { useDeepCompareEffect } from "ahooks";
|
import { useDeepCompareEffect } from "ahooks";
|
||||||
import { Button, Card, Dropdown, Form, Input, Modal, Space, Tabs, Typography, message, notification } from "antd";
|
import { Alert, Button, Card, Dropdown, Form, Input, Modal, Space, Tabs, Typography, message, notification } from "antd";
|
||||||
import { createSchemaFieldRule } from "antd-zod";
|
import { createSchemaFieldRule } from "antd-zod";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
import { isEqual } from "radash";
|
import { isEqual } from "radash";
|
||||||
@ -39,15 +39,15 @@ const WorkflowDetail = () => {
|
|||||||
const [notificationApi, NotificationContextHolder] = notification.useNotification();
|
const [notificationApi, NotificationContextHolder] = notification.useNotification();
|
||||||
|
|
||||||
const { id: workflowId } = useParams();
|
const { id: workflowId } = useParams();
|
||||||
const { workflow, initialized, init, save, destroy, setBaseInfo, switchEnable } = useWorkflowStore(
|
const { workflow, initialized, ...workflowState } = useWorkflowStore(
|
||||||
useZustandShallowSelector(["workflow", "initialized", "init", "destroy", "save", "setBaseInfo", "switchEnable"])
|
useZustandShallowSelector(["workflow", "initialized", "init", "destroy", "setBaseInfo", "setEnabled", "release", "discard"])
|
||||||
);
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// TODO: loading & error
|
// TODO: loading & error
|
||||||
init(workflowId!);
|
workflowState.init(workflowId!);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
destroy();
|
workflowState.destroy();
|
||||||
};
|
};
|
||||||
}, [workflowId]);
|
}, [workflowId]);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ const WorkflowDetail = () => {
|
|||||||
|
|
||||||
const handleBaseInfoFormFinish = async (values: Pick<WorkflowModel, "name" | "description">) => {
|
const handleBaseInfoFormFinish = async (values: Pick<WorkflowModel, "name" | "description">) => {
|
||||||
try {
|
try {
|
||||||
await setBaseInfo(values.name!, values.description!);
|
await workflowState.setBaseInfo(values.name!, values.description!);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
||||||
@ -83,7 +83,7 @@ const WorkflowDetail = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await switchEnable();
|
await workflowState.setEnabled(!workflow.enabled);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
||||||
@ -112,8 +112,15 @@ const WorkflowDetail = () => {
|
|||||||
modalApi.confirm({
|
modalApi.confirm({
|
||||||
title: t("workflow.detail.orchestration.action.discard"),
|
title: t("workflow.detail.orchestration.action.discard"),
|
||||||
content: t("workflow.detail.orchestration.action.discard.confirm"),
|
content: t("workflow.detail.orchestration.action.discard.confirm"),
|
||||||
onOk: () => {
|
onOk: async () => {
|
||||||
alert("TODO");
|
try {
|
||||||
|
await workflowState.discard();
|
||||||
|
|
||||||
|
messageApi.success(t("common.text.operation_succeeded"));
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -129,7 +136,7 @@ const WorkflowDetail = () => {
|
|||||||
content: t("workflow.detail.orchestration.action.release.confirm"),
|
content: t("workflow.detail.orchestration.action.release.confirm"),
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
await save();
|
await workflowState.release();
|
||||||
|
|
||||||
messageApi.success(t("common.text.operation_succeeded"));
|
messageApi.success(t("common.text.operation_succeeded"));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -242,38 +249,45 @@ const WorkflowDetail = () => {
|
|||||||
<Card loading={!initialized}>
|
<Card loading={!initialized}>
|
||||||
<Show when={tabValue === "orchestration"}>
|
<Show when={tabValue === "orchestration"}>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="py-12 lg:pr-36 xl:pr-48">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<WorkflowElements />
|
<div className="flex-1 overflow-hidden">
|
||||||
</div>
|
<Show when={workflow.hasDraft!}>
|
||||||
<div className="absolute right-0 top-0 z-[1]">
|
<Alert banner message={<div className="truncate">{t("workflow.detail.orchestration.draft.alert")}</div>} type="warning" />
|
||||||
<Space>
|
</Show>
|
||||||
<Button disabled={!allowRun} icon={<CaretRightOutlinedIcon />} loading={isRunning} type="primary" onClick={handleRunClick}>
|
</div>
|
||||||
{t("workflow.detail.orchestration.action.run")}
|
<div className="flex justify-end">
|
||||||
</Button>
|
<Space>
|
||||||
|
<Button disabled={!allowRun} icon={<CaretRightOutlinedIcon />} loading={isRunning} type="primary" onClick={handleRunClick}>
|
||||||
<Button.Group>
|
{t("workflow.detail.orchestration.action.run")}
|
||||||
<Button color="primary" disabled={!allowRelease} variant="outlined" onClick={handleReleaseClick}>
|
|
||||||
{t("workflow.detail.orchestration.action.release")}
|
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Dropdown
|
<Button.Group>
|
||||||
menu={{
|
<Button color="primary" disabled={!allowRelease} variant="outlined" onClick={handleReleaseClick}>
|
||||||
items: [
|
{t("workflow.detail.orchestration.action.release")}
|
||||||
{
|
</Button>
|
||||||
key: "discard",
|
|
||||||
disabled: !allowDiscard,
|
<Dropdown
|
||||||
label: t("workflow.detail.orchestration.action.discard"),
|
menu={{
|
||||||
icon: <UndoOutlinedIcon />,
|
items: [
|
||||||
onClick: handleDiscardClick,
|
{
|
||||||
},
|
key: "discard",
|
||||||
],
|
disabled: !allowDiscard,
|
||||||
}}
|
label: t("workflow.detail.orchestration.action.discard"),
|
||||||
trigger={["click"]}
|
icon: <UndoOutlinedIcon />,
|
||||||
>
|
onClick: handleDiscardClick,
|
||||||
<Button color="primary" disabled={!allowDiscard} icon={<EllipsisOutlinedIcon />} variant="outlined" />
|
},
|
||||||
</Dropdown>
|
],
|
||||||
</Button.Group>
|
}}
|
||||||
</Space>
|
trigger={["click"]}
|
||||||
|
>
|
||||||
|
<Button color="primary" disabled={!allowDiscard} icon={<EllipsisOutlinedIcon />} variant="outlined" />
|
||||||
|
</Dropdown>
|
||||||
|
</Button.Group>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="px-12 py-8">
|
||||||
|
<WorkflowElements />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
@ -35,7 +35,7 @@ export const get = async (id: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const save = async (record: Record<string, string | boolean | WorkflowNode>) => {
|
export const save = async (record: MaybeModelRecord<WorkflowModel>) => {
|
||||||
if (record.id) {
|
if (record.id) {
|
||||||
return await getPocketBase()
|
return await getPocketBase()
|
||||||
.collection(COLLECTION_NAME)
|
.collection(COLLECTION_NAME)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
import { produce } from "immer";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type WorkflowModel,
|
type WorkflowModel,
|
||||||
type WorkflowNode,
|
type WorkflowNode,
|
||||||
|
type WorkflowNodeConfigForStart,
|
||||||
addBranch,
|
addBranch,
|
||||||
addNode,
|
addNode,
|
||||||
getExecuteMethod,
|
|
||||||
getWorkflowOutputBeforeId,
|
getWorkflowOutputBeforeId,
|
||||||
removeBranch,
|
removeBranch,
|
||||||
removeNode,
|
removeNode,
|
||||||
@ -16,17 +17,22 @@ import { get as getWorkflow, save as saveWorkflow } from "@/repository/workflow"
|
|||||||
export type WorkflowState = {
|
export type WorkflowState = {
|
||||||
workflow: WorkflowModel;
|
workflow: WorkflowModel;
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
updateNode: (node: WorkflowNode) => void;
|
|
||||||
addNode: (node: WorkflowNode, preId: string) => void;
|
|
||||||
addBranch: (branchId: string) => void;
|
|
||||||
removeNode: (nodeId: string) => void;
|
|
||||||
removeBranch: (branchId: string, index: number) => void;
|
|
||||||
getWorkflowOuptutBeforeId: (id: string, type: string) => WorkflowNode[];
|
|
||||||
switchEnable(): void;
|
|
||||||
save(): void;
|
|
||||||
setBaseInfo: (name: string, description: string) => void;
|
|
||||||
init(id: string): void;
|
init(id: string): void;
|
||||||
|
setBaseInfo: (name: string, description: string) => void;
|
||||||
|
setEnabled(enabled: boolean): void;
|
||||||
|
release(): void;
|
||||||
|
discard(): void;
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
|
|
||||||
|
addNode: (node: WorkflowNode, preId: string) => void;
|
||||||
|
updateNode: (node: WorkflowNode) => void;
|
||||||
|
removeNode: (nodeId: string) => void;
|
||||||
|
|
||||||
|
addBranch: (branchId: string) => void;
|
||||||
|
removeBranch: (branchId: string, index: number) => void;
|
||||||
|
|
||||||
|
getWorkflowOuptutBeforeId: (id: string, type: string) => WorkflowNode[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
||||||
@ -42,171 +48,197 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroy: () => {
|
||||||
|
set({
|
||||||
|
workflow: {} as WorkflowModel,
|
||||||
|
initialized: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setBaseInfo: async (name: string, description: string) => {
|
setBaseInfo: async (name: string, description: string) => {
|
||||||
const data: Record<string, string | boolean | WorkflowNode> = {
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
id: (get().workflow.id as string) ?? "",
|
|
||||||
|
const resp = await saveWorkflow({
|
||||||
|
id: get().workflow.id!,
|
||||||
name: name || "",
|
name: name || "",
|
||||||
description: description || "",
|
description: description || "",
|
||||||
};
|
|
||||||
const resp = await saveWorkflow(data);
|
|
||||||
set((state: WorkflowState) => {
|
|
||||||
return {
|
|
||||||
workflow: {
|
|
||||||
...state.workflow,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
id: resp.id,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
switchEnable: async () => {
|
|
||||||
const root = get().workflow.content as WorkflowNode;
|
|
||||||
const executeMethod = getExecuteMethod(root);
|
|
||||||
const resp = await saveWorkflow({
|
|
||||||
id: (get().workflow.id as string) ?? "",
|
|
||||||
content: root,
|
|
||||||
enabled: !get().workflow.enabled,
|
|
||||||
trigger: executeMethod.trigger,
|
|
||||||
triggerCron: executeMethod.triggerCron,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.name = resp.name;
|
||||||
id: resp.id,
|
draft.description = resp.description;
|
||||||
content: resp.content,
|
}),
|
||||||
enabled: resp.enabled,
|
|
||||||
trigger: resp.trigger,
|
|
||||||
triggerCron: resp.triggerCron,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
save: async () => {
|
setEnabled: async (enabled: boolean) => {
|
||||||
const root = get().workflow.draft as WorkflowNode;
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
const executeMethod = getExecuteMethod(root);
|
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: get().workflow.id!,
|
||||||
|
enabled: enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
set((state: WorkflowState) => {
|
||||||
|
return {
|
||||||
|
workflow: produce(state.workflow, (draft) => {
|
||||||
|
draft.enabled = resp.enabled;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
release: async () => {
|
||||||
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = get().workflow.draft!;
|
||||||
|
const startConfig = root.config as WorkflowNodeConfigForStart;
|
||||||
|
const resp = await saveWorkflow({
|
||||||
|
id: get().workflow.id!,
|
||||||
|
trigger: startConfig.trigger,
|
||||||
|
triggerCron: startConfig.triggerCron,
|
||||||
content: root,
|
content: root,
|
||||||
hasDraft: false,
|
hasDraft: false,
|
||||||
trigger: executeMethod.trigger,
|
|
||||||
triggerCron: executeMethod.triggerCron,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.trigger = resp.trigger;
|
||||||
id: resp.id,
|
draft.triggerCron = resp.triggerCron;
|
||||||
content: resp.content,
|
draft.content = resp.content;
|
||||||
hasDraft: false,
|
draft.draft = resp.draft;
|
||||||
trigger: resp.trigger,
|
draft.hasDraft = resp.hasDraft;
|
||||||
triggerCron: resp.triggerCron,
|
}),
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateNode: async (node: WorkflowNode) => {
|
discard: async () => {
|
||||||
const newRoot = updateNode(get().workflow.draft as WorkflowNode, node);
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = get().workflow.content!;
|
||||||
|
const startConfig = root.config as WorkflowNodeConfigForStart;
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: get().workflow.id!,
|
||||||
draft: newRoot,
|
draft: root,
|
||||||
hasDraft: true,
|
hasDraft: false,
|
||||||
|
trigger: startConfig.trigger,
|
||||||
|
triggerCron: startConfig.triggerCron,
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.trigger = resp.trigger;
|
||||||
draft: newRoot,
|
draft.triggerCron = resp.triggerCron;
|
||||||
id: resp.id,
|
draft.content = resp.content;
|
||||||
hasDraft: true,
|
draft.draft = resp.draft;
|
||||||
},
|
draft.hasDraft = resp.hasDraft;
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addNode: async (node: WorkflowNode, preId: string) => {
|
addNode: async (node: WorkflowNode, preId: string) => {
|
||||||
const newRoot = addNode(get().workflow.draft as WorkflowNode, preId, node);
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = addNode(get().workflow.draft!, preId, node);
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: get().workflow.id!,
|
||||||
draft: newRoot,
|
draft: root,
|
||||||
hasDraft: true,
|
hasDraft: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.draft = resp.draft;
|
||||||
draft: newRoot,
|
draft.hasDraft = resp.hasDraft;
|
||||||
id: resp.id,
|
}),
|
||||||
hasDraft: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addBranch: async (branchId: string) => {
|
updateNode: async (node: WorkflowNode) => {
|
||||||
const newRoot = addBranch(get().workflow.draft as WorkflowNode, branchId);
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = updateNode(get().workflow.draft!, node);
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: get().workflow.id!,
|
||||||
draft: newRoot,
|
draft: root,
|
||||||
hasDraft: true,
|
hasDraft: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.draft = resp.draft;
|
||||||
draft: newRoot,
|
draft.hasDraft = resp.hasDraft;
|
||||||
id: resp.id,
|
}),
|
||||||
hasDraft: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeBranch: async (branchId: string, index: number) => {
|
|
||||||
const newRoot = removeBranch(get().workflow.draft as WorkflowNode, branchId, index);
|
|
||||||
const resp = await saveWorkflow({
|
|
||||||
id: (get().workflow.id as string) ?? "",
|
|
||||||
draft: newRoot,
|
|
||||||
hasDraft: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
|
||||||
return {
|
|
||||||
workflow: {
|
|
||||||
...state.workflow,
|
|
||||||
draft: newRoot,
|
|
||||||
id: resp.id,
|
|
||||||
hasDraft: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeNode: async (nodeId: string) => {
|
removeNode: async (nodeId: string) => {
|
||||||
const newRoot = removeNode(get().workflow.draft as WorkflowNode, nodeId);
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = removeNode(get().workflow.draft!, nodeId);
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: get().workflow.id!,
|
||||||
draft: newRoot,
|
draft: root,
|
||||||
hasDraft: true,
|
hasDraft: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
set((state: WorkflowState) => {
|
set((state: WorkflowState) => {
|
||||||
return {
|
return {
|
||||||
workflow: {
|
workflow: produce(state.workflow, (draft) => {
|
||||||
...state.workflow,
|
draft.draft = resp.draft;
|
||||||
draft: newRoot,
|
draft.hasDraft = resp.hasDraft;
|
||||||
id: resp.id,
|
}),
|
||||||
hasDraft: true,
|
};
|
||||||
},
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addBranch: async (branchId: string) => {
|
||||||
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = addBranch(get().workflow.draft!, branchId);
|
||||||
|
const resp = await saveWorkflow({
|
||||||
|
id: get().workflow.id!,
|
||||||
|
draft: root,
|
||||||
|
hasDraft: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
set((state: WorkflowState) => {
|
||||||
|
return {
|
||||||
|
workflow: produce(state.workflow, (draft) => {
|
||||||
|
draft.draft = resp.draft;
|
||||||
|
draft.hasDraft = resp.hasDraft;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeBranch: async (branchId: string, index: number) => {
|
||||||
|
if (!get().initialized) throw "Workflow not initialized yet";
|
||||||
|
|
||||||
|
const root = removeBranch(get().workflow.draft!, branchId, index);
|
||||||
|
const resp = await saveWorkflow({
|
||||||
|
id: get().workflow.id!,
|
||||||
|
draft: root,
|
||||||
|
hasDraft: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
set((state: WorkflowState) => {
|
||||||
|
return {
|
||||||
|
workflow: produce(state.workflow, (draft) => {
|
||||||
|
draft.draft = resp.draft;
|
||||||
|
draft.hasDraft = resp.hasDraft;
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -214,11 +246,4 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
|||||||
getWorkflowOuptutBeforeId: (id: string, type: string) => {
|
getWorkflowOuptutBeforeId: (id: string, type: string) => {
|
||||||
return getWorkflowOutputBeforeId(get().workflow.draft as WorkflowNode, id, type);
|
return getWorkflowOutputBeforeId(get().workflow.draft as WorkflowNode, id, type);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: () => {
|
|
||||||
set({
|
|
||||||
workflow: {} as WorkflowModel,
|
|
||||||
initialized: false,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user