From 80a74167a154a47798811de6dc24e63f6d89eca7 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Tue, 22 May 2018 16:45:19 -0400 Subject: [PATCH] LP#1750894 Server prefs view/migration options Adds a "Server Prefs" tab to the Stored User Preferences user interface. Adds options for migrating workstation settings to server settings, both in test mode and delete-local-once-complete mode. Signed-off-by: Bill Erickson --- .../templates/staff/admin/workstation/index.tt2 | 2 + .../templates/staff/admin/workstation/t_splash.tt2 | 28 +++++++++ .../staff/admin/workstation/t_stored_prefs.tt2 | 42 ++++++++++++- .../js/ui/default/staff/admin/workstation/app.js | 45 +++++++++++++- Open-ILS/web/js/ui/default/staff/services/hatch.js | 69 +++++++++++++++------- 5 files changed, 161 insertions(+), 25 deletions(-) diff --git a/Open-ILS/src/templates/staff/admin/workstation/index.tt2 b/Open-ILS/src/templates/staff/admin/workstation/index.tt2 index 44842eaf37..97472cf01c 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/index.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/index.tt2 @@ -23,6 +23,8 @@ angular.module('egCoreMod').run(['egStrings', function(s) { s.PRINT_TEMPLATES_FAIL_IMPORT = "[% l('Failed to import any print template(s)') %]"; s.HATCH_SETTINGS_MIGRATION_SUCCESS = "[% l('Settings successfully migrated') %]"; s.HATCH_SETTINGS_MIGRATION_FAILURE = "[% l('Settings migration failed') %]"; + s.HATCH_SERVER_SETTINGS_MIGRATION_CONFIRM = + "[% l('This will delete the local version all settings configured to live on the server. Continue?') %]" }]); [% END %] diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 index 345f7db6d3..50a60ef0db 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 @@ -82,6 +82,7 @@ +
@@ -127,6 +128,33 @@
+
+
+ +

[% | l %]Settings may be migrated to the server using the first +option below as many times as needed for testing and verification. Once +local settings are deleted via the second option, the migration will be +marked as complete and no more migration attempts may occur.[% END %] +

+
    +
  1. + +
  2. +
  3. + +
  4. +
+
+
+ + diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 index dc031b44bb..e4c34c99f5 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 @@ -15,13 +15,48 @@ [% |l %] Preference values are stored as JSON strings. Click on a preference to view the stored value. -Click on the delete (X) button to remove a preference's value. +Click on the delete (X) button to remove a preference value. [% END %]
+
+
+
+

+ [% l('Experimental: Migrate Workstation Settings to Server') %] +

+
+
+

+[% | l %]Settings may be migrated to the server using the first option below +as many times as needed for testing and verification. Once local settings +are deleted via the second option, no settings will remain to migrate, unless +they are added back through some external mechanism.[% END %] +

+

+[% | l %]Note that just because a setting exists under "Server Prefs" below +does not mean it has been migrated. Check the value by clicking on the +setting name to be sure.[% END %] +

