Bundle frontend with esbuild, serve fonts offline, fix dashboard
- Add esbuild bundling: JS (IIFE, minified, sourcemapped) and CSS into single dist/ files, replacing 15+ individual CSS links and CDN scripts - Bundle Chart.js and ELK.js from npm instead of CDN (fully offline) - Serve DM Sans and Orbitron fonts locally from static/fonts/ - Fix dashboard automation card stretching full width (max-width: 500px) - Fix time_of_day condition not localized in automation cards - Add Chrome browser tools context file for MCP testing workflow - Update frontend context with bundling docs and Chrome tools reference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
17
server/src/wled_controller/static/css/all.css
Normal file
17
server/src/wled_controller/static/css/all.css
Normal file
@@ -0,0 +1,17 @@
|
||||
/* CSS bundle entry — imports all stylesheets in correct order */
|
||||
@import './fonts.css';
|
||||
@import './base.css';
|
||||
@import './layout.css';
|
||||
@import './components.css';
|
||||
@import './cards.css';
|
||||
@import './modal.css';
|
||||
@import './calibration.css';
|
||||
@import './advanced-calibration.css';
|
||||
@import './dashboard.css';
|
||||
@import './streams.css';
|
||||
@import './patterns.css';
|
||||
@import './automations.css';
|
||||
@import './tree-nav.css';
|
||||
@import './tutorials.css';
|
||||
@import './graph-editor.css';
|
||||
@import './mobile.css';
|
||||
@@ -306,6 +306,10 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dashboard-automation {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.dashboard-automation .dashboard-target-metrics {
|
||||
min-width: 48px;
|
||||
}
|
||||
|
||||
31
server/src/wled_controller/static/css/fonts.css
Normal file
31
server/src/wled_controller/static/css/fonts.css
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Local font faces — no external CDN dependency */
|
||||
|
||||
/* DM Sans — latin-ext */
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/dm-sans-latin-ext.woff2') format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* DM Sans — latin */
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/dm-sans-latin.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* Orbitron 700 — latin */
|
||||
@font-face {
|
||||
font-family: 'Orbitron';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/orbitron-700-latin.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
BIN
server/src/wled_controller/static/fonts/dm-sans-latin-ext.woff2
Normal file
BIN
server/src/wled_controller/static/fonts/dm-sans-latin-ext.woff2
Normal file
Binary file not shown.
BIN
server/src/wled_controller/static/fonts/dm-sans-latin.woff2
Normal file
BIN
server/src/wled_controller/static/fonts/dm-sans-latin.woff2
Normal file
Binary file not shown.
BIN
server/src/wled_controller/static/fonts/orbitron-700-latin.woff2
Normal file
BIN
server/src/wled_controller/static/fonts/orbitron-700-latin.woff2
Normal file
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
* Graph layout via ELK.js — converts entity data into positioned nodes/edges.
|
||||
*/
|
||||
|
||||
/* global ELK */
|
||||
import ELK from 'elkjs/lib/elk.bundled.js';
|
||||
|
||||
const NODE_WIDTH = 190;
|
||||
const NODE_HEIGHT = 56;
|
||||
|
||||
@@ -681,7 +681,8 @@ function renderDashboardAutomation(automation, sceneMap = new Map()) {
|
||||
return `${apps} (${matchLabel})`;
|
||||
}
|
||||
if (c.condition_type === 'startup') return t('automations.condition.startup');
|
||||
return c.condition_type;
|
||||
if (c.condition_type === 'time_of_day') return t('automations.condition.time_of_day');
|
||||
return t(`automations.condition.${c.condition_type}`) || c.condition_type;
|
||||
});
|
||||
const logic = automation.condition_logic === 'and' ? ' & ' : ' | ';
|
||||
condSummary = parts.join(logic);
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
* History is seeded from the server-side ring buffer on init.
|
||||
*/
|
||||
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
Chart.register(...registerables);
|
||||
window.Chart = Chart; // expose globally for targets.js, dashboard.js
|
||||
|
||||
import { API_BASE, getHeaders } from '../core/api.js';
|
||||
import { t } from '../core/i18n.js';
|
||||
import { dashboardPollInterval } from '../core/state.js';
|
||||
|
||||
Reference in New Issue
Block a user