secubox-openwrt/luci-app-cdn-cache/htdocs/luci-static/resources/view/cdn-cache/cache.js

190 lines
7.2 KiB
JavaScript

'use strict';
'require view';
'require poll';
'require rpc';
'require ui';
var callCacheList = rpc.declare({
object: 'luci.cdn-cache',
method: 'cache_list',
expect: { items: [] }
});
var callPurgeDomain = rpc.declare({
object: 'luci.cdn-cache',
method: 'purge_domain',
params: ['domain']
});
var callTopDomains = rpc.declare({
object: 'luci.cdn-cache',
method: 'top_domains',
expect: { domains: [] }
});
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
var k = 1024;
var sizes = ['B', 'KB', 'MB', 'GB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatAge(seconds) {
if (seconds < 60) return seconds + 's';
if (seconds < 3600) return Math.floor(seconds / 60) + 'm';
if (seconds < 86400) return Math.floor(seconds / 3600) + 'h';
return Math.floor(seconds / 86400) + 'j';
}
function getFileIcon(filename) {
var ext = filename.split('.').pop().toLowerCase();
var icons = {
'exe': '⚙️', 'msi': '⚙️', 'deb': '📦', 'rpm': '📦',
'js': '📜', 'css': '🎨', 'html': '📄',
'png': '🖼️', 'jpg': '🖼️', 'gif': '🖼️', 'svg': '🖼️', 'webp': '🖼️',
'woff': '🔤', 'woff2': '🔤', 'ttf': '🔤',
'apk': '📱', 'ipa': '📱',
'zip': '🗜️', 'tar': '🗜️', 'gz': '🗜️'
};
return icons[ext] || '📄';
}
return view.extend({
load: function() {
return Promise.all([
callCacheList(),
callTopDomains()
]);
},
render: function(data) {
var items = data[0].items || [];
var domains = data[1].domains || [];
var self = this;
var view = E('div', { 'class': 'cbi-map cdn-cache-view' }, [
E('style', {}, `
.cdn-cache-view { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.cdn-page-header { background: linear-gradient(135deg, #0891b2, #06b6d4); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px; display: flex; justify-content: space-between; align-items: center; }
.cdn-page-title { font-size: 24px; font-weight: 700; margin: 0; }
.cdn-section { background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155; margin-bottom: 20px; }
.cdn-section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.cdn-section-title { font-size: 16px; font-weight: 600; color: #f1f5f9; display: flex; align-items: center; gap: 8px; }
.cdn-table { width: 100%; border-collapse: collapse; }
.cdn-table th { text-align: left; padding: 12px; color: #94a3b8; font-weight: 500; font-size: 12px; text-transform: uppercase; border-bottom: 1px solid #334155; }
.cdn-table td { padding: 12px; border-bottom: 1px solid #334155; color: #f1f5f9; font-size: 14px; }
.cdn-table tr:hover { background: rgba(6,182,212,0.05); }
.cdn-file-info { display: flex; align-items: center; gap: 10px; }
.cdn-file-icon { font-size: 20px; }
.cdn-file-name { font-weight: 500; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cdn-domain-badge { background: rgba(6,182,212,0.15); color: #06b6d4; padding: 4px 10px; border-radius: 6px; font-size: 12px; }
.cdn-size { font-family: 'JetBrains Mono', monospace; color: #94a3b8; }
.cdn-age { color: #64748b; font-size: 13px; }
.cdn-btn { padding: 8px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; border: none; transition: all 0.2s; }
.cdn-btn-sm { padding: 4px 10px; font-size: 12px; }
.cdn-btn-primary { background: #06b6d4; color: white; }
.cdn-btn-primary:hover { background: #0891b2; }
.cdn-btn-danger { background: #ef4444; color: white; }
.cdn-btn-danger:hover { background: #dc2626; }
.cdn-empty { text-align: center; padding: 40px; color: #64748b; }
.cdn-domain-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.cdn-domain-card { background: #0f172a; border: 1px solid #334155; border-radius: 10px; padding: 16px; }
.cdn-domain-card:hover { border-color: #06b6d4; }
.cdn-domain-name { font-weight: 600; color: #f1f5f9; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; }
.cdn-domain-stats { display: flex; gap: 16px; font-size: 13px; color: #94a3b8; }
`),
E('div', { 'class': 'cdn-page-header' }, [
E('h2', { 'class': 'cdn-page-title' }, '💿 Cache Status'),
E('div', {}, [
E('span', { 'style': 'margin-right: 12px; opacity: 0.9;' }, items.length + ' objets en cache')
])
]),
E('div', { 'class': 'cdn-section' }, [
E('div', { 'class': 'cdn-section-header' }, [
E('div', { 'class': 'cdn-section-title' }, ['🌐 ', 'Domaines en Cache']),
]),
E('div', { 'class': 'cdn-domain-grid' },
domains.length > 0 ? domains.map(function(d) {
return E('div', { 'class': 'cdn-domain-card' }, [
E('div', { 'class': 'cdn-domain-name' }, [
E('span', {}, d.domain),
E('button', {
'class': 'cdn-btn cdn-btn-sm cdn-btn-danger',
'click': function() {
ui.showModal('Purger le domaine', [
E('p', {}, 'Supprimer tout le cache pour ' + d.domain + ' ?'),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, 'Annuler'),
' ',
E('button', {
'class': 'btn cbi-button-negative',
'click': function() {
callPurgeDomain(d.domain).then(function() {
ui.hideModal();
window.location.reload();
});
}
}, 'Purger')
])
]);
}
}, '🗑️')
]),
E('div', { 'class': 'cdn-domain-stats' }, [
E('span', {}, '📁 ' + d.files + ' fichiers'),
E('span', {}, '💾 ' + formatBytes(d.size_kb * 1024))
])
]);
}) : [E('div', { 'class': 'cdn-empty' }, 'Aucun domaine en cache')]
)
]),
E('div', { 'class': 'cdn-section' }, [
E('div', { 'class': 'cdn-section-header' }, [
E('div', { 'class': 'cdn-section-title' }, ['📄 ', 'Fichiers Récents']),
]),
items.length > 0 ? E('table', { 'class': 'cdn-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', {}, 'Fichier'),
E('th', {}, 'Domaine'),
E('th', {}, 'Taille'),
E('th', {}, 'Âge')
])
]),
E('tbody', {}, items.slice(0, 50).map(function(item) {
return E('tr', {}, [
E('td', {}, [
E('div', { 'class': 'cdn-file-info' }, [
E('span', { 'class': 'cdn-file-icon' }, getFileIcon(item.filename)),
E('span', { 'class': 'cdn-file-name', 'title': item.filename }, item.filename)
])
]),
E('td', {}, [
E('span', { 'class': 'cdn-domain-badge' }, item.domain || 'unknown')
]),
E('td', { 'class': 'cdn-size' }, formatBytes(item.size)),
E('td', { 'class': 'cdn-age' }, formatAge(item.age))
]);
}))
]) : E('div', { 'class': 'cdn-empty' }, [
E('div', { 'style': 'font-size: 48px; margin-bottom: 16px;' }, '📭'),
E('div', {}, 'Le cache est vide')
])
])
]);
return view;
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});