Merge claude/1
|
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
|
Before Width: | Height: | Size: 356 B After Width: | Height: | Size: 356 B |
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 443 B |
@ -44,8 +44,8 @@ if (typeof window.ConfigManager === 'undefined') {
|
||||
try { this.sidebar.populateSidebar(); } catch (e) {}
|
||||
// charts.js is the chart-rendering helper admin-overview pulls in.
|
||||
await Promise.all([
|
||||
lazyLoad('/components/admin/admin-overview.js'),
|
||||
lazyLoad('/components/admin/charts.js')
|
||||
lazyLoad('/components/admin/overview/js/admin-overview.js'),
|
||||
lazyLoad('/components/admin/system/js/charts.js')
|
||||
]);
|
||||
if (typeof AdminOverview !== 'undefined') {
|
||||
window.adminOverview = new AdminOverview('config-section');
|
||||
@ -60,7 +60,7 @@ if (typeof window.ConfigManager === 'undefined') {
|
||||
// a config category — render its own controller into the main pane.
|
||||
if (category === 'ssh-access') {
|
||||
try { this.sidebar.populateSidebar(); } catch (e) {}
|
||||
await lazyLoad('/components/admin/ssh-page.js');
|
||||
await lazyLoad('/components/admin/ssh/js/ssh-page.js');
|
||||
if (typeof SshPage !== 'undefined') {
|
||||
window.sshPage = new SshPage('config-section');
|
||||
await window.sshPage.init();
|
||||
@ -76,9 +76,9 @@ if (typeof window.ConfigManager === 'undefined') {
|
||||
// we inject its content template, then init PeersPage.
|
||||
if (category === 'peers') {
|
||||
try { this.sidebar.populateSidebar(); } catch (e) {}
|
||||
await lazyLoad('/components/admin/peers-page.js');
|
||||
await lazyLoad('/components/admin/peers/js/peers-page.js');
|
||||
try {
|
||||
const html = await fetch('/components/admin/peers-content.html').then(r => r.text());
|
||||
const html = await fetch('/components/admin/peers/html/peers-content.html').then(r => r.text());
|
||||
configSection.innerHTML = html;
|
||||
} catch (e) {
|
||||
configSection.innerHTML = '<div class="error">Peers page template failed to load.</div>';
|
||||
@ -100,10 +100,10 @@ if (typeof window.ConfigManager === 'undefined') {
|
||||
if (category === 'system') {
|
||||
try { this.sidebar.populateSidebar(); } catch (e) {}
|
||||
await Promise.all([
|
||||
lazyLoad('/components/admin/charts.js'),
|
||||
lazyLoad('/components/admin/admin-system.js'),
|
||||
lazyLoad('/components/admin/system-metric-page.js'),
|
||||
lazyLoad('/components/admin/system-storage-page.js')
|
||||
lazyLoad('/components/admin/system/js/charts.js'),
|
||||
lazyLoad('/components/admin/system/js/admin-system.js'),
|
||||
lazyLoad('/components/admin/system/js/system-metric-page.js'),
|
||||
lazyLoad('/components/admin/system/js/system-storage-page.js')
|
||||
]);
|
||||
if (typeof AdminSystem !== 'undefined') {
|
||||
window.adminSystem = new AdminSystem('config-section');
|
||||
@ -216,7 +216,7 @@ if (typeof window.ConfigManager === 'undefined') {
|
||||
var catIcon = catMeta.icon || category;
|
||||
var headerHTML =
|
||||
'<div class="page-header config-page-header">' +
|
||||
'<img class="page-header-icon" src="/core/icons/config/' + catIcon + '.svg" alt="" onerror="this.style.display=\'none\'">' +
|
||||
'<img class="page-header-icon" src="/components/admin/config/icons/config/' + catIcon + '.svg" alt="" onerror="this.style.display=\'none\'">' +
|
||||
'<div class="page-header-title">' +
|
||||
'<div class="admin-breadcrumb">Config</div>' +
|
||||
'<h1>' + catTitle + '</h1>' +
|
||||
@ -88,7 +88,7 @@ class ConfigSidebar {
|
||||
|
||||
// Use correct icon from our new structure
|
||||
const iconName = category.icon || category.id;
|
||||
const iconPath = '/core/icons/config/' + iconName + '.svg';
|
||||
const iconPath = '/components/admin/config/icons/config/' + iconName + '.svg';
|
||||
|
||||
categoryItem.innerHTML = '<img src="' + iconPath + '" alt="' + category.title + '" style="width: 20px; height: 20px; margin-right: 8px;"/> ' + category.title;
|
||||
|
||||
@ -16,7 +16,7 @@ LP.features.register({
|
||||
async mount(ctx) {
|
||||
window.configCategory = ctx.services.router.adminCategoryFromPath(window.location.pathname);
|
||||
|
||||
const html = await ctx.loadFragment('/components/admin/config-content.html');
|
||||
const html = await ctx.loadFragment('/components/admin/config/html/config-content.html');
|
||||
ctx.setContent(html, 'Admin');
|
||||
|
||||
if (window.configManager) {
|
||||
|
||||
|
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 780 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 963 B After Width: | Height: | Size: 963 B |
@ -401,14 +401,14 @@ class AdminSystem {
|
||||
return `<div class="sys-stat"><span class="sys-stat-label">${this.escape(label)}</span><strong class="sys-stat-value">${this.escape(value)}</strong></div>`;
|
||||
}
|
||||
|
||||
// OS stat with a distro icon (bundled under /core/icons/os/, generic Linux glyph
|
||||
// OS stat with a distro icon (bundled under /components/admin/system/icons/os/, generic Linux glyph
|
||||
// for anything we don't have a logo for).
|
||||
_osStat(os) {
|
||||
const slug = String(os || '').toLowerCase().replace(/[^a-z0-9]/g, '') || 'linux';
|
||||
return `<div class="sys-stat">
|
||||
<span class="sys-stat-label">OS</span>
|
||||
<strong class="sys-stat-value sys-id-value">
|
||||
<span class="sys-id-icon"><img src="/core/icons/os/${slug}.svg" alt="" onerror="this.onerror=null;this.src='/core/icons/os/linux.svg'"></span>
|
||||
<span class="sys-id-icon"><img src="/components/admin/system/icons/os/${slug}.svg" alt="" onerror="this.onerror=null;this.src='/components/admin/system/icons/os/linux.svg'"></span>
|
||||
${this.escape(os || '—')}
|
||||
</strong>
|
||||
</div>`;
|
||||
@ -430,7 +430,7 @@ class AdminSystem {
|
||||
_cpuStat(cpu) {
|
||||
const raw = String(cpu || '');
|
||||
const vendor = /amd/i.test(raw) ? 'amd' : /intel/i.test(raw) ? 'intel' : null;
|
||||
const icon = vendor ? `<span class="sys-id-icon"><img src="/core/icons/cpu/${vendor}.svg" alt="${vendor}"></span>` : '';
|
||||
const icon = vendor ? `<span class="sys-id-icon"><img src="/components/admin/system/icons/cpu/${vendor}.svg" alt="${vendor}"></span>` : '';
|
||||
return `<div class="sys-stat">
|
||||
<span class="sys-stat-label">CPU</span>
|
||||
<strong class="sys-stat-value sys-id-value">${icon}${this.escape(this._cleanCpu(raw))}</strong>
|
||||
@ -42,7 +42,7 @@ LP.features.register({
|
||||
}
|
||||
}
|
||||
|
||||
const html = await ctx.loadFragment('/components/apps/apps-unified-layout.html');
|
||||
const html = await ctx.loadFragment('/components/apps/core/html/apps-unified-layout.html');
|
||||
ctx.setContent(html, appName);
|
||||
|
||||
if (!window.appTabbedManager) {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 496 B |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 952 B After Width: | Height: | Size: 952 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 814 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 361 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -2408,7 +2408,7 @@ class AppsManager {
|
||||
const existing = document.getElementById('mullvad-generate-modal');
|
||||
if (existing) existing.remove();
|
||||
|
||||
const mullvadIcon = (window.gluetunProviderIcons && window.gluetunProviderIcons.mullvad) || '/core/icons/vpn/mullvad.svg';
|
||||
const mullvadIcon = (window.gluetunProviderIcons && window.gluetunProviderIcons.mullvad) || '/components/apps/core/icons/vpn/mullvad.svg';
|
||||
const bodyHtml = `
|
||||
<p class="eo-modal-section-text">
|
||||
Enter your 16-digit Mullvad account number. A new WireGuard key will be generated locally
|
||||
@ -3354,7 +3354,7 @@ class AppsManager {
|
||||
{ name: 'TaskCommands', src: '/core/lib/task-commands.js' },
|
||||
{ name: 'TaskActions', src: '/core/lib/task-actions.js' },
|
||||
{ name: 'TaskRouter', src: '/core/lib/task-router.js' },
|
||||
{ name: 'TasksManager', src: '/components/tasks/tasks-manager.js' }
|
||||
{ name: 'TasksManager', src: '/components/tasks/js/tasks-manager.js' }
|
||||
];
|
||||
|
||||
for (const script of scripts) {
|
||||
@ -28,7 +28,7 @@ LP.features.register({
|
||||
// Load the unified layout only if it isn't already present — preserves grid
|
||||
// state when moving between categories / back from app-detail (legacy behaviour).
|
||||
if (!document.querySelector('.apps-layout')) {
|
||||
const html = await ctx.loadFragment('/components/apps/apps-unified-layout.html');
|
||||
const html = await ctx.loadFragment('/components/apps/core/html/apps-unified-layout.html');
|
||||
ctx.setContent(html, 'Applications');
|
||||
}
|
||||
|
||||
|
||||
@ -14,14 +14,14 @@ LP.features.register({
|
||||
routes: ['/backup', '/backup*'],
|
||||
// Controllers the feature needs; lazy-loaded on first mount (idempotent).
|
||||
scripts: [
|
||||
'/components/backup/backup-schema.js',
|
||||
'/components/backup/backup-page.js',
|
||||
'/components/backup/js/backup-schema.js',
|
||||
'/components/backup/js/backup-page.js',
|
||||
'/core/lib/backup-app-card.js',
|
||||
],
|
||||
|
||||
async mount(ctx) {
|
||||
await ctx.loadScripts(this.scripts);
|
||||
const html = await ctx.loadFragment('/components/backup/backup-content.html');
|
||||
const html = await ctx.loadFragment('/components/backup/html/backup-content.html');
|
||||
ctx.setContent(html, 'Backups');
|
||||
if (typeof BackupPage === 'undefined') {
|
||||
throw new Error('BackupPage controller failed to load');
|
||||
|
||||
@ -13,7 +13,7 @@ LP.features.register({
|
||||
routes: ['/', '/dashboard'],
|
||||
|
||||
async mount(ctx) {
|
||||
const html = await ctx.loadFragment('/components/dashboard/dashboard-content.html');
|
||||
const html = await ctx.loadFragment('/components/dashboard/html/dashboard-content.html');
|
||||
ctx.setContent(html, 'Dashboard');
|
||||
|
||||
// Render the installed-apps icon grid (handleDashboard's only post-render call).
|
||||
|
||||
@ -11,7 +11,7 @@ LP.features.register({
|
||||
routes: ['/tasks', '/tasks*'],
|
||||
|
||||
async mount(ctx) {
|
||||
const html = await ctx.loadFragment('/components/tasks/tasks-content.html');
|
||||
const html = await ctx.loadFragment('/components/tasks/html/tasks-content.html');
|
||||
ctx.setContent(html, 'Tasks');
|
||||
|
||||
if (window.tasksManager) {
|
||||
|
||||
@ -9,11 +9,11 @@
|
||||
LP.features.register({
|
||||
id: 'updater',
|
||||
routes: ['/updater', '/updater*'],
|
||||
scripts: ['/components/updater/updater-page.js'],
|
||||
scripts: ['/components/updater/js/updater-page.js'],
|
||||
|
||||
async mount(ctx) {
|
||||
await ctx.loadScripts(this.scripts);
|
||||
const html = await ctx.loadFragment('/components/updater/updater-content.html');
|
||||
const html = await ctx.loadFragment('/components/updater/html/updater-content.html');
|
||||
ctx.setContent(html, 'Updates');
|
||||
if (typeof UpdaterPage === 'undefined') {
|
||||
throw new Error('UpdaterPage controller failed to load');
|
||||
|
||||
@ -41,16 +41,16 @@ class SystemLoader {
|
||||
scripts: [
|
||||
'/core/lib/config-options.js',
|
||||
'/core/lib/config-shared.js',
|
||||
'/components/admin/config-validator.js',
|
||||
'/components/admin/toggle-manager.js',
|
||||
'/components/admin/config-core.js',
|
||||
'/components/admin/domain-manager.js',
|
||||
'/components/admin/ip-whitelist-manager.js',
|
||||
'/components/admin/config-renderer.js',
|
||||
'/components/admin/config-sidebar.js',
|
||||
'/components/admin/config-form.js',
|
||||
'/components/admin/config-utils.js',
|
||||
'/components/admin/config-manager.js'
|
||||
'/components/admin/config/js/config-validator.js',
|
||||
'/components/admin/config/js/toggle-manager.js',
|
||||
'/components/admin/config/js/config-core.js',
|
||||
'/components/admin/config/js/domain-manager.js',
|
||||
'/components/admin/config/js/ip-whitelist-manager.js',
|
||||
'/components/admin/config/js/config-renderer.js',
|
||||
'/components/admin/config/js/config-sidebar.js',
|
||||
'/components/admin/config/js/config-form.js',
|
||||
'/components/admin/config/js/config-utils.js',
|
||||
'/components/admin/config/js/config-manager.js'
|
||||
]
|
||||
});
|
||||
|
||||
@ -174,7 +174,7 @@ class SystemLoader {
|
||||
'/core/lib/task-global-functions.js',
|
||||
'/core/lib/task-manager.js',
|
||||
'/core/lib/task-parameter-preserve.js',
|
||||
'/components/tasks/tasks-manager.js'
|
||||
'/components/tasks/js/tasks-manager.js'
|
||||
]
|
||||
});
|
||||
|
||||
@ -204,13 +204,13 @@ class SystemLoader {
|
||||
global: 'appsManager',
|
||||
dependencies: ['data'],
|
||||
scripts: [
|
||||
'/components/apps/port-manager.js',
|
||||
'/components/apps/port-manager/js/port-manager.js',
|
||||
'/core/lib/task-manager.js', // Add TaskManager for backup functionality
|
||||
'/core/lib/backup-app-card.js',
|
||||
'/components/apps/services-manager.js',
|
||||
'/components/apps/tools-manager.js',
|
||||
'/components/apps/routing-manager.js',
|
||||
'/components/apps/apps-manager.js'
|
||||
'/components/apps/services/js/services-manager.js',
|
||||
'/components/apps/tools/js/tools-manager.js',
|
||||
'/components/apps/routing/js/routing-manager.js',
|
||||
'/components/apps/core/js/apps-manager.js'
|
||||
]
|
||||
});
|
||||
|
||||
@ -232,7 +232,7 @@ class SystemLoader {
|
||||
},
|
||||
global: 'appTabbedManager',
|
||||
dependencies: [],
|
||||
script: '/components/apps/app-tabbed-manager.js'
|
||||
script: '/components/apps/core/js/app-tabbed-manager.js'
|
||||
});
|
||||
|
||||
// console.log('TEST: Components added. Total components:', this.components.size);
|
||||
|
||||
@ -341,7 +341,7 @@ class LibrePortalSPAClean {
|
||||
|
||||
try {
|
||||
// console.log('📄 SPA: Fetching dashboard content...');
|
||||
const html = await this.fetchContent('/components/dashboard/dashboard-content.html');
|
||||
const html = await this.fetchContent('/components/dashboard/html/dashboard-content.html');
|
||||
// console.log('📄 SPA: Dashboard content fetched, loading...');
|
||||
this.loadContent(html, 'Dashboard');
|
||||
// console.log('📄 SPA: Dashboard content loaded');
|
||||
@ -362,10 +362,10 @@ class LibrePortalSPAClean {
|
||||
// backup-page.js + backup-app-card.js are loaded on first navigation.
|
||||
// loadScript is idempotent — subsequent /backup navigations are no-ops.
|
||||
await Promise.all([
|
||||
this.loadScript('/components/backup/backup-page.js'),
|
||||
this.loadScript('/components/backup/js/backup-page.js'),
|
||||
this.loadScript('/core/lib/backup-app-card.js')
|
||||
]);
|
||||
const html = await this.fetchContent('/components/backup/backup-content.html');
|
||||
const html = await this.fetchContent('/components/backup/html/backup-content.html');
|
||||
this.loadContent(html, 'Backups');
|
||||
if (typeof BackupPage !== 'undefined') {
|
||||
window.backupPage = new BackupPage();
|
||||
@ -409,7 +409,7 @@ class LibrePortalSPAClean {
|
||||
// Ensure unified layout is loaded (like the old SPA)
|
||||
if (!document.querySelector('.apps-layout')) {
|
||||
//console.log('📄 Loading apps layout HTML...');
|
||||
const html = await this.fetchContent('/components/apps/apps-unified-layout.html');
|
||||
const html = await this.fetchContent('/components/apps/core/html/apps-unified-layout.html');
|
||||
this.loadContent(html, 'Applications');
|
||||
} else {
|
||||
//console.log('📄 Apps layout already exists, skipping HTML load');
|
||||
@ -477,7 +477,7 @@ class LibrePortalSPAClean {
|
||||
}
|
||||
|
||||
try {
|
||||
const html = await this.fetchContent('/components/apps/apps-unified-layout.html');
|
||||
const html = await this.fetchContent('/components/apps/core/html/apps-unified-layout.html');
|
||||
this.loadContent(html, appName); // Will be updated after app data loads
|
||||
|
||||
// AppTabbedManager should already be initialized by SystemLoader
|
||||
@ -502,7 +502,7 @@ class LibrePortalSPAClean {
|
||||
window.configCategory = window.adminCategoryFromPath(window.location.pathname);
|
||||
|
||||
try {
|
||||
const html = await this.fetchContent('/components/admin/config-content.html');
|
||||
const html = await this.fetchContent('/components/admin/config/html/config-content.html');
|
||||
this.loadContent(html, 'Admin');
|
||||
|
||||
if (window.configManager) {
|
||||
@ -535,7 +535,7 @@ class LibrePortalSPAClean {
|
||||
//console.log('📋 Loading tasks...');
|
||||
|
||||
try {
|
||||
const html = await this.fetchContent('/components/tasks/tasks-content.html');
|
||||
const html = await this.fetchContent('/components/tasks/html/tasks-content.html');
|
||||
this.loadContent(html, 'Tasks');
|
||||
|
||||
// Tasks manager should already be initialized by SystemLoader
|
||||
|
||||
@ -16,27 +16,27 @@
|
||||
<link rel="stylesheet" href="/core/css/loading-screen.css">
|
||||
<link rel="stylesheet" href="/core/css/setup-wizard.css">
|
||||
<link rel="stylesheet" href="/core/css/style.css">
|
||||
<link rel="stylesheet" href="/components/admin/ip-whitelist.css">
|
||||
<link rel="stylesheet" href="/components/apps/port-manager.css">
|
||||
<link rel="stylesheet" href="/components/backup/backup.css">
|
||||
<link rel="stylesheet" href="/components/admin/ssh.css">
|
||||
<link rel="stylesheet" href="/components/admin/admin.css">
|
||||
<link rel="stylesheet" href="/components/apps/services.css">
|
||||
<link rel="stylesheet" href="/components/admin/config/css/ip-whitelist.css">
|
||||
<link rel="stylesheet" href="/components/apps/port-manager/css/port-manager.css">
|
||||
<link rel="stylesheet" href="/components/backup/css/backup.css">
|
||||
<link rel="stylesheet" href="/components/admin/ssh/css/ssh.css">
|
||||
<link rel="stylesheet" href="/components/admin/css/admin.css">
|
||||
<link rel="stylesheet" href="/components/apps/services/css/services.css">
|
||||
<link rel="stylesheet" href="/core/css/modal.css">
|
||||
<link rel="stylesheet" href="/components/apps/tools.css">
|
||||
<link rel="stylesheet" href="/components/apps/routing.css">
|
||||
<link rel="stylesheet" href="/components/apps/tools/css/tools.css">
|
||||
<link rel="stylesheet" href="/components/apps/routing/css/routing.css">
|
||||
<link rel="stylesheet" href="/core/css/login.css">
|
||||
<link rel="stylesheet" href="/core/css/aurora-background.css">
|
||||
<link rel="stylesheet" href="/core/css/topbar.css">
|
||||
<link rel="stylesheet" href="/core/css/sidebar.css">
|
||||
<link rel="stylesheet" href="/components/apps/apps-layout.css">
|
||||
<link rel="stylesheet" href="/components/apps/apps.css">
|
||||
<link rel="stylesheet" href="/components/apps/core/css/apps-layout.css">
|
||||
<link rel="stylesheet" href="/components/apps/core/css/apps.css">
|
||||
<link rel="stylesheet" href="/core/css/forms.css">
|
||||
<link rel="stylesheet" href="/core/css/config.css">
|
||||
<link rel="stylesheet" href="/components/apps/service-buttons.css">
|
||||
<link rel="stylesheet" href="/components/dashboard/dashboard.css">
|
||||
<link rel="stylesheet" href="/components/tasks/tasks.css">
|
||||
<link rel="stylesheet" href="/components/updater/updater.css">
|
||||
<link rel="stylesheet" href="/components/apps/core/css/service-buttons.css">
|
||||
<link rel="stylesheet" href="/components/dashboard/css/dashboard.css">
|
||||
<link rel="stylesheet" href="/components/tasks/css/tasks.css">
|
||||
<link rel="stylesheet" href="/components/updater/css/updater.css">
|
||||
<link rel="stylesheet" href="/core/css/update-notifier.css">
|
||||
<script>
|
||||
// Inline data-theme bootstrap — runs before any rendering so the right
|
||||
@ -98,7 +98,7 @@
|
||||
<script src="/core/lib/dismissible.js"></script>
|
||||
<script src="/core/ui/eo-modal.js"></script>
|
||||
<script src="/core/lib/task-refresh-coordinator.js"></script>
|
||||
<script src="/components/dashboard/dashboard.js"></script>
|
||||
<script src="/components/dashboard/js/dashboard.js"></script>
|
||||
<script src="/core/boot/system-loader.js"></script>
|
||||
<script src="/core/boot/loading-ui.js"></script>
|
||||
<script src="/core/boot/setup-detector.js"></script>
|
||||
|
||||