Merge pull request #132 from gbw/fix/unlimited-storage-quota-display
fix: display unlimited quota (∞) when storage_quota_bytes = 0
This commit is contained in:
@@ -367,6 +367,16 @@ pub fn format_file_size(bytes: u64) -> String {
|
||||
format!("{} {}", formatted, SIZES[i])
|
||||
}
|
||||
|
||||
/// Formats a byte count for quota display. When bytes is 0, returns "∞" (unlimited).
|
||||
///
|
||||
/// Matches the JavaScript `formatQuotaSize()` output.
|
||||
pub fn format_quota_size(bytes: u64) -> String {
|
||||
if bytes == 0 {
|
||||
return "∞".to_string();
|
||||
}
|
||||
format_file_size(bytes)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -382,6 +392,15 @@ mod tests {
|
||||
assert_eq!(format_file_size(1_073_741_824), "1 GB");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_quota_size() {
|
||||
// Unlimited quota (0) should show infinity symbol
|
||||
assert_eq!(format_quota_size(0), "∞");
|
||||
// Non-zero values should format normally
|
||||
assert_eq!(format_quota_size(500), "500 Bytes");
|
||||
assert_eq!(format_quota_size(1_073_741_824), "1 GB");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_icon_class_for_with_extension_fallback() {
|
||||
// Specific MIME types
|
||||
|
||||
@@ -567,7 +567,8 @@ function updateStorageUsageDisplay(userData) {
|
||||
// Get values from user data if available
|
||||
if (userData) {
|
||||
usedBytes = userData.storage_used_bytes || 0;
|
||||
quotaBytes = userData.storage_quota_bytes || DEFAULT_QUOTA;
|
||||
// Use == null to allow 0 (unlimited) to pass through; only default to DEFAULT_QUOTA when null/undefined
|
||||
quotaBytes = userData.storage_quota_bytes == null ? DEFAULT_QUOTA : userData.storage_quota_bytes;
|
||||
|
||||
// Calculate percentage (avoid division by zero)
|
||||
if (quotaBytes > 0) {
|
||||
@@ -577,7 +578,7 @@ function updateStorageUsageDisplay(userData) {
|
||||
|
||||
// Format the numbers for display
|
||||
const usedFormatted = formatFileSize(usedBytes);
|
||||
const quotaFormatted = formatFileSize(quotaBytes);
|
||||
const quotaFormatted = formatQuotaSize(quotaBytes);
|
||||
|
||||
// Update the storage display elements
|
||||
const storageFill = document.querySelector('.storage-fill');
|
||||
|
||||
@@ -135,14 +135,14 @@ function updateUserMenuData() {
|
||||
}
|
||||
|
||||
const usedBytes = userData.storage_used_bytes || 0;
|
||||
const quotaBytes = userData.storage_quota_bytes || (10 * 1024 * 1024 * 1024);
|
||||
const quotaBytes = userData.storage_quota_bytes == null ? (10 * 1024 * 1024 * 1024) : userData.storage_quota_bytes;
|
||||
const percentage = quotaBytes > 0 ? Math.min(Math.round((usedBytes / quotaBytes) * 100), 100) : 0;
|
||||
|
||||
if (storageFill) storageFill.style.width = percentage + '%';
|
||||
if (storageText) {
|
||||
const used = window.formatFileSize(usedBytes);
|
||||
const total = window.formatFileSize(quotaBytes);
|
||||
storageText.textContent = `${percentage}% · ${used} / ${total}`;
|
||||
const total = window.formatQuotaSize(quotaBytes);
|
||||
storageText.textContent = `${quotaBytes > 0 ? `${percentage}% · ` : ''}${used} / ${total}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ function showUserProfileModal() {
|
||||
const role = userData.role || 'user';
|
||||
const initials = username.substring(0, 2).toUpperCase();
|
||||
const usedBytes = userData.storage_used_bytes || 0;
|
||||
const quotaBytes = userData.storage_quota_bytes || (10 * 1024 * 1024 * 1024);
|
||||
const quotaBytes = userData.storage_quota_bytes == null ? (10 * 1024 * 1024 * 1024) : userData.storage_quota_bytes;
|
||||
const percentage = quotaBytes > 0 ? Math.min(Math.round((usedBytes / quotaBytes) * 100), 100) : 0;
|
||||
const barColor = percentage > 90 ? '#ef4444' : percentage > 70 ? '#f59e0b' : '#22c55e';
|
||||
|
||||
@@ -200,7 +200,7 @@ function showUserProfileModal() {
|
||||
<div style="background:#f1f5f9;border-radius:6px;height:8px;overflow:hidden;margin-bottom:4px">
|
||||
<div style="height:100%;width:${percentage}%;background:${barColor};border-radius:6px;transition:width .3s"></div>
|
||||
</div>
|
||||
<div style="font-size:12px;color:#64748b;text-align:right">${percentage}% · ${window.formatFileSize(usedBytes)} / ${quotaBytes > 0 ? window.formatFileSize(quotaBytes) : '∞'}</div>
|
||||
<div style="font-size:12px;color:#64748b;text-align:right">${percentage}% · ${window.formatFileSize(usedBytes)} / ${window.formatQuotaSize(quotaBytes)}</div>
|
||||
</div>
|
||||
<div style="padding:0 20px 16px;display:flex;justify-content:center">
|
||||
<button id="profile-modal-close" style="padding:8px 24px;border:1px solid #e2e8f0;border-radius:8px;background:#fff;color:#334155;font-size:13px;font-weight:600;cursor:pointer;transition:background .15s">${t('actions.close', 'Close')}</button>
|
||||
|
||||
@@ -23,6 +23,12 @@ function formatFileSize(bytes) {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
/// Formats a byte count for quota display. When bytes is 0, returns "∞" (unlimited).
|
||||
function formatQuotaSize(bytes) {
|
||||
if (bytes === 0) return '∞';
|
||||
return formatFileSize(bytes);
|
||||
}
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) return '';
|
||||
let dateValue;
|
||||
@@ -58,6 +64,7 @@ function isTextViewable(mimeType) {
|
||||
|
||||
window.escapeHtml = escapeHtml;
|
||||
window.formatFileSize = formatFileSize;
|
||||
window.formatQuotaSize = formatQuotaSize;
|
||||
window.formatDateTime = formatDateTime;
|
||||
window.formatDateShort = formatDateShort;
|
||||
window.isTextViewable = isTextViewable;
|
||||
|
||||
Reference in New Issue
Block a user