group tasks
parent
346839917b
commit
da125051f3
|
@ -2,12 +2,18 @@ import { Route, Routes } from "react-router-dom";
|
||||||
import Dashboard from "../../Pages/Dashboard";
|
import Dashboard from "../../Pages/Dashboard";
|
||||||
import GroupTasks from "../../Pages/GroupTasks";
|
import GroupTasks from "../../Pages/GroupTasks";
|
||||||
|
|
||||||
function AppRoutes() {
|
export default function AppRoutes() {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Dashboard />}></Route>
|
<Route path="/" element={<Dashboard />} />
|
||||||
<Route path="/group-tasks" element={<GroupTasks />}></Route>
|
<Route
|
||||||
|
path="/group-tasks"
|
||||||
|
element={<GroupTasks isGroupTasksViewModalOpen={false} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/group-tasks/:groupTaskId"
|
||||||
|
element={<GroupTasks isGroupTasksViewModalOpen={true} />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default AppRoutes;
|
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
import {
|
|
||||||
Alert,
|
|
||||||
Button,
|
|
||||||
Divider,
|
|
||||||
Form,
|
|
||||||
Input,
|
|
||||||
Modal,
|
|
||||||
Steps,
|
|
||||||
message,
|
|
||||||
} from "antd";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
{
|
|
||||||
title: "First",
|
|
||||||
content: "First-content",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Second",
|
|
||||||
content: "Second-content",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Last",
|
|
||||||
content: "Last-content",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const contentData = [
|
|
||||||
<Form layout="vertical">
|
|
||||||
<Form.Item label="Format des Labels">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</Form>,
|
|
||||||
"",
|
|
||||||
<h1>hakki</h1>,
|
|
||||||
];
|
|
||||||
|
|
||||||
const consoleContentData = [
|
|
||||||
{
|
|
||||||
description: [
|
|
||||||
<p>
|
|
||||||
Error: An Uncaught Error at s
|
|
||||||
(https://ant.design/demos.a6f2ae2b.async.js:1:10244) at S
|
|
||||||
(https://ant.design/umi.996fb2f6.js:6081:13535) at u at a
|
|
||||||
(https://ant.design/umi.996fb2f6.js:41615:61022) at b
|
|
||||||
(https://ant.design/umi.996fb2f6.js:211:19559) at S
|
|
||||||
(https://ant.design/umi.996fb2f6.js:6081:13535) at section at section at
|
|
||||||
$t (https://ant.design/umi.996fb2f6.js:125:690029) at h4
|
|
||||||
(https://ant.design/umi.996fb2f6.js:211:1412)
|
|
||||||
</p>,
|
|
||||||
],
|
|
||||||
status: "error",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: [<p>Test</p>],
|
|
||||||
status: "success",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: [<p>Test</p>],
|
|
||||||
status: "warning",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function GroupTaskModal({ isOpen, setIsOpen }) {
|
|
||||||
const [currentStep, setCurrentStep] = useState(0);
|
|
||||||
const [content, setContent] = useState(contentData[currentStep]);
|
|
||||||
const [consoleContent, setConsoleContent] = useState(
|
|
||||||
consoleContentData[currentStep]
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateContentData = (value) => {
|
|
||||||
setContent(contentData[value]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const next = () => {
|
|
||||||
const val = currentStep + 1;
|
|
||||||
setCurrentStep(val);
|
|
||||||
updateContentData(val);
|
|
||||||
setConsoleContent(consoleContentData[val]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const prev = () => {
|
|
||||||
const val = currentStep - 1;
|
|
||||||
setCurrentStep(val);
|
|
||||||
updateContentData(val);
|
|
||||||
setConsoleContent(consoleContentData[val]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
setIsOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
open={isOpen}
|
|
||||||
width={"70%"}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
maskClosable={false}
|
|
||||||
>
|
|
||||||
<h1 style={{ color: "#e67e22", fontWeight: "bold" }}>
|
|
||||||
Produktionstask 1
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
<span style={{ fontWeight: "bold" }}>Started at:</span> 19.01.2023 -
|
|
||||||
11:14:30
|
|
||||||
</p>
|
|
||||||
<Steps
|
|
||||||
direction="vertical"
|
|
||||||
current={currentStep}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
title: "Bild zu Label konvertieren",
|
|
||||||
description: currentStep === 0 ? content : null,
|
|
||||||
onClick: (value) => console.log(value),
|
|
||||||
status: "error",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Label drucken",
|
|
||||||
description: currentStep === 1 ? content : null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Waiting",
|
|
||||||
description: currentStep === 2 ? content : null,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<div style={{ marginTop: 24 }}>
|
|
||||||
{currentStep < steps.length - 1 && (
|
|
||||||
<Button type="primary" onClick={() => next()}>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{currentStep === steps.length - 1 && (
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={() => message.success("Processing complete!")}
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{currentStep > 0 && (
|
|
||||||
<Button style={{ margin: "0 8px" }} onClick={() => prev()}>
|
|
||||||
Previous
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Divider />
|
|
||||||
<Alert
|
|
||||||
message={<b>{consoleContent.status}</b>}
|
|
||||||
description={consoleContent.description}
|
|
||||||
type={consoleContent.status}
|
|
||||||
showIcon
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { PlusOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||||
|
import { Badge, Button, Divider, Popconfirm, Space, Table } from "antd";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { FormatDatetime } from "../../utils";
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: "ID",
|
||||||
|
dataIndex: "id",
|
||||||
|
key: "id",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Group Name",
|
||||||
|
dataIndex: "groupName",
|
||||||
|
key: "groupName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Step",
|
||||||
|
dataIndex: "step",
|
||||||
|
key: "step",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Status",
|
||||||
|
dataIndex: "status",
|
||||||
|
key: "status",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Started At",
|
||||||
|
dataIndex: "startedAt",
|
||||||
|
key: "startedAt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Action",
|
||||||
|
dataIndex: "action",
|
||||||
|
key: "action",
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Link to={record.id}>View</Link>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
/*
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
key: "1",
|
||||||
|
id: "12312",
|
||||||
|
groupname: "Janex Device Acryl Led Lamp",
|
||||||
|
step: "6 / 6",
|
||||||
|
status: <Badge status="success" text="Finished" />,
|
||||||
|
datetime: "2020-01-01 12:00:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "2",
|
||||||
|
id: "9999",
|
||||||
|
groupname: "Acryl Glas schneiden",
|
||||||
|
step: "3 / 6",
|
||||||
|
status: <Badge status="error" text="Failed" />,
|
||||||
|
datetime: "2020-01-01 12:00:00",
|
||||||
|
},
|
||||||
|
]; */
|
||||||
|
|
||||||
|
export default function GroupTaskTableList({
|
||||||
|
categoryGroup,
|
||||||
|
showGroupTypeSelectionModal,
|
||||||
|
groupTasks,
|
||||||
|
}) {
|
||||||
|
const getStatusBadge = (status) => {
|
||||||
|
switch (status) {
|
||||||
|
case 0:
|
||||||
|
return <Badge status="success" text="Finished" />;
|
||||||
|
case 1:
|
||||||
|
return <Badge status="processing" text="Processing" />;
|
||||||
|
case 2:
|
||||||
|
return <Badge status="warning" text="Canceled" />;
|
||||||
|
case 3:
|
||||||
|
return <Badge status="error" text="Failed" />;
|
||||||
|
default:
|
||||||
|
return <Badge status="error" text="Status not found" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTableItems = () => {
|
||||||
|
let items = [];
|
||||||
|
|
||||||
|
groupTasks.forEach((groupTask) => {
|
||||||
|
if (groupTask.Category === categoryGroup.category) {
|
||||||
|
items.push({
|
||||||
|
key: groupTask.Id,
|
||||||
|
id: groupTask.Id,
|
||||||
|
groupName: groupTask.GroupName,
|
||||||
|
step: `${groupTask.CurrentTasksStep} / ${groupTask.NumberOfSteps}`,
|
||||||
|
status: getStatusBadge(groupTask.Status),
|
||||||
|
startedAt: FormatDatetime(groupTask.StartedAt),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider orientation="left">{categoryGroup.category}</Divider>
|
||||||
|
<Space
|
||||||
|
style={{
|
||||||
|
marginBottom: 16,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => showGroupTypeSelectionModal(categoryGroup)}
|
||||||
|
>
|
||||||
|
New task
|
||||||
|
</Button>
|
||||||
|
<Popconfirm
|
||||||
|
placement="left"
|
||||||
|
title="Are you sure you want to reload the group?"
|
||||||
|
okText="Yes"
|
||||||
|
>
|
||||||
|
<Button icon={<ReloadOutlined />}>Reload</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
<Table columns={columns} dataSource={getTableItems()} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,207 @@
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
Result,
|
||||||
|
Steps,
|
||||||
|
message,
|
||||||
|
} from "antd";
|
||||||
|
import { useContext, useState } from "react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { Constants, FormatDatetime, WebSocketContext } from "../../utils";
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
title: "First",
|
||||||
|
content: "First-content",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Second",
|
||||||
|
content: "Second-content",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Last",
|
||||||
|
content: "Last-content",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const contentData = [
|
||||||
|
<Form layout="vertical">
|
||||||
|
<Form.Item label="Format des Labels">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>,
|
||||||
|
"",
|
||||||
|
<h1>hakki</h1>,
|
||||||
|
];
|
||||||
|
|
||||||
|
const consoleContentData = [
|
||||||
|
{
|
||||||
|
description: [
|
||||||
|
<p>
|
||||||
|
Error: An Uncaught Error at s
|
||||||
|
(https://ant.design/demos.a6f2ae2b.async.js:1:10244) at S
|
||||||
|
(https://ant.design/umi.996fb2f6.js:6081:13535) at u at a
|
||||||
|
(https://ant.design/umi.996fb2f6.js:41615:61022) at b
|
||||||
|
(https://ant.design/umi.996fb2f6.js:211:19559) at S
|
||||||
|
(https://ant.design/umi.996fb2f6.js:6081:13535) at section at section at
|
||||||
|
$t (https://ant.design/umi.996fb2f6.js:125:690029) at h4
|
||||||
|
(https://ant.design/umi.996fb2f6.js:211:1412)
|
||||||
|
</p>,
|
||||||
|
],
|
||||||
|
status: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: [<p>Test</p>],
|
||||||
|
status: "success",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: [<p>Test</p>],
|
||||||
|
status: "warning",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function GroupTasksViewModal({ isOpen }) {
|
||||||
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
|
const [content, setContent] = useState(contentData[currentStep]);
|
||||||
|
const [consoleContent, setConsoleContent] = useState(
|
||||||
|
consoleContentData[currentStep]
|
||||||
|
);
|
||||||
|
const webSocketContext = useContext(WebSocketContext);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
let { groupTaskId } = useParams();
|
||||||
|
|
||||||
|
const updateContentData = (value) => {
|
||||||
|
setContent(contentData[value]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const next = () => {
|
||||||
|
const val = currentStep + 1;
|
||||||
|
setCurrentStep(val);
|
||||||
|
updateContentData(val);
|
||||||
|
setConsoleContent(consoleContentData[val]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const prev = () => {
|
||||||
|
const val = currentStep - 1;
|
||||||
|
setCurrentStep(val);
|
||||||
|
updateContentData(val);
|
||||||
|
setConsoleContent(consoleContentData[val]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
console.log("handleCancel", isOpen);
|
||||||
|
navigate(Constants.ROUTE_PATHS.GROUP_TASKS);
|
||||||
|
};
|
||||||
|
|
||||||
|
let currentGroupTask;
|
||||||
|
|
||||||
|
webSocketContext.GroupTasks.forEach((groupTask) => {
|
||||||
|
if (groupTask.Id === groupTaskId) {
|
||||||
|
currentGroupTask = groupTask;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// invalid group task id in url specified
|
||||||
|
if (!currentGroupTask) {
|
||||||
|
const handleCancel = () => navigate(Constants.ROUTE_PATHS.GROUP_TASKS);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={isOpen}
|
||||||
|
width="70%"
|
||||||
|
maskClosable={true}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
footer={<Button onClick={handleCancel}>Close</Button>}
|
||||||
|
>
|
||||||
|
<Result status="500" title="Group Task not found" />{" "}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={isOpen}
|
||||||
|
width="70%"
|
||||||
|
onCancel={handleCancel}
|
||||||
|
maskClosable={false}
|
||||||
|
>
|
||||||
|
{webSocketContext.GroupTasks.map((groupTask) => {
|
||||||
|
if (groupTask.Id === groupTaskId) {
|
||||||
|
console.log("groupTask", groupTask);
|
||||||
|
|
||||||
|
let currentGroupTask = groupTask;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 style={{ color: "#e67e22", fontWeight: "bold" }}>
|
||||||
|
{currentGroupTask.GroupName}
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
<span style={{ fontWeight: "bold" }}>ID:</span> {groupTaskId}{" "}
|
||||||
|
<br />
|
||||||
|
<span style={{ fontWeight: "bold" }}>Category:</span>{" "}
|
||||||
|
{currentGroupTask.Category}
|
||||||
|
<br />
|
||||||
|
<span style={{ fontWeight: "bold" }}>Started at:</span>{" "}
|
||||||
|
{FormatDatetime(currentGroupTask.StartedAt)}
|
||||||
|
</p>
|
||||||
|
<Steps
|
||||||
|
direction="vertical"
|
||||||
|
current={currentStep}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
title: "Bild zu Label konvertieren",
|
||||||
|
description: currentStep === 0 ? content : null,
|
||||||
|
onClick: (value) => console.log(value),
|
||||||
|
status: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Label drucken",
|
||||||
|
description: currentStep === 1 ? content : null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Waiting",
|
||||||
|
description: currentStep === 2 ? content : null,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div style={{ marginTop: 24 }}>
|
||||||
|
{currentStep < steps.length - 1 && (
|
||||||
|
<Button type="primary" onClick={() => next()}>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{currentStep === steps.length - 1 && (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => message.success("Processing complete!")}
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{currentStep > 0 && (
|
||||||
|
<Button style={{ margin: "0 8px" }} onClick={() => prev()}>
|
||||||
|
Previous
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<Alert
|
||||||
|
message={<b>{consoleContent.status}</b>}
|
||||||
|
description={consoleContent.description}
|
||||||
|
type={consoleContent.status}
|
||||||
|
showIcon
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
|
||||||
|
// return <ModalHandler />;
|
||||||
|
}
|
|
@ -9,24 +9,27 @@ import {
|
||||||
Space,
|
Space,
|
||||||
notification,
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
|
import { WebSocketContext, SentMessagesCommands } from "../../utils";
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
export default function GroupTypeSelectionModal({
|
export default function GroupTypeSelectionModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
setIsGroupTaskModalOpen,
|
|
||||||
categoryGroup,
|
categoryGroup,
|
||||||
currentSelectedModalGroupType,
|
currentSelectedModalGroupType,
|
||||||
setCurrentSelectedModalGroupType,
|
setCurrentSelectedModalGroupType,
|
||||||
}) {
|
}) {
|
||||||
const handleCancel = () => setIsOpen(false);
|
const handleCancel = () => setIsOpen(false);
|
||||||
const [api, contextHolder] = notification.useNotification();
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
const webSocketContext = useContext(WebSocketContext);
|
||||||
|
|
||||||
const GroupGlobalInputs = ({ groupType }) => {
|
const GroupGlobalInputs = ({ groupType }) => {
|
||||||
if (groupType !== null) {
|
if (groupType !== null) {
|
||||||
var elements = [];
|
var elements = [];
|
||||||
|
|
||||||
categoryGroup.groups.forEach((group) => {
|
categoryGroup.groups.forEach((group) => {
|
||||||
if (group.name === groupType && group.globalInputs?.length > 0) {
|
if (group.id === groupType && group.globalInputs?.length > 0) {
|
||||||
group.globalInputs.forEach((globalInput) => {
|
group.globalInputs.forEach((globalInput) => {
|
||||||
switch (globalInput.type) {
|
switch (globalInput.type) {
|
||||||
case "text":
|
case "text":
|
||||||
|
@ -52,7 +55,7 @@ export default function GroupTypeSelectionModal({
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
api["error"]({
|
notificationApi["error"]({
|
||||||
message: `Type ${globalInput.type} not implemented`,
|
message: `Type ${globalInput.type} not implemented`,
|
||||||
description: `Was specified in: ${globalInput.displayName}`,
|
description: `Was specified in: ${globalInput.displayName}`,
|
||||||
});
|
});
|
||||||
|
@ -76,7 +79,7 @@ export default function GroupTypeSelectionModal({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const startTaskPossible = () => {
|
const isStartTaskPossible = () => {
|
||||||
if (
|
if (
|
||||||
currentSelectedModalGroupType === null ||
|
currentSelectedModalGroupType === null ||
|
||||||
currentSelectedModalGroupType === undefined
|
currentSelectedModalGroupType === undefined
|
||||||
|
@ -87,7 +90,7 @@ export default function GroupTypeSelectionModal({
|
||||||
let possible = false;
|
let possible = false;
|
||||||
|
|
||||||
categoryGroup.groups.forEach((group) => {
|
categoryGroup.groups.forEach((group) => {
|
||||||
if (group.name === currentSelectedModalGroupType) {
|
if (group.id === currentSelectedModalGroupType) {
|
||||||
if (group.tasks === null) {
|
if (group.tasks === null) {
|
||||||
possible = true;
|
possible = true;
|
||||||
return;
|
return;
|
||||||
|
@ -98,6 +101,42 @@ export default function GroupTypeSelectionModal({
|
||||||
return possible;
|
return possible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleStartTask = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
//setIsGroupTasksViewModalOpen(true);
|
||||||
|
|
||||||
|
let groupName;
|
||||||
|
let numberOfSteps;
|
||||||
|
|
||||||
|
categoryGroup.groups.forEach((group) => {
|
||||||
|
if (group.id === currentSelectedModalGroupType) {
|
||||||
|
groupName = group.name;
|
||||||
|
numberOfSteps = group.tasks.length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const rememberId = window.crypto.randomUUID();
|
||||||
|
|
||||||
|
localStorage.setItem("rememberId", rememberId);
|
||||||
|
|
||||||
|
console.log("set rememberId", rememberId);
|
||||||
|
|
||||||
|
webSocketContext.SendSocketMessage(SentMessagesCommands.StartGroupTasks, {
|
||||||
|
category: categoryGroup.category,
|
||||||
|
id: currentSelectedModalGroupType,
|
||||||
|
groupName: groupName,
|
||||||
|
numberOfSteps: parseInt(numberOfSteps),
|
||||||
|
rememberId: rememberId, // used to open the modal when group task is started by backend and send via websocket back
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"starting task",
|
||||||
|
currentSelectedModalGroupType,
|
||||||
|
webSocketContext.groupTypeSelectionModalRememberId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="Select a group type"
|
title="Select a group type"
|
||||||
|
@ -114,18 +153,15 @@ export default function GroupTypeSelectionModal({
|
||||||
<Button
|
<Button
|
||||||
key="submit"
|
key="submit"
|
||||||
type="primary"
|
type="primary"
|
||||||
disabled={startTaskPossible()}
|
disabled={isStartTaskPossible()}
|
||||||
onClick={() => {
|
onClick={handleStartTask}
|
||||||
setIsOpen(false);
|
|
||||||
setIsGroupTaskModalOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Start task
|
Start task
|
||||||
</Button>
|
</Button>
|
||||||
</Space>,
|
</Space>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{contextHolder}
|
{notificationContextHolder}
|
||||||
<Select
|
<Select
|
||||||
placeholder="Choose a group type"
|
placeholder="Choose a group type"
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
|
@ -134,9 +170,8 @@ export default function GroupTypeSelectionModal({
|
||||||
>
|
>
|
||||||
{categoryGroup.category !== undefined
|
{categoryGroup.category !== undefined
|
||||||
? categoryGroup.groups.map((group, index) => {
|
? categoryGroup.groups.map((group, index) => {
|
||||||
console.log(group);
|
|
||||||
return (
|
return (
|
||||||
<Select.Option key={index} value={group.name}>
|
<Select.Option key={index} value={group.id}>
|
||||||
{group.name}
|
{group.name}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,71 +1,15 @@
|
||||||
import { PlusOutlined, ReloadOutlined } from "@ant-design/icons";
|
import { Result } from "antd";
|
||||||
import { Button, Divider, Popconfirm, Result, Space, Table } from "antd";
|
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import GroupTasksViewModal from "./GroupTasksViewModal";
|
||||||
import GroupTaskModal from "./GroupTaskModal";
|
|
||||||
import GroupTypeSelectionModal from "./GroupTypeSelectionModal";
|
import GroupTypeSelectionModal from "./GroupTypeSelectionModal";
|
||||||
import { WebSocketContext } from "../../utils";
|
import { WebSocketContext } from "../../utils";
|
||||||
|
import GroupTaskTableList from "./GroupTasksTableList";
|
||||||
|
|
||||||
const columns = [
|
export default function GroupTasks({
|
||||||
{
|
isGroupTasksViewModalOpen,
|
||||||
title: "ID",
|
setIsGroupTasksViewModalOpen,
|
||||||
dataIndex: "id",
|
}) {
|
||||||
key: "id",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Group Name",
|
|
||||||
dataIndex: "groupname",
|
|
||||||
key: "groupname",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Step",
|
|
||||||
dataIndex: "step",
|
|
||||||
key: "step",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Status",
|
|
||||||
dataIndex: "status",
|
|
||||||
key: "status",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Datetime",
|
|
||||||
dataIndex: "datetime",
|
|
||||||
key: "datetime",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Action",
|
|
||||||
dataIndex: "action",
|
|
||||||
key: "action",
|
|
||||||
render: () => (
|
|
||||||
<Space size="middle">
|
|
||||||
<Link>View</Link>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
/*
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
key: "1",
|
|
||||||
id: "12312",
|
|
||||||
groupname: "Janex Device Acryl Led Lamp",
|
|
||||||
step: "6 / 6",
|
|
||||||
status: <Badge status="success" text="Finished" />,
|
|
||||||
datetime: "2020-01-01 12:00:00",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "2",
|
|
||||||
id: "9999",
|
|
||||||
groupname: "Acryl Glas schneiden",
|
|
||||||
step: "3 / 6",
|
|
||||||
status: <Badge status="error" text="Failed" />,
|
|
||||||
datetime: "2020-01-01 12:00:00",
|
|
||||||
},
|
|
||||||
]; */
|
|
||||||
|
|
||||||
export default function GroupTasks() {
|
|
||||||
const [isGroupTypeModalOpen, setIsGroupTypeModalOpen] = useState(false);
|
const [isGroupTypeModalOpen, setIsGroupTypeModalOpen] = useState(false);
|
||||||
const [isGroupTaskModalOpen, setIsGroupTaskModalOpen] = useState(false);
|
|
||||||
const [currentCategoryGroup, setCurrentCategoryGroup] = useState([]);
|
const [currentCategoryGroup, setCurrentCategoryGroup] = useState([]);
|
||||||
const [currentSelectedModalGroupType, setCurrentSelectedModalGroupType] =
|
const [currentSelectedModalGroupType, setCurrentSelectedModalGroupType] =
|
||||||
useState();
|
useState();
|
||||||
|
@ -86,10 +30,11 @@ export default function GroupTasks() {
|
||||||
) : (
|
) : (
|
||||||
webSocketContext.CategoryGroups.map((categoryGroup) => {
|
webSocketContext.CategoryGroups.map((categoryGroup) => {
|
||||||
return (
|
return (
|
||||||
<GroupTaskList
|
<GroupTaskTableList
|
||||||
key={categoryGroup.category}
|
key={categoryGroup.category}
|
||||||
categoryGroup={categoryGroup}
|
categoryGroup={categoryGroup}
|
||||||
showGroupTypeSelectionModal={showGroupTypeSelectionModal}
|
showGroupTypeSelectionModal={showGroupTypeSelectionModal}
|
||||||
|
groupTasks={webSocketContext.GroupTasks}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -98,60 +43,16 @@ export default function GroupTasks() {
|
||||||
<GroupTypeSelectionModal
|
<GroupTypeSelectionModal
|
||||||
isOpen={isGroupTypeModalOpen}
|
isOpen={isGroupTypeModalOpen}
|
||||||
setIsOpen={setIsGroupTypeModalOpen}
|
setIsOpen={setIsGroupTypeModalOpen}
|
||||||
setIsGroupTaskModalOpen={setIsGroupTaskModalOpen}
|
setIsGroupTasksViewModalOpen={setIsGroupTasksViewModalOpen}
|
||||||
categoryGroup={currentCategoryGroup}
|
categoryGroup={currentCategoryGroup}
|
||||||
currentSelectedModalGroupType={currentSelectedModalGroupType}
|
currentSelectedModalGroupType={currentSelectedModalGroupType}
|
||||||
setCurrentSelectedModalGroupType={setCurrentSelectedModalGroupType}
|
setCurrentSelectedModalGroupType={setCurrentSelectedModalGroupType}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<GroupTaskModal
|
<GroupTasksViewModal
|
||||||
isOpen={isGroupTaskModalOpen}
|
isOpen={isGroupTasksViewModalOpen}
|
||||||
setIsOpen={setIsGroupTaskModalOpen}
|
setIsOpen={setIsGroupTasksViewModalOpen}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function GroupTaskList({ categoryGroup, showGroupTypeSelectionModal }) {
|
|
||||||
/*const tasksAvailable = () => {
|
|
||||||
let available = true;
|
|
||||||
|
|
||||||
categoryGroup.groups.forEach((group) => {
|
|
||||||
if (group.tasks !== null) {
|
|
||||||
available = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return available;
|
|
||||||
}; */
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Divider orientation="left">{categoryGroup.category}</Divider>
|
|
||||||
<Space
|
|
||||||
style={{
|
|
||||||
marginBottom: 16,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
onClick={() => showGroupTypeSelectionModal(categoryGroup)}
|
|
||||||
>
|
|
||||||
New task
|
|
||||||
</Button>
|
|
||||||
<Popconfirm
|
|
||||||
placement="left"
|
|
||||||
title="Are you sure you want to reload the group?"
|
|
||||||
okText="Yes"
|
|
||||||
>
|
|
||||||
<Button icon={<ReloadOutlined />}>Reload</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
</Space>
|
|
||||||
<Table columns={columns} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
45
src/utils.js
45
src/utils.js
|
@ -1,4 +1,5 @@
|
||||||
import { createContext, useEffect, useState } from "react";
|
import { createContext, useEffect, useRef, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constants
|
* constants
|
||||||
|
@ -6,6 +7,9 @@ import { createContext, useEffect, useState } from "react";
|
||||||
export const Constants = {
|
export const Constants = {
|
||||||
API_ADDRESS: "http://localhost:8080/v1",
|
API_ADDRESS: "http://localhost:8080/v1",
|
||||||
WS_ADDRESS: "ws://localhost:8080/ws",
|
WS_ADDRESS: "ws://localhost:8080/ws",
|
||||||
|
ROUTE_PATHS: {
|
||||||
|
GROUP_TASKS: "/group-tasks",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,6 +51,7 @@ let webSocketContextPreview = {
|
||||||
ConnectionBadgeStatus: "error",
|
ConnectionBadgeStatus: "error",
|
||||||
ConnectedWebSocketUsersCount: 0,
|
ConnectedWebSocketUsersCount: 0,
|
||||||
CategoryGroups: [],
|
CategoryGroups: [],
|
||||||
|
GroupTasks: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WebSocketContext = createContext(webSocketContextPreview);
|
export const WebSocketContext = createContext(webSocketContextPreview);
|
||||||
|
@ -55,6 +60,12 @@ export const WebSocketContext = createContext(webSocketContextPreview);
|
||||||
const ReceivedMessagesCommands = {
|
const ReceivedMessagesCommands = {
|
||||||
InitUserSocketConnection: 1,
|
InitUserSocketConnection: 1,
|
||||||
UpdateConnectedUsers: 2,
|
UpdateConnectedUsers: 2,
|
||||||
|
NewGroupTaskStarted: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// commands sent to the backend server
|
||||||
|
export const SentMessagesCommands = {
|
||||||
|
StartGroupTasks: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function WebSocketProvider({ children, userSession, setUserSession }) {
|
export function WebSocketProvider({ children, userSession, setUserSession }) {
|
||||||
|
@ -68,12 +79,18 @@ export function WebSocketProvider({ children, userSession, setUserSession }) {
|
||||||
const [categoryGroups, setCategoryGroups] = useState(
|
const [categoryGroups, setCategoryGroups] = useState(
|
||||||
webSocketContextPreview.CategoryGroups
|
webSocketContextPreview.CategoryGroups
|
||||||
);
|
);
|
||||||
|
// these are all group tasks that are then filtered and displayed in the respective tables for the category
|
||||||
|
const [groupTasks, setGroupTasks] = useState([]);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
let socket = null;
|
let socket = null;
|
||||||
|
const ws = useRef(null);
|
||||||
|
|
||||||
const connect = () => {
|
const connect = () => {
|
||||||
socket = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
|
socket = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
|
||||||
|
|
||||||
|
ws.current = socket;
|
||||||
|
|
||||||
socket.onopen = () => {
|
socket.onopen = () => {
|
||||||
console.log("connected");
|
console.log("connected");
|
||||||
setConnectionBadgeStatus("success");
|
setConnectionBadgeStatus("success");
|
||||||
|
@ -91,10 +108,22 @@ export function WebSocketProvider({ children, userSession, setUserSession }) {
|
||||||
case ReceivedMessagesCommands.InitUserSocketConnection:
|
case ReceivedMessagesCommands.InitUserSocketConnection:
|
||||||
setUser(body.User);
|
setUser(body.User);
|
||||||
setCategoryGroups(body.CategoryGroups);
|
setCategoryGroups(body.CategoryGroups);
|
||||||
|
setGroupTasks(body.GroupTasks);
|
||||||
break;
|
break;
|
||||||
case ReceivedMessagesCommands.UpdateConnectedUsers:
|
case ReceivedMessagesCommands.UpdateConnectedUsers:
|
||||||
setConnectedWebSocketUsersCount(body);
|
setConnectedWebSocketUsersCount(body);
|
||||||
break;
|
break;
|
||||||
|
case ReceivedMessagesCommands.NewGroupTaskStarted:
|
||||||
|
setGroupTasks((arr) => [...arr, body]);
|
||||||
|
|
||||||
|
if (body.RememberId === localStorage.getItem("rememberId")) {
|
||||||
|
navigate(`${Constants.ROUTE_PATHS.GROUP_TASKS}/${body.Id}`);
|
||||||
|
localStorage.removeItem("rememberId");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("unknown command", cmd);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,16 +153,30 @@ export function WebSocketProvider({ children, userSession, setUserSession }) {
|
||||||
return () => socket.close();
|
return () => socket.close();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const SendSocketMessage = (cmd, body) => {
|
||||||
|
if (isReady) {
|
||||||
|
ws.current.send(JSON.stringify({ Cmd: cmd, Body: body }));
|
||||||
|
} else {
|
||||||
|
console.log("websocket not ready");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WebSocketContext.Provider
|
<WebSocketContext.Provider
|
||||||
value={{
|
value={{
|
||||||
ConnectionBadgeStatus: connectionBadgeStatus,
|
ConnectionBadgeStatus: connectionBadgeStatus,
|
||||||
ConnectedWebSocketUsersCount: connectedWebSocketUsersCount,
|
ConnectedWebSocketUsersCount: connectedWebSocketUsersCount,
|
||||||
CategoryGroups: categoryGroups,
|
CategoryGroups: categoryGroups,
|
||||||
|
GroupTasks: groupTasks,
|
||||||
User: user,
|
User: user,
|
||||||
|
SendSocketMessage: SendSocketMessage,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</WebSocketContext.Provider>
|
</WebSocketContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FormatDatetime(datetime) {
|
||||||
|
return new Date(datetime).toLocaleString("de-DE");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue