Merge branch 'main' of https://gitea.nswteam.net/andrew.ng/ATC_SIMPLE
This commit is contained in:
commit
13a3788c4a
|
|
@ -286,6 +286,11 @@ export default class LineConnection {
|
|||
if (!this.client || this.client.destroyed) {
|
||||
console.log('Not connected')
|
||||
this.isRunningScript = false
|
||||
this.socketIO.emit('running_scenario', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
title: '',
|
||||
})
|
||||
this.outputBuffer = ''
|
||||
return
|
||||
}
|
||||
|
|
@ -299,6 +304,11 @@ export default class LineConnection {
|
|||
)
|
||||
if (script?.title === 'DPELP') this.dataDPELP = ''
|
||||
this.isRunningScript = true
|
||||
this.socketIO.emit('running_scenario', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
title: script?.title,
|
||||
})
|
||||
const now = Date.now()
|
||||
this.outputScenario += `\n\n---start-scenarios---${now}---${userName}---${script?.title}---\n---scenario---${script?.title}---${now}---\n`
|
||||
appendLog(
|
||||
|
|
@ -318,6 +328,11 @@ export default class LineConnection {
|
|||
return new Promise((resolve, reject) => {
|
||||
const timeoutTimer = setTimeout(() => {
|
||||
this.isRunningScript = false
|
||||
this.socketIO.emit('running_scenario', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
title: '',
|
||||
})
|
||||
this.outputBuffer = ''
|
||||
this.outputScenario = ''
|
||||
this.config.output += 'Timeout run scenario'
|
||||
|
|
@ -347,6 +362,11 @@ export default class LineConnection {
|
|||
return
|
||||
} else clearTimeout(timeoutTimer)
|
||||
this.isRunningScript = false
|
||||
this.socketIO.emit('running_scenario', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
title: '',
|
||||
})
|
||||
this.outputBuffer = ''
|
||||
this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
|
||||
appendLog(
|
||||
|
|
@ -676,7 +696,7 @@ export default class LineConnection {
|
|||
(Tóm tắt trạng thái tổng thể của hệ thống trong 2–4 ý)
|
||||
|
||||
issue:
|
||||
(Tóm tắt cực ngắn gọn các lỗi/dấu hiệu bất thường, mỗi vấn đề 1 dòng)
|
||||
(Tóm tắt cực ngắn gọn các lỗi/dấu hiệu bất thường, mỗi vấn đề 1 dòng, bỏ qua các vấn đề không quan trọng như về port up/down hay Invalid input, Incomplete command)
|
||||
|
||||
Quy tắc:
|
||||
Không giải thích dài dòng.
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ export default class SwitchController {
|
|||
|
||||
public async getPorts(): Promise<boolean> {
|
||||
this._send(' terminal length 0')
|
||||
this._send('show interface status')
|
||||
this._send('show interface')
|
||||
this._send(' ')
|
||||
await this.sleep(2000)
|
||||
const statusOutput = this.buffer
|
||||
|
|
@ -289,17 +289,25 @@ export default class SwitchController {
|
|||
|
||||
const lines = statusOutput.split('\n')
|
||||
const ports = this.ports?.length > 0 ? [...this.ports] : []
|
||||
|
||||
for (const line of lines) {
|
||||
const match = line.match(/^(\S+)\s+(connected|notconnect|disabled|inactive)/i)
|
||||
// Match: "Gi0/1 is up, line protocol is up"
|
||||
const match = line.match(
|
||||
/^(TenGigabitEthernet|GigabitEthernet|FastEthernet|Ethernet)\S*\s+is\s+(\S+),\s+line protocol is\s+(\S+)/i
|
||||
)
|
||||
if (match) {
|
||||
const name = match[1]
|
||||
const rawStatus = match[2].toLowerCase()
|
||||
const status = rawStatus === 'connected' ? 'ON' : 'OFF'
|
||||
const name = match[1] + line.split(' ')[0].replace(match[1], '')
|
||||
const status1 = match[2].toLowerCase() // up / down / administratively
|
||||
const status2 = match[3].toLowerCase() // up / down
|
||||
|
||||
// Rule: interface is considered ON only when both are "up"
|
||||
const status = status1 === 'up' && status2 === 'up' ? 'ON' : 'OFF'
|
||||
|
||||
const port = ports.find((p) => p.name === name)
|
||||
if (port) {
|
||||
port.status = status
|
||||
} else ports.push({ name, status, poe: 'UNKNOWN' })
|
||||
} else {
|
||||
ports.push({ name, status, poe: 'UNKNOWN' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -346,6 +346,16 @@ function App() {
|
|||
}, 100);
|
||||
});
|
||||
|
||||
socket?.on("running_scenario", (data) => {
|
||||
setTimeout(() => {
|
||||
updateValueLineStation(
|
||||
data?.lineId,
|
||||
{ runningScenario: data?.title || "" },
|
||||
data?.stationId
|
||||
);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// ✅ cleanup on unmount or when socket changes
|
||||
return () => {
|
||||
socket.off("init");
|
||||
|
|
@ -359,6 +369,9 @@ function App() {
|
|||
socket.off("response_content_log");
|
||||
socket.off("data_textfsm");
|
||||
socket.off("update_ticket");
|
||||
socket.off("update_baud");
|
||||
socket.off("line_connecting");
|
||||
socket.off("running_scenario");
|
||||
};
|
||||
}, [socket, stations, selectedLine]);
|
||||
|
||||
|
|
|
|||
|
|
@ -284,6 +284,19 @@ const CardLine = ({
|
|||
connecting...
|
||||
</motion.div>
|
||||
)}
|
||||
{line?.runningScenario && (
|
||||
<motion.div
|
||||
style={{ fontSize: "11px", color: "red" }}
|
||||
animate={{ opacity: [0.2, 1, 0.2] }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
>
|
||||
Running {line?.runningScenario}
|
||||
</motion.div>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex justify={"space-between"} w={"100%"} display={"none"}>
|
||||
<Box>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import axios from "axios";
|
|||
import { notifications } from "@mantine/notifications";
|
||||
import classes from "./Component.module.css";
|
||||
import { listBaudDefault } from "../untils/constanst";
|
||||
import { motion } from "motion/react";
|
||||
const apiUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
const INIT_TICKET = {
|
||||
|
|
@ -427,6 +428,34 @@ const ModalTerminal = ({
|
|||
>
|
||||
<Grid>
|
||||
<Grid.Col span={3}>
|
||||
<Flex style={{ height: "20px" }}>
|
||||
{line?.connecting && (
|
||||
<motion.div
|
||||
style={{ fontSize: "12px", color: "red" }}
|
||||
animate={{ opacity: [0.2, 1, 0.2] }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
>
|
||||
connecting...
|
||||
</motion.div>
|
||||
)}
|
||||
{line?.runningScenario && (
|
||||
<motion.div
|
||||
style={{ fontSize: "12px", color: "red" }}
|
||||
animate={{ opacity: [0.2, 1, 0.2] }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
>
|
||||
Running {line?.runningScenario}
|
||||
</motion.div>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex justify={"space-between"} direction={"column"} h={"95%"}>
|
||||
<Box>
|
||||
<Flex gap={"sm"} justify={"center"} align={"center"}>
|
||||
|
|
|
|||
|
|
@ -134,7 +134,10 @@ const TerminalCLI: React.FC<TerminalCLIProps> = ({
|
|||
useEffect(() => {
|
||||
if (cliOpened && isInit) {
|
||||
if (terminal.current)
|
||||
setTimeout(() => terminal.current?.write(content), 200);
|
||||
setTimeout(() => {
|
||||
terminal.current?.write(content);
|
||||
terminal.current?.scrollToBottom();
|
||||
}, 200);
|
||||
|
||||
if (fitRef.current) setTimeout(() => fitRef.current?.fit(), 500);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ export type TLine = {
|
|||
baud?: number;
|
||||
tickets?: TDataTicket[];
|
||||
connecting?: boolean;
|
||||
runningScenario?: string;
|
||||
};
|
||||
|
||||
export type TUser = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue