fix: Release v0.4.4 - Improved version handling and helpers refactoring
This release focuses on consistent version display across all modules and proper OOP structure for network-modes helpers. ## Version Display Improvements (3 files) Added robust version resolution functions to handle various version field names: **SecuBox Dashboard** (dashboard.js): - Added getModuleVersion() function with fallback chain - Checks: version, pkg_version, package_version, packageVersion, Version - Handles both string and number types - Returns '—' if no version found - Loads modules list from API for accurate version data **SecuBox Modules** (modules.js): - Added resolveModuleVersion() function with same fallback logic - Ensures consistent version display in module cards - Handles missing or undefined versions gracefully **System Hub Components** (components.js): - Added getComponentVersion() function with version fallback chain - Consistent version display across all components - Proper handling of edge cases (null, undefined, empty strings) ## Network Modes Refactoring (1 file) **helpers.js**: - Refactored from plain object export to baseclass.extend() - Proper OOP structure following LuCI conventions - Added 'require baseclass' import - All helper functions now properly encapsulated - Better integration with LuCI module system ## Benefits - Consistent version display across SecuBox, System Hub, and Components - Handles version field name variations (legacy, OpenWrt, custom) - Type-safe version handling (numbers → strings) - Improved code maintainability with proper OOP structure - Better error handling for missing version information Summary: - 4 files changed (+85, -8) - 3 new version resolution functions - 1 OOP refactoring for helpers - Improved consistency and reliability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
de40c8e533
commit
a9fca35644
@ -1,4 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
'require baseclass';
|
||||||
'require ui';
|
'require ui';
|
||||||
'require network-modes.api as api';
|
'require network-modes.api as api';
|
||||||
|
|
||||||
@ -156,7 +157,7 @@ function createNavigationTabs(activeId) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return baseclass.extend({
|
||||||
isToggleActive: isToggleActive,
|
isToggleActive: isToggleActive,
|
||||||
persistSettings: persistSettings,
|
persistSettings: persistSettings,
|
||||||
showGeneratedConfig: showGeneratedConfig,
|
showGeneratedConfig: showGeneratedConfig,
|
||||||
@ -166,4 +167,4 @@ return {
|
|||||||
createList: createList,
|
createList: createList,
|
||||||
createStepper: createStepper,
|
createStepper: createStepper,
|
||||||
createNavigationTabs: createNavigationTabs
|
createNavigationTabs: createNavigationTabs
|
||||||
};
|
});
|
||||||
|
|||||||
@ -22,6 +22,7 @@ return view.extend({
|
|||||||
dashboardData: null,
|
dashboardData: null,
|
||||||
healthData: null,
|
healthData: null,
|
||||||
alertsData: null,
|
alertsData: null,
|
||||||
|
modulesList: [],
|
||||||
activeCategory: 'all',
|
activeCategory: 'all',
|
||||||
|
|
||||||
load: function() {
|
load: function() {
|
||||||
@ -33,11 +34,13 @@ return view.extend({
|
|||||||
return Promise.all([
|
return Promise.all([
|
||||||
API.getDashboardData(),
|
API.getDashboardData(),
|
||||||
API.getSystemHealth(),
|
API.getSystemHealth(),
|
||||||
API.getAlerts()
|
API.getAlerts(),
|
||||||
|
API.getModules()
|
||||||
]).then(function(data) {
|
]).then(function(data) {
|
||||||
self.dashboardData = data[0] || {};
|
self.dashboardData = data[0] || {};
|
||||||
self.healthData = data[1] || {};
|
self.healthData = data[1] || {};
|
||||||
self.alertsData = data[2] || {};
|
self.alertsData = data[2] || {};
|
||||||
|
self.modulesList = (data[3] && data[3].modules) || [];
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -157,7 +160,9 @@ return view.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getFilteredModules: function() {
|
getFilteredModules: function() {
|
||||||
var modules = this.dashboardData.modules || [];
|
var modules = (this.modulesList && this.modulesList.length)
|
||||||
|
? this.modulesList
|
||||||
|
: (this.dashboardData.modules || []);
|
||||||
if (this.activeCategory === 'all')
|
if (this.activeCategory === 'all')
|
||||||
return modules;
|
return modules;
|
||||||
return modules.filter(function(module) {
|
return modules.filter(function(module) {
|
||||||
@ -165,6 +170,29 @@ return view.extend({
|
|||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getModuleVersion: function(module) {
|
||||||
|
if (!module)
|
||||||
|
return '—';
|
||||||
|
|
||||||
|
var candidates = [
|
||||||
|
module.version,
|
||||||
|
module.pkg_version,
|
||||||
|
module.package_version,
|
||||||
|
module.packageVersion,
|
||||||
|
module.Version
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < candidates.length; i++) {
|
||||||
|
var value = candidates[i];
|
||||||
|
if (typeof value === 'number')
|
||||||
|
return String(value);
|
||||||
|
if (typeof value === 'string' && value.trim())
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '—';
|
||||||
|
},
|
||||||
|
|
||||||
renderModuleCard: function(module) {
|
renderModuleCard: function(module) {
|
||||||
var status = module.status || 'unknown';
|
var status = module.status || 'unknown';
|
||||||
var statusLabel = status === 'active' ? _('Running') :
|
var statusLabel = status === 'active' ? _('Running') :
|
||||||
@ -180,8 +208,8 @@ return view.extend({
|
|||||||
]),
|
]),
|
||||||
E('span', { 'class': 'sb-status-pill' }, statusLabel)
|
E('span', { 'class': 'sb-status-pill' }, statusLabel)
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'sb-module-meta' }, [
|
E('div', { 'class': 'sb-module-meta' }, [
|
||||||
E('span', {}, _('Version: ') + (module.version || '0.0.0')),
|
E('span', {}, _('Version: ') + this.getModuleVersion(module)),
|
||||||
E('span', {}, _('Category: ') + (module.category || 'other'))
|
E('span', {}, _('Category: ') + (module.category || 'other'))
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'sb-module-actions' }, [
|
E('div', { 'class': 'sb-module-actions' }, [
|
||||||
|
|||||||
@ -159,6 +159,29 @@ return view.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resolveModuleVersion: function(module) {
|
||||||
|
if (!module)
|
||||||
|
return '—';
|
||||||
|
|
||||||
|
var candidates = [
|
||||||
|
module.version,
|
||||||
|
module.pkg_version,
|
||||||
|
module.package_version,
|
||||||
|
module.packageVersion,
|
||||||
|
module.Version
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < candidates.length; i++) {
|
||||||
|
var value = candidates[i];
|
||||||
|
if (typeof value === 'number')
|
||||||
|
return String(value);
|
||||||
|
if (typeof value === 'string' && value.trim())
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '—';
|
||||||
|
},
|
||||||
|
|
||||||
renderModuleCard: function(module) {
|
renderModuleCard: function(module) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var status = module.status || 'unknown';
|
var status = module.status || 'unknown';
|
||||||
@ -175,6 +198,7 @@ return view.extend({
|
|||||||
};
|
};
|
||||||
|
|
||||||
var statusLabel = isInstalled ? (statusLabels[status] || '○ Désactivé') : statusLabels['not-installed'];
|
var statusLabel = isInstalled ? (statusLabels[status] || '○ Désactivé') : statusLabels['not-installed'];
|
||||||
|
var versionLabel = this.resolveModuleVersion(module);
|
||||||
|
|
||||||
return E('div', {
|
return E('div', {
|
||||||
'class': 'secubox-module-card secubox-module-' + statusClass,
|
'class': 'secubox-module-card secubox-module-' + statusClass,
|
||||||
@ -189,7 +213,7 @@ return view.extend({
|
|||||||
E('span', { 'class': 'secubox-module-category' },
|
E('span', { 'class': 'secubox-module-category' },
|
||||||
this.getCategoryIcon(module.category) + ' ' + (module.category || 'other')),
|
this.getCategoryIcon(module.category) + ' ' + (module.category || 'other')),
|
||||||
E('span', { 'class': 'secubox-module-version' },
|
E('span', { 'class': 'secubox-module-version' },
|
||||||
'v' + (module.version || '0.0.9'))
|
versionLabel === '—' ? versionLabel : 'v' + versionLabel)
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
E('div', {
|
E('div', {
|
||||||
|
|||||||
@ -114,11 +114,35 @@ return view.extend({
|
|||||||
return filtered.map(L.bind(this.renderComponentCard, this));
|
return filtered.map(L.bind(this.renderComponentCard, this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getComponentVersion: function(component) {
|
||||||
|
if (!component)
|
||||||
|
return '—';
|
||||||
|
|
||||||
|
var candidates = [
|
||||||
|
component.version,
|
||||||
|
component.pkg_version,
|
||||||
|
component.package_version,
|
||||||
|
component.packageVersion,
|
||||||
|
component.Version
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < candidates.length; i++) {
|
||||||
|
var value = candidates[i];
|
||||||
|
if (typeof value === 'number')
|
||||||
|
return String(value);
|
||||||
|
if (typeof value === 'string' && value.trim())
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '—';
|
||||||
|
},
|
||||||
|
|
||||||
renderComponentCard: function(component) {
|
renderComponentCard: function(component) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var isRunning = component.running;
|
var isRunning = component.running;
|
||||||
var isInstalled = component.installed;
|
var isInstalled = component.installed;
|
||||||
var statusClass = isRunning ? 'running' : (isInstalled ? 'stopped' : 'not-installed');
|
var statusClass = isRunning ? 'running' : (isInstalled ? 'stopped' : 'not-installed');
|
||||||
|
var versionLabel = this.getComponentVersion(component);
|
||||||
|
|
||||||
return E('div', {
|
return E('div', {
|
||||||
'class': 'sh-component-card sh-component-' + statusClass,
|
'class': 'sh-component-card sh-component-' + statusClass,
|
||||||
@ -130,7 +154,7 @@ return view.extend({
|
|||||||
E('h3', { 'class': 'sh-component-name' }, component.name || component.id),
|
E('h3', { 'class': 'sh-component-name' }, component.name || component.id),
|
||||||
E('div', { 'class': 'sh-component-meta' }, [
|
E('div', { 'class': 'sh-component-meta' }, [
|
||||||
E('span', { 'class': 'sh-component-version' },
|
E('span', { 'class': 'sh-component-version' },
|
||||||
'v' + (component.version || '0.0.9')),
|
versionLabel === '—' ? versionLabel : 'v' + versionLabel),
|
||||||
E('span', { 'class': 'sh-component-category' },
|
E('span', { 'class': 'sh-component-category' },
|
||||||
component.category || 'other')
|
component.category || 'other')
|
||||||
])
|
])
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user