]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html
LP1959048: manual ng lint fixes
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / catalog / hold / hold.component.html
1
2 <eg-patron-search-dialog #patronSearch>
3 </eg-patron-search-dialog>
4
5 <eg-alert-dialog #activeDateAlert
6   i18n-dialogTitle i18n-dialogBody
7   dialogTitle="Invalid Hold Activation Date"
8   dialogBody="Hold activation date {{activeDateYmd}} is not valid.
9     Please chose a date in the future">
10 </eg-alert-dialog>
11
12 <div class="row">
13   <div class="col-lg-1">
14     <button class="btn btn-info label-with-material-icon"
15       (click)="goBack()" [disabled]="hasNoHistory()">
16       <span class="material-icons">keyboard_backspace</span>
17       <span i18n>Return</span>
18     </button>
19   </div>
20   <div class="col-lg-5">
21     <ng-container *ngIf="badBarcode">
22       <div class="alert alert-danger" i18n>
23         Barcode '{{badBarcode}}' not found.
24       </div>
25     </ng-container>
26     <ng-container *ngIf="!badBarcode">
27       <h3 i18n>Place Hold
28         <small *ngIf="user">
29         ({{user.pref_family_name() ? user.pref_family_name() : user.family_name()}}, 
30         {{user.pref_first_given_name() ? user.pref_first_given_name() :user.first_given_name()}})
31         </small>
32       </h3>
33     </ng-container>
34   </div>
35   <div class="col-lg-2">
36     <button class="btn btn-outline-dark btn-sm" (click)="searchPatrons()">
37       <span class="material-icons mat-icon-in-button align-middle"
38         i18n-title title="Search for Patron">search</span>
39       <span class="align-middle" i18n>Search for Patron</span>
40     </button>
41   </div>
42 </div>
43
44 <form class="form form-validated common-form"
45   autocomplete="off" (keydown.enter)="$event.preventDefault()">
46   <div class="row">
47     <div class="col-lg-6 common-form striped-odd">
48       <div class="row mt-2">
49         <div class="col-lg-6">
50           <div class="form-check">
51             <input class="form-check-input" type="radio"
52               (change)="holdForChanged()"
53               id="hold-for-patron"
54               name="holdFor" value="patron" [(ngModel)]="holdFor"/>
55             <label class="form-check-label" for="hold-for-patron" i18n>
56               Place hold for patron by barcode:
57             </label>
58           </div>
59         </div>
60         <div class="col-lg-6">
61           <div class="input-group">
62             <input type='text' class="form-control" name="userBarcode"
63               [disabled]="holdFor!=='patron'" id='patron-barcode'
64               aria-label="Patron barcode" i18n-aria-label
65               (ngModelChange)="debounceUserBarcodeLookup($event)"
66               (paste)="debounceUserBarcodeLookup($event)"
67               [(ngModel)]="userBarcode"/>
68             <div class="input-group-append">
69               <button class="btn btn-outline-dark" (click)="userBarcodeChanged()">Submit</button>
70             </div>
71           </div>
72         </div>
73       </div>
74       <div class="row mt-2">
75         <div class="col-lg-6">
76           <div class="form-check">
77             <input class="form-check-input" type="radio"
78               (change)="holdForChanged()"
79               id="hold-for-staff"
80               name="holdFor" value="staff" [(ngModel)]="holdFor"/>
81             <label class="form-check-label" i18n for="hold-for-staff">
82               Place hold for this staff account:
83             </label>
84           </div>
85         </div>
86         <div class="col-lg-6 font-weight-bold">{{requestor.usrname()}}</div>
87       </div>
88       <div class="row mt-2">
89         <div class="col-lg-6">
90           <label i18n>Pickup Location: </label>
91         </div>
92         <div class="col-lg-6">
93           <eg-org-select (onChange)="pickupLib = $event ? $event.id() : null"
94             [disableOrgs]="disableOrgs" [applyOrgId]="pickupLib"></eg-org-select>
95         </div>
96       </div>
97       <div class="row mt-2">
98         <div class="col-lg-6">
99           <div class="form-check">
100             <input class="form-check-input" type="checkbox" id="suspend"
101               name="suspend" [(ngModel)]="suspend"/>
102             <label class="form-check-label" for="suspend" i18n>Suspend Hold</label>
103           </div>
104         </div>
105         <div class="col-lg-6">
106           <div [ngClass]="{'border border-danger rounded': activeDateInvalid}">
107             <eg-date-select [(ngModel)]="activeDate" name='active-date'
108               (onChangeAsYmd)="activeDateYmd = $event"
109               (onChangeAsDate)="setActiveDate($event)"
110               (onChangeAsIso)="activeDateSelected($event)" [disabled]="!suspend">
111             </eg-date-select>
112           </div>
113         </div>
114       </div>
115       <div class="row mt-2" *ngIf="multiHoldsActive">
116         <div class="col-lg-6">
117           <label for='multi-hold-count' i18n>Number of copies:</label>
118         </div>
119         <div class="col-lg-6">
120           <select class="form-control" name="multi-hold-count"
121             id="multi-hold-count" [(ngModel)]="multiHoldCount">
122             <option [value]="num"
123               *ngFor="let num of holdCountRange()">{{num}}</option>
124           </select>
125         </div>
126       </div>
127
128     </div><!-- left column -->
129     <div class="col-lg-6">
130       <div class="card">
131         <div class="card-header">
132           <h4 i18n>Notifications</h4>
133         </div>
134         <ul class="list-group list-group-flush">
135           <li class="list-group-item d-flex">
136             <div class="flex-1">
137               <div class="form-check">
138                 <input class="form-check-input" type="checkbox" name="notifyEmail"
139                   id="notifyEmail"
140                   [disabled]="!user || !user.email()" [(ngModel)]="notifyEmail"/>
141                 <label class="form-check-label" for="notifyEmail" i18n>Notify by Email</label>
142               </div>
143             </div>
144             <div class="flex-1">
145               <div class="input-group">
146                 <div class="input-group-prepend">
147                   <label for="userEmail" class="input-group-text" i18n>Email Address</label>
148                 </div>
149                 <input type="text" class="form-control" name="userEmail"
150                   id="userEmail"
151                   [disabled]="true" value="{{user ? user.email() : ''}}"/>
152               </div>
153             </div>
154           </li>
155           <li class="list-group-item d-flex">
156             <div class="flex-1">
157               <div class="form-check">
158                 <input class="form-check-input" type="checkbox"
159                   id="notifyPhone"
160                   name="notifyPhone" [(ngModel)]="notifyPhone"/>
161                 <label class="form-check-label" for="notifyPhone" i18n>Notify by Phone</label>
162               </div>
163             </div>
164             <div class="flex-1">
165               <div class="input-group">
166                 <div class="input-group-prepend">
167                   <label for="phoneValue" class="input-group-text" i18n>Phone Number</label>
168                 </div>
169                 <input type="text" class="form-control" [disabled]="!notifyPhone"
170                   name="phoneValue" id="phoneValue" [(ngModel)]="phoneValue"/>
171               </div>
172             </div>
173           </li>
174           <li *ngIf="smsEnabled" class="list-group-item d-flex">
175             <div class="flex-1">
176               <div class="form-check">
177                 <input class="form-check-input" type="checkbox" id="notifySms"
178                   name="notifySms" [(ngModel)]="notifySms"/>
179                 <label class="form-check-label" for="notifySms" i18n>Notify by SMS</label>
180               </div>
181             </div>
182             <div class="flex-1">
183               <div class="input-group">
184                 <div class="input-group-prepend">
185                   <label for="smsValue" class="input-group-text" i18n>SMS Number</label>
186                 </div>
187                 <input type="text" class="form-control" [disabled]="!notifySms"
188                   id="smsValue" name="smsValue" [(ngModel)]="smsValue"
189                   [required]="notifySms"/>
190               </div>
191             </div>
192           </li>
193           <li *ngIf="smsEnabled" class="list-group-item d-flex">
194             <div class="flex-1">
195               <label for="smsCarriers" i18n>SMS Carrier</label>
196             </div>
197             <div class="flex-1">
198               <eg-combobox [disabled]="!notifySms" #smsCbox
199                 domId="smsCarriers" [required]="notifySms"
200                 placeholder="SMS Carriers" i18n-placeholder
201                 [entries]="smsCarriers">
202               </eg-combobox>
203             </div>
204           </li>
205           <li class="list-group-item">
206             <button class="btn btn-success" (click)="placeHolds()"
207               [disabled]="!readyToPlaceHolds()" i18n>Place Hold(s)</button>
208             <button class="btn btn-outline-dark ml-2" (click)="resetForm()" i18n>Reset</button>
209           </li>
210         </ul><!-- col -->
211       </div><!-- row -->
212     </div><!--card -->
213   </div><!-- col -->
214 </form>
215
216 <div class="row"><div class="col-lg-12"><hr/></div></div>
217
218 <div class="row pt-3 ml-1 mr-1 d-flex">
219   <div class="">
220     <span class="font-weight-bold" i18n>Placing
221       <ng-container *ngIf="holdType === 'M'">METARECORD</ng-container>
222       <ng-container *ngIf="holdType === 'T'">TITLE</ng-container>
223       <ng-container *ngIf="holdType === 'V'">CALL NUMBER</ng-container>
224       <ng-container *ngIf="holdType === 'F'">FORCE ITEM</ng-container>
225       <ng-container *ngIf="holdType === 'C'">ITEM</ng-container>
226       <ng-container *ngIf="holdType === 'R'">RECALL</ng-container>
227       <ng-container *ngIf="holdType === 'I'">ISSUANCE</ng-container>
228       <ng-container *ngIf="holdType === 'P'">PARTS</ng-container>
229       hold on record(s)
230     </span>
231   </div>
232   <div class="flex-1"> </div>
233   <div>
234     <span class="pl-3" *ngIf="isItemHold()">
235       <span i18n>Item-Level Hold Options:</span>
236       <span class="pl-2">
237         <a routerLink="/staff/catalog/hold/C" queryParamsHandling="merge">
238           <button [disabled]="holdType === 'C'" class="btn btn-outline-primary"
239             i18n>Item Hold</button>
240         </a>
241       </span>
242       <span class="pl-2">
243         <a routerLink="/staff/catalog/hold/R" queryParamsHandling="merge">
244           <button [disabled]="holdType === 'R'" class="btn btn-outline-primary"
245             i18n>Recall Hold</button>
246         </a>
247       </span>
248       <span class="pl-2">
249         <a routerLink="/staff/catalog/hold/F" queryParamsHandling="merge">
250           <button [disabled]="holdType === 'F'" class="btn btn-outline-primary"
251             i18n>Force Item Hold</button>
252         </a>
253       </span>
254     </span>
255   </div>
256 </div>
257
258 <ng-template #anyValue>
259   <span class="font-italic" i18n>ANY</span>
260 </ng-template>
261
262 <!--
263     TODO: add a section per hold context for metarecord holds
264     listing the possible formats and languages.
265
266     TODO: add a secion per hold context for T holds providing a
267     link to the metarecord hold equivalent (AKA "Advanced Hold
268     Options") for each record that has selectable filters (and
269     only when metarecord holds are enabled).
270 -->
271
272 <div class="hold-records-list common-form striped-even">
273
274   <div class="row mt-2 ml-1 mr-1 font-weight-bold">
275     <div class="col-lg-1" i18n>Format</div>
276     <div class="col-lg-2" i18n>Title</div>
277     <div class="col-lg-1" i18n>Author</div>
278     <div class="col-lg-2" i18n>Part</div>
279     <div class="col-lg-2" i18n>Call Number</div>
280     <div class="col-lg-1" i18n>Barcode</div>
281     <div class="col-lg-2" i18n>Holds Status</div>
282     <div class="col-lg-1" i18n>Override</div>
283   </div>
284   <div class="row mt-1 ml-1 mr-1" *ngFor="let ctx of holdContexts">
285     <div class="col-lg-12" *ngIf="ctx.holdMeta">
286       <div class="row">
287         <div class="col-lg-1">
288           <ng-container
289             *ngFor="let code of ctx.holdMeta.bibSummary.attributes.icon_format">
290             <img class="pr-1"
291               alt="{{iconFormatLabel(code)}}"
292               title="{{iconFormatLabel(code)}}"
293               src="/images/format_icons/icon_format/{{code}}.png"/>
294           </ng-container>
295         </div>
296         <!-- TODO: link for a metarecord should
297             jump to constituent bib list search page? -->
298         <div class="col-lg-2">
299           <a routerLink="/staff/catalog/record/{{ctx.holdMeta.bibId}}">
300             {{ctx.holdMeta.bibSummary.display.title}}
301           </a>
302         </div>
303         <div class="col-lg-1">{{ctx.holdMeta.bibSummary.display.author}}</div>
304         <div class="col-lg-2">
305           <ng-container *ngIf="ctx.holdMeta.parts.length">
306             <select class="form-control"  (change)="setPart(ctx, $event)"
307               [ngModel]="ctx.holdMeta.part ? ctx.holdMeta.part.id() : ''">
308               <option value="" i18n>Any Part</option>
309               <option *ngFor="let part of ctx.holdMeta.parts"
310                 value="{{part.id()}}">{{part.label()}}</option>
311             </select>
312           </ng-container>
313           <ng-container *ngIf="ctx.holdMeta.parts.length === 0">
314             <ng-container *ngIf="ctx.holdMeta.part">
315               <span>{{ctx.holdMeta.part.label()}}</span>
316             </ng-container>
317             <ng-container *ngIf="!ctx.holdMeta.part">
318               <span i18n>N/A</span>
319             </ng-container>
320           </ng-container>
321         </div>
322         <div class="col-lg-2">
323           <ng-container *ngIf="ctx.holdMeta.callNum; else anyValue">
324             {{ctx.holdMeta.callNum.label()}}
325           </ng-container>
326         </div>
327         <div class="col-lg-1">
328           <ng-container *ngIf="ctx.holdMeta.copy; else anyValue">
329             {{ctx.holdMeta.copy.barcode()}}
330           </ng-container>
331         </div>
332         <div class="col-lg-2">
333           <ng-container *ngIf="!ctx.lastRequest && !ctx.processing">
334             <div class="alert alert-info p-1 ml-2" i18n>Hold Pending</div>
335           </ng-container>
336           <ng-container *ngIf="ctx.processing">
337             <div class="alert alert-primary p-1 ml-2" i18n>Hold Processing...</div>
338           </ng-container>
339           <ng-container *ngIf="ctx.lastRequest">
340             <ng-container *ngIf="ctx.lastRequest.result.success">
341               <div class="alert alert-success p-1 ml-2" i18n>Hold Succeeded</div>
342             </ng-container>
343             <ng-container *ngIf="!ctx.lastRequest.result.success">
344               <div class="alert alert-danger p-1 ml-2"
345                 title="{{ctx.lastRequest.result.evt.textcode}}">
346                 {{ctx.lastRequest.result.evt.textcode}}
347               </div>
348             </ng-container>
349           </ng-container>
350         </div>
351         <div class="col-lg-1">
352           <ng-container *ngIf="canOverride(ctx)">
353             <button class="btn btn-info" (click)="override(ctx)">Override</button>
354           </ng-container>
355         </div>
356       </div>
357       <!-- note: using inline style since class-level styling for rows
358           is superseded by the striped-even styling of the container -->
359       <div class="row" *ngIf="hasMetaFilters(ctx)"
360         style="background-color:inherit; border:none">
361         <div class="col-lg-1"><label i18n>Formats: </label></div>
362         <div class="col-lg-11 d-flex">
363           <ng-container
364             *ngFor="let ccvm of ctx.holdMeta.metarecord_filters.formats">
365             <div class="form-check ml-3">
366               <input class="form-check-input" type="checkbox"
367                 [disabled]="ctx.holdMeta.metarecord_filters.formats.length === 1"
368                 [(ngModel)]="ctx.selectedFormats.formats[ccvm.code()]"/>
369               <img class="ml-1"
370                 alt="{{iconFormatLabel(ccvm.code())}}"
371                 title="{{iconFormatLabel(ccvm.code())}}"
372                 src="/images/format_icons/icon_format/{{ccvm.code()}}.png"/>
373               <label class="form-check-label ml-1">
374                 {{ccvm.search_label() || ccvm.value()}}
375               </label>
376             </div>
377           </ng-container>
378         </div>
379       </div>
380       <div class="row" *ngIf="hasMetaFilters(ctx)"
381         style="background-color:inherit; border:none">
382         <div class="col-lg-1"><label i18n>Languages: </label></div>
383         <div class="col-lg-11 d-flex">
384           <ng-container
385             *ngFor="let ccvm of ctx.holdMeta.metarecord_filters.langs">
386             <div class="form-check ml-3">
387               <input class="form-check-input" type="checkbox"
388                 [disabled]="ctx.holdMeta.metarecord_filters.langs.length === 1"
389                 [(ngModel)]="ctx.selectedFormats.langs[ccvm.code()]"/>
390               <label class="form-check-label ml-1">
391                 {{ccvm.search_label() || ccvm.value()}}
392               </label>
393             </div>
394           </ng-container>
395         </div>
396       </div>
397     </div>
398   </div>
399 </div>
400
401