334 lines
8.0 KiB
TypeScript
334 lines
8.0 KiB
TypeScript
import { useCallback, useRef } from "react";
|
|
|
|
export const numberOnly = (value: string): string => {
|
|
const matched = value.match(/[\d.]+/g);
|
|
return matched ? matched.join("") : "";
|
|
};
|
|
|
|
export const passwordRegex =
|
|
/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&#])[A-Za-z\d@$!%*?&#]{8,}$/;
|
|
|
|
export const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
|
|
|
|
export function isJsonString(str: string | null) {
|
|
if (typeof str !== "string") return false;
|
|
try {
|
|
const parsed = JSON.parse(str);
|
|
// Kiểm tra xem parsed có phải là object hoặc array thật sự
|
|
return parsed !== null && typeof parsed === "object";
|
|
} catch (e) {
|
|
console.log("Error isJsonString", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function mergeArray(array: any[], key: string) {
|
|
return array
|
|
.map((el) => el[key])
|
|
.flat()
|
|
.filter((el) => Object.keys(el).length > 0);
|
|
}
|
|
|
|
// Function to convert timestamp to date
|
|
export const convertTimestampToDate = (timestamp: number) => {
|
|
const date = new Date(Number(timestamp));
|
|
return date.toLocaleString();
|
|
};
|
|
|
|
/**
|
|
* Custom debounce hook.
|
|
* @param callback - Function to debounce.
|
|
* @param delay - Delay in milliseconds.
|
|
* @returns A debounced version of the callback.
|
|
*/
|
|
export const useDebounce = <T extends (...args: any[]) => void>(
|
|
callback: T,
|
|
delay: number,
|
|
) => {
|
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
|
|
const debouncedFn = useCallback(
|
|
(...args: Parameters<T>) => {
|
|
if (timer.current) {
|
|
clearTimeout(timer.current);
|
|
}
|
|
|
|
timer.current = setTimeout(() => {
|
|
callback(...args);
|
|
}, delay);
|
|
},
|
|
[callback, delay],
|
|
);
|
|
|
|
return debouncedFn;
|
|
};
|
|
|
|
export const handleStorageCommand = (command: string, lineId: number) => {
|
|
const storage = localStorage.getItem("history_commands");
|
|
const history: Record<number, string[]> = storage ? JSON.parse(storage) : {};
|
|
let commands = history[lineId] || [];
|
|
commands = [command, ...commands.filter((cmd) => cmd !== command)];
|
|
commands = commands.slice(0, 10);
|
|
history[lineId] = commands;
|
|
|
|
localStorage.setItem("history_commands", JSON.stringify(history));
|
|
};
|
|
|
|
export const handleGetStorageCommand = (lineId: number): string[] => {
|
|
const storage = localStorage.getItem("history_commands");
|
|
const history: Record<number, string[]> = storage ? JSON.parse(storage) : {};
|
|
return history[lineId] || [];
|
|
};
|
|
|
|
//Function convert bytes to MB
|
|
export function bytesToMB(bytes: number, decimal = 2): number {
|
|
return Number((bytes / (1024 * 1024)).toFixed(decimal));
|
|
}
|
|
|
|
//Function convert bytes to KB
|
|
export function bytesToKB(bytes: number, decimal = 2): number {
|
|
return Number((bytes / 1024).toFixed(decimal));
|
|
}
|
|
export const bodyDPELP = [
|
|
{
|
|
expect: "",
|
|
send: "",
|
|
delay: "1",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: " no",
|
|
delay: "1",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "\r\n",
|
|
delay: "1",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "\r\n",
|
|
delay: "2",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
// {
|
|
// expect: "",
|
|
// send: " terminal length 0",
|
|
// delay: "3",
|
|
// repeat: "1",
|
|
// note: "",
|
|
// },
|
|
{
|
|
expect: "",
|
|
send: "enable",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show inventory",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show version | include License",
|
|
delay: "1",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show version",
|
|
delay: "1",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show diag",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show post",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show env all",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show license",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show log",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
{
|
|
expect: "",
|
|
send: "show platform",
|
|
delay: "3",
|
|
repeat: "1",
|
|
note: "",
|
|
},
|
|
];
|
|
|
|
export function convertFromKilobytesString(
|
|
input: string,
|
|
decimals = 0,
|
|
): string {
|
|
if (!input) return "0 KB";
|
|
|
|
const parts = input.split("/");
|
|
if (parts.length === 0) return "0 KB";
|
|
|
|
// ---- Step 1: parse + cộng tất cả về KB ----
|
|
const toKB: Record<string, number> = {
|
|
K: 1,
|
|
M: 1024,
|
|
G: 1024 ** 2,
|
|
T: 1024 ** 3,
|
|
};
|
|
|
|
let totalKB = 0;
|
|
|
|
for (const part of parts) {
|
|
const trimmed = part.trim().toUpperCase();
|
|
const match = trimmed.match(/^([\d.]+)\s*(K|M|G|T)?B?$/);
|
|
|
|
if (!match) continue;
|
|
|
|
const value = Number.parseFloat(match[1]);
|
|
const unit = match[2] || "K";
|
|
|
|
totalKB += value * toKB[unit];
|
|
}
|
|
|
|
if (totalKB === 0) return "0 KB";
|
|
|
|
// ---- Step 2: convert KB -> đơn vị đẹp nhất ----
|
|
const units = ["KB", "MB", "GB", "TB"];
|
|
let unitIndex = 0;
|
|
let displayValue = totalKB;
|
|
|
|
while (displayValue >= 1024 && unitIndex < units.length - 1) {
|
|
displayValue /= 1024;
|
|
unitIndex++;
|
|
}
|
|
|
|
return `${displayValue.toFixed(decimals)} ${units[unitIndex]}`;
|
|
}
|
|
|
|
/**
|
|
* Hàm tách và rút gọn log Cisco (show inv, show version, show license)
|
|
* @param {string} rawLog - Chuỗi log thô ban đầu (chứa toàn bộ kết quả terminal)
|
|
* @returns {string} Chuỗi log đã được rút gọn theo định dạng yêu cầu
|
|
*/
|
|
export function createShortLog(rawLog: string): string {
|
|
const shortLog = [];
|
|
|
|
// 1. Tách show inventory
|
|
const invRegex =
|
|
/(NAME:\s*"[^"]*",\s*DESCR:\s*"[^"]*"\r?\nPID:\s*[^,]+,\s*VID:\s*[^,]+,\s*SN:\s*\S+)/i;
|
|
const invMatch = rawLog.match(invRegex);
|
|
if (invMatch) {
|
|
shortLog.push(invMatch[1].trim());
|
|
}
|
|
|
|
// 2. Tách show version (Đã fix vụ bỏ phần thừa ở giữa)
|
|
const verRegex =
|
|
/(System image file is[^\r\n]+)[\s\S]*?(cisco\s+[a-zA-Z0-9\-]+\s+\([^)]+\)\s+processor[\s\S]*?Configuration register is 0x[0-9a-fA-F]+)/i;
|
|
const verMatch = rawLog.match(verRegex);
|
|
if (verMatch) {
|
|
shortLog.push(`${verMatch[1].trim()}\n${verMatch[2].trim()}`);
|
|
}
|
|
|
|
// 3. Tách show license
|
|
const licRegex =
|
|
/(Index\s+1\s+Feature:[\s\S]*?)(?=\r?\n[a-zA-Z0-9\-\_]+[#>]|$)/i;
|
|
const licMatch = rawLog.match(licRegex);
|
|
if (licMatch) {
|
|
shortLog.push("\n" + licMatch[1].trim());
|
|
}
|
|
|
|
return shortLog.join("\n");
|
|
}
|
|
|
|
/**
|
|
* Hàm in log ra máy in vật lý trong môi trường Web (React/Vue/Vanilla)
|
|
* @param shortLog - Chuỗi log đã được rút gọn
|
|
*/
|
|
export function printLogWeb(shortLog: string): void {
|
|
if (!shortLog.trim()) {
|
|
console.warn("Không có dữ liệu để in.");
|
|
return;
|
|
}
|
|
|
|
// Mở một cửa sổ ẩn để in
|
|
const printWindow = window.open("", "_blank", "width=800,height=600");
|
|
if (!printWindow) {
|
|
console.error("Trình duyệt đã chặn popup. Vui lòng cho phép popup để in.");
|
|
return;
|
|
}
|
|
|
|
// Ghi nội dung HTML với font monospace (giống terminal)
|
|
printWindow.document.write(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Cisco Short Log</title>
|
|
<style>
|
|
body {
|
|
font-family: 'Courier New', Courier, monospace;
|
|
font-size: 12px;
|
|
padding: 20px;
|
|
color: #000;
|
|
}
|
|
pre {
|
|
white-space: pre-wrap; /* Tự động xuống dòng nếu quá dài */
|
|
word-wrap: break-word;
|
|
}
|
|
@media print {
|
|
@page { margin: 1cm; }
|
|
body { padding: 0; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<pre>${shortLog}</pre>
|
|
</body>
|
|
</html>
|
|
`);
|
|
|
|
printWindow.document.close();
|
|
printWindow.focus();
|
|
|
|
// Gọi lệnh in và đóng cửa sổ sau khi in xong (hoặc hủy)
|
|
printWindow.print();
|
|
printWindow.onafterprint = () => printWindow.close();
|
|
}
|