File core-utils.js of Package PersistenceOS
/**
* PersistenceOS Core Utilities Module
* Shared utilities, common functions, and base configurations
*
* This module provides the foundation for all other dashboard modules
* and handles common functionality like notifications, API calls, and utilities.
*/
// =============================================================================
// CORE CONFIGURATION
// =============================================================================
const PERSISTENCE_CONFIG = {
API_BASE_URL: '/api',
NOTIFICATION_TIMEOUT: 3000,
REFRESH_INTERVALS: {
SYSTEM_STATS: 30000,
VM_DATA: 15000,
NETWORK_DATA: 20000,
STORAGE_DATA: 25000,
SNAPSHOT_DATA: 30000
},
UI_CONSTANTS: {
SIDEBAR_COLLAPSED_KEY: 'persistence_sidebar_collapsed',
ACTIVE_SECTION_KEY: 'persistence_active_section'
}
};
// =============================================================================
// NOTIFICATION SYSTEM
// =============================================================================
/**
* Show notification to user
* @param {string} message - Message to display
* @param {string} type - Notification type: 'success', 'error', 'info', 'warning'
*/
function showNotification(message, type = 'info') {
const colors = {
success: '#28a745',
error: '#dc3545',
info: '#17a2b8',
warning: '#ffc107'
};
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: ${colors[type]};
color: white;
padding: 12px 20px;
border-radius: 6px;
z-index: 10001;
font-family: Arial, sans-serif;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
animation: slideInDown 0.3s ease-out;
`;
notification.textContent = message;
// Add animation styles
if (!document.getElementById('notification-styles')) {
const style = document.createElement('style');
style.id = 'notification-styles';
style.textContent = `
@keyframes slideInDown {
from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
`;
document.head.appendChild(style);
}
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'slideInDown 0.3s ease-out reverse';
setTimeout(() => notification.remove(), 300);
}, PERSISTENCE_CONFIG.NOTIFICATION_TIMEOUT);
}
// =============================================================================
// API UTILITIES
// =============================================================================
/**
* Make authenticated API request
* @param {string} endpoint - API endpoint
* @param {object} options - Fetch options
* @returns {Promise<Response>}
*/
async function makeApiRequest(endpoint, options = {}) {
const token = localStorage.getItem('access_token');
const defaultHeaders = {
'Content-Type': 'application/json',
...(token && { 'Authorization': `Bearer ${token}` })
};
const config = {
...options,
headers: {
...defaultHeaders,
...options.headers
}
};
const url = endpoint.startsWith('http') ? endpoint : `${PERSISTENCE_CONFIG.API_BASE_URL}${endpoint}`;
try {
const response = await fetch(url, config);
// Handle authentication errors
if (response.status === 401) {
console.warn('Authentication failed, redirecting to login');
localStorage.removeItem('access_token');
window.location.href = '/login.html';
throw new Error('Authentication required');
}
return response;
} catch (error) {
console.error(`API request failed for ${endpoint}:`, error);
throw error;
}
}
/**
* Make GET request to API
* @param {string} endpoint - API endpoint
* @returns {Promise<any>}
*/
async function apiGet(endpoint) {
const response = await makeApiRequest(endpoint);
if (!response.ok) {
throw new Error(`GET ${endpoint} failed: ${response.status} ${response.statusText}`);
}
return await response.json();
}
/**
* Make POST request to API
* @param {string} endpoint - API endpoint
* @param {any} data - Request body data
* @returns {Promise<any>}
*/
async function apiPost(endpoint, data) {
const response = await makeApiRequest(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`POST ${endpoint} failed: ${response.status} ${response.statusText}`);
}
return await response.json();
}
/**
* Make DELETE request to API
* @param {string} endpoint - API endpoint
* @returns {Promise<any>}
*/
async function apiDelete(endpoint) {
const response = await makeApiRequest(endpoint, {
method: 'DELETE'
});
if (!response.ok) {
throw new Error(`DELETE ${endpoint} failed: ${response.status} ${response.statusText}`);
}
return await response.json();
}
// =============================================================================
// UTILITY FUNCTIONS
// =============================================================================
/**
* Format bytes to human readable format
* @param {number} bytes - Number of bytes
* @param {number} decimals - Number of decimal places
* @returns {string}
*/
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
/**
* Get color based on usage percentage
* @param {number} percentage - Usage percentage (0-100)
* @returns {string} - CSS color value
*/
function getUsageColor(percentage) {
if (percentage < 50) return '#28a745'; // Green
if (percentage < 80) return '#ffc107'; // Yellow
return '#dc3545'; // Red
}
/**
* Debounce function calls
* @param {Function} func - Function to debounce
* @param {number} wait - Wait time in milliseconds
* @returns {Function}
*/
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* Format timestamp to readable date
* @param {string|Date} timestamp - Timestamp to format
* @returns {string}
*/
function formatTimestamp(timestamp) {
const date = new Date(timestamp);
return date.toLocaleString();
}
/**
* Validate required fields in an object
* @param {object} obj - Object to validate
* @param {string[]} requiredFields - Array of required field names
* @returns {boolean}
*/
function validateRequiredFields(obj, requiredFields) {
return requiredFields.every(field =>
obj.hasOwnProperty(field) &&
obj[field] !== null &&
obj[field] !== undefined &&
obj[field] !== ''
);
}
// =============================================================================
// LOCAL STORAGE UTILITIES
// =============================================================================
/**
* Get item from localStorage with JSON parsing
* @param {string} key - Storage key
* @param {any} defaultValue - Default value if key doesn't exist
* @returns {any}
*/
function getStorageItem(key, defaultValue = null) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch (error) {
console.warn(`Failed to parse localStorage item ${key}:`, error);
return defaultValue;
}
}
/**
* Set item in localStorage with JSON stringification
* @param {string} key - Storage key
* @param {any} value - Value to store
*/
function setStorageItem(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(`Failed to set localStorage item ${key}:`, error);
}
}
// =============================================================================
// EXPORT FOR MODULE SYSTEM
// =============================================================================
// Export all utilities for use by other modules
window.PersistenceCore = {
config: PERSISTENCE_CONFIG,
showNotification,
makeApiRequest,
apiGet,
apiPost,
apiDelete,
formatBytes,
getUsageColor,
debounce,
formatTimestamp,
validateRequiredFields,
getStorageItem,
setStorageItem
};
console.log('✅ PersistenceOS Core Utilities Module loaded');