Enhance switch and APC controls, UI improvements
Refactored switch port restart logic to use turnPortOff/on methods. Improved socket communication for switch port status and clear line actions. Updated DrawerControl and ModalTerminal to streamline APC and switch controls, added filtering and persistent view options for switch ports, and improved UI consistency. Fixed ticket creation logic and enhanced terminal and toolbar layouts for better usability.
This commit is contained in:
parent
1e058636b2
commit
f695062ec4
|
|
@ -123,14 +123,17 @@ class APCController {
|
|||
}
|
||||
}
|
||||
|
||||
private _handleError(err: NodeJS.ErrnoException): void {
|
||||
private async _handleError(err: NodeJS.ErrnoException): Promise<void> {
|
||||
this.output += `\r\n\r\n[ERROR] ${err.message}`
|
||||
this.onData(this.output, this.status)
|
||||
if (err.code === 'ECONNRESET') {
|
||||
setTimeout(() => {
|
||||
console.log('[ECONNRESET] Trying reconnect apc:', this.apc_ip)
|
||||
this.reconnect()
|
||||
}, 15000)
|
||||
console.log('[ECONNRESET] Trying reconnect apc:', this.apc_ip)
|
||||
if (this.retryConnect <= 5) {
|
||||
await this.sleep(15000)
|
||||
console.log('Retry connect times', this.retryConnect)
|
||||
this.retryConnect += 1
|
||||
await this.reconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export default class LineConnection {
|
|||
this.socketIO.emit('line_error', {
|
||||
stationId,
|
||||
lineId: id,
|
||||
error: '\n' + err.message + '\n',
|
||||
error: '\r\n' + err.message + '\r\n',
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -214,21 +214,26 @@ export default class SwitchController {
|
|||
}
|
||||
|
||||
public async restartPort(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`shutdown`)
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
await this.sleep(2000)
|
||||
this._send(`no shutdown`)
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
// await this.enterEnableMode()
|
||||
// this._send(`configure terminal`)
|
||||
// // await this._waitFor('(config)#')
|
||||
// await this.sleep(500)
|
||||
// this._send(`interface ${port}`)
|
||||
// // await this._waitFor('(config-if)#')
|
||||
// await this.sleep(500)
|
||||
// this._send(`shutdown`)
|
||||
// // await this._waitFor('(config-if)#')
|
||||
// await this.sleep(500)
|
||||
// await this.sleep(2000)
|
||||
// this._send(`no shutdown`)
|
||||
// // await this._waitFor('(config-if)#')
|
||||
// await this.sleep(500)
|
||||
// this._send(`end`)
|
||||
await this.turnPortOff(port)
|
||||
await this.sleep(300)
|
||||
await this.getPorts()
|
||||
await this.sleep(300)
|
||||
await this.turnPortOn(port)
|
||||
}
|
||||
|
||||
public async disablePoE(port: string) {
|
||||
|
|
|
|||
|
|
@ -380,6 +380,13 @@ export class WebSocketIo {
|
|||
portGroups: element.portGroups,
|
||||
status: element.status,
|
||||
})
|
||||
socket.emit('switch_ports_status', {
|
||||
stationId: station.id,
|
||||
ports:
|
||||
Array.isArray(element.portGroups) && element.portGroups?.length > 0
|
||||
? element.portGroups?.flat()
|
||||
: [],
|
||||
})
|
||||
} else if (element && element.status !== 'CONNECTED') {
|
||||
await element.reconnect()
|
||||
} else await this.connectSwitch(io, station)
|
||||
|
|
@ -460,6 +467,11 @@ export class WebSocketIo {
|
|||
line.config = { ...line.config, ...update }
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('clear_line', async (data) => {
|
||||
const { stationId, lineClear } = data
|
||||
await this.clearLineBeforeConnect(stationId, lineClear)
|
||||
})
|
||||
})
|
||||
|
||||
socketServer.listen(SOCKET_IO_PORT, () => {
|
||||
|
|
@ -659,6 +671,10 @@ export class WebSocketIo {
|
|||
portGroups: ports,
|
||||
status,
|
||||
})
|
||||
socket.emit('switch_ports_status', {
|
||||
stationId: station.id,
|
||||
ports: Array.isArray(ports) && ports?.length > 0 ? ports?.flat() : [],
|
||||
})
|
||||
},
|
||||
})
|
||||
// Connect và login
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ function App() {
|
|||
borderRadius: 8,
|
||||
}}
|
||||
>
|
||||
<ScrollArea h={expandedBottomBar ? "73vh" : "85vh"}>
|
||||
<ScrollArea h={expandedBottomBar ? "70vh" : "85vh"}>
|
||||
{station.lines.length > 8 ? (
|
||||
<Grid
|
||||
style={{
|
||||
|
|
@ -517,13 +517,11 @@ function App() {
|
|||
onChange={(id) => {
|
||||
if (selectedLines.length > 0) {
|
||||
selectedLines.forEach((el) => {
|
||||
if (
|
||||
el?.userOpenCLI === user?.userName &&
|
||||
!selectedLines.find((value) => value.id === el?.id)
|
||||
)
|
||||
console.log(el?.userOpenCLI, user?.userName);
|
||||
if (el?.userOpenCLI === user?.userName)
|
||||
socket?.emit("close_cli", {
|
||||
lineId: el?.id,
|
||||
stationId: el?.station_id,
|
||||
stationId: Number(activeTab),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -532,7 +530,7 @@ function App() {
|
|||
setLoadingTerminal(false);
|
||||
setTimeout(() => {
|
||||
setLoadingTerminal(true);
|
||||
}, 100);
|
||||
}, 500);
|
||||
}}
|
||||
setActive={setActiveTab}
|
||||
active={activeTab}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ const BottomToolBar = ({
|
|||
<motion.div
|
||||
initial={false}
|
||||
animate={{
|
||||
height: isExpand ? "15vh" : 0,
|
||||
height: isExpand ? "18vh" : 0,
|
||||
y: 0, // đẩy xuống khi thu nhỏ
|
||||
}}
|
||||
transition={{ type: "spring", stiffness: 180, damping: 20 }}
|
||||
|
|
@ -114,7 +114,7 @@ const BottomToolBar = ({
|
|||
setActiveTabBottom(val || "command");
|
||||
}}
|
||||
className={classes.containerBottom}
|
||||
style={{ height: "14vh" }}
|
||||
style={{ height: "18vh" }}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
|
|
@ -156,7 +156,7 @@ const BottomToolBar = ({
|
|||
|
||||
<Tabs.Panel value="command" p={"xs"}>
|
||||
<Flex justify={"space-between"}>
|
||||
<ScrollArea h={"10vh"}>
|
||||
<ScrollArea h={"13vh"}>
|
||||
<Flex wrap={"wrap"} gap={"xs"} w={"400px"}>
|
||||
{selectedLines.map((el) => (
|
||||
<Box
|
||||
|
|
@ -314,7 +314,12 @@ const BottomToolBar = ({
|
|||
}, 5000);
|
||||
}}
|
||||
/>
|
||||
<Menu shadow="md" position="top">
|
||||
<Menu
|
||||
trigger="hover"
|
||||
withArrow
|
||||
shadow="md"
|
||||
position="top"
|
||||
>
|
||||
<Menu.Target>
|
||||
<Button
|
||||
fw={400}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import {
|
|||
Card,
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Loader,
|
||||
Radio,
|
||||
ScrollArea,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
|
|
@ -254,7 +256,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: [],
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "reconnect",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
|
|
@ -270,10 +272,144 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
) : (
|
||||
<div style={{ height: "24px" }}></div>
|
||||
)}
|
||||
<Button
|
||||
disabled={isSubmit}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.length
|
||||
? "Deselect All"
|
||||
: "Select All"
|
||||
}
|
||||
// mt={'xs'}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length
|
||||
) {
|
||||
setListOutletSelected([]);
|
||||
} else {
|
||||
setListOutletSelected(
|
||||
listOutlet
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => ({ ...el, apc: 1 }))
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length
|
||||
? "Deselect"
|
||||
: "Select All"}
|
||||
</Button>
|
||||
<Button
|
||||
className={classes.buttonMenuTool}
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={"Restart"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "restart",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={"Turn On"}
|
||||
// mt={'xs'}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "on",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Turn On
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={"Turn Off"}
|
||||
// mt={'xs'}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "off",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Turn Off
|
||||
</Button>
|
||||
</div>
|
||||
</legend>
|
||||
<Box>
|
||||
<Box style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: "10px",
|
||||
paddingTop: "8px",
|
||||
paddingBottom: "8px",
|
||||
}}
|
||||
>
|
||||
{listOutlet
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((outlet, i) => (
|
||||
|
|
@ -315,182 +451,6 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "left",
|
||||
marginTop: "10px",
|
||||
// marginBottom: "10px",
|
||||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmit}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.length
|
||||
? "Deselect All"
|
||||
: "Select All"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length
|
||||
) {
|
||||
setListOutletSelected([]);
|
||||
} else {
|
||||
setListOutletSelected(
|
||||
listOutlet
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => ({ ...el, apc: 1 }))
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length
|
||||
? "Deselect All"
|
||||
: "Select All"}{" "}
|
||||
{"(" + listOutlet.filter((el) => el.apc === 1).length + ")"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Restart All"
|
||||
: "Restart Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "restart",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Restart All"
|
||||
: "Restart Selected"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Turn On All"
|
||||
: "Turn On Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "on",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Turn On All"
|
||||
: "Turn On Selected"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 1).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
0 ||
|
||||
dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Turn Off All"
|
||||
: "Turn Off Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 1)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "off",
|
||||
apcName: "apc_1",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 1).length ===
|
||||
listOutlet.filter((el) => el.apc === 1).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 1).length === 0
|
||||
? "Turn Off All"
|
||||
: "Turn Off Selected"}
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</fieldset>
|
||||
</Grid.Col>
|
||||
|
|
@ -512,7 +472,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: [],
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "reconnect",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
|
|
@ -528,10 +488,145 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
) : (
|
||||
<div style={{ height: "24px" }}></div>
|
||||
)}
|
||||
<Button
|
||||
disabled={isSubmit}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.length
|
||||
? "Deselect All"
|
||||
: "Select All"
|
||||
}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length
|
||||
) {
|
||||
setListOutletSelected([]);
|
||||
} else {
|
||||
setListOutletSelected(
|
||||
listOutlet
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => ({ ...el }))
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length
|
||||
? "Deselect"
|
||||
: "Select All"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
title={"Restart"}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "restart",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
title={"Turn On All"}
|
||||
className={classes.buttonMenuTool}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "on",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Turn On
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
className={classes.buttonMenuTool}
|
||||
title={"Turn Off"}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: { ...stationAPI, lines: [] },
|
||||
action: "off",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Turn Off
|
||||
</Button>
|
||||
</div>
|
||||
</legend>
|
||||
<Box>
|
||||
<Box style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: "10px",
|
||||
paddingTop: "8px",
|
||||
paddingBottom: "8px",
|
||||
}}
|
||||
>
|
||||
{listOutlet
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((outlet, i) => (
|
||||
|
|
@ -573,183 +668,6 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "left",
|
||||
marginTop: "10px",
|
||||
// marginBottom: "10px",
|
||||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmit}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.length
|
||||
? "Deselect All"
|
||||
: "Select All"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length
|
||||
) {
|
||||
setListOutletSelected([]);
|
||||
} else {
|
||||
setListOutletSelected(
|
||||
listOutlet
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => ({ ...el }))
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length
|
||||
? "Deselect All"
|
||||
: "Select All"}{" "}
|
||||
{"(" + listOutlet.filter((el) => el.apc === 2).length + ")"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length === 0
|
||||
? "Restart All"
|
||||
: "Restart Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "restart",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 2).length === 0
|
||||
? "Restart All"
|
||||
: "Restart Selected"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
? "Turn On All"
|
||||
: "Turn On Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "on",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length === 0
|
||||
? "Turn On All"
|
||||
: "Turn On Selected"}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
isSubmit ||
|
||||
listOutlet.filter((el) => el.apc === 2).length === 0 ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
0 ||
|
||||
dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT"
|
||||
}
|
||||
title={
|
||||
listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length === 0
|
||||
? "Turn Off All"
|
||||
: "Turn Off Selected"
|
||||
}
|
||||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
socket?.emit("control_apc", {
|
||||
outletNumbers: listOutletSelected
|
||||
.filter((el) => el.apc === 2)
|
||||
.map((el) => el.number),
|
||||
station: stationAPI,
|
||||
action: "off",
|
||||
apcName: "apc_2",
|
||||
});
|
||||
setListOutletSelected([]);
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{listOutletSelected.filter((el) => el.apc === 2).length ===
|
||||
listOutlet.filter((el) => el.apc === 2).length ||
|
||||
listOutletSelected.filter((el) => el.apc === 2).length === 0
|
||||
? "Turn Off All"
|
||||
: "Turn Off Selected"}
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</fieldset>
|
||||
</Grid.Col>
|
||||
|
|
@ -768,6 +686,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
>([]);
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [checkedActive, setCheckedActive] = useState("all");
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
|
|
@ -776,6 +695,13 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
}
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
const value = localStorage.getItem("show-switch-port");
|
||||
if (value) {
|
||||
setCheckedActive(value);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (loading)
|
||||
setTimeout(() => {
|
||||
|
|
@ -881,6 +807,11 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
return `${type}${last}`;
|
||||
};
|
||||
|
||||
const changeShowPort = (status: string) => {
|
||||
localStorage.setItem("show-switch-port", status);
|
||||
setCheckedActive(status);
|
||||
};
|
||||
|
||||
return loading ? (
|
||||
<Box
|
||||
style={{
|
||||
|
|
@ -932,7 +863,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
socket?.emit("control_switch", {
|
||||
ports: [],
|
||||
command: "reconnect",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
setIsSubmit(true);
|
||||
|
|
@ -1002,7 +933,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe !== "ON")
|
||||
.map((el) => el.name),
|
||||
command: "restart",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
|
|
@ -1011,7 +942,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe === "ON")
|
||||
.map((el) => el.name),
|
||||
command: "restart-poe",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
setListPortsSelected([]);
|
||||
|
|
@ -1058,7 +989,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe !== "ON")
|
||||
.map((el) => el.name),
|
||||
command: "on",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
|
|
@ -1067,7 +998,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe === "ON")
|
||||
.map((el) => el.name),
|
||||
command: "on-poe",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
setListPortsSelected([]);
|
||||
|
|
@ -1114,7 +1045,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe !== "ON")
|
||||
.map((el) => el.name),
|
||||
command: "off",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
|
|
@ -1123,7 +1054,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
.filter((el) => el.poe === "ON")
|
||||
.map((el) => el.name),
|
||||
command: "off-poe",
|
||||
station: stationAPI,
|
||||
station: { ...stationAPI, lines: [] },
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
setListPortsSelected([]);
|
||||
|
|
@ -1138,6 +1069,26 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
? "Turn Off All"
|
||||
: "Turn Off Selected"}
|
||||
</Button>
|
||||
<Group ms="xs" style={{ display: "flex", gap: "8px" }}>
|
||||
<Radio
|
||||
value="all"
|
||||
label="All"
|
||||
checked={checkedActive === "all"}
|
||||
onChange={() => changeShowPort("all")}
|
||||
/>
|
||||
<Radio
|
||||
value="on"
|
||||
label="On"
|
||||
checked={checkedActive === "on"}
|
||||
onChange={() => changeShowPort("on")}
|
||||
/>
|
||||
<Radio
|
||||
value="off"
|
||||
label="Off"
|
||||
checked={checkedActive === "off"}
|
||||
onChange={() => changeShowPort("off")}
|
||||
/>
|
||||
</Group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1155,10 +1106,17 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
span={isLarge ? 11 : isMini ? 1 : 12}
|
||||
>
|
||||
{isLarge ? (
|
||||
<ScrollArea h={"7vh"} w={"68vw"}>
|
||||
<ScrollArea h={"12vh"} w={"68vw"}>
|
||||
<Flex gap={"8px"} wrap={"nowrap"}>
|
||||
{sortedPorts(group)
|
||||
.slice(0, sortedPorts(group).length / 2)
|
||||
.filter((el) => {
|
||||
if (checkedActive === "all") return true;
|
||||
if (checkedActive === "on")
|
||||
return el.status === "ON";
|
||||
if (checkedActive === "off")
|
||||
return el.status === "OFF";
|
||||
})
|
||||
?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
|
|
@ -1212,6 +1170,13 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
sortedPorts(group).length / 2,
|
||||
sortedPorts(group).length
|
||||
)
|
||||
.filter((el) => {
|
||||
if (checkedActive === "all") return true;
|
||||
if (checkedActive === "on")
|
||||
return el.status === "ON";
|
||||
if (checkedActive === "off")
|
||||
return el.status === "OFF";
|
||||
})
|
||||
?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
|
|
@ -1268,49 +1233,59 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
justifyContent: "center",
|
||||
gap: "10px",
|
||||
overflow: "auto",
|
||||
maxHeight: "7vh",
|
||||
maxHeight: "12vh",
|
||||
maxWidth: "70vw",
|
||||
borderLeft: "1px solid #dedede",
|
||||
}}
|
||||
>
|
||||
{sortedPorts(group)?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
shadow="sm"
|
||||
padding="xs"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "50px",
|
||||
backgroundColor:
|
||||
port.poe === "ON"
|
||||
? "#f2dcf8"
|
||||
: port.status === "ON"
|
||||
? "#d4f1d3"
|
||||
: "#f5f5f5",
|
||||
cursor: "pointer",
|
||||
border: listPortsSelected.find(
|
||||
(el) => el.name === port.name
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
}}
|
||||
className={`${isSubmit ? classes.isDisabled : ""}`}
|
||||
onClick={() => {
|
||||
toggleSelect(port);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
{sortedPorts(group)
|
||||
?.filter((el) => {
|
||||
if (checkedActive === "all") return true;
|
||||
if (checkedActive === "on")
|
||||
return el.status === "ON";
|
||||
if (checkedActive === "off")
|
||||
return el.status === "OFF";
|
||||
})
|
||||
?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
shadow="sm"
|
||||
padding="xs"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "2px",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
position: "relative",
|
||||
width: "50px",
|
||||
backgroundColor:
|
||||
port.poe === "ON"
|
||||
? "#f2dcf8"
|
||||
: port.status === "ON"
|
||||
? "#d4f1d3"
|
||||
: "#f5f5f5",
|
||||
cursor: "pointer",
|
||||
border: listPortsSelected.find(
|
||||
(el) => el.name === port.name
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
}}
|
||||
className={`${
|
||||
isSubmit ? classes.isDisabled : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
toggleSelect(port);
|
||||
}}
|
||||
>
|
||||
{/* <IconSection
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "2px",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{/* <IconSection
|
||||
size={"12px"}
|
||||
color={
|
||||
port.poe === "ON"
|
||||
|
|
@ -1320,12 +1295,12 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
: "#b8b8b8"
|
||||
}
|
||||
/> */}
|
||||
<Text fw={500} fz={"11px"}>
|
||||
{normalizePortName(port.name)}
|
||||
</Text>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
<Text fw={500} fz={"11px"}>
|
||||
{normalizePortName(port.name)}
|
||||
</Text>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Grid.Col>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
} from "@mantine/core";
|
||||
import type {
|
||||
IScenario,
|
||||
SwitchPortsProps,
|
||||
TDataTicket,
|
||||
THistoryTicket,
|
||||
TLine,
|
||||
|
|
@ -32,6 +33,15 @@ import axios from "axios";
|
|||
import { notifications } from "@mantine/notifications";
|
||||
const apiUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
const INIT_TICKET = {
|
||||
description: "",
|
||||
sn: "",
|
||||
model: "",
|
||||
station_id: 0,
|
||||
history: "",
|
||||
status: "open",
|
||||
};
|
||||
|
||||
const ModalTerminal = ({
|
||||
opened,
|
||||
onClose,
|
||||
|
|
@ -57,31 +67,32 @@ const ModalTerminal = ({
|
|||
}, []);
|
||||
const [isDisable, setIsDisable] = useState<boolean>(false);
|
||||
const [isDisableTicket, setIsDisableTicket] = useState<boolean>(false);
|
||||
const [latestTicket, setLatestTicket] = useState<TDataTicket>({
|
||||
description: "",
|
||||
sn: "",
|
||||
model: "",
|
||||
station_id: 0,
|
||||
history: "",
|
||||
status: "open",
|
||||
});
|
||||
const [dataTicket, setDataTicket] = useState<TDataTicket>({
|
||||
description: "",
|
||||
sn: "",
|
||||
model: "",
|
||||
station_id: 0,
|
||||
history: "",
|
||||
status: "open",
|
||||
});
|
||||
const [listPorts, setListPorts] = useState<SwitchPortsProps[]>([]);
|
||||
const [latestTicket, setLatestTicket] = useState<TDataTicket>(INIT_TICKET);
|
||||
const [dataTicket, setDataTicket] = useState<TDataTicket>(INIT_TICKET);
|
||||
|
||||
useEffect(() => {
|
||||
if (opened && line?.tickets && line?.tickets?.length > 0) {
|
||||
const data = line?.tickets[0];
|
||||
setLatestTicket(data);
|
||||
setDataTicket({ ...data, description: "" });
|
||||
} else {
|
||||
setLatestTicket(INIT_TICKET);
|
||||
setDataTicket(INIT_TICKET);
|
||||
}
|
||||
}, [opened, line?.tickets]);
|
||||
|
||||
useEffect(() => {
|
||||
socket?.on("switch_ports_status", (data) => {
|
||||
if (data.stationId !== stationItem?.id) return;
|
||||
if (data?.ports && data?.ports.length > 0)
|
||||
setListPorts(data?.ports || []);
|
||||
});
|
||||
return () => {
|
||||
socket?.off("switch_ports_status");
|
||||
};
|
||||
}, [socket, stationItem]);
|
||||
|
||||
const renderHistory = (data: TDataTicket) => {
|
||||
const latest = JSON.parse(latestTicket?.history || "[]");
|
||||
const list =
|
||||
|
|
@ -165,8 +176,8 @@ const ModalTerminal = ({
|
|||
const payload = {
|
||||
id: dataTicket.id || 0,
|
||||
description: dataTicket.description.trim(),
|
||||
model: dataTicket.model.trim(),
|
||||
sn: dataTicket.sn.trim(),
|
||||
model: line?.inventory?.pid.trim(),
|
||||
sn: line?.inventory?.sn.trim(),
|
||||
station_id: Number(stationItem?.id),
|
||||
line_id: Number(line?.id),
|
||||
status: "open",
|
||||
|
|
@ -313,6 +324,35 @@ const ModalTerminal = ({
|
|||
}, 5000);
|
||||
};
|
||||
|
||||
const controlSwitch = (action: string) => {
|
||||
if (!line?.interface) {
|
||||
notifications.show({
|
||||
title: "Error",
|
||||
message: "Hasn't config interface",
|
||||
color: "red",
|
||||
});
|
||||
return;
|
||||
}
|
||||
socket?.emit("control_switch", {
|
||||
ports: [line?.interface],
|
||||
command: action,
|
||||
station: { ...stationItem, lines: [] },
|
||||
ip: stationItem?.switch_control_ip,
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
const findSwitchPort = (portName: string): SwitchPortsProps | null => {
|
||||
if (listPorts?.length > 0) {
|
||||
const port = listPorts.find((el) => el.name === portName);
|
||||
if (port) return port;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Modal
|
||||
|
|
@ -428,55 +468,109 @@ const ModalTerminal = ({
|
|||
</Flex>
|
||||
<Flex>
|
||||
<Text size="md" mr={"sm"} fw={"bold"}>
|
||||
Warning from test report:
|
||||
Warning from test report: AI
|
||||
</Text>
|
||||
<Text size="md">{""}</Text>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Flex justify={"center"}>
|
||||
<IconCircleDot color="green" />
|
||||
<Text size="md" ml={"sm"}>
|
||||
Internet Connected
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex justify={"space-around"} mt={"4px"}>
|
||||
<Button
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
onClick={() => {}}
|
||||
>
|
||||
ON
|
||||
</Button>
|
||||
<Button
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="red"
|
||||
size="xs"
|
||||
onClick={() => {}}
|
||||
>
|
||||
OFF
|
||||
</Button>
|
||||
<Button
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="orange"
|
||||
size="xs"
|
||||
onClick={() => {}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
</Flex>
|
||||
<fieldset>
|
||||
<Flex justify={"center"}>
|
||||
<IconCircleDot color="green" />
|
||||
<Flex>
|
||||
<Text size="sm" ml={"sm"}>
|
||||
Internet
|
||||
</Text>
|
||||
{line?.interface ? (
|
||||
findSwitchPort(line?.interface)?.status === "ON" ? (
|
||||
<Text size="sm" ml={"4px"} c={"green"}>
|
||||
Connected ({line?.interface})
|
||||
</Text>
|
||||
) : (
|
||||
<Text size="sm" ml={"4px"} c={"red"}>
|
||||
Not Connected ({line?.interface})
|
||||
</Text>
|
||||
)
|
||||
) : (
|
||||
<Text c={"red"} size="sm" ml={"4px"}>
|
||||
Not Connected
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex justify={"space-around"} mt={"4px"}>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlSwitch("on");
|
||||
}}
|
||||
>
|
||||
ON
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="red"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlSwitch("off");
|
||||
}}
|
||||
>
|
||||
OFF
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="orange"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlSwitch("restart");
|
||||
}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
</Flex>
|
||||
</fieldset>
|
||||
</Box>
|
||||
<Flex justify={"center"}>
|
||||
<Flex
|
||||
justify={"center"}
|
||||
style={{
|
||||
borderTop: "1px solid #ccc",
|
||||
borderBottom: "1px solid #ccc",
|
||||
paddingTop: "12px",
|
||||
paddingBottom: "12px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
w={"120px"}
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
onClick={() => {}}
|
||||
onClick={() => {
|
||||
if (!line?.lineClear && !line?.line_clear) {
|
||||
notifications.show({
|
||||
title: "Error",
|
||||
message: "Clear line has not been configured",
|
||||
color: "red",
|
||||
});
|
||||
return;
|
||||
}
|
||||
socket?.emit("clear_line", {
|
||||
lineClear: line?.lineClear || line?.line_clear,
|
||||
stationId: stationItem?.id,
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
Clear line
|
||||
</Button>
|
||||
|
|
@ -505,7 +599,7 @@ const ModalTerminal = ({
|
|||
}
|
||||
line_status={line?.status || ""}
|
||||
/>
|
||||
<Flex justify={"space-between"} mt={"md"} pt={"md"} pb={"md"}>
|
||||
<Flex justify={"space-around"} mt={"md"} pt={"md"} pb={"md"}>
|
||||
<ButtonDPELP
|
||||
socket={socket}
|
||||
selectedLines={line ? [line] : []}
|
||||
|
|
@ -517,7 +611,7 @@ const ModalTerminal = ({
|
|||
}, 10000);
|
||||
}}
|
||||
/>
|
||||
<Menu shadow="md" position="top">
|
||||
<Menu trigger="hover" withArrow shadow="md" position="top">
|
||||
<Menu.Target>
|
||||
<Button
|
||||
fw={400}
|
||||
|
|
@ -560,7 +654,7 @@ const ModalTerminal = ({
|
|||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
disabled={true}
|
||||
fw={400}
|
||||
variant="filled"
|
||||
color="green"
|
||||
|
|
@ -570,7 +664,7 @@ const ModalTerminal = ({
|
|||
Select license
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
disabled={true}
|
||||
fw={400}
|
||||
variant="filled"
|
||||
color="green"
|
||||
|
|
@ -599,46 +693,61 @@ const ModalTerminal = ({
|
|||
>
|
||||
Send Break
|
||||
</Button>
|
||||
<Flex justify={"end"}>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
mr={"8px"}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("on");
|
||||
}}
|
||||
>
|
||||
ON
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
mr={"8px"}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="red"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("off");
|
||||
}}
|
||||
>
|
||||
OFF
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="orange"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("restart");
|
||||
}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
</Flex>
|
||||
<Menu trigger="hover" withArrow shadow="md" position="top">
|
||||
<Menu.Target>
|
||||
<Button
|
||||
fw={400}
|
||||
disabled={isDisable}
|
||||
variant="filled"
|
||||
style={{ height: "30px", width: "100px" }}
|
||||
onClick={() => {}}
|
||||
>
|
||||
Power
|
||||
</Button>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Flex gap={"4px"} p={"4px"}>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
mr={"8px"}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("on");
|
||||
}}
|
||||
>
|
||||
ON
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
mr={"8px"}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="red"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("off");
|
||||
}}
|
||||
>
|
||||
OFF
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="orange"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
controlApc("restart");
|
||||
}}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
</Flex>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Flex>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={3}>
|
||||
|
|
@ -722,7 +831,7 @@ const ModalTerminal = ({
|
|||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter" && dataTicket.description) {
|
||||
setDataTicket((pre) => ({ ...pre, description: "" }));
|
||||
if (dataTicket?.status === "closed") {
|
||||
if (dataTicket?.status === "closed" || !dataTicket.id) {
|
||||
handleCreate();
|
||||
} else handleUpdate("open");
|
||||
setIsDisableTicket(true);
|
||||
|
|
@ -747,7 +856,7 @@ const ModalTerminal = ({
|
|||
</Box>
|
||||
<Box mt={"8px"}>
|
||||
<Flex justify={"end"} mt={"4px"}>
|
||||
{dataTicket?.status === "closed" ? (
|
||||
{dataTicket?.status === "closed" || !dataTicket.id ? (
|
||||
<Button
|
||||
disabled={isDisableTicket || !dataTicket.description}
|
||||
mr={"8px"}
|
||||
|
|
@ -787,6 +896,7 @@ const ModalTerminal = ({
|
|||
disabled={
|
||||
isDisableTicket ||
|
||||
dataTicket?.status === "closed" ||
|
||||
!dataTicket.id ||
|
||||
!dataTicket.description
|
||||
}
|
||||
mr={"8px"}
|
||||
|
|
@ -806,7 +916,11 @@ const ModalTerminal = ({
|
|||
Issue
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isDisableTicket || dataTicket?.status === "closed"}
|
||||
disabled={
|
||||
isDisableTicket ||
|
||||
!dataTicket.id ||
|
||||
dataTicket?.status === "closed"
|
||||
}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="red"
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ const TerminalCLI: React.FC<TerminalCLIProps> = ({
|
|||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
if (fitRef.current) fitRef.current?.fit();
|
||||
} else {
|
||||
setIsInit(false);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue