From feb8d823e59f8c9bf1bdadce6c7fc2a88966f12e Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Wed, 7 Oct 2020 14:42:39 +0200 Subject: luci-app-advanced-reboot: convert to client side Rework the advanced-reboot app to client side implementation. Change devices file to json type. Signed-off-by: Ansuel Smith Tested-by: Stefan Lippers-Hollmann --- .../resources/view/system/advanced_reboot.js | 237 +++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js (limited to 'applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view') diff --git a/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js b/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js new file mode 100644 index 0000000000..762d65f669 --- /dev/null +++ b/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js @@ -0,0 +1,237 @@ +'use strict'; +'require view'; +'require rpc'; +'require ui'; +'require uci'; +'require fs'; + +return view.extend({ + translateTable: { + NO_BOARD_NAME : function(args) { return _('Unable to find Device Board Name.')}, + NO_DUAL_FLAG : function(args) {return _('Unable to find Dual Boot Flag Partition.')}, + ERR_SET_DUAL_FLAG : function(args) { return _('Unable to set Dual Boot Flag Partition entry for partition: %s.').format(args[0])}, + NO_FIRM_ENV : function(args) { return _('Unable to obtain firmware environment variable: %s.').format(args[0])}, + ERR_SET_ENV : function(args) { return _('Unable to set firmware environment variable: %s to %s.').format(args[0],args[1])} + }, + + callReboot: rpc.declare({ + object: 'system', + method: 'reboot', + expect: { result: 0 } + }), + + callObtainDeviceInfo: rpc.declare({ + object: 'luci.advanced_reboot', + method: 'obtain_device_info', + expect: { } + }), + + callTogglePartition: rpc.declare({ + object: 'luci.advanced_reboot', + method: 'toggle_boot_partition', + expect: { } + }), + + callPowerOff: function() { + return fs.exec('/sbin/poweroff').then(function() { + ui.showModal(_('Shutting down...'), [ + E('p', { 'class': 'spinning' }, _('The system is shutting down now.
DO NOT POWER OFF THE DEVICE!
It might be necessary to renew the address of your computer to reach the device again, depending on your settings.')) + ]); + }) + }, + + handlePowerOff: function() { + + ui.showModal(_('Power Off Device'), [ + E('p', _("WARNING: Power off might result in a reboot on a device which doesn't support power off.

\ + Click \"Proceed\" below to power off your device.")), + E('div', { 'class': 'right' }, [ + E('button', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Cancel')), ' ', + E('button', { + 'class': 'cbi-button cbi-button-positive important', + 'click': L.bind(this.callPowerOff, this) + }, _('Proceed')) + ]) + ]); + + }, + + handleReboot: function(ev) { + return this.callReboot().then(function(res) { + if (res != 0) { + ui.addNotification(null, E('p', _('The reboot command failed with code %d').format(res))); + L.raise('Error', 'Reboot failed'); + } + + ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning' }, _('Waiting for device...')) + ]); + + window.setTimeout(function() { + ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning alert-message warning' }, + _('Device unreachable! Still waiting for device...')) + ]); + }, 150000); + + ui.awaitReconnect(); + }) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + handleTogglePartition: function(ev) { + return this.callTogglePartition().then(L.bind(function(res) { + if (res.error) { + ui.hideModal() + return ui.addNotification(null, E('p', this.translateTable[res.error](res.args))); + } + + return this.callReboot().then(function(res) { + if (res != 0) { + ui.addNotification(null, E('p', _('The reboot command failed with code %d').format(res))); + L.raise('Error', 'Reboot failed'); + } + + ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning' }, _('The system is rebooting to an alternative partition now.
DO NOT POWER OFF THE DEVICE!
Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings.')) + ]); + + window.setTimeout(function() { + ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning alert-message warning' }, + _('Device unreachable! Still waiting for device...')) + ]); + }, 150000); + + ui.awaitReconnect(); + }) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, this)); + }, + + handleAlternativeReboot: function(ev) { + return Promise.all([ + L.resolveDefault(fs.stat('/usr/sbin/fw_printenv'), null), + L.resolveDefault(fs.stat('/usr/sbin/fw_setenv'), null), + ]).then(L.bind(function (data) { + if (!data[0] || !data[1]) { + return ui.addNotification(null, E('p', _('No access to fw_printenv or fw_printenv!'))); + } + + ui.showModal(_('Reboot Device to an Alternative Partition') + " - " + _("Confirm"), [ + E('p', _("WARNING: An alternative partition might have its own settings and completely different firmware.

\ + As your network configuration and WiFi SSID/password on alternative partition might be different,\ + you might have to adjust your computer settings to be able to access your device once it reboots.

\ + Please also be aware that alternative partition firmware might not provide an easy way to switch active partition\ + and boot back to the currently active partition.

\ + Click \"Proceed\" below to reboot device to an alternative partition.")), + E('div', { 'class': 'right' }, [ + E('button', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Cancel')), ' ', + E('button', { + 'class': 'cbi-button cbi-button-positive important', + 'click': L.bind(this.handleTogglePartition, this) + }, _('Proceed')) + ]) + ]); + }, this)) + }, + + parsePartitions: function(partitions) { + var res = []; + + partitions.forEach(L.bind(function(partition) { + var func, text; + + if (partition.state == 'Current') { + func = 'handleReboot'; + text = _('Reboot to current partition'); + } else { + func = 'handleAlternativeReboot'; + text = _('Reboot to alternative partition...'); + } + + res.push([ + (partition.number).toString(16).toUpperCase(), + _(partition.state), + partition.os.replace("Unknown", _("Unknown")).replace("Compressed", _("Compressed")), + E('button', { + 'class': 'cbi-button cbi-button-apply important', + 'click': ui.createHandlerFn(this, func) + }, text) + ]) + }, this)); + + return res; + }, + + load: function() { + return Promise.all([ + uci.changes(), + L.resolveDefault(fs.stat('/sbin/poweroff'), null), + this.callObtainDeviceInfo() + ]); + }, + + render: function(data) { + var changes = data[0], + poweroff_supported = data[1] != null ? true : false, + device_info = data[2]; + + var body = E([ + E('h2', _('Advanced Reboot')) + ]); + + for (var config in (changes || {})) { + body.appendChild(E('p', { 'class': 'alert-message warning' }, + _('Warning: There are unsaved changes that will get lost on reboot!'))); + break; + } + + if (device_info.error) + body.appendChild(E('p', { 'class' : 'alert-message warning'}, _("ERROR: ") + this.translateTable[device_info.error]())); + + body.appendChild(E('h3', device_info.device_name + _(' Partitions'))); + if (device_info.device_name) { + var partitions_table = E('div', { 'class': 'table' }, [ + E('div', { 'class': 'tr table-titles' }, [ + E('div', { 'class': 'th' }, [ _('Partition') ]), + E('div', { 'class': 'th' }, [ _('Status') ]), + E('div', { 'class': 'th' }, [ _('Firmware') ]), + E('div', { 'class': 'th' }, [ _('Reboot') ]) + ]) + ]); + + cbi_update_table(partitions_table, this.parsePartitions(device_info.partitions)); + + body.appendChild(partitions_table); + } else { + body.appendChild(E('p', { 'class' : 'alert-message warning'}, + device_info.rom_board_name ? _("Warning: Device (%s) is unknown or isn't a dual-partition device!").format(device_info.rom_board_name) + : _('Warning: Unable to obtain device information!') + )); + } + + body.appendChild(E('hr')); + body.appendChild( + poweroff_supported ? E('button', { + 'class': 'cbi-button cbi-button-apply important', + 'click': ui.createHandlerFn(this, 'handlePowerOff') + }, _('Perform power off...')) + + : E('p', { 'class' : 'alert-message warning'}, + _('Warning: This system does not support powering off!')) + ); + + return body; + }, + + handleSaveApply: null, + handleSave: null, + handleReset: null +}); -- cgit v1.2.3