Enhance user tracking and UI adjustments across app
Backend now logs user information during command/script execution and adds retry logic for command sending. Frontend adjusts button/menu sizes, input widths, and scenario button font sizes for better UI consistency. ModalLog now highlights user log entries, and minor style tweaks are applied throughout.
This commit is contained in:
parent
abfae279da
commit
c2d68c685c
|
|
@ -25,7 +25,7 @@ interface LineConfig {
|
|||
openCLI: boolean
|
||||
userEmailOpenCLI: string
|
||||
userOpenCLI: string
|
||||
inventory?: string
|
||||
inventory: string
|
||||
latestScenario?: {
|
||||
name: string
|
||||
time: number
|
||||
|
|
@ -54,6 +54,7 @@ export default class LineConnection {
|
|||
private outputInventory: string
|
||||
private outputScenario: string
|
||||
private bufferCommand: string
|
||||
private retryConnect: number
|
||||
|
||||
constructor(config: LineConfig, socketIO: any) {
|
||||
this.config = config
|
||||
|
|
@ -66,6 +67,7 @@ export default class LineConnection {
|
|||
this.outputInventory = ''
|
||||
this.outputScenario = ''
|
||||
this.bufferCommand = ''
|
||||
this.retryConnect = 0
|
||||
}
|
||||
|
||||
connect(timeoutMs = 5000) {
|
||||
|
|
@ -187,27 +189,39 @@ export default class LineConnection {
|
|||
})
|
||||
}
|
||||
|
||||
writeCommand(cmd: string | Buffer<ArrayBuffer>, isWrite = false) {
|
||||
async writeCommand(cmd: string | Buffer<ArrayBuffer>, userName = '') {
|
||||
if (this.client.destroyed) {
|
||||
console.log(`⚠️ Cannot send, line ${this.config.lineNumber} is closed`)
|
||||
if (this.retryConnect <= 3) {
|
||||
await sleep(2000)
|
||||
console.log('Retry connect times', this.retryConnect)
|
||||
this.retryConnect += 1
|
||||
await this.connect()
|
||||
await this.writeCommand(cmd)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.client.write(`${cmd}`)
|
||||
if (isWrite) {
|
||||
const command = cmd.toString()
|
||||
for (const char of command) {
|
||||
if (char === '\x7F') this.bufferCommand = this.bufferCommand.slice(0, -1)
|
||||
else if (char === '\r' && cleanData(this.bufferCommand).length > 0) {
|
||||
this.config.commands = [
|
||||
cleanData(this.bufferCommand.replace('\r', '')),
|
||||
...this.config.commands.filter(
|
||||
(el) => el !== cleanData(this.bufferCommand.replace('\r', ''))
|
||||
),
|
||||
].slice(0, 10)
|
||||
this.bufferCommand = ''
|
||||
} else this.bufferCommand += char
|
||||
}
|
||||
if (userName) {
|
||||
// appendLog(
|
||||
// `\n---${userName}---\n`,
|
||||
// this.config.stationId,
|
||||
// this.config.lineNumber,
|
||||
// this.config.port
|
||||
// )
|
||||
// for (const char of command) {
|
||||
// if (char === '\x7F') this.bufferCommand = this.bufferCommand.slice(0, -1)
|
||||
// else if (char === '\r' && cleanData(this.bufferCommand).length > 0) {
|
||||
// this.config.commands = [
|
||||
// cleanData(this.bufferCommand.replace('\r', '')),
|
||||
// ...this.config.commands.filter(
|
||||
// (el) => el !== cleanData(this.bufferCommand.replace('\r', ''))
|
||||
// ),
|
||||
// ].slice(0, 10)
|
||||
// this.bufferCommand = ''
|
||||
// } else this.bufferCommand += char
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +239,7 @@ export default class LineConnection {
|
|||
}
|
||||
}
|
||||
|
||||
async runScript(script: Scenario) {
|
||||
async runScript(script: Scenario, userName: string) {
|
||||
if (!this.client || this.client.destroyed) {
|
||||
console.log('Not connected')
|
||||
this.isRunningScript = false
|
||||
|
|
@ -239,9 +253,9 @@ export default class LineConnection {
|
|||
|
||||
this.isRunningScript = true
|
||||
const now = Date.now()
|
||||
this.outputScenario += `\n\n---start-scenarios---${now}---\n---scenario---${script?.title}---${now}---\n`
|
||||
this.outputScenario += `\n\n---start-scenarios---${now}---${userName}---\n---scenario---${script?.title}---${now}---\n`
|
||||
appendLog(
|
||||
`\n\n---start-scenarios---${now}---\n---scenario---${script?.title}---${now}---\n`,
|
||||
`\n\n---start-scenarios---${now}---${userName}---\n---scenario---${script?.title}---${now}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.lineNumber,
|
||||
this.config.port
|
||||
|
|
@ -264,9 +278,9 @@ export default class LineConnection {
|
|||
lineId: this.config.id,
|
||||
data: 'Timeout run scenario',
|
||||
})
|
||||
this.outputScenario += `\n---end-scenarios---${now}---\n`
|
||||
this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
|
||||
appendLog(
|
||||
`\n---end-scenarios---${now}---\n`,
|
||||
`\n---end-scenarios---${now}---${userName}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.lineNumber,
|
||||
this.config.port
|
||||
|
|
@ -285,9 +299,9 @@ export default class LineConnection {
|
|||
} else clearTimeout(timeoutTimer)
|
||||
this.isRunningScript = false
|
||||
this.outputBuffer = ''
|
||||
this.outputScenario += `\n---end-scenarios---${now}---\n`
|
||||
this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
|
||||
appendLog(
|
||||
`\n---end-scenarios---${now}---\n`,
|
||||
`\n---end-scenarios---${now}---${userName}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.lineNumber,
|
||||
this.config.port
|
||||
|
|
@ -379,6 +393,12 @@ export default class LineConnection {
|
|||
userEmailOpenCLI: user.userEmail,
|
||||
userOpenCLI: user.userName,
|
||||
})
|
||||
appendLog(
|
||||
`\n-------${user.userName}-------\n`,
|
||||
this.config.stationId,
|
||||
this.config.lineNumber,
|
||||
this.config.port
|
||||
)
|
||||
}
|
||||
|
||||
userCloseCLI() {
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export class WebSocketIo {
|
|||
stationId,
|
||||
lineIds,
|
||||
async (line) =>
|
||||
command === 'spam_break' ? line.breakSpam() : line.writeCommand(command, true),
|
||||
command === 'spam_break' ? line.breakSpam() : line.writeCommand(command, userName),
|
||||
{ command, timeout: 120000 }
|
||||
)
|
||||
})
|
||||
|
|
@ -159,7 +159,7 @@ export class WebSocketIo {
|
|||
io,
|
||||
data.stationId,
|
||||
[lineId],
|
||||
async (line) => line.runScript(scenario),
|
||||
async (line) => line.runScript(scenario, userName),
|
||||
{
|
||||
scenario,
|
||||
timeout: scenario?.timeout ? Number(scenario.timeout) + 120000 : 300000,
|
||||
|
|
@ -472,7 +472,7 @@ export class WebSocketIo {
|
|||
lines: Line[],
|
||||
station: Station,
|
||||
output = '',
|
||||
commands: string[] = []
|
||||
inventory: string = ''
|
||||
) {
|
||||
try {
|
||||
for (const line of lines) {
|
||||
|
|
@ -491,7 +491,8 @@ export class WebSocketIo {
|
|||
userEmailOpenCLI: '',
|
||||
userOpenCLI: '',
|
||||
data: [],
|
||||
commands: commands,
|
||||
commands: [],
|
||||
inventory: inventory,
|
||||
},
|
||||
socket
|
||||
)
|
||||
|
|
@ -531,7 +532,7 @@ export class WebSocketIo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Hàm xử lý chung cho mọi action (writeCommand, runScript, v.v.)
|
||||
* Hàm xử lý chung cho mọi action (write command, runScript, v.v.)
|
||||
*/
|
||||
async handleLineOperation(
|
||||
io: CustomServer,
|
||||
|
|
@ -562,7 +563,7 @@ export class WebSocketIo {
|
|||
[linesData],
|
||||
stationData,
|
||||
line?.config?.output || '',
|
||||
line?.config?.commands || []
|
||||
line?.config?.inventory || ''
|
||||
)
|
||||
this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
/* background-color: red; */
|
||||
}
|
||||
|
||||
body {
|
||||
/* body {
|
||||
font-family: "Mulish", sans-serif;
|
||||
}
|
||||
} */
|
||||
|
||||
.list {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ const BottomToolBar = ({
|
|||
<Box>
|
||||
<Input
|
||||
style={{
|
||||
width: "600px",
|
||||
width: "30vw",
|
||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||
}}
|
||||
placeholder={"Send command to port(s)"}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ export const ButtonDPELP = ({
|
|||
},
|
||||
{
|
||||
expect: "",
|
||||
send: "show env",
|
||||
send: "show env all",
|
||||
delay: "3000",
|
||||
repeat: "1",
|
||||
note: "",
|
||||
|
|
@ -133,18 +133,20 @@ export const ButtonScenario = ({
|
|||
onClick,
|
||||
selectedLines,
|
||||
scenario,
|
||||
fontSize = "12px",
|
||||
}: {
|
||||
socket: Socket | null;
|
||||
isDisable: boolean;
|
||||
onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||
selectedLines: TLine[];
|
||||
scenario: IScenario;
|
||||
fontSize?: string;
|
||||
}) => {
|
||||
return (
|
||||
<Button
|
||||
disabled={isDisable}
|
||||
miw={"100px"}
|
||||
style={{ minHeight: "28px", height: "auto" }}
|
||||
style={{ minHeight: "28px", height: "auto", fontSize: fontSize }}
|
||||
mr={"5px"}
|
||||
variant="outline"
|
||||
color="#00a164"
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ const CardLine = ({
|
|||
</Flex>
|
||||
</Flex>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown style={{ width: "90px", backgroundColor: "#2d2d2d" }}>
|
||||
<Menu.Dropdown style={{ width: "80px", backgroundColor: "#2d2d2d" }}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
|
|
@ -363,6 +363,7 @@ const CardLine = ({
|
|||
}, 5000);
|
||||
}}
|
||||
scenario={el}
|
||||
fontSize="9px"
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
|
|
@ -386,7 +387,7 @@ const CardLine = ({
|
|||
BAUD <IconCaretRight size={"14px"} />
|
||||
</Button>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown style={{ width: "100px" }}>
|
||||
<Menu.Dropdown style={{ width: "90px" }}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@
|
|||
}
|
||||
|
||||
.buttonMenuTool {
|
||||
font-size: 11px !important;
|
||||
width: 80px !important;
|
||||
min-width: 80px !important;
|
||||
font-size: 9px !important;
|
||||
width: 70px !important;
|
||||
min-width: 70px !important;
|
||||
height: 30px !important;
|
||||
padding-right: 4px !important;
|
||||
padding-left: 4px !important;
|
||||
|
|
|
|||
|
|
@ -23,18 +23,25 @@ const ModalLog = ({
|
|||
const highlightSystemLog = (logText: string): string => {
|
||||
const colorStart = "#7fffd4";
|
||||
const colorEnd = "#ffa589";
|
||||
return logText
|
||||
.replace(/---scenario---.*\n?/g, "") // Remove lines with ---scenario---
|
||||
.replace(/\n?---send-command---.*\n?/g, "") // Remove lines with ---send-command---
|
||||
.replace(
|
||||
/^(---start-testing---|---end-testing---|---start-scenarios---|---end-scenarios---)(\d+)(---.*)?$/gm,
|
||||
(_, prefix, timestamp, suffix = "") => {
|
||||
const date = convertTimestampToDate(timestamp);
|
||||
return `<span style="background-color: ${
|
||||
prefix.includes("start") ? colorStart : colorEnd
|
||||
}" title="${date}">${prefix}${timestamp}${suffix}</span>`;
|
||||
}
|
||||
);
|
||||
const colorUser = "#f1ef5e";
|
||||
return (
|
||||
logText
|
||||
.replace(/---scenario---.*\n?/g, "") // Remove lines with ---scenario---
|
||||
.replace(/\n?---send-command---.*\n?/g, "") // Remove lines with ---send-command---
|
||||
.replace(
|
||||
/^(---start-testing---|---end-testing---|---start-scenarios---|---end-scenarios---)(\d+)(---.*)?$/gm,
|
||||
(_, prefix, timestamp, suffix = "") => {
|
||||
const date = convertTimestampToDate(timestamp);
|
||||
return `<span style="background-color: ${
|
||||
prefix.includes("start") ? colorStart : colorEnd
|
||||
}" title="${date}">${prefix}${timestamp}${suffix}</span>`;
|
||||
}
|
||||
)
|
||||
// Highlight full ---User---
|
||||
.replace(/^-------([^-\n]+)-------$/gm, (match) => {
|
||||
return `<span style="background-color: ${colorUser}" title="User">${match}</span>`;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
Loading…
Reference in New Issue