Browse Source

Merge pull request #2288 from visuddhinanda/development

Development
visuddhinanda 1 year ago
parent
commit
e6105ffc15

+ 1 - 1
api-v8/app/Http/Api/TaskApi.php

@@ -83,7 +83,7 @@ class TaskApi
     public static function getRelationTasks($taskId, $relation = 'pre')
     {
         $key = TaskApi::taskRelationRedisKey($taskId, $relation);
-        Log::debug('task redis key=' . $key . ' has=' . RedisClusters::has($key));
+        //Log::debug('task redis key=' . $key . ' has=' . RedisClusters::has($key));
         $data = RedisClusters::remember($key, 3 * 24 * 3600, function () use ($taskId, $relation) {
             Log::debug('getRelationTasks task=' . $taskId . ' relation=' . $relation);
             if ($relation === 'pre') {

+ 7 - 0
api-v8/app/Http/Controllers/TaskController.php

@@ -77,6 +77,13 @@ class TaskController extends Controller
                 ->select('task_id')->get();
             $table = $table->whereNotIn('id', $assigneesTasks);
         }
+        //指派给
+        if ($request->has('assignees_id_null')) {
+            $table = $table->doesntHave('task_assignees');
+        }
+        if ($request->has('assignees_id_not-null')) {
+            $table = $table->has('task_assignees');
+        }
 
         if ($request->get('sign_up_equals') === 'true') {
             $table = $table->whereNull('assignees_id')

+ 6 - 0
api-v8/app/Models/Task.php

@@ -20,4 +20,10 @@ class Task extends Model
         'started_at',
         'finished_at',
     ];
+
+    // app/Models/User.php
+    public function task_assignees()
+    {
+        return $this->hasMany(TaskAssignee::class, 'task_id', 'id');
+    }
 }

+ 9 - 0
dashboard-v4/dashboard/src/components/task/Filter.tsx

@@ -5,6 +5,7 @@ import { useIntl } from "react-intl";
 import UserSelect from "../template/UserSelect";
 import {
   ProForm,
+  ProFormDependency,
   ProFormInstance,
   ProFormSelect,
 } from "@ant-design/pro-components";
@@ -19,6 +20,7 @@ interface IProps {
 }
 const FilterItem = ({ item, sn, onRemove }: IProps) => {
   const intl = useIntl();
+  const [operator, setOperator] = useState<string | null>(item.operator);
   return (
     <ProForm.Group>
       <ProFormSelect
@@ -42,6 +44,12 @@ const FilterItem = ({ item, sn, onRemove }: IProps) => {
       />
       <ProFormSelect
         initialValue={item.operator}
+        fieldProps={{
+          value: operator,
+          onChange(value, option) {
+            setOperator(value);
+          },
+        }}
         name={`operator_${sn}`}
         style={{ width: 120 }}
         options={[
@@ -64,6 +72,7 @@ const FilterItem = ({ item, sn, onRemove }: IProps) => {
         initialValue={item.value}
         required={false}
         hiddenTitle
+        hidden={operator === "null" || operator === "not-null"}
       />
       <Button type="link" icon={<DeleteOutlined />} danger onClick={onRemove} />
     </ProForm.Group>

+ 86 - 0
dashboard-v4/dashboard/src/components/task/TaskFlowchart.tsx

@@ -0,0 +1,86 @@
+import { ITaskData } from "../api/task";
+import Mermaid from "../general/Mermaid";
+
+interface IWidget {
+  tasks?: ITaskData[];
+}
+const TaskFlowchart = ({ tasks }: IWidget) => {
+  let mermaidText = "flowchart LR\n";
+
+  //节点样式
+  const color = [
+    {
+      status: "pending",
+      fill: "#fafafa",
+      stroke: "#d9d9d9",
+      color: "#000000d9",
+    },
+    {
+      status: "published",
+      fill: "#fff7e6",
+      stroke: "#ffd591",
+      color: "#d46b08",
+    },
+    { status: "running", fill: "#e6f7ff", stroke: "#91d5ff", color: "#1890ff" },
+    { status: "done", fill: "#f6ffed", stroke: "#b7eb8f", color: "#52c41a" },
+    {
+      status: "restarted",
+      fill: "r#fff2f0",
+      stroke: "#ffccc7",
+      color: "#ff4d4f",
+    },
+    {
+      status: "requested_restart",
+      fill: "#fffbe6",
+      stroke: "#ffe58f",
+      color: "#faad14",
+    },
+    { status: "closed", fill: "yellow", stroke: "#333", color: "#333" },
+    { status: "canceled", fill: "gray", stroke: "#333", color: "#333" },
+    { status: "expired", fill: "brown", stroke: "#333", color: "#333" },
+  ];
+
+  color.forEach((value) => {
+    mermaidText += `classDef ${value.status} fill:${value.fill},stroke:${value.stroke},color:${value.color},stroke-width:1px;\n`;
+  });
+
+  let relationLine = new Map<string, number>();
+  tasks?.forEach((task: ITaskData, index: number, array: ITaskData[]) => {
+    //输出节点
+    mermaidText += `${task.id}[${task.title}]:::${task.status};\n`;
+
+    //输出带有子任务的节点
+    const children = array.filter(
+      (value: ITaskData, index: number, array: ITaskData[]) => {
+        return value.parent_id === task.id;
+      }
+    );
+    if (children.length > 0) {
+      mermaidText += `subgraph ${task.id} ["${task.title}"]\n`;
+      mermaidText += `${children.map((task) => task.id).join(`;\n`)}`;
+      mermaidText += ";\nend\n";
+    }
+
+    //关系线
+    task.pre_task?.map((item) =>
+      relationLine.set(`${item.id} --> ${task.id};\n`, 0)
+    );
+    task.next_task?.map((item) =>
+      relationLine.set(`${task.id} --> ${item.id};\n`, 0)
+    );
+  });
+
+  Array.from(relationLine.keys()).forEach((value) => {
+    mermaidText += value;
+  });
+
+  console.debug(mermaidText);
+
+  return (
+    <div>
+      <Mermaid text={mermaidText} />
+    </div>
+  );
+};
+
+export default TaskFlowchart;

+ 23 - 75
dashboard-v4/dashboard/src/components/task/TaskRelation.tsx

@@ -1,89 +1,37 @@
-import { ITaskData } from "../api/task";
+import { Collapse } from "antd";
+import { IProject, ITaskData } from "../api/task";
+import TaskFlowchart from "./TaskFlowchart";
 
-import "../article/article.css";
-
-import Mermaid from "../general/Mermaid";
+const { Panel } = Collapse;
 
 interface IWidget {
   projectId?: string;
   tasks?: ITaskData[];
 }
 const TaskRelation = ({ tasks }: IWidget) => {
-  let mermaidText = "flowchart LR\n";
-
-  //节点样式
-  const color = [
-    {
-      status: "pending",
-      fill: "#fafafa",
-      stroke: "#d9d9d9",
-      color: "#000000d9",
-    },
-    {
-      status: "published",
-      fill: "#fff7e6",
-      stroke: "#ffd591",
-      color: "#d46b08",
-    },
-    { status: "running", fill: "#e6f7ff", stroke: "#91d5ff", color: "#1890ff" },
-    { status: "done", fill: "#f6ffed", stroke: "#b7eb8f", color: "#52c41a" },
-    {
-      status: "restarted",
-      fill: "r#fff2f0",
-      stroke: "#ffccc7",
-      color: "#ff4d4f",
-    },
-    {
-      status: "requested_restart",
-      fill: "#fffbe6",
-      stroke: "#ffe58f",
-      color: "#faad14",
-    },
-    { status: "closed", fill: "yellow", stroke: "#333", color: "#333" },
-    { status: "canceled", fill: "gray", stroke: "#333", color: "#333" },
-    { status: "expired", fill: "brown", stroke: "#333", color: "#333" },
-  ];
-
-  color.forEach((value) => {
-    mermaidText += `classDef ${value.status} fill:${value.fill},stroke:${value.stroke},color:${value.color},stroke-width:1px;\n`;
+  const projects = new Map<string, IProject>();
+  tasks?.forEach((value) => {
+    value.project && projects.set(value.project.id, value.project);
   });
-
-  let relationLine = new Map<string, number>();
-  tasks?.forEach((task: ITaskData, index: number, array: ITaskData[]) => {
-    //输出节点
-    mermaidText += `${task.id}[${task.title}]:::${task.status};\n`;
-
-    //输出带有子任务的节点
-    const children = array.filter(
-      (value: ITaskData, index: number, array: ITaskData[]) => {
-        return value.parent_id === task.id;
-      }
-    );
-    if (children.length > 0) {
-      mermaidText += `subgraph ${task.id} ["${task.title}"]\n`;
-      mermaidText += `${children.map((task) => task.id).join(`;\n`)}`;
-      mermaidText += ";\nend\n";
-    }
-
-    //关系线
-    task.pre_task?.map((item) =>
-      relationLine.set(`${item.id} --> ${task.id};\n`, 0)
-    );
-    task.next_task?.map((item) =>
-      relationLine.set(`${task.id} --> ${item.id};\n`, 0)
-    );
-  });
-
-  Array.from(relationLine.keys()).forEach((value) => {
-    mermaidText += value;
+  let flowcharts: IProject[] = [];
+  projects.forEach((value: IProject, key: string) => {
+    flowcharts.push(value);
   });
 
-  console.debug(mermaidText);
-
   return (
-    <div>
-      <Mermaid text={mermaidText} />
-    </div>
+    <Collapse
+      defaultActiveKey={Array.from({ length: flowcharts.length }, (_, i) => i)}
+    >
+      {flowcharts.map((item, id) => {
+        return (
+          <Panel header={item.title} key={id}>
+            <TaskFlowchart
+              tasks={tasks?.filter((value) => value.project_id === item.id)}
+            />
+          </Panel>
+        );
+      })}
+    </Collapse>
   );
 };
 

+ 3 - 3
dashboard-v4/dashboard/src/pages/studio/task/hall.tsx

@@ -13,9 +13,9 @@ const Widget = () => {
       status={["published"]}
       filters={[
         {
-          field: "sign_up",
-          operator: "equals",
-          value: "true",
+          field: "assignees_id",
+          operator: "null",
+          value: "",
         },
       ]}
     />