fix: rewrite dashboard_refresh.js with correct bricks API
- Replace non-existent bricks.app.find_widget_by_id() with bricks.getWidgetById(id, bricks.app) - Replace widget.el.textContent with widget.set_text() method - Fix getBaseUrl() to handle /modulename paths (no .ui suffix) returning /undefined - Remove chart refresh from JS — use ChartBar's built-in refresh_period: 10 - Update index.ui ChartBar widget with refresh_period: 10 - Also fixed all find_widget_by_id references across skills: * bricks-framework SKILL.md (2 occurrences) * bricks-framework references: auto-refresh-dashboard.md, auto-refresh-pattern.md, bar.md, line.md, websocket.md * module-development-spec references: read-only-module-pattern.md * harnessed-module-development SKILL.md (2 occurrences) * harnessed-module-development references: reasoning-visualization.md, bricks-ui-pitfalls.md * rbac-permission-initialization-pattern references: websocket-debugging.md
This commit is contained in:
parent
b83131146a
commit
c7180bda77
@ -1,48 +1,42 @@
|
|||||||
/**
|
/**
|
||||||
* Dashboard auto-refresh script
|
* Dashboard auto-refresh script
|
||||||
* Polls API every 10 seconds and updates stat cards + chart
|
* Polls API every 10 seconds and updates stat cards
|
||||||
* Auto-loaded by Sage's header.tmpl from wwwroot/scripts/
|
* ChartBar handles its own refresh via refresh_period
|
||||||
|
* Auto-loaded by Sage's header.tmpl from wwwroot/
|
||||||
*/
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Derive base URL from current page (e.g. /dashboard_for_sage/index.ui -> /dashboard_for_sage)
|
|
||||||
function getBaseUrl() {
|
function getBaseUrl() {
|
||||||
var path = window.location.pathname;
|
var path = window.location.pathname;
|
||||||
// path is like /dashboard_for_sage/index.ui or /dashboard_for_sage
|
// path is like /dashboard_for_sage/index.ui or /dashboard_for_sage/
|
||||||
var parts = path.split('/').filter(function(p) { return p; });
|
var parts = path.split('/').filter(function(p) { return p.length > 0; });
|
||||||
|
if (parts.length === 0) return '';
|
||||||
return '/' + parts[0];
|
return '/' + parts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUrl(dspyFile) {
|
function buildUrl(dspyFile) {
|
||||||
var base = getBaseUrl();
|
var base = getBaseUrl();
|
||||||
// Add _webbricks_=1 for non-initial requests
|
|
||||||
return base + '/' + dspyFile + '?_webbricks_=1';
|
return base + '/' + dspyFile + '?_webbricks_=1';
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCard(id, value) {
|
function setCardText(cardId, value) {
|
||||||
try {
|
try {
|
||||||
var widget = bricks.app.find_widget_by_id(id);
|
var widget = bricks.getWidgetById(cardId, bricks.app);
|
||||||
if (widget && widget.el) {
|
if (widget && typeof widget.set_text === 'function') {
|
||||||
widget.el.textContent = value;
|
widget.set_text(String(value));
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {}
|
||||||
// Widget may not be ready yet
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatNumber(n) {
|
function formatNumber(n) {
|
||||||
if (typeof n === 'number') {
|
if (typeof n === 'number') return n.toLocaleString();
|
||||||
return n.toLocaleString();
|
return String(n);
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAmount(n) {
|
function formatAmount(n) {
|
||||||
if (typeof n === 'number') {
|
if (typeof n === 'number') return '\u00a5' + n.toFixed(2);
|
||||||
return '¥' + n.toFixed(2);
|
return '\u00a50.00';
|
||||||
}
|
|
||||||
return '¥0.00';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshStats() {
|
async function refreshStats() {
|
||||||
@ -51,10 +45,10 @@
|
|||||||
var resp = await fetch(url, { credentials: 'include' });
|
var resp = await fetch(url, { credentials: 'include' });
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
var data = await resp.json();
|
var data = await resp.json();
|
||||||
updateCard('today_cnt_value', formatNumber(data.cnt));
|
setCardText('today_cnt_value', formatNumber(data.cnt));
|
||||||
updateCard('today_amount_value', formatAmount(data.total_amount));
|
setCardText('today_amount_value', formatAmount(data.total_amount));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
// Silently fail on refresh errors
|
console.error('refreshStats error:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,35 +58,22 @@
|
|||||||
var resp = await fetch(url, { credentials: 'include' });
|
var resp = await fetch(url, { credentials: 'include' });
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
var data = await resp.json();
|
var data = await resp.json();
|
||||||
updateCard('total_users_value', formatNumber(data.total_users));
|
setCardText('total_users_value', formatNumber(data.total_users));
|
||||||
updateCard('concurrent_users_value', formatNumber(data.concurrent_users));
|
setCardText('concurrent_users_value', formatNumber(data.concurrent_users));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
// Silently fail on refresh errors
|
console.error('refreshUsers error:', e);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshChart() {
|
|
||||||
try {
|
|
||||||
var chart = bricks.app.find_widget_by_id('top_models_chart');
|
|
||||||
if (chart && chart.render_urldata) {
|
|
||||||
await chart.render_urldata({});
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
// Silently fail on refresh errors
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshAll() {
|
async function refreshAll() {
|
||||||
await refreshStats();
|
await refreshStats();
|
||||||
await refreshUsers();
|
await refreshUsers();
|
||||||
await refreshChart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start auto-refresh every 10 seconds
|
// Wait for bricks framework to initialize, then start auto-refresh
|
||||||
// Delay initial load to allow bricks framework to initialize
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
refreshAll();
|
refreshAll();
|
||||||
setInterval(refreshAll, 10000);
|
setInterval(refreshAll, 10000);
|
||||||
}, 1000);
|
}, 2000);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@ -188,7 +188,8 @@
|
|||||||
"width": "100%",
|
"width": "100%",
|
||||||
"data_url": "{{entire_url('api/get_top_models.dspy')}}",
|
"data_url": "{{entire_url('api/get_top_models.dspy')}}",
|
||||||
"nameField": "model_name",
|
"nameField": "model_name",
|
||||||
"valueFields": ["cnt", "total_amount"]
|
"valueFields": ["cnt", "total_amount"],
|
||||||
|
"refresh_period": 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user