LP#1750894 support getKeys() / batch of print template settings
authorBill Erickson <berickxx@gmail.com>
Wed, 30 May 2018 15:46:16 +0000 (11:46 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 30 May 2018 15:46:16 +0000 (11:46 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/Settings.pm
Open-ILS/src/sql/Pg/upgrade/YYYY.data.workstation-settings.sql
Open-ILS/web/js/ui/default/staff/circ/checkin/app.js
Open-ILS/web/js/ui/default/staff/services/hatch.js

index 6ab6818..601188c 100644 (file)
@@ -15,11 +15,11 @@ my $name_regex = qr/[^a-zA-Z0-9_\.]/;
 
 __PACKAGE__->register_method (
     method      => 'retrieve_settings',
-    api_name    => 'open-ils.actor.settings.retrieve', 
+    api_name    => 'open-ils.actor.settings.retrieve',
     stream      => 1,
     signature => {
         desc => q/
-            Returns org unit, user, and workstation setting values 
+            Returns org unit, user, and workstation setting values
             for the requested setting types.
 
             The API makes a best effort to find the correct setting
@@ -28,8 +28,8 @@ __PACKAGE__->register_method (
             If no auth token is provided, only publicly visible org
             unit settings may be returned.
 
-            If no workstation is linked to the provided auth token, only 
-            user settings and perm-visible org unit settings may be 
+            If no workstation is linked to the provided auth token, only
+            user settings and perm-visible org unit settings may be
             returned.
 
             If no org unit is provided, but a workstation is linked to the
@@ -43,8 +43,8 @@ __PACKAGE__->register_method (
         ],
         return => {
             desc => q/
-                Stream of setting name=>value pairs in the same order 
-                as the provided list of setting names.  No key-value 
+                Stream of setting name=>value pairs in the same order
+                as the provided list of setting names.  No key-value
                 pair is returned for settings that have no value defined./,
             type => 'string'
         }
@@ -57,7 +57,7 @@ sub retrieve_settings {
     my ($aou_id, $user_id, $ws_id, $evt) = get_context($auth, $org_id);
     return $evt if $evt; # bogus auth token
 
-    return OpenILS::Event->new('BAD_PARAMS', 
+    return OpenILS::Event->new('BAD_PARAMS',
         desc => 'Cannot retrieve settings without a user or org unit')
         unless ($user_id || $aou_id);
 
@@ -67,12 +67,12 @@ sub retrieve_settings {
     # Encode as a db-friendly array.
     my $settings_str = '{' . join(',', @$settings) . '}';
 
-    # Some settings could be bulky, so fetch them as a stream from 
+    # Some settings could be bulky, so fetch them as a stream from
     # cstore, relaying values back to the caller as they arrive.
     my $ses = OpenSRF::AppSession->create('open-ils.cstore');
     my $req = $ses->request('open-ils.cstore.json_query', {
         from => [
-            'actor.get_cascade_setting_batch', 
+            'actor.get_cascade_setting_batch',
             $settings_str, $aou_id, $user_id, $ws_id
         ]
     });
@@ -93,7 +93,7 @@ sub get_context {
     my ($auth, $org_id) = @_;
 
     return ($org_id) unless $auth;
-    
+
     my $e = new_editor(authtoken => $auth);
     return (undef, undef, undef, $e->event) unless $e->checkauth;
 
@@ -108,7 +108,7 @@ sub get_context {
 
 __PACKAGE__->register_method (
     method      => 'apply_user_or_ws_setting',
-    api_name    => 'open-ils.actor.settings.apply.user_or_ws', 
+    api_name    => 'open-ils.actor.settings.apply.user_or_ws',
     stream      => 1,
     signature => {
         desc => q/
@@ -156,7 +156,7 @@ sub apply_user_or_ws_setting {
                 # Confirm the caller has permission to apply workstation
                 # settings at the logged-in workstation before applying.
                 # Do the perm check here so it's only needed once per batch.
-                return $e->die_event unless 
+                return $e->die_event unless
                     $ws_allowed = $e->allowed('APPLY_WORKSTATION_SETTING');
             }
 
@@ -235,4 +235,80 @@ sub apply_workstation_setting {
     return undef;
 }
 
+__PACKAGE__->register_method (
+    method      => 'applied_settings',
+    api_name    => 'open-ils.actor.settings.staff.applied.names',
+    stream      => 1,
+    authoritative => 1,
+    signature => {
+        desc => q/
+            Returns a list of setting names where a value is applied to
+            the current user or workstation.
+
+            This is a staff-only API created primarily to support the
+            getKeys() functionality used in the browser client for
+            server-managed settings.
+        /,
+        params => [
+            {desc => 'authtoken', type => 'string'},
+            {desc =>
+                'prefix.  Limit keys to those starting with $prefix',
+             type => 'string'
+            },
+        ],
+        return => {
+            desc => 'List of strings, Event on error',
+            type => 'array'
+        }
+    }
+);
+
+sub applied_settings {
+    my ($self, $client, $auth, $prefix) = @_;
+
+    my $e = new_editor(authtoken => $auth);
+    return $e->event unless $e->checkauth;
+
+    return $e->event unless
+        $e->allowed('STAFF_LOGIN') &&
+        $e->allowed('APPLY_WORKSTATION_SETTING');
+
+
+    my $query = {
+        select => {awss => ['name']},
+        from => 'awss',
+        where => {
+            workstation => $e->requestor->wsid
+        }
+    };
+
+    $query->{where}->{name} = {like => "$prefix%"} if $prefix;
+
+    for my $key (@{$e->json_query($query)}) {
+        $client->respond($key->{name});
+    }
+
+    $query = {
+        select => {aus => ['name']},
+        from => 'aus',
+        where => {
+            usr => $e->requestor->id
+        }
+    };
+
+    $query->{where}->{name} = {like => "$prefix%"} if $prefix;
+
+    for my $key (@{$e->json_query($query)}) {
+        $client->respond($key->{name});
+    }
+
+    return undef;
+}
+
+
+
+
+
+
+
 1;
index a9f82fe..f43aef6 100644 (file)
@@ -1,5 +1,8 @@
 BEGIN;
 
+INSERT INTO permission.perm_list (id, code, description) VALUES
+ (607, 'APPLY_WORKSTATION_SETTING',
+   oils_i18n_gettext(607, 'APPLY_WORKSTATION_SETTING', 'ppl', 'description'));
 
 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
 VALUES (
@@ -471,9 +474,380 @@ VALUES (
         'MARC Editor Stack Subfields',
         'cwst', 'label'
     )
-
+), (
+    'eg.offline.print_receipt', 'gui', 'bool',
+    oils_i18n_gettext(
+        'eg.offline.print_receipt',
+        'Offline Print Receipt',
+        'cwst', 'label'
+    )
+), (
+    'eg.offline.strict_barcode', 'gui', 'bool',
+    oils_i18n_gettext(
+        'eg.offline.strict_barcode',
+        'Offline Use Strict Barcode',
+        'cwst', 'label'
+    )
+), (
+    'cat.default_bib_marc_template', 'gui', 'string',
+    oils_i18n_gettext(
+        'cat.default_bib_marc_template',
+        'Default MARC Template',
+        'cwst', 'label'
+    )
+), (
+    'eg.audio.disable', 'gui', 'bool',
+    oils_i18n_gettext(
+        'eg.audio.disable',
+        'Disable Staff Client Notification Audio',
+        'cwst', 'label'
+    )
+), (
+    'eg.search.adv_pane', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.search.adv_pane',
+        'Catalog Advanced Search Default Pane',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.bills_current', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.bills_current',
+        'Print Template Context: bills_current',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.bills_current', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.bills_current',
+        'Print Template: bills_current',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.bills_historical', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.bills_historical',
+        'Print Template Context: bills_historical',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.bills_historical', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.bills_historical',
+        'Print Template: bills_historical',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.bill_payment', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.bill_payment',
+        'Print Template Context: bill_payment',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.bill_payment', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.bill_payment',
+        'Print Template: bill_payment',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.checkin', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.checkin',
+        'Print Template Context: checkin',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.checkin', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.checkin',
+        'Print Template: checkin',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.checkout', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.checkout',
+        'Print Template Context: checkout',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.checkout', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.checkout',
+        'Print Template: checkout',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.hold_transit_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.hold_transit_slip',
+        'Print Template Context: hold_transit_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.hold_transit_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.hold_transit_slip',
+        'Print Template: hold_transit_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.hold_shelf_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.hold_shelf_slip',
+        'Print Template Context: hold_shelf_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.hold_shelf_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.hold_shelf_slip',
+        'Print Template: hold_shelf_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.holds_for_bib', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.holds_for_bib',
+        'Print Template Context: holds_for_bib',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.holds_for_bib', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.holds_for_bib',
+        'Print Template: holds_for_bib',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.holds_for_patron', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.holds_for_patron',
+        'Print Template Context: holds_for_patron',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.holds_for_patron', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.holds_for_patron',
+        'Print Template: holds_for_patron',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.hold_pull_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.hold_pull_list',
+        'Print Template Context: hold_pull_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.hold_pull_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.hold_pull_list',
+        'Print Template: hold_pull_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.hold_shelf_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.hold_shelf_list',
+        'Print Template Context: hold_shelf_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.hold_shelf_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.hold_shelf_list',
+        'Print Template: hold_shelf_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.in_house_use_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.in_house_use_list',
+        'Print Template Context: in_house_use_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.in_house_use_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.in_house_use_list',
+        'Print Template: in_house_use_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.item_status', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.item_status',
+        'Print Template Context: item_status',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.item_status', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.item_status',
+        'Print Template: item_status',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.items_out', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.items_out',
+        'Print Template Context: items_out',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.items_out', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.items_out',
+        'Print Template: items_out',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.patron_address', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.patron_address',
+        'Print Template Context: patron_address',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.patron_address', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.patron_address',
+        'Print Template: patron_address',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.patron_data', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.patron_data',
+        'Print Template Context: patron_data',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.patron_data', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.patron_data',
+        'Print Template: patron_data',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.patron_note', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.patron_note',
+        'Print Template Context: patron_note',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.patron_note', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.patron_note',
+        'Print Template: patron_note',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.renew', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.renew',
+        'Print Template Context: renew',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.renew', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.renew',
+        'Print Template: renew',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.transit_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.transit_list',
+        'Print Template Context: transit_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.transit_list', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.transit_list',
+        'Print Template: transit_list',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.transit_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.transit_slip',
+        'Print Template Context: transit_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.transit_slip', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.transit_slip',
+        'Print Template: transit_slip',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.offline_checkout', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.offline_checkout',
+        'Print Template Context: offline_checkout',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.offline_checkout', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.offline_checkout',
+        'Print Template: offline_checkout',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.offline_renew', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.offline_renew',
+        'Print Template Context: offline_renew',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.offline_renew', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.offline_renew',
+        'Print Template: offline_renew',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.offline_checkin', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.offline_checkin',
+        'Print Template Context: offline_checkin',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.offline_checkin', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.offline_checkin',
+        'Print Template: offline_checkin',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template_context.offline_in_house_use', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template_context.offline_in_house_use',
+        'Print Template Context: offline_in_house_use',
+        'cwst', 'label'
+    )
+), (
+    'eg.print.template.offline_in_house_use', 'gui', 'string',
+    oils_i18n_gettext(
+        'eg.print.template.offline_in_house_use',
+        'Print Template: offline_in_house_use',
+        'cwst', 'label'
+    )
 );
 
+
 -- More values with fm_class'es
 INSERT INTO config.workstation_setting_type (name, grp, datatype, fm_class, label)
 VALUES (
@@ -493,13 +867,6 @@ VALUES (
 );
 
 
-
-/*
-INSERT INTO permission.perm_list (id, code, description) VALUES
- (594, 'APPLY_WORKSTATION_SETTING',
-   oils_i18n_gettext(594, 'APPLY_WORKSTATION_SETTING', 'ppl', 'description'));
-*/
-
 COMMIT;
 
 
@@ -507,3 +874,4 @@ COMMIT;
 
 
 
+
index 7eb8cf0..72f57a0 100644 (file)
@@ -89,11 +89,8 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg
     }
 
     // set modifiers from stored preferences
-    // We know these settings live on the server, so manually batch
-    // them for speed.
-    // TODO: once Hatch storage is deprecated, add a getItemBatch function.
     var snames = modifiers.map(function(m) {return 'eg.circ.checkin.' + m;});
-    egCore.hatch.getServerItemBatch(snames).then(function(settings) {
+    egCore.hatch.getItemBatch(snames).then(function(settings) {
         angular.forEach(settings, function(val, key) {
             if (val === true) {
                 var parts = key.split('.')
index 4936cab..f8df253 100644 (file)
@@ -233,6 +233,8 @@ angular.module('egCoreMod')
         );
     }
 
+    // TODO: once Hatch is printing-only, should probably store
+    // this preference on the server.
     service.usePrinting = function() {
         return service.getLocalItem('eg.hatch.enable.printing');
     }
@@ -271,6 +273,46 @@ angular.module('egCoreMod')
         return deferred.promise;
     }
 
+    // Collect values in batch.
+    // For server-stored values espeically, this is more efficient 
+    // than a series of one-off calls.
+    service.getItemBatch = function(keys) {
+        var browserKeys = [];
+        var serverKeys = [];
+
+        // To take full advantage of the getServerItemBatch call,
+        // we have to know in advance which keys to send to the server
+        // vs those to handle in the browser.
+        keys.forEach(function(key) {
+            if (service.keyStoredInBrowser(key)) {
+                browserKeys.push(key);
+            } else {
+                serverKeys.push(key);
+            }
+        });
+
+        var settings = {};
+
+        var serverPromise = serverKeys.length === 0 ? $q.when() : 
+            service.getServerItemBatch(serverKeys).then(function(values) {
+                angular.forEach(values, function(val, key) {
+                    settings[key] = val;
+                });
+            });
+
+        var browserPromises = [];
+        browserKeys.forEach(function(key) {
+            browserPromises.push(
+                service.getBrowserItem(key).then(function(val) {
+                    settings[key] = val;
+                })
+            );
+        });
+
+        return $q.all(browserPromises.concat(serverPromise))
+            .then(function() {return settings});
+    }
+
     service.getBrowserItem = function(key) {
         if (service.useSettings()) {
             if (service.hatchAvailable) {
@@ -508,11 +550,11 @@ angular.module('egCoreMod')
             function() { return foundValues; }, 
             function() {},
             function(setting) {
-                var val = setting.value();
+                var val = setting.value;
                 // The server returns null for undefined settings.
                 // Treat as undefined locally for backwards compat.
-                service.keyCache[setting.name()] = 
-                    foundValues[setting.name()] = 
+                service.keyCache[setting.name] = 
+                    foundValues[setting.name] = 
                     (val === null) ? undefined : val;
             }
         );
@@ -678,9 +720,12 @@ angular.module('egCoreMod')
 
     // if set, prefix limits the return set to keys starting with 'prefix'
     service.getKeys = function(prefix) {
-        if (service.useSettings()) 
-            return service.getRemoteKeys(prefix);
-        return $q.when(service.getLocalKeys(prefix));
+        var promise = service.getServerKeys(prefix);
+        return service.getBrowserKeys(prefix).then(function(browserKeys) {
+            return promise.then(function(serverKeys) {
+                return serverKeys.concat(browserKeys);
+            });
+        });
     }
 
     service.getRemoteKeys = function(prefix) {
@@ -690,18 +735,20 @@ angular.module('egCoreMod')
         });
     }
 
+    service.getBrowserKeys = function(prefix) {
+        if (service.useSettings()) 
+            return service.getRemoteKeys(prefix);
+        return $q.when(service.getLocalKeys(prefix));
+    }
+
     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);
+        if (!service.auth) service.auth = $injector.get('egAuth');
+        if (!service.auth.token()) return $q.when({});
+        return egNet.request(
+            'open-ils.actor',
+            'open-ils.actor.settings.staff.applied.names.authoritative.atomic',
+            service.auth.token(), prefix
+        );
     }
 
     service.getLocalKeys = function(prefix) {