+
+ + +
+
+
+
+
+ +
diff --git a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js index f599bc0bbc..fa0df895f3 100644 --- a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js +++ b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js @@ -728,8 +728,8 @@ function($scope , $q , egCore , ngToast) { }]) .controller('StoredPrefsCtrl', - ['$scope','$q','egCore','egConfirmDialog', -function($scope , $q , egCore , egConfirmDialog) { + ['$scope','$q','egCore','egConfirmDialog','egProgressDialog','$timeout', +function($scope , $q , egCore , egConfirmDialog , egProgressDialog , $timeout) { console.log('StoredPrefsCtrl'); $scope.setContext = function(ctx) { @@ -745,7 +745,7 @@ function($scope , $q , egCore , egConfirmDialog) { // fetch the keys function refreshKeys() { - $scope.keys = {local : [], remote : []}; + $scope.keys = {local : [], remote : [], server: []}; if (egCore.hatch.hatchAvailable) { egCore.hatch.getRemoteKeys().then( @@ -754,6 +754,10 @@ function($scope , $q , egCore , egConfirmDialog) { // local calls are non-async $scope.keys.local = egCore.hatch.getLocalKeys(); + + egCore.hatch.getServerKeys().then(function(keys) { + $scope.keys.server = keys; + }); } refreshKeys(); @@ -763,6 +767,11 @@ function($scope , $q , egCore , egConfirmDialog) { if ($scope.context == 'local') { $scope.currentKeyContent = egCore.hatch.getLocalItem(key); + } else if ($scope.context === 'server') { + egCore.hatch.getServerItem(key) + .then(function(content) { + $scope.currentKeyContent = content + }); } else { egCore.hatch.getRemoteItem(key) .then(function(content) { @@ -783,6 +792,9 @@ function($scope , $q , egCore , egConfirmDialog) { if ($scope.context == 'local') { egCore.hatch.removeLocalItem(key); refreshKeys(); + } else if ($scope.context == 'server') { + egCore.hatch.removeServerItem(key) + .then(function() { refreshKeys() }); } else { egCore.hatch.removeItem(key) .then(function() { refreshKeys() }); @@ -792,6 +804,33 @@ function($scope , $q , egCore , egConfirmDialog) { } ); } + + $scope.migrateServerSettings = function(deleteLocal) { + + var promise = !deleteLocal ? $q.when() : + egConfirmDialog.open( + egCore.strings.HATCH_SERVER_SETTINGS_MIGRATION_CONFIRM, '', {} + ).result; + + promise.then(function() { + egProgressDialog.open(); + // timeout added because closing a progress dialog too quickly + // (before it's registered that it's opened) can leave the + // dialog stranded open. This is only an issue when no local + // settings data exists to migrate, causing the migration to + // be instantaneous. + $timeout(function() { + egCore.hatch.migrateServerSettings(deleteLocal).then( + function() {}, + function() {}, + function() { + egProgressDialog.increment(); + } + )['finally'](egProgressDialog.close); + }, 100); + }); + } + }]) .controller('WSRegCtrl', diff --git a/Open-ILS/web/js/ui/default/staff/services/hatch.js b/Open-ILS/web/js/ui/default/staff/services/hatch.js index 973f145cff..6fa8ae228a 100644 --- a/Open-ILS/web/js/ui/default/staff/services/hatch.js +++ b/Open-ILS/web/js/ui/default/staff/services/hatch.js @@ -33,6 +33,7 @@ angular.module('egCoreMod') service.messages = {}; service.hatchAvailable = false; service.auth = null; // ref to egAuth loaded on-demand to avoid circular ref. + service.disableServerSettings = false; // key/value cache -- avoid unnecessary Hatch extension requests. // Only affects *RemoteItem calls. @@ -90,6 +91,11 @@ angular.module('egCoreMod') ]; service.keyStoredOnServer = function(key) { + + if (service.disableServerSettings) { + return false; + } + var browserOnly = false; angular.forEach(service.browserOnlyPrefixes, function(pfx) { if (key.match(new RegExp('^' + pfx))) @@ -368,7 +374,7 @@ angular.module('egCoreMod') }); } - service.migrateServerSettings = function() { + service.migrateServerSettings = function(deleteLocal) { if (!service.auth) service.auth = $injector.get('egAuth'); if (!service.auth.token()) return $q.reject('no authtoken'); @@ -376,45 +382,46 @@ angular.module('egCoreMod') var deferred = $q.defer(); var settings = service.serverSettings.slice(0); // clone + // Allow get/remove calls to fall back to local options + // during migration. + service.disableServerSettings = true; + function migrateNext(key) { + if (!key) { + service.disableServerSettings = false; return deferred.resolve(); } - service.migrateOneServerSetting(key).then( + service.migrateOneServerSetting(key, deleteLocal).then( function() { deferred.notify('migrated ' + key); migrateNext(settings.shift()); }, function() { + service.disableServerSettings = false; deferred.reject( 'Something failed during settings migration'); } ); - } + migrateNext(settings.shift()); return deferred.promise; } - service.migrateOneServerSetting = function(key) { - console.log('migrating server setting ' + key); + service.migrateOneServerSetting = function(key, deleteLocal) { var deferred = $q.defer(); - function remove(key) { - return service.useSettings() ? - service.removeRemoteItem(key) : - $q.when(service.removeLocalItem(key)); - } - - var prom = service.useSettings() ? - service.getRemoteItem(key) : - $q.when(service.getLocalItem(key)); - - prom.then(function(value) { + service.getItem(key).then(function(value) { if (value === undefined || value === null) { - remove(key); // for good measure. + console.log(key + ' has no value to migrate'); + // Nothing to migrate. + if (deleteLocal) { + // for good measure. + service.removeItem(key); + } return deferred.resolve(); } @@ -423,9 +430,13 @@ angular.module('egCoreMod') console.debug( 'setting ' + key + ' successfully stored on server'); - remove(key).then(function() { + if (!deleteLocal) { + return deferred.resolve(); + } + + service.removeItem(key).then(function() { console.debug( - 'setting ' + key + ' removed from local storage'); + 'setting ' + key + ' removed from workstation'); deferred.resolve(); }); }, @@ -551,7 +562,7 @@ angular.module('egCoreMod') // remove a stored item service.removeItem = function(key) { if (service.keyStoredOnServer(key)) - return service.setServerItem(key, null); + return service.removeServerItem(key); if (!service.useSettings()) return $q.when(service.removeLocalItem(key)); @@ -570,6 +581,10 @@ angular.module('egCoreMod') return $q.reject(); } + service.removeServerItem = function(key) { + return service.setServerItem(key, null); + } + service.removeRemoteItem = function(key) { delete service.keyCache[key]; return service.attemptHatchDelivery({ @@ -617,6 +632,20 @@ angular.module('egCoreMod') }); } + service.getServerKeys = function(prefix) { + var keys = []; + var idx = 0; + service.serverSettings.forEach(function(k) { + // key prefix match test + if (prefix && k.substr(0, prefix.length) != prefix) { + return; + } + keys.push(k); + }); + // these may eventually come from the server, so return a promise. + return $q.when(keys); + } + service.getLocalKeys = function(prefix) { var keys = []; var idx = 0; -- 2.11.0