Update form report summary fully tested
This commit is contained in:
parent
63b264304e
commit
4369d722ef
|
|
@ -76,6 +76,7 @@ interface LineConfig {
|
|||
ports: string[]
|
||||
runningScenario: string
|
||||
runningPhysical: boolean
|
||||
listFeatureTested: string[]
|
||||
// history: string
|
||||
}
|
||||
|
||||
|
|
@ -133,8 +134,6 @@ export default class LineConnection {
|
|||
private outputPhysicalTest: string
|
||||
private outputLoadIosLicense: string | boolean
|
||||
private listDeviceIos: string[]
|
||||
private debounceTimer: NodeJS.Timeout | null = null
|
||||
private testingPortPoE: boolean
|
||||
|
||||
constructor(config: LineConfig, socketIO: any, handleClearLine: () => void) {
|
||||
this.config = config
|
||||
|
|
@ -164,8 +163,6 @@ export default class LineConnection {
|
|||
this.outputPhysicalTest = ''
|
||||
this.outputLoadIosLicense = ''
|
||||
this.listDeviceIos = []
|
||||
this.debounceTimer = null
|
||||
this.testingPortPoE = false
|
||||
}
|
||||
/**
|
||||
* Connect to line with socket
|
||||
|
|
@ -193,6 +190,8 @@ export default class LineConnection {
|
|||
lineNumber,
|
||||
status: 'connected',
|
||||
})
|
||||
this.config.listFeatureTested = []
|
||||
this.sendFeatureTested()
|
||||
this.checkLog()
|
||||
resolve()
|
||||
}, 1000)
|
||||
|
|
@ -570,7 +569,10 @@ export default class LineConnection {
|
|||
`DPELP DATA line ${this.config.lineNumber} of ${this.config.stationName}:`,
|
||||
this.dataDPELP
|
||||
)
|
||||
|
||||
this.config.listFeatureTested = [
|
||||
...new Set([...this.config.listFeatureTested, 'DPELP']),
|
||||
]
|
||||
this.sendFeatureTested()
|
||||
// }
|
||||
if (this.config.latestScenario)
|
||||
this.config.latestScenario = { ...this.config.latestScenario, detectAI: detectLog }
|
||||
|
|
@ -1088,7 +1090,6 @@ export default class LineConnection {
|
|||
this.config.runningPhysical = true
|
||||
this.config.runningScenario = 'Physical Test'
|
||||
const listPorts = await this.getPorts()
|
||||
this.testingPortPoE = true
|
||||
this.socketIO.emit('running_scenario', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
|
|
@ -1107,7 +1108,7 @@ export default class LineConnection {
|
|||
this.config.inventory
|
||||
)
|
||||
const interval = setInterval(async () => {
|
||||
if (!this.config.runningPhysical) {
|
||||
if (!this.config.runningPhysical || this.config.status !== 'connected') {
|
||||
clearInterval(interval)
|
||||
} else {
|
||||
this.flushLogBuffer()
|
||||
|
|
@ -1146,7 +1147,6 @@ export default class LineConnection {
|
|||
this.physicalTest.resetTestedPorts()
|
||||
this.config.runningPhysical = false
|
||||
this.config.runningScenario = ''
|
||||
this.testingPortPoE = false
|
||||
this.outputBuffer = ''
|
||||
this.outputScenario = ''
|
||||
this.outputPhysicalTest = ''
|
||||
|
|
@ -1196,6 +1196,8 @@ export default class LineConnection {
|
|||
* Send report after done physical test
|
||||
*/
|
||||
async sendReportPhysicalTest() {
|
||||
this.config.listFeatureTested = [...new Set([...this.config.listFeatureTested, 'PHYSICAL'])]
|
||||
this.sendFeatureTested()
|
||||
const formReport = this.physicalTest.getFormReport()
|
||||
await sendMessageToMail(
|
||||
`[ATC] - [${this.config.stationName} - Line: ${this.config.lineNumber}] - Physical Ports Test`,
|
||||
|
|
@ -1640,4 +1642,64 @@ ${log}
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendFeatureTested = async () => {
|
||||
this.socketIO.emit('feature_tested', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
listFeatureTested: this.config.listFeatureTested,
|
||||
})
|
||||
}
|
||||
|
||||
sendReportSummary = async () => {
|
||||
const portPhysical = Array.from(this.physicalTest.ports.values())
|
||||
const showVersion = this.config?.data?.find(
|
||||
(d) => d.command?.trim()?.includes('show ver') || d.command?.trim()?.includes('sh ver')
|
||||
)
|
||||
const dataShowVersion =
|
||||
showVersion?.textfsm && showVersion?.textfsm?.[0]
|
||||
? showVersion?.textfsm?.[0]
|
||||
: this.config?.inventory
|
||||
|
||||
const showLicense = this.config?.data?.find(
|
||||
(d) => d.command?.trim()?.includes('show lic') || d.command?.trim()?.includes('sh lic')
|
||||
)
|
||||
const dataShowLic =
|
||||
showLicense?.textfsm && Array.isArray(showLicense?.textfsm) ? showLicense?.textfsm : null
|
||||
const issue = this.config?.latestScenario?.detectAI?.issue || []
|
||||
const body = `<table cellpadding="6" cellspacing="0" border="1" style="margin-top: 10px; border-collapse: collapse; width: 100%">
|
||||
<tr>
|
||||
<td style="width: 50%; text-align: center;">DPELP</td>
|
||||
<td style="text-align: center;">Physical Test</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 50%;">
|
||||
Model : <b>${this.config?.inventory?.pid ?? 'N/A'}</b><br/>
|
||||
Serial Number : <b>${this.config?.inventory?.sn ?? 'N/A'}</b><br/>
|
||||
MAC : <b>${dataShowVersion?.MAC_ADDRESS ?? ''}</b><br/>
|
||||
IOS : <b>${dataShowVersion?.SOFTWARE_IMAGE ?? ''}</b><br/>
|
||||
License : <b>${
|
||||
dataShowLic
|
||||
? dataShowLic
|
||||
?.filter((el) => el.LICENSE_TYPE === 'Permanent')
|
||||
?.map((v) => v.FEATURE)
|
||||
?.join(', ')
|
||||
: ''
|
||||
}</b><br/>
|
||||
Summary : <b>${this.config?.latestScenario?.detectAI?.summary || ''}</b><br/>
|
||||
Issue : <b>${issue?.length ? `<br>- ` + issue.join(`<br>- `) : 'No issues detected.'}</b><br/>
|
||||
</td>
|
||||
<td>
|
||||
Total Ports : ${portPhysical?.length}<br/>
|
||||
Ports Tested (UP) : <b style="color: #008000;">${portPhysical.filter((p) => p.tested).length}</b><br/>
|
||||
Ports Missing : <b style="color: #ff0000;">${portPhysical.filter((p) => !p.tested).length}</b><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>`
|
||||
|
||||
await sendMessageToMail(
|
||||
`[ATC] - [${this.config.stationName} - Line: ${this.config.lineNumber}] - Summary Fully Tested`,
|
||||
body
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ export class WebSocketIo {
|
|||
titleAuto: `[${scenarioName || 'DPELP'}] - ${stationName} - ` + dataFormat,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error('Error sending wiki message:', error)
|
||||
}
|
||||
try {
|
||||
await sendMessageToMail(
|
||||
|
|
@ -637,7 +637,7 @@ export class WebSocketIo {
|
|||
tableHTML
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error('Error sending mail:', error)
|
||||
}
|
||||
try {
|
||||
await sendMessageToZulip(
|
||||
|
|
@ -648,7 +648,7 @@ export class WebSocketIo {
|
|||
zulipMess
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error('Error sending zulip message:', error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
@ -830,6 +830,23 @@ export class WebSocketIo {
|
|||
{}
|
||||
)
|
||||
})
|
||||
|
||||
socket.on('send_summary_report', async (data) => {
|
||||
const { stationId, lineId } = data
|
||||
// Check station is active
|
||||
const activeStation = await checkStationActive(stationId)
|
||||
if (!activeStation) return
|
||||
|
||||
await this.handleLineOperation(
|
||||
io,
|
||||
stationId,
|
||||
[lineId],
|
||||
async (lineCon) => {
|
||||
lineCon.sendReportSummary()
|
||||
},
|
||||
{}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
socketServer.listen(SOCKET_IO_PORT, () => {
|
||||
|
|
@ -876,6 +893,7 @@ export class WebSocketIo {
|
|||
runningPhysical: false,
|
||||
runningScenario: '',
|
||||
latestScenario: latestScenario,
|
||||
listFeatureTested: [],
|
||||
},
|
||||
socket,
|
||||
async () => {
|
||||
|
|
|
|||
|
|
@ -441,6 +441,15 @@ function App() {
|
|||
);
|
||||
});
|
||||
|
||||
socket?.on("feature_tested", (data) => {
|
||||
if (data?.listFeatureTested && data?.listFeatureTested.length > 0)
|
||||
updateValueLineStation(
|
||||
data?.lineId,
|
||||
{ listFeatureTested: data?.listFeatureTested },
|
||||
data?.stationId
|
||||
);
|
||||
});
|
||||
|
||||
// ✅ cleanup on unmount or when socket changes
|
||||
return () => {
|
||||
socket.off("init");
|
||||
|
|
@ -459,6 +468,7 @@ function App() {
|
|||
socket.off("running_scenario");
|
||||
socket.off("user_clear_terminal");
|
||||
socket.off("test_port_physical");
|
||||
socket.off("feature_tested");
|
||||
};
|
||||
}, [socket, stations, selectedLine]);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
Modal,
|
||||
ScrollArea,
|
||||
SimpleGrid,
|
||||
Stepper,
|
||||
Tabs,
|
||||
Text,
|
||||
Textarea,
|
||||
|
|
@ -53,6 +54,7 @@ import ModalSelectLicense from "./ModalSelectLicense";
|
|||
import ModalRunScenario from "./ModalRunScenario";
|
||||
import DrawerScenario from "./ModalScenario";
|
||||
import AutoProgress from "../Components/AutoProgress";
|
||||
import { bodyDPELP } from "../../untils/helper";
|
||||
const apiUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
const INIT_TICKET = {
|
||||
|
|
@ -117,11 +119,24 @@ const ModalTerminal = ({
|
|||
const [openScenarioModal, setOpenScenarioModal] = useState<boolean>(false);
|
||||
const [openDrawerScenario, setOpenDrawerScenario] = useState<boolean>(false);
|
||||
const [isPhysicalTest, setIsPhysicalTest] = useState<boolean>(false);
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [activeTabs, setActiveTabs] = useState("general");
|
||||
|
||||
useEffect(() => {
|
||||
setIsPhysicalTest(line?.runningPhysical || false);
|
||||
}, [line?.runningPhysical]);
|
||||
|
||||
useEffect(() => {
|
||||
if (line?.listFeatureTested && line?.listFeatureTested.length > 0) {
|
||||
if (line?.listFeatureTested?.includes("DPELP")) setActiveStep(1);
|
||||
if (
|
||||
line?.listFeatureTested?.includes("PHYSICAL") &&
|
||||
line?.listFeatureTested?.includes("DPELP")
|
||||
)
|
||||
setActiveStep(2);
|
||||
} else setActiveStep(0);
|
||||
}, [opened, line?.listFeatureTested]);
|
||||
|
||||
useEffect(() => {
|
||||
if (opened && line?.tickets && line?.tickets?.length > 0) {
|
||||
const data = line?.tickets[0];
|
||||
|
|
@ -131,6 +146,7 @@ const ModalTerminal = ({
|
|||
setLatestTicket(INIT_TICKET);
|
||||
setDataTicket(INIT_TICKET);
|
||||
setValueBaud("");
|
||||
setActiveStep(0);
|
||||
}
|
||||
}, [opened, line?.tickets]);
|
||||
|
||||
|
|
@ -520,70 +536,154 @@ const ModalTerminal = ({
|
|||
)
|
||||
socket?.emit("close_cli", {
|
||||
lineId: line?.id,
|
||||
stationId: line?.station_id,
|
||||
stationId: line?.station_id || line?.stationId,
|
||||
});
|
||||
}}
|
||||
size={"100%"}
|
||||
style={{ position: "absolute", left: 0 }}
|
||||
title={
|
||||
<Flex align={"center"} w={"400px"} justify={"space-between"}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
// justifyContent: "center",
|
||||
// width: "400px",
|
||||
marginRight: "12px",
|
||||
<Flex justify={"space-between"} align={"center"} w={"100%"}>
|
||||
<Flex w={"30vw"}>
|
||||
<Flex align={"center"} w={"400px"} justify={"space-between"}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
// justifyContent: "center",
|
||||
// width: "400px",
|
||||
marginRight: "12px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
alignItems: "center",
|
||||
fontSize: "13px",
|
||||
color: "red",
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
{line?.userOpenCLI
|
||||
? (line?.userOpenCLI === user?.userName
|
||||
? "You are"
|
||||
: line?.userOpenCLI + " is") + " using"
|
||||
: "Terminal is used"}
|
||||
</div>
|
||||
</Box>
|
||||
<Flex>
|
||||
{line?.connecting && line?.status !== "connected" && (
|
||||
<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>
|
||||
</Flex>
|
||||
<Stepper
|
||||
w={600}
|
||||
size="xs"
|
||||
color={isDisable ? "gray" : "cyan"}
|
||||
active={activeStep}
|
||||
onStepClick={(step) => {
|
||||
if (!line) return;
|
||||
if (step === 0) {
|
||||
const dpelp = scenarios?.find(
|
||||
(el) => el.title.toUpperCase() === "DPELP"
|
||||
);
|
||||
socket?.emit(
|
||||
"run_scenario",
|
||||
Object.assign(line, {
|
||||
scenario: dpelp
|
||||
? dpelp
|
||||
: {
|
||||
id: 0,
|
||||
is_reboot: 0,
|
||||
title: "DPELP",
|
||||
timeout: 360000,
|
||||
body: JSON.stringify(bodyDPELP),
|
||||
},
|
||||
})
|
||||
);
|
||||
socket?.emit("run_all_dpelp", {
|
||||
lineIds: [line?.id],
|
||||
stationName: stationItem?.name,
|
||||
stationId: Number(stationItem?.id),
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 10000);
|
||||
}
|
||||
if (step === 1) {
|
||||
setActiveTabs("physical");
|
||||
socket?.emit("run_physical_test", {
|
||||
lineId: line?.id,
|
||||
stationId: Number(stationItem?.id),
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 15000);
|
||||
}
|
||||
if (step === 2 && !isDisable) {
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
socket?.emit("send_summary_report", {
|
||||
lineId: line?.id,
|
||||
stationId: line?.station_id || line?.stationId,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
alignItems: "center",
|
||||
fontSize: "13px",
|
||||
color: "red",
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
{line?.userOpenCLI
|
||||
? (line?.userOpenCLI === user?.userName
|
||||
? "You are"
|
||||
: line?.userOpenCLI + " is") + " using"
|
||||
: "Terminal is used"}
|
||||
</div>
|
||||
</Box>
|
||||
<Flex>
|
||||
{line?.connecting && line?.status !== "connected" && (
|
||||
<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>
|
||||
<Stepper.Step
|
||||
disabled={isDisable}
|
||||
label="DPELP"
|
||||
description="Run DPELP Test"
|
||||
></Stepper.Step>
|
||||
<Stepper.Step
|
||||
disabled={isDisable}
|
||||
label="Physical Test"
|
||||
description="Test physical ports"
|
||||
></Stepper.Step>
|
||||
<Stepper.Step
|
||||
disabled={isDisable}
|
||||
label="Completed"
|
||||
description="Click to send report"
|
||||
></Stepper.Step>
|
||||
</Stepper>
|
||||
<Flex></Flex>
|
||||
</Flex>
|
||||
}
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={3}>
|
||||
<Tabs defaultValue="general" h={"100%"}>
|
||||
<Tabs
|
||||
defaultValue="general"
|
||||
h={"100%"}
|
||||
value={activeTabs}
|
||||
onChange={(value) => setActiveTabs(value || "general")}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab w={"50%"} value="general">
|
||||
<IconInfoCircle
|
||||
|
|
|
|||
|
|
@ -89,3 +89,110 @@ export function bytesToMB(bytes: number, decimal = 2): number {
|
|||
export function bytesToKB(bytes: number, decimal = 2): number {
|
||||
return Number((bytes / 1024).toFixed(decimal));
|
||||
}
|
||||
export const bodyDPELP = [
|
||||
{
|
||||
expect: "",
|
||||
send: "",
|
||||
delay: "1",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: " no",
|
||||
delay: "1",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "\r\n",
|
||||
delay: "1",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "\r\n",
|
||||
delay: "2",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
// {
|
||||
// expect: "",
|
||||
// send: " terminal length 0",
|
||||
// delay: "3",
|
||||
// repeat: "1",
|
||||
// note: "",
|
||||
// },
|
||||
{
|
||||
expect: "",
|
||||
send: "enable",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show inventory",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show version | include License",
|
||||
delay: "1",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show version",
|
||||
delay: "1",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show diag",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show post",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show env all",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show license",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show log",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show platform",
|
||||
delay: "3",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ export type TLine = {
|
|||
loadingClearTerminal?: boolean;
|
||||
runningPhysical?: boolean;
|
||||
listPortsPhysical?: string[];
|
||||
listFeatureTested?: string[];
|
||||
};
|
||||
|
||||
export type TUser = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue