From 32873ad388b755489c735fb1ce432557ddd592e3 Mon Sep 17 00:00:00 2001 From: nguyentrungthat <80239428+nguentrungthat@users.noreply.github.com> Date: Tue, 11 Nov 2025 09:38:06 +0700 Subject: [PATCH] Update --- .../1762822728281_create_tickets_table.ts | 23 +++++++++++++++++++ BACKEND/providers/socket_io_provider.ts | 18 +++++++-------- FRONTEND/src/components/CardLine.tsx | 14 +++++++++++ FRONTEND/src/components/DrawerControl.tsx | 1 + FRONTEND/src/components/TerminalXTerm.tsx | 15 ++++++++++++ 5 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 BACKEND/database/migrations/1762822728281_create_tickets_table.ts diff --git a/BACKEND/database/migrations/1762822728281_create_tickets_table.ts b/BACKEND/database/migrations/1762822728281_create_tickets_table.ts new file mode 100644 index 0000000..45bb607 --- /dev/null +++ b/BACKEND/database/migrations/1762822728281_create_tickets_table.ts @@ -0,0 +1,23 @@ +import { BaseSchema } from '@adonisjs/lucid/schema' + +export default class extends BaseSchema { + protected tableName = 'tickets' + + async up() { + this.schema.createTable(this.tableName, (table) => { + table.increments('id') + table.string('description').notNullable() + table.string('model').notNullable() + table.string('sn').notNullable() + table.integer('line_id').notNullable() + table.integer('station_id').notNullable() + table.string('status').notNullable() + table.text('history').notNullable() + table.timestamps() + }) + } + + async down() { + this.schema.dropTable(this.tableName) + } +} diff --git a/BACKEND/providers/socket_io_provider.ts b/BACKEND/providers/socket_io_provider.ts index 11bc6b1..1c0338a 100644 --- a/BACKEND/providers/socket_io_provider.ts +++ b/BACKEND/providers/socket_io_provider.ts @@ -159,15 +159,15 @@ export class WebSocketIo { socket.on('open_cli', async (data) => { const { lineId, userEmail, userName: name, stationId } = data const line = this.lineMap.get(lineId) - if (line) { - line.userOpenCLI({ userEmail, userName: name }) + if (line && line?.userOpenCLI) { + line?.userOpenCLI({ userEmail, userName: name }) } else { if (this.lineConnecting.includes(lineId)) return const linesData = await Line.findBy('id', lineId) const stationData = await Station.findBy('id', stationId) if (linesData && stationData) { this.lineConnecting.push(lineId) - await this.connectLine(io, [linesData], stationData) + await this.connectLine(io, [linesData], stationData, line?.config?.output || '') const lineReconnect = this.lineMap.get(lineId) if (lineReconnect) { lineReconnect.userOpenCLI({ userEmail, userName: name }) @@ -179,15 +179,15 @@ export class WebSocketIo { socket.on('close_cli', async (data) => { const { lineId, stationId } = data const line = this.lineMap.get(lineId) - if (line) { - line.userCloseCLI() + if (line && line?.userCloseCLI) { + line?.userCloseCLI() } else { if (this.lineConnecting.includes(lineId)) return const linesData = await Line.findBy('id', lineId) const stationData = await Station.findBy('id', stationId) if (linesData && stationData) { this.lineConnecting.push(lineId) - await this.connectLine(io, [linesData], stationData) + await this.connectLine(io, [linesData], stationData, line?.config?.output || '') const lineReconnect = this.lineMap.get(lineId) if (lineReconnect) { lineReconnect.userCloseCLI() @@ -422,7 +422,7 @@ export class WebSocketIo { return io } - private async connectLine(socket: any, lines: Line[], station: Station) { + private async connectLine(socket: any, lines: Line[], station: Station, output = '') { try { this.stationMap.set(station.id, station) for (const line of lines) { @@ -435,7 +435,7 @@ export class WebSocketIo { stationId: station.id, apcName: line.apcName, outlet: line.outlet, - output: '', + output: output, status: '', openCLI: false, userEmailOpenCLI: '', @@ -505,7 +505,7 @@ export class WebSocketIo { if (linesData && stationData) { this.lineConnecting.push(lineId) - await this.connectLine(io, [linesData], stationData) + await this.connectLine(io, [linesData], stationData, line?.config?.output || '') this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId) const lineReconnect = this.lineMap.get(lineId) diff --git a/FRONTEND/src/components/CardLine.tsx b/FRONTEND/src/components/CardLine.tsx index 13d937c..10680ac 100644 --- a/FRONTEND/src/components/CardLine.tsx +++ b/FRONTEND/src/components/CardLine.tsx @@ -138,6 +138,20 @@ const CardLine = ({ onDoubleClick={() => { openTerminal(line); }} + onFocus={() => { + socket?.emit("open_cli", { + lineId: line.id, + stationId: line.stationId || line.station_id, + userEmail: user?.email, + userName: user?.userName, + }); + }} + onBlur={() => { + socket?.emit("close_cli", { + lineId: line?.id, + stationId: line.stationId || line.station_id, + }); + }} /> diff --git a/FRONTEND/src/components/DrawerControl.tsx b/FRONTEND/src/components/DrawerControl.tsx index 78369d1..003ca00 100644 --- a/FRONTEND/src/components/DrawerControl.tsx +++ b/FRONTEND/src/components/DrawerControl.tsx @@ -810,6 +810,7 @@ export const DrawerSwitchControl: React.FC = ({ useEffect(() => { if (!open) { setListPortsSelected([]); + setLoading(true); } }, [open]); diff --git a/FRONTEND/src/components/TerminalXTerm.tsx b/FRONTEND/src/components/TerminalXTerm.tsx index 631063d..d4c6a60 100644 --- a/FRONTEND/src/components/TerminalXTerm.tsx +++ b/FRONTEND/src/components/TerminalXTerm.tsx @@ -22,6 +22,8 @@ interface TerminalCLIProps { paddingLeft?: string; }; onDoubleClick?: () => void; + onFocus?: () => void; + onBlur?: () => void; fontSize?: number; miniSize?: boolean; loadingContent?: boolean; @@ -40,6 +42,8 @@ const TerminalCLI: React.FC = ({ miniSize = false, initContent = "", loadingContent = false, + onFocus, + onBlur, }) => { const xtermRef = useRef(null); const terminal = useRef(null); @@ -182,6 +186,17 @@ const TerminalCLI: React.FC = ({ }} >
{ + event.preventDefault(); + event.stopPropagation(); + if (!isDisabled) { + terminal.current?.focus(); + if (onFocus) onFocus(); + } + }} + onBlurCapture={() => { + if (onBlur) onBlur(); + }} ref={xtermRef} style={{ width: "100%",