mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 13:05:13 +08:00
⛄ Sync 2026-04-23 20:32:35
This commit is contained in:
1 parent
ac97aa196d
commit
618f49f6ca
206 files changed
+725671
No files matched your search
@@ -0,0 +1,390 @@
|
||||
'use strict';
|
||||
'require view';
|
||||
'require fs';
|
||||
'require poll';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require rpc';
|
||||
'require form';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
const callRcList = rpc.declare({
|
||||
object: 'rc',
|
||||
method: 'list',
|
||||
params: [ 'name' ],
|
||||
expect: { '': {} },
|
||||
filter(res) {
|
||||
for (var k in res)
|
||||
return +res[k].enabled;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
const callRcInit = rpc.declare({
|
||||
object: 'rc',
|
||||
method: 'init',
|
||||
params: [ 'name', 'action' ],
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
const callGetUnixtime = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getUnixtime',
|
||||
expect: { result: 0 }
|
||||
});
|
||||
|
||||
const callSetLocaltime = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setLocaltime',
|
||||
params: [ 'localtime' ],
|
||||
expect: { result: 0 }
|
||||
});
|
||||
|
||||
const callTimezone = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTimezones',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function formatTime(epoch) {
|
||||
const date = new Date(epoch * 1000);
|
||||
const zn = uci.get('system', '@system[0]', 'zonename')?.replaceAll(' ', '_') || 'UTC';
|
||||
const ts = uci.get('system', '@system[0]', 'clock_timestyle') || 0;
|
||||
const hc = uci.get('system', '@system[0]', 'clock_hourcycle') || 0;
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: 'medium',
|
||||
timeStyle: (ts == 0) ? 'long' : 'full',
|
||||
hourCycle: (hc == 0) ? undefined : hc,
|
||||
timeZone: zn
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
const CBILocalTime = form.DummyValue.extend({
|
||||
renderWidget(section_id, option_id, cfgvalue) {
|
||||
return E([], [
|
||||
E('input', {
|
||||
'id': 'localtime',
|
||||
'type': 'text',
|
||||
'readonly': true,
|
||||
'value': formatTime(cfgvalue)
|
||||
}),
|
||||
E('br'),
|
||||
E('span', { 'class': 'control-group' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-apply',
|
||||
'click': ui.createHandlerFn(this, function() {
|
||||
return callSetLocaltime(Math.floor(Date.now() / 1000));
|
||||
}),
|
||||
'disabled': (this.readonly != null) ? this.readonly : this.map.readonly
|
||||
}, _('Sync with browser')),
|
||||
' ',
|
||||
this.ntpd_support ? E('button', {
|
||||
'class': 'cbi-button cbi-button-apply',
|
||||
'click': ui.createHandlerFn(this, function() {
|
||||
return callRcInit('sysntpd', 'restart');
|
||||
}),
|
||||
'disabled': (this.readonly != null) ? this.readonly : this.map.readonly
|
||||
}, _('Sync with NTP-Server')) : ''
|
||||
])
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load() {
|
||||
return Promise.all([
|
||||
callRcList('sysntpd'),
|
||||
callTimezone(),
|
||||
callGetUnixtime(),
|
||||
uci.load('luci'),
|
||||
uci.load('system'),
|
||||
L.hasSystemFeature('zram')
|
||||
? L.resolveDefault(fs.read('/sys/block/zram0/comp_algorithm'), '')
|
||||
: ''
|
||||
]);
|
||||
},
|
||||
|
||||
render([ntpd_enabled, timezones, unixtime, _luci, _system, zram_algorithms]) {
|
||||
let m, s, o;
|
||||
const system_section = uci.sections('system', 'system')[0];
|
||||
|
||||
m = new form.Map('system',
|
||||
_('System'),
|
||||
_('Here you can configure the basic aspects of your device like its hostname or the timezone.'));
|
||||
this.map = m;
|
||||
this.systemSid = system_section?.['.name'];
|
||||
|
||||
m.chain('luci');
|
||||
|
||||
s = m.section(form.TypedSection, 'system', _('System Properties'));
|
||||
s.anonymous = true;
|
||||
s.addremove = false;
|
||||
|
||||
s.tab('general', _('General Settings'));
|
||||
s.tab('logging', _('Logging'));
|
||||
s.tab('timesync', _('Time Synchronization'));
|
||||
s.tab('language', _('Language and Style'));
|
||||
|
||||
/*
|
||||
* System Properties
|
||||
*/
|
||||
|
||||
o = s.taboption('general', CBILocalTime, '_systime', _('Local Time'));
|
||||
o.cfgvalue = function() { return unixtime };
|
||||
o.ntpd_support = ntpd_enabled;
|
||||
|
||||
o = s.taboption('general', form.Value, 'hostname', _('Hostname'));
|
||||
o.datatype = 'hostname';
|
||||
|
||||
/* could be used also as a default for LLDP, SNMP "system description" in the future */
|
||||
o = s.taboption('general', form.Value, 'description', _('Description'), _('An optional, short description for this device'));
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('general', form.TextValue, 'notes', _('Notes'), _('Optional, free-form notes about this device'));
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'zonename', _('Timezone'));
|
||||
o.value('UTC');
|
||||
|
||||
const zones = Object.keys(timezones || {}).sort();
|
||||
for (let zone of zones)
|
||||
o.value(zone);
|
||||
|
||||
o.write = function(section_id, formvalue) {
|
||||
const tz = timezones[formvalue] ? timezones[formvalue].tzstring : null;
|
||||
uci.set('system', section_id, 'zonename', formvalue);
|
||||
uci.set('system', section_id, 'timezone', tz);
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Flag, 'clock_timestyle', _('Full TimeZone Name'), _('Unchecked means the timezone offset (E.g. GMT+1) is displayed'));
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'clock_hourcycle', _('Time Format'));
|
||||
o.value('', _('Default'));
|
||||
o.value('h12', _('12-Hour Clock'));
|
||||
o.value('h23', _('24-Hour Clock'));
|
||||
|
||||
/*
|
||||
* Logging
|
||||
*/
|
||||
|
||||
o = s.taboption('logging', form.Value, 'log_size', _('System log buffer size'), "kiB");
|
||||
o.optional = true;
|
||||
o.placeholder = 128;
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('logging', form.Value, 'log_ip', _('External system log server'));
|
||||
o.optional = true;
|
||||
o.placeholder = '0.0.0.0';
|
||||
o.datatype = 'host';
|
||||
|
||||
o = s.taboption('logging', form.Value, 'log_port', _('External system log server port'));
|
||||
o.optional = true;
|
||||
o.placeholder = 514;
|
||||
o.datatype = 'port';
|
||||
|
||||
o = s.taboption('logging', form.ListValue, 'log_proto', _('External system log server protocol'));
|
||||
o.value('udp', 'UDP');
|
||||
o.value('tcp', 'TCP');
|
||||
|
||||
o = s.taboption('logging', form.Value, 'log_file', _('Write system log to file'));
|
||||
o.optional = true;
|
||||
o.placeholder = '/tmp/system.log';
|
||||
|
||||
o = s.taboption('logging', form.ListValue, 'conloglevel', _('Log output level'), _('Only affects dmesg kernel log'));
|
||||
o.value(8, _('Debug'));
|
||||
o.value(7, _('Info'));
|
||||
o.value(6, _('Notice'));
|
||||
o.value(5, _('Warning'));
|
||||
o.value(4, _('Error'));
|
||||
o.value(3, _('Critical'));
|
||||
o.value(2, _('Alert'));
|
||||
o.value(1, _('Emergency'));
|
||||
|
||||
o = s.taboption('logging', form.ListValue, 'cronloglevel', _('Cron Log Level'));
|
||||
o.default = 7;
|
||||
o.value(7, _('Normal'));
|
||||
o.value(9, _('Disabled'));
|
||||
o.value(5, _('Debug'));
|
||||
|
||||
/*
|
||||
* Zram Properties
|
||||
*/
|
||||
|
||||
if (L.hasSystemFeature('zram')) {
|
||||
s.tab('zram', _('ZRam Settings'));
|
||||
|
||||
o = s.taboption('zram', form.Flag, 'zram_enabled', _('Enable'));
|
||||
o.enabled = '1';
|
||||
o.disabled = '0';
|
||||
o.default = '1';
|
||||
o.rmempty = false;
|
||||
o.cfgvalue = function(section_id) {
|
||||
return String(uci.get('system', section_id, 'zram_enabled') ?? '1');
|
||||
};
|
||||
|
||||
o = s.taboption('zram', form.Value, 'zram_size_mb', _('ZRam Size'), _('Size of the ZRam device in megabytes'));
|
||||
o.optional = true;
|
||||
o.placeholder = 16;
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('zram_enabled', '1');
|
||||
|
||||
const supported_algorithms = String(zram_algorithms || '')
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.map(algo => algo.replace(/[\[\]]/g, ''))
|
||||
.filter((algo, index, list) => algo && list.indexOf(algo) === index);
|
||||
const current_algorithm = uci.get('system', '@system[0]', 'zram_comp_algo');
|
||||
|
||||
o = s.taboption('zram', form.ListValue, 'zram_comp_algo', _('ZRam Compression Algorithm'));
|
||||
o.optional = true;
|
||||
o.default = current_algorithm || supported_algorithms[0] || 'lzo';
|
||||
o.depends('zram_enabled', '1');
|
||||
|
||||
if (!supported_algorithms.length) {
|
||||
[ 'lzo', 'lz4', 'zstd' ].forEach(algo => o.value(algo, algo));
|
||||
}
|
||||
else {
|
||||
supported_algorithms.forEach(algo => o.value(algo, algo));
|
||||
|
||||
if (current_algorithm && supported_algorithms.indexOf(current_algorithm) < 0)
|
||||
o.value(current_algorithm, '%s (%s)'.format(current_algorithm, _('unsupported')));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Language & Style
|
||||
*/
|
||||
|
||||
o = s.taboption('language', form.ListValue, '_lang', _('Language'))
|
||||
o.uciconfig = 'luci';
|
||||
o.ucisection = 'main';
|
||||
o.ucioption = 'lang';
|
||||
o.value('auto', _('auto'));
|
||||
|
||||
const l = Object.assign({ en: 'English' }, uci.get('luci', 'languages'));
|
||||
const keys = Object.keys(l).sort();
|
||||
for (let k of keys)
|
||||
if (k.charAt(0) != '.')
|
||||
o.value(k, l[k]);
|
||||
|
||||
o = s.taboption('language', form.ListValue, '_mediaurlbase', _('Design'))
|
||||
o.uciconfig = 'luci';
|
||||
o.ucisection = 'main';
|
||||
o.ucioption = 'mediaurlbase';
|
||||
|
||||
const th = Object.keys(uci.get('luci', 'themes') || {}).sort();
|
||||
for (let t of th)
|
||||
if (t.charAt(0) != '.')
|
||||
o.value(uci.get('luci', 'themes', t), t);
|
||||
|
||||
o = s.taboption('language', form.Flag, '_tablefilters', _('Table Filters'));
|
||||
o.default = o.disabled;
|
||||
o.uciconfig = 'luci';
|
||||
o.ucisection = 'main';
|
||||
o.ucioption = 'tablefilters';
|
||||
|
||||
/*
|
||||
* NTP
|
||||
*/
|
||||
|
||||
if (L.hasSystemFeature('sysntpd')) {
|
||||
var default_servers = [
|
||||
'0.openwrt.pool.ntp.org', '1.openwrt.pool.ntp.org',
|
||||
'2.openwrt.pool.ntp.org', '3.openwrt.pool.ntp.org'
|
||||
];
|
||||
|
||||
o = s.taboption('timesync', form.Flag, 'enabled', _('Enable NTP client'));
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'ntp';
|
||||
o.default = o.disabled;
|
||||
o.write = function(section_id, value) {
|
||||
ntpd_enabled = +value;
|
||||
|
||||
if (ntpd_enabled && !uci.get('system', 'ntp')) {
|
||||
uci.add('system', 'timeserver', 'ntp');
|
||||
uci.set('system', 'ntp', 'server', default_servers);
|
||||
}
|
||||
|
||||
if (!ntpd_enabled)
|
||||
uci.set('system', 'ntp', 'enabled', 0);
|
||||
else
|
||||
uci.unset('system', 'ntp', 'enabled');
|
||||
|
||||
return callRcInit('sysntpd', 'enable');
|
||||
};
|
||||
o.load = function(section_id) {
|
||||
return (ntpd_enabled == 1 &&
|
||||
uci.get('system', 'ntp') != null &&
|
||||
uci.get('system', 'ntp', 'enabled') != 0) ? '1' : '0';
|
||||
};
|
||||
|
||||
o = s.taboption('timesync', form.Flag, 'enable_server', _('Provide NTP server'));
|
||||
o.ucisection = 'ntp';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.taboption('timesync', widgets.NetworkSelect, 'interface',
|
||||
_('Bind NTP server'),
|
||||
_('Provide the NTP server to the selected interface or, if unspecified, to all interfaces'));
|
||||
o.ucisection = 'ntp';
|
||||
o.depends('enable_server', '1');
|
||||
o.multiple = false;
|
||||
o.nocreate = true;
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('timesync', form.Flag, 'use_dhcp', _('Use DHCP advertised servers'));
|
||||
o.ucisection = 'ntp';
|
||||
o.default = o.enabled;
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.taboption('timesync', form.DynamicList, 'server', _('NTP server candidates'),
|
||||
_('List of upstream NTP server candidates with which to synchronize.'));
|
||||
o.datatype = 'host(0)';
|
||||
o.ucisection = 'ntp';
|
||||
o.depends('enabled', '1');
|
||||
o.load = function(section_id) {
|
||||
return uci.get('system', 'ntp', 'server');
|
||||
};
|
||||
}
|
||||
|
||||
return m.render().then(function(mapEl) {
|
||||
poll.add(function() {
|
||||
return callGetUnixtime().then(function(t) {
|
||||
mapEl.querySelector('#localtime').value = formatTime(t);
|
||||
});
|
||||
});
|
||||
|
||||
return mapEl;
|
||||
});
|
||||
},
|
||||
|
||||
isZramChanged() {
|
||||
if (!L.hasSystemFeature('zram') || !this.map || !this.systemSid)
|
||||
return false;
|
||||
|
||||
const enabled = this.map.lookupOption('zram_enabled', this.systemSid);
|
||||
const size = this.map.lookupOption('zram_size_mb', this.systemSid);
|
||||
const algo = this.map.lookupOption('zram_comp_algo', this.systemSid);
|
||||
const current_enabled = String(uci.get('system', '@system[0]', 'zram_enabled') ?? '1');
|
||||
const current_size = String(uci.get('system', '@system[0]', 'zram_size_mb') ?? '');
|
||||
const current_algo = String(uci.get('system', '@system[0]', 'zram_comp_algo') ?? '');
|
||||
const form_enabled = String(enabled ? (enabled[0].formvalue(enabled[1]) ?? '') : current_enabled);
|
||||
const form_size = String(size ? (size[0].formvalue(size[1]) ?? '') : current_size);
|
||||
const form_algo = String(algo ? (algo[0].formvalue(algo[1]) ?? '') : current_algo);
|
||||
|
||||
return (form_enabled !== current_enabled || form_size !== current_size || form_algo !== current_algo);
|
||||
},
|
||||
|
||||
handleSaveApply(ev, mode) {
|
||||
if (this.isZramChanged()) {
|
||||
const fn = L.bind(() => {
|
||||
callRcInit('zram', 'restart');
|
||||
document.removeEventListener('uci-applied', fn);
|
||||
});
|
||||
|
||||
document.addEventListener('uci-applied', fn);
|
||||
}
|
||||
|
||||
return this.super('handleSaveApply', [ev, mode]);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user