Update UI Bottom Tool Bar
This commit is contained in:
parent
f04bc0b4c1
commit
31036ff7da
|
|
@ -17,8 +17,8 @@ interface PromptCallback {
|
|||
}
|
||||
|
||||
class APCController {
|
||||
private apc_number?: number
|
||||
private apc_ip: string
|
||||
public apc_number?: number
|
||||
public apc_ip: string
|
||||
private apc_port: number
|
||||
private apc_username: string
|
||||
private apc_password: string
|
||||
|
|
@ -100,7 +100,7 @@ class APCController {
|
|||
this.buffer = ''
|
||||
}
|
||||
}
|
||||
// appendLog(data, 0, 0, this.apc_number || 0)
|
||||
appendLog(data, 0, 0, this.apc_number || 0)
|
||||
}
|
||||
|
||||
private _handleClose(): void {
|
||||
|
|
@ -130,7 +130,7 @@ class APCController {
|
|||
setTimeout(() => {
|
||||
console.log('[ECONNRESET] Trying reconnect apc:', this.apc_ip)
|
||||
this.reconnect()
|
||||
}, 10000)
|
||||
}, 15000)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ export default class LineConnection {
|
|||
})
|
||||
}
|
||||
|
||||
writeCommand(cmd: string, isWrite = false) {
|
||||
writeCommand(cmd: string | Buffer<ArrayBuffer>, isWrite = false) {
|
||||
if (this.client.destroyed) {
|
||||
console.log(`⚠️ Cannot send, line ${this.config.lineNumber} is closed`)
|
||||
return
|
||||
|
|
@ -513,4 +513,17 @@ export default class LineConnection {
|
|||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Gửi nhiều ký tự ESC để vào ROMMON
|
||||
breakSpam() {
|
||||
let count = 0
|
||||
const escInterval = setInterval(() => {
|
||||
if (count >= 100) {
|
||||
clearInterval(escInterval)
|
||||
return
|
||||
}
|
||||
this.writeCommand(Buffer.from([0xff, 0xf3])) // Ctrl + Break
|
||||
count++
|
||||
}, 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default class SwitchController {
|
|||
private _waitFor(prompt: string, timeout = 5000): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error(`Timeout waiting for: ${prompt}`))
|
||||
resolve(`Timeout waiting for: ${prompt}`)
|
||||
}, timeout)
|
||||
|
||||
this.promptCallbacks.push({
|
||||
|
|
@ -188,58 +188,74 @@ export default class SwitchController {
|
|||
public async turnPortOff(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
await this._waitFor('(config)#')
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`shutdown`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
}
|
||||
|
||||
public async turnPortOn(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
await this._waitFor('(config)#')
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`no shutdown`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
}
|
||||
|
||||
public async restartPort(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
await this._waitFor('(config)#')
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`shutdown`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
await this.sleep(2000)
|
||||
this._send(`no shutdown`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
}
|
||||
|
||||
public async disablePoE(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
await this._waitFor('(config)#')
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`power inline never`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
}
|
||||
|
||||
public async enablePoE(port: string) {
|
||||
await this.enterEnableMode()
|
||||
this._send(`configure terminal`)
|
||||
await this._waitFor('(config)#')
|
||||
// await this._waitFor('(config)#')
|
||||
await this.sleep(500)
|
||||
this._send(`interface ${port}`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`power inline auto`)
|
||||
await this._waitFor('(config-if)#')
|
||||
// await this._waitFor('(config-if)#')
|
||||
await this.sleep(500)
|
||||
this._send(`end`)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,12 +63,12 @@ export default class SocketIoProvider {
|
|||
|
||||
export class WebSocketIo {
|
||||
intervalMap: { [key: string]: NodeJS.Timeout } = {}
|
||||
stationMap: Map<number, Station> = new Map()
|
||||
lineMap: Map<number, LineConnection> = new Map() // key = lineId
|
||||
userConnecting: Map<number, { userId: number; userName: string }> = new Map()
|
||||
apcsControl: Map<string, APCController> = new Map()
|
||||
switchControl: Map<string, SwitchController> = new Map()
|
||||
lineConnecting: number[] = [] // key = lineId
|
||||
intervalKeepConnect: { [key: string]: NodeJS.Timeout } = {}
|
||||
|
||||
constructor(protected app: ApplicationService) {}
|
||||
|
||||
|
|
@ -115,7 +115,16 @@ export class WebSocketIo {
|
|||
listLineS.forEach((el) => {
|
||||
if (el?.userOpenCLI === userName) {
|
||||
const line = this.lineMap.get(el.id)
|
||||
if (line && line?.userCloseCLI()) line?.userCloseCLI()
|
||||
if (line) {
|
||||
line.config.openCLI = false
|
||||
line.config.userEmailOpenCLI = ''
|
||||
line.config.userOpenCLI = ''
|
||||
io.emit('user_close_cli', {
|
||||
stationId: line.config.stationId,
|
||||
lineId: line.config.id,
|
||||
userEmailOpenCLI: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
|
|
@ -136,7 +145,8 @@ export class WebSocketIo {
|
|||
io,
|
||||
stationId,
|
||||
lineIds,
|
||||
async (line) => line.writeCommand(command, true),
|
||||
async (line) =>
|
||||
command === 'spam_break' ? line.breakSpam() : line.writeCommand(command, true),
|
||||
{ command, timeout: 120000 }
|
||||
)
|
||||
})
|
||||
|
|
@ -159,21 +169,26 @@ 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) {
|
||||
line?.userOpenCLI({ userEmail, userName: name })
|
||||
if (line) {
|
||||
if (line?.userOpenCLI) line?.userOpenCLI({ userEmail, userName: name })
|
||||
else {
|
||||
line.config.openCLI = true
|
||||
line.config.userEmailOpenCLI = userEmail
|
||||
line.config.userOpenCLI = userName
|
||||
io.emit('user_open_cli', {
|
||||
stationId: line.config.stationId,
|
||||
lineId: line.config.id,
|
||||
userEmailOpenCLI: userEmail,
|
||||
userOpenCLI: userName,
|
||||
})
|
||||
}
|
||||
} 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,
|
||||
line?.config?.output || '',
|
||||
line?.config?.commands || []
|
||||
)
|
||||
await this.connectLine(io, [linesData], stationData)
|
||||
const lineReconnect = this.lineMap.get(lineId)
|
||||
if (lineReconnect) {
|
||||
lineReconnect.userOpenCLI({ userEmail, userName: name })
|
||||
|
|
@ -185,21 +200,25 @@ export class WebSocketIo {
|
|||
socket.on('close_cli', async (data) => {
|
||||
const { lineId, stationId } = data
|
||||
const line = this.lineMap.get(lineId)
|
||||
if (line && line?.userCloseCLI) {
|
||||
line?.userCloseCLI()
|
||||
if (line) {
|
||||
if (line?.userCloseCLI) line?.userCloseCLI()
|
||||
else {
|
||||
line.config.openCLI = false
|
||||
line.config.userEmailOpenCLI = ''
|
||||
line.config.userOpenCLI = ''
|
||||
io.emit('user_close_cli', {
|
||||
stationId: line.config.stationId,
|
||||
lineId: line.config.id,
|
||||
userEmailOpenCLI: '',
|
||||
})
|
||||
}
|
||||
} 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,
|
||||
line?.config?.output || '',
|
||||
line?.config?.commands || []
|
||||
)
|
||||
await this.connectLine(io, [linesData], stationData)
|
||||
const lineReconnect = this.lineMap.get(lineId)
|
||||
if (lineReconnect) {
|
||||
lineReconnect.userCloseCLI()
|
||||
|
|
@ -265,7 +284,10 @@ export class WebSocketIo {
|
|||
if (!station) return
|
||||
const apcIp = (station as any)[`${apcName}_ip`] as string
|
||||
const apc = this.apcsControl.get(apcIp)
|
||||
if (apc) await apc.reconnect()
|
||||
if (apc) {
|
||||
await apc.reconnect()
|
||||
this.keepConnectAPC(apcIp, io)
|
||||
} else await this.connectApc(io, apcName, station)
|
||||
} else {
|
||||
for (const outletNumber of outletNumbers) {
|
||||
if (!outletNumber || outletNumber < 0) return
|
||||
|
|
@ -282,7 +304,11 @@ export class WebSocketIo {
|
|||
|
||||
const apcIp = (station as any)[`${apcName}_ip`] as string
|
||||
const apc = this.apcsControl.get(apcIp)
|
||||
if (apc && apc.status === 'CONNECTED') {
|
||||
if (apc && apc.status !== 'CONNECTED') {
|
||||
await apc.reconnect()
|
||||
this.keepConnectAPC(apcIp, io)
|
||||
}
|
||||
if (apc) {
|
||||
switch (action) {
|
||||
case 'on':
|
||||
await apc?.turnOnOutlet(outletNumber)
|
||||
|
|
@ -302,24 +328,6 @@ export class WebSocketIo {
|
|||
setTimeout(() => {
|
||||
apc?.navigateToOutlets()
|
||||
}, 10000)
|
||||
} else if (apc && apc.status !== 'CONNECTED') {
|
||||
await apc.reconnect()
|
||||
switch (action) {
|
||||
case 'on':
|
||||
await apc?.turnOnOutlet(outletNumber)
|
||||
break
|
||||
case 'off':
|
||||
await apc?.turnOffOutlet(outletNumber)
|
||||
break
|
||||
case 'restart':
|
||||
await apc?.restartOutlet(outletNumber)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
setTimeout(() => {
|
||||
apc?.navigateToOutlets()
|
||||
}, 10000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -336,8 +344,11 @@ export class WebSocketIo {
|
|||
data: apc.output,
|
||||
status: apc.status,
|
||||
})
|
||||
this.keepConnectAPC(apcIp, io)
|
||||
} else if (apc && apc.status !== 'CONNECTED') {
|
||||
await apc.reconnect()
|
||||
this.apcsControl.set(apcIp, apc)
|
||||
this.keepConnectAPC(apcIp, io)
|
||||
} else await this.connectApc(io, apcName, station)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
|
@ -442,7 +453,6 @@ export class WebSocketIo {
|
|||
commands: string[] = []
|
||||
) {
|
||||
try {
|
||||
this.stationMap.set(station.id, station)
|
||||
for (const line of lines) {
|
||||
const lineConn = new LineConnection(
|
||||
{
|
||||
|
|
@ -584,6 +594,7 @@ export class WebSocketIo {
|
|||
await apc.connect()
|
||||
await apc.login()
|
||||
this.apcsControl.set(ip, apc)
|
||||
this.keepConnectAPC(ip, socket)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
|
@ -603,7 +614,7 @@ export class WebSocketIo {
|
|||
status: 'DISCONNECTED',
|
||||
message: `Missing Switch configuration`,
|
||||
})
|
||||
throw new Error(`Missing Switch configuration`)
|
||||
return
|
||||
}
|
||||
|
||||
// Tạo APC Controller instance
|
||||
|
|
@ -633,7 +644,10 @@ export class WebSocketIo {
|
|||
|
||||
private async clearLineBeforeConnect(stationId: number, clearLine: number) {
|
||||
const station = await Station.find(stationId)
|
||||
if (!station) throw new Error(`Station ${stationId} not found`)
|
||||
if (!station) {
|
||||
console.log('[ERROR connect station] Not found!')
|
||||
return
|
||||
}
|
||||
|
||||
// Kết nối tới station qua Telnet / Socket
|
||||
const client = new net.Socket()
|
||||
|
|
@ -679,7 +693,9 @@ export class WebSocketIo {
|
|||
const newMap = new Map<number, LineConnection>()
|
||||
this.lineMap.forEach((line, id) => {
|
||||
if (line && line.config) {
|
||||
newMap.set(id, { config: { ...line.config, status: 'disconnected' } } as LineConnection)
|
||||
newMap.set(id, {
|
||||
config: { ...line.config, status: 'disconnected' },
|
||||
} as LineConnection)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -695,4 +711,19 @@ export class WebSocketIo {
|
|||
const parsed = JSON.parse(raw)
|
||||
this.lineMap = new Map(parsed.lineMap)
|
||||
}
|
||||
|
||||
private keepConnectAPC = (ip: string, io: any) => {
|
||||
if (this.intervalKeepConnect[`${ip}`]) {
|
||||
clearInterval(this.intervalKeepConnect[`${ip}`])
|
||||
delete this.intervalKeepConnect[`${ip}`]
|
||||
}
|
||||
const interval = setInterval(() => {
|
||||
const apcConnect = this.apcsControl.get(ip)
|
||||
if (apcConnect && apcConnect.status === 'CONNECTED') {
|
||||
apcConnect._send('ENTER')
|
||||
}
|
||||
}, 40000)
|
||||
|
||||
this.intervalKeepConnect[`${ip}`] = interval
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,3 +70,10 @@ body {
|
|||
margin: 0.1rem auto 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.containerMain {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 88vh;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,22 +27,22 @@ import type {
|
|||
import axios from "axios";
|
||||
import CardLine from "./components/CardLine";
|
||||
import { SocketProvider, useSocket } from "./context/SocketContext";
|
||||
import {
|
||||
// ButtonConnect,
|
||||
ButtonControlApc,
|
||||
ButtonCopy,
|
||||
ButtonDPELP,
|
||||
ButtonScenario,
|
||||
ButtonSelect,
|
||||
} from "./components/ButtonAction";
|
||||
import // ButtonConnect,
|
||||
// ButtonControlApc,
|
||||
// ButtonCopy,
|
||||
// ButtonDPELP,
|
||||
// ButtonScenario,
|
||||
// ButtonSelect,
|
||||
"./components/ButtonAction";
|
||||
import StationSetting from "./components/FormAddEdit";
|
||||
import DrawerScenario from "./components/DrawerScenario";
|
||||
// import DrawerScenario from "./components/DrawerScenario";
|
||||
import { Notifications } from "@mantine/notifications";
|
||||
import ModalTerminal from "./components/ModalTerminal";
|
||||
import PageLogin from "./components/Authentication/LoginPage";
|
||||
import DrawerLogs from "./components/DrawerLogs";
|
||||
// import DrawerLogs from "./components/DrawerLogs";
|
||||
import DraggableTabs from "./components/DragTabs";
|
||||
import { isJsonString } from "./untils/helper";
|
||||
import BottomToolBar from "./components/BottomToolBar";
|
||||
|
||||
const apiUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
|
|
@ -67,7 +67,6 @@ function App() {
|
|||
const [stations, setStations] = useState<TStation[]>([]);
|
||||
const [selectedLines, setSelectedLines] = useState<TLine[]>([]);
|
||||
const [activeTab, setActiveTab] = useState("0");
|
||||
const [showBottomShadow, setShowBottomShadow] = useState(false);
|
||||
const [isDisable, setIsDisable] = useState(false);
|
||||
const [isOpenAddStation, setIsOpenAddStation] = useState(false);
|
||||
const [isEditStation, setIsEditStation] = useState(false);
|
||||
|
|
@ -84,6 +83,29 @@ function App() {
|
|||
const [testLogContent, setTestLogContent] = useState("");
|
||||
const [isLogModalOpen, setIsLogModalOpen] = useState(false);
|
||||
|
||||
const connectApcSwitch = (station: TStation) => {
|
||||
if (station?.apc_1_ip && station?.apc_1_port) {
|
||||
socket?.emit("connect_apc", {
|
||||
station: station,
|
||||
apcIp: station?.apc_1_ip,
|
||||
apcName: "apc_1",
|
||||
});
|
||||
}
|
||||
if (station?.apc_2_ip && station?.apc_2_port) {
|
||||
socket?.emit("connect_apc", {
|
||||
station: station,
|
||||
apcIp: station?.apc_2_ip,
|
||||
apcName: "apc_2",
|
||||
});
|
||||
}
|
||||
if (station?.switch_control_ip && station?.switch_control_port) {
|
||||
socket?.emit("connect_switch", {
|
||||
station: station,
|
||||
ip: station?.switch_control_ip,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// function get list station
|
||||
const getStation = async () => {
|
||||
try {
|
||||
|
|
@ -91,6 +113,9 @@ function App() {
|
|||
if (response.status) {
|
||||
if (Array.isArray(response.data)) {
|
||||
setStations(response.data);
|
||||
response.data.forEach((station) => {
|
||||
connectApcSwitch(station);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -113,9 +138,10 @@ function App() {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return;
|
||||
getStation();
|
||||
getScenarios();
|
||||
}, []);
|
||||
}, [socket]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket || !stations?.length) return;
|
||||
|
|
@ -363,16 +389,6 @@ function App() {
|
|||
setSelectedLine(data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (selectedLine)
|
||||
socket?.emit("close_cli", {
|
||||
lineId: selectedLine?.id,
|
||||
stationId: selectedLine?.station_id,
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container w={"100%"} style={{ maxWidth: "100%" }}>
|
||||
<DraggableTabs
|
||||
|
|
@ -389,37 +405,28 @@ function App() {
|
|||
value={station.id.toString()}
|
||||
pt="md"
|
||||
>
|
||||
<Flex className={classes.containerMain}>
|
||||
<Grid>
|
||||
<Grid.Col
|
||||
span={11}
|
||||
span={12}
|
||||
style={{
|
||||
boxShadow: showBottomShadow
|
||||
? "inset 0 -12px 10px -10px rgba(0, 0, 0, 0.2)"
|
||||
: "none",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
>
|
||||
<ScrollArea
|
||||
h={"84vh"}
|
||||
onScrollPositionChange={({ y }) => {
|
||||
const el = document.querySelector(
|
||||
".mantine-ScrollArea-viewport"
|
||||
);
|
||||
if (!el) return;
|
||||
const maxScroll = el.scrollHeight - el.clientHeight;
|
||||
setShowBottomShadow(y < maxScroll - 2);
|
||||
}}
|
||||
>
|
||||
<ScrollArea h={"63vh"}>
|
||||
{station.lines.length > 8 ? (
|
||||
<Grid
|
||||
style={{
|
||||
marginLeft: "3%",
|
||||
width: "90%",
|
||||
width: "95%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Grid.Col span={6}>
|
||||
<Grid.Col
|
||||
span={6}
|
||||
style={{ borderRight: "1px solid #ccc" }}
|
||||
>
|
||||
<Flex wrap="wrap" gap="sm" justify={"center"}>
|
||||
{station.lines.slice(0, 8).map((line, i) => (
|
||||
<CardLine
|
||||
|
|
@ -460,7 +467,8 @@ function App() {
|
|||
</Flex>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
) : station.lines.length <= 8 && station.lines.length > 0 ? (
|
||||
) : station.lines.length <= 8 &&
|
||||
station.lines.length > 0 ? (
|
||||
<Flex wrap="wrap" gap="sm" justify={"center"}>
|
||||
{station.lines.map((line, i) => (
|
||||
<CardLine
|
||||
|
|
@ -485,114 +493,20 @@ function App() {
|
|||
)}
|
||||
</ScrollArea>
|
||||
</Grid.Col>
|
||||
<Grid.Col
|
||||
span={1}
|
||||
style={{ backgroundColor: "#f1f1f1", borderRadius: 8 }}
|
||||
>
|
||||
<Flex
|
||||
direction={"column"}
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
h={"100%"}
|
||||
>
|
||||
<Flex
|
||||
direction={"column"}
|
||||
align={"center"}
|
||||
gap={"6px"}
|
||||
wrap={"wrap"}
|
||||
>
|
||||
<ButtonSelect
|
||||
</Grid>
|
||||
<BottomToolBar
|
||||
selectedLines={selectedLines}
|
||||
socket={socket}
|
||||
setSelectedLines={setSelectedLines}
|
||||
isDisable={isDisable}
|
||||
setIsDisable={setIsDisable}
|
||||
station={station}
|
||||
/>
|
||||
{/* <ButtonConnect
|
||||
selectedLines={selectedLines}
|
||||
setSelectedLines={setSelectedLines}
|
||||
station={station}
|
||||
socket={socket}
|
||||
/> */}
|
||||
<ButtonControlApc
|
||||
selectedLines={selectedLines}
|
||||
setSelectedLines={setSelectedLines}
|
||||
station={station}
|
||||
socket={socket}
|
||||
/>
|
||||
<ButtonCopy
|
||||
selectedLines={selectedLines}
|
||||
setSelectedLines={setSelectedLines}
|
||||
/>
|
||||
<Flex
|
||||
w={"100%"}
|
||||
direction={"column"}
|
||||
align={"center"}
|
||||
wrap={"wrap"}
|
||||
>
|
||||
<hr style={{ width: "100%" }} />
|
||||
<DrawerScenario
|
||||
scenarios={scenarios}
|
||||
setScenarios={setScenarios}
|
||||
/>
|
||||
</Flex>
|
||||
<ButtonDPELP
|
||||
socket={socket}
|
||||
selectedLines={selectedLines}
|
||||
isDisable={isDisable || selectedLines.length === 0}
|
||||
onClick={() => {
|
||||
setSelectedLines([]);
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
/>
|
||||
<ScrollArea h={"60vh"} style={{ paddingBottom: "12px" }}>
|
||||
<Flex
|
||||
w={"100%"}
|
||||
direction={"column"}
|
||||
wrap={"wrap"}
|
||||
gap={"6px"}
|
||||
>
|
||||
{scenarios.map((el, i) => (
|
||||
<ButtonScenario
|
||||
key={i}
|
||||
socket={socket}
|
||||
selectedLines={selectedLines.filter(
|
||||
(el) =>
|
||||
!el?.userEmailOpenCLI ||
|
||||
el?.userEmailOpenCLI === user?.email
|
||||
)}
|
||||
isDisable={
|
||||
isDisable ||
|
||||
selectedLines.filter(
|
||||
(el) =>
|
||||
!el?.userEmailOpenCLI ||
|
||||
el?.userEmailOpenCLI === user?.email
|
||||
).length === 0
|
||||
}
|
||||
onClick={() => {
|
||||
setSelectedLines([]);
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
scenario={el}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
</Flex>
|
||||
<DrawerLogs
|
||||
socket={socket}
|
||||
testLogContent={testLogContent}
|
||||
isLogModalOpen={isLogModalOpen}
|
||||
setIsLogModalOpen={setIsLogModalOpen}
|
||||
testLogContent={testLogContent}
|
||||
setTestLogContent={setTestLogContent}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Tabs.Panel>
|
||||
))}
|
||||
onChange={(id) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,278 @@
|
|||
import {
|
||||
Box,
|
||||
Button,
|
||||
CloseButton,
|
||||
Flex,
|
||||
Input,
|
||||
ScrollArea,
|
||||
Tabs,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
import classes from "./Component.module.css";
|
||||
import type { TLine, TStation } from "../untils/types";
|
||||
import type { Socket } from "socket.io-client";
|
||||
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
|
||||
import DrawerLogs from "./DrawerLogs";
|
||||
import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl";
|
||||
|
||||
interface TabsProps {
|
||||
selectedLines: TLine[];
|
||||
socket: Socket | null;
|
||||
setSelectedLines: (lines: React.SetStateAction<TLine[]>) => void;
|
||||
isDisable: boolean;
|
||||
station: TStation;
|
||||
setIsDisable: (lines: React.SetStateAction<boolean>) => void;
|
||||
testLogContent: string;
|
||||
isLogModalOpen: boolean;
|
||||
setIsLogModalOpen: (lines: React.SetStateAction<boolean>) => void;
|
||||
setTestLogContent: (lines: React.SetStateAction<string>) => void;
|
||||
}
|
||||
|
||||
const BottomToolBar = ({
|
||||
selectedLines,
|
||||
socket,
|
||||
setSelectedLines,
|
||||
isDisable,
|
||||
station,
|
||||
setIsDisable,
|
||||
testLogContent,
|
||||
isLogModalOpen,
|
||||
setIsLogModalOpen,
|
||||
setTestLogContent,
|
||||
}: TabsProps) => {
|
||||
const [valueInput, setValueInput] = useState<string>("");
|
||||
const [activeTabBottom, setActiveBottom] = useState<string>("command");
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
defaultValue="command"
|
||||
orientation="vertical"
|
||||
value={activeTabBottom}
|
||||
onChange={(val) => {
|
||||
setActiveBottom(val || "command");
|
||||
}}
|
||||
className={classes.containerBottom}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
style={{
|
||||
backgroundColor: activeTabBottom === "command" ? "#c8d9fd" : "",
|
||||
}}
|
||||
value="command"
|
||||
>
|
||||
Command Line
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
style={{
|
||||
backgroundColor: activeTabBottom === "apc" ? "#c8d9fd" : "",
|
||||
}}
|
||||
value="apc"
|
||||
>
|
||||
APC
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
style={{
|
||||
backgroundColor: activeTabBottom === "switch" ? "#c8d9fd" : "",
|
||||
}}
|
||||
value="switch"
|
||||
>
|
||||
Switch
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="command" p={"xs"}>
|
||||
<Flex justify={"space-between"}>
|
||||
<ScrollArea h={"17vh"}>
|
||||
<Flex wrap={"wrap"} gap={"xs"} w={"400px"}>
|
||||
{selectedLines.map((el) => (
|
||||
<Box
|
||||
key={el.id}
|
||||
style={{
|
||||
paddingLeft: "4px",
|
||||
height: "30px",
|
||||
width: "80px",
|
||||
backgroundColor: "#d4e3ff",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
>
|
||||
<Flex align={"center"} justify={"center"} gap={"4px"}>
|
||||
<Text fz={"12px"}>Line {el.lineNumber}</Text>
|
||||
<CloseButton
|
||||
style={{ minWidth: "24px" }}
|
||||
aria-label="Clear input"
|
||||
onClick={() =>
|
||||
setSelectedLines(
|
||||
selectedLines.filter((line) => line.id !== el.id)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
<Box pl={"md"} pr={"md"}>
|
||||
<Flex justify={"space-between"} mb={"xs"}>
|
||||
<Flex></Flex>
|
||||
<Button
|
||||
disabled={isDisable || selectedLines.length === 0}
|
||||
variant="filled"
|
||||
color="orange"
|
||||
size="xs"
|
||||
radius="md"
|
||||
onClick={() => {
|
||||
const listLine = selectedLines.length
|
||||
? selectedLines
|
||||
: station?.lines;
|
||||
if (listLine.length) {
|
||||
socket?.emit("write_command_line_from_web", {
|
||||
lineIds: listLine.map((line) => line.id),
|
||||
stationId: station.id,
|
||||
command: " \n",
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Send Break
|
||||
</Button>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Input
|
||||
style={{
|
||||
width: "600px",
|
||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||
}}
|
||||
placeholder={"Send command to port(s)"}
|
||||
value={valueInput}
|
||||
onChange={(event) => {
|
||||
const newValue = event.currentTarget.value;
|
||||
setValueInput(newValue);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
const listLine = selectedLines.length
|
||||
? selectedLines
|
||||
: station?.lines;
|
||||
if (listLine?.length) {
|
||||
socket?.emit("write_command_line_from_web", {
|
||||
lineIds: listLine.map((line) => line.id),
|
||||
stationId: station.id,
|
||||
command: valueInput + "\n",
|
||||
});
|
||||
setTimeout(() => {
|
||||
socket?.emit("write_command_line_from_web", {
|
||||
lineIds: listLine.map((line) => line.id),
|
||||
stationId: station.id,
|
||||
command: " \n",
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
setValueInput("");
|
||||
}
|
||||
}}
|
||||
rightSectionPointerEvents="all"
|
||||
rightSection={
|
||||
<CloseButton
|
||||
aria-label="Clear input"
|
||||
onClick={() => setValueInput("")}
|
||||
style={{
|
||||
display: valueInput ? undefined : "none",
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={{ width: "220px" }}>
|
||||
<Flex align={"center"} wrap={"wrap"} gap={"xs"}>
|
||||
<ButtonSelect
|
||||
selectedLines={selectedLines}
|
||||
setSelectedLines={setSelectedLines}
|
||||
station={station}
|
||||
/>
|
||||
<ButtonDPELP
|
||||
socket={socket}
|
||||
selectedLines={selectedLines}
|
||||
isDisable={isDisable || selectedLines.length === 0}
|
||||
onClick={() => {
|
||||
setSelectedLines([]);
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
disabled={isDisable || selectedLines.length === 0}
|
||||
variant="outline"
|
||||
color="green"
|
||||
style={{ height: "30px", width: "100px" }}
|
||||
onClick={() => {
|
||||
if (selectedLines.length !== station.lines.length)
|
||||
setSelectedLines(station.lines);
|
||||
else setSelectedLines([]);
|
||||
}}
|
||||
>
|
||||
Scenario
|
||||
</Button>
|
||||
{/* <Flex
|
||||
w={"100%"}
|
||||
direction={"column"}
|
||||
wrap={"wrap"}
|
||||
gap={"6px"}
|
||||
>
|
||||
{scenarios.map((el, i) => (
|
||||
<ButtonScenario
|
||||
key={i}
|
||||
socket={socket}
|
||||
selectedLines={selectedLines.filter(
|
||||
(el) =>
|
||||
!el?.userEmailOpenCLI ||
|
||||
el?.userEmailOpenCLI === user?.email
|
||||
)}
|
||||
isDisable={
|
||||
isDisable ||
|
||||
selectedLines.filter(
|
||||
(el) =>
|
||||
!el?.userEmailOpenCLI ||
|
||||
el?.userEmailOpenCLI === user?.email
|
||||
).length === 0
|
||||
}
|
||||
onClick={() => {
|
||||
setSelectedLines([]);
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
scenario={el}
|
||||
/>
|
||||
))}
|
||||
</Flex> */}
|
||||
<DrawerLogs
|
||||
socket={socket}
|
||||
isLogModalOpen={isLogModalOpen}
|
||||
setIsLogModalOpen={setIsLogModalOpen}
|
||||
testLogContent={testLogContent}
|
||||
setTestLogContent={setTestLogContent}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="apc" ps={"xs"}>
|
||||
<DrawerAPCControl socket={socket} stationAPI={station} />
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="switch" ps={"xs"}>
|
||||
<DrawerSwitchControl socket={socket} stationAPI={station} />
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
export default BottomToolBar;
|
||||
|
|
@ -111,3 +111,11 @@
|
|||
.hideScrollBar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.containerBottom {
|
||||
height: 22vh;
|
||||
padding: 8px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
background-color: #f3f3f38c;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@ import {
|
|||
ActionIcon,
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
CloseButton,
|
||||
Flex,
|
||||
Group,
|
||||
Input,
|
||||
Menu,
|
||||
Tabs,
|
||||
Text,
|
||||
|
|
@ -39,7 +36,6 @@ import {
|
|||
import classes from "./Component.module.css";
|
||||
import type { TStation, TUser } from "../untils/types";
|
||||
import type { Socket } from "socket.io-client";
|
||||
import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl";
|
||||
|
||||
interface DraggableTabsProps {
|
||||
tabsData: TStation[];
|
||||
|
|
@ -87,6 +83,7 @@ function SortableTab({
|
|||
transition,
|
||||
cursor: "grab",
|
||||
userSelect: "none",
|
||||
backgroundColor: active === tab.id.toString() ? "#deffde" : "",
|
||||
}}
|
||||
color={active === tab.id.toString() ? "green" : ""}
|
||||
fw={600}
|
||||
|
|
@ -116,7 +113,6 @@ export default function DraggableTabs({
|
|||
setStationEdit,
|
||||
active,
|
||||
setActive,
|
||||
onSendCommand,
|
||||
}: DraggableTabsProps) {
|
||||
const user = useMemo(() => {
|
||||
return localStorage.getItem("user") &&
|
||||
|
|
@ -127,12 +123,6 @@ export default function DraggableTabs({
|
|||
const [tabs, setTabs] = useState<TStation[]>(tabsData);
|
||||
const [isChangeTab, setIsChangeTab] = useState<boolean>(false);
|
||||
const [isSetActive, setIsSetActive] = useState<boolean>(false);
|
||||
const [valueInput, setValueInput] = useState<string>("");
|
||||
const [openedAPC, setOpenedAPC] = useState(false);
|
||||
const [openedSwitch, setOpenedSwitch] = useState(false);
|
||||
// const [active, setActive] = useState<string | null>(
|
||||
// tabsData?.length > 0 ? tabsData[0]?.id.toString() : null
|
||||
// );
|
||||
|
||||
const sensors = useSensors(useSensor(PointerSensor));
|
||||
|
||||
|
|
@ -220,29 +210,6 @@ export default function DraggableTabs({
|
|||
};
|
||||
}, []);
|
||||
|
||||
const connectApcSwitch = (station: TStation) => {
|
||||
if (station?.apc_1_ip && station?.apc_1_port) {
|
||||
socket?.emit("connect_apc", {
|
||||
station: station,
|
||||
apcIp: station?.apc_1_ip,
|
||||
apcName: "apc_1",
|
||||
});
|
||||
}
|
||||
if (station?.apc_2_ip && station?.apc_2_port) {
|
||||
socket?.emit("connect_apc", {
|
||||
station: station,
|
||||
apcIp: station?.apc_2_ip,
|
||||
apcName: "apc_2",
|
||||
});
|
||||
}
|
||||
if (station?.switch_control_ip && station?.switch_control_port) {
|
||||
socket?.emit("connect_switch", {
|
||||
station: station,
|
||||
ip: station?.switch_control_ip,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
|
|
@ -259,69 +226,7 @@ export default function DraggableTabs({
|
|||
w={w}
|
||||
>
|
||||
<Flex justify={"space-between"}>
|
||||
<Flex style={{ width: "400px" }} align={"center"}>
|
||||
<Input
|
||||
style={{
|
||||
width: "300px",
|
||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||
}}
|
||||
placeholder={"Chat to Port/All"}
|
||||
value={valueInput}
|
||||
onChange={(event) => {
|
||||
const newValue = event.currentTarget.value;
|
||||
setValueInput(newValue);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
onSendCommand(valueInput);
|
||||
setValueInput("");
|
||||
}
|
||||
}}
|
||||
rightSectionPointerEvents="all"
|
||||
rightSection={
|
||||
<CloseButton
|
||||
aria-label="Clear input"
|
||||
onClick={() => setValueInput("")}
|
||||
style={{ display: valueInput ? undefined : "none" }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Flex gap={"xs"} ms={"md"}>
|
||||
<Button
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
const station = tabs.find(
|
||||
(el) => el.id.toString() === active
|
||||
);
|
||||
if (!station) return;
|
||||
setOpenedAPC(true);
|
||||
connectApcSwitch(station);
|
||||
}}
|
||||
>
|
||||
APC
|
||||
</Button>
|
||||
<Button
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
const station = tabs.find(
|
||||
(el) => el.id.toString() === active
|
||||
);
|
||||
if (!station) return;
|
||||
setOpenedSwitch(true);
|
||||
connectApcSwitch(station);
|
||||
}}
|
||||
>
|
||||
Switch
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex></Flex>
|
||||
<Tabs.List className={classes.list}>
|
||||
<SortableContext
|
||||
items={tabs}
|
||||
|
|
@ -429,36 +334,6 @@ export default function DraggableTabs({
|
|||
|
||||
{panels}
|
||||
</Tabs>
|
||||
|
||||
{tabs.find((el) => el.id.toString() === active) && (
|
||||
<DrawerAPCControl
|
||||
open={openedAPC}
|
||||
onClose={() => {
|
||||
setOpenedAPC(false);
|
||||
}}
|
||||
socket={socket}
|
||||
stationAPI={tabs.find((el) => el.id.toString() === active) || tabs[0]}
|
||||
openedSwitch={() => {
|
||||
setOpenedAPC(false);
|
||||
setOpenedSwitch(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{tabs.find((el) => el.id.toString() === active) && (
|
||||
<DrawerSwitchControl
|
||||
open={openedSwitch}
|
||||
onClose={() => {
|
||||
setOpenedSwitch(false);
|
||||
}}
|
||||
socket={socket}
|
||||
stationAPI={tabs.find((el) => el.id.toString() === active) || tabs[0]}
|
||||
openedAPC={() => {
|
||||
setOpenedSwitch(false);
|
||||
setOpenedAPC(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DndContext>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Button, Card, Drawer, Grid, Loader, Text } from "@mantine/core";
|
||||
import { Box, Button, Card, Grid, Loader, Text } from "@mantine/core";
|
||||
import { IconRepeat, IconSection } from "@tabler/icons-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import classes from "./Component.module.css";
|
||||
|
|
@ -8,10 +8,6 @@ import type { Socket } from "socket.io-client";
|
|||
interface DrawerProps {
|
||||
stationAPI: TStation;
|
||||
socket: Socket | null;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
openedSwitch?: () => void;
|
||||
openedAPC?: () => void;
|
||||
}
|
||||
|
||||
type TSelectedOutlet = {
|
||||
|
|
@ -24,9 +20,6 @@ type TSelectedOutlet = {
|
|||
export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
||||
stationAPI,
|
||||
socket,
|
||||
open,
|
||||
onClose,
|
||||
openedSwitch,
|
||||
}) => {
|
||||
const findLineByOutlet = (outlet: TSelectedOutlet) => {
|
||||
return stationAPI.lines.find(
|
||||
|
|
@ -58,12 +51,6 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
>([]);
|
||||
const [isSubmit, setIsSubmit] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
setListOutletSelected([]);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const detectOutlet = (
|
||||
apc: APCProps,
|
||||
lines: string[],
|
||||
|
|
@ -195,12 +182,12 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
};
|
||||
|
||||
const RenderAPCStatus = (apc: APCProps) => {
|
||||
switch (apc.status) {
|
||||
switch (apc?.status) {
|
||||
case "CONNECTED":
|
||||
return (
|
||||
<>
|
||||
<Text size="sm" fw={800} c="green">
|
||||
{apc.status}
|
||||
<Text fw={800} c="green" fz={"12px"}>
|
||||
{apc?.status}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
|
|
@ -208,26 +195,24 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
case "DISCONNECTED":
|
||||
return (
|
||||
<>
|
||||
<div></div>
|
||||
|
||||
<Text size="sm" fw={800} c="red">
|
||||
{apc.status}
|
||||
<Text fw={800} c="red" fz={"12px"}>
|
||||
{apc?.status}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
case "TIMEOUT":
|
||||
return (
|
||||
<>
|
||||
<Text size="sm" fw={800} c="yellow">
|
||||
{apc.status}
|
||||
<Text fw={800} c="yellow" fz={"12px"}>
|
||||
{apc?.status}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<>
|
||||
{/* <Text size="sm" fw={800} c="blue">
|
||||
{line.status}
|
||||
{/* <Text fw={800} c="red" fz={"12px"}>
|
||||
WRONG CONFIG
|
||||
</Text> */}
|
||||
</>
|
||||
);
|
||||
|
|
@ -235,48 +220,15 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
style={{ position: "absolute", left: 0 }}
|
||||
opened={open}
|
||||
onClose={onClose}
|
||||
title={
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
APC Control
|
||||
<div style={{ marginLeft: "12px" }}>
|
||||
<Button
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
variant="filled"
|
||||
color="blue"
|
||||
onClick={() => {
|
||||
if (openedSwitch) openedSwitch();
|
||||
}}
|
||||
>
|
||||
Switch Control
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
size="xs"
|
||||
position="bottom"
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<fieldset style={{ padding: "4px 6px" }}>
|
||||
<legend>
|
||||
<div className={classes.titleAPC}>
|
||||
<Text fw={700} c={"#514d4d"} fz={"sm"}>
|
||||
<Text fw={700} c={"#514d4d"} fz={"xs"}>
|
||||
APC 1
|
||||
</Text>
|
||||
{dataStation?.apc1?.status &&
|
||||
RenderAPCStatus(dataStation?.apc1)}
|
||||
{RenderAPCStatus(dataStation?.apc1)}
|
||||
{dataStation?.apc1?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc1?.status === "TIMEOUT" ? (
|
||||
<Button
|
||||
|
|
@ -320,12 +272,11 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
className={`${isSubmit ? classes.isDisabled : ""}`}
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "90px",
|
||||
width: "80px",
|
||||
cursor: "pointer",
|
||||
textAlign: "center",
|
||||
border: listOutletSelected.find(
|
||||
(el) =>
|
||||
el.name === outlet.name && el.apc === outlet.apc
|
||||
(el) => el.name === outlet.name && el.apc === outlet.apc
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
|
|
@ -336,7 +287,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
>
|
||||
<Text
|
||||
fw={500}
|
||||
fz={"14px"}
|
||||
fz={"12px"}
|
||||
style={{
|
||||
color: outlet.status === "ON" ? "#40c057" : "#f03e3e",
|
||||
}}
|
||||
|
|
@ -352,7 +303,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "left",
|
||||
marginTop: "20px",
|
||||
marginTop: "10px",
|
||||
marginBottom: "10px",
|
||||
gap: "20px",
|
||||
}}
|
||||
|
|
@ -368,7 +319,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
|
|
@ -410,7 +361,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
|
|
@ -454,7 +405,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
|
|
@ -498,7 +449,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
|
|
@ -531,11 +482,10 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
<fieldset style={{ padding: "4px 6px" }}>
|
||||
<legend>
|
||||
<div className={classes.titleAPC}>
|
||||
<Text fw={700} c={"#514d4d"} fz={"sm"}>
|
||||
<Text fw={700} c={"#514d4d"} fz={"xs"}>
|
||||
APC 2
|
||||
</Text>
|
||||
{dataStation?.apc2?.status &&
|
||||
RenderAPCStatus(dataStation?.apc2)}
|
||||
{RenderAPCStatus(dataStation?.apc2)}
|
||||
{dataStation?.apc2?.status === "DISCONNECTED" ||
|
||||
dataStation?.apc2?.status === "TIMEOUT" ? (
|
||||
<Button
|
||||
|
|
@ -579,12 +529,11 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
className={`${isSubmit ? classes.isDisabled : ""}`}
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "90px",
|
||||
width: "80px",
|
||||
cursor: "pointer",
|
||||
textAlign: "center",
|
||||
border: listOutletSelected.find(
|
||||
(el) =>
|
||||
el.name === outlet.name && el.apc === outlet.apc
|
||||
(el) => el.name === outlet.name && el.apc === outlet.apc
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
|
|
@ -595,7 +544,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
>
|
||||
<Text
|
||||
fw={500}
|
||||
fz={"14px"}
|
||||
fz={"12px"}
|
||||
style={{
|
||||
color: outlet.status === "ON" ? "#40c057" : "#f03e3e",
|
||||
}}
|
||||
|
|
@ -611,7 +560,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "left",
|
||||
marginTop: "20px",
|
||||
marginTop: "10px",
|
||||
marginBottom: "10px",
|
||||
gap: "20px",
|
||||
}}
|
||||
|
|
@ -627,7 +576,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (
|
||||
|
|
@ -669,7 +618,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
|
|
@ -714,7 +663,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
|
|
@ -758,7 +707,7 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
|
|
@ -788,16 +737,12 @@ export const DrawerAPCControl: React.FC<DrawerProps> = ({
|
|||
</fieldset>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||
stationAPI,
|
||||
socket,
|
||||
open,
|
||||
onClose,
|
||||
openedAPC,
|
||||
}) => {
|
||||
const [listPorts, setListPorts] = useState<SwitchPortsProps[][]>([]);
|
||||
const [dataStation, setDataStation] = useState<TStation>(stationAPI);
|
||||
|
|
@ -903,100 +848,10 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
style={{ position: "absolute", left: 0 }}
|
||||
opened={open}
|
||||
onClose={onClose}
|
||||
title={
|
||||
dataStation?.switch ? (
|
||||
<div className={classes.titleAPC}>
|
||||
<Text fw={700} c={"#514d4d"} fz={"sm"}>
|
||||
Switch Control
|
||||
</Text>
|
||||
{dataStation?.switch?.status &&
|
||||
RenderAPCStatus(dataStation?.switch)}
|
||||
{dataStation?.switch?.status === "DISCONNECTED" ||
|
||||
dataStation?.switch?.status === "TIMEOUT" ? (
|
||||
<Button
|
||||
size="xs"
|
||||
disabled={isSubmit}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
socket?.emit("control_switch", {
|
||||
ports:
|
||||
listPortsSelected?.length > 0
|
||||
? listPortsSelected.map((el) => el.name)
|
||||
: listPorts.flat().map((el) => el.name),
|
||||
command: "reconnect",
|
||||
station: stationAPI,
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
setIsSubmit(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmit(false);
|
||||
}, 10000);
|
||||
}}
|
||||
>
|
||||
<IconRepeat size={14} />
|
||||
</Button>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
variant="filled"
|
||||
color="blue"
|
||||
onClick={() => {
|
||||
if (openedAPC) openedAPC();
|
||||
}}
|
||||
>
|
||||
APC Control
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
Switch Control
|
||||
<div style={{ marginLeft: "12px" }}>
|
||||
<Button
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="blue"
|
||||
onClick={() => {
|
||||
if (openedAPC) openedAPC();
|
||||
}}
|
||||
>
|
||||
APC Control
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
size="sm"
|
||||
position="bottom"
|
||||
>
|
||||
{loading ? (
|
||||
return loading ? (
|
||||
<Box
|
||||
style={{
|
||||
height: "300px",
|
||||
height: "10vh",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
|
|
@ -1007,107 +862,6 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
</Box>
|
||||
) : (
|
||||
<Grid>
|
||||
<Grid.Col span={12}>
|
||||
{listPorts?.length > 0 && (
|
||||
<Box>
|
||||
<Grid>
|
||||
{listPorts?.map((group, key) => (
|
||||
<Grid.Col
|
||||
key={key}
|
||||
span={
|
||||
group?.length > 20
|
||||
? 11
|
||||
: group?.length > 0 && group?.length < 4
|
||||
? 1
|
||||
: 12
|
||||
}
|
||||
>
|
||||
<fieldset
|
||||
style={{
|
||||
padding: "4px 6px",
|
||||
paddingBottom: "12px",
|
||||
height: "-webkit-fill-available",
|
||||
}}
|
||||
>
|
||||
<legend>
|
||||
<Text fw={700} c={"#514d4d"} fz={"sm"}>
|
||||
{group[0]?.name.substring(0, 2) || ""}
|
||||
</Text>
|
||||
</legend>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
gap: "10px",
|
||||
overflowY: "auto",
|
||||
maxHeight: "300px",
|
||||
}}
|
||||
>
|
||||
{group?.length > 0 &&
|
||||
sortedPorts(group)?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
shadow="sm"
|
||||
padding="xs"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "60px",
|
||||
backgroundColor:
|
||||
port.poe === "ON"
|
||||
? "#f2dcf8"
|
||||
: port.status === "ON"
|
||||
? "#d4f1d3"
|
||||
: "#f5f5f5",
|
||||
cursor: "pointer",
|
||||
border: listPortsSelected.find(
|
||||
(el) => el.name === port.name
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
}}
|
||||
className={`${
|
||||
isSubmit ? classes.isDisabled : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
toggleSelect(port);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "2px",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<IconSection
|
||||
size={"18px"}
|
||||
color={
|
||||
port.poe === "ON"
|
||||
? "#b722d4"
|
||||
: port.status === "ON"
|
||||
? "#40c057"
|
||||
: "#b8b8b8"
|
||||
}
|
||||
/>
|
||||
<Text fw={500} fz={"12px"}>
|
||||
{port.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
</fieldset>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
</Grid.Col>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
|
|
@ -1126,6 +880,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
<Box ps={"8px"} pt={"4px"}>
|
||||
{dataStation?.switch ? RenderAPCStatus(dataStation?.switch) : ""}
|
||||
</Box>
|
||||
<Button
|
||||
disabled={isSubmit}
|
||||
title={
|
||||
|
|
@ -1136,7 +893,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
onClick={() => {
|
||||
if (listPortsSelected.length === listPorts.flat().length) {
|
||||
|
|
@ -1169,7 +926,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="yellow"
|
||||
onClick={() => {
|
||||
|
|
@ -1177,9 +934,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
listPortsSelected?.length > 0
|
||||
? listPortsSelected
|
||||
: listPorts.flat();
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe !== "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe !== "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe !== "ON")
|
||||
|
|
@ -1188,9 +943,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
station: stationAPI,
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe === "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe === "ON")
|
||||
|
|
@ -1229,7 +982,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
|
|
@ -1237,9 +990,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
listPortsSelected?.length > 0
|
||||
? listPortsSelected
|
||||
: listPorts.flat();
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe !== "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe !== "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe !== "ON")
|
||||
|
|
@ -1248,9 +999,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
station: stationAPI,
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe === "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe === "ON")
|
||||
|
|
@ -1289,7 +1038,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
// mt={'xs'}
|
||||
miw={"80px"}
|
||||
size="xs"
|
||||
fz={"sm"}
|
||||
fz={"xs"}
|
||||
variant="filled"
|
||||
color="red"
|
||||
onClick={() => {
|
||||
|
|
@ -1297,9 +1046,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
listPortsSelected?.length > 0
|
||||
? listPortsSelected
|
||||
: listPorts.flat();
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe !== "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe !== "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe !== "ON")
|
||||
|
|
@ -1308,9 +1055,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
station: stationAPI,
|
||||
ip: stationAPI?.switch_control_ip,
|
||||
});
|
||||
if (
|
||||
listPortsRestart.filter((el) => el.poe === "ON").length > 0
|
||||
)
|
||||
if (listPortsRestart.filter((el) => el.poe === "ON").length > 0)
|
||||
socket?.emit("control_switch", {
|
||||
ports: listPortsRestart
|
||||
.filter((el) => el.poe === "ON")
|
||||
|
|
@ -1333,8 +1078,106 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
|||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Grid.Col span={12} pt={0}>
|
||||
{listPorts?.length > 0 && (
|
||||
<Box>
|
||||
<Grid>
|
||||
{listPorts?.map((group, key) => (
|
||||
<Grid.Col
|
||||
key={key}
|
||||
span={
|
||||
group?.length > 20
|
||||
? 11
|
||||
: group?.length > 0 && group?.length < 4
|
||||
? 1
|
||||
: 12
|
||||
}
|
||||
>
|
||||
<fieldset
|
||||
style={{
|
||||
padding: "4px 6px",
|
||||
paddingBottom: "12px",
|
||||
height: "-webkit-fill-available",
|
||||
}}
|
||||
>
|
||||
<legend>
|
||||
<Text fw={700} c={"#514d4d"} fz={"xs"}>
|
||||
{group[0]?.name.substring(0, 2) || ""}
|
||||
</Text>
|
||||
</legend>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
gap: "10px",
|
||||
overflowY: "auto",
|
||||
maxHeight: "100px",
|
||||
}}
|
||||
>
|
||||
{group?.length > 0 &&
|
||||
sortedPorts(group)?.map((port, i) => (
|
||||
<Card
|
||||
key={i}
|
||||
shadow="sm"
|
||||
padding="xs"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "60px",
|
||||
backgroundColor:
|
||||
port.poe === "ON"
|
||||
? "#f2dcf8"
|
||||
: port.status === "ON"
|
||||
? "#d4f1d3"
|
||||
: "#f5f5f5",
|
||||
cursor: "pointer",
|
||||
border: listPortsSelected.find(
|
||||
(el) => el.name === port.name
|
||||
)?.name
|
||||
? "1px solid #0018ff"
|
||||
: "",
|
||||
}}
|
||||
className={`${isSubmit ? classes.isDisabled : ""}`}
|
||||
onClick={() => {
|
||||
toggleSelect(port);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "2px",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<IconSection
|
||||
size={"12px"}
|
||||
color={
|
||||
port.poe === "ON"
|
||||
? "#b722d4"
|
||||
: port.status === "ON"
|
||||
? "#40c057"
|
||||
: "#b8b8b8"
|
||||
}
|
||||
/>
|
||||
<Text fw={500} fz={"11px"}>
|
||||
{port.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
</fieldset>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
</Drawer>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ function DrawerLogs({
|
|||
</Drawer>
|
||||
|
||||
<Button
|
||||
style={{ height: "30px", width: "100px" }}
|
||||
title="Add Scenario"
|
||||
variant="outline"
|
||||
// color="green"
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ const TerminalCLI: React.FC<TerminalCLIProps> = ({
|
|||
loadingContent = false,
|
||||
onFocus,
|
||||
onBlur,
|
||||
line,
|
||||
}) => {
|
||||
const xtermRef = useRef<HTMLDivElement>(null);
|
||||
const terminal = useRef<Terminal>(null);
|
||||
|
|
|
|||
Loading…
Reference in New Issue