'use strict'; 'require view'; 'require poll'; 'require fs'; 'require uci'; 'require ui'; 'require dom'; 'require rpc'; 'require form'; const mntpkgs = '/mnt/packagesync'; const mntreg = RegExp(/\/mnt\/packagesync/); const conf = 'packagesync'; const release = 'release'; const instance = 'sync'; const callServiceList = rpc.declare({ object: 'service', method: 'list', params: ['name'], expect: { '': {} } }); function getServiceStatus() { return L.resolveDefault(callServiceList(conf), {}) .then((res) => { let isrunning = false; try { isrunning = res[conf]['instances'][instance]['running']; } catch (e) { } return isrunning; }); } return view.extend({ // handleSaveApply: null, // handleSave: null, // handleReset: null, load() { return Promise.all([ L.resolveDefault(fs.read('/var/packagesync/releaseslist'), null), L.resolveDefault(fs.read('/var/packagesync/targetslist'), null), L.resolveDefault(fs.read('/var/packagesync/pkgarchslist'), null), L.resolveDefault(fs.stat('/var/run/packagesync.pid'), {}), L.resolveDefault(fs.exec('/etc/init.d/packagesync', ['checkln']), {}), L.resolveDefault(fs.exec('/bin/df', ['-hT']), {}), getServiceStatus(), uci.load('packagesync') ]); }, poll_status(nodes, stat) { const isRunning = stat[0]; let view = nodes.querySelector('#sync_status'); if (isRunning) { view.innerHTML = "" + _("SYNC IN PROGRESS") + ""; } else { view.innerHTML = "" + _("SYNC NOT IN PROGRESS") + ""; } return; }, render(res) { const releaseslist = res[0] ? res[0].trim().split("\n") : []; const targetslist = res[1] ? res[1].trim().split("\n") : []; const pkgarchslist = res[2] ? res[2].trim().split("\n") : []; const locked = res[3].path; const usedname = res[4].stdout ? res[4].stdout.trim().split("\n") : []; const storages = res[5].stdout ? res[5].stdout.trim().split("\n") : []; const isRunning = res[6]; let storage = []; if (storages.length) { for (let i = 1; i < storages.length; i++) { if (storages[i].match(mntreg)) { storage = storages[i].trim().split(/\s+/, 7); break; } } }; let m, s, o; m = new form.Map('packagesync'); s = m.section(form.NamedSection, 'config', 'packagesync', _('Local software source'), _('packagesync used to build a local mirror feeds source on the router
\ To use packagesync, you need to prepare a storage device with a size of at least 16G and connect it to the router
\ then open Mount Points, find the connected device and set its mount point to %s, check Enabled and click Save&Apple') .format(L.url('admin', 'system', 'mounts'), mntpkgs)); s.anonymous = true; o = s.option(form.DummyValue, '_status', _('Running Status')); o.rawhtml = true; if (isRunning) { o.cfgvalue = function(s) { return E('div', { class: 'cbi-section' }, [ E('div', { id: 'sync_status' }, [ E('span', { 'style': 'color:green;font-weight:bold' }, [ _("SYNC IN PROGRESS") ]) ]) ]); } } else { o.cfgvalue = function(s) { return E('div', { class: 'cbi-section' }, [ E('div', { id: 'sync_status' }, [ E('span', { 'style': 'color:red;font-weight:bold' }, [ _("SYNC NOT IN PROGRESS") ]) ]) ]); } }; o = s.option(form.Value, 'home_url', _('Home URL'), _('Open URL').format(uci.get('packagesync', '@packagesync[0]', 'home_url'))); o.placeholder = 'packagesync'; o.rmempty = false; o.validate = function(section, value) { if (usedname.length) for (let i = 0; i < usedname.length; i++) if (usedname[i] == value) return _('The Name %h is already used').format(value); return true; }; o.write = function(section, value) { uci.set('packagesync', section, 'home_url', value); fs.exec('/etc/init.d/packagesync', ['symln', value]); }; o = s.option(form.Button, '_exec_now', _('Execute')); o.inputtitle = _('Execute'); o.inputstyle = 'apply'; if ((! storage.length) || locked) o.readonly = true; o.onclick = function() { window.setTimeout(() => { window.location = window.location.href.split('#')[0]; }, L.env.apply_display * 500); return fs.exec('/etc/init.d/packagesync', ['start']) .catch((e) => { ui.addNotification(null, E('p', e.message), 'error') }); }; o = s.option(form.Value, 'download_url', _('Download URL')); o.placeholder = 'https://downloads.openwrt.org'; o.rmempty = false; o = s.option(form.Value, 'rsync_url', _('Rsync URL'), _('%s') .format('https://openwrt.org/mirrors', _('Available Mirrors'))); o.placeholder = 'rsync://rsync.openwrt.org/downloads'; o.rmempty = false; o = s.option(form.ListValue, 'bwlimit', _('Bandwidth Limit')); o.value('0', _('Unlimited')); o.value('100', _('100 KB/s')); o.value('200', _('200 KB/s')); o.value('300', _('300 KB/s')); o.value('500', _('500 KB/s')); o.value('800', _('800 KB/s')); o.value('1000', _('1 MB/s')); o.value('2000', _('2 MB/s')); o.value('3000', _('3 MB/s')); o.value('5000', _('5 MB/s')); o.value('8000', _('8 MB/s')); o.value('10000', _('10 MB/s')); o.value('20000', _('20 MB/s')); o.value('30000', _('30 MB/s')); o.value('50000', _('50 MB/s')); o.value('80000', _('80 MB/s')); o.value('100000', _('100 MB/s')); o.default = '8000'; o.rmempty = false; o = s.option(form.Flag, 'auto_exec', _('Auto Exec')); o.default = o.enabled; o.rmempty = false; o.write = function(section, value) { uci.set('packagesync', section, 'auto_exec', value); if (value == 1) { fs.exec('/etc/init.d/packagesync', ['setcron', uci.get('packagesync', '@packagesync[0]', 'cron_expression')]); } else { fs.exec('/etc/init.d/packagesync', ['setcron']); } }; o = s.option(form.Value, 'cron_expression', _('Cron expression'), _('The default value is 0:00 every day')); o.default = '0 0 * * *'; o.placeholder = '0 0 * * *'; o.rmempty = false; o.retain = true; o.depends('auto_exec', '1'); o.write = function(section, value) { uci.set('packagesync', section, 'cron_expression', value); fs.exec('/etc/init.d/packagesync', ['setcron', value]); }; o.remove = function(section, value) { //uci.unset('packagesync', section, 'cron_expression'); fs.exec('/etc/init.d/packagesync', ['setcron']); }; o = s.option(form.Flag, 'proxy_enabled', _('Enable proxy')); o.rmempty = false; o = s.option(form.ListValue, 'proxy_protocol', _('Proxy Protocol')); o.value('http', 'HTTP'); o.value('https', 'HTTPS'); o.value('socks5', 'SOCKS5'); o.value('socks5h', 'SOCKS5H'); o.default = 'socks5'; o.rmempty = false; o.retain = true; o.depends('proxy_enabled', '1'); o = s.option(form.Value, 'proxy_server', _('Proxy Server')); o.datatype = "ipaddrport(1)"; o.placeholder = '192.168.1.10:1080'; o.rmempty = false; o.retain = true; o.depends('proxy_enabled', '1'); o = s.option(form.Button, '_list_invalid', _('List removable versions')); o.inputtitle = _('List'); o.inputstyle = 'apply'; if (! storage.length) o.readonly = true; o.onclick = function(ev, section_id) { let precontent = document.getElementById('cleanup-output'); return fs.exec('/etc/init.d/packagesync', ['cleanup']) .then((res) => { dom.content(precontent, [ res.stdout.trim().length ? res.stdout.trim() : _('no objects need to remove.'), res.stderr ? res.stderr : '' ]) }) .catch((err) => { ui.addNotification(null, E('p', err.message), 'error') }); }; o = s.option(form.DummyValue, '_removable_versions', ' '); o.rawhtml = true; o.cfgvalue = function(section_id) { return E('pre', { 'id': 'cleanup-output' }, []); }; s = m.section(form.GridSection, '_storage'); s.render = L.bind(function(view, section_id) { let table = E('table', { 'class': 'table cbi-section-table', 'id': 'storage_device' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th' }, _('Filesystem')), E('th', { 'class': 'th' }, _('Type')), E('th', { 'class': 'th' }, _('Size')), E('th', { 'class': 'th' }, _('Used')), E('th', { 'class': 'th' }, _('Available')), E('th', { 'class': 'th' }, _('Used') + ' %'), E('th', { 'class': 'th' }, _('Mount point')), E('th', { 'class': 'th cbi-section-actions' }, '') ]) ]); let rows = []; if (storage.length) { storage[5] = E('div', { 'class': 'cbi-progressbar', 'title': storage[5], 'style': 'min-width:8em !important' }, E('div', { 'style': 'width:' + storage[5] })) //storage[5] = E('div', { 'class': 'cbi-progressbar', 'title': storage[3] + ' / ' + storage[2] + ' (' + storage[5] + ')', 'style': 'min-width:8em !important' }, [ // E('div', { 'style': 'width:' + storage[5] }) //]); rows.push(storage); }; cbi_update_table(table, rows, E('em', _('Device not exist or mount point in the wrong location'))); return E('div', { 'class': 'cbi-section cbi-tblsection' }, [ E('h3', _('Storage Device')), table ]); }, o, this); s = m.section(form.GridSection, 'release', _('Mirror Releases')); s.sortable = true; s.anonymous = true; s.addremove = true; o = s.option(form.Value, 'name', _('Nick name')); o.datatype = 'uciname'; o.rmempty = false; o.validate = function(section_id, value) { let ss = uci.sections(conf, release); for (let i = 0; i < ss.length; i++) { let sid = ss[i]['.name']; if (sid == section_id) continue; if (value == uci.get(conf, sid, 'name')) return _('The Nick name is already used'); }; return true; }; o = s.option(form.Flag, 'enabled', _('Enable')); o.default = o.enabled; o.editable = true; o.rmempty = false; o = s.option(form.Button, '_getinfo', _('Get Option Info')); o.modalonly = true; o.write = function() {}; o.onclick = function() { return fs.exec_direct('/etc/init.d/packagesync', ['getinfo']) .then((res) => { return window.location.reload() }) .catch((e) => { ui.addNotification(null, E('p', e.message), 'error') }); }; o = s.option(form.Value, 'version', _('Version')); o.rmempty = false; if (releaseslist.length) { for (let i = 0; i < releaseslist.length; i++) o.value(releaseslist[i]); }; o = s.option(form.Value, 'target', _('Target')); o.placeholder = 'x86/64'; o.rmempty = false; if (targetslist.length) { for (let i = 0; i < targetslist.length; i++) o.value(targetslist[i]); }; o = s.option(form.Flag, 'extra', _('Supplementary Files')); o.default = o.disabled; o.rmempty = false; o.modalonly = true; o = s.option(form.Value, 'pkgarch', _('Arch')); o.rmempty = false; if (pkgarchslist.length) { for (let i = 0; i < pkgarchslist.length; i++) o.value(pkgarchslist[i]); }; o = s.option(form.Value, 'model', _('Product model')); o.rmempty = true; o = s.option(form.DummyValue, 'return', _('Last exec result')); o.readonly = true; o = s.option(form.DummyValue, '_return_log', _('Last Error log')); o.editable = true; o.readonly = true; //o.rawhtml = true; //o.modalonly = true; o.cfgvalue = function(section_id) { let href = uci.get('packagesync', '@packagesync[0]', 'home_url'); let result = uci.get('packagesync', section_id, 'name'); return E('span', { 'style': 'font-weight:bold' }, [ E('a', { 'href': '/' + href + '/results/' + result + '.log', 'target': '_blank' }, _('Click to view')) ]); }; return m.render() .then(L.bind(function(m, nodes) { poll.add(L.bind(function() { return Promise.all([ getServiceStatus() ]).then(L.bind(this.poll_status, this, nodes)); }, this), 3); return nodes; }, this, m)); } });