255f463c4267119c3db3e9533e5dc0a223af4d00
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / staff / circ / patron / edit.component.html
1 <eg-string key="circ.patron.edit.test_notify.success" 
2   i18n-text text="Test Notification Sent"></eg-string>
3 <eg-string key="circ.patron.edit.test_notify.fail" 
4   i18n-text text="Test Notification Failed to Send"></eg-string>
5 <eg-string key="circ.patron.edit.invalidate.success" 
6   i18n-text text="Field Invalidation Succeeded"></eg-string>
7 <eg-string key="circ.patron.edit.invalidate.fail" 
8   i18n-text text="Failed to Invalidate Field"></eg-string>
9 <eg-string key="circ.patron.edit.grplink.success" 
10   i18n-text text="Group Link Succeeded"></eg-string>
11 <eg-string key="circ.patron.edit.grplink.fail" 
12   i18n-text text="Group Link Failed"></eg-string>
13 <eg-string key="circ.patron.edit.default_addr_type"
14   i18n-text text="Mailing"></eg-string>
15
16 <eg-patron-secondary-groups [secondaryGroups]="secondaryGroups" #secondaryGroupsDialog>
17 </eg-patron-secondary-groups>
18 <eg-patron-barcodes #barcodesDialog [patron]="patron"></eg-patron-barcodes>
19
20 <eg-alert-dialog #addrAlert
21   i18n-dialogTitle dialogTitle="Address Alert">
22 </eg-alert-dialog>
23
24 <eg-alert-dialog #addrRequiredAlert
25   i18n-dialogTitle dialogTitle="Address Required"
26   i18n-dialogBody dialogBody="An address is required during registration">
27 </eg-alert-dialog>
28
29 <eg-alert-dialog #xactCollisionAlert
30   i18n-dialogTitle dialogTitle="Save Collision"
31   i18n-dialogBody dialogBody="Patron record was modified by another user while you were 
32   editing it. Your changes were not saved; please reapply them.">
33 </eg-alert-dialog>
34
35 <eg-hold-notify-update-dialog #holdNotifyUpdateDialog>
36 </eg-hold-notify-update-dialog>
37
38 <div class="row" *ngIf="!showForm">
39   <div class="col-lg-6 offset-lg-3">
40     <eg-progress-inline></eg-progress-inline>
41   </div>
42 </div>
43
44 <ng-template #fieldExample let-args="args">
45   <span class="ml-2" *ngIf="exampleText(args.cls, args.field)" i18n>
46     Example: {{exampleText(args.cls, args.field)}}
47   </span>
48 </ng-template>
49
50 <!-- IDL-generated field labels.  Override with args.overrideLabel -->
51 <ng-template #fieldLabel let-args="args">
52   <div class="col-lg-3 field-label">
53     <label for="{{getClass(args.cls)}}-{{args.field}}-input">
54       {{getFieldLabel(getClass(args.cls), args.field, args.overrideLabel)}}
55     </label>
56     <eg-help-popover *ngIf="getFieldDoc(args.cls, args.field)"
57       buttonClass="btn-sm text-info p-0 m-0"
58       [placement]="'right'" [helpText]="getFieldDoc(args.cls, args.field)">
59     </eg-help-popover>
60   </div>
61 </ng-template>
62
63 <ng-template #userSettingLabel let-args="args">
64   <div class="col-lg-3 field-label">
65     <label for="cust-{{args.settingName}}-input">
66       {{userSettingTypes[args.settingName].label()}}
67     </label>
68   </div>
69 </ng-template>
70
71 <!-- text / number / email inputs -->
72 <ng-template #fieldInput let-args="args">
73   <div class="col-lg-3">
74     <input 
75       type="{{args.type || 'text'}}"
76       class="form-control" 
77       name="{{getClass(args.cls)}}-{{args.field}}-input"
78       id="{{getClass(args.cls)}}-{{args.field}}-input"
79       [ngModel]="objectFromPath(args.path, args.index)[args.field]()"
80       (ngModelChange)="fieldValueChange(args.path, args.index, args.field, $event)"
81       (change)="afterFieldChange(args.path, args.index, args.field)"
82       [required]="fieldRequired(getClass(args.cls) + '.' + args.field)"
83       [pattern]="fieldPattern(getClass(args.cls), args.field)"
84       [disabled]="args.disabled"
85     />
86   </div>
87 </ng-template>
88
89 <!-- checkbox inputs -->
90 <ng-template #fieldCheckbox let-args="args">
91   <div class="col-lg-3">
92     <input 
93       type="checkbox"
94       class="form-check-input ml-0"
95       name="{{getClass(args.cls)}}-{{args.field}}-input"
96       id="{{getClass(args.cls)}}-{{args.field}}-input"
97       [ngModel]="objectFromPath(args.path, args.index)[args.field]() === 't'"
98       (ngModelChange)="fieldValueChange(args.path, args.index, args.field, $event)"
99       (change)="afterFieldChange(args.path, args.index, args.field)"
100       [pattern]="fieldPattern(getClass(args.cls), args.field)"
101       [disabled]="disabled"
102     />
103   </div>
104 </ng-template>
105
106 <!-- combobox inputs -->
107 <ng-template #fieldCombobox let-args="args">
108   <div class="col-lg-3">
109     <eg-combobox [entries]="args.entries"
110       name="{{getClass(args.cls)}}-{{args.field}}-input"
111       domId="{{getClass(args.cls)}}-{{args.field}}-input"
112       [selectedId]="getFieldValue(args.path, args.index, args.field)"
113       (onChange)="
114         fieldValueChange(args.path, args.index, args.field, $event ? $event.id : null); 
115         afterFieldChange(args.path, args.index, args.field)"
116       [required]="fieldRequired(getClass(args.cls) + '.' + args.field)"
117       [disabled]="args.disabled">
118     </eg-combobox>
119   </div>
120 </ng-template>
121
122 <!-- like fieldRow below, but for user settings checkboxes -->
123 <ng-template #userSettingsCheckboxRow let-args="args">
124   <div class="row pt-1 pb-1 mt-1">
125     <ng-container *ngTemplateOutlet="userSettingLabel; context: {args: args}">
126     </ng-container>
127     <div class="col-lg-3">
128       <input 
129         type="checkbox"
130         class="form-check-input ml-0"
131         name="cust-{{args.settingName}}-input"
132         id="cust-{{args.settingName}}-input"
133         [ngModel]="userSettings[args.settingName]"
134         (ngModelChange)="userSettingChange(args.settingName, $event)"
135         [disabled]="args.disabled"
136       />
137     </div>
138   </div>
139 </ng-template>
140
141 <ng-template #userSettingInput let-args="args">
142   <div class="col-lg-3">
143     <input 
144       type="{{args.type || 'text'}}"
145       class="form-control"
146       name="cust-{{args.settingName}}-input"
147       id="cust-{{args.settingName}}-input"
148       [ngModel]="userSettings[args.settingName]"
149       (ngModelChange)="userSettingChange(args.settingName, $event)"
150       [required]="settingFieldRequired(args.settingName)"
151       [disabled]="args.disabled"
152     />
153   </div>
154 </ng-template>
155
156
157 <ng-template #userSettingInputRow let-args="args">
158   <div class="row pt-1 pb-1 mt-1">
159     <ng-container *ngTemplateOutlet="userSettingLabel; context: {args: args}">
160     </ng-container>
161     <ng-container *ngTemplateOutlet="userSettingInput; context: {args: args}">
162     </ng-container>
163   </div>
164 </ng-template>
165
166
167 <!-- One row of label + field.  
168     Used when a field requires no additional toggles. -->
169 <ng-template #fieldRow let-args="args">
170   <div class="row pt-1 pb-1 mt-1" *ngIf="showField(getClass(args.cls) + '.' + args.field)">
171     <ng-container *ngTemplateOutlet="fieldLabel; context: {args: args}">
172     </ng-container>
173     <ng-container *ngTemplateOutlet="args.template; context: {args: args}">
174     </ng-container>
175     <ng-container *ngTemplateOutlet="fieldExample; context: {args: args}">
176     </ng-container>
177   </div>
178 </ng-template>
179
180
181 <!-- The List O' Fields -->
182
183 <div class="mt-3 striped-rows-even patron-edit-container form-validated" *ngIf="patron && showForm">
184
185   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('ac.barcode')">
186     <ng-container *ngTemplateOutlet="fieldLabel; 
187       context: {args: {cls: 'ac', path: 'card', field: 'barcode'}}">
188     </ng-container>
189     <ng-container *ngTemplateOutlet="fieldInput; context: {args: 
190       {cls: 'ac', path: 'card', field: 'barcode', disabled: !patron.card().isnew()}}">
191     </ng-container>
192     <div class="col-lg-6">
193       <ng-container *ngIf="!patron.isnew()">
194         <button [disabled]="replaceBarcodeUsed" class="btn btn-outline-dark" 
195           (click)="replaceBarcode()" i18n>
196           Replace Barcode
197         </button>
198         <button class="btn btn-outline-dark ml-2" (click)="barcodesDialog.open()" i18n>
199           See All
200         </button>
201       </ng-container>
202       <span *ngIf="dupeBarcode" class="text-danger font-weight-bold ml-2" i18n>
203         Barcode is already in use
204       </span>
205     </div>
206   </div>
207
208   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.usrname')">
209     <ng-container *ngTemplateOutlet="fieldLabel; context: {args: {field: 'usrname'}}">
210     </ng-container>
211     <ng-container *ngTemplateOutlet="fieldInput; context: {args: {field: 'usrname'}}">
212     </ng-container>
213     <div class="col-lg-6">
214       <span *ngIf="dupeUsername" class="text-danger font-weight-bold ml-2" i18n>
215         Username is already in use
216       </span>
217     </div>
218   </div>
219
220   <div class="row pt-1 pb-1 mt-1">
221     <ng-container *ngTemplateOutlet="fieldLabel; context: {args: {field: 'passwd'}}">
222     </ng-container>
223     <ng-container 
224       *ngTemplateOutlet="fieldInput; context: {args: {field: 'passwd'}}">
225     </ng-container>
226     <div class="col-lg-3">
227       <button class="btn btn-outline-dark" (click)="generatePassword()" i18n>
228         Generate Password
229       </button>
230     </div>
231   </div>
232
233   <!-- Name / Preferred Name Tabs -->
234   <ul ngbNav #nameNav="ngbNav" class="nav-tabs" [(activeId)]="nameTab" [keyboard]="true" [roles]="false" role="tablist">
235     <li role="presentation" ngbNavItem="primary">
236       <a role="tab" ngbNavLink i18n>Primary Name</a>
237       <ng-template ngbNavContent>
238         <ng-container *ngTemplateOutlet="fieldRow; context: 
239           {args: {template: fieldInput, field: 'prefix'}}">
240         </ng-container>
241         <ng-container *ngTemplateOutlet="fieldRow; context: 
242           {args: {template: fieldInput, field: 'first_given_name'}}">
243         </ng-container>
244         <ng-container *ngTemplateOutlet="fieldRow; context: 
245           {args: {template: fieldInput, field: 'second_given_name'}}">
246         </ng-container>
247         <ng-container *ngTemplateOutlet="fieldRow; context: 
248           {args: {template: fieldInput, field: 'family_name'}}">
249         </ng-container>
250         <ng-container *ngTemplateOutlet="fieldRow; context: 
251           {args: {template: fieldInput, field: 'suffix'}}">
252         </ng-container>
253       </ng-template>
254     </li>
255     <li role="presentation" ngbNavItem="preferred">
256       <a role="tab" ngbNavLink i18n>Preferred Name</a>
257       <ng-template ngbNavContent>
258         <ng-container *ngTemplateOutlet="fieldRow; context: 
259           {args: {template: fieldInput, field: 'pref_prefix'}}">
260         </ng-container>
261         <ng-container *ngTemplateOutlet="fieldRow; context: 
262           {args: {template: fieldInput, field: 'pref_first_given_name'}}">
263         </ng-container>
264         <ng-container *ngTemplateOutlet="fieldRow; context: 
265           {args: {template: fieldInput, field: 'pref_second_given_name'}}">
266         </ng-container>
267         <ng-container *ngTemplateOutlet="fieldRow; context: 
268           {args: {template: fieldInput, field: 'pref_family_name'}}">
269         </ng-container>
270         <ng-container *ngTemplateOutlet="fieldRow; context: 
271           {args: {template: fieldInput, field: 'pref_suffix'}}">
272         </ng-container>
273       </ng-template>
274     </li>
275   </ul>
276
277   <!-- Container div for name / pref name tabs -->
278   <div class="border rounded p-2" [ngClass]="{
279     'border-primary': nameTab === 'primary', 
280     'border-success': nameTab === 'preferred'}">
281     <div [ngbNavOutlet]="nameNav"></div>
282   </div>
283
284   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.name_keywords')">
285     <ng-container 
286       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'name_keywords'}}">
287     </ng-container>
288     <div class="col-lg-3">
289       <textarea
290         class="form-control" 
291         name="au-name_keywords-input"
292         id="au-name_keywords-input"
293         [ngModel]="objectFromPath(null, null)['name_keywords']()"
294         (ngModelChange)="fieldValueChange(null, null, 'name_keywords', $event)"
295         (change)="afterFieldChange(null, args.index, 'name_keywords')"
296         [required]="fieldRequired('au.name_keywords')"
297         [pattern]="fieldPattern('au', 'name_keywords')">
298       </textarea>
299     </div>
300   </div>
301
302   <!-- example of overriding a field label -->
303   <eg-string #holdAliasString i18n-text text="Holds Alias"></eg-string>
304   <ng-container *ngTemplateOutlet="fieldRow; context: 
305     {args: {template: fieldInput, field: 'alias', overrideLabel: holdAliasString.text}}">
306   </ng-container>
307
308   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.dob')">
309     <ng-container 
310       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'dob'}}">
311     </ng-container>
312     <div class="col-lg-3">
313       <eg-date-select
314         domId="au-dob-input"
315         fieldName="au-dob-input"
316         [noMaxWidth]="true"
317         [initialYmd]="patron.dob()"
318         (onChangeAsIso)="
319           fieldValueChange(null, null, 'dob', $event); 
320           afterFieldChange(null, null, 'dob')"
321         [required]="fieldRequired('au.dob')">
322       </eg-date-select>
323     </div>
324   </div>
325   <ng-container *ngTemplateOutlet="fieldRow; context: 
326     {args: {template: fieldCheckbox, field: 'juvenile'}}">
327   </ng-container>
328   <ng-container *ngTemplateOutlet="fieldRow; context: 
329     {args: {template: fieldInput, field: 'guardian'}}">
330   </ng-container>
331   <ng-container *ngTemplateOutlet="fieldRow; context: 
332     {args: {template: fieldCombobox, field: 'ident_type', entries: identTypes}}">
333   </ng-container>
334   <ng-container *ngTemplateOutlet="fieldRow; context: 
335     {args: {template: fieldInput, field: 'ident_value'}}">
336   </ng-container>
337   <ng-container *ngTemplateOutlet="fieldRow; context: 
338     {args: {template: fieldCombobox, field: 'ident_type2', entries: identTypes}}">
339   </ng-container>
340   <ng-container *ngTemplateOutlet="fieldRow; context: 
341     {args: {template: fieldInput, field: 'ident_value2'}}">
342   </ng-container>
343
344   <div class="row pt-1 pb-1 mt-1">
345     <ng-container 
346       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'email'}}">
347     </ng-container>
348     <ng-container 
349       *ngTemplateOutlet="fieldInput; context: {args: {field: 'email', type: 'email'}}">
350     </ng-container>
351     <div class="col-lg-6">
352       <ng-container *ngIf="patron.email()">
353         <button class="btn btn-outline-dark" 
354           (click)="sendTestMessage('au.email.test')" i18n>
355           Send Test Email
356         </button>
357         <ng-container *ngIf="!patron.isnew()">
358          <button class="btn btn-outline-dark ml-2" 
359            (click)="invalidateField('email')" i18n>Invalidate</button>
360         </ng-container>
361       </ng-container>
362     </div>
363   </div>
364
365   <ng-container 
366     *ngIf="userSettingTypes['circ.send_email_checkout_receipts'] && showField('au.email')">
367     <ng-container *ngTemplateOutlet="userSettingsCheckboxRow; context: 
368       {args: {settingName: 'circ.send_email_checkout_receipts'}}">
369     </ng-container>
370   </ng-container>
371
372   <div class="row pt-1 pb-1 mt-1">
373     <ng-container 
374       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'day_phone'}}">
375     </ng-container>
376     <ng-container 
377       *ngTemplateOutlet="fieldInput; context: {args: {field: 'day_phone'}}">
378     </ng-container>
379     <div class="col-lg-6">
380       <ng-container *ngIf="patron.day_phone() && !patron.isnew()">
381         <button class="btn btn-outline-dark" 
382           (click)="invalidateField('day_phone')" i18n>Invalidate</button>
383       </ng-container>
384       <ng-container *ngTemplateOutlet="fieldExample; context: {args: {field: 'day_phone'}}">
385       </ng-container>
386     </div>
387   </div>
388
389   <div class="row pt-1 pb-1 mt-1">
390     <ng-container 
391       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'evening_phone'}}">
392     </ng-container>
393     <ng-container 
394       *ngTemplateOutlet="fieldInput; context: {args: {field: 'evening_phone'}}">
395     </ng-container>
396     <div class="col-lg-6">
397       <ng-container *ngIf="patron.evening_phone() && !patron.isnew()">
398         <button class="btn btn-outline-dark" 
399           (click)="invalidateField('evening_phone')" i18n>Invalidate</button>
400       </ng-container>
401       <ng-container *ngTemplateOutlet="fieldExample; context: {args: {field: 'evening_phone'}}">
402       </ng-container>
403     </div>
404   </div>
405
406   <div class="row pt-1 pb-1 mt-1">
407     <ng-container 
408       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'other_phone'}}">
409     </ng-container>
410     <ng-container 
411       *ngTemplateOutlet="fieldInput; context: {args: {field: 'other_phone'}}">
412     </ng-container>
413     <div class="col-lg-6">
414       <ng-container *ngIf="patron.other_phone() && !patron.isnew()">
415         <button class="btn btn-outline-dark" 
416           (click)="invalidateField('other_phone')" i18n>Invalidate</button>
417       </ng-container>
418       <ng-container *ngTemplateOutlet="fieldExample; context: {args: {field: 'other_phone'}}">
419       </ng-container>
420     </div>
421   </div>
422
423   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.home_ou')">
424     <ng-container 
425       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'home_ou'}}">
426     </ng-container>
427     <div class="col-lg-3">
428       <eg-org-select
429         domId="au-home_ou-input"
430         fieldName="au-home_ou-input"
431         [initialOrgId]="patron.home_ou()"
432         [disableOrgs]="cannotHaveUsersOrgs()"
433         [required]="true"
434         (onChange)="
435           fieldValueChange(null, null, 'home_ou', $event ? $event.id() : null); 
436           afterFieldChange(null, null, 'home_ou')">
437       </eg-org-select>
438     </div>
439   </div>
440
441   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.profile')">
442     <ng-container 
443       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'profile'}}">
444     </ng-container>
445     <div class="col-lg-3">
446       <eg-profile-select #profileSelect 
447         [useDisplayEntries]="true"
448         [initialGroupId]="patron.profile()" 
449         [required]="true"
450         (profileChange)="
451           fieldValueChange(null, null, 'profile', $event ? $event.id() : null); 
452           afterFieldChange(null, null, 'profile')">
453       </eg-profile-select>
454     </div>
455     <div class="col-lg-6">
456       <button class="btn btn-outline-dark" 
457         *ngIf="hasPerm.CREATE_USER_GROUP_LINK"
458         (click)="openGroupsDialog()" i18n>Secondary Groups</button>
459     </div>
460   </div>
461
462   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.expire_date')">
463     <ng-container 
464       *ngTemplateOutlet="fieldLabel; context: {args: {field: 'expire_date'}}">
465     </ng-container>
466     <div class="col-lg-3">
467       <eg-date-select
468         domId="au-expire_date-input"
469         fieldName="au-expire_date-input"
470         [required]="fieldRequired('au.expire_date')"
471         (onChangeAsIso)="
472           fieldValueChange(null, null, 'expire_date', $event); 
473           afterFieldChange(null, null, 'expire_date')"
474         [(ngModel)]="expireDate">
475       </eg-date-select>
476     </div>
477     <div class="col-lg-6">
478       <button class="btn btn-outline-dark" (click)="setExpireDate()" i18n>
479         Update Expire Date
480       </button>
481     </div>
482   </div>
483   <ng-container *ngTemplateOutlet="fieldRow; context: 
484     {args: {template: fieldCombobox, field: 'net_access_level', entries: inetLevels}}">
485   </ng-container>
486   <ng-container *ngTemplateOutlet="fieldRow; context: 
487     {args: {template: fieldCheckbox, field: 'active'}}">
488   </ng-container>
489   <ng-container *ngTemplateOutlet="fieldRow; context: 
490     {args: {template: fieldCheckbox, field: 'barred'}}">
491   </ng-container>
492   <ng-container *ngTemplateOutlet="fieldRow; context: 
493     {args: {template: fieldCheckbox, field: 'master_account'}}">
494   </ng-container>
495   <ng-container *ngTemplateOutlet="fieldRow; context: 
496     {args: {template: fieldInput, field: 'claims_returned_count', 
497       type: 'number', disabled: !hasPerm.UPDATE_PATRON_CLAIM_RETURN_COUNT}}">
498   </ng-container>
499   <ng-container *ngTemplateOutlet="fieldRow; context: 
500     {args: {template: fieldInput, field: 'claims_never_checked_out_count', 
501       type: 'number', disabled: !hasPerm.UPDATE_PATRON_CLAIM_NEVER_CHECKED_OUT_COUNT}}">
502   </ng-container>
503
504   <div class="alert alert-success pt-2 pb-2 mt-3 mb-3 d-flex">
505     <div class="m-auto font-weight-bold" i18n>User Settings</div>
506   </div>
507
508   <ng-container *ngTemplateOutlet="userSettingInputRow; context: 
509     {args: {settingName: 'opac.default_phone'}}">
510   </ng-container>
511
512   <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.home_ou')">
513     <ng-container *ngTemplateOutlet="userSettingLabel; 
514       context: {args: {settingName: 'opac.default_pickup_location'}}">
515     </ng-container>
516     <div class="col-lg-3">
517       <eg-org-select
518         domId="cust-opac.default_pickup_location-input"
519         fieldName="cust-opac.default_pickup_location-input"
520         [initialOrgId]="userSettings['opac.default_pickup_location']"
521         [disableOrgs]="cannotHaveVolsOrgs()"
522         (onChange)="userSettingChange(
523           'opac.default_pickup_location', $event ? $event.id() : null)">
524       </eg-org-select>
525     </div>
526   </div>
527
528   <div class="row pt-1 pb-1 mt-1">
529     <ng-container *ngTemplateOutlet="userSettingLabel; 
530       context: {args: {settingName: 'opac.hold_notify'}}">
531     </ng-container>
532     <div class="col-lg-3">
533       <div class="form-check form-check-inline mr-2">
534         <input class="form-check-input" type="checkbox" name="hold-notify-phone" 
535           id="hold-notify-phone" [(ngModel)]="holdNotifyTypes.phone"
536           (ngModelChange)="emitSaveState()"/>
537         <label class="form-check-label" for="hold-notify-phone" i18n>Phone</label>
538       </div>
539       <div class="form-check form-check-inline mr-2">
540         <input class="form-check-input" type="checkbox" name="hold-notify-email" 
541           id="hold-notify-email" [(ngModel)]="holdNotifyTypes.email"
542           (ngModelChange)="emitSaveState()"/>
543         <label class="form-check-label" for="hold-notify-email" i18n>Email</label>
544       </div>
545       <div class="form-check form-check-inline mr-2" 
546         *ngIf="context.settingsCache['sms.enable']">
547         <input class="form-check-input" type="checkbox" name="hold-notify-sms" 
548           id="hold-notify-sms" [(ngModel)]="holdNotifyTypes.sms"
549           (ngModelChange)="emitSaveState()"/>
550         <label class="form-check-label" for="hold-notify-sms" i18n>SMS</label>
551       </div>
552     </div>
553   </div>
554
555   <ng-container *ngIf="context.settingsCache['sms.enable']">
556
557     <div class="row pt-1 pb-1 mt-1">
558       <ng-container *ngTemplateOutlet="userSettingLabel; 
559         context: {args: {settingName: 'opac.default_sms_notify'}}">
560       </ng-container>
561       <ng-container *ngTemplateOutlet="userSettingInput;
562         context: {args: {settingName: 'opac.default_sms_notify'}}">
563       </ng-container>
564       <div class="col-lg-6">
565         <ng-container *ngIf="userSettings['opac.default_sms_notify'] && 
566           userSettings['opac.default_sms_carrier']">
567           <button class="btn btn-outline-dark" 
568             (click)="sendTestMessage('au.sms_text.test')" i18n>
569             Send Test Text
570           </button>
571         </ng-container>
572       </div>
573     </div>
574
575     <div class="row pt-1 pb-1 mt-1">
576       <ng-container *ngTemplateOutlet="userSettingLabel; 
577         context: {args: {settingName: 'opac.default_sms_carrier'}}">
578       </ng-container>
579       <div class="col-lg-3">
580         <eg-combobox [entries]="smsCarriers"
581           name="cust-opac.default_sms_carrier-input"
582           domId="cust-opac.default_sms_carrier-input"
583           [selectedId]="userSettings['opac.default_sms_carrier']"
584           [required]="settingFieldRequired('opac.default_sms_carrier')"
585           (onChange)="userSettingChange(
586             'opac.default_sms_carrier', $event ? $event.id : null)">
587         </eg-combobox>
588       </div>
589     </div>
590   </ng-container>
591
592   <ng-container *ngFor="let set of optInSettingTypes | keyvalue">
593     <ng-container *ngTemplateOutlet="userSettingsCheckboxRow;
594       context: {args: {settingName: set.key}}">
595     </ng-container>
596   </ng-container>
597
598   <ng-container *ngIf="context.settingsCache['circ.privacy_waiver']">
599     <div class="row pt-1 pb-1 mt-1" 
600       *ngFor="let waiver of patron.waiver_entries(); let index = index">
601       <div class="col-lg-3">
602         <span *ngIf="index === 0" i18n>Allow others to use my account</span>
603       </div>
604       <div class="col-lg-3">
605         <input type="text" class="form-control" [ngModel]="waiver.name()"
606           [disabled]="waiver.isdeleted()"
607           (ngModelChange)="fieldValueChange('waiver_entries', index, 'name', $event)"
608           (change)="afterFieldChange('waiver_entries', index, 'name')"
609           i18n-placeholder placeholder="Enter Name..."/>
610       </div>
611       <div class="col-lg-6 d-flex">
612         <div>
613           <div class="form-inline">
614             <input class="form-check-input" type="checkbox" 
615               [disabled]="waiver.isdeleted()"
616               id="waiver-holds-{{waiver.id()}}" [ngModel]="waiver.place_holds() === 't'"
617               (ngModelChange)="fieldValueChange('waiver_entries', index, 'place_holds', $event)"
618               (change)="afterFieldChange('waiver_entries', index, 'place_holds')"/>
619             <label class="form-check-label"
620               for="waiver-holds-{{waiver.id()}}" i18n>Place Holds?</label>
621           </div>
622           <div class="form-inline">
623             <input class="form-check-input" type="checkbox" 
624               [disabled]="waiver.isdeleted()"
625               id="waiver-history-{{waiver.id()}}" [ngModel]="waiver.view_history() === 't'"
626               (ngModelChange)="fieldValueChange('waiver_entries', index, 'view_history', $event)"
627               (change)="afterFieldChange('waiver_entries', index, 'view_history')"/>
628             <label class="form-check-label"
629               for="waiver-history-{{waiver.id()}}" i18n>View Borrowing History?</label>
630           </div>
631         </div>
632         <div class="ml-3">
633           <div class="form-inline">
634             <input class="form-check-input" type="checkbox" 
635               [disabled]="waiver.isdeleted()"
636               id="waiver-pickup-{{waiver.id()}}" [ngModel]="waiver.pickup_holds() === 't'"
637               (ngModelChange)="fieldValueChange('waiver_entries', index, 'pickup_hold', $event)"
638               (change)="afterFieldChange('waiver_entries', index, 'pickup_hold')"/>
639             <label class="form-check-label"
640               for="waiver-pickup-{{waiver.id()}}" i18n>Pick Up Holds?</label>
641           </div>
642           <div class="form-inline">
643             <input class="form-check-input" type="checkbox" 
644               [disabled]="waiver.isdeleted()"
645               id="waiver-checkout-{{waiver.id()}}" [ngModel]="waiver.checkout_items() === 't'"
646               (ngModelChange)="fieldValueChange('waiver_entries', index, 'checkout_items', $event)"
647               (change)="afterFieldChange('waiver_entries', index, 'checkout_items')"/>
648             <label class="form-check-label"
649               for="waiver-checkout-{{waiver.id()}}" i18n>Check Out Items?</label>
650           </div>
651         </div>
652         <div class="ml-3">
653           <button class="btn btn-danger material-icon-button" 
654             [ngClass]="{'invisible': waiver.isdeleted()}"
655             (click)="removeWaiver(waiver)"
656             i18n-title title="Remove Privacy Waiver">
657             <span class="text-danger material-icons">delete</span>
658           </button>
659         </div>
660         <div class="ml-2" *ngIf="index === patron.waiver_entries().length - 1">
661           <button class="btn btn-success material-icon-button" 
662           (click)="addWaiver()" i18n-title title="Add Privacy Waiver">
663             <span class="text-success material-icons">add</span>
664           </button>
665         </div>
666       </div>
667     </div>
668   </ng-container>
669
670   <div class="alert alert-success pt-2 pb-2 mt-3 mb-3 d-flex">
671     <div class="m-auto font-weight-bold" i18n>Addresses</div>
672   </div>
673
674   <ng-container *ngFor="let addr of patron.addresses(); let index = index">
675     <div class="mb-2" *ngIf="!addr.isdeleted()">
676
677       <div class="alert alert-info p-1">
678         <div class="row">
679           <div class="col-lg-3" i18n>Address #{{index + 1}}</div>
680           <div class="col-lg-9">
681             <div class="form-check form-check-inline mr-2">
682               <input class="form-check-input" type="checkbox" 
683                 name="addr-{{addr.id()}}-mailing" id="addr-{{addr.id()}}-mailing" 
684                 [ngModel]="patron.mailing_address() && addr.id() === patron.mailing_address().id()"
685                 (ngModelChange)="setAddrType('mailing', addr, $event)"/>
686               <label class="form-check-label" 
687                 for="addr-{{addr.id()}}-mailing" i18n>Mailing</label>
688             </div>
689             <div class="form-check form-check-inline mr-2">
690               <input class="form-check-input" type="checkbox" 
691                 name="addr-{{addr.id()}}-billing" id="addr-{{addr.id()}}-billing" 
692                 [ngModel]="patron.billing_address() && addr.id() === patron.billing_address().id()"
693                 (ngModelChange)="setAddrType('billing', addr, $event)"/>
694               <label class="form-check-label" 
695                 for="addr-{{addr.id()}}-billing" i18n>Physical</label>
696             </div>
697             <button class="btn btn-danger" (click)="deleteAddr(addr)" i18n>Delete</button>
698           </div>
699         </div>
700       </div>
701       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
702         fieldInput, field: 'address_type', cls: 'aua', path: 'addresses', index: index}}">
703       </ng-container>
704       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
705         fieldInput, field: 'post_code', cls: 'aua', path: 'addresses', index: index}}">
706       </ng-container>
707       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
708         fieldInput, field: 'street1', cls: 'aua', path: 'addresses', index: index}}">
709       </ng-container>
710       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
711         fieldInput, field: 'street2', cls: 'aua', path: 'addresses', index: index}}">
712       </ng-container>
713       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
714         fieldInput, field: 'city', cls: 'aua', path: 'addresses', index: index}}">
715       </ng-container>
716       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
717         fieldInput, field: 'county', cls: 'aua', path: 'addresses', index: index}}">
718       </ng-container>
719       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
720         fieldInput, field: 'state', cls: 'aua', path: 'addresses', index: index}}">
721       </ng-container>
722       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
723         fieldInput, field: 'country', cls: 'aua', path: 'addresses', index: index}}">
724       </ng-container>
725       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
726         fieldCheckbox, field: 'valid', cls: 'aua', path: 'addresses', index: index}}">
727       </ng-container>
728       <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template: 
729         fieldCheckbox, field: 'within_city_limits', cls: 'aua', path: 'addresses', index: index}}">
730       </ng-container>
731     </div>
732   </ng-container>
733
734   <button class="btn btn-success" (click)="newAddr()" i18n>New Address</button>
735
736   <ng-container *ngIf="showField('stat_cats') && statCats.length > 0">
737     <div class="alert alert-success pt-2 pb-2 mt-3 mb-3 d-flex">
738       <div class="m-auto font-weight-bold" i18n>Statistical Categories</div>
739     </div>
740
741     <div class="row pt-1 pb-1 mt-1" *ngFor="let stat of statCats">
742      <div class="col-lg-3 field-label">
743       <label for="asc-{{stat.cat.id()}}-input">{{stat.cat.name()}}</label>
744      </div>
745      <div class="col-lg-3">
746       <eg-combobox
747         domId="asc-{{stat.cat.id()}}-input"
748         name="asc-{{stat.cat.id()}}-input"
749         [entries]="stat.entries"
750         [required]="stat.cat.required() === 1"
751         [allowFreeText]="stat.cat.allow_freetext() === 1"
752         [(ngModel)]="userStatCats[stat.cat.id()]"
753         (onChange)="userStatCatChange(stat.cat, $event)">
754       </eg-combobox>
755      </div>
756     </div>
757   </ng-container>
758
759
760   <ng-container *ngIf="showField('surveys') && surveys.length > 0">
761     <div class="alert alert-success pt-2 pb-2 mt-2 mb-2 d-flex">
762       <div class="m-auto font-weight-bold" i18n>Surveys</div>
763     </div>
764     <div class="card pt-1 pb-1 mt-1" *ngFor="let survey of surveys">
765       <div class="card-header">{{survey.name()}}</div>
766       <div class="card-body">
767         <div class="row pt-1 pb-1 mt-1" *ngFor="let question of survey.questions()">
768           <div class="col-lg-3 field-label">
769             <label for="asvq-{{question.id()}}-input">{{question.question()}}</label>
770           </div>
771           <div class="col-lg-3">
772             <eg-combobox
773               domId="asvq-{{question.id()}}-input"
774               name="asvq-{{question.id()}}-input"
775               [entries]="surveyQuestionAnswers(question)"
776               (onChange)="applySurveyResponse(question, $event)">
777             </eg-combobox>
778           </div>
779         </div>
780       </div>
781     </div>
782   </ng-container>
783
784 </div>
785