From 8ad2827adfa78c9484e73fb2df027d592edcb13f Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 24 Mar 2021 15:36:18 -0400 Subject: [PATCH] LP1904036 field visibility Signed-off-by: Bill Erickson Signed-off-by: Jane Sandberg Signed-off-by: Galen Charlton --- .../staff/circ/patron/edit-toolbar.component.html | 12 +- .../staff/circ/patron/edit-toolbar.component.ts | 9 +- .../src/app/staff/circ/patron/edit.component.html | 152 ++++++++++++--------- .../src/app/staff/circ/patron/edit.component.ts | 129 ++++++++++++++--- .../src/app/staff/circ/patron/patron.service.ts | 14 +- .../src/app/staff/circ/patron/resolver.service.ts | 85 +++++++++++- .../app/staff/circ/patron/summary.component.html | 2 +- 7 files changed, 297 insertions(+), 106 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.html b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.html index 222e4d01fb..7b6d74bf4b 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.html +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.html @@ -3,14 +3,14 @@
Show: + [disabled]="context.editorFieldVisibilityLevel == 2" + (click)="changeFields(2)" i18n>Required Fields + [disabled]="context.editorFieldVisibilityLevel == 1" + (click)="changeFields(1)" i18n>Suggested Fields + [disabled]="context.editorFieldVisibilityLevel == 0" + (click)="changeFields(0)" i18n>All Fields
diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.ts index 0c6d9df0db..9a686608d4 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit-toolbar.component.ts @@ -4,7 +4,7 @@ import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap'; 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', @@ -12,8 +12,6 @@ import {PatronContextService, EditorFieldOptions} from './patron.service'; }) export class EditToolbarComponent implements OnInit { - showFields: EditorFieldOptions = 'all'; - constructor( private org: OrgService, private net: NetService, @@ -24,9 +22,8 @@ export class EditToolbarComponent implements OnInit { ngOnInit() { } - changeFields(field: EditorFieldOptions) { - this.showFields = field; - this.context.showFieldsChanged.emit(field); + changeFields(v: FieldVisibilityLevel) { + this.context.editorFieldVisibilityLevel = v; } } diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.html b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.html index 3952ddac3f..fa6d555754 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.html +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.html @@ -49,8 +49,8 @@ [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" />
@@ -67,8 +67,8 @@ [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" /> @@ -84,7 +84,7 @@ (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"> @@ -137,7 +137,7 @@ -
+
@@ -148,11 +148,25 @@ -
- - +
+ +
+ + + + +
+ + +
+
+ @@ -220,7 +234,7 @@
-
+
@@ -232,8 +246,8 @@ [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')">
@@ -244,7 +258,7 @@ {args: {template: fieldInput, field: 'alias', overrideLabel: holdAliasString.text}}"> -
+
@@ -257,7 +271,7 @@ (onChangeAsIso)=" fieldValueChange(null, null, 'dob', $event); afterFieldChange(null, null, 'dob')" - [required]="fieldRequired('au', 'dob')"> + [required]="fieldRequired('au.dob')">
@@ -303,7 +317,7 @@
+ *ngIf="userSettingTypes['circ.send_email_checkout_receipts'] && showField('au.email')"> @@ -331,7 +345,7 @@ {args: {template: fieldInput, field: 'other_phone'}}"> -
+
@@ -348,7 +362,7 @@
-
+
@@ -368,7 +382,7 @@
-
+
@@ -377,7 +391,7 @@ domId="au-expire_date-input" fieldName="au-expire_date-input" [noMaxWidth]="true" - [required]="fieldRequired('au', 'expire_date')" + [required]="fieldRequired('au.expire_date')" [(ngModel)]="expireDate">
@@ -406,7 +420,7 @@ {args: {template: fieldInput, field: 'claims_never_checked_out_count', type: 'number'}}"> -
+
@@ -418,8 +432,8 @@ [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')">
@@ -432,7 +446,7 @@ {args: {settingName: 'opac.default_phone'}}"> -
+
@@ -454,24 +468,25 @@
-
-
-
- +
- +
New Address -
-
Statistical Categories
-
+ +
+
Statistical Categories
+
-
-
- -
-
- - -
-
+
+
+ +
+
+ + +
+
+
-
-
Surveys
-
-
-
{{survey.name()}}
-
-
-
- -
-
- - + +
+
Surveys
+
+
+
{{survey.name()}}
+
+
+
+ +
+
+ + +
-
+
diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.ts index ee0676de99..4b08ab908e 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.ts @@ -8,7 +8,7 @@ import {NetService} from '@eg/core/net.service'; 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'; @@ -29,12 +29,6 @@ const COMMON_USER_SETTING_TYPES = [ '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', @@ -47,6 +41,44 @@ const PERMS_NEEDED = [ '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[]; @@ -79,7 +111,6 @@ export class EditComponent implements OnInit { smsCarriers: ComboboxEntry[]; identTypes: ComboboxEntry[]; inetLevels: ComboboxEntry[]; - orgSettings: {[name: string]: any} = {}; statCats: StatCat[] = []; userStatCats: {[statId: number]: ComboboxEntry} = {}; userSettings: {[name: string]: any} = {}; @@ -87,7 +118,8 @@ export class EditComponent implements OnInit { 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[]}; @@ -119,7 +151,6 @@ export class EditComponent implements OnInit { 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(); } @@ -134,7 +165,6 @@ export class EditComponent implements OnInit { .then(_ => this.setIdentTypes()) .then(_ => this.setInetLevels()) .then(_ => this.setOptInSettings()) - .then(_ => this.setOrgSettings()) .then(_ => this.setSmsCarriers()) .then(_ => this.loading = false); } @@ -167,13 +197,8 @@ export class EditComponent implements OnInit { }); } - setOrgSettings(): Promise { - return this.serverStore.getItemBatch(ORG_SETTING_TYPES) - .then(settings => this.orgSettings = settings); - } - setSmsCarriers(): Promise { - if (!this.orgSettings['sms.enable']) { + if (!this.context.settingsCache['sms.enable']) { return Promise.resolve(); } @@ -326,12 +351,14 @@ export class EditComponent implements OnInit { 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; } @@ -449,18 +476,58 @@ export class EditComponent implements OnInit { } } - 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; } @@ -749,6 +816,24 @@ export class EditComponent implements OnInit { 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() { + } } diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/patron.service.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/patron.service.ts index 7508dc82ac..49be822e76 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/patron.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/patron.service.ts @@ -8,8 +8,11 @@ import {PatronSearch} from '@eg/staff/share/patron/search.component'; 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 @@ -110,14 +113,17 @@ export class PatronContextService { // 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 = new EventEmitter(); saveCloneClicked: EventEmitter = new EventEmitter(); printClicked: EventEmitter = new EventEmitter(); - showFieldsChanged: EventEmitter = - new EventEmitter(); + + editorFieldVisibilityLevel: FieldVisibilityLevel = + FieldVisibilityLevel.ALL_FIELDS; constructor( private store: StoreService, diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts index 90cf9df1c7..a781d55b85 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts @@ -45,8 +45,91 @@ export class PatronResolver implements Resolve> { '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']; diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/summary.component.html b/Open-ILS/src/eg2/src/app/staff/circ/patron/summary.component.html index c2352c65d9..0a523dba64 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/summary.component.html +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/summary.component.html @@ -35,7 +35,7 @@
+ title="{{pen.standing_penalty().name()}}"> {{pen.note() || pen.standing_penalty().label()}}
{{pen.set_date() | date:'shortDate'}}
-- 2.11.0