class="form-control"
name="{{getClass(args.cls)}}-{{args.field}}-input"
id="{{getClass(args.cls)}}-{{args.field}}-input"
- [ngModel]="objectFromPath(args.path)[args.field]()"
- (ngModelChange)="fieldValueChange(args.path, args.field, $event)"
- (change)="afterFieldChange(args.path, args.field)"
+ [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)"
[disabled]="args.disabled"
class="form-check-input ml-0"
name="{{getClass(args.cls)}}-{{args.field}}-input"
id="{{getClass(args.cls)}}-{{args.field}}-input"
- [ngModel]="objectFromPath(args.path)[args.field]() == 't'"
- (ngModelChange)="fieldValueChange(args.path, args.field, $event)"
- (change)="afterFieldChange(args.path, args.field)"
+ [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)"
[disabled]="disabled"
<eg-combobox [entries]="args.entries"
name="{{getClass(args.cls)}}-{{args.field}}-input"
domId="{{getClass(args.cls)}}-{{args.field}}-input"
- [selectedId]="getFieldValue(args.path, args.field)"
+ [selectedId]="getFieldValue(args.path, args.index, args.field)"
(onChange)="
- fieldValueChange(args.path, args.field, $event ? $event.id : null);
- afterFieldChange(args.path, args.field)"
+ 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)"
[disabled]="args.disabled">
</eg-combobox>
class="form-control"
name="au-name_keywords-input"
id="au-name_keywords-input"
- [ngModel]="objectFromPath(null)['name_keywords']()"
- (ngModelChange)="fieldValueChange(null, 'name_keywords', $event)"
- (change)="afterFieldChange(null, 'name_keywords')"
+ [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')">
</textarea>
[noMaxWidth]="true"
[initialIso]="patron.dob()"
(onChangeAsIso)="
- fieldValueChange(null, 'dob', $event);
- afterFieldChange(null, 'dob')"
+ fieldValueChange(null, null, 'dob', $event);
+ afterFieldChange(null, null, 'dob')"
[required]="fieldRequired('au', 'dob')">
</eg-date-select>
</div>
[initialOrgId]="patron.home_ou()"
[disableOrgs]="cannotHaveUsersOrgs()"
(onChange)="
- fieldValueChange(null, 'home_ou', $event ? $event.id() : null);
- afterFieldChange(null, 'home_ou')">
+ fieldValueChange(null, null, 'home_ou', $event ? $event.id() : null);
+ afterFieldChange(null, null, 'home_ou')">
</eg-org-select>
</div>
</div>
[useDisplayEntries]="true"
[initialGroupId]="patron.profile()"
(profileChange)="
- fieldValueChange(null, 'profile', $event ? $event.id() : null);
- afterFieldChange(null, 'profile')">
+ fieldValueChange(null, null, 'profile', $event ? $event.id() : null);
+ afterFieldChange(null, null, 'profile')">
</eg-profile-select>
</div>
<div class="col-lg-6">
class="form-control"
name="au-alert_message-input"
id="au-alert_message-input"
- [ngModel]="objectFromPath(null)['alert_message']()"
- (ngModelChange)="fieldValueChange(null, 'alert_message', $event)"
- (change)="afterFieldChange(null, 'alert_message')"
+ [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')">
</textarea>
</div>
</ng-container>
+ <ng-container *ngFor="let addr of patron.addresses(); let index = index">
+ <div class="alert alert-success p-2 m-3 d-flex">
+ <div class="col-lg-3" i18n>Address</div>
+ <div class="col-lg-9">
+ <div class="form-check form-check-inline mr-2">
+ <input class="form-check-input" type="checkbox"
+ name="addr-{{addr.id()}}-mailing" id="addr-{{addr.id()}}-mailing"
+ [ngModel]="addr.id() == patron.mailing_address().id()"
+ (ngModelChange)="setAddrType('mailing', addr, $event)"/>
+ <label class="form-check-label"
+ for="addr-{{addr.id()}}-mailing" i18n>Mailing</label>
+ </div>
+ <div class="form-check form-check-inline mr-2">
+ <input class="form-check-input" type="checkbox"
+ name="addr-{{addr.id()}}-billing" id="addr-{{addr.id()}}-billing"
+ [ngModel]="addr.id() == patron.billing_address().id()"
+ (ngModelChange)="setAddrType('billing', addr, $event)"/>
+ <label class="form-check-label"
+ for="addr-{{addr.id()}}-billing" i18n>Physical</label>
+ </div>
+ <button class="btn btn-danger" (click)="deleteAddr(addr)" i18n>Delete</button>
+ </div>
+ </div>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'address_type', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'post_code', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'street1', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'street2', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'city', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'county', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'state', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldInput, field: 'country', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldCheckbox, field: 'valid', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ <ng-container *ngTemplateOutlet="fieldRow; context: {args: {template:
+ fieldCheckbox, field: 'within_city_limits', cls: 'aua', path: 'addresses', index: index}}">
+ </ng-container>
+ </ng-container>
- <div class="alert alert-success p-2 m-3" i18n>Addresses</div>
+ <button class="btn btn-success" (click)="newAddr()" i18n>New Address</button>
</div>
this.patron = patron;
}
- objectFromPath(path: string): IdlObject {
- return path ? this.patron[path]() : this.patron;
+ objectFromPath(path: string, index: number): IdlObject {
+ const base = path ? this.patron[path]() : this.patron;
+ if (index === null || index === undefined) {
+ return base;
+ } else {
+ // Some paths lead to an array of objects.
+ return base[index];
+ }
}
getFieldLabel(idlClass: string, field: string, override?: string): string {
return cls || 'au';
}
- getFieldValue(path: string, field: string): any {
- return this.objectFromPath(path)[field]();
+ getFieldValue(path: string, index: number, field: string): any {
+ return this.objectFromPath(path, index)[field]();
}
userSettingChange(name: string, value: any) {
// Called as the model changes.
// This may be called many times before the final value is applied,
// so avoid any heavy lifting here. See afterFieldChange();
- fieldValueChange(path: string, field: string, value: any) {
+ fieldValueChange(path: string, index: number, field: string, value: any) {
if (typeof value === 'boolean') { value = value ? 't' : 'f'; }
// This can be called in cases where components fire up, even
// though the actual value on the patron has not changed.
// Exit early in that case so we don't mark the form as dirty.
- const oldValue = this.getFieldValue(path, field);
+ const oldValue = this.getFieldValue(path, index, field);
if (oldValue === value) { return; }
this.changeHandlerNeeded = true;
- this.objectFromPath(path)[field](value);
+ this.objectFromPath(path, index)[field](value);
}
// Called after a change operation has completed (e.g. on blur)
- afterFieldChange(path: string, field: string) {
+ afterFieldChange(path: string, index: number, field: string) {
if (!this.changeHandlerNeeded) { return; } // no changes applied
this.changeHandlerNeeded = false;
// TODO: set dirty
- const obj = path ? this.patron[path]() : this.patron;
- const value = obj[field]();
+ const value = this.getFieldValue(path, index, field);
console.debug(
`Modifying field path=${path || ''} field=${field} value=${value}`);
}
generatePassword() {
- this.fieldValueChange(null,
+ this.fieldValueChange(null, null,
'passwd', Math.floor(Math.random() * 9000) + 1000);
// Normally this is called on (blur), but the input is not
// focused when using the generate button.
- this.afterFieldChange(null, 'passwd');
+ this.afterFieldChange(null, null, 'passwd');
}
const nowEpoch = new Date().getTime();
const newDate = new Date(nowEpoch + (seconds * 1000 /* millis */));
this.expireDate = newDate;
- this.fieldValueChange(null, 'profile', newDate.toISOString());
- this.afterFieldChange(null, 'profile');
+ this.fieldValueChange(null, null, 'profile', newDate.toISOString());
+ this.afterFieldChange(null, null, 'profile');
}
handleBoolResponse(success: boolean,
).toPromise().then(resp => {
if (Number(resp) === 1) {
-
return this.handleBoolResponse(
true, 'circ.patron.edit.grplink.success');
} else {
-
return this.handleBoolResponse(
false, 'circ.patron.edit.grplink.fail',
'Failed to change group links: ' + resp);
}
});
}
+
+ // Set the mailing or billing address
+ setAddrType(addrType: string, addr: IdlObject, selected: boolean) {
+ if (selected) {
+ this.patron[addrType + '_address'](addr);
+ } else {
+ // Unchecking mailing/billing means we have to randomly
+ // select another address to fill that role. Select the
+ // first address in the list (that does not match the
+ // modifed address)
+ this.patron.addresses().some(a => {
+ if (a.id() !== addr.id()) {
+ this.patron[addrType + '_address'](a);
+ return true;
+ }
+ });
+ }
+ }
+
+ deleteAddr(addr: IdlObject) {
+ }
+
+ newAddr() {
+ const addr = this.idl.create('aua');
+ addr.isnew(true);
+ addr.valid('t');
+ this.patron.addresses().push(addr);
+ }
}
+