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