UNPKG

besper-frontend-site-dev-main

Version:

Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment

303 lines (265 loc) 8.26 kB
/** * Storage Indicator Component * Displays storage usage information for the bot's knowledge base */ export class StorageIndicator { constructor(widget, state, i18n = null) { this.widget = widget; this.state = state; this.i18n = i18n; this.maxStorageMB = 1024; // 1GB default limit } /** * Update language * @param {string} language - New language code */ updateLanguage(language) { if (this.i18n) { console.log(`[StorageIndicator] Language updated to: ${language}`); } } /** * Get translated text * @param {string} key - Translation key * @param {Object} variables - Variables for substitution * @returns {string} Translated text */ t(key, variables = {}) { return this.i18n ? this.i18n.t(key, variables) : key; } /** * Generate the HTML for the storage indicator * @returns {string} Storage indicator HTML string */ getHTML() { return ` <div class="bm-storage-info" id="bm-storageInfo"> <div class="bm-storage-bar"> <div class="bm-storage-used" id="bm-storageUsed" style="width: 0%"></div> </div> <span class="bm-storage-text" id="bm-storageText">0 MB / ${this.maxStorageMB} MB used</span> </div> `; } /** * Update storage display with current usage * @param {Object} storageUsage - Storage usage data */ updateDisplay(storageUsage) { const storageUsed = this.widget.querySelector('#bm-storageUsed'); const storageText = this.widget.querySelector('#bm-storageText'); if (!storageUsage || !storageUsed || !storageText) return; const usedMB = Math.round(storageUsage.total_size_bytes / (1024 * 1024)); const percentage = Math.min((usedMB / this.maxStorageMB) * 100, 100); // Update visual indicator storageUsed.style.width = `${percentage}%`; // Update text const itemsText = storageUsage.total_items ? ` (${storageUsage.total_items} ${this.t('storage.items').toLowerCase()})` : ''; storageText.textContent = this.t('storage.storageUsed', { used: usedMB, total: this.maxStorageMB, }) + itemsText; // Update color based on usage storageUsed.style.background = this.getUsageColor(percentage); // Store current usage this.currentUsage = { usedMB, percentage, totalItems: storageUsage.total_items || 0, }; } /** * Get color based on usage percentage * @param {number} percentage - Usage percentage * @returns {string} CSS color value */ getUsageColor(percentage) { if (percentage > 90) { return '#ef4444'; // Red - Critical } else if (percentage > 75) { return '#f59e0b'; // Orange - Warning } else if (percentage > 50) { return '#3b82f6'; // Blue - Normal } else { return '#10b981'; // Green - Good } } /** * Get usage status text * @param {number} percentage - Usage percentage * @returns {string} Status text */ getUsageStatus(percentage) { if (percentage > 90) { return this.t('storage.criticalStatus'); } else if (percentage > 75) { return this.t('storage.warningStatus'); } else if (percentage > 50) { return this.t('storage.normalStatus'); } else { return this.t('storage.goodStatus'); } } /** * Show detailed storage information * @returns {Object} Detailed storage info */ getDetailedInfo() { if (!this.currentUsage) { return { usedMB: 0, availableMB: this.maxStorageMB, percentage: 0, status: this.t('storage.noDataAvailable'), totalItems: 0, }; } const availableMB = this.maxStorageMB - this.currentUsage.usedMB; const status = this.getUsageStatus(this.currentUsage.percentage); return { usedMB: this.currentUsage.usedMB, availableMB: Math.max(0, availableMB), percentage: this.currentUsage.percentage, status, totalItems: this.currentUsage.totalItems, }; } /** * Check if storage is near capacity * @param {number} threshold - Percentage threshold (default: 80) * @returns {boolean} Whether storage is near capacity */ isNearCapacity(threshold = 80) { return this.currentUsage && this.currentUsage.percentage >= threshold; } /** * Check if storage is at capacity * @param {number} threshold - Percentage threshold (default: 95) * @returns {boolean} Whether storage is at capacity */ isAtCapacity(threshold = 95) { return this.currentUsage && this.currentUsage.percentage >= threshold; } /** * Reset storage display */ reset() { const storageUsed = this.widget.querySelector('#bm-storageUsed'); const storageText = this.widget.querySelector('#bm-storageText'); if (storageUsed) { storageUsed.style.width = '0%'; storageUsed.style.background = '#10b981'; } if (storageText) { storageText.textContent = this.t('storage.storageUsed', { used: 0, total: this.maxStorageMB, }); } this.currentUsage = null; } /** * Show loading state */ showLoading() { const storageText = this.widget.querySelector('#bm-storageText'); if (storageText) { storageText.textContent = this.t('storage.loadingInfo'); } } /** * Show error state * @param {string} message - Error message */ showError(message = null) { const errorMessage = message || this.t('storage.failedToLoad'); const storageText = this.widget.querySelector('#bm-storageText'); if (storageText) { storageText.textContent = errorMessage; storageText.style.color = '#ef4444'; } } /** * Add tooltip with detailed information */ addTooltip() { const storageInfo = this.widget.querySelector('#bm-storageInfo'); if (!storageInfo) return; storageInfo.addEventListener('mouseenter', () => { this.showTooltip(); }); storageInfo.addEventListener('mouseleave', () => { this.hideTooltip(); }); } /** * Show tooltip with detailed storage information */ showTooltip() { // Remove existing tooltip this.hideTooltip(); const info = this.getDetailedInfo(); const tooltip = document.createElement('div'); tooltip.className = 'bm-storage-tooltip'; tooltip.innerHTML = ` <div class="bm-tooltip-content"> <div class="besper-h4">${this.t('storage.storageDetails')}</div> <div class="besper-p"><strong>${this.t('storage.used')}:</strong> ${info.usedMB} MB</div> <div class="besper-p"><strong>${this.t('storage.available')}:</strong> ${info.availableMB} MB</div> <div class="besper-p"><strong>${this.t('storage.usage')}:</strong> ${info.percentage.toFixed(1)}%</div> <div class="besper-p"><strong>${this.t('storage.items')}:</strong> ${info.totalItems}</div> <div class="besper-p"><strong>${this.t('storage.status')}:</strong> ${info.status}</div> </div> `; const storageInfo = this.widget.querySelector('#bm-storageInfo'); if (storageInfo) { storageInfo.appendChild(tooltip); this.currentTooltip = tooltip; } } /** * Hide tooltip */ hideTooltip() { if (this.currentTooltip) { this.currentTooltip.remove(); this.currentTooltip = null; } } /** * Set storage limit * @param {number} limitMB - Storage limit in MB */ setStorageLimit(limitMB) { this.maxStorageMB = limitMB; // Update display if we have current usage if (this.currentUsage) { const storageUsage = { total_size_bytes: this.currentUsage.usedMB * 1024 * 1024, total_items: this.currentUsage.totalItems, }; this.updateDisplay(storageUsage); } } /** * Format bytes to human readable format * @param {number} bytes - Bytes to format * @returns {string} Formatted string */ static formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; } /** * Cleanup method for component destruction */ destroy() { this.hideTooltip(); } }