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';
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LED Grab</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='0.9em' font-size='90'>💡</text></svg>">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Orbitron:wght@700&display=swap" rel="stylesheet">
|
||||
<!-- PWA -->
|
||||
<meta name="theme-color" content="#1a1a1a">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
@@ -15,23 +12,7 @@
|
||||
<meta name="apple-mobile-web-app-title" content="LED Grab">
|
||||
<link rel="apple-touch-icon" href="/static/icons/icon-192.png">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="stylesheet" href="/static/css/base.css">
|
||||
<link rel="stylesheet" href="/static/css/layout.css">
|
||||
<link rel="stylesheet" href="/static/css/components.css">
|
||||
<link rel="stylesheet" href="/static/css/cards.css">
|
||||
<link rel="stylesheet" href="/static/css/modal.css">
|
||||
<link rel="stylesheet" href="/static/css/calibration.css">
|
||||
<link rel="stylesheet" href="/static/css/advanced-calibration.css">
|
||||
<link rel="stylesheet" href="/static/css/dashboard.css">
|
||||
<link rel="stylesheet" href="/static/css/streams.css">
|
||||
<link rel="stylesheet" href="/static/css/patterns.css">
|
||||
<link rel="stylesheet" href="/static/css/automations.css">
|
||||
<link rel="stylesheet" href="/static/css/tree-nav.css">
|
||||
<link rel="stylesheet" href="/static/css/tutorials.css">
|
||||
<link rel="stylesheet" href="/static/css/graph-editor.css">
|
||||
<link rel="stylesheet" href="/static/css/mobile.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/elkjs@0.9.3/lib/elk.bundled.js"></script>
|
||||
<link rel="stylesheet" href="/static/dist/app.bundle.css">
|
||||
</head>
|
||||
<body style="visibility: hidden;">
|
||||
<canvas id="bg-anim-canvas"></canvas>
|
||||
@@ -221,7 +202,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="/static/js/app.js"></script>
|
||||
<script defer src="/static/dist/app.bundle.js"></script>
|
||||
<script>
|
||||
// Initialize ambient background
|
||||
const savedBgAnim = localStorage.getItem('bgAnim') || 'off';
|
||||
|
||||
Reference in New Issue
Block a user