group tasks
parent
346839917b
commit
da125051f3
|
@ -2,12 +2,18 @@ import { Route, Routes } from "react-router-dom";
|
|||
import Dashboard from "../../Pages/Dashboard";
|
||||
import GroupTasks from "../../Pages/GroupTasks";
|
||||
|
||||
function AppRoutes() {
|
||||
export default function AppRoutes() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<Dashboard />}></Route>
|
||||
<Route path="/group-tasks" element={<GroupTasks />}></Route>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route
|
||||
path="/group-tasks"
|
||||
element={<GroupTasks isGroupTasksViewModalOpen={false} />}
|
||||
/>
|
||||
<Route
|
||||
path="/group-tasks/:groupTaskId"
|
||||
element={<GroupTasks isGroupTasksViewModalOpen={true} />}
|
||||
/>
|
||||
</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,
|
||||
notification,
|
||||
} from "antd";
|
||||
import { WebSocketContext, SentMessagesCommands } from "../../utils";
|
||||
import { useContext } from "react";
|
||||
|
||||
export default function GroupTypeSelectionModal({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
setIsGroupTaskModalOpen,
|
||||
categoryGroup,
|
||||
currentSelectedModalGroupType,
|
||||
setCurrentSelectedModalGroupType,
|
||||
}) {
|
||||
const handleCancel = () => setIsOpen(false);
|
||||
const [api, contextHolder] = notification.useNotification();
|
||||
const [notificationApi, notificationContextHolder] =
|
||||
notification.useNotification();
|
||||
const webSocketContext = useContext(WebSocketContext);
|
||||
|
||||
const GroupGlobalInputs = ({ groupType }) => {
|
||||
if (groupType !== null) {
|
||||
var elements = [];
|
||||
|
||||
categoryGroup.groups.forEach((group) => {
|
||||
if (group.name === groupType && group.globalInputs?.length > 0) {
|
||||
if (group.id === groupType && group.globalInputs?.length > 0) {
|
||||
group.globalInputs.forEach((globalInput) => {
|
||||
switch (globalInput.type) {
|
||||
case "text":
|
||||
|
@ -52,7 +55,7 @@ export default function GroupTypeSelectionModal({
|
|||
);
|
||||
break;
|
||||
default:
|
||||
api["error"]({
|
||||
notificationApi["error"]({
|
||||
message: `Type ${globalInput.type} not implemented`,
|
||||
description: `Was specified in: ${globalInput.displayName}`,
|
||||
});
|
||||
|
@ -76,7 +79,7 @@ export default function GroupTypeSelectionModal({
|
|||
}
|
||||
};
|
||||
|
||||
const startTaskPossible = () => {
|
||||
const isStartTaskPossible = () => {
|
||||
if (
|
||||
currentSelectedModalGroupType === null ||
|
||||
currentSelectedModalGroupType === undefined
|
||||
|
@ -87,7 +90,7 @@ export default function GroupTypeSelectionModal({
|
|||
let possible = false;
|
||||
|
||||
categoryGroup.groups.forEach((group) => {
|
||||
if (group.name === currentSelectedModalGroupType) {
|
||||
if (group.id === currentSelectedModalGroupType) {
|
||||
if (group.tasks === null) {
|
||||
possible = true;
|
||||
return;
|
||||
|
@ -98,6 +101,42 @@ export default function GroupTypeSelectionModal({
|
|||
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 (
|
||||
<Modal
|
||||
title="Select a group type"
|
||||
|
@ -114,18 +153,15 @@ export default function GroupTypeSelectionModal({
|
|||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
disabled={startTaskPossible()}
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
setIsGroupTaskModalOpen(true);
|
||||
}}
|
||||
disabled={isStartTaskPossible()}
|
||||
onClick={handleStartTask}
|
||||
>
|
||||
Start task
|
||||
</Button>
|
||||
</Space>,
|
||||
]}
|
||||
>
|
||||
{contextHolder}
|
||||
{notificationContextHolder}
|
||||
<Select
|
||||
placeholder="Choose a group type"
|
||||
style={{ width: "100%" }}
|
||||
|
@ -134,9 +170,8 @@ export default function GroupTypeSelectionModal({
|
|||
>
|
||||
{categoryGroup.category !== undefined
|
||||
? categoryGroup.groups.map((group, index) => {
|
||||
console.log(group);
|
||||
return (
|
||||
<Select.Option key={index} value={group.name}>
|
||||
<Select.Option key={index} value={group.id}>
|
||||
{group.name}
|
||||
</Select.Option>
|
||||
);
|
||||
|
|
|
@ -1,71 +1,15 @@
|
|||
import { PlusOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||
import { Button, Divider, Popconfirm, Result, Space, Table } from "antd";
|
||||
import { Result } from "antd";
|
||||
import { useContext, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import GroupTaskModal from "./GroupTaskModal";
|
||||
import GroupTasksViewModal from "./GroupTasksViewModal";
|
||||
import GroupTypeSelectionModal from "./GroupTypeSelectionModal";
|
||||
import { WebSocketContext } from "../../utils";
|
||||
import GroupTaskTableList from "./GroupTasksTableList";
|
||||
|
||||
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: "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() {
|
||||
export default function GroupTasks({
|
||||
isGroupTasksViewModalOpen,
|
||||
setIsGroupTasksViewModalOpen,
|
||||
}) {
|
||||
const [isGroupTypeModalOpen, setIsGroupTypeModalOpen] = useState(false);
|
||||
const [isGroupTaskModalOpen, setIsGroupTaskModalOpen] = useState(false);
|
||||
const [currentCategoryGroup, setCurrentCategoryGroup] = useState([]);
|
||||
const [currentSelectedModalGroupType, setCurrentSelectedModalGroupType] =
|
||||
useState();
|
||||
|
@ -86,10 +30,11 @@ export default function GroupTasks() {
|
|||
) : (
|
||||
webSocketContext.CategoryGroups.map((categoryGroup) => {
|
||||
return (
|
||||
<GroupTaskList
|
||||
<GroupTaskTableList
|
||||
key={categoryGroup.category}
|
||||
categoryGroup={categoryGroup}
|
||||
showGroupTypeSelectionModal={showGroupTypeSelectionModal}
|
||||
groupTasks={webSocketContext.GroupTasks}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
@ -98,60 +43,16 @@ export default function GroupTasks() {
|
|||
<GroupTypeSelectionModal
|
||||
isOpen={isGroupTypeModalOpen}
|
||||
setIsOpen={setIsGroupTypeModalOpen}
|
||||
setIsGroupTaskModalOpen={setIsGroupTaskModalOpen}
|
||||
setIsGroupTasksViewModalOpen={setIsGroupTasksViewModalOpen}
|
||||
categoryGroup={currentCategoryGroup}
|
||||
currentSelectedModalGroupType={currentSelectedModalGroupType}
|
||||
setCurrentSelectedModalGroupType={setCurrentSelectedModalGroupType}
|
||||
/>
|
||||
|
||||
<GroupTaskModal
|
||||
isOpen={isGroupTaskModalOpen}
|
||||
setIsOpen={setIsGroupTaskModalOpen}
|
||||
<GroupTasksViewModal
|
||||
isOpen={isGroupTasksViewModalOpen}
|
||||
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
|
||||
|
@ -6,6 +7,9 @@ import { createContext, useEffect, useState } from "react";
|
|||
export const Constants = {
|
||||
API_ADDRESS: "http://localhost:8080/v1",
|
||||
WS_ADDRESS: "ws://localhost:8080/ws",
|
||||
ROUTE_PATHS: {
|
||||
GROUP_TASKS: "/group-tasks",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -47,6 +51,7 @@ let webSocketContextPreview = {
|
|||
ConnectionBadgeStatus: "error",
|
||||
ConnectedWebSocketUsersCount: 0,
|
||||
CategoryGroups: [],
|
||||
GroupTasks: [],
|
||||
};
|
||||
|
||||
export const WebSocketContext = createContext(webSocketContextPreview);
|
||||
|
@ -55,6 +60,12 @@ export const WebSocketContext = createContext(webSocketContextPreview);
|
|||
const ReceivedMessagesCommands = {
|
||||
InitUserSocketConnection: 1,
|
||||
UpdateConnectedUsers: 2,
|
||||
NewGroupTaskStarted: 3,
|
||||
};
|
||||
|
||||
// commands sent to the backend server
|
||||
export const SentMessagesCommands = {
|
||||
StartGroupTasks: 1,
|
||||
};
|
||||
|
||||
export function WebSocketProvider({ children, userSession, setUserSession }) {
|
||||
|
@ -68,12 +79,18 @@ export function WebSocketProvider({ children, userSession, setUserSession }) {
|
|||
const [categoryGroups, setCategoryGroups] = useState(
|
||||
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;
|
||||
const ws = useRef(null);
|
||||
|
||||
const connect = () => {
|
||||
socket = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
|
||||
|
||||
ws.current = socket;
|
||||
|
||||
socket.onopen = () => {
|
||||
console.log("connected");
|
||||
setConnectionBadgeStatus("success");
|
||||
|
@ -91,10 +108,22 @@ export function WebSocketProvider({ children, userSession, setUserSession }) {
|
|||
case ReceivedMessagesCommands.InitUserSocketConnection:
|
||||
setUser(body.User);
|
||||
setCategoryGroups(body.CategoryGroups);
|
||||
setGroupTasks(body.GroupTasks);
|
||||
break;
|
||||
case ReceivedMessagesCommands.UpdateConnectedUsers:
|
||||
setConnectedWebSocketUsersCount(body);
|
||||
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();
|
||||
}, []);
|
||||
|
||||
const SendSocketMessage = (cmd, body) => {
|
||||
if (isReady) {
|
||||
ws.current.send(JSON.stringify({ Cmd: cmd, Body: body }));
|
||||
} else {
|
||||
console.log("websocket not ready");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<WebSocketContext.Provider
|
||||
value={{
|
||||
ConnectionBadgeStatus: connectionBadgeStatus,
|
||||
ConnectedWebSocketUsersCount: connectedWebSocketUsersCount,
|
||||
CategoryGroups: categoryGroups,
|
||||
GroupTasks: groupTasks,
|
||||
User: user,
|
||||
SendSocketMessage: SendSocketMessage,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WebSocketContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function FormatDatetime(datetime) {
|
||||
return new Date(datetime).toLocaleString("de-DE");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue