Update send Wiki

This commit is contained in:
nguyentrungthat 2025-12-04 15:54:18 +07:00
parent 17e5aad8d9
commit 2ad1ee195f
8 changed files with 155 additions and 62 deletions

View File

@ -79,4 +79,7 @@ export default class Station extends BaseModel {
@column.dateTime({ autoCreate: true, autoUpdate: true }) @column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime declare updatedAt: DateTime
@column()
declare sendWiki: boolean
} }

View File

@ -164,7 +164,13 @@ export function mapToLineFormat(input: InputData) {
// MAC // MAC
let mac = '' let mac = ''
let ios = '' let ios = ''
const showVersion = input.data?.find((d) => d.command === 'show version') const showVersion = input.data?.find(
(d) =>
d.command === 'show version' ||
d.command === 'sh version' ||
d.command === 'show ver' ||
d.command === 'sh ver'
)
if (showVersion?.textfsm?.[0]?.MAC_ADDRESS) { if (showVersion?.textfsm?.[0]?.MAC_ADDRESS) {
mac = showVersion.textfsm[0].MAC_ADDRESS mac = showVersion.textfsm[0].MAC_ADDRESS
} }

View File

@ -0,0 +1,17 @@
import { BaseSchema } from '@adonisjs/lucid/schema'
export default class extends BaseSchema {
protected tableName = 'stations'
async up() {
this.schema.alterTable(this.tableName, (table) => {
table.boolean('send_wiki').defaultTo(true)
})
}
async down() {
this.schema.alterTable(this.tableName, (table) => {
table.dropColumn('send_wiki')
})
}
}

View File

@ -545,6 +545,11 @@ export class WebSocketIo {
socket.on('run_all_dpelp', async (data) => { socket.on('run_all_dpelp', async (data) => {
try { try {
const lineIds = data.lineIds const lineIds = data.lineIds
const stationName = data.stationName || ''
const stationId = data.stationId || ''
const station = await Station.find(stationId)
// Check station sendWiki flag
if (!station || !station?.sendWiki) return
console.log('[DPELP] Received run all dpelp') console.log('[DPELP] Received run all dpelp')
const results = await this.waitUntilAllReady(lineIds) const results = await this.waitUntilAllReady(lineIds)
@ -557,13 +562,13 @@ export class WebSocketIo {
process.env.LINK_WIKI || 'https://logs.danielvu.com/api/wiki/page/insert?title=Dev_test' process.env.LINK_WIKI || 'https://logs.danielvu.com/api/wiki/page/insert?title=Dev_test'
await axios.post(linkWiki, { await axios.post(linkWiki, {
data: tableHTML, data: tableHTML,
titleAuto: '[DPELP] Report AUTO - ' + dataFormat, titleAuto: `[DPELP] Report AUTO - ${stationName} - ` + dataFormat,
}) })
await sendMessageToMail( await sendMessageToMail(
'andrew.ng@apactech.io', 'andrew.ng@apactech.io',
`[DPELP] Report AUTO - ${dataFormat}`, `[DPELP] Report AUTO - ${stationName} - ${dataFormat}`,
tableHTML, tableHTML,
['ips@ipsupply.com.au', 'kay@ipsupply.com.au'] ['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
) )
} catch (error) { } catch (error) {
console.log(error) console.log(error)

View File

@ -781,6 +781,8 @@ const BottomToolBar = ({
) { ) {
socket?.emit("run_all_dpelp", { socket?.emit("run_all_dpelp", {
lineIds: selectedLines.map((line) => line.id), lineIds: selectedLines.map((line) => line.id),
stationName: station.name,
stationId: station.id,
}); });
} }
setIsDisable(true); setIsDisable(true);

View File

@ -2,6 +2,7 @@ import {
ActionIcon, ActionIcon,
Box, Box,
Button, Button,
Checkbox,
Flex, Flex,
Group, Group,
Input, Input,
@ -80,6 +81,7 @@ const StationSetting = ({
form.setFieldValue("apc_2_username", dataStation.apc_2_username); form.setFieldValue("apc_2_username", dataStation.apc_2_username);
form.setFieldValue("apc_2_password", dataStation.apc_2_password); form.setFieldValue("apc_2_password", dataStation.apc_2_password);
form.setFieldValue("switch_control_ip", dataStation.switch_control_ip); form.setFieldValue("switch_control_ip", dataStation.switch_control_ip);
form.setFieldValue("send_wiki", dataStation?.send_wiki);
form.setFieldValue( form.setFieldValue(
"switch_control_port", "switch_control_port",
dataStation.switch_control_port dataStation.switch_control_port
@ -391,6 +393,14 @@ const StationSetting = ({
Delete Delete
</Button> </Button>
)} )}
<Checkbox
ml={"12px"}
label="Send Wiki/email when run all DPELP"
checked={form.values.send_wiki}
onChange={(event) =>
form.setFieldValue("send_wiki", event.currentTarget.checked)
}
/>
</div> </div>
} }
size={"90%"} size={"90%"}

View File

@ -9,12 +9,15 @@ import {
Modal, Modal,
ScrollArea, ScrollArea,
Text, Text,
Textarea,
Tooltip, Tooltip,
} from "@mantine/core"; } from "@mantine/core";
import type { import type {
IScenario, IScenario,
SwitchPortsProps, SwitchPortsProps,
TDataTicket, TDataTicket,
TextFSM,
TextTSMLicense,
THistoryTicket, THistoryTicket,
TLine, TLine,
TStation, TStation,
@ -75,6 +78,8 @@ const ModalTerminal = ({
const [latestTicket, setLatestTicket] = useState<TDataTicket>(INIT_TICKET); const [latestTicket, setLatestTicket] = useState<TDataTicket>(INIT_TICKET);
const [dataTicket, setDataTicket] = useState<TDataTicket>(INIT_TICKET); const [dataTicket, setDataTicket] = useState<TDataTicket>(INIT_TICKET);
const [valueBaud, setValueBaud] = useState<string>(""); const [valueBaud, setValueBaud] = useState<string>("");
const [valueIssue, setValueIssue] = useState<string>("");
const [dataTextfsm, setDataTextfsm] = useState<TextFSM[]>([]);
useEffect(() => { useEffect(() => {
if (opened && line?.tickets && line?.tickets?.length > 0) { if (opened && line?.tickets && line?.tickets?.length > 0) {
@ -88,6 +93,28 @@ const ModalTerminal = ({
} }
}, [opened, line?.tickets]); }, [opened, line?.tickets]);
useEffect(() => {
if (opened && line?.latestScenario?.detectAI) {
const data =
line?.latestScenario?.detectAI?.issue &&
Array.isArray(line?.latestScenario?.detectAI?.issue)
? "- " + line?.latestScenario?.detectAI?.issue?.join("\n- ")
: "";
setValueIssue(data);
} else {
setValueIssue("");
}
}, [opened, line?.latestScenario?.detectAI]);
useEffect(() => {
if (opened && line?.data) {
const data = Array.isArray(line?.data) ? line?.data : [];
setDataTextfsm(data);
} else {
setDataTextfsm([]);
}
}, [opened, line?.data]);
useEffect(() => { useEffect(() => {
setListPorts([]); setListPorts([]);
}, [stationItem?.id]); }, [stationItem?.id]);
@ -383,6 +410,32 @@ const ModalTerminal = ({
return `${type?.slice(0, 2)}${last}`; return `${type?.slice(0, 2)}${last}`;
}; };
const findDataShowVersion = () => {
const showVersion = dataTextfsm?.find(
(d) =>
d.command?.trim() === "show version" ||
d.command?.trim() === "sh version" ||
d.command?.trim() === "show ver" ||
d.command?.trim() === "sh ver"
);
return showVersion?.textfsm && showVersion?.textfsm?.[0]
? showVersion?.textfsm?.[0]
: null;
};
const findDataShowLicense = () => {
const showLicense = dataTextfsm?.find(
(d) =>
d.command?.trim() === "show license" ||
d.command?.trim() === "sh license" ||
d.command?.trim() === "show lic" ||
d.command?.trim() === "sh lic"
);
return showLicense?.textfsm && Array.isArray(showLicense?.textfsm)
? showLicense?.textfsm
: null;
};
return ( return (
<Box> <Box>
<Modal <Modal
@ -542,7 +595,11 @@ const ModalTerminal = ({
<CopyIcon <CopyIcon
value={ value={
line?.inventory?.pid && line?.inventory?.sn line?.inventory?.pid && line?.inventory?.sn
? `Line ${line?.lineNumber || line?.line_number || ""}: ${line.inventory?.pid}${line.inventory?.vid ? ` ${line.inventory.vid}` : ""} - ${line.inventory?.sn}` ? `Line ${
line?.lineNumber || line?.line_number || ""
}: ${line.inventory?.pid}${
line.inventory?.vid ? ` ${line.inventory.vid}` : ""
} - ${line.inventory?.sn}`
: "" : ""
} }
label="Copy PID + SN" label="Copy PID + SN"
@ -555,14 +612,32 @@ const ModalTerminal = ({
<Text size="md" mr={"6px"} fw={"bold"}> <Text size="md" mr={"6px"} fw={"bold"}>
IOS: IOS:
</Text> </Text>
<Text size="md">{""}</Text> <Text size="md">
{findDataShowVersion()
? findDataShowVersion()?.SOFTWARE_IMAGE
? findDataShowVersion()?.SOFTWARE_IMAGE +
" " +
(findDataShowVersion()?.VERSION || "")
: ""
: ""}
</Text>
</Flex> </Flex>
</Box> </Box>
<Flex> <Flex>
<Text size="md" mr={"sm"} fw={"bold"}> <Text size="md" mr={"sm"} fw={"bold"}>
License: License:
</Text> </Text>
<Text size="md">{""}</Text> <Text size="md">
{findDataShowLicense()
? findDataShowLicense()
?.filter(
(el: TextTSMLicense) =>
el.LICENSE_TYPE === "Permanent"
)
?.map((v: TextTSMLicense) => v.FEATURE)
?.join(", ")
: ""}
</Text>
</Flex> </Flex>
<Flex> <Flex>
<Text size="md" mr={"sm"} fw={"bold"}> <Text size="md" mr={"sm"} fw={"bold"}>
@ -574,56 +649,30 @@ const ModalTerminal = ({
<Text size="md" mr={"sm"} fw={"bold"}> <Text size="md" mr={"sm"} fw={"bold"}>
Mem/Flash: Mem/Flash:
</Text> </Text>
<Text size="md">{""}</Text> <Text size="md">
{findDataShowVersion()
? findDataShowVersion()?.MEMORY +
(findDataShowVersion()?.USB_FLASH
? "/" + findDataShowVersion()?.USB_FLASH
: "")
: ""}
</Text>
</Flex> </Flex>
<Box> <Box>
<Text size="md" mr={"sm"} fw={"bold"}> <Text size="md" mr={"sm"} fw={"bold"}>
Warning from test report: AI Warning from test report: AI
</Text> </Text>
<ScrollArea <Box>
h={"150px"} <Textarea
style={{ rows={5}
border: "1px solid #ccc", size="sm"
borderRadius: "8px", placeholder="Report from AI"
padding: "4px", value={valueIssue}
}} onChange={(event) =>
> setValueIssue(event.currentTarget.value)
{line?.latestScenario?.detectAI ? ( }
<Box> />
{/* <Box> </Box>
<Text size="sm" fw={"bold"}>
Status:
</Text>
{line?.latestScenario?.detectAI?.status?.map(
(el, i) => (
<Box key={i}>
<Text size="sm">- {el}</Text>
</Box>
)
)}
</Box> */}
{line?.latestScenario?.detectAI?.issue &&
Array.isArray(line?.latestScenario?.detectAI?.issue) ? (
<Box>
<Text size="sm" fw={"bold"}>
Issue:
</Text>
{line?.latestScenario?.detectAI?.issue?.map(
(el, i) => (
<Box key={i}>
<Text size="sm">- {el}</Text>
</Box>
)
)}
</Box>
) : (
""
)}
</Box>
) : (
""
)}
</ScrollArea>
</Box> </Box>
<Box <Box
style={{ style={{

View File

@ -55,6 +55,7 @@ export type TStation = {
switch_control_password?: string; // Optional switch_control_password?: string; // Optional
switches?: SwitchesProps[]; switches?: SwitchesProps[];
switch?: SwitchesProps; switch?: SwitchesProps;
send_wiki?: boolean;
}; };
export type TLine = { export type TLine = {
@ -228,13 +229,13 @@ export type THistoryTicket = {
userId: number; userId: number;
}; };
interface HistoryItem { export type TextTSMLicense = {
pid: string; INDEX: string;
vid: string; FEATURE: string;
sn: string; PERIOD_LEFT: string;
scenario: string; PERIOD_USED: string;
id: number; LICENSE_TYPE: string;
number: number; LICENSE_STATE: string;
stationId: number; LICENSE_COUNT: string;
timestamp?: number; LICENSE_PRIORITY: string;
} };