mirror of
https://github.com/openwrt/luci.git
synced 2026-04-15 19:01:56 +00:00
luci-app-attendedsysupgrade: rework check-for-new-firmware
Do a complete overhaul of the firmware check: When the Status -> Overview page is loaded, we check if the configuration is set. If not, we ask the user to choose between enabled or disabled. Once this is done, it never appears again (much like the "set password" logic in the shell). As a result, there is no longer a persistent section on the Overview page with a simple toggle eating real estate and playing havoc with the Hide/Show button scheme. When the setting is enabled, then every time Status -> Overview is loaded, we do the firmware check and display an alert notice as before. But, the alert notice now contains a button to disable the alerts, so navigation is still simple, you don't have to dig around to figure out how to turn it off. The logic for version comparisons was cleaned up and simplified. Fixes: #7925 Fixes: #8226 Signed-off-by: Eric Fahlgren <ericfahlgren@gmail.com>
This commit is contained in:
committed by
Paul Donald
parent
720c96ce5b
commit
2aa6aba3bc
@@ -26,20 +26,28 @@ return view.extend({
|
||||
form.DynamicList,
|
||||
'rebuilder',
|
||||
_('Rebuilders'),
|
||||
_(
|
||||
'Other ASU server instances that rebuild a requested image. ' +
|
||||
'Allows to compare checksums and verify that the results are the same.'
|
||||
_('Other ASU server instances that rebuild a requested image. ' +
|
||||
'Allows to compare checksums and verify that the results are the same.'
|
||||
)
|
||||
);
|
||||
|
||||
s = m.section(form.TypedSection, 'client', _('Client'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(
|
||||
form.Flag,
|
||||
'login_check_for_upgrades',
|
||||
_('Check for upgrades'),
|
||||
_('Check for upgrades whenever the System -> Overview page is loaded.')
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(
|
||||
form.Flag,
|
||||
'auto_search',
|
||||
_('Search on opening'),
|
||||
_('Search for new sysupgrades on opening the tab')
|
||||
_('Search for upgrades when opening the Attended Sysupgrade tab')
|
||||
);
|
||||
o.default = '1';
|
||||
o.rmempty = false;
|
||||
|
||||
@@ -11,13 +11,25 @@ const callSystemBoard = rpc.declare({
|
||||
method: 'board'
|
||||
});
|
||||
|
||||
function showUpgradeNotification(type, boardinfo, new_version, upgrade_info)
|
||||
const check_setting = [ 'attendedsysupgrade', 'client', 'login_check_for_upgrades' ];
|
||||
|
||||
function setSetUpgradeCheck(pref) {
|
||||
uci.set(...check_setting, pref);
|
||||
return uci.save()
|
||||
.then(L.bind(L.ui.changes.init, L.ui.changes))
|
||||
.then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
|
||||
}
|
||||
|
||||
function showUpgradeNotification(type, boardinfo, version, upgrade_info)
|
||||
{
|
||||
|
||||
// TODO show the toggle for _('Look online for upgrades upon status page load')...
|
||||
|
||||
const table_rows = [
|
||||
// Title Current Available
|
||||
[_('Firmware Version'), boardinfo.release.version, upgrade_info.version_number ],
|
||||
[_('Revision'), boardinfo.release.revision, upgrade_info.version_code ],
|
||||
[_('Kernel Version'), boardinfo?.kernel, upgrade_info.linux_kernel?.version ],
|
||||
[_('Kernel Version'), boardinfo.kernel, upgrade_info.linux_kernel?.version ],
|
||||
];
|
||||
|
||||
const table = E('table', { 'class': 'table' });
|
||||
@@ -30,54 +42,55 @@ function showUpgradeNotification(type, boardinfo, new_version, upgrade_info)
|
||||
])
|
||||
);
|
||||
|
||||
table_rows.forEach((cols) => {
|
||||
table_rows.forEach(([c1, c2, c3]) => {
|
||||
table.appendChild(E('tr', { 'class': 'tr' }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ cols[0] ]),
|
||||
E('td', { 'class': 'td left' }, [ cols[1] ?? '?' ]),
|
||||
E('td', { 'class': 'td left' }, [ cols[2] ?? '?' ]),
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ c1 ]),
|
||||
E('td', { 'class': 'td left' }, [ c2 ?? '?' ]),
|
||||
E('td', { 'class': 'td left' }, [ c3 ?? '?' ]),
|
||||
]));
|
||||
});
|
||||
|
||||
const branch = version.split('.').slice(0, 2).join('.');
|
||||
ui.addTimeLimitedNotification(_('New Firmware Available'), [
|
||||
E('p', _('A new %s version of OpenWrt is available:').format(type)),
|
||||
table,
|
||||
E('p', [
|
||||
_('Check') + ' ',
|
||||
E('a', {href: `/cgi-bin/luci/admin/system/attendedsysupgrade`}, _('Attended Sysupgrade')),
|
||||
E('a', {href: '/cgi-bin/luci/admin/system/attendedsysupgrade'}, _('Attended Sysupgrade')),
|
||||
' ' + _('and') + ' ',
|
||||
E('a', {href: `https://openwrt.org/releases/${new_version?.split('.').slice(0, 2).join('.')}/notes-${new_version}`}, _('release notes')),
|
||||
E('a', {href: `https://openwrt.org/releases/${branch}/notes-${version}`}, _('release notes')),
|
||||
]),
|
||||
E('div', { class: 'btn', click: () => setSetUpgradeCheck(false) }, _('Stop showing upgrade alerts')),
|
||||
], 60000, 'notice');
|
||||
};
|
||||
}
|
||||
|
||||
function shouldUpgrade(installed, available)
|
||||
{
|
||||
// If installed is any snapshot (release or main), don't upgrade.
|
||||
|
||||
if (! available) return false;
|
||||
if (! installed || installed.includes('SNAPSHOT')) return false
|
||||
if (! installed) return false;
|
||||
if (installed.includes('SNAPSHOT')) return false;
|
||||
|
||||
const parse = (v) => v.split(/[-+]/)[0]?.split('.').map(Number);
|
||||
const parseRC = (v) => v.split(/[-+]/)[1]?.split('').map(Number);
|
||||
const isPrerelease = (v) => /-/.test(v);
|
||||
// At this point we know the versions are in one of two forms:
|
||||
// MM.mm.rr
|
||||
// MM.mm.rr-rcN
|
||||
// so partition them up into a 4-element array, with a value of
|
||||
// 99 for the "release candidate" part of any release.
|
||||
const parse = (v) => [
|
||||
...v.split('-')[0].split('.').map(Number),
|
||||
Number(v.split(/rc/)[1] || 99)
|
||||
];
|
||||
|
||||
const [aParts, bParts] = [parse(available), parse(installed)];
|
||||
const [aParts, iParts] = [parse(available), parse(installed)];
|
||||
|
||||
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
||||
const numA = aParts[i] || 0;
|
||||
const numB = bParts[i] || 0;
|
||||
if (numA > numB) return true;
|
||||
if (numA < numB) return false;
|
||||
for (let i = 0; i < iParts.length; i++) {
|
||||
const aVal = aParts[i];
|
||||
const iVal = iParts[i];
|
||||
if (aVal > iVal) return true;
|
||||
if (aVal < iVal) return false;
|
||||
}
|
||||
|
||||
const [aRC, bRC] = [parseRC(available), parseRC(installed)];
|
||||
|
||||
if (aRC > bRC) return true;
|
||||
if (aRC < bRC) return false;
|
||||
|
||||
// If numeric parts are equal, handle release candidates
|
||||
// if (isPrerelease(available) && !isPrerelease(installed)) return false;
|
||||
if (!isPrerelease(available) && isPrerelease(installed)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,24 +129,14 @@ return baseclass.extend({
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(callSystemBoard(), {}),
|
||||
uci.load('luci')
|
||||
uci.load(check_setting[0]),
|
||||
]);
|
||||
},
|
||||
|
||||
handleSetUpgradeCheck: function(pref, ev) {
|
||||
ev.currentTarget.classList.add('spinning');
|
||||
ev.currentTarget.blur();
|
||||
|
||||
uci.set('luci', 'main', 'check_for_newer_firmwares', pref);
|
||||
|
||||
return uci.save()
|
||||
.then(L.bind(L.ui.changes.init, L.ui.changes))
|
||||
.then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
|
||||
},
|
||||
|
||||
oneshot: function(data) {
|
||||
var boardinfo = data[0];
|
||||
const check_upgrades = uci.get_bool('luci', 'main', 'check_for_newer_firmwares');
|
||||
const check_upgrades = uci.get_bool(...check_setting);
|
||||
|
||||
if (check_upgrades) {
|
||||
fetch('https://downloads.openwrt.org/.versions.json')
|
||||
@@ -177,14 +180,32 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
const check_upgrades = uci.get_bool('luci', 'main', 'check_for_newer_firmwares') ?? false;
|
||||
const isReadonlyView = !L.hasViewPermission();
|
||||
const isReadOnlyView = !L.hasViewPermission();
|
||||
if (isReadOnlyView)
|
||||
return null;
|
||||
|
||||
let perform_check_pref = E('input', { type: 'checkbox', 'click': L.bind(this.handleSetUpgradeCheck, this, !check_upgrades), });
|
||||
perform_check_pref.checked = check_upgrades;
|
||||
let check_upgrades = uci.get(...check_setting);
|
||||
if (check_upgrades != null)
|
||||
return null;
|
||||
|
||||
let perform_check_pref_p = E('div', [_('Look online for upgrades upon status page load') + ' ', perform_check_pref]);
|
||||
let modal_body = [
|
||||
E('p', _('Checking for firmware upgrades requires access to several files ' +
|
||||
'on the downloads site, so requires internet access.')),
|
||||
|
||||
return E('div', [!isReadonlyView ? perform_check_pref_p : '']);
|
||||
E('p', _('The check will be performed every time the Status -> Overview page is loaded.')),
|
||||
|
||||
E('p', _('You have not yet specified a preference for this setting. ' +
|
||||
'Once set, this dialog will not be shown again, but you can go to ' +
|
||||
'System -> Attended Sysupgrade configuration to change the setting.')),
|
||||
|
||||
E('div', { class: 'right' }, [
|
||||
E('div', { class: 'btn', click: () => setSetUpgradeCheck(true) }, _('Yes, enable checking')),
|
||||
E('div', { class: 'btn', click: () => setSetUpgradeCheck(false) }, _('No, disable checking')),
|
||||
E('div', { class: 'btn', click: ui.hideModal }, _('Close')),
|
||||
]),
|
||||
];
|
||||
ui.showModal(_('Check online for firmware upgrades'), modal_body);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
check="$(uci -q get luci.main.check_for_newer_firmwares)"
|
||||
if [ -n "$check" ]; then
|
||||
if ! uci -q get attendedsysupgrade.client.login_check_for_upgrades >/dev/null; then
|
||||
uci set attendedsysupgrade.client.login_check_for_upgrades="$check"
|
||||
fi
|
||||
uci -q delete luci.main.check_for_newer_firmwares
|
||||
fi
|
||||
exit 0
|
||||
Reference in New Issue
Block a user