Refactor BottomToolBar and update user types #15
|
|
@ -14,7 +14,7 @@ import {
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import classes from "./Component.module.css";
|
import classes from "./Component.module.css";
|
||||||
import type { IScenario, TLine, TStation } from "../untils/types";
|
import type { IScenario, TLine, TStation, TUser } from "../untils/types";
|
||||||
import type { Socket } from "socket.io-client";
|
import type { Socket } from "socket.io-client";
|
||||||
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
|
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
|
||||||
import DrawerLogs from "./DrawerLogs";
|
import DrawerLogs from "./DrawerLogs";
|
||||||
|
|
@ -22,7 +22,12 @@ import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl";
|
||||||
import DrawerScenario from "./DrawerScenario";
|
import DrawerScenario from "./DrawerScenario";
|
||||||
import { isJsonString } from "../untils/helper";
|
import { isJsonString } from "../untils/helper";
|
||||||
import { motion } from "motion/react";
|
import { motion } from "motion/react";
|
||||||
import { IconCaretDown, IconCaretUp, IconPlayerPlay, IconPlus } from "@tabler/icons-react";
|
import {
|
||||||
|
IconCaretDown,
|
||||||
|
IconCaretUp,
|
||||||
|
IconPlayerPlay,
|
||||||
|
IconPlus,
|
||||||
|
} from "@tabler/icons-react";
|
||||||
|
|
||||||
interface TabsProps {
|
interface TabsProps {
|
||||||
selectedLines: TLine[];
|
selectedLines: TLine[];
|
||||||
|
|
@ -58,7 +63,7 @@ const ScenarioCard = ({
|
||||||
index: number;
|
index: number;
|
||||||
isDisable: boolean;
|
isDisable: boolean;
|
||||||
selectedLines: TLine[];
|
selectedLines: TLine[];
|
||||||
user: any;
|
user: TUser;
|
||||||
socket: Socket | null;
|
socket: Socket | null;
|
||||||
setOpenScenarioModal: (value: boolean) => void;
|
setOpenScenarioModal: (value: boolean) => void;
|
||||||
setIsDisable: (value: boolean) => void;
|
setIsDisable: (value: boolean) => void;
|
||||||
|
|
@ -73,7 +78,7 @@ const ScenarioCard = ({
|
||||||
const rect = cardRef.current.getBoundingClientRect();
|
const rect = cardRef.current.getBoundingClientRect();
|
||||||
const overlayWidth = 400;
|
const overlayWidth = 400;
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
|
|
||||||
// Tính toán vị trí để overlay không tràn ra ngoài màn hình
|
// Tính toán vị trí để overlay không tràn ra ngoài màn hình
|
||||||
let left = rect.left;
|
let left = rect.left;
|
||||||
if (left + overlayWidth > viewportWidth) {
|
if (left + overlayWidth > viewportWidth) {
|
||||||
|
|
@ -82,7 +87,7 @@ const ScenarioCard = ({
|
||||||
if (left < 10) {
|
if (left < 10) {
|
||||||
left = 10; // 10px margin từ bên trái
|
left = 10; // 10px margin từ bên trái
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverlayPosition({
|
setOverlayPosition({
|
||||||
top: rect.top,
|
top: rect.top,
|
||||||
left: left,
|
left: left,
|
||||||
|
|
@ -98,7 +103,7 @@ const ScenarioCard = ({
|
||||||
const rect = cardRef.current.getBoundingClientRect();
|
const rect = cardRef.current.getBoundingClientRect();
|
||||||
const overlayWidth = 400;
|
const overlayWidth = 400;
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
|
|
||||||
let left = rect.left;
|
let left = rect.left;
|
||||||
if (left + overlayWidth > viewportWidth) {
|
if (left + overlayWidth > viewportWidth) {
|
||||||
left = viewportWidth - overlayWidth - 10;
|
left = viewportWidth - overlayWidth - 10;
|
||||||
|
|
@ -106,7 +111,7 @@ const ScenarioCard = ({
|
||||||
if (left < 10) {
|
if (left < 10) {
|
||||||
left = 10;
|
left = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverlayPosition({
|
setOverlayPosition({
|
||||||
top: rect.top,
|
top: rect.top,
|
||||||
left: left,
|
left: left,
|
||||||
|
|
@ -122,7 +127,7 @@ const ScenarioCard = ({
|
||||||
scrollContainers.forEach((container) => {
|
scrollContainers.forEach((container) => {
|
||||||
container.addEventListener("scroll", updatePosition, true);
|
container.addEventListener("scroll", updatePosition, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("scroll", updatePosition, true);
|
window.addEventListener("scroll", updatePosition, true);
|
||||||
window.addEventListener("resize", updatePosition);
|
window.addEventListener("resize", updatePosition);
|
||||||
|
|
||||||
|
|
@ -138,10 +143,7 @@ const ScenarioCard = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid.Col key={scenario.id} span={3}>
|
<Grid.Col key={scenario.id} span={3}>
|
||||||
<div
|
<div ref={cardRef} style={{ position: "relative" }}>
|
||||||
ref={cardRef}
|
|
||||||
style={{ position: "relative" }}
|
|
||||||
>
|
|
||||||
<Card
|
<Card
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
padding="md"
|
padding="md"
|
||||||
|
|
@ -178,7 +180,8 @@ const ScenarioCard = ({
|
||||||
isDisable ||
|
isDisable ||
|
||||||
selectedLines.filter(
|
selectedLines.filter(
|
||||||
(el) =>
|
(el) =>
|
||||||
!el?.userEmailOpenCLI || el?.userEmailOpenCLI === user?.email
|
!el?.userEmailOpenCLI ||
|
||||||
|
el?.userEmailOpenCLI === user?.email
|
||||||
).length === 0
|
).length === 0
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -270,23 +273,21 @@ const ScenarioCard = ({
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{steps
|
{steps.slice(0, 5).map((step: { send: string }, i: number) => (
|
||||||
.slice(0, 5)
|
<Text
|
||||||
.map((step: { send: string }, i: number) => (
|
key={i}
|
||||||
<Text
|
size="xs"
|
||||||
key={i}
|
c="dimmed"
|
||||||
size="xs"
|
style={{
|
||||||
c="dimmed"
|
fontFamily: "monospace",
|
||||||
style={{
|
whiteSpace: "nowrap",
|
||||||
fontFamily: "monospace",
|
overflow: "hidden",
|
||||||
whiteSpace: "nowrap",
|
textOverflow: "ellipsis",
|
||||||
overflow: "hidden",
|
}}
|
||||||
textOverflow: "ellipsis",
|
>
|
||||||
}}
|
{i + 1}. {step.send || "(empty)"}
|
||||||
>
|
</Text>
|
||||||
{i + 1}. {step.send || "(empty)"}
|
))}
|
||||||
</Text>
|
|
||||||
))}
|
|
||||||
{steps.length > 5 && (
|
{steps.length > 5 && (
|
||||||
<Text size="xs" c="dimmed" ta="center" mt="xs">
|
<Text size="xs" c="dimmed" ta="center" mt="xs">
|
||||||
... and {steps.length - 5} more
|
... and {steps.length - 5} more
|
||||||
|
|
@ -420,7 +421,11 @@ const BottomToolBar = ({
|
||||||
{scenarios.length > 0 ? (
|
{scenarios.length > 0 ? (
|
||||||
<Grid
|
<Grid
|
||||||
gutter="md"
|
gutter="md"
|
||||||
style={{ margin: 0, overflow: "visible", position: "relative" }}
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
overflow: "visible",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{scenarios.map((scenario, index) => (
|
{scenarios.map((scenario, index) => (
|
||||||
<ScenarioCard
|
<ScenarioCard
|
||||||
|
|
@ -475,217 +480,143 @@ const BottomToolBar = ({
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box style={{ position: "relative" }}>
|
<Box style={{ position: "relative" }}>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: isExpand ? -4 : -24,
|
top: isExpand ? -4 : -24,
|
||||||
left: "50%",
|
left: "50%",
|
||||||
translate: "-19px 0",
|
translate: "-19px 0",
|
||||||
backgroundColor: "#e3e0e0",
|
backgroundColor: "#e3e0e0",
|
||||||
width: "55px",
|
width: "55px",
|
||||||
}}
|
}}
|
||||||
variant="light"
|
variant="light"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setExpanded((prev) => !prev);
|
setExpanded((prev) => !prev);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isExpand ? (
|
{isExpand ? (
|
||||||
<IconCaretDown color="green" />
|
<IconCaretDown color="green" />
|
||||||
) : (
|
) : (
|
||||||
<IconCaretUp color="green" />
|
<IconCaretUp color="green" />
|
||||||
)}
|
)}
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={1}></Grid.Col>
|
<Grid.Col span={1}></Grid.Col>
|
||||||
<Grid.Col span={10}>
|
<Grid.Col span={10}>
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="command"
|
defaultValue="command"
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
value={activeTabBottom}
|
value={activeTabBottom}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
setActiveTabBottom(val || "command");
|
setActiveTabBottom(val || "command");
|
||||||
}}
|
}}
|
||||||
className={classes.containerBottom}
|
className={classes.containerBottom}
|
||||||
style={{ height: "20vh" }}
|
style={{ height: "20vh" }}
|
||||||
>
|
>
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
style={{
|
style={{
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
activeTabBottom === "command" ? "#c8d9fd" : "",
|
activeTabBottom === "command" ? "#c8d9fd" : "",
|
||||||
fontSize: "13px",
|
fontSize: "13px",
|
||||||
paddingTop: "8px",
|
paddingTop: "8px",
|
||||||
paddingBottom: "8px",
|
paddingBottom: "8px",
|
||||||
}}
|
}}
|
||||||
value="command"
|
value="command"
|
||||||
>
|
>
|
||||||
Command Line
|
Command Line
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: activeTabBottom === "apc" ? "#c8d9fd" : "",
|
backgroundColor:
|
||||||
fontSize: "13px",
|
activeTabBottom === "apc" ? "#c8d9fd" : "",
|
||||||
paddingTop: "8px",
|
fontSize: "13px",
|
||||||
paddingBottom: "8px",
|
paddingTop: "8px",
|
||||||
}}
|
paddingBottom: "8px",
|
||||||
value="apc"
|
}}
|
||||||
>
|
value="apc"
|
||||||
APC
|
>
|
||||||
</Tabs.Tab>
|
APC
|
||||||
<Tabs.Tab
|
</Tabs.Tab>
|
||||||
style={{
|
<Tabs.Tab
|
||||||
backgroundColor:
|
style={{
|
||||||
activeTabBottom === "switch" ? "#c8d9fd" : "",
|
backgroundColor:
|
||||||
fontSize: "13px",
|
activeTabBottom === "switch" ? "#c8d9fd" : "",
|
||||||
paddingTop: "8px",
|
fontSize: "13px",
|
||||||
paddingBottom: "8px",
|
paddingTop: "8px",
|
||||||
}}
|
paddingBottom: "8px",
|
||||||
value="switch"
|
}}
|
||||||
>
|
value="switch"
|
||||||
Switch
|
>
|
||||||
</Tabs.Tab>
|
Switch
|
||||||
</Tabs.List>
|
</Tabs.Tab>
|
||||||
|
</Tabs.List>
|
||||||
|
|
||||||
<Tabs.Panel value="command" p={"xs"}>
|
<Tabs.Panel value="command" p={"xs"}>
|
||||||
<Flex justify={"space-between"}>
|
<Flex justify={"space-between"}>
|
||||||
<ScrollArea h={"15vh"}>
|
|
||||||
<Flex wrap={"wrap"} gap={"xs"} w={"400px"}>
|
|
||||||
{selectedLines.map((el) => (
|
|
||||||
<Box
|
|
||||||
key={el.id}
|
|
||||||
style={{
|
|
||||||
paddingLeft: "4px",
|
|
||||||
height: "30px",
|
|
||||||
width: "80px",
|
|
||||||
backgroundColor: "#d4e3ff",
|
|
||||||
borderRadius: "8px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Flex align={"center"} justify={"center"} gap={"4px"}>
|
|
||||||
<Text fz={"12px"}>Line {el.lineNumber}</Text>
|
|
||||||
<CloseButton
|
|
||||||
style={{ minWidth: "24px" }}
|
|
||||||
aria-label="Clear input"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedLines(
|
|
||||||
selectedLines.filter(
|
|
||||||
(line) => line.id !== el.id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
socket?.emit("close_cli", {
|
|
||||||
lineId: el?.id,
|
|
||||||
stationId: el.stationId || el.station_id,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Flex>
|
|
||||||
</ScrollArea>
|
|
||||||
<Box pl={"md"} pr={"md"}>
|
|
||||||
<Flex justify={"space-between"} mb={"xs"}>
|
|
||||||
<Flex></Flex>
|
|
||||||
<Button
|
|
||||||
fw={400}
|
|
||||||
disabled={isDisable || selectedLines.length === 0}
|
|
||||||
variant="filled"
|
|
||||||
color="orange"
|
|
||||||
size="xs"
|
|
||||||
radius="md"
|
|
||||||
onClick={() => {
|
|
||||||
const listLine = selectedLines.length
|
|
||||||
? selectedLines
|
|
||||||
: station?.lines;
|
|
||||||
if (listLine.length) {
|
|
||||||
socket?.emit("write_command_line_from_web", {
|
|
||||||
lineIds: listLine.map((line) => line.id),
|
|
||||||
stationId: station.id,
|
|
||||||
command: "spam_break",
|
|
||||||
});
|
|
||||||
setIsDisable(true);
|
|
||||||
setTimeout(() => {
|
|
||||||
setIsDisable(false);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Send Break
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
<Box>
|
<Box>
|
||||||
<Input
|
<ScrollArea h={"12vh"}>
|
||||||
ref={inputRef}
|
<Flex wrap={"wrap"} gap={"8px"} w={"420px"}>
|
||||||
style={{
|
{selectedLines.map((el) => (
|
||||||
width: "30vw",
|
<Box
|
||||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
key={el.id}
|
||||||
}}
|
style={{
|
||||||
placeholder={"Send command to port(s)"}
|
position: "relative",
|
||||||
value={valueInput}
|
padding: "4px 6px",
|
||||||
onChange={(event) => {
|
height: "26px",
|
||||||
const newValue = event.currentTarget.value;
|
width: "60px",
|
||||||
setValueInput(newValue);
|
backgroundColor: "#d4e3ff",
|
||||||
}}
|
borderRadius: "8px",
|
||||||
onKeyDown={(event) => {
|
}}
|
||||||
if (event.key === "Enter") {
|
>
|
||||||
const listLine = selectedLines.length
|
{/* Close button góc trên phải */}
|
||||||
? selectedLines
|
<CloseButton
|
||||||
: station?.lines;
|
size="xs"
|
||||||
if (listLine?.length) {
|
style={{
|
||||||
socket?.emit("write_command_line_from_web", {
|
position: "absolute",
|
||||||
lineIds: listLine.map((line) => line.id),
|
top: "-4px",
|
||||||
stationId: station.id,
|
right: "-6px",
|
||||||
command: valueInput + "\r\n",
|
minWidth: "18px",
|
||||||
});
|
width: "18px",
|
||||||
// setTimeout(() => {
|
height: "18px",
|
||||||
// socket?.emit("write_command_line_from_web", {
|
zIndex: 10,
|
||||||
// lineIds: listLine.map((line) => line.id),
|
}}
|
||||||
// stationId: station.id,
|
onClick={() => {
|
||||||
// command: " \n",
|
setSelectedLines(
|
||||||
// });
|
selectedLines.filter(
|
||||||
// }, 1000);
|
(line) => line.id !== el.id
|
||||||
}
|
)
|
||||||
setValueInput("");
|
);
|
||||||
}
|
socket?.emit("close_cli", {
|
||||||
}}
|
lineId: el?.id,
|
||||||
rightSectionPointerEvents="all"
|
stationId: el.stationId || el.station_id,
|
||||||
rightSection={
|
});
|
||||||
<CloseButton
|
}}
|
||||||
aria-label="Clear input"
|
/>
|
||||||
onClick={() => setValueInput("")}
|
|
||||||
style={{
|
<Flex
|
||||||
display: valueInput ? undefined : "none",
|
align={"center"}
|
||||||
}}
|
justify={"center"}
|
||||||
/>
|
h="100%"
|
||||||
}
|
>
|
||||||
/>
|
<Text fz={"11px"}>Line {el.lineNumber}</Text>
|
||||||
</Box>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
<Box style={{ width: "220px" }}>
|
))}
|
||||||
<Flex align={"center"} wrap={"wrap"} gap={"xs"}>
|
</Flex>
|
||||||
<ButtonSelect
|
</ScrollArea>
|
||||||
selectedLines={selectedLines}
|
{selectedLines?.length > 0 ? (
|
||||||
setSelectedLines={setSelectedLines}
|
<Button
|
||||||
station={station}
|
fw={400}
|
||||||
userName={user?.userName}
|
className={classes.buttonControl}
|
||||||
onClick={() => {
|
variant="outline"
|
||||||
const lines = station.lines.filter(
|
onClick={() => {
|
||||||
(line) =>
|
const lines = station.lines.filter(
|
||||||
!line?.userOpenCLI ||
|
(line) =>
|
||||||
line?.userOpenCLI === user?.userName
|
!line?.userOpenCLI ||
|
||||||
);
|
line?.userOpenCLI === user?.userName
|
||||||
if (selectedLines.length !== lines.length) {
|
);
|
||||||
setSelectedLines(lines);
|
|
||||||
lines.forEach((line) => {
|
|
||||||
socket?.emit("open_cli", {
|
|
||||||
lineId: line.id,
|
|
||||||
stationId: line.stationId || line.station_id,
|
|
||||||
userEmail: user?.email,
|
|
||||||
userName: user?.userName,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
lines.forEach((line) => {
|
lines.forEach((line) => {
|
||||||
socket?.emit("close_cli", {
|
socket?.emit("close_cli", {
|
||||||
lineId: line?.id,
|
lineId: line?.id,
|
||||||
|
|
@ -693,53 +624,170 @@ const BottomToolBar = ({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setSelectedLines([]);
|
setSelectedLines([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Box pl={"md"} pr={"md"}>
|
||||||
|
<Flex justify={"space-between"} mb={"xs"}>
|
||||||
|
<Flex></Flex>
|
||||||
|
<Button
|
||||||
|
fw={400}
|
||||||
|
disabled={isDisable || selectedLines.length === 0}
|
||||||
|
variant="filled"
|
||||||
|
color="orange"
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
onClick={() => {
|
||||||
|
const listLine = selectedLines.length
|
||||||
|
? selectedLines
|
||||||
|
: station?.lines;
|
||||||
|
if (listLine.length) {
|
||||||
|
socket?.emit("write_command_line_from_web", {
|
||||||
|
lineIds: listLine.map((line) => line.id),
|
||||||
|
stationId: station.id,
|
||||||
|
command: "spam_break",
|
||||||
|
});
|
||||||
|
setIsDisable(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsDisable(false);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Send Break
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
<Box>
|
||||||
|
<Input
|
||||||
|
ref={inputRef}
|
||||||
|
style={{
|
||||||
|
width: "30vw",
|
||||||
|
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||||
|
}}
|
||||||
|
placeholder={"Send command to port(s)"}
|
||||||
|
value={valueInput}
|
||||||
|
onChange={(event) => {
|
||||||
|
const newValue = event.currentTarget.value;
|
||||||
|
setValueInput(newValue);
|
||||||
|
}}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
const listLine = selectedLines.length
|
||||||
|
? selectedLines
|
||||||
|
: station?.lines;
|
||||||
|
if (listLine?.length) {
|
||||||
|
socket?.emit("write_command_line_from_web", {
|
||||||
|
lineIds: listLine.map((line) => line.id),
|
||||||
|
stationId: station.id,
|
||||||
|
command: valueInput + "\r\n",
|
||||||
|
});
|
||||||
|
// setTimeout(() => {
|
||||||
|
// socket?.emit("write_command_line_from_web", {
|
||||||
|
// lineIds: listLine.map((line) => line.id),
|
||||||
|
// stationId: station.id,
|
||||||
|
// command: " \n",
|
||||||
|
// });
|
||||||
|
// }, 1000);
|
||||||
|
}
|
||||||
|
setValueInput("");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
rightSectionPointerEvents="all"
|
||||||
|
rightSection={
|
||||||
|
<CloseButton
|
||||||
|
aria-label="Clear input"
|
||||||
|
onClick={() => setValueInput("")}
|
||||||
|
style={{
|
||||||
|
display: valueInput ? undefined : "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
}}
|
/>
|
||||||
/>
|
</Box>
|
||||||
<ButtonDPELP
|
</Box>
|
||||||
socket={socket}
|
<Box style={{ width: "220px" }}>
|
||||||
selectedLines={selectedLines}
|
<Flex align={"center"} wrap={"wrap"} gap={"xs"}>
|
||||||
isDisable={isDisable || selectedLines.length === 0}
|
<ButtonSelect
|
||||||
onClick={() => {
|
selectedLines={selectedLines}
|
||||||
// setSelectedLines([]);
|
setSelectedLines={setSelectedLines}
|
||||||
setIsDisable(true);
|
station={station}
|
||||||
setTimeout(() => {
|
userName={user?.userName}
|
||||||
setIsDisable(false);
|
onClick={() => {
|
||||||
}, 5000);
|
const lines = station.lines.filter(
|
||||||
}}
|
(line) =>
|
||||||
/>
|
!line?.userOpenCLI ||
|
||||||
<Button
|
line?.userOpenCLI === user?.userName
|
||||||
fw={400}
|
);
|
||||||
disabled={isDisable || selectedLines.length === 0}
|
if (selectedLines.length !== lines.length) {
|
||||||
variant="filled"
|
setSelectedLines(lines);
|
||||||
color="yellow"
|
lines.forEach((line) => {
|
||||||
style={{ height: "30px", width: "100px" }}
|
socket?.emit("open_cli", {
|
||||||
onClick={() => setOpenScenarioModal(true)}
|
lineId: line.id,
|
||||||
>
|
stationId: line.stationId || line.station_id,
|
||||||
Scenario
|
userEmail: user?.email,
|
||||||
</Button>
|
userName: user?.userName,
|
||||||
<DrawerLogs
|
});
|
||||||
socket={socket}
|
});
|
||||||
isLogModalOpen={isLogModalOpen}
|
} else {
|
||||||
setIsLogModalOpen={setIsLogModalOpen}
|
lines.forEach((line) => {
|
||||||
testLogContent={testLogContent}
|
socket?.emit("close_cli", {
|
||||||
setTestLogContent={setTestLogContent}
|
lineId: line?.id,
|
||||||
/>
|
stationId: line.stationId || line.station_id,
|
||||||
</Flex>
|
});
|
||||||
</Box>
|
});
|
||||||
</Flex>
|
setSelectedLines([]);
|
||||||
</Tabs.Panel>
|
}
|
||||||
<Tabs.Panel value="apc" ps={"xs"}>
|
}}
|
||||||
<DrawerAPCControl socket={socket} stationAPI={station} />
|
/>
|
||||||
</Tabs.Panel>
|
<ButtonDPELP
|
||||||
<Tabs.Panel value="switch" ps={"xs"}>
|
socket={socket}
|
||||||
<DrawerSwitchControl socket={socket} stationAPI={station} />
|
selectedLines={selectedLines}
|
||||||
</Tabs.Panel>
|
isDisable={isDisable || selectedLines.length === 0}
|
||||||
</Tabs>
|
onClick={() => {
|
||||||
</Grid.Col>
|
// setSelectedLines([]);
|
||||||
<Grid.Col span={1}></Grid.Col>
|
setIsDisable(true);
|
||||||
</Grid>
|
setTimeout(() => {
|
||||||
</Box>
|
setIsDisable(false);
|
||||||
|
}, 5000);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
fw={400}
|
||||||
|
disabled={isDisable || selectedLines.length === 0}
|
||||||
|
variant="filled"
|
||||||
|
color="yellow"
|
||||||
|
style={{ height: "30px", width: "100px" }}
|
||||||
|
onClick={() => setOpenScenarioModal(true)}
|
||||||
|
>
|
||||||
|
Scenario
|
||||||
|
</Button>
|
||||||
|
<DrawerLogs
|
||||||
|
socket={socket}
|
||||||
|
isLogModalOpen={isLogModalOpen}
|
||||||
|
setIsLogModalOpen={setIsLogModalOpen}
|
||||||
|
testLogContent={testLogContent}
|
||||||
|
setTestLogContent={setTestLogContent}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</Tabs.Panel>
|
||||||
|
<Tabs.Panel value="apc" ps={"xs"}>
|
||||||
|
<DrawerAPCControl socket={socket} stationAPI={station} />
|
||||||
|
</Tabs.Panel>
|
||||||
|
<Tabs.Panel value="switch" ps={"xs"}>
|
||||||
|
<DrawerSwitchControl socket={socket} stationAPI={station} />
|
||||||
|
</Tabs.Panel>
|
||||||
|
</Tabs>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={1}></Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Drawer Scenario để Add/Edit */}
|
{/* Drawer Scenario để Add/Edit */}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Avatar,
|
Avatar,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Group,
|
Group,
|
||||||
Menu,
|
Menu,
|
||||||
|
|
@ -296,7 +295,7 @@ export default function DraggableTabs({
|
||||||
<Tooltip
|
<Tooltip
|
||||||
withArrow
|
withArrow
|
||||||
label={usersConnecting.map((el) => (
|
label={usersConnecting.map((el) => (
|
||||||
<Text key={el.userId}>{el.userName}</Text>
|
<Text key={el.userId || el.id}>{el.userName}</Text>
|
||||||
))}
|
))}
|
||||||
>
|
>
|
||||||
<Avatar radius="xl" me={"sm"}>
|
<Avatar radius="xl" me={"sm"}>
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,8 @@ export type TLine = {
|
||||||
export type TUser = {
|
export type TUser = {
|
||||||
userId: number;
|
userId: number;
|
||||||
userName: string;
|
userName: string;
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type APCProps = {
|
export type APCProps = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue