Update flow physical test va confirm skip test

This commit is contained in:
nguyentrungthat 2026-03-10 15:31:43 +07:00
parent faf37c7136
commit c032a29cdd
9 changed files with 462 additions and 232 deletions

View File

@ -28,7 +28,7 @@ import path from 'node:path'
import axios from 'axios'
import redis from '@adonisjs/redis/services/main'
import Line from '#models/line'
import { ErrorRow, TestResult } from '../ultils/types.js'
import { CustomSocket, ErrorRow, TestResult } from '../ultils/types.js'
import momentTZ from 'moment-timezone'
import { PhysicalPortTest } from './physical_test_service.js'
import Station from '#models/station'
@ -79,6 +79,8 @@ interface LineConfig {
runningPhysical: boolean
listFeatureTested: string[]
isReady: boolean
isSkipPhysical?: boolean
reasonSkipPhysical?: string
// history: string
}
@ -201,6 +203,8 @@ export default class LineConnection {
status: 'connected',
})
this.config.listFeatureTested = []
this.config.isSkipPhysical = false
this.config.reasonSkipPhysical = ''
this.sendFeatureTested()
this.checkLog()
resolve()
@ -296,6 +300,8 @@ export default class LineConnection {
this.config.status = 'disconnected'
this.config.output += this.config.output + '[CLEAR_TERMINAL_SCROLL_BACK]'
this.config.listFeatureTested = []
this.config.isSkipPhysical = false
this.config.reasonSkipPhysical = ''
this.config.latestScenario = undefined
this.physicalTest = new PhysicalPortTest([])
this.config.isReady = false
@ -1110,7 +1116,9 @@ ${data.issues?.length ? `- ` + data.issues.join(`\n- `) : ''}
*****[Physical]*****
Total Ports: ${portPhysical?.length}
Ports Tested (Link UP): ${tested.length} (${testedPoE?.length} PoE, ${testedSFP?.length} SFP)
Ports Missing/Down: ${missing.length}\n\n`
Ports Missing/Down: ${missing.length}
${this.config.reasonSkipPhysical ? `***User skip test ports:\n- ${this.config.reasonSkipPhysical}` : ''}
\n`
await updateNoteToERP(sn, note)
}
@ -1173,6 +1181,8 @@ Ports Missing/Down: ${missing.length}\n\n`
})
if (listPorts.length === 0) {
this.config.listFeatureTested = [...new Set([...this.config.listFeatureTested, 'PHYSICAL'])]
this.config.isSkipPhysical = true
this.config.reasonSkipPhysical = ''
this.sendFeatureTested()
console.log('End physical test')
this.endTesting()
@ -1301,15 +1311,28 @@ Ports Missing/Down: ${missing.length}\n\n`
/**
* Send report after done physical test
*/
async sendReportPhysicalTest() {
async sendReportPhysicalTest(reason?: string) {
this.config.listFeatureTested = [...new Set([...this.config.listFeatureTested, 'PHYSICAL'])]
if (reason) {
this.config.isSkipPhysical = true
this.config.reasonSkipPhysical = reason
}
this.sendFeatureTested()
// Set timeout send report
this.setTimeoutSendSummaryReport(30000)
const formReport = this.physicalTest.getFormReport()
if (
this.config.listFeatureTested?.includes('PHYSICAL') &&
this.config.listFeatureTested?.includes('DPELP')
)
this.setTimeoutSendSummaryReport(30000)
const formReport = this.physicalTest.getFormReport(this.config.inventory)
const reasonSkipPhysical = reason
? `<b style="color: #ff0000;">User Skip Test Port</b><br/>
<br/>
${reason}`
: ''
await sendMessageToMail(
`[ATC] - [${this.config.stationName} - Line: ${this.config.lineNumber}] - Physical Ports Test`,
formReport
formReport + reasonSkipPhysical
)
}
@ -1762,6 +1785,8 @@ ${log}
stationId: this.config.stationId,
lineId: this.config.id,
listFeatureTested: this.config.listFeatureTested,
isSkipPhysical: this.config.isSkipPhysical,
reasonSkipPhysical: this.config.reasonSkipPhysical,
})
}
@ -1771,6 +1796,7 @@ ${log}
sendReportSummary = async (snapshot?: {
snapConfig: LineConfig
snapPhysical: PhysicalPortTest
reason: string
}) => {
if (this.debounceSendSummaryReport) clearTimeout(this.debounceSendSummaryReport)
const physicalTest = snapshot?.snapPhysical ? snapshot?.snapPhysical : this.physicalTest
@ -1797,6 +1823,13 @@ ${log}
showLicense?.textfsm && Array.isArray(showLicense?.textfsm) ? showLicense?.textfsm : null
const issue = config?.latestScenario?.detectAI?.issue || []
const summary = config?.latestScenario?.detectAI?.summary || ''
const reasonSkipPhysical =
snapshot?.reason || this.config.reasonSkipPhysical
? `<br/><b style="color: #ff0000;">User Skip Test Port</b><br/>
<br/>
${snapshot?.reason || this.config.reasonSkipPhysical}`
: ''
const body = `<table cellpadding="6" cellspacing="0" border="1" style="margin-top: 10px; border-collapse: collapse; width: 100%">
<tr>
<td style="width: 600px; text-align: center;">DPELP</td>
@ -1842,6 +1875,7 @@ ${log}
<div style="column-count: 6;">${missingSFP.map((p) => physicalTest.normalizePortName(p.name)).join('<br/>')}</div>`
: ''
}
${reasonSkipPhysical}
</td>
</tr>
</table>`
@ -1883,16 +1917,21 @@ ${log}
this.physicalTest = new PhysicalPortTest([])
}
setTimeoutSendSummaryReport(timeout: number) {
setTimeoutSendSummaryReport(timeout: number, reason?: string) {
// Debounce send summary report
if (this.debounceSendSummaryReport) clearTimeout(this.debounceSendSummaryReport)
// Snapshot toàn bộ data tại thời điểm này
const snapshot = {
snapConfig: this.config,
snapPhysical: this.physicalTest,
reason: reason || '',
}
this.debounceSendSummaryReport = setTimeout(() => {
this.config.listFeatureTested = ['DPELP', 'PHYSICAL']
if (!this.config.listFeatureTested?.includes('PHYSICAL')) {
this.config.isSkipPhysical = true
this.config.reasonSkipPhysical = ''
}
this.config.listFeatureTested = ['DPELP', 'PHYSICAL', 'SUMMARY']
this.sendFeatureTested()
this.sendReportSummary(snapshot)
}, timeout)
@ -1900,6 +1939,8 @@ ${log}
resetDPELP() {
this.config.listFeatureTested = []
this.config.isSkipPhysical = false
this.config.reasonSkipPhysical = ''
this.dataDPELP = ''
this.sendFeatureTested()
console.log('Reset DPELP data and features', this.config.id, this.config.listFeatureTested)

View File

@ -127,11 +127,11 @@ export class PhysicalPortTest {
console.log('✅ Physical Test DONE')
}
getFormReport() {
getFormReport(inventory?: any) {
const report: PhysicalTestReport = {
device: {
model: this?.inventory?.pid || '',
serial: this?.inventory?.sn || '',
model: this?.inventory?.pid || inventory?.pid || '',
serial: this?.inventory?.sn || inventory?.sn || '',
},
startTime: this.startTime,
endTime: new Date(),

View File

@ -611,6 +611,7 @@ export class WebSocketIo {
const stationId = data.stationId || ''
const scenarioName = data.scenarioName || ''
const skipTestPorts = data.skipTestPorts || false
const reasonSkipPhysical = data.reasonSkipPhysical || false
const station = await Station.find(stationId)
// Check station is active
const activeStation = await checkStationActive(stationId)
@ -625,6 +626,8 @@ export class WebSocketIo {
line.config.listFeatureTested = [
...new Set([...line.config.listFeatureTested, 'PHYSICAL']),
]
line.config.isSkipPhysical = true
line.config.reasonSkipPhysical = reasonSkipPhysical
} else if (line.config.status === 'connected') {
console.log('Reset list feature tested for line', lineId)
line.resetDPELP()
@ -653,21 +656,21 @@ export class WebSocketIo {
console.error('Error sending wiki message:', error)
}
try {
// await sendMessageToMail(
// `[${scenarioName || 'DPELP'}] - ${stationName} - ${dataFormat}`,
// tableHTML
// )
await sendMessageToMail(
`[${scenarioName || 'DPELP'}] - ${stationName} - ${dataFormat}`,
tableHTML
)
} catch (error) {
console.error('Error sending mail:', error)
}
try {
await sendMessageToZulip(
'stream',
'ATC_Report',
station.name,
`\n\n---\n**[${scenarioName || 'DPELP'}] - ${stationName} - ${dataFormat}**\n\n` +
zulipMess
)
// await sendMessageToZulip(
// 'stream',
// 'ATC_Report',
// station.name,
// `\n\n---\n**[${scenarioName || 'DPELP'}] - ${stationName} - ${dataFormat}**\n\n` +
// zulipMess
// )
} catch (error) {
console.error('Error sending zulip message:', error)
}
@ -707,7 +710,7 @@ export class WebSocketIo {
})
socket.on('end_run_physical_test', async (data) => {
const { stationId, lineId } = data
const { stationId, lineId, reasonSkipPhysical } = data
// Check station is active
const activeStation = await checkStationActive(stationId)
if (!activeStation) return
@ -717,7 +720,7 @@ export class WebSocketIo {
stationId,
[lineId],
async (lineCon) => {
await lineCon.sendReportPhysicalTest()
await lineCon.sendReportPhysicalTest(reasonSkipPhysical)
lineCon.endTesting()
},
{}
@ -887,7 +890,8 @@ export class WebSocketIo {
output = '',
inventory: string = '',
latestScenario?: any,
data?: any
data?: any,
reasonSkipPhysical?: string
) {
try {
for (const line of lines) {
@ -916,6 +920,8 @@ export class WebSocketIo {
latestScenario: latestScenario,
listFeatureTested: [],
isReady: false,
reasonSkipPhysical: reasonSkipPhysical,
isSkipPhysical: reasonSkipPhysical ? true : false,
},
socket,
async () => {
@ -1001,7 +1007,8 @@ export class WebSocketIo {
line?.config?.output || '',
line?.config?.inventory || '',
line?.config?.latestScenario || undefined,
line?.config?.data || []
line?.config?.data || [],
line?.config?.reasonSkipPhysical || ''
)
this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId)

View File

@ -55,6 +55,7 @@ import PageLogin from "./components/Authentication/LoginPage";
import DraggableTabs from "./components/DragTabs";
import { isJsonString } from "./untils/helper";
import BottomToolBar from "./components/BottomToolBar";
import ModalConfirmSkipTestPort from "./components/Modal/ModalConfirmSkipTestPort";
// import ModalConfirmRunScenario from "./components/Modal/ModalConfirmRunScenario";
const apiUrl = import.meta.env.VITE_BACKEND_URL;
@ -109,6 +110,7 @@ function App() {
const [listIos, setListIos] = useState<FileInfo[]>([]);
const [listLicense, setListLicense] = useState<FileInfo[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [linesConfirmSkipPort, setLinesConfirmSkipPort] = useState<TLine[]>([]);
const connectApcSwitch = (station: TStation) => {
if (!station?.is_active) return;
@ -468,12 +470,21 @@ function App() {
});
socket?.on("feature_tested", (data) => {
if (data?.listFeatureTested)
if (data?.listFeatureTested) {
updateValueLineStation(
data?.lineId,
{ listFeatureTested: data?.listFeatureTested },
{
listFeatureTested: data?.listFeatureTested,
isSkipPhysical: data?.isSkipPhysical,
reasonSkipPhysical: data?.reasonSkipPhysical,
},
data?.stationId
);
if (data?.isSkipPhysical && !data?.reasonSkipPhysical) {
const valueLine = findLineByLineId(data?.lineId, data?.stationId);
if (valueLine) setLinesConfirmSkipPort((pre) => [...pre, valueLine]);
}
}
});
// ✅ cleanup on unmount or when socket changes
@ -649,6 +660,13 @@ function App() {
}
}, [expandedBottomBar]);
const findLineByLineId = (lineId: number, stationId?: number) => {
const valueStation = stations.find((el) => el.id === stationId);
if (!valueStation || !stationId) return null;
const valueLine = valueStation?.lines?.find((el) => el.id === lineId);
return valueLine;
};
return (
<Container w={"100%"} style={{ maxWidth: "100%" }}>
<DraggableTabs
@ -958,6 +976,8 @@ function App() {
setScenarios={setScenarios}
listBrands={listBrands}
listCategories={listCategories}
setLinesConfirmSkipPort={setLinesConfirmSkipPort}
linesConfirmSkipPort={linesConfirmSkipPort}
/>
{/* <ModalConfirmRunScenario
@ -965,6 +985,13 @@ function App() {
station={stations.find((el) => el.id === Number(activeTab))}
scenarios={scenarios}
/> */}
<ModalConfirmSkipTestPort
listLines={linesConfirmSkipPort}
setListLines={setLinesConfirmSkipPort}
socket={socket}
station={stations.find((el) => el.id === Number(activeTab))}
/>
</Container>
);
}

View File

@ -5,7 +5,6 @@ import {
CloseButton,
Flex,
Grid,
Menu,
ScrollArea,
Tabs,
Text,
@ -26,11 +25,7 @@ import { DrawerAPCControl, DrawerSwitchControl } from "./Drawer/DrawerControl";
import DrawerScenario from "./Modal/ModalScenario";
import { isJsonString } from "../untils/helper";
import { motion } from "motion/react";
import {
IconCaretDown,
IconCaretRight,
IconCaretUp,
} from "@tabler/icons-react";
import { IconCaretDown, IconCaretUp } from "@tabler/icons-react";
import InputHistory from "./InputHistory";
import ModalRunScenario from "./Modal/ModalRunScenario";
@ -365,94 +360,27 @@ const BottomToolBar = ({
gap={"xs"}
wrap={"wrap"}
>
<Menu
trigger="hover"
withArrow
shadow="md"
position="top"
>
<Menu.Target>
<Button
fw={400}
mr={"5px"}
disabled={
isDisable || selectedLines.length === 0
}
variant="outline"
color="green"
style={{ height: "30px", width: "100px" }}
onClick={() => {}}
>
DPELP <IconCaretRight size={"14px"} />
</Button>
</Menu.Target>
<Menu.Dropdown>
<Flex direction={"column"} gap={"8px"}>
<ButtonDPELP
socket={socket}
selectedLines={selectedLines}
isDisable={
isDisable || selectedLines.length === 0
}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
onClick={() => {
if (
selectedLines.length > 0
// &&
// selectedLines.length === station?.lines?.length
) {
socket?.emit("run_all_dpelp", {
lineIds: selectedLines.map(
(line) => line.id
),
stationName: station.name,
stationId: station.id,
});
}
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
text="Run Test Ports after DPELP"
/>
<ButtonDPELP
socket={socket}
selectedLines={selectedLines}
isDisable={
isDisable || selectedLines.length === 0
}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
onClick={() => {
if (
selectedLines.length > 0
// &&
// selectedLines.length === station?.lines?.length
) {
socket?.emit("run_all_dpelp", {
lineIds: selectedLines.map(
(line) => line.id
),
stationName: station.name,
stationId: station.id,
skipTestPorts: true,
});
}
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
text="Skip Test Ports"
color="yellow"
/>
</Flex>
</Menu.Dropdown>
</Menu>
<ButtonDPELP
socket={socket}
selectedLines={selectedLines}
isDisable={isDisable || selectedLines.length === 0}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
onClick={() => {
if (selectedLines.length > 0) {
socket?.emit("run_all_dpelp", {
lineIds: selectedLines.map((line) => line.id),
stationName: station.name,
stationId: station.id,
});
}
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
/>
<Button
fw={400}
disabled={isDisable || selectedLines.length === 0}

View File

@ -1,4 +1,13 @@
import { Card, Text, Box, Flex, Menu, Button, Input } from "@mantine/core";
import {
Card,
Text,
Box,
Flex,
Menu,
Button,
Input,
Tooltip,
} from "@mantine/core";
import type { IScenario, TLine, TStation } from "../untils/types";
import classes from "./Component.module.css";
import TerminalCLI from "./TerminalXTerm";
@ -399,19 +408,48 @@ const CardLine = ({
""
)}
{line?.listFeatureTested?.includes("PHYSICAL") ? (
<Text
style={{
border: "1px solid #ccc",
borderRadius: "16px",
paddingLeft: "4px",
paddingRight: "4px",
backgroundColor: "#69da53",
}}
fz={"9px"}
c={"dark"}
>
Physical
</Text>
line?.isSkipPhysical ? (
<Tooltip
label={
line?.reasonSkipPhysical ||
"User skip physical test"
}
>
<motion.div
style={{
border: "1px solid #ccc",
borderRadius: "16px",
paddingLeft: "4px",
paddingRight: "4px",
fontSize: "9px",
backgroundColor: "red",
color: "white",
}}
animate={{ opacity: [0.2, 1, 0.2] }}
transition={{
duration: 1.2,
repeat: Infinity,
ease: "easeInOut",
}}
>
Physical
</motion.div>
</Tooltip>
) : (
<Text
style={{
border: "1px solid #ccc",
borderRadius: "16px",
paddingLeft: "4px",
paddingRight: "4px",
backgroundColor: "#69da53",
}}
fz={"9px"}
c={"dark"}
>
Physical
</Text>
)
) : (
""
)}

View File

@ -0,0 +1,161 @@
import { useEffect, useState } from "react";
import {
Modal,
Box,
Text,
Flex,
TextInput,
Button,
ScrollArea,
} from "@mantine/core";
import type { TLine, TStation } from "../../untils/types";
import type { Socket } from "socket.io-client";
interface Props {
listLines: TLine[];
setListLines: (lines: React.SetStateAction<TLine[]>) => void;
socket: Socket | null;
station: TStation | undefined;
}
interface PropsLines {
id: number | undefined;
note: string;
pid?: string;
sn?: string;
vid?: string;
lineNumber?: number;
isError?: boolean;
}
export default function ModalConfirmSkipTestPort({
listLines,
setListLines,
socket,
station,
}: Props) {
const [dataLines, setDataLines] = useState<PropsLines[]>([]);
const [isDisabled, setIsDisabled] = useState<boolean>(false);
useEffect(() => {
if (listLines) {
setDataLines((prev) =>
listLines
.filter((line) => line.id)
.map((line) => ({
id: line.id,
lineNumber: line?.lineNumber,
pid: line?.inventory?.pid,
sn: line?.inventory?.sn,
vid: line?.inventory?.vid,
note: prev?.find((el) => el.id === line.id)
? prev?.find((el) => el.id === line.id)?.note || ""
: "",
}))
);
}
}, [listLines]);
return (
<Modal
size={"xl"}
style={{ position: "absolute", left: 0 }}
opened={dataLines.length > 0}
onClose={() => {}}
closeOnClickOutside={false}
closeOnEscape={false}
withCloseButton={false}
title="Confirm Skip Test Ports"
>
<Box>
<ScrollArea h={"66vh"}>
{dataLines.map((line, i) => (
<Box
key={i}
style={{ borderBottom: "1px #ccc solid" }}
pb="sm"
mb="sm"
>
<Flex
p={"xs"}
style={{
backgroundColor: "#e9ecef",
fontWeight: 600,
}}
gap={"lg"}
>
<Text size="sm" fw={600}>
Line: {line.lineNumber}
</Text>
<Text size="sm" fw={600}>
PID: {line.pid || ""}
</Text>
<Text size="sm" fw={600}>
SN: {line.sn || ""}
</Text>
<Text size="sm" fw={600}>
VID: {line.vid || ""}
</Text>
</Flex>
<Box>
<TextInput
required
placeholder="Enter the reason for skip test ports"
mt="4px"
mb="4px"
value={line.note}
onChange={(e) =>
setDataLines(
dataLines.map((el) =>
el.id === line.id
? {
...el,
note: e.target.value,
isError: false,
}
: el
)
)
}
error={
line.isError
? "Please enter the reason for skip test ports"
: ""
}
/>
</Box>
<Flex justify={"end"}>
<Button
disabled={isDisabled}
color={"green"}
size="xs"
onClick={() => {
if (!line.note)
setDataLines(
dataLines.map((el) => ({ ...el, isError: true }))
);
else {
socket?.emit("end_run_physical_test", {
lineId: line?.id,
stationId: Number(station?.id),
reasonSkipPhysical: line?.note,
});
setDataLines(dataLines.filter((el) => el.id !== line.id));
setListLines(listLines.filter((el) => el.id !== line.id));
}
setIsDisabled(true);
setTimeout(() => {
setIsDisabled(false);
}, 1000);
}}
>
Save
</Button>
</Flex>
</Box>
))}
</ScrollArea>
</Box>
</Modal>
);
}

View File

@ -81,6 +81,8 @@ const ModalTerminal = ({
listBrands,
listCategories,
setScenarios,
setLinesConfirmSkipPort,
linesConfirmSkipPort,
}: {
opened: boolean;
onClose: () => void;
@ -96,6 +98,8 @@ const ModalTerminal = ({
listBrands: TBrands[];
listCategories: TCategories[];
setScenarios: (value: React.SetStateAction<IScenario[]>) => void;
setLinesConfirmSkipPort: (value: React.SetStateAction<TLine[]>) => void;
linesConfirmSkipPort: TLine[];
}) => {
const user = useMemo(() => {
return localStorage.getItem("user") &&
@ -134,6 +138,12 @@ const ModalTerminal = ({
line?.listFeatureTested?.includes("DPELP")
)
setActiveStep(2);
if (
line?.listFeatureTested?.includes("PHYSICAL") &&
line?.listFeatureTested?.includes("DPELP") &&
line?.listFeatureTested?.includes("SUMMARY")
)
setActiveStep(3);
} else setActiveStep(0);
}, [opened, line?.listFeatureTested]);
@ -537,6 +547,7 @@ const ModalTerminal = ({
return;
}
if (openSelectIos) return;
if (linesConfirmSkipPort.length) return;
onClose();
if (
line?.userOpenCLI === user?.userName &&
@ -685,7 +696,31 @@ const ModalTerminal = ({
></Stepper.Step>
<Stepper.Step
disabled={isDisable}
label="Physical Test"
label={
line?.isSkipPhysical ? (
<Tooltip
label={
line?.reasonSkipPhysical || "User skip physical test"
}
>
<motion.div
style={{
color: "red",
}}
animate={{ opacity: [0.2, 1, 0.2] }}
transition={{
duration: 1.2,
repeat: Infinity,
ease: "easeInOut",
}}
>
Physical Test
</motion.div>
</Tooltip>
) : (
"Physical Test"
)
}
description="Test physical ports"
></Stepper.Step>
<Stepper.Step
@ -1209,16 +1244,17 @@ const ModalTerminal = ({
<SimpleGrid cols={5} spacing={"xs"}>
{isPhysicalTest && line?.ports
? line.ports.map((port, i) => (
<Text
fz={"15px"}
key={i}
c={
line?.listPortsPhysical?.includes(port)
? "#014a1a"
: "#dedede"
}
>
{normalizePortName(port)}
<Box key={i}>
<Text
fz={"15px"}
c={
line?.listPortsPhysical?.includes(port)
? "#014a1a"
: "#dedede"
}
>
{normalizePortName(port)}
</Text>
{port?.includes("SFP") ? (
<Text
mt={-4}
@ -1235,7 +1271,7 @@ const ModalTerminal = ({
) : (
""
)}
</Text>
</Box>
))
: null}
</SimpleGrid>
@ -1265,31 +1301,58 @@ const ModalTerminal = ({
Reset
</Button>
{isPhysicalTest ? (
<Button
fw={400}
disabled={isDisable}
variant="filled"
color="green"
size="xs"
fz={"xs"}
mt={"8px"}
onClick={() => {
socket?.emit("end_run_physical_test", {
lineId: line?.id,
stationId: Number(stationItem?.id),
});
// setListPortsPhysical([]);
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
>
Done/End
</Button>
<Flex gap={"sm"}>
<Button
fw={400}
disabled={isDisable}
variant="outline"
color="red"
size="xs"
fz={"xs"}
mt={"8px"}
onClick={() => {
if (line)
setLinesConfirmSkipPort((pre) => [...pre, line]);
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
>
Skip test ports
</Button>
<Button
fw={400}
disabled={isDisable}
variant="filled"
color="green"
size="xs"
fz={"xs"}
mt={"8px"}
onClick={() => {
socket?.emit("end_run_physical_test", {
lineId: line?.id,
stationId: Number(stationItem?.id),
});
// setListPortsPhysical([]);
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 5000);
}}
>
Done/End
</Button>
</Flex>
) : (
<Button
disabled={isDisable}
disabled={
isDisable ||
(line?.runningScenario &&
line?.runningScenario?.length > 0
? true
: false)
}
fw={400}
variant="filled"
// color="green"
@ -1395,67 +1458,30 @@ const ModalTerminal = ({
</Flex>
</Menu.Dropdown>
</Menu>
<Menu trigger="hover" withArrow shadow="md" position="top">
<Menu.Target>
<Button
fw={400}
mr={"5px"}
disabled={isDisable}
variant="outline"
color="green"
style={{ height: "30px", width: "100px" }}
onClick={() => {}}
>
DPELP <IconCaretRight size={"14px"} />
</Button>
</Menu.Target>
<Menu.Dropdown>
<Flex direction={"column"} gap={"8px"}>
<ButtonDPELP
socket={socket}
selectedLines={line ? [line] : []}
isDisable={isDisable}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
onClick={() => {
socket?.emit("run_all_dpelp", {
lineIds: [line?.id],
stationName: stationItem?.name,
stationId: Number(stationItem?.id),
});
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 10000);
}}
text="Run Test Ports after DPELP"
/>
<ButtonDPELP
socket={socket}
selectedLines={line ? [line] : []}
isDisable={isDisable}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
onClick={() => {
socket?.emit("run_all_dpelp", {
lineIds: [line?.id],
stationName: stationItem?.name,
stationId: Number(stationItem?.id),
skipTestPorts: true,
});
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 10000);
}}
text="Skip Test Ports"
color="yellow"
/>
</Flex>
</Menu.Dropdown>
</Menu>
<ButtonDPELP
socket={socket}
selectedLines={line ? [line] : []}
isDisable={
isDisable ||
(line?.runningScenario && line?.runningScenario?.length > 0
? true
: false)
}
onClick={() => {
socket?.emit("run_all_dpelp", {
lineIds: [line?.id],
stationName: stationItem?.name,
stationId: Number(stationItem?.id),
});
setIsDisable(true);
setTimeout(() => {
setIsDisable(false);
}, 10000);
}}
dataDPELP={scenarios?.find(
(el) => el.title.toUpperCase() === "DPELP"
)}
/>
<Button
fw={400}
disabled={isDisable}

View File

@ -109,6 +109,8 @@ export type TLine = {
listPortsPhysical?: string[];
listFeatureTested?: string[];
isReady?: boolean;
isSkipPhysical?: boolean;
reasonSkipPhysical?: string;
};
export type TUser = {