<div class="col-lg-6">
<span class="font-weight-bold" i18n>Show:</span>
<button class="btn btn-sm btn-outline-dark ml-2"
- [disabled]="showFields == 'required'"
- (click)="changeFields('required')" i18n>Required Fields</button>
+ [disabled]="context.editorFieldVisibilityLevel == 2"
+ (click)="changeFields(2)" i18n>Required Fields</button>
<button class="btn btn-sm btn-outline-dark ml-2"
- [disabled]="showFields == 'suggested'"
- (click)="changeFields('suggested')" i18n>Suggested Fields</button>
+ [disabled]="context.editorFieldVisibilityLevel == 1"
+ (click)="changeFields(1)" i18n>Suggested Fields</button>
<button class="btn btn-sm btn-outline-dark ml-2"
- [disabled]="showFields == 'all'"
- (click)="changeFields('all')" i18n>All Fields</button>
+ [disabled]="context.editorFieldVisibilityLevel == 0"
+ (click)="changeFields(0)" i18n>All Fields</button>
</div>
<div class="col-lg-6 d-flex">
import {OrgService} from '@eg/core/org.service';
import {NetService} from '@eg/core/net.service';
import {PatronService} from '@eg/staff/share/patron/patron.service';
-import {PatronContextService, EditorFieldOptions} from './patron.service';
+import {PatronContextService, FieldVisibilityLevel} from './patron.service';
@Component({
templateUrl: 'edit-toolbar.component.html',
})
export class EditToolbarComponent implements OnInit {
- showFields: EditorFieldOptions = 'all';
-
constructor(
private org: OrgService,
private net: NetService,
ngOnInit() {
}
- changeFields(field: EditorFieldOptions) {
- this.showFields = field;
- this.context.showFieldsChanged.emit(field);
+ changeFields(v: FieldVisibilityLevel) {
+ this.context.editorFieldVisibilityLevel = v;
}
}
[ngModel]="objectFromPath(args.path, args.index)[args.field]()"
(ngModelChange)="fieldValueChange(args.path, args.index, args.field, $event)"
(change)="afterFieldChange(args.path, args.index, args.field)"
- [required]="fieldRequired(getClass(args.cls), args.field)"
- [pattern]="fieldPattern(getClass(args.cls), args.field)"
+ [required]="fieldRequired(getClass(args.cls) + '.' + args.field)"
+ [pattern]="fieldPattern(getClass(args.cls) + '.' + args.field)"
[disabled]="args.disabled"
/>
</div>
[ngModel]="objectFromPath(args.path, args.index)[args.field]() == 't'"
(ngModelChange)="fieldValueChange(args.path, args.index, args.field, $event)"
(change)="afterFieldChange(args.path, args.index, args.field)"
- [required]="fieldRequired(getClass(args.cls), args.field)"
- [pattern]="fieldPattern(getClass(args.cls), args.field)"
+ [required]="fieldRequired(getClass(args.cls) + '.' + args.field)"
+ [pattern]="fieldPattern(getClass(args.cls) + '.' + args.field)"
[disabled]="disabled"
/>
</div>
(onChange)="
fieldValueChange(args.path, args.index, args.field, $event ? $event.id : null);
afterFieldChange(args.path, args.index, args.field)"
- [required]="fieldRequired(getClass(args.cls), args.field)"
+ [required]="fieldRequired(getClass(args.cls) + '.' + args.field)"
[disabled]="args.disabled">
</eg-combobox>
</div>
<!-- One row of label + field.
Used when a field requires no additional toggles. -->
<ng-template #fieldRow let-args="args">
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField(args.cls, args.field)">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField(getClass(args.cls) + '.' + args.field)">
<ng-container *ngTemplateOutlet="fieldLabel; context: {args: args}">
</ng-container>
<ng-container *ngTemplateOutlet="args.template; context: {args: args}">
<!-- The List O' Fields -->
-<div class="mt-3 striped-rows-even patron-edit-container" *ngIf="patron && !loading">
- <ng-container *ngTemplateOutlet="fieldRow; context: {args:
- {template: fieldInput, field: 'barcode', cls: 'ac',
- path: 'card', disabled: !patron.isnew()}}">
- </ng-container>
+<div class="mt-3 striped-rows-even patron-edit-container form-validated" *ngIf="patron && !loading">
+
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('ac.barcode')">
+ <ng-container *ngTemplateOutlet="fieldLabel;
+ context: {args: {cls: 'ac', path: 'card', field: 'barcode'}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldInput; context: {args:
+ {cls: 'ac', path: 'card', field: 'barcode', disabled: !patron.card().isnew()}}">
+ </ng-container>
+ <div class="col-lg-6">
+ <button class="btn btn-outline-dark" (click)="replaceBarcode()" i18n>
+ Replace Barcode
+ </button>
+ <button class="btn btn-outline-dark ml-2" (click)="showBarcodes()" i18n>
+ See All
+ </button>
+ </div>
+ </div>
+
<ng-container *ngTemplateOutlet="fieldRow; context:
{args: {template: fieldInput, field: 'usrname'}}">
</ng-container>
<div [ngbNavOutlet]="nameNav"></div>
</div>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'name_keywords')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.name_keywords')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'name_keywords'}}">
</ng-container>
[ngModel]="objectFromPath(null, null)['name_keywords']()"
(ngModelChange)="fieldValueChange(null, null, 'name_keywords', $event)"
(change)="afterFieldChange(null, args.index, 'name_keywords')"
- [required]="fieldRequired('au', 'name_keywords')"
- [pattern]="fieldPattern('au', 'name_keywords')">
+ [required]="fieldRequired('au.name_keywords')"
+ [pattern]="fieldPattern('au.name_keywords')">
</textarea>
</div>
</div>
{args: {template: fieldInput, field: 'alias', overrideLabel: holdAliasString.text}}">
</ng-container>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'dob')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.dob')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'dob'}}">
</ng-container>
(onChangeAsIso)="
fieldValueChange(null, null, 'dob', $event);
afterFieldChange(null, null, 'dob')"
- [required]="fieldRequired('au', 'dob')">
+ [required]="fieldRequired('au.dob')">
</eg-date-select>
</div>
</div>
</div>
<ng-container
- *ngIf="userSettingTypes['circ.send_email_checkout_receipts'] && showField('au', 'email')">
+ *ngIf="userSettingTypes['circ.send_email_checkout_receipts'] && showField('au.email')">
<ng-container *ngTemplateOutlet="userSettingsCheckboxRow; context:
{args: {settingName: 'circ.send_email_checkout_receipts'}}">
</ng-container>
{args: {template: fieldInput, field: 'other_phone'}}">
</ng-container>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'home_ou')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.home_ou')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'home_ou'}}">
</ng-container>
</div>
</div>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'profile')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.profile')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'profile'}}">
</ng-container>
</div>
</div>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'expire_date')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.expire_date')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'expire_date'}}">
</ng-container>
domId="au-expire_date-input"
fieldName="au-expire_date-input"
[noMaxWidth]="true"
- [required]="fieldRequired('au', 'expire_date')"
+ [required]="fieldRequired('au.expire_date')"
[(ngModel)]="expireDate">
</eg-date-select>
</div>
{args: {template: fieldInput, field: 'claims_never_checked_out_count', type: 'number'}}">
</ng-container>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'alert_message')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.alert_message')">
<ng-container
*ngTemplateOutlet="fieldLabel; context: {args: {field: 'alert_message'}}">
</ng-container>
[ngModel]="objectFromPath(null, null)['alert_message']()"
(ngModelChange)="fieldValueChange(null, null, 'alert_message', $event)"
(change)="afterFieldChange(null, null, 'alert_message')"
- [required]="fieldRequired('au', 'alert_message')"
- [pattern]="fieldPattern('au', 'alert_message')">
+ [required]="fieldRequired('au.alert_message')"
+ [pattern]="fieldPattern('au.alert_message')">
</textarea>
</div>
</div>
{args: {settingName: 'opac.default_phone'}}">
</ng-container>
- <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au', 'home_ou')">
+ <div class="row pt-1 pb-1 mt-1" *ngIf="showField('au.home_ou')">
<ng-container *ngTemplateOutlet="userSettingLabel;
context: {args: {settingName: 'opac.default_pickup_location'}}">
</ng-container>
</ng-container>
<div class="col-lg-3">
<div class="form-check form-check-inline mr-2">
- <input class="form-check-input" type="radio" name="hold-notify-phone"
+ <input class="form-check-input" type="checkbox" name="hold-notify-phone"
id="hold-notify-phone" [(ngModel)]="holdNotifyTypes.phone"/>
<label class="form-check-label" for="hold-notify-phone" i18n>Phone</label>
</div>
<div class="form-check form-check-inline mr-2">
- <input class="form-check-input" type="radio" name="hold-notify-email"
+ <input class="form-check-input" type="checkbox" name="hold-notify-email"
id="hold-notify-email" [(ngModel)]="holdNotifyTypes.email"/>
<label class="form-check-label" for="hold-notify-email" i18n>Email</label>
</div>
- <div class="form-check form-check-inline mr-2" *ngIf="orgSettings['sms.enable']">
- <input class="form-check-input" type="radio" name="hold-notify-sms"
+ <div class="form-check form-check-inline mr-2"
+ *ngIf="context.settingsCache['sms.enable']">
+ <input class="form-check-input" type="checkbox" name="hold-notify-sms"
id="hold-notify-sms" [(ngModel)]="holdNotifyTypes.sms"/>
<label class="form-check-label" for="hold-notify-sms" i18n>SMS</label>
</div>
</div>
</div>
- <ng-container *ngIf="orgSettings['sms.enable']">
+ <ng-container *ngIf="context.settingsCache['sms.enable']">
<div class="row pt-1 pb-1 mt-1">
<ng-container *ngTemplateOutlet="userSettingLabel;
<button class="btn btn-success" (click)="newAddr()" i18n>New Address</button>
- <div class="alert alert-success pt-2 pb-2 mt-3 mb-3 d-flex">
- <div class="m-auto font-weight-bold" i18n>Statistical Categories</div>
- </div>
+ <ng-container *ngIf="showField('stat_cats')">
+ <div class="alert alert-success pt-2 pb-2 mt-3 mb-3 d-flex">
+ <div class="m-auto font-weight-bold" i18n>Statistical Categories</div>
+ </div>
- <div class="row pt-1 pb-1 mt-1" *ngFor="let stat of statCats">
- <div class="col-lg-3 field-label">
- <label for="asc-{{stat.cat.id()}}-input">{{stat.cat.name()}}</label>
- </div>
- <div class="col-lg-3">
- <eg-combobox
- domId="asc-{{stat.cat.id()}}-input"
- name="asc-{{stat.cat.id()}}-input"
- [entries]="stat.entries"
- [allowFreeText]="stat.cat.allow_freetext() == 1"
- [(ngModel)]="userStatCats[stat.cat.id()]"
- (onChange)="userStatCatChange(stat.cat, $event)">
- </eg-combobox>
- </div>
- </div>
+ <div class="row pt-1 pb-1 mt-1" *ngFor="let stat of statCats">
+ <div class="col-lg-3 field-label">
+ <label for="asc-{{stat.cat.id()}}-input">{{stat.cat.name()}}</label>
+ </div>
+ <div class="col-lg-3">
+ <eg-combobox
+ domId="asc-{{stat.cat.id()}}-input"
+ name="asc-{{stat.cat.id()}}-input"
+ [entries]="stat.entries"
+ [required]="stat.cat.required() == 1"
+ [allowFreeText]="stat.cat.allow_freetext() == 1"
+ [(ngModel)]="userStatCats[stat.cat.id()]"
+ (onChange)="userStatCatChange(stat.cat, $event)">
+ </eg-combobox>
+ </div>
+ </div>
+ </ng-container>
- <div class="alert alert-success pt-2 pb-2 mt-2 mb-2 d-flex">
- <div class="m-auto font-weight-bold" i18n>Surveys</div>
- </div>
- <div class="card pt-1 pb-1 mt-1" *ngFor="let survey of surveys">
- <div class="card-header">{{survey.name()}}</div>
- <div class="card-body">
- <div class="row pt-1 pb-1 mt-1" *ngFor="let question of survey.questions()">
- <div class="col-lg-3 field-label">
- <label for="asvq-{{question.id()}}-input">{{question.question()}}</label>
- </div>
- <div class="col-lg-3">
- <eg-combobox
- domId="asvq-{{question.id()}}-input"
- name="asvq-{{question.id()}}-input"
- [entries]="surveyQuestionAnswers(question)"
- (onChange)="applySurveyResponse(question, $event)">
- </eg-combobox>
+ <ng-container *ngIf="showField('surveys')">
+ <div class="alert alert-success pt-2 pb-2 mt-2 mb-2 d-flex">
+ <div class="m-auto font-weight-bold" i18n>Surveys</div>
+ </div>
+ <div class="card pt-1 pb-1 mt-1" *ngFor="let survey of surveys">
+ <div class="card-header">{{survey.name()}}</div>
+ <div class="card-body">
+ <div class="row pt-1 pb-1 mt-1" *ngFor="let question of survey.questions()">
+ <div class="col-lg-3 field-label">
+ <label for="asvq-{{question.id()}}-input">{{question.question()}}</label>
+ </div>
+ <div class="col-lg-3">
+ <eg-combobox
+ domId="asvq-{{question.id()}}-input"
+ name="asvq-{{question.id()}}-input"
+ [entries]="surveyQuestionAnswers(question)"
+ (onChange)="applySurveyResponse(question, $event)">
+ </eg-combobox>
+ </div>
</div>
</div>
</div>
- </div>
+ </ng-container>
</div>
import {AuthService} from '@eg/core/auth.service';
import {PcrudService} from '@eg/core/pcrud.service';
import {PatronService} from '@eg/staff/share/patron/patron.service';
-import {PatronContextService, EditorFieldOptions} from './patron.service';
+import {PatronContextService, FieldVisibilityLevel} from './patron.service';
import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
import {DateUtil} from '@eg/share/util/date';
import {ProfileSelectComponent} from '@eg/staff/share/patron/profile-select.component';
'opac.default_sms_notify'
];
-// Duplicate these settings in resolver.service so they can be
-// fetched/cached with the original batch (fewer net calls).
-const ORG_SETTING_TYPES = [
- 'sms.enable'
-]
-
const PERMS_NEEDED = [
'EDIT_SELF_IN_CLIENT',
'UPDATE_USER',
'UPDATE_PATRON_PRIMARY_CARD'
];
+enum FieldVisibility {
+ REQUIRED = 3,
+ VISIBLE = 2,
+ SUGGESTED = 1
+}
+
+// 3 == value universally required
+// 2 == field is visible by default
+// 1 == field is suggested by default
+const DEFAULT_FIELD_VISIBILITY = {
+ 'ac.barcode': FieldVisibility.REQUIRED,
+ 'au.usrname': FieldVisibility.REQUIRED,
+ 'au.passwd': FieldVisibility.REQUIRED,
+ 'au.first_given_name': FieldVisibility.REQUIRED,
+ 'au.family_name': FieldVisibility.REQUIRED,
+ 'au.pref_first_given_name': FieldVisibility.VISIBLE,
+ 'au.pref_family_name': FieldVisibility.VISIBLE,
+ 'au.ident_type': FieldVisibility.REQUIRED,
+ 'au.ident_type2': FieldVisibility.VISIBLE,
+ 'au.home_ou': FieldVisibility.REQUIRED,
+ 'au.profile': FieldVisibility.REQUIRED,
+ 'au.expire_date': FieldVisibility.REQUIRED,
+ 'au.net_access_level': FieldVisibility.REQUIRED,
+ 'aua.address_type': FieldVisibility.REQUIRED,
+ 'aua.post_code': FieldVisibility.REQUIRED,
+ 'aua.street1': FieldVisibility.REQUIRED,
+ 'aua.street2': FieldVisibility.VISIBLE,
+ 'aua.city': FieldVisibility.REQUIRED,
+ 'aua.county': FieldVisibility.VISIBLE,
+ 'aua.state': FieldVisibility.VISIBLE,
+ 'aua.country': FieldVisibility.REQUIRED,
+ 'aua.valid': FieldVisibility.VISIBLE,
+ 'aua.within_city_limits': FieldVisibility.VISIBLE,
+ 'stat_cats': FieldVisibility.SUGGESTED,
+ 'surveys': FieldVisibility.SUGGESTED,
+ 'au.name_keywords': FieldVisibility.SUGGESTED
+};
+
interface StatCat {
cat: IdlObject;
entries: ComboboxEntry[];
smsCarriers: ComboboxEntry[];
identTypes: ComboboxEntry[];
inetLevels: ComboboxEntry[];
- orgSettings: {[name: string]: any} = {};
statCats: StatCat[] = [];
userStatCats: {[statId: number]: ComboboxEntry} = {};
userSettings: {[name: string]: any} = {};
optInSettingTypes: {[name: string]: IdlObject} = {};
secondaryGroups: IdlObject[];
expireDate: Date;
- visibleFields: EditorFieldOptions;
+
+ fieldVisibility: {[key: string]: FieldVisibility} = {};
// All locations we have the specified permissions
permOrgs: {[name: string]: number[]};
this.context.saveClicked.subscribe(_ => this.save());
this.context.saveCloneClicked.subscribe(_ => this.saveClone());
this.context.printClicked.subscribe(_ => this.printPatron());
- this.context.showFieldsChanged.subscribe(f => this.visibleFields = f);
this.load();
}
.then(_ => this.setIdentTypes())
.then(_ => this.setInetLevels())
.then(_ => this.setOptInSettings())
- .then(_ => this.setOrgSettings())
.then(_ => this.setSmsCarriers())
.then(_ => this.loading = false);
}
});
}
- setOrgSettings(): Promise<any> {
- return this.serverStore.getItemBatch(ORG_SETTING_TYPES)
- .then(settings => this.orgSettings = settings);
- }
-
setSmsCarriers(): Promise<any> {
- if (!this.orgSettings['sms.enable']) {
+ if (!this.context.settingsCache['sms.enable']) {
return Promise.resolve();
}
patron.isnew(true);
patron.addresses([]);
patron.settings([]);
+ patron.cards([]);
patron.waiver_entries([]);
const card = this.idl.create('ac');
card.isnew(true);
card.usr(-1);
patron.card(card);
+ patron.cards().push(card);
this.patron = patron;
}
}
}
- showField(idlClass: string, field: string): boolean {
- // TODO
- return true;
+ showField(field: string): boolean {
+
+ if (this.fieldVisibility[field] === undefined) {
+ // Settings have not yet been applied for this field.
+ // Calculate them now.
+
+ // The preferred name fields use the primary name field settings
+ let settingKey = field;
+ let altName = false;
+ if (field.match(/^au.alt_/)) {
+ altName = true;
+ settingKey = field.replace(/alt_/, '');
+ }
+
+ const required = `ui.patron.edit.${settingKey}.require`;
+ const show = `ui.patron.edit.${settingKey}.show`;
+ const suggest = `ui.patron.edit.${settingKey}.suggest`;
+
+ if (this.context.settingsCache[required]) {
+ if (altName) {
+ // Preferred name fields are never required.
+ this.fieldVisibility[field] = FieldVisibility.VISIBLE;
+ } else {
+ this.fieldVisibility[field] = FieldVisibility.REQUIRED;
+ }
+
+ } else if (this.context.settingsCache[show]) {
+ this.fieldVisibility[field] = FieldVisibility.VISIBLE;
+
+ } else if (this.context.settingsCache[suggest]) {
+ this.fieldVisibility[field] = FieldVisibility.SUGGESTED;
+ }
+ }
+
+ if (this.fieldVisibility[field] == undefined) {
+ // No org settings were applied above. Use the default
+ // settings if present or assume the field has no
+ // visibility flags applied.
+ this.fieldVisibility[field] = DEFAULT_FIELD_VISIBILITY[field] || 0;
+ }
+
+ return this.fieldVisibility[field] >=
+ this.context.editorFieldVisibilityLevel;
}
- fieldRequired(idlClass: string, field: string): boolean {
+ fieldRequired(field: string): boolean {
// TODO
return false;
}
- fieldPattern(idlClass: string, field: string): string {
+ fieldPattern(field: string): string {
// TODO
return null;
}
printPatron() {
// TODO
}
+
+ replaceBarcode() {
+ // Disable current card
+ this.patron.card().active('f');
+ this.patron.card().ischanged(true);
+
+ const card = this.idl.create('ac');
+ card.isnew(true);
+ card.id(this.autoId--);
+ card.usr(this.patron.id());
+ card.active('t');
+
+ this.patron.card(card);
+ this.patron.cards().push(card);
+ }
+
+ showBarcodes() {
+ }
}
import {StoreService} from '@eg/core/store.service';
import {CircService, CircDisplayInfo} from '@eg/staff/share/circ/circ.service';
-export type EditorFieldOptions = 'required' | 'suggested' | 'all';
-
+export enum FieldVisibilityLevel {
+ ALL_FIELDS = 0,
+ SUGGESTED_FIELDS = 1,
+ REQUIRED_FIELDS = 2
+}
export interface BillGridEntry extends CircDisplayInfo {
xact: IdlObject; // mbt
// These should persist tab changes
checkouts: CircGridEntry[] = [];
+ settingsCache: {[key: string]: any} = {};
+
// Emitted by the patron edit toolbar, which is kept as a
// separate component so it can be positioned differently.
// We just act as a go-between.
saveClicked: EventEmitter<void> = new EventEmitter<void>();
saveCloneClicked: EventEmitter<void> = new EventEmitter<void>();
printClicked: EventEmitter<void> = new EventEmitter<void>();
- showFieldsChanged: EventEmitter<EditorFieldOptions> =
- new EventEmitter<EditorFieldOptions>();
+
+ editorFieldVisibilityLevel: FieldVisibilityLevel =
+ FieldVisibilityLevel.ALL_FIELDS;
constructor(
private store: StoreService,
'circ.disable_patron_credit',
'sms.enable',
'ui.patron.registration.require_address',
- 'credit.processor.default'
+ 'credit.processor.default',
+ 'global.password_regex',
+ 'global.juvenile_age_threshold',
+ 'patron.password.use_phone',
+ 'ui.patron.default_inet_access_level',
+ 'ui.patron.default_ident_type',
+ 'ui.patron.default_country',
+ 'ui.patron.registration.require_address',
+ 'circ.holds.behind_desk_pickup_supported',
+ 'circ.patron_edit.clone.copy_address',
+ 'circ.privacy_waiver',
+ 'ui.patron.edit.au.prefix.require',
+ 'ui.patron.edit.au.prefix.show',
+ 'ui.patron.edit.au.prefix.suggest',
+ 'ui.patron.edit.ac.barcode.regex',
+ 'ui.patron.edit.au.second_given_name.show',
+ 'ui.patron.edit.au.second_given_name.suggest',
+ 'ui.patron.edit.au.suffix.show',
+ 'ui.patron.edit.au.suffix.suggest',
+ 'ui.patron.edit.au.alias.show',
+ 'ui.patron.edit.au.alias.suggest',
+ 'ui.patron.edit.au.dob.require',
+ 'ui.patron.edit.au.dob.show',
+ 'ui.patron.edit.au.dob.suggest',
+ 'ui.patron.edit.au.dob.calendar',
+ 'ui.patron.edit.au.dob.example',
+ 'ui.patron.edit.au.juvenile.show',
+ 'ui.patron.edit.au.juvenile.suggest',
+ 'ui.patron.edit.au.ident_value.show',
+ 'ui.patron.edit.au.ident_value.require',
+ 'ui.patron.edit.au.ident_value.suggest',
+ 'ui.patron.edit.au.ident_value2.show',
+ 'ui.patron.edit.au.ident_value2.suggest',
+ 'ui.patron.edit.au.email.require',
+ 'ui.patron.edit.au.email.show',
+ 'ui.patron.edit.au.email.suggest',
+ 'ui.patron.edit.au.email.regex',
+ 'ui.patron.edit.au.email.example',
+ 'ui.patron.edit.au.day_phone.require',
+ 'ui.patron.edit.au.day_phone.show',
+ 'ui.patron.edit.au.day_phone.suggest',
+ 'ui.patron.edit.au.day_phone.regex',
+ 'ui.patron.edit.au.day_phone.example',
+ 'ui.patron.edit.au.evening_phone.require',
+ 'ui.patron.edit.au.evening_phone.show',
+ 'ui.patron.edit.au.evening_phone.suggest',
+ 'ui.patron.edit.au.evening_phone.regex',
+ 'ui.patron.edit.au.evening_phone.example',
+ 'ui.patron.edit.au.other_phone.require',
+ 'ui.patron.edit.au.other_phone.show',
+ 'ui.patron.edit.au.other_phone.suggest',
+ 'ui.patron.edit.au.other_phone.regex',
+ 'ui.patron.edit.au.other_phone.example',
+ 'ui.patron.edit.phone.regex',
+ 'ui.patron.edit.phone.example',
+ 'ui.patron.edit.au.active.show',
+ 'ui.patron.edit.au.active.suggest',
+ 'ui.patron.edit.au.barred.show',
+ 'ui.patron.edit.au.barred.suggest',
+ 'ui.patron.edit.au.master_account.show',
+ 'ui.patron.edit.au.master_account.suggest',
+ 'ui.patron.edit.au.claims_returned_count.show',
+ 'ui.patron.edit.au.claims_returned_count.suggest',
+ 'ui.patron.edit.au.claims_never_checked_out_count.show',
+ 'ui.patron.edit.au.claims_never_checked_out_count.suggest',
+ 'ui.patron.edit.au.alert_message.show',
+ 'ui.patron.edit.au.alert_message.suggest',
+ 'ui.patron.edit.aua.post_code.regex',
+ 'ui.patron.edit.aua.post_code.example',
+ 'ui.patron.edit.aua.county.require',
+ 'ui.patron.edit.au.guardian.show',
+ 'ui.patron.edit.au.guardian.suggest',
+ 'ui.patron.edit.guardian_required_for_juv',
+ 'format.date',
+ 'ui.patron.edit.default_suggested',
+ 'opac.barcode_regex',
+ 'opac.username_regex',
+ 'sms.enable',
+ 'ui.patron.edit.aua.state.require',
+ 'ui.patron.edit.aua.state.suggest',
+ 'ui.patron.edit.aua.state.show',
+ 'ui.admin.work_log.max_entries',
+ 'ui.admin.patron_log.max_entries'
]).then(settings => {
+ this.context.settingsCache = settings;
this.context.noTallyClaimsReturned =
settings['circ.do_not_tally_claims_returned'];
this.context.tallyLost = settings['circ.tally_lost'];
<div class="row mb-1 alert alert-danger p-0"
*ngFor="let pen of context.alerts.alertPenalties">
<div class="col-lg-9"
- title="{{pen.standing_penalty().name()">
+ title="{{pen.standing_penalty().name()}}">
{{pen.note() || pen.standing_penalty().label()}}
</div>
<div class="col-lg-3">{{pen.set_date() | date:'shortDate'}}</div>