LP#1879983: UI for claiming staging
authorGalen Charlton <gmc@equinoxinitiative.org>
Fri, 12 Jun 2020 18:47:58 +0000 (14:47 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Fri, 12 Jun 2020 18:47:58 +0000 (14:47 -0400)
This patch adds a "Staging Staff" column to the To Be Staged
staff and buttons to allow staff to claim and release claims
of responsibility to handle staging an appointment.  A staff
member can take over another's claim, but will be asked to
confirm that they want to do so.

Also, reduces the freshness check interval on the to be staged
tab to five seconds, since if the curbside operations require
that staff claim appointments to stage in the first place, there
may be multiple computers in play displaying the to be staged tab.

Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/templates/staff/circ/curbside/index.tt2
Open-ILS/src/templates/staff/circ/curbside/t_to_be_staged_manager.tt2
Open-ILS/web/js/ui/default/staff/circ/curbside/directives/to_be_staged_manager.js
Open-ILS/web/js/ui/default/staff/circ/curbside/services/core.js

index bc51b4b..f42d332 100644 (file)
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/curbside/directives/schedule_pickup.js"></script>
 <script>
 angular.module('egCoreMod').run(['egStrings', function(s) {
+    s.CONFIRM_TAKE_OVER_STAGING_TITLE = "[% l('Take Over Claim for Staging Curbside Pickup Appointment') %]";
+    s.CONFIRM_TAKE_OVER_STAGING_BODY = "[% l('Take over staging pickup appointment [_1] from staff user [_2]?', '{{slot_id}}','{{other_staff}}') %]";
+    s.SUCCESS_CANCEL_APPOINTMENT = "[% l('Canceled curbside appointment {{slot_id}}') %]";
+    s.SUCCESS_CURBSIDE_CLAIM_STAGING = "[% l('Released claim on curbside appointment {{slot_id}} for staging') %]";
+    s.NOTFOUND_CURBSIDE_CLAIM_STAGING = "[% l('Could not find curbside appointment {{slot_id}} to release claim for staging') %]";
+    s.FAILED_CURBSIDE_CLAIM_STAGING = "[% l('Failed to release claim on curbside appointment {{slot_id}} for staging: {{evt_code}}') %]";
+    s.SUCCESS_CURBSIDE_UNCLAIM_STAGING = "[% l('Released claim on curbside appointment {{slot_id}} for staging') %]";
+    s.NOTFOUND_CURBSIDE_UNCLAIM_STAGING = "[% l('Could not find curbside appointment {{slot_id}} to release claim for staging') %]";
+    s.FAILED_CURBSIDE_UNCLAIM_STAGING = "[% l('Failed to release claim on curbside appointment {{slot_id}} for staging: {{evt_code}}') %]";
     s.SUCCESS_CURBSIDE_MARK_STAGED = "[% l('Marked curbside appointment {{slot_id}} as staged') %]";
     s.NOTFOUND_CURBSIDE_MARK_STAGED = "[% l('Could not find curbside appointment {{slot_id}} to mark as staged') %]";
     s.FAILED_CURBSIDE_MARK_STAGED = "[% l('Failed to mark curbside appointment {{slot_id}} as staged: {{evt_code}}') %]";
index ffe98df..5759b18 100644 (file)
     <eg-grid-field label="[% l('Items for Pickup') %]" path="holds" compiled>
       <eg-curbside-holds-list holds="item.holds" bib-data="item.bib_data_by_hold"></eg-curbside-holds-list>
     </eg-grid-field>
+    <eg-grid-field label="[% l('Staging Staff') %]" path="slot.stage_staff" handlers="gridCellHandlers" compiled>
+      {{item.slot.stage_staff().usrname()}}
+      <button class="btn btn-sm btn-default"
+        ng-disabled="!col.handlers.canClaimStaging(item)"
+        ng-click="col.handlers.claim_staging(item)">
+        [% l('Claim') %]
+      </button>
+      <button class="btn btn-sm btn-default"
+        ng-disabled="!col.handlers.canUnclaimStaging(item)"
+        ng-click="col.handlers.unclaim_staging(item)">
+        [% l('Release Claim') %]
+      </button>
+    </eg-grid-field>
     <eg-grid-field label="[% l('Action') %]" handlers="gridCellHandlers" compiled>
       <button class="btn btn-sm btn-primary"
         ng-disabled="col.handlers.wasHandled(item['slot_id']) || col.handlers.patronIsBlocked(item['slot'].patron())"
index b3c7efc..993ecac 100644 (file)
@@ -31,7 +31,7 @@ function($scope , $q , egCurbsideCoreSvc , egCore , egGridDataProvider ,
                         latestTime = latest;
                     }
                 });
-            }, 15000);
+            }, 5000);
         }
     }
     function stopRefreshCheck() {
@@ -91,5 +91,102 @@ function($scope , $q , egCurbsideCoreSvc , egCore , egGridDataProvider ,
     $scope.gridCellHandlers.patronIsBlocked = function(usr) {
         return egCurbsideCoreSvc.patron_blocked(usr);
     }
+    $scope.gridCellHandlers.canClaimStaging = function(item) {
+        if ($scope.wasHandled[item.slot_id]) return false;
+        if (!item.slot.stage_staff()) return true;
+        if (item.slot.stage_staff().id() == egCore.auth.user().id()) return false;
+        return true;
+    }
+    $scope.gridCellHandlers.canUnclaimStaging = function(item) {
+        if ($scope.wasHandled[item.slot_id]) return false;
+        if (!item.slot.stage_staff()) return false;
+        if (item.slot.stage_staff().id() == egCore.auth.user().id()) return true;
+        return false;
+    }
+    $scope.gridCellHandlers.claim_staging = function(item) {
+        console.debug('claim');
+    }
+    doClaimStaging = function(item) {
+        var id = item.slot_id;
+        egCurbsideCoreSvc.claim_staging(id).then(function(resp) {
+            if (evt = egCore.evt.parse(resp)) {
+                ngToast.danger(egCore.strings.$replace(
+                    egCore.strings.FAILED_CURBSIDE_CLAIM_STAGING,
+                    { slot_id : id, evt_code : evt.code }
+                ));
+                return;
+            }
+            if (!angular.isDefined(resp)) {
+                ngToast.warning(egCore.strings.$replace(
+                    egCore.strings.NOTFOUND_CURBSIDE_CLAIM_STAGING,
+                    { slot_id : id }
+                ));
+                return;
+            }
+
+            item.slot = resp;
+
+            // attempt to avoid a spurious refresh prompt
+            egCurbsideCoreSvc.get_latest_to_be_staged().then(function(latest) {
+                if (angular.isDefined(latest)) {
+                    latestTime = latest
+                }
+            });
+
+            ngToast.success(egCore.strings.$replace(
+                egCore.strings.SUCCESS_CURBSIDE_CLAIM_STAGING,
+                { slot_id : id }
+            ));
+        });
+    }
+    $scope.gridCellHandlers.claim_staging = function(item) {
+        if (item.slot.stage_staff() &&
+            item.slot.stage_staff().id() !== egCore.auth.user().id()) {
+            egConfirmDialog.open(
+                egCore.strings.CONFIRM_TAKE_OVER_STAGING_TITLE,
+                egCore.strings.CONFIRM_TAKE_OVER_STAGING_BODY,
+                {   slot_id : item.slot_id,
+                    other_staff : item.slot.stage_staff().usrname(),
+                    ok : function() { doClaimStaging(item) },
+                    cancel : function() {}
+                }
+            );
+        } else {
+            doClaimStaging(item);
+        }
+    }
+    $scope.gridCellHandlers.unclaim_staging = function(item) {
+        var id = item.slot_id;
+        egCurbsideCoreSvc.unclaim_staging(id).then(function(resp) {
+            if (evt = egCore.evt.parse(resp)) {
+                ngToast.danger(egCore.strings.$replace(
+                    egCore.strings.FAILED_CURBSIDE_UNCLAIM_STAGING,
+                    { slot_id : id, evt_code : evt.code }
+                ));
+                return;
+            }
+            if (!angular.isDefined(resp)) {
+                ngToast.warning(egCore.strings.$replace(
+                    egCore.strings.NOTFOUND_CURBSIDE_UNCLAIM_STAGING,
+                    { slot_id : id }
+                ));
+                return;
+            }
+
+            item.slot = resp;
+
+            // attempt to avoid a spurious refresh prompt
+            egCurbsideCoreSvc.get_latest_to_be_staged().then(function(latest) {
+                if (angular.isDefined(latest)) {
+                    latestTime = latest
+                }
+            });
+
+            ngToast.success(egCore.strings.$replace(
+                egCore.strings.SUCCESS_CURBSIDE_UNCLAIM_STAGING,
+                { slot_id : id }
+            ));
+        });
+    }
 
 }]}});
index 1dcd3b0..8a4daa3 100644 (file)
@@ -133,6 +133,23 @@ function(egCore , orderByFilter , $q , $filter , $uibModal , ngToast , egConfirm
         );
     }
 
+    service.claim_staging = function(slot_id) {
+        return egCore.net.request(
+            'open-ils.curbside',
+            'open-ils.curbside.claim_staging',
+            egCore.auth.token(),
+            slot_id
+        );
+    }
+    service.unclaim_staging = function(slot_id) {
+        return egCore.net.request(
+            'open-ils.curbside',
+            'open-ils.curbside.unclaim_staging',
+            egCore.auth.token(),
+            slot_id
+        );
+    }
+
     service.patron_blocked = function(usr) {
         if (usr.barred() == 't' ||
             usr.active() == 'f') {