ATC_SIMPLE/FRONTEND/src/untils/helper.ts

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();
}