From 1db81cf40bd5b1f227db9efe3072e6ecbc3bd26c Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 8 Mar 2019 13:16:35 -0500 Subject: [PATCH] LP1819179 PCRUD selector fleshing handles maps Teach the PCUD selector fleshing code to handle selector fields on mapped classes, where an intermediate object flesh is performed by pcrud at flesh time. Adds a 'selector' column on metabib.metarecord in the IDL so that we can have a functioning example of this to use in the sandbox test code. Signed-off-by: Bill Erickson Signed-off-by: Dan Wells --- Open-ILS/examples/fm_IDL.xml | 2 +- .../src/eg2/src/app/core/format.service.ts | 38 ++++++++----------- Open-ILS/src/eg2/src/app/core/idl.service.ts | 11 +++++- .../src/eg2/src/app/core/pcrud.service.ts | 21 +++++++++- .../app/staff/sandbox/sandbox.component.html | 2 + .../app/staff/sandbox/sandbox.component.ts | 16 ++++++++ 6 files changed, 63 insertions(+), 27 deletions(-) diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index db651878bd..1f510735fb 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -3934,7 +3934,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - + diff --git a/Open-ILS/src/eg2/src/app/core/format.service.ts b/Open-ILS/src/eg2/src/app/core/format.service.ts index ad7e9ce180..e788cd0e40 100644 --- a/Open-ILS/src/eg2/src/app/core/format.service.ts +++ b/Open-ILS/src/eg2/src/app/core/format.service.ts @@ -78,37 +78,29 @@ export class FormatService { if (!params.idlClass || !params.idlField) { // Without a full accounting of the field data, - // we can't determine the display value. + // we can't determine the linked selector field. return value + ''; } - const localClass = this.idl.classes[params.idlClass]; + const selector = + this.idl.getLinkSelector(params.idlClass, params.idlField); - if (!localClass) { - console.warn(`No such IDL class ${params.idlClass}`); - return value + ''; - } + if (selector && typeof value[selector] === 'function') { + const val = value[selector](); - if (!localClass.field_map[params.idlField]) { - console.warn(`IDL class ${params.idlClass} ` + - `has no field named "${params.idlField}"`); - return value + ''; - } + if (Array.isArray(val)) { + // Typically has_many links will not be fleshed, + // but in the off-chance the are, avoid displaying + // an array reference value. + return ''; + } else { + return val + ''; + } - const linkType = localClass.field_map[params.idlField]['reltype']; - if (linkType !== 'has_a') { - return value + ''; // eh? + } else { + return value + ''; } - const localField = localClass.field_map[params.idlField]; - const remoteKey = localField['key']; - - const remoteClass = this.idl.classes[localField['class']]; - const remoteField = remoteClass.field_map[remoteKey]; - const remoteSelector = remoteField.selector || remoteField.name; - - return value[remoteSelector]() + ''; - case 'org_unit': const orgField = params.orgField || 'shortname'; const org = this.org.get(value); diff --git a/Open-ILS/src/eg2/src/app/core/idl.service.ts b/Open-ILS/src/eg2/src/app/core/idl.service.ts index b6f8173159..56b8b90e1f 100644 --- a/Open-ILS/src/eg2/src/app/core/idl.service.ts +++ b/Open-ILS/src/eg2/src/app/core/idl.service.ts @@ -138,7 +138,16 @@ export class IdlService { // on the linked class that acts as the selector for the linked class. // Returns null if no selector is found or the field is not a link. getLinkSelector(fmClass: string, field: string): string { - const fieldDef = this.classes[fmClass].field_map[field]; + let fieldDef = this.classes[fmClass].field_map[field]; + + if (fieldDef.map) { + // For mapped fields, we want the selector field on the + // remotely linked object instead of the directly + // linked object. + const linkedClass = this.classes[fieldDef.class]; + fieldDef = linkedClass.field_map[fieldDef.map]; + } + if (fieldDef.class) { const classDef = this.classes[fieldDef.class]; if (classDef.pkey) { diff --git a/Open-ILS/src/eg2/src/app/core/pcrud.service.ts b/Open-ILS/src/eg2/src/app/core/pcrud.service.ts index b3d4288a53..9e14191c0f 100644 --- a/Open-ILS/src/eg2/src/app/core/pcrud.service.ts +++ b/Open-ILS/src/eg2/src/app/core/pcrud.service.ts @@ -104,14 +104,31 @@ export class PcrudContext { } this.idl.classes[fmClass].fields - .filter(f => + .filter(f => f.datatype === 'link' && ( - f.reltype === 'has_a' || f.reltype === 'might_have' + f.reltype === 'has_a' || f.reltype === 'might_have' ) ).forEach(field => { + const selector = this.idl.getLinkSelector(fmClass, field.name); if (!selector) { return; } + if (field.map) { + // For mapped fields, we only want to auto-flesh them + // if both steps along the path are single-row fleshers. + + const mapClass = field['class']; + const mapField = field.map; + const def = this.idl.classes[mapClass].field_map[mapField]; + + if (!(def.reltype === 'has_a' || + def.reltype === 'might_have')) { + // Field maps to a remote field which may contain + // multiple rows. Skip it. + return; + } + } + if (!pcrudOps.flesh_fields[fmClass]) { pcrudOps.flesh_fields[fmClass] = []; } diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html index 00c2ee7397..5f1f1ad0bf 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html @@ -147,4 +147,6 @@

+

PCRUD auto flesh and FormatService detection

+
Fingerprint: {{aMetarecord}}
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts index ed2c496257..4ee4ebc0f7 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts @@ -13,6 +13,7 @@ import {Pager} from '@eg/share/util/pager'; import {DateSelectComponent} from '@eg/share/date-select/date-select.component'; import {PrintService} from '@eg/share/print/print.service'; import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; +import {FormatService} from '@eg/core/format.service'; @Component({ templateUrl: 'sandbox.component.html' @@ -58,12 +59,16 @@ export class SandboxComponent implements OnInit { complimentEvergreen: (rows: IdlObject[]) => void; notOneSelectedRow: (rows: IdlObject[]) => boolean; + // selector field value on metarecord object + aMetarecord: string; + constructor( private idl: IdlService, private org: OrgService, private pcrud: PcrudService, private strings: StringService, private toast: ToastService, + private format: FormatService, private printer: PrintService ) { } @@ -114,6 +119,17 @@ export class SandboxComponent implements OnInit { this.complimentEvergreen = (rows: IdlObject[]) => alert('Evergreen is great!'); this.notOneSelectedRow = (rows: IdlObject[]) => (rows.length !== 1); + + this.pcrud.retrieve('bre', 1, {}, {fleshSelectors: true}) + .subscribe(bib => { + // Format service will automatically find the selector + // value to display from our fleshed metarecord field. + this.aMetarecord = this.format.transform({ + value: bib.metarecord(), + idlClass: 'bre', + idlField: 'metarecord' + }); + }); } btGridRowClassCallback(row: any): string { -- 2.43.2