mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-07 21:19:51 +00:00
add clone alert
This commit is contained in:
parent
19bbe1f069
commit
c713d4705e
@ -6,7 +6,7 @@ export type UploadNodeProps = SharedNodeProps;
|
||||
const CloneNode = ({ node, disabled }: SharedNodeProps) => {
|
||||
return (
|
||||
<>
|
||||
<Card className="relative z-[1] mt-10 w-[256px] shadow-md" styles={{ body: { padding: 0 } }} hoverable>
|
||||
<Card className="relative z-[1] w-[256px] shadow-md" styles={{ body: { padding: 0 } }} hoverable>
|
||||
<div className="flex h-[64px] flex-col items-center justify-center truncate px-4 py-2">选择节点复制到此处</div>
|
||||
</Card>
|
||||
<AddNode node={node} disabled={disabled} />
|
||||
|
@ -507,3 +507,45 @@ export const isAllNodesValidated = (node: WorkflowNode): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
export const hasCloneNode = (node: WorkflowNode): boolean => {
|
||||
let current = node as typeof node | undefined;
|
||||
while (current) {
|
||||
if (current.type === WorkflowNodeType.Clone) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isBranchLike(current)) {
|
||||
for (const branch of current.branches!) {
|
||||
if (hasCloneNode(branch)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current = current.next;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const removeCloneNode = (node: WorkflowNode): WorkflowNode => {
|
||||
return produce(node, (draft) => {
|
||||
let current = draft as typeof draft | undefined;
|
||||
|
||||
while (current) {
|
||||
if (current.next?.type === WorkflowNodeType.Clone) {
|
||||
current.next = current.next.next;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isBranchLike(current) && current.branches) {
|
||||
current.branches = current.branches.map((branch) => removeCloneNode(branch));
|
||||
}
|
||||
|
||||
current = current.next;
|
||||
}
|
||||
|
||||
return draft;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,7 @@ import ModalForm from "@/components/ModalForm";
|
||||
import Show from "@/components/Show";
|
||||
import WorkflowElementsContainer from "@/components/workflow/WorkflowElementsContainer";
|
||||
import WorkflowRuns from "@/components/workflow/WorkflowRuns";
|
||||
import { isAllNodesValidated } from "@/domain/workflow";
|
||||
import { hasCloneNode, isAllNodesValidated } from "@/domain/workflow";
|
||||
import { WORKFLOW_RUN_STATUSES } from "@/domain/workflowRun";
|
||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||
import { remove as removeWorkflow, subscribe as subscribeWorkflow, unsubscribe as unsubscribeWorkflow } from "@/repository/workflow";
|
||||
@ -38,9 +38,12 @@ const WorkflowDetail = () => {
|
||||
const [notificationApi, NotificationContextHolder] = notification.useNotification();
|
||||
|
||||
const { id: workflowId } = useParams();
|
||||
const { workflow, initialized, ...workflowState } = useWorkflowStore(
|
||||
useZustandShallowSelector(["workflow", "initialized", "init", "destroy", "setEnabled", "release", "discard"])
|
||||
const { workflow, initialized, cancelClone, ...workflowState } = useWorkflowStore(
|
||||
useZustandShallowSelector(["workflow", "initialized", "cancelClone", "init", "destroy", "setEnabled", "release", "discard"])
|
||||
);
|
||||
|
||||
const cloning = hasCloneNode(workflow.draft!);
|
||||
|
||||
useEffect(() => {
|
||||
workflowState.init(workflowId!);
|
||||
|
||||
@ -308,6 +311,28 @@ const WorkflowDetail = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Show when={cloning}>
|
||||
<div className="absolute top-4 left-0 right-0 z-[10] flex justify-center">
|
||||
<Alert
|
||||
className="shadow-lg animate-fadeIn"
|
||||
showIcon
|
||||
message="选择要复制的节点,复制到目标位置"
|
||||
type="info"
|
||||
action={
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() => {
|
||||
cancelClone();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<WorkflowElementsContainer className="pt-16" />
|
||||
</Card>
|
||||
</div>
|
||||
@ -395,3 +420,4 @@ const WorkflowBaseInfoModal = ({ trigger }: { trigger?: React.ReactNode }) => {
|
||||
};
|
||||
|
||||
export default WorkflowDetail;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
addNode,
|
||||
getOutputBeforeNodeId,
|
||||
removeBranch,
|
||||
removeCloneNode,
|
||||
removeNode,
|
||||
updateNode,
|
||||
} from "@/domain/workflow";
|
||||
@ -28,6 +29,7 @@ export type WorkflowState = {
|
||||
addNode: (node: WorkflowNode, previousNodeId: string) => void;
|
||||
updateNode: (node: WorkflowNode) => void;
|
||||
removeNode: (nodeId: string) => void;
|
||||
cancelClone: () => void;
|
||||
|
||||
addBranch: (branchId: string) => void;
|
||||
removeBranch: (branchId: string, index: number) => void;
|
||||
@ -203,6 +205,27 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
||||
});
|
||||
},
|
||||
|
||||
cancelClone: async () => {
|
||||
if (!get().initialized) throw "Workflow not initialized yet";
|
||||
|
||||
const root = removeCloneNode(get().workflow.draft!);
|
||||
|
||||
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;
|
||||
}),
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
addBranch: async (branchId: string) => {
|
||||
if (!get().initialized) throw "Workflow not initialized yet";
|
||||
|
||||
@ -247,3 +270,4 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
||||
return getOutputBeforeNodeId(get().workflow.draft as WorkflowNode, nodeId, type);
|
||||
},
|
||||
}));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user