From: Bill Erickson Date: Thu, 14 Nov 2019 21:54:21 +0000 (-0500) Subject: LPXXX MARC enriched editor WIP X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=06c9749bc343b70ed858bc2d47958890e68c7835;p=working%2FEvergreen.git LPXXX MARC enriched editor WIP Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts new file mode 100644 index 0000000000..88447fd3e2 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts @@ -0,0 +1,25 @@ +import {EventEmitter} from '@angular/core'; +import {MarcRecord} from './marcrecord'; + +export class MarcEditContext { + + recordChange: EventEmitter; + + private _record: MarcRecord; + set record(r: MarcRecord) { + if (r !== this._record) { + this._record = r; + this.recordChange.emit(r); + } + } + + get record(): MarcRecord { + return this._record; + } + + constructor() { + this.recordChange = new EventEmitter(); + } + +} + diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.html index 55c5af69ea..be6845583b 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.html @@ -43,25 +43,12 @@ -
- Enhanced MARC Editor is not yet implemented. See the - - - AngularJS MARC Editor. - - - - - AngularJS MARC Editor. - - -
+
- +
diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.ts index e25734f35c..a4d466e1a8 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.ts @@ -11,6 +11,7 @@ import {MarcRecord} from './marcrecord'; import {ComboboxEntry, ComboboxComponent } from '@eg/share/combobox/combobox.component'; import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; +import {MarcEditContext} from './editor-context'; interface MarcSavedEvent { marcXml: string; @@ -28,9 +29,9 @@ interface MarcSavedEvent { export class MarcEditorComponent implements OnInit { - record: MarcRecord; editorTab: 'rich' | 'flat'; sources: ComboboxEntry[]; + context: MarcEditContext; @Input() set recordId(id: number) { if (!id) { return; } @@ -39,7 +40,13 @@ export class MarcEditorComponent implements OnInit { } @Input() set recordXml(xml: string) { - if (xml) { this.fromXml(xml); } + if (xml) { + this.fromXml(xml); + } + } + + get record(): MarcRecord { + return this.context.record; } // Tell us which record source to select by default. @@ -56,6 +63,9 @@ export class MarcEditorComponent implements OnInit { // the record is successfully saved. @Output() recordSaved: EventEmitter; + // Fired when our underlying source record changes. + recordChange: EventEmitter; + @ViewChild('sourceSelector', { static: true }) sourceSelector: ComboboxComponent; @ViewChild('confirmDelete', { static: true }) confirmDelete: ConfirmDialogComponent; @ViewChild('confirmUndelete', { static: true }) confirmUndelete: ConfirmDialogComponent; @@ -74,11 +84,12 @@ export class MarcEditorComponent implements OnInit { ) { this.sources = []; this.recordSaved = new EventEmitter(); + this.context = new MarcEditContext(); } ngOnInit() { // Default to flat for now since it's all that's supported. - this.editorTab = 'flat'; + //this.editorTab = 'flat'; this.pcrud.retrieveAll('cbs').subscribe( src => this.sources.push({id: +src.id(), label: src.source()}), @@ -140,7 +151,7 @@ export class MarcEditorComponent implements OnInit { fromId(id: number): Promise { return this.pcrud.retrieve('bre', id) .toPromise().then(bib => { - this.record = new MarcRecord(bib.marc()); + this.context.record = new MarcRecord(bib.marc()); this.record.id = id; this.record.deleted = bib.deleted() === 't'; if (bib.source()) { @@ -150,7 +161,7 @@ export class MarcEditorComponent implements OnInit { } fromXml(xml: string) { - this.record = new MarcRecord(xml); + this.context.record = new MarcRecord(xml); this.record.id = null; } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.html new file mode 100644 index 0000000000..f8086a0888 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.html @@ -0,0 +1,9 @@ + + +
+ + +
+
+ diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.ts new file mode 100644 index 0000000000..a7c4f9003a --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.ts @@ -0,0 +1,61 @@ +import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter, + OnDestroy} from '@angular/core'; +import {MarcRecord} from './marcrecord'; +import {MarcEditContext} from './editor-context'; +import {TagTableService} from './tagtable.service'; + +/** + * MARC Fixed Field Editing Component + */ + +@Component({ + selector: 'eg-fixed-field', + templateUrl: './fixed-field.component.html' +}) + +export class FixedFieldComponent implements OnInit { + + @Input() fieldCode: string; + @Input() fieldLabel: string; + @Input() context: MarcEditContext; + + get record(): MarcRecord { return this.context.record; } + + fieldValue: string; + fieldMeta: any; + fieldSize = 4; + + constructor( + private tagTable: TagTableService + ) {} + + ngOnInit() { + this.init().then(_ => + this.context.recordChange.subscribe(_ => this.init())); + } + + init(): Promise { + if (!this.record) { return Promise.resolve(); } + + this.tagTable.getFFPosTable(this.record.recordType()) + .then(table => { + + // Note the AngJS MARC editor stores the full POS table + // for all record types in every copy of the table, hence + // the seemingly extraneous check in recordType. + this.fieldMeta = table.filter( + field => field.fixed_field === this.fieldCode + && field.rec_type === this.record.recordType())[0]; + + if (!this.fieldMeta) { + // Not all record types have all field types. + return; + } + + this.fieldSize = this.fieldMeta.length; + this.fieldValue = + this.context.record.extractFixedField(this.fieldCode); + }); + } +} + diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.html new file mode 100644 index 0000000000..e95df99dd3 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.html @@ -0,0 +1,18 @@ + +
+
+ +
+
+
+
+ +
+
+ + + diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.ts new file mode 100644 index 0000000000..d02981606b --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-fields-editor.component.ts @@ -0,0 +1,31 @@ +import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter, + OnDestroy} from '@angular/core'; +import {IdlService} from '@eg/core/idl.service'; +import {OrgService} from '@eg/core/org.service'; +import {MarcRecord} from './marcrecord'; +import {MarcEditContext} from './editor-context'; +import {TagTableService} from './tagtable.service'; + +/** + * MARC Fixed Fields Editor Component + */ + +@Component({ + selector: 'eg-fixed-fields-editor', + templateUrl: './fixed-fields-editor.component.html' +}) + +export class FixedFieldsEditorComponent implements OnInit { + + @Input() context: MarcEditContext; + get record(): MarcRecord { return this.context.record; } + + constructor( + private idl: IdlService, + private org: OrgService, + private tagTable: TagTableService + ) {} + + ngOnInit() {} +} + diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/flat-editor.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/flat-editor.component.ts index b5e2f41277..3c3da2a8c1 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/flat-editor.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/flat-editor.component.ts @@ -1,9 +1,9 @@ -import {Component, Input, OnInit, Host} from '@angular/core'; +import {Component, Input, OnInit} from '@angular/core'; import {IdlService} from '@eg/core/idl.service'; import {OrgService} from '@eg/core/org.service'; import {ServerStoreService} from '@eg/core/server-store.service'; -import {MarcEditorComponent} from './editor.component'; import {MarcRecord} from './marcrecord'; +import {MarcEditContext} from './editor-context'; /** * MARC Record flat text (marc-breaker) editor. @@ -17,17 +17,16 @@ import {MarcRecord} from './marcrecord'; export class MarcFlatEditorComponent implements OnInit { + @Input() context: MarcEditContext; get record(): MarcRecord { - return this.editor.record; + return this.context.record; } constructor( private idl: IdlService, private org: OrgService, - private store: ServerStoreService, - @Host() private editor: MarcEditorComponent - ) { - } + private store: ServerStoreService + ) {} ngOnInit() {} diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marc-edit.module.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marc-edit.module.ts index a18eb0b7a4..c17ef22ed0 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marc-edit.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marc-edit.module.ts @@ -3,12 +3,17 @@ import {StaffCommonModule} from '@eg/staff/common.module'; import {MarcEditorComponent} from './editor.component'; import {MarcRichEditorComponent} from './rich-editor.component'; import {MarcFlatEditorComponent} from './flat-editor.component'; +import {FixedFieldsEditorComponent} from './fixed-fields-editor.component'; +import {FixedFieldComponent} from './fixed-field.component'; +import {TagTableService} from './tagtable.service'; @NgModule({ declarations: [ MarcEditorComponent, MarcRichEditorComponent, - MarcFlatEditorComponent + MarcFlatEditorComponent, + FixedFieldsEditorComponent, + FixedFieldComponent ], imports: [ StaffCommonModule @@ -17,6 +22,7 @@ import {MarcFlatEditorComponent} from './flat-editor.component'; MarcEditorComponent ], providers: [ + TagTableService ] }) diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts index df1a492762..da41ba4397 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts @@ -27,9 +27,17 @@ export class MarcRecord { return this.record.toBreaker(); } + recordType(): string { + return this.record.recordType(); + } + absorbBreakerChanges() { this.record = new MARC21.Record( {marcbreaker: this.breakerText, delimiter: DELIMITER}); } + + extractFixedField(fixedFieldCode: string): string { + return this.record.extractFixedField(fixedFieldCode); + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html index e69de29bb2..e87706e623 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html @@ -0,0 +1,9 @@ + +
+
+
+ +
+
+
+ diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts index 7f8ac334e3..9e5528a94e 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.ts @@ -2,6 +2,10 @@ import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter, OnDestroy} from '@angular/core'; import {IdlService} from '@eg/core/idl.service'; import {OrgService} from '@eg/core/org.service'; +import {TagTableService} from './tagtable.service'; +import {MarcRecord} from './marcrecord'; +import {MarcEditContext} from './editor-context'; + /** * MARC Record rich editor interface. @@ -15,13 +19,28 @@ import {OrgService} from '@eg/core/org.service'; export class MarcRichEditorComponent implements OnInit { + @Input() context: MarcEditContext; + get record(): MarcRecord { return this.context.record; } + constructor( private idl: IdlService, - private org: OrgService - ) { + private org: OrgService, + private tagTable: TagTableService + ) {} + + ngOnInit() { + this.init().then(_ => + this.context.recordChange.subscribe(_ => this.init())); } - ngOnInit() {} + init(): Promise { + if (!this.record) { return Promise.resolve(); } + + return Promise.all([ + this.tagTable.getFFPosTable(this.record.recordType()), + this.tagTable.getFFValueTable(this.record.recordType()) + ]); + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/tagtable.service.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/tagtable.service.ts new file mode 100644 index 0000000000..956255d237 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/tagtable.service.ts @@ -0,0 +1,86 @@ +import {Injectable, EventEmitter} from '@angular/core'; +import {map} from 'rxjs/operators'; +import {StoreService} from '@eg/core/store.service'; +import {AuthService} from '@eg/core/auth.service'; +import {NetService} from '@eg/core/net.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {EventService} from '@eg/core/event.service'; + + +@Injectable() +export class TagTableService { + + ffPosMap: {[rtype: string]: any[]} = {}; + ffValueMap: {[rtype: string]: any} = {}; + promiseCache: {[ptype: string]: Promise} = {}; + + constructor( + private store: StoreService, + private auth: AuthService, + private net: NetService, + private pcrud: PcrudService, + private evt: EventService + ) {} + + getFFPosTable(rtype: string): Promise { + const storeKey = 'FFPosTable_' + rtype; + + if (this.ffPosMap[rtype]) { + return Promise.resolve(this.ffPosMap[rtype]); + } + + this.ffPosMap[rtype] = this.store.getLocalItem(storeKey); + + if (this.ffPosMap[rtype]) { + return Promise.resolve(this.ffPosMap[rtype]); + } + + if (this.promiseCache[storeKey]) { + return this.promiseCache[storeKey]; + } + + this.promiseCache[storeKey] = this.net.request( + 'open-ils.fielder', 'open-ils.fielder.cmfpm.atomic', + {query: {tag: {'!=' : '006'}, rec_type: rtype}} + ).toPromise().then(table => { + + this.store.setLocalItem(storeKey, table); + delete this.promiseCache[storeKey]; + return this.ffPosMap[rtype] = table; + }); + + return this.promiseCache[storeKey]; + } + + getFFValueTable(rtype: string): Promise { + + const storeKey = 'FFValueTable_' + rtype; + + if (this.ffValueMap[rtype]) { + return Promise.resolve(this.ffValueMap[rtype]); + } + + this.ffValueMap[rtype] = this.store.getLocalItem(storeKey); + + if (this.ffValueMap[rtype]) { + return Promise.resolve(this.ffValueMap[rtype]); + } + + if (this.promiseCache[storeKey]) { + return this.promiseCache[storeKey]; + } + + this.promiseCache[storeKey] = this.net.request( + 'open-ils.cat', + 'open-ils.cat.biblio.fixed_field_values.by_rec_type', rtype + ).toPromise().then(table => { + delete this.promiseCache[storeKey]; + this.store.setLocalItem(storeKey, table); + return this.ffValueMap[rtype] = table; + }); + + return this.promiseCache[storeKey]; + } +} + +