diff --git a/src/controllers/dashboard/devices/devices.html b/src/controllers/dashboard/devices/devices.html index 63c348c900..e2504cd3e7 100644 --- a/src/controllers/dashboard/devices/devices.html +++ b/src/controllers/dashboard/devices/devices.html @@ -5,6 +5,7 @@

${HeaderDevices}

${Help} +
diff --git a/src/controllers/dashboard/devices/devices.js b/src/controllers/dashboard/devices/devices.js index 1178a0f1bd..c6e7281645 100644 --- a/src/controllers/dashboard/devices/devices.js +++ b/src/controllers/dashboard/devices/devices.js @@ -10,10 +10,32 @@ import 'cardStyle'; /* eslint-disable indent */ + // Local cache of loaded + let deviceIds = []; + function canDelete(deviceId) { return deviceId !== ApiClient.deviceId(); } + function deleteAllDevices(page) { + const msg = globalize.translate('DeleteDevicesConfirmation'); + + require(['confirm'], async function (confirm) { + await confirm({ + text: msg, + title: globalize.translate('HeaderDeleteDevices'), + confirmText: globalize.translate('ButtonDelete'), + primary: 'delete' + }); + + loading.show(); + await Promise.all( + deviceIds.filter(canDelete).map((id) => ApiClient.deleteDevice(id)) + ); + loadData(page); + }); + } + function deleteDevice(page, id) { const msg = globalize.translate('DeleteDeviceConfirmation'); @@ -23,16 +45,10 @@ import 'cardStyle'; title: globalize.translate('HeaderDeleteDevice'), confirmText: globalize.translate('Delete'), primary: 'delete' - }).then(function () { + }).then(async () => { loading.show(); - ApiClient.ajax({ - type: 'DELETE', - url: ApiClient.getUrl('Devices', { - Id: id - }) - }).then(function () { - loadData(page); - }); + await ApiClient.deleteDevice(id); + loadData(page); }); }); } @@ -129,6 +145,7 @@ import 'cardStyle'; loading.show(); ApiClient.getJSON(ApiClient.getUrl('Devices')).then(function (result) { load(page, result.Items); + deviceIds = result.Items.map((device) => device.Id); loading.hide(); }); } @@ -145,6 +162,9 @@ import 'cardStyle'; view.addEventListener('viewshow', function () { loadData(this); }); - } + view.querySelector('#deviceDeleteAll').addEventListener('click', function() { + deleteAllDevices(view); + }); + } /* eslint-enable indent */ diff --git a/src/strings/en-us.json b/src/strings/en-us.json index ab547f3854..c2ad064922 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -150,6 +150,8 @@ "DefaultSubtitlesHelp": "Subtitles are loaded based on the default and forced flags in the embedded metadata. Language preferences are considered when multiple options are available.", "DeinterlaceMethodHelp": "Select the deinterlacing method to use when software transcoding interlaced content. When hardware acceleration supporting hardware deinterlacing is enabled the hardware deinterlacer will be used instead of this setting.", "Delete": "Delete", + "DeleteAll": "Delete All", + "DeleteDevicesConfirmation": "Are you sure you wish to delete all devices? All other sessions will be logged out. Devices will reappear the next time a user signs in.", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", "DeleteImage": "Delete Image", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", @@ -298,6 +300,7 @@ "HeaderDateIssued": "Date Issued", "HeaderDefaultRecordingSettings": "Default Recording Settings", "HeaderDeleteDevice": "Delete Device", + "HeaderDeleteDevices": "Delete All Devices", "HeaderDeleteItem": "Delete Item", "HeaderDeleteItems": "Delete Items", "HeaderDeleteProvider": "Delete Provider",