2 <eg-patron-search-dialog #patronSearch>
3 </eg-patron-search-dialog>
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">
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>
20 <div class="col-lg-5">
21 <ng-container *ngIf="badBarcode">
22 <div class="alert alert-danger" i18n>
23 Barcode '{{badBarcode}}' not found.
26 <ng-container *ngIf="!badBarcode">
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()}})
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>
44 <form class="form form-validated common-form"
45 autocomplete="off" (keydown.enter)="$event.preventDefault()">
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()"
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:
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>
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()"
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:
86 <div class="col-lg-6 font-weight-bold">{{requestor.usrname()}}</div>
88 <div class="row mt-2">
89 <div class="col-lg-6">
90 <label i18n>Pickup Location: </label>
92 <div class="col-lg-6">
93 <eg-org-select (onChange)="pickupLib = $event ? $event.id() : null"
94 [disableOrgs]="disableOrgs" [applyOrgId]="pickupLib"></eg-org-select>
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>
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">
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>
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>
128 </div><!-- left column -->
129 <div class="col-lg-6">
131 <div class="card-header">
132 <h4 i18n>Notifications</h4>
134 <ul class="list-group list-group-flush">
135 <li class="list-group-item d-flex">
137 <div class="form-check">
138 <input class="form-check-input" type="checkbox" name="notifyEmail"
140 [disabled]="!user || !user.email()" [(ngModel)]="notifyEmail"/>
141 <label class="form-check-label" for="notifyEmail" i18n>Notify by Email</label>
145 <div class="input-group">
146 <div class="input-group-prepend">
147 <label for="userEmail" class="input-group-text" i18n>Email Address</label>
149 <input type="text" class="form-control" name="userEmail"
151 [disabled]="true" value="{{user ? user.email() : ''}}"/>
155 <li class="list-group-item d-flex">
157 <div class="form-check">
158 <input class="form-check-input" type="checkbox"
160 name="notifyPhone" [(ngModel)]="notifyPhone"/>
161 <label class="form-check-label" for="notifyPhone" i18n>Notify by Phone</label>
165 <div class="input-group">
166 <div class="input-group-prepend">
167 <label for="phoneValue" class="input-group-text" i18n>Phone Number</label>
169 <input type="text" class="form-control" [disabled]="!notifyPhone"
170 name="phoneValue" id="phoneValue" [(ngModel)]="phoneValue"/>
174 <li *ngIf="smsEnabled" class="list-group-item d-flex">
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>
183 <div class="input-group">
184 <div class="input-group-prepend">
185 <label for="smsValue" class="input-group-text" i18n>SMS Number</label>
187 <input type="text" class="form-control" [disabled]="!notifySms"
188 id="smsValue" name="smsValue" [(ngModel)]="smsValue"
189 [required]="notifySms"/>
193 <li *ngIf="smsEnabled" class="list-group-item d-flex">
195 <label for="smsCarriers" i18n>SMS Carrier</label>
198 <eg-combobox [disabled]="!notifySms" #smsCbox
199 domId="smsCarriers" [required]="notifySms"
200 placeholder="SMS Carriers" i18n-placeholder
201 [entries]="smsCarriers">
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>
216 <div class="row"><div class="col-lg-12"><hr/></div></div>
218 <div class="row pt-3 ml-1 mr-1 d-flex">
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>
232 <div class="flex-1"> </div>
234 <span class="pl-3" *ngIf="isItemHold()">
235 <span i18n>Item-Level Hold Options:</span>
237 <a routerLink="/staff/catalog/hold/C" queryParamsHandling="merge">
238 <button [disabled]="holdType === 'C'" class="btn btn-outline-primary"
239 i18n>Item Hold</button>
243 <a routerLink="/staff/catalog/hold/R" queryParamsHandling="merge">
244 <button [disabled]="holdType === 'R'" class="btn btn-outline-primary"
245 i18n>Recall Hold</button>
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>
258 <ng-template #anyValue>
259 <span class="font-italic" i18n>ANY</span>
263 TODO: add a section per hold context for metarecord holds
264 listing the possible formats and languages.
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).
272 <div class="hold-records-list common-form striped-even">
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>
284 <div class="row mt-1 ml-1 mr-1" *ngFor="let ctx of holdContexts">
285 <div class="col-lg-12" *ngIf="ctx.holdMeta">
287 <div class="col-lg-1">
289 *ngFor="let code of ctx.holdMeta.bibSummary.attributes.icon_format">
291 alt="{{iconFormatLabel(code)}}"
292 title="{{iconFormatLabel(code)}}"
293 src="/images/format_icons/icon_format/{{code}}.png"/>
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}}
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>
313 <ng-container *ngIf="ctx.holdMeta.parts.length === 0">
314 <ng-container *ngIf="ctx.holdMeta.part">
315 <span>{{ctx.holdMeta.part.label()}}</span>
317 <ng-container *ngIf="!ctx.holdMeta.part">
318 <span i18n>N/A</span>
322 <div class="col-lg-2">
323 <ng-container *ngIf="ctx.holdMeta.callNum; else anyValue">
324 {{ctx.holdMeta.callNum.label()}}
327 <div class="col-lg-1">
328 <ng-container *ngIf="ctx.holdMeta.copy; else anyValue">
329 {{ctx.holdMeta.copy.barcode()}}
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>
336 <ng-container *ngIf="ctx.processing">
337 <div class="alert alert-primary p-1 ml-2" i18n>Hold Processing...</div>
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>
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}}
351 <div class="col-lg-1">
352 <ng-container *ngIf="canOverride(ctx)">
353 <button class="btn btn-info" (click)="override(ctx)">Override</button>
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">
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()]"/>
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()}}
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">
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()}}