From ac87df3ce64f68850e86d813b9b7e285196a6375 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 20 Nov 2019 16:04:55 -0500 Subject: [PATCH] LPXXX Copy fields up/down Signed-off-by: Bill Erickson --- .../share/marc-edit/editable-content.component.ts | 34 ++++++++---- .../app/staff/share/marc-edit/editor-context.ts | 2 +- .../src/app/staff/share/marc-edit/marcrecord.ts | 64 +++++++++++++++++++--- .../staff/share/marc-edit/rich-editor.component.ts | 6 +- 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts index af537d109e..2b202dfe6a 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts @@ -1,7 +1,7 @@ import {ElementRef, Component, Input, Output, OnInit, EventEmitter, AfterViewInit, Renderer2} from '@angular/core'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; -import {MarcRecord} from './marcrecord'; +import {MarcRecord, MarcField} from './marcrecord'; import {MarcEditContext} from './editor-context'; /** @@ -17,7 +17,7 @@ import {MarcEditContext} from './editor-context'; export class EditableContentComponent implements OnInit, AfterViewInit { @Input() context: MarcEditContext; - @Input() field: any; // MARC.Field + @Input() field: MarcField; @Input() fieldType: 'ldr' | 'tag' | 'cfld' | 'ind' | 'sfc' | 'sfv' = null; // used when the fieldType is ambiguous. E.g. 'ind1' @@ -27,7 +27,7 @@ export class EditableContentComponent implements OnInit, AfterViewInit { @Input() fieldText: string = null; // array of subfield code and subfield value - @Input() subfield: any; // MARC.Subfield + @Input() subfield: string[]; // [code, value] // space-separated list of additional CSS classes to append @Input() moreClasses: string; @@ -140,10 +140,16 @@ export class EditableContentComponent implements OnInit, AfterViewInit { switch (evt.key) { case 'ArrowDown': - if (evt.ctrlKey) { - // Copy the field down - } else { - // Navigate down one field + + if (evt.ctrlKey) { // Copy field down + + this.context.record.insertFieldsAfter( + this.field, + this.context.record.cloneField(this.field) + ); + + } else { // Jump to next tag + const field = this.record.getNextField(this.field.fieldId); if (field) { this.context.requestFieldFocus(field.fieldId); @@ -153,10 +159,16 @@ export class EditableContentComponent implements OnInit, AfterViewInit { break; case 'ArrowUp': - if (evt.ctrlKey) { - // Copy the field up - } else { - // Navigate upone field + + if (evt.ctrlKey) { // Copy field up + + this.context.record.insertFieldsBefore( + this.field, + this.context.record.cloneField(this.field) + ); + + } else { // Jump to previous tag + const field = this.record.getPreviousField(this.field.fieldId); if (field) { this.context.requestFieldFocus(field.fieldId); 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 index 31705a9b32..990fd793a9 100644 --- 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 @@ -1,5 +1,5 @@ import {EventEmitter} from '@angular/core'; -import {MarcRecord} from './marcrecord'; +import {MarcRecord, MarcField} from './marcrecord'; import {NgbPopover} from '@ng-bootstrap/ng-bootstrap'; /* Per-instance MARC editor context. */ 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 58ec9f1cde..9be812288e 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 @@ -7,6 +7,20 @@ declare var MARC21; // MARC breaker delimiter const DELIMITER = '$'; +// This acts as a veneer over a Marc.Field object. +export interface MarcField { + fieldId?: number; + data?: string; + tag?: string; + ind1?: string; + ind2?: string; + + // [[sfCode, sfValue], [sfCode, sfValue], ...] + subfields?: string[][]; + + isControlfield(): boolean; +} + export class MarcRecord { id: number; // Database ID when known. @@ -26,11 +40,11 @@ export class MarcRecord { this.record.leader = l; } - get fields(): any[] { + get fields(): MarcField[] { return this.record.fields; } - set fields(f: any[]) { + set fields(f: MarcField[]) { this.record.fields = f; } @@ -69,15 +83,30 @@ export class MarcRecord { // Give each field an identifier so it may be referenced later. stampFieldIds() { - this.fields.forEach(f => - f.fieldId = Math.floor(Math.random() * 100000)); + this.fields.forEach(f => { + if (!f.fieldId) { + f.fieldId = Math.floor(Math.random() * 100000) + } + }); + } + + insertFieldsBefore(field: MarcField, ...newFields: MarcField[]) { + this.record.insertFieldsBefore.apply( + this.record, [field].concat(newFields)); + this.stampFieldIds(); + } + + insertFieldsAfter(field: MarcField, ...newFields: MarcField[]) { + this.record.insertFieldsAfter.apply( + this.record, [field].concat(newFields)); + this.stampFieldIds(); } - getField(id: number) { + getField(id: number): MarcField { return this.fields.filter(f => f.fieldId === id)[0]; } - getPreviousField(id: number) { + getPreviousField(id: number): MarcField { for (let idx = 0; idx < this.fields.length; idx++) { if (this.fields[idx].fieldId === id) { return this.fields[idx - 1]; @@ -85,12 +114,33 @@ export class MarcRecord { } } - getNextField(id: number) { + getNextField(id: number): MarcField { for (let idx = 0; idx < this.fields.length; idx++) { if (this.fields[idx].fieldId === id) { return this.fields[idx + 1]; } } } + + cloneField(field: MarcField): MarcField { + const newField: any = {tag: field.tag}; + + if (field.isControlfield()) { + newField.data = field.data; + return new MARC21.Field(newField); + } + + newField.ind1 = field.ind1; + newField.ind2 = field.ind2; + newField.subfields = this.cloneSubfields(field.subfields); + + return new MARC21.Field(newField); + } + + cloneSubfields(subfields: string[][]): string[][] { + const root = []; + subfields.forEach(sf => root.push([].concat(sf))); + return root; + } } 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 7532e6fb54..906a9196c9 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 @@ -3,7 +3,7 @@ import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter, import {IdlService} from '@eg/core/idl.service'; import {OrgService} from '@eg/core/org.service'; import {TagTableService} from './tagtable.service'; -import {MarcRecord} from './marcrecord'; +import {MarcRecord, MarcField} from './marcrecord'; import {MarcEditContext} from './editor-context'; @@ -46,11 +46,11 @@ export class MarcRichEditorComponent implements OnInit { ]).then(_ => this.dataLoaded = true); } - controlFields(): any[] { + controlFields(): MarcField[] { return this.record.fields.filter(f => f.isControlfield()); } - dataFields(): any[] { + dataFields(): MarcField[] { return this.record.fields.filter(f => !f.isControlfield()); } } -- 2.11.0