robots table
parent
4acbe50f8b
commit
28c823bc41
|
@ -0,0 +1,7 @@
|
|||
git add *
|
||||
|
||||
read -p "Commit message: " commit_message
|
||||
|
||||
git commit -m "$commit_message"
|
||||
|
||||
git push -u origin main
|
|
@ -178,13 +178,31 @@
|
|||
"firmwareVersion": "Firmware Version",
|
||||
"createdAt": "Erstellt am",
|
||||
"actions": "Maßnahmen"
|
||||
},
|
||||
"status": {
|
||||
"idle": "Inaktiv",
|
||||
"processing": "Verarbeitung",
|
||||
"connecting": "Verbinden",
|
||||
"error": "Fehler",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"popconfirmEdit": {
|
||||
"title": "Sind Sie sicher, dass Sie diesen Roboter bearbeiten wollen?",
|
||||
"errorNotification": {
|
||||
"message": "Roboter konnte nicht bearbeitet werden",
|
||||
"description": "Name bereits vergeben"
|
||||
}
|
||||
},
|
||||
"popconfirmDisconnect": {
|
||||
"title": "Sind Sie sicher, dass Sie diesen Roboter trennen wollen?",
|
||||
"description": "Der Roboter wird getrennt und kann nicht mehr für Aufträge verwendet werden"
|
||||
}
|
||||
},
|
||||
"unauthorizedRobots": {
|
||||
"header": "Nicht autorisierte Roboter",
|
||||
"popconfirmDeny": {
|
||||
"title": "Sind Sie sicher, dass Sie diesen Roboter ablehnen wollen?",
|
||||
"description": "Der Roboter wird getrennt und muss sich ernuet verbinden"
|
||||
"description": "Der Roboter wird getrennt und muss sich erneut verbinden"
|
||||
},
|
||||
"popconfirmAuthorize": {
|
||||
"title": "Sind Sie sicher, dass Sie diesen Roboter autorisieren wollen?",
|
||||
|
|
|
@ -178,6 +178,24 @@
|
|||
"firmwareVersion": "Firmware version",
|
||||
"createdAt": "Created At",
|
||||
"actions": "Actions"
|
||||
},
|
||||
"status": {
|
||||
"idle": "Idle",
|
||||
"processing": "Processing",
|
||||
"connecting": "Connecting",
|
||||
"error": "Error",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"popconfirmEdit": {
|
||||
"title": "Are you sure you want to edit this robot?",
|
||||
"errorNotification": {
|
||||
"message": "Robot could not be edited",
|
||||
"description": "Name already taken"
|
||||
}
|
||||
},
|
||||
"popconfirmDisconnect": {
|
||||
"title": "Are you sure you want to disconnect this robot?",
|
||||
"description": "The robot will be disconnected and cannot be longer used for jobs"
|
||||
}
|
||||
},
|
||||
"unauthorizedRobots": {
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import { Badge, Popconfirm, Space, Table, Typography } from "antd";
|
||||
import {
|
||||
Badge,
|
||||
Input,
|
||||
Popconfirm,
|
||||
Space,
|
||||
Table,
|
||||
Typography,
|
||||
notification,
|
||||
} from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useRoboticsRobotContext } from "../../../Contexts/RoboticsRobot";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
@ -16,6 +24,8 @@ const ReceivedSSECommands = {
|
|||
AddUnauthorizedRobot: 2,
|
||||
AddRobot: 3,
|
||||
RemoveUnauthorizedRobot: 4,
|
||||
RemoveRobot: 5,
|
||||
RobotUpdated: 6,
|
||||
};
|
||||
|
||||
function getRobotTypeString(type) {
|
||||
|
@ -32,27 +42,46 @@ function getRobotTypeString(type) {
|
|||
export default function Robots() {
|
||||
const robotsContext = useRoboticsRobotContext();
|
||||
const { t } = useTranslation();
|
||||
const [notificationApi, notificationContextHolder] =
|
||||
notification.useNotification();
|
||||
|
||||
const [robotsPaginationPage, setRobotsPaginationPage] = useState(1);
|
||||
const [
|
||||
unauthorizedRobotsPaginationPage,
|
||||
setUnauthorizedRobotsPaginationPage,
|
||||
] = useState(1);
|
||||
const [selectedRobotName, setSelectedRobotName] = useState("");
|
||||
|
||||
const sseEventSource = useRef(null);
|
||||
|
||||
const getRobotStatusBadge = (status) => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return <Badge status="success" text={"Idle"} />;
|
||||
return (
|
||||
<Badge status="success" text={t("robotics.robots.status.idle")} />
|
||||
);
|
||||
case 2:
|
||||
return <Badge status="processing" text={"Running"} />;
|
||||
return (
|
||||
<Badge
|
||||
status="processing"
|
||||
text={t("robotics.robots.status.processing")}
|
||||
/>
|
||||
);
|
||||
case 3:
|
||||
return <Badge status="warning" text={"Connecting"} />;
|
||||
return (
|
||||
<Badge
|
||||
status="warning"
|
||||
text={t("robotics.robots.status.connecting")}
|
||||
/>
|
||||
);
|
||||
case 4:
|
||||
return <Badge status="warning" text={"Error"} />;
|
||||
return (
|
||||
<Badge status="warning" text={t("robotics.robots.status.error")} />
|
||||
);
|
||||
case 5:
|
||||
return <Badge status="default" text={"Offline"} />;
|
||||
return (
|
||||
<Badge status="default" text={t("robotics.robots.status.offline")} />
|
||||
);
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -116,8 +145,78 @@ export default function Robots() {
|
|||
key: "actions",
|
||||
render: (_, record) => (
|
||||
<Space size="middle">
|
||||
<Link to="#">{t("common.text.edit")}</Link>
|
||||
<Link to="#">{t("common.text.disconnect")}</Link>
|
||||
<Popconfirm
|
||||
placement="left"
|
||||
title={t("robotics.robots.popconfirmEdit.title")}
|
||||
description={
|
||||
<Input
|
||||
placeholder="Name"
|
||||
value={selectedRobotName}
|
||||
onChange={(e) => setSelectedRobotName(e.target.value)}
|
||||
minLength={Constants.GLOBALS.MIN_ROBOTICS_ROBOT_NAME_LENGTH}
|
||||
maxLength={Constants.GLOBALS.MAX_ROBOTICS_ROBOT_NAME_LENGTH}
|
||||
/>
|
||||
}
|
||||
okButtonProps={{
|
||||
disabled:
|
||||
selectedRobotName.length <
|
||||
Constants.GLOBALS.MIN_ROBOTICS_ROBOT_NAME_LENGTH ||
|
||||
selectedRobotName.length >
|
||||
Constants.GLOBALS.MAX_ROBOTICS_ROBOT_NAME_LENGTH,
|
||||
}}
|
||||
okText={t("common.button.confirm")}
|
||||
cancelText={t("common.button.cancel")}
|
||||
onConfirm={() =>
|
||||
myFetch(
|
||||
`/robot`,
|
||||
"PATCH",
|
||||
{
|
||||
robotId: record.id,
|
||||
name: selectedRobotName,
|
||||
},
|
||||
{},
|
||||
myFetchContentType.JSON,
|
||||
Constants.ROBOTICS_API_ADDRESS
|
||||
).catch((err) => {
|
||||
if (err === 422) {
|
||||
notificationApi["error"]({
|
||||
message: t(
|
||||
"robotics.robots.popconfirmEdit.errorNotification.message"
|
||||
),
|
||||
description: t(
|
||||
"robotics.robots.popconfirmEdit.errorNotification.description"
|
||||
),
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
>
|
||||
<Link to="#" onClick={() => setSelectedRobotName(record.name)}>
|
||||
{t("common.text.edit")}
|
||||
</Link>
|
||||
</Popconfirm>
|
||||
|
||||
<Popconfirm
|
||||
placement="left"
|
||||
title={t("robotics.robots.popconfirmDisconnect.title")}
|
||||
description={t(
|
||||
"robotics.robots.popconfirmDisconnect.description"
|
||||
)}
|
||||
okText={t("common.button.confirm")}
|
||||
cancelText={t("common.button.cancel")}
|
||||
onConfirm={() =>
|
||||
myFetch(
|
||||
`/robot/${record.id}`,
|
||||
"DELETE",
|
||||
null,
|
||||
{},
|
||||
myFetchContentType.JSON,
|
||||
Constants.ROBOTICS_API_ADDRESS
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link to="#">{t("common.text.disconnect")}</Link>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
|
@ -129,21 +228,27 @@ export default function Robots() {
|
|||
const getRobotsTableItems = (robots) => {
|
||||
let items = [];
|
||||
|
||||
robots.forEach((robot) => {
|
||||
robots.sort((a, b) => a.Status - b.Status);
|
||||
|
||||
robots.forEach((robot) =>
|
||||
items.push({
|
||||
key: robot.Id,
|
||||
id: robot.Id,
|
||||
type: getRobotTypeString(robot.Type),
|
||||
name: robot.Name,
|
||||
status: getRobotStatusBadge(robot.Status),
|
||||
currentJob: robot.CurrentJob,
|
||||
currentJob:
|
||||
robot.CurrentJobId === ""
|
||||
? Constants.TEXT_EMPTY_PLACEHOLDER
|
||||
: robot.CurrentJobId,
|
||||
jobsWaiting: robot.JobsWaitingCount,
|
||||
address: robot.Address,
|
||||
firmwareVersion: robot.FirmwareVersion,
|
||||
connectedAt: FormatDatetime(robot.ConnectedAt),
|
||||
createdAt: FormatDatetime(robot.CreatedAt),
|
||||
actions: robot.Actions,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return items;
|
||||
};
|
||||
|
@ -170,6 +275,11 @@ export default function Robots() {
|
|||
dataIndex: "connectedAt",
|
||||
key: "connectedAt",
|
||||
},
|
||||
{
|
||||
title: t("robotics.robots.column.firmwareVersion"),
|
||||
dataIndex: "firmwareVersion",
|
||||
key: "firmwareVersion",
|
||||
},
|
||||
{
|
||||
title: t("robotics.robots.column.actions"),
|
||||
dataIndex: "actions",
|
||||
|
@ -192,9 +302,7 @@ export default function Robots() {
|
|||
{},
|
||||
myFetchContentType.JSON,
|
||||
Constants.ROBOTICS_API_ADDRESS
|
||||
).then((data) => {
|
||||
console.log("data", data);
|
||||
})
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link to="#">{t("common.text.deny")}</Link>
|
||||
|
@ -216,9 +324,7 @@ export default function Robots() {
|
|||
{},
|
||||
myFetchContentType.JSON,
|
||||
Constants.ROBOTICS_API_ADDRESS
|
||||
).then((data) => {
|
||||
console.log("data", data);
|
||||
})
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link to="#">{t("common.text.authorize")}</Link>
|
||||
|
@ -241,6 +347,7 @@ export default function Robots() {
|
|||
type: getRobotTypeString(robot.Type),
|
||||
address: robot.Address,
|
||||
connectedAt: FormatDatetime(robot.ConnectedAt),
|
||||
firmwareVersion: robot.FirmwareVersion,
|
||||
actions: robot.Actions,
|
||||
});
|
||||
});
|
||||
|
@ -293,12 +400,8 @@ export default function Robots() {
|
|||
robotsContext.setRobots((arr) => {
|
||||
const newArr = [...arr];
|
||||
|
||||
console.log("arr", arr);
|
||||
|
||||
const index = arr.findIndex((x) => x.Id === body.RobotId);
|
||||
|
||||
console.log("index", index);
|
||||
|
||||
if (index !== -1) {
|
||||
newArr[index].Status = body.Status;
|
||||
}
|
||||
|
@ -335,6 +438,19 @@ export default function Robots() {
|
|||
|
||||
return newArr;
|
||||
});
|
||||
|
||||
// remove from unauthorized robots
|
||||
robotsContext.setUnauthorizedRobots((arr) => {
|
||||
const newArr = [...arr];
|
||||
|
||||
const index = arr.findIndex((x) => x.Id === body.Id);
|
||||
|
||||
if (index !== -1) {
|
||||
newArr.splice(index, 1);
|
||||
}
|
||||
|
||||
return newArr;
|
||||
});
|
||||
break;
|
||||
case ReceivedSSECommands.RemoveUnauthorizedRobot:
|
||||
robotsContext.setUnauthorizedRobots((arr) => {
|
||||
|
@ -349,6 +465,32 @@ export default function Robots() {
|
|||
return newArr;
|
||||
});
|
||||
break;
|
||||
case ReceivedSSECommands.RemoveRobot:
|
||||
robotsContext.setRobots((arr) => {
|
||||
const newArr = [...arr];
|
||||
|
||||
const index = arr.findIndex((x) => x.Id === body);
|
||||
|
||||
if (index !== -1) {
|
||||
newArr.splice(index, 1);
|
||||
}
|
||||
|
||||
return newArr;
|
||||
});
|
||||
break;
|
||||
case ReceivedSSECommands.RobotUpdated:
|
||||
robotsContext.setRobots((arr) => {
|
||||
const newArr = [...arr];
|
||||
|
||||
const index = arr.findIndex((x) => x.Id === body.RobotId);
|
||||
|
||||
if (index !== -1) {
|
||||
newArr[index].Name = body.Name;
|
||||
}
|
||||
|
||||
return newArr;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -365,6 +507,8 @@ export default function Robots() {
|
|||
|
||||
return (
|
||||
<>
|
||||
{notificationContextHolder}
|
||||
|
||||
<Typography.Title level={4}>
|
||||
{t("robotics.robots.header")} ({robotsContext.robots.length})
|
||||
</Typography.Title>
|
||||
|
|
|
@ -102,6 +102,8 @@ export const Constants = {
|
|||
MAX_LOG_MANAGER_DISPLAY_NAME_LENGTH: 16,
|
||||
MIN_LOG_MANAGER_ADDRESS_LENGTH: 3,
|
||||
MAX_LOG_MANAGER_ADDRESS_LENGTH: 100,
|
||||
MIN_ROBOTICS_ROBOT_NAME_LENGTH: 2,
|
||||
MAX_ROBOTICS_ROBOT_NAME_LENGTH: 30,
|
||||
},
|
||||
MAX_AVATAR_SIZE: 5 * 1024 * 1024,
|
||||
ACCEPTED_AVATAR_FILE_TYPES: [
|
||||
|
@ -1390,7 +1392,7 @@ export function myFetch(
|
|||
window.location.href = "/";
|
||||
}
|
||||
|
||||
return;
|
||||
throw response.status;
|
||||
}
|
||||
|
||||
// check if response is json
|
||||
|
|
Loading…
Reference in New Issue