💐 Sync 2026-09-14 23:49:49

This commit is contained in:
github-actions[bot] committed 2026-09-14 23:49:49 +08:00
1 parent 06a2e88aee
commit 2bab511fb4
60 files changed
+11427 -1

No files matched your search

@@ -0,0 +1,162 @@
'use strict';
'require view';
'require dom';
'require poll';
'require fs';
'require ui';
'require network';
document.querySelector('head').appendChild(E('link', {
'rel': 'stylesheet',
'type': 'text/css',
'href': L.resource('view/dashboard/css/custom.css')
}));
function invokeIncludesLoad(includes) {
const tasks = [];
let has_load = false;
for (let i = 0; i < includes.length; i++) {
includes[i].failed = false;
if (typeof(includes[i].load) == 'function') {
tasks.push(includes[i].load().catch(function(e) {
console.error(e);
this.failed = true;
}.bind(includes[i])));
has_load = true;
}
else {
tasks.push(null);
}
}
return has_load ? Promise.all(tasks) : Promise.resolve(null);
}
function collectSections(includes, results) {
const sections = { kpi: [], charts: [], tabs: [], extra: [] };
for (let i = 0; i < includes.length; i++) {
let content = null;
if (includes[i].failed)
continue;
try {
if (typeof(includes[i].render) == 'function')
content = includes[i].render(results ? results[i] : null);
else if (includes[i].content != null)
content = includes[i].content;
}
catch (e) {
console.error(e);
continue;
}
if (content == null)
continue;
if (content instanceof Node || Array.isArray(content)) {
sections.extra.push(content);
continue;
}
for (const key of [ 'kpi', 'charts', 'tabs' ])
(content[key] || []).forEach(item => sections[key].push(item));
}
return sections;
}
function renderSections(sections) {
const nodes = [];
if (sections.kpi.length)
nodes.push(E('div', { 'class': 'dashboard-kpi-row' }, sections.kpi));
if (sections.charts.length)
nodes.push(E('div', { 'class': 'dashboard-charts' }, sections.charts));
if (sections.tabs.length)
nodes.push(E('div', { 'class': 'cbi-map' }, [
E('div', { 'class': 'cbi-map-tabbed' }, sections.tabs.map(tab => E('div', {
'class': 'cbi-section',
'data-tab': tab.id,
'data-tab-title': (tab.count != null) ? '%s (%d)'.format(tab.title, tab.count) : tab.title
}, tab.content)))
]));
if (sections.extra.length)
nodes.push(E('div', {}, sections.extra));
return nodes;
}
function saveChartScroll(root) {
const positions = {};
root.querySelectorAll('[data-chart]').forEach(node => {
if (node.dataset.chart)
positions[node.dataset.chart] = node.scrollLeft;
});
return positions;
}
function restoreChartScroll(root, positions) {
root.querySelectorAll('[data-chart]').forEach(node => {
if (positions[node.dataset.chart])
node.scrollLeft = positions[node.dataset.chart];
});
}
function startPolling(includes, root) {
const step = () => {
return network.flushCache().then(() => {
return invokeIncludesLoad(includes);
}).then(results => {
const positions = saveChartScroll(root);
dom.content(root, renderSections(collectSections(includes, results)));
const group = root.querySelector('.cbi-map-tabbed');
if (group)
ui.tabs.initTabGroup(group.childNodes);
restoreChartScroll(root, positions);
root.classList.add('fade-in');
});
};
return step().then(() => {
poll.add(step);
});
}
return view.extend({
load() {
return L.resolveDefault(fs.list('/www' + L.resource('view/dashboard/include')), []).then(entries => {
return Promise.all(entries.filter(e => {
return (e.type == 'file' && e.name.match(/\.js$/));
}).map(e => {
return 'view.dashboard.include.' + e.name.replace(/\.js$/, '');
}).sort().map(n => {
return L.require(n);
}));
});
},
render(includes) {
const root = E('div', { 'class': 'Dashboard' });
return startPolling(includes, root).then(() => {
return root;
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});