diff --git a/src/Components/AppRoutes/index.js b/src/Components/AppRoutes/index.js index 8601bea..2aa6ef2 100644 --- a/src/Components/AppRoutes/index.js +++ b/src/Components/AppRoutes/index.js @@ -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 ( - }> - }> + } /> + } + /> + } + /> ); } -export default AppRoutes; diff --git a/src/Pages/GroupTasks/GroupTaskModal.js b/src/Pages/GroupTasks/GroupTaskModal.js deleted file mode 100644 index 7529a16..0000000 --- a/src/Pages/GroupTasks/GroupTaskModal.js +++ /dev/null @@ -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 = [ -
- - - -
, - "", -

hakki

, -]; - -const consoleContentData = [ - { - description: [ -

- 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) -

, - ], - status: "error", - }, - { - description: [

Test

], - status: "success", - }, - { - description: [

Test

], - 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 ( - -

- Produktionstask 1 -

-

- Started at: 19.01.2023 - - 11:14:30 -

- console.log(value), - status: "error", - }, - { - title: "Label drucken", - description: currentStep === 1 ? content : null, - }, - { - title: "Waiting", - description: currentStep === 2 ? content : null, - }, - ]} - /> -
- {currentStep < steps.length - 1 && ( - - )} - {currentStep === steps.length - 1 && ( - - )} - {currentStep > 0 && ( - - )} -
- - {consoleContent.status}} - description={consoleContent.description} - type={consoleContent.status} - showIcon - /> -
- ); -} diff --git a/src/Pages/GroupTasks/GroupTasksTableList.js b/src/Pages/GroupTasks/GroupTasksTableList.js new file mode 100644 index 0000000..1f61454 --- /dev/null +++ b/src/Pages/GroupTasks/GroupTasksTableList.js @@ -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) => ( + + View + + ), + }, +]; +/* + const data = [ + { + key: "1", + id: "12312", + groupname: "Janex Device Acryl Led Lamp", + step: "6 / 6", + status: , + datetime: "2020-01-01 12:00:00", + }, + { + key: "2", + id: "9999", + groupname: "Acryl Glas schneiden", + step: "3 / 6", + status: , + datetime: "2020-01-01 12:00:00", + }, + ]; */ + +export default function GroupTaskTableList({ + categoryGroup, + showGroupTypeSelectionModal, + groupTasks, +}) { + const getStatusBadge = (status) => { + switch (status) { + case 0: + return ; + case 1: + return ; + case 2: + return ; + case 3: + return ; + default: + return ; + } + }; + + 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 ( + <> + {categoryGroup.category} + + + + + + + + + ); +} diff --git a/src/Pages/GroupTasks/GroupTasksViewModal.js b/src/Pages/GroupTasks/GroupTasksViewModal.js new file mode 100644 index 0000000..296c2fe --- /dev/null +++ b/src/Pages/GroupTasks/GroupTasksViewModal.js @@ -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 = [ + + + + + , + "", +

hakki

, +]; + +const consoleContentData = [ + { + description: [ +

+ 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) +

, + ], + status: "error", + }, + { + description: [

Test

], + status: "success", + }, + { + description: [

Test

], + 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 ( + Close} + > + {" "} + + ); + } + + return ( + + {webSocketContext.GroupTasks.map((groupTask) => { + if (groupTask.Id === groupTaskId) { + console.log("groupTask", groupTask); + + let currentGroupTask = groupTask; + + return ( + <> +

+ {currentGroupTask.GroupName} +

+

+ ID: {groupTaskId}{" "} +
+ Category:{" "} + {currentGroupTask.Category} +
+ Started at:{" "} + {FormatDatetime(currentGroupTask.StartedAt)} +

+ console.log(value), + status: "error", + }, + { + title: "Label drucken", + description: currentStep === 1 ? content : null, + }, + { + title: "Waiting", + description: currentStep === 2 ? content : null, + }, + ]} + /> +
+ {currentStep < steps.length - 1 && ( + + )} + {currentStep === steps.length - 1 && ( + + )} + {currentStep > 0 && ( + + )} +
+ + {consoleContent.status}} + description={consoleContent.description} + type={consoleContent.status} + showIcon + /> + + ); + } + })} +
+ ); + + // return ; +} diff --git a/src/Pages/GroupTasks/GroupTypeSelectionModal.js b/src/Pages/GroupTasks/GroupTypeSelectionModal.js index d8989e7..99b32e2 100644 --- a/src/Pages/GroupTasks/GroupTypeSelectionModal.js +++ b/src/Pages/GroupTasks/GroupTypeSelectionModal.js @@ -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 ( { - setIsOpen(false); - setIsGroupTaskModalOpen(true); - }} + disabled={isStartTaskPossible()} + onClick={handleStartTask} > Start task , ]} > - {contextHolder} + {notificationContextHolder}
- - ); -} diff --git a/src/utils.js b/src/utils.js index 2715c87..f4352b7 100644 --- a/src/utils.js +++ b/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 ( {children} ); } + +export function FormatDatetime(datetime) { + return new Date(datetime).toLocaleString("de-DE"); +}