mirror of https://github.com/usual2970/certimate
				
				
				
			feat(ui): disable nodes during workflow running
							parent
							
								
									52dfa5e8c3
								
							
						
					
					
						commit
						2213399f5e
					
				| 
						 | 
				
			
			@ -44,8 +44,6 @@ var sslProviderUrls = map[string]string{
 | 
			
		|||
	sslProviderGts:         gtsUrl,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultEmail = "536464346@qq.com"
 | 
			
		||||
 | 
			
		||||
type Certificate struct {
 | 
			
		||||
	CertUrl           string `json:"certUrl"`
 | 
			
		||||
	CertStableUrl     string `json:"certStableUrl"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,10 @@ import AddNode from "./node/AddNode";
 | 
			
		|||
 | 
			
		||||
export type NodeProps = {
 | 
			
		||||
  node: WorkflowNode;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const WorkflowElement = ({ node }: NodeProps) => {
 | 
			
		||||
const WorkflowElement = ({ node, disabled }: NodeProps) => {
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
  const { updateNode, removeNode } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeNode"]));
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +95,8 @@ const WorkflowElement = ({ node }: NodeProps) => {
 | 
			
		|||
  };
 | 
			
		||||
 | 
			
		||||
  const handleNodeClick = () => {
 | 
			
		||||
    if (disabled) return;
 | 
			
		||||
 | 
			
		||||
    showPanel({
 | 
			
		||||
      name: node.name,
 | 
			
		||||
      children: <PanelBody data={node} />,
 | 
			
		||||
| 
						 | 
				
			
			@ -111,10 +114,13 @@ const WorkflowElement = ({ node }: NodeProps) => {
 | 
			
		|||
                items: [
 | 
			
		||||
                  {
 | 
			
		||||
                    key: "delete",
 | 
			
		||||
                    disabled: disabled,
 | 
			
		||||
                    label: t("workflow_node.action.delete_node"),
 | 
			
		||||
                    icon: <CloseCircleOutlinedIcon />,
 | 
			
		||||
                    danger: true,
 | 
			
		||||
                    onClick: () => {
 | 
			
		||||
                      if (disabled) return;
 | 
			
		||||
 | 
			
		||||
                      removeNode(node.id);
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +156,7 @@ const WorkflowElement = ({ node }: NodeProps) => {
 | 
			
		|||
        </Card>
 | 
			
		||||
      </Popover>
 | 
			
		||||
 | 
			
		||||
      <AddNode node={node} />
 | 
			
		||||
      <AddNode node={node} disabled={disabled} />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,10 @@ import { useWorkflowStore } from "@/stores/workflow";
 | 
			
		|||
export type WorkflowElementsProps = {
 | 
			
		||||
  className?: string;
 | 
			
		||||
  style?: React.CSSProperties;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const WorkflowElements = ({ className, style }: WorkflowElementsProps) => {
 | 
			
		||||
const WorkflowElements = ({ className, style, disabled }: WorkflowElementsProps) => {
 | 
			
		||||
  const { workflow } = useWorkflowStore(useZustandShallowSelector(["workflow"]));
 | 
			
		||||
 | 
			
		||||
  const elements = useMemo(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +21,7 @@ const WorkflowElements = ({ className, style }: WorkflowElementsProps) => {
 | 
			
		|||
 | 
			
		||||
    let current = workflow.draft as WorkflowNode;
 | 
			
		||||
    while (current) {
 | 
			
		||||
      nodes.push(<NodeRender node={current} key={current.id} />);
 | 
			
		||||
      nodes.push(<NodeRender key={current.id} node={current} disabled={disabled} />);
 | 
			
		||||
      current = current.next as WorkflowNode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,10 @@ import { useWorkflowStore } from "@/stores/workflow";
 | 
			
		|||
 | 
			
		||||
export type AddNodeProps = {
 | 
			
		||||
  node: WorkflowNode;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AddNode = ({ node }: AddNodeProps) => {
 | 
			
		||||
const AddNode = ({ node, disabled }: AddNodeProps) => {
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
  const { addNode } = useWorkflowStore(useZustandShallowSelector(["addNode"]));
 | 
			
		||||
| 
						 | 
				
			
			@ -31,20 +32,19 @@ const AddNode = ({ node }: AddNodeProps) => {
 | 
			
		|||
    ].map(([type, label, icon]) => {
 | 
			
		||||
      return {
 | 
			
		||||
        key: type as string,
 | 
			
		||||
        disabled: true,
 | 
			
		||||
        label: t(label as string),
 | 
			
		||||
        icon: icon,
 | 
			
		||||
        onClick: () => {
 | 
			
		||||
          handleNodeTypeSelect(type as WorkflowNodeType);
 | 
			
		||||
          if (disabled) return;
 | 
			
		||||
 | 
			
		||||
          const nextNode = newNode(type as WorkflowNodeType);
 | 
			
		||||
          addNode(nextNode, node.id);
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const handleNodeTypeSelect = (type: WorkflowNodeType) => {
 | 
			
		||||
    const nextNode = newNode(type);
 | 
			
		||||
    addNode(nextNode, node.id);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="relative py-6 before:absolute before:left-1/2 before:top-0 before:h-full before:w-[2px] before:-translate-x-1/2 before:bg-stone-200 before:content-['']">
 | 
			
		||||
      <Dropdown menu={{ items: dropdownMenus }} trigger={["click"]}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,10 @@ import NodeRender from "./NodeRender";
 | 
			
		|||
 | 
			
		||||
export type BrandNodeProps = {
 | 
			
		||||
  node: WorkflowNode;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const BranchNode = ({ node }: BrandNodeProps) => {
 | 
			
		||||
const BranchNode = ({ node, disabled }: BrandNodeProps) => {
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
  const { addBranch } = useWorkflowStore(useZustandShallowSelector(["addBranch"]));
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +24,7 @@ const BranchNode = ({ node }: BrandNodeProps) => {
 | 
			
		|||
 | 
			
		||||
    let current = node as WorkflowNode | undefined;
 | 
			
		||||
    while (current) {
 | 
			
		||||
      elements.push(<NodeRender key={current.id} node={current} branchId={branchNodeId} branchIndex={branchIndex} />);
 | 
			
		||||
      elements.push(<NodeRender key={current.id} node={current} branchId={branchNodeId} branchIndex={branchIndex} disabled={disabled} />);
 | 
			
		||||
      current = current.next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,7 @@ const BranchNode = ({ node }: BrandNodeProps) => {
 | 
			
		|||
      <div className="relative flex gap-x-16 before:absolute before:inset-x-[128px] before:top-0 before:h-[2px] before:bg-stone-200 before:content-[''] after:absolute after:inset-x-[128px] after:bottom-0 after:h-[2px] after:bg-stone-200 after:content-['']">
 | 
			
		||||
        <Button
 | 
			
		||||
          className="absolute left-1/2 z-[1] -translate-x-1/2 -translate-y-1/2 text-xs"
 | 
			
		||||
          disabled={disabled}
 | 
			
		||||
          size="small"
 | 
			
		||||
          shape="round"
 | 
			
		||||
          variant="outlined"
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +57,7 @@ const BranchNode = ({ node }: BrandNodeProps) => {
 | 
			
		|||
        ))}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <AddNode node={node} />
 | 
			
		||||
      <AddNode node={node} disabled={disabled} />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,12 @@ import AddNode from "./AddNode";
 | 
			
		|||
 | 
			
		||||
export type ConditionNodeProps = {
 | 
			
		||||
  node: WorkflowNode;
 | 
			
		||||
  branchId?: string;
 | 
			
		||||
  branchIndex?: number;
 | 
			
		||||
  branchId: string;
 | 
			
		||||
  branchIndex: number;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ConditionNode = ({ node, branchId, branchIndex }: ConditionNodeProps) => {
 | 
			
		||||
const ConditionNode = ({ node, branchId, branchIndex, disabled }: ConditionNodeProps) => {
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
 | 
			
		||||
  const { updateNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeBranch"]));
 | 
			
		||||
| 
						 | 
				
			
			@ -44,11 +45,14 @@ const ConditionNode = ({ node, branchId, branchIndex }: ConditionNodeProps) => {
 | 
			
		|||
              items: [
 | 
			
		||||
                {
 | 
			
		||||
                  key: "delete",
 | 
			
		||||
                  disabled: disabled,
 | 
			
		||||
                  label: t("workflow_node.action.delete_branch"),
 | 
			
		||||
                  icon: <CloseCircleOutlinedIcon />,
 | 
			
		||||
                  danger: true,
 | 
			
		||||
                  onClick: () => {
 | 
			
		||||
                    removeBranch(branchId ?? "", branchIndex ?? 0);
 | 
			
		||||
                    if (disabled) return;
 | 
			
		||||
 | 
			
		||||
                    removeBranch(branchId!, branchIndex!);
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              ],
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +80,7 @@ const ConditionNode = ({ node, branchId, branchIndex }: ConditionNodeProps) => {
 | 
			
		|||
        </Card>
 | 
			
		||||
      </Popover>
 | 
			
		||||
 | 
			
		||||
      <AddNode node={node} />
 | 
			
		||||
      <AddNode node={node} disabled={disabled} />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,22 +11,23 @@ export type NodeRenderProps = {
 | 
			
		|||
  node: WorkflowNode;
 | 
			
		||||
  branchId?: string;
 | 
			
		||||
  branchIndex?: number;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const NodeRender = ({ node: data, branchId, branchIndex }: NodeRenderProps) => {
 | 
			
		||||
const NodeRender = ({ node: data, branchId, branchIndex, disabled }: NodeRenderProps) => {
 | 
			
		||||
  const render = () => {
 | 
			
		||||
    switch (data.type) {
 | 
			
		||||
      case WorkflowNodeType.Start:
 | 
			
		||||
      case WorkflowNodeType.Apply:
 | 
			
		||||
      case WorkflowNodeType.Deploy:
 | 
			
		||||
      case WorkflowNodeType.Notify:
 | 
			
		||||
        return <WorkflowElement node={data} />;
 | 
			
		||||
        return <WorkflowElement node={data} disabled={disabled} />;
 | 
			
		||||
      case WorkflowNodeType.End:
 | 
			
		||||
        return <EndNode />;
 | 
			
		||||
      case WorkflowNodeType.Branch:
 | 
			
		||||
        return <BranchNode node={data} />;
 | 
			
		||||
        return <BranchNode node={data} disabled={disabled} />;
 | 
			
		||||
      case WorkflowNodeType.Condition:
 | 
			
		||||
        return <ConditionNode node={data as WorkflowNode} branchId={branchId} branchIndex={branchIndex} />;
 | 
			
		||||
        return <ConditionNode node={data as WorkflowNode} branchId={branchId!} branchIndex={branchIndex!} disabled={disabled} />;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ const WorkflowDetail = () => {
 | 
			
		|||
          <Show when={tabValue === "orchestration"}>
 | 
			
		||||
            <div className="relative">
 | 
			
		||||
              <div className="py-12 lg:pr-36 xl:pr-48">
 | 
			
		||||
                <WorkflowElements />
 | 
			
		||||
                <WorkflowElements disabled={isRunning} />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="absolute right-0 top-0 z-[1]">
 | 
			
		||||
                <Space>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue