secubox-openwrt/package/secubox/luci-app-traffic-shaper/htdocs/luci-static/resources/view/traffic-shaper/presets.js
CyberMind-FR 31a87c5d7a feat(structure): reorganize luci-app packages into package/secubox/ + appstore migration
Major structural reorganization and feature additions:

## Folder Reorganization
- Move 17 luci-app-* packages to package/secubox/ (except luci-app-secubox core hub)
- Update all tooling to support new structure:
  - secubox-tools/quick-deploy.sh: search both locations
  - secubox-tools/validate-modules.sh: validate both directories
  - secubox-tools/fix-permissions.sh: fix permissions in both locations
  - .github/workflows/test-validate.yml: build from both paths
- Update README.md links to new package/secubox/ paths

## AppStore Migration (Complete)
- Add catalog entries for all remaining luci-app packages:
  - network-tweaks.json: Network optimization tools
  - secubox-bonus.json: Documentation & demos hub
- Total: 24 apps in AppStore catalog (22 existing + 2 new)
- New category: 'documentation' for docs/demos/tutorials

## VHost Manager v2.0 Enhancements
- Add profile activation system for Internal Services and Redirects
- Implement createVHost() API wrapper for template-based deployment
- Fix Virtual Hosts view rendering with proper LuCI patterns
- Fix RPCD backend shell script errors (remove invalid local declarations)
- Extend backend validation for nginx return directives (redirect support)
- Add section_id parameter for named VHost profiles
- Add Remove button to Redirects page for feature parity
- Update README to v2.0 with comprehensive feature documentation

## Network Tweaks Dashboard
- Close button added to component details modal

Files changed: 340+ (336 renames with preserved git history)
Packages affected: 19 luci-app, 2 secubox-app, 1 theme, 4 tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 14:59:38 +01:00

194 lines
6.3 KiB
JavaScript

