Browse Source

Merge pull request #2281 from visuddhinanda/development

Development
visuddhinanda 1 year ago
parent
commit
925964475a

+ 20 - 4
dashboard-v4/dashboard/src/components/task/TaskBuilderChapter.tsx

@@ -32,6 +32,7 @@ import {
   TPower,
 } from "../api/token";
 import ProjectWithTasks from "./ProjectWithTasks";
+import { useIntl } from "react-intl";
 const { Text, Paragraph } = Typography;
 
 interface IModal {
@@ -88,6 +89,8 @@ const TaskBuilderChapter = ({
   style,
   channels,
 }: IWidget) => {
+  const intl = useIntl();
+
   const [current, setCurrent] = useState(0);
   const [workflow, setWorkflow] = useState<ITaskData[]>();
   const [chapter, setChapter] = useState<IChapterToc[]>();
@@ -98,6 +101,7 @@ const TaskBuilderChapter = ({
   const [loading, setLoading] = useState(false);
   const [projects, setProjects] = useState<IProjectTreeData[]>();
   const [done, setDone] = useState(false);
+
   const steps = [
     {
       title: "选择章节",
@@ -162,7 +166,15 @@ const TaskBuilderChapter = ({
       content: (
         <Workflow
           studioName={studioName}
-          onData={(data) => setWorkflow(data)}
+          onSelect={(data) => {
+            if (typeof data === "undefined") {
+              setWorkflow(undefined);
+            }
+          }}
+          onData={(data) => {
+            console.debug("workflow", data);
+            setWorkflow(data);
+          }}
         />
       ),
     },
@@ -386,15 +398,19 @@ const TaskBuilderChapter = ({
             disabled={current === 0}
             onClick={() => prev()}
           >
-            Previous
+            {intl.formatMessage({ id: "buttons.previous" })}
           </Button>
         ) : (
           <></>
         )}
 
         {current < steps.length - 2 && (
-          <Button type="primary" onClick={() => next()}>
-            Next
+          <Button
+            type="primary"
+            disabled={current === 1 && typeof workflow === "undefined"}
+            onClick={() => next()}
+          >
+            {intl.formatMessage({ id: "buttons.next" })}
           </Button>
         )}
         {current === steps.length - 2 && (

+ 22 - 60
dashboard-v4/dashboard/src/components/task/TaskList.tsx

@@ -9,8 +9,6 @@ import {
   IProjectData,
   IProjectResponse,
   ITaskData,
-  ITaskGroupInsertRequest,
-  ITaskGroupResponse,
   ITaskListResponse,
   ITaskResponse,
   ITaskUpdateRequest,
@@ -22,11 +20,11 @@ import { GroupIcon } from "../../assets/icon";
 import Options, { IMenu } from "./Options";
 import Filter from "./Filter";
 import { Milestone } from "./TaskReader";
-import { WorkflowModal } from "./Workflow";
 import Assignees from "./Assignees";
 import TaskStatusButton from "./TaskStatusButton";
 import Executors from "./Executors";
 import Category from "./Category";
+import TaskListAdd from "./TaskListAdd";
 
 const { Text } = Typography;
 
@@ -406,19 +404,7 @@ const TaskList = ({
         }}
         actionRef={actionRef}
         // 关闭默认的新建按钮
-        recordCreatorProps={
-          editable && project
-            ? {
-                record: () => ({
-                  id: generateUUID(),
-                  title: "新建任务",
-                  type: project.type === "workflow" ? "workflow" : "instance",
-                  is_milestone: false,
-                  status: "pending",
-                }),
-              }
-            : false
-        }
+        recordCreatorProps={false}
         columns={columns}
         request={async (params = {}, sorter, filter) => {
           let url = `/v2/task?a=a`;
@@ -612,51 +598,27 @@ const TaskList = ({
               actionRef.current?.reload();
             }}
           />,
-          editable && (
-            <WorkflowModal
-              tiger={<Button type="primary">从模版创建任务</Button>}
-              studioName={studioName}
-              onData={(data) => {
-                if (!projectId || !project) {
-                  return;
-                }
-                const url = "/v2/task-group";
-                const values: ITaskGroupInsertRequest = {
-                  data: [
-                    {
-                      project_id: projectId,
-                      tasks: data.map((item) => {
-                        return {
-                          id: item.id,
-                          title: item.title,
-                          type:
-                            project.type === "workflow"
-                              ? "workflow"
-                              : "instance",
-                          order: item.order,
-                          status: item.status,
-                          parent_id: item.parent_id,
-                          project_id: projectId,
-                          is_milestone: item.is_milestone,
-                        };
-                      }),
-                    },
-                  ],
-                };
-                console.info("api request", url, values);
-                post<ITaskGroupInsertRequest, ITaskGroupResponse>(
-                  url,
-                  values
-                ).then((json) => {
-                  console.info("api response", json);
-                  if (json.ok) {
-                    message.success("ok");
-                    actionRef.current?.reload();
-                  }
+          <TaskListAdd
+            studioName={studioName}
+            projectId={projectId}
+            project={project}
+            readonly={!editable}
+            onAddNew={() => {
+              if (project) {
+                actionRef.current?.addEditRecord?.({
+                  id: generateUUID(),
+                  title: "新建任务",
+                  type: project.type === "workflow" ? "workflow" : "instance",
+                  is_milestone: false,
+                  status: "pending",
                 });
-              }}
-            />
-          ),
+              }
+            }}
+            onWorkflow={() => {
+              message.success("ok");
+              actionRef.current?.reload();
+            }}
+          />,
         ]}
       />
       <TaskEditDrawer

+ 106 - 0
dashboard-v4/dashboard/src/components/task/TaskListAdd.tsx

@@ -0,0 +1,106 @@
+import { Dropdown } from "antd";
+import { DownOutlined } from "@ant-design/icons";
+import type { MenuProps } from "antd";
+import {
+  IProjectData,
+  ITaskGroupInsertRequest,
+  ITaskGroupResponse,
+} from "../api/task";
+import { useState } from "react";
+import { WorkflowModal } from "./Workflow";
+import { post } from "../../request";
+import { useIntl } from "react-intl";
+
+interface IWidget {
+  studioName?: string;
+  projectId?: string;
+  project?: IProjectData;
+  readonly?: boolean;
+  onAddNew: () => void;
+  onWorkflow: () => void;
+}
+const TaskListAdd = ({
+  studioName,
+  projectId,
+  project,
+  readonly = false,
+  onAddNew,
+  onWorkflow,
+}: IWidget) => {
+  const intl = useIntl();
+
+  const [open, setOpen] = useState(false);
+
+  const items: MenuProps["items"] = [
+    {
+      label: "从工作流创建任务",
+      key: "workflow",
+    },
+  ];
+  return (
+    <>
+      <Dropdown.Button
+        type="primary"
+        icon={<DownOutlined />}
+        disabled={readonly}
+        menu={{
+          items,
+          onClick: (info) => {
+            switch (info.key) {
+              case "workflow":
+                setOpen(true);
+                break;
+
+              default:
+                break;
+            }
+          },
+        }}
+        onClick={onAddNew}
+      >
+        {intl.formatMessage({ id: "buttons.add" })}
+      </Dropdown.Button>
+
+      <WorkflowModal
+        studioName={studioName}
+        open={open}
+        onClose={() => setOpen(false)}
+        onOk={(data) => {
+          if (!projectId || !project || !data) {
+            return;
+          }
+          const url = "/v2/task-group";
+          const values: ITaskGroupInsertRequest = {
+            data: [
+              {
+                project_id: projectId,
+                tasks: data.map((item) => {
+                  return {
+                    id: item.id,
+                    title: item.title,
+                    type: project.type === "workflow" ? "workflow" : "instance",
+                    order: item.order,
+                    status: item.status,
+                    parent_id: item.parent_id,
+                    project_id: projectId,
+                    is_milestone: item.is_milestone,
+                  };
+                }),
+              },
+            ],
+          };
+          console.info("api request", url, values);
+          post<ITaskGroupInsertRequest, ITaskGroupResponse>(url, values).then(
+            (json) => {
+              console.info("api response", json);
+              if (json.ok) {
+                onWorkflow();
+              }
+            }
+          );
+        }}
+      />
+    </>
+  );
+};
+export default TaskListAdd;

+ 56 - 20
dashboard-v4/dashboard/src/components/task/Workflow.tsx

@@ -1,36 +1,51 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
 import { IProjectData, ITaskData } from "../api/task";
 import ProjectList, { TView } from "./ProjectList";
 import ProjectTask from "./ProjectTask";
 import { Button, Card, Modal, Tree } from "antd";
 import { ArrowLeftOutlined } from "@ant-design/icons";
 import { Key } from "antd/es/table/interface";
+import { useIntl } from "react-intl";
 
 interface IModal {
   tiger?: React.ReactNode;
   studioName?: string;
-  onSelect?: (data: IProjectData) => void;
-  onData?: (data: ITaskData[]) => void;
+  open?: boolean;
+  onClose?: () => void;
+  onSelect?: (data: IProjectData | undefined) => void;
+  onOk?: (data: ITaskData[] | undefined) => void;
 }
 export const WorkflowModal = ({
   tiger,
   studioName,
+  open,
   onSelect,
-  onData,
+  onOk,
+  onClose,
 }: IModal) => {
-  const [open, setOpen] = useState(false);
+  const [openModal, setOpenModal] = useState(open);
   const [data, setData] = useState<ITaskData[]>();
+
+  useEffect(() => setOpenModal(open), [open]);
+
   const showModal = () => {
-    setOpen(true);
+    setOpenModal(true);
   };
 
   const handleOk = () => {
-    onData && data && onData(data);
-    setOpen(false);
+    if (onOk) {
+      onOk(data);
+    } else {
+      setOpenModal(false);
+    }
   };
 
   const handleCancel = () => {
-    setOpen(false);
+    if (onClose) {
+      onClose();
+    } else {
+      setOpenModal(false);
+    }
   };
   return (
     <>
@@ -40,11 +55,15 @@ export const WorkflowModal = ({
         width={1200}
         style={{ top: 10 }}
         title={""}
-        open={open}
+        open={openModal}
         onOk={handleOk}
         onCancel={handleCancel}
       >
-        <Workflow studioName={studioName} onData={(data) => setData(data)} />
+        <Workflow
+          studioName={studioName}
+          onData={(data) => setData(data)}
+          onSelect={onSelect}
+        />
       </Modal>
     </>
   );
@@ -52,13 +71,20 @@ export const WorkflowModal = ({
 
 interface IWidget {
   studioName?: string;
-  onSelect?: (data: IProjectData) => void;
-  onData?: (data: ITaskData[]) => void;
+  onSelect?: (data: IProjectData | undefined) => void;
+  onData?: (data: ITaskData[] | undefined) => void;
 }
 
 const Workflow = ({ studioName, onSelect, onData }: IWidget) => {
+  const intl = useIntl();
+
   const [project, setProject] = useState<IProjectData>();
   const [view, setView] = useState<TView>("studio");
+
+  const selectWorkflow = (selected: IProjectData | undefined) => {
+    onSelect && onSelect(selected);
+    setProject(selected);
+  };
   return (
     <div style={{ display: "flex" }}>
       <div style={{ minWidth: 200, flex: 1 }}>
@@ -66,15 +92,23 @@ const Workflow = ({ studioName, onSelect, onData }: IWidget) => {
           multiple={false}
           defaultSelectedKeys={["studio"]}
           treeData={[
-            { title: "my", key: "studio" },
-            { title: "shared", key: "shared" },
-            { title: "community", key: "community" },
-            { title: "authors", key: "authors" },
+            {
+              title: intl.formatMessage({ id: "labels.this-studio" }),
+              key: "studio",
+            },
+            {
+              title: intl.formatMessage({ id: "labels.shared" }),
+              key: "shared",
+            },
+            {
+              title: intl.formatMessage({ id: "labels.community" }),
+              key: "community",
+            },
           ]}
           onSelect={(selectedKeys: Key[]) => {
             console.debug("selectedKeys", selectedKeys);
             if (selectedKeys.length > 0) {
-              setProject(undefined);
+              selectWorkflow(undefined);
               setView(selectedKeys[0].toString() as TView);
             }
           }}
@@ -89,7 +123,9 @@ const Workflow = ({ studioName, onSelect, onData }: IWidget) => {
                   <Button
                     type="link"
                     icon={<ArrowLeftOutlined />}
-                    onClick={() => setProject(undefined)}
+                    onClick={() => {
+                      selectWorkflow(undefined);
+                    }}
                   />
                   {project.title}
                 </>
@@ -116,7 +152,7 @@ const Workflow = ({ studioName, onSelect, onData }: IWidget) => {
             view={view}
             type="workflow"
             readonly
-            onSelect={(data: IProjectData) => setProject(data)}
+            onSelect={(data: IProjectData) => selectWorkflow(data)}
           />
         </div>
       </div>

+ 2 - 0
dashboard-v4/dashboard/src/locales/en-US/buttons.ts

@@ -105,6 +105,8 @@ const items = {
   "buttons.task.add.next-task": "next task",
   "buttons.remove.milestone": "remove milestone",
   "buttons.set.milestone": "set as milestone",
+  "buttons.next": "Next",
+  "buttons.previous": "Previous",
 };
 
 export default items;

+ 6 - 4
dashboard-v4/dashboard/src/locales/en-US/label.ts

@@ -85,10 +85,12 @@ const items = {
   "labels.filters.and": "and",
   "labels.filters.or": "or",
   "labels.task.workflows": "Workflows",
-  "labels.milestone": "milestone",
-  "labels.flowchart": "flowchart",
-  "labels.table": "table",
-  "labels.list": "list",
+  "labels.milestone": "Milestone",
+  "labels.flowchart": "Flowchart",
+  "labels.table": "Table",
+  "labels.list": "List",
+  "labels.shared": "Shared",
+  "labels.community": "Community",
 };
 
 export default items;

+ 2 - 0
dashboard-v4/dashboard/src/locales/zh-Hans/buttons.ts

@@ -106,6 +106,8 @@ const items = {
   "buttons.task.add.next-task": "添加后置任务",
   "buttons.remove.milestone": "移除里程碑",
   "buttons.set.milestone": "设置为里程碑",
+  "buttons.next": "下一步",
+  "buttons.previous": "上一步",
 };
 
 export default items;

+ 2 - 0
dashboard-v4/dashboard/src/locales/zh-Hans/label.ts

@@ -97,6 +97,8 @@ const items = {
   "labels.flowchart": "流程图",
   "labels.table": "表格",
   "labels.list": "列表",
+  "labels.shared": "共享",
+  "labels.community": "社区",
 };
 
 export default items;