Files
I-Fun c649f055d8 feat: initialize Infra Manager with React, Tailwind CSS, and Inertia.js
- Added main application entry point (app.jsx) and bootstrap file for React setup.
- Created Wiki index page (Index.jsx) for documentation and file management.
- Implemented utility functions for formatting and status handling in utils.js.
- Set up Blade template (app.blade.php) for Inertia.js integration.
- Defined API routes for metrics and terminal access in api.php.
- Established console commands for scheduled tasks in console.php.
- Created web routes for various application features including authentication, hypervisors, containers, cloud accounts, security, backups, and wiki management in web.php.
- Developed setup scripts for Windows (setup.ps1) and Linux (setup.sh) environments.
- Configured Tailwind CSS for styling with custom themes and animations in tailwind.config.js.
- Set up Vite for asset bundling and development server in vite.config.js.
2026-04-07 20:29:32 +07:00

72 lines
2.2 KiB
JavaScript

import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
export function formatBytes(bytes, decimals = 2) {
if (!bytes || bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
export function formatUptime(seconds) {
const d = Math.floor(seconds / 86400);
const h = Math.floor((seconds % 86400) / 3600);
const m = Math.floor((seconds % 3600) / 60);
if (d > 0) return `${d}d ${h}h`;
if (h > 0) return `${h}h ${m}m`;
return `${m}m`;
}
export function getStatusColor(status) {
const map = {
online: 'text-green-400',
running: 'text-cyan-400',
active: 'text-green-400',
stopped: 'text-slate-400',
offline: 'text-red-400',
error: 'text-red-400',
warning: 'text-yellow-400',
unknown: 'text-gray-400',
paused: 'text-yellow-400',
exited: 'text-slate-400',
};
return map[status?.toLowerCase()] ?? 'text-gray-400';
}
export function getStatusDot(status) {
const map = {
online: 'bg-green-400',
running: 'bg-cyan-400',
active: 'bg-green-400',
stopped: 'bg-slate-500',
offline: 'bg-red-400',
error: 'bg-red-400',
warning: 'bg-yellow-400',
unknown: 'bg-gray-500',
paused: 'bg-yellow-400',
exited: 'bg-slate-500',
};
return map[status?.toLowerCase()] ?? 'bg-gray-500';
}
export function getSecurityGradeColor(grade) {
const map = { A: 'text-green-400', B: 'text-cyan-400', C: 'text-yellow-400', D: 'text-orange-400', F: 'text-red-400' };
return map[grade] ?? 'text-gray-400';
}
export function timeAgo(date) {
if (!date) return 'Never';
const d = new Date(date);
const seconds = Math.floor((new Date() - d) / 1000);
if (seconds < 60) return `${seconds}s ago`;
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
return `${Math.floor(seconds / 86400)}d ago`;
}