fix(crowdsec-dashboard): Use baseclass.singleton for theme manager

Fix "not a constructor" error by using baseclass.singleton()
pattern instead of baseclass.extend() with manual instantiation.
Theme module now exports a singleton directly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-30 09:30:54 +01:00
parent 2d15c641f1
commit b35b86684e
3 changed files with 13 additions and 22 deletions

View File

@ -3,7 +3,7 @@
'require uci';
/**
* CrowdSec Dashboard Theme Manager
* CrowdSec Dashboard Theme Manager (Singleton)
* Handles loading and switching between UI themes
*
* Available themes:
@ -13,11 +13,10 @@
*
* Profiles can extend themes with custom configurations
*
* Usage: var theme = new (require('crowdsec-dashboard.theme'))();
* theme.init().then(function() { ... });
* Usage: theme.init().then(function() { ... });
*/
return baseclass.extend({
return baseclass.singleton({
// Available themes
themes: {
'classic': {

View File

@ -5,7 +5,7 @@
'require ui';
'require uci';
'require crowdsec-dashboard.api as api';
'require crowdsec-dashboard.theme as ThemeClass';
'require crowdsec-dashboard.theme as theme';
/**
* CrowdSec SOC Dashboard - Overview
@ -13,16 +13,12 @@
* Version 1.1.0
*/
var themeInstance = new ThemeClass();
return view.extend({
title: _('CrowdSec SOC'),
theme: themeInstance,
load: function() {
var self = this;
return Promise.all([
self.theme.init(),
theme.init(),
api.getOverview().catch(function() { return {}; })
]);
},
@ -34,7 +30,7 @@ return view.extend({
// Apply theme class
document.body.classList.add('cs-fullwidth');
var view = E('div', { 'class': self.theme.getDashboardClass() }, [
var view = E('div', { 'class': theme.getDashboardClass() }, [
this.renderHeader(status),
this.renderNav('overview'),
E('div', { 'id': 'cs-stats' }, this.renderStats(status)),

View File

@ -4,7 +4,7 @@
'require ui';
'require uci';
'require crowdsec-dashboard.api as api';
'require crowdsec-dashboard.theme as ThemeClass';
'require crowdsec-dashboard.theme as theme';
/**
* CrowdSec SOC - Settings View
@ -12,19 +12,15 @@
* With theme/appearance settings
*/
var themeInstance = new ThemeClass();
return view.extend({
title: _('Settings'),
status: {},
machines: [],
collections: [],
theme: themeInstance,
load: function() {
var self = this;
return Promise.all([
self.theme.init(),
theme.init(),
api.getStatus(),
api.getMachines(),
api.getCollections(),
@ -46,7 +42,7 @@ return view.extend({
document.body.classList.add('cs-fullwidth');
return E('div', { 'class': self.theme.getDashboardClass() }, [
return E('div', { 'class': theme.getDashboardClass() }, [
this.renderHeader(),
this.renderNav('settings'),
E('div', { 'class': 'cs-stats' }, this.renderServiceStats()),
@ -93,8 +89,8 @@ return view.extend({
var currentTheme = uci.get('crowdsec-dashboard', 'main', 'theme') || 'classic';
var currentProfile = uci.get('crowdsec-dashboard', 'main', 'profile') || 'default';
var themes = this.theme.getThemes();
var profiles = this.theme.getProfiles();
var themes = theme.getThemes();
var profiles = theme.getProfiles();
return E('div', {}, [
E('div', { 'style': 'margin-bottom: 16px;' }, [
@ -131,11 +127,11 @@ return view.extend({
},
previewTheme: function(themeName) {
this.theme.switchTheme(themeName);
theme.switchTheme(themeName);
},
previewProfile: function(profileName) {
this.theme.switchProfile(profileName);
theme.switchProfile(profileName);
},
saveAppearance: function() {