LP#1929587 Place hold button in staff client user/dbriem/lp_1929587_place_hold_visible_no_holdable_copies
authorDan Briem <dbriem@wlsmail.org>
Thu, 3 Jun 2021 00:53:44 +0000 (20:53 -0400)
committerDan Briem <dbriem@wlsmail.org>
Thu, 3 Jun 2021 00:53:44 +0000 (20:53 -0400)
Disables and gray's out the place hold button on records in the
Angular catalog that are deleted or have no holdable copies
unless the user has the perm PLACE_UNFILLABLE_HOLD.

To test:
* Search for records with and without any copies
* Search for records with and without holdable copies
* Search as user with and without the permission
  PLACE_UNFILLABLE_HOLD

Signed-off-by: Dan Briem <dbriem@wlsmail.org>
Open-ILS/src/eg2/src/app/share/catalog/bib-record.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/actions.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/actions.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html
Open-ILS/src/eg2/src/app/staff/catalog/result/record.component.html
Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm

index ce352c7..808aace 100644 (file)
@@ -6,6 +6,7 @@ import {UnapiService} from '@eg/share/catalog/unapi.service';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {NetService} from '@eg/core/net.service';
 import {PcrudService} from '@eg/core/pcrud.service';
+import {PermService} from '@eg/core/perm.service';
 
 export const NAMESPACE_MAPS = {
     'mods':     'http://www.loc.gov/mods/v3',
@@ -38,6 +39,7 @@ export class BibRecordSummary {
     net: NetService;
     displayHighlights: {[name: string]: string | string[]} = {};
     eResourceUrls: EResourceUrl[] = [];
+    isHoldable: boolean;
 
     constructor(record: IdlObject, orgId: number, orgDepth?: number) {
         this.id = Number(record.id());
@@ -79,15 +81,21 @@ export class BibRecordService {
     // Cache of bib editor / creator objects
     // Assumption is this list will be limited in size.
     userCache: {[id: number]: IdlObject};
+    allowUnfillableHolds: boolean;
 
     constructor(
         private idl: IdlService,
         private net: NetService,
         private org: OrgService,
         private unapi: UnapiService,
-        private pcrud: PcrudService
+        private pcrud: PcrudService,
+        private perm: PermService
     ) {
         this.userCache = {};
+        this.perm.hasWorkPermHere(['PLACE_UNFILLABLE_HOLD'])
+            .then(perms => {
+                this.allowUnfillableHolds = perms.PLACE_UNFILLABLE_HOLD;
+            });
     }
 
     getBibSummary(id: number,
@@ -113,6 +121,9 @@ export class BibRecordService {
             summary.holdCount = bibSummary.hold_count;
             summary.holdingsSummary = bibSummary.copy_counts;
             summary.eResourceUrls = bibSummary.urls;
+            summary.isHoldable = bibSummary.record.deleted() == 'f'
+                && bibSummary.has_holdable_copy
+                || this.allowUnfillableHolds;
             return summary;
         }));
     }
@@ -136,6 +147,9 @@ export class BibRecordService {
             summary.attributes = metabibSummary.attributes;
             summary.holdCount = metabibSummary.hold_count;
             summary.holdingsSummary = metabibSummary.copy_counts;
+            summary.isHoldable = metabibSummary.record.deleted() == 'f'
+                && metabibSummary.has_holdable_copy
+                || this.allowUnfillableHolds;
             return summary;
         }));
     }
index 9a64f73..a8d3e45 100644 (file)
 
 <div class="row ml-0 mr-0">
 
-  <a routerLink="/staff/catalog/hold/T" [queryParams]="{target: recId}">
+  <a routerLink="/staff/catalog/hold/T" [queryParams]="{target: recId}"
+    *ngIf="isHoldable">
     <button class="btn btn-outline-primary ml-1" i18n>Place Hold</button>
   </a>
+  <button class="btn btn-outline-secondary ml-1" *ngIf="!isHoldable" disabled i18n>
+    Place Hold
+  </button>
 
   <button class="btn btn-outline-primary ml-1" (click)="addHoldings()" i18n>
     Add Holdings
index bb4eca1..bc50745 100644 (file)
@@ -52,6 +52,8 @@ export class RecordActionsComponent implements OnInit {
         }
     }
 
+    @Input() isHoldable: boolean;
+
     constructor(
         private router: Router,
         private store: StoreService,
index 0630d3b..a083663 100644 (file)
@@ -23,6 +23,7 @@
     <div class="flex-1"></div>
     <div id='staff-catalog-bib-navigation'>
       <eg-catalog-record-actions [recordId]="recordId"
+        [isHoldable]="summary && summary.isHoldable"
         (addHoldingsRequested)="addHoldingsRequested()">
       </eg-catalog-record-actions>
     </div>
index 3f05d42..47dc5a2 100644 (file)
               <ng-container *ngIf="summary.record.deleted() == 't'">
                 <span class="text-danger" i18n>(Deleted)</span>
               </ng-container>
-              <ng-container *ngIf="summary.record.deleted() == 'f'">
-                <span>
-                  <button (click)="placeHold()"
-                    class="btn btn-sm btn-success label-with-material-icon small-text-1">
-                    <span class="material-icons">check</span>
-                    <span i18n>Place Hold</span>
-                  </button>
-                </span>
-              </ng-container>
+              <span>
+                <button (click)="placeHold()" [disabled]="!summary.isHoldable"
+                  [ngClass]="summary.isHoldable ? 'btn-success' : 'btn-secondary'"
+                  class="btn btn-sm label-with-material-icon small-text-1">
+                  <span class="material-icons">check</span>
+                  <span i18n>Place Hold</span>
+                </button>
+              </span>
             </div>
           </div>
         </div>
index 5aec635..286a562 100644 (file)
@@ -3075,6 +3075,12 @@ sub catalog_record_summary {
 
     $copy_method = $self->method_lookup($copy_method); # local method
 
+    my $holdable_method = $is_meta ?
+        'open-ils.search.biblio.metarecord.has_holdable_copy':
+        'open-ils.search.biblio.record.has_holdable_copy';
+
+    $holdable_method = $self->method_lookup($holdable_method); # local method
+
     for my $rec_id (@$record_ids) {
 
         my $response = $is_meta ? 
@@ -3086,6 +3092,8 @@ sub catalog_record_summary {
         $response->{hold_count} = 
             $U->simplereq('open-ils.circ', $holds_method, $rec_id);
 
+        ($response->{has_holdable_copy}) = $holdable_method->run($rec_id);
+
         $client->respond($response);
     }