'use strict';
'require view';
'require secubox-theme/theme as Theme';
'require ui';
'require dom';
'require traffic-shaper/api as API';
return view.extend({
load: function() {
return API.listPresets();
},
render: function(data) {
var presets = data.presets || [];
var container = E('div', { 'class': 'traffic-shaper-dashboard' }, [
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox-theme/secubox-theme.css') }),
E('h2', {}, _('Traffic Shaping Presets')),
E('div', { 'class': 'cbi-section' }, [
E('p', {}, _('Apply pre-configured traffic shaping profiles optimized for common use cases. Applying a preset will replace your current configuration.')),
E('p', { 'style': 'background: #fff3cd; padding: 0.75em; border-left: 4px solid #ffc107;' }, [
E('strong', {}, _('Warning:')),
' ',
_('Applying a preset will overwrite all existing traffic classes and rules.')
])
]),
E('div', { 'class': 'ts-preset-grid' },
presets.length > 0 ?
presets.map(L.bind(this.renderPresetCard, this)) :
this.renderDefaultPresets()
)
]);
return container;
},
renderPresetCard: function(preset) {
return E('div', { 'class': 'ts-preset-card' }, [
E('div', { 'class': 'ts-preset-title' }, preset.name || preset.id),
E('div', { 'class': 'ts-preset-description' }, preset.description || ''),
E('div', { 'style': 'margin: 1em 0; padding: 1em; background: #f8f9fa; border-radius: 4px;' }, [
E('strong', {}, _('Configuration:')),
E('ul', { 'style': 'margin: 0.5em 0 0 0; padding-left: 1.5em;' },
(preset.classes || []).map(function(cls) {
return E('li', {}, '%s: %s (priority %s)'.format(
cls.name,
cls.rate + ' → ' + cls.ceil,
cls.priority
));
})
)
]),
E('div', { 'class': 'ts-preset-apply' }, [
E('button', {
'class': 'ts-btn ts-btn-success',
'click': L.bind(function(ev) {
this.handleApplyPreset(ev, preset.id);
}, this)
}, _('Apply This Preset'))
])
]);
},
renderDefaultPresets: function() {
// Fallback presets if backend doesn't provide them
var defaultPresets = [
{
id: 'gaming',
name: _('Gaming & Low-Latency'),
description: _('Optimized for online gaming, VoIP, and real-time applications. Prioritizes UDP and low-latency traffic.'),
classes: [
{ name: _('Gaming/VoIP'), priority: '1', rate: '5mbit', ceil: '50mbit' },
{ name: _('Interactive'), priority: '3', rate: '10mbit', ceil: '80mbit' },
{ name: _('Streaming'), priority: '5', rate: '8mbit', ceil: '60mbit' },
{ name: _('Bulk Downloads'), priority: '8', rate: '2mbit', ceil: '30mbit' }
]
},
{
id: 'streaming',
name: _('Video Streaming'),
description: _('Optimized for video streaming services like Netflix, YouTube, and video conferencing. Ensures smooth playback.'),
classes: [
{ name: _('Video Conference'), priority: '2', rate: '10mbit', ceil: '60mbit' },
{ name: _('Video Streaming'), priority: '3', rate: '15mbit', ceil: '80mbit' },
{ name: _('Web Browsing'), priority: '5', rate: '5mbit', ceil: '50mbit' },
{ name: _('Background'), priority: '7', rate: '2mbit', ceil: '30mbit' }
]
},
{
id: 'work_from_home',
name: _('Work From Home'),
description: _('Balanced configuration for remote work. Prioritizes video calls, VPN, and web applications while allowing downloads.'),
classes: [
{ name: _('Video Calls'), priority: '1', rate: '8mbit', ceil: '50mbit' },
{ name: _('VPN Traffic'), priority: '2', rate: '10mbit', ceil: '60mbit' },
{ name: _('Web/Email'), priority: '4', rate: '8mbit', ceil: '70mbit' },
{ name: _('Downloads'), priority: '6', rate: '5mbit', ceil: '40mbit' }
]
},
{
id: 'balanced',
name: _('Balanced (Default)'),
description: _('General-purpose configuration that works well for most households. Equal priority for common applications.'),
classes: [
{ name: _('High Priority'), priority: '2', rate: '10mbit', ceil: '60mbit' },
{ name: _('Normal Traffic'), priority: '5', rate: '15mbit', ceil: '80mbit' },
{ name: _('Bulk Transfer'), priority: '7', rate: '5mbit', ceil: '50mbit' }
]
}
];
return defaultPresets.map(L.bind(this.renderPresetCard, this));
},
handleApplyPreset: function(ev, presetId) {
var btn = ev.target;
ui.showModal(_('Apply Preset'), [
E('p', {}, _('Are you sure you want to apply this preset? This will:')),
E('ul', {}, [
E('li', {}, _('Delete all existing traffic classes')),
E('li', {}, _('Delete all existing classification rules')),
E('li', {}, _('Create new classes from the preset')),
E('li', {}, _('Apply the new configuration immediately'))
]),
E('p', { 'style': 'font-weight: bold; color: #dc3545;' },
_('This action cannot be undone!')),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': L.bind(function() {
ui.hideModal();
this.applyPreset(presetId, btn);
}, this)
}, _('Yes, Apply Preset'))
])
]);
},
applyPreset: function(presetId, btn) {
var originalText = btn.textContent;
btn.disabled = true;
btn.textContent = _('Applying...');
ui.showModal(_('Applying Preset'), [
E('p', { 'class': 'spinning' }, _('Applying preset configuration...'))
], null, null, { 'spinning': true });
API.applyPreset(presetId).then(L.bind(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null,
E('p', _('Preset applied successfully! Traffic shaping has been reconfigured.')),
'info'
);
// Redirect to overview after 2 seconds
setTimeout(function() {
window.location.href = L.url('admin/network/traffic-shaper/overview');
}, 2000);
} else {
ui.addNotification(null,
E('p', _('Failed to apply preset: %s').format(result.message || _('Unknown error'))),
'error'
);
btn.disabled = false;
btn.textContent = originalText;
}
}, this)).catch(L.bind(function(err) {
ui.hideModal();
ui.addNotification(null,
E('p', _('Error applying preset: %s').format(err.message || err)),
'error'
);
btn.disabled = false;
btn.textContent = originalText;
}, this));
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});