LPXXX marc edit continued
authorBill Erickson <berickxx@gmail.com>
Fri, 6 Dec 2019 21:47:02 +0000 (16:47 -0500)
committerBill Erickson <berickxx@gmail.com>
Fri, 6 Dec 2019 21:47:02 +0000 (16:47 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/share/marc-edit/editable-content.component.ts
Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor-context.ts
Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.ts
Open-ILS/src/eg2/src/app/staff/share/marc-edit/fixed-field.component.html
Open-ILS/src/eg2/src/app/staff/share/marc-edit/rich-editor.component.html

index c26578b..72d432c 100644 (file)
@@ -47,6 +47,7 @@ export class EditableContentComponent
 
     focusSub: Subscription;
     undoRedoSub: Subscription;
+    isLeader: boolean; // convenience
 
     constructor(
         private renderer: Renderer2,
@@ -74,10 +75,14 @@ export class EditableContentComponent
     }
 
     focusRequestIsMe(req: FieldFocusRequest): boolean {
-        if (!this.field) { return false; } // LDR
-        if (req.fieldId !== this.field.fieldId) { return false; }
         if (req.target !== this.fieldType) { return false; }
 
+        if (this.field) {
+            if (req.fieldId !== this.field.fieldId) { return false; }
+        } else if (req.target === 'ldr') {
+            return this.isLeader;
+        }
+
         if (req.sfOffset !== undefined && 
             req.sfOffset !== this.subfield[2]) {
             // this is not the subfield you are looking for.
@@ -99,7 +104,7 @@ export class EditableContentComponent
             // clicking, etc.  Model the event as a focus request
             // so it can be tracked the same.
             req = {
-                fieldId: this.field.fieldId, 
+                fieldId: this.field ? this.field.fieldId : -1,
                 target: this.fieldType,
                 sfOffset: this.subfield ? this.subfield[2] : undefined
             };
@@ -114,7 +119,10 @@ export class EditableContentComponent
 
         switch (this.fieldType) {
             case 'ldr':
+                this.isLeader = true;
                 if (content) { this.maxLength = content.length; }
+                this.watchForFocusRequests();
+                this.watchForUndoRedoRequests();
                 break;
 
             case 'tag':
@@ -152,7 +160,7 @@ export class EditableContentComponent
     // These are served dynamically to handle cases where a tag or
     // subfield is modified in place.
     contextMenuEntries(): ContextMenuEntry[] {
-        if (!this.field) { return; } // LDR tag
+        if (this.isLeader) { return; }
 
         switch(this.fieldType) {
             case 'tag': 
@@ -297,7 +305,51 @@ export class EditableContentComponent
 
     // Route keydown events to the appropriate handler
     inputKeyDown(evt: KeyboardEvent) {
-        
+
+        switch(evt.key) {
+            case 'y': 
+                if (evt.ctrlKey) { // redo
+                    this.context.requestRedo();
+                    evt.preventDefault();
+                }
+                return;
+
+            case 'z': 
+                if (evt.ctrlKey) { // undo
+                    this.context.requestUndo();
+                    evt.preventDefault();
+                }
+                return;
+
+            case 'F6': 
+                if (evt.shiftKey) {
+                    // shift+F6 => add 006
+                    this.context.add00X('006');
+                    evt.preventDefault();
+                    evt.stopPropagation();
+                }
+                return;
+
+            case 'F7': 
+                if (evt.shiftKey) {
+                    // shift+F7 => add 007
+                    this.context.add00X('007');
+                    evt.preventDefault();
+                    evt.stopPropagation();
+                }
+                return;
+
+            case 'F8': 
+                if (evt.shiftKey) {
+                    // shift+F8 => add/replace 008
+                    this.context.insertReplace008();
+                    evt.preventDefault();
+                    evt.stopPropagation();
+                }
+                return;
+        }
+
+        // None of the remaining key combos are supported by the LDR.
         if (this.fieldType === 'ldr') { return; }
 
         switch (evt.key) {
@@ -357,34 +409,6 @@ export class EditableContentComponent
                 evt.preventDefault();
                 break;
 
-
-            case 'F6': 
-                if (evt.shiftKey) {
-                    // shift+F6 => add 006
-                    this.context.add00X('006');
-                    evt.preventDefault();
-                    evt.stopPropagation();
-                }
-                break;
-
-            case 'F7': 
-                if (evt.shiftKey) {
-                    // shift+F7 => add 007
-                    this.context.add00X('007');
-                    evt.preventDefault();
-                    evt.stopPropagation();
-                }
-                break;
-
-            case 'F8': 
-                if (evt.shiftKey) {
-                    // shift+F8 => add/replace 008
-                    this.context.insertReplace008();
-                    evt.preventDefault();
-                    evt.stopPropagation();
-                }
-                break;
-
             case 'd': // thunk
             case 'i':
                 if (evt.ctrlKey) {
@@ -394,21 +418,6 @@ export class EditableContentComponent
                     evt.preventDefault();
                 }
                 break;
-
-            case 'y': 
-                if (evt.ctrlKey) { // redo
-                    this.context.requestRedo();
-                    evt.preventDefault();
-                }
-                break;
-
-            case 'z': 
-                if (evt.ctrlKey) { // undo
-                    this.context.requestUndo();
-                    evt.preventDefault();
-                }
-                break;
-
         }
     }
 
index 9e097af..4e15a9a 100644 (file)
@@ -42,6 +42,9 @@ export class StructUndoRedoAction extends UndoRedoAction {
     // Position preceding the modified position to mark the position
     // of deletion recovery.
     prevPosition: FieldFocusRequest;
+
+    // Location of the cursor at time of initial action.
+    prevFocus: FieldFocusRequest;
 }
 
 
@@ -79,10 +82,12 @@ export class MarcEditContext {
     requestFieldFocus(req: FieldFocusRequest) {
         // timeout allows for new components to be built before the
         // focus request is emitted.
-        setTimeout(() => {
-            console.log('focusing ', req);
-            this.fieldFocusRequest.emit(req);
-        });
+        setTimeout(() => this.fieldFocusRequest.emit(req));
+    }
+
+    resetUndos() {
+        this.undoStack = [];
+        this.redoStack = [];
     }
 
     requestUndo() {
@@ -117,22 +122,18 @@ export class MarcEditContext {
             // Remove the added field
 
             if (action.subfield) {
-
                 const prevPos = action.subfield[2] - 1;
                 action.field.deleteExactSubfields(action.subfield);
                 this.focusSubfield(action.field, prevPos);
 
             } else {
                 this.record.deleteFields(action.field);
-
-                if (this.lastFocused.fieldId === action.field.fieldId) {
-                    // If the field we are deleting is currently focused,
-                    // move focus to the previous field.  Otherwse, leave
-                    // the focus where it is.
-                    this.requestFieldFocus(action.prevPosition);
-                }
             }
 
+            // When deleting chunks, always return focus to the
+            // pre-insert position.
+            this.requestFieldFocus(action.prevFocus);
+
         } else {
             // Re-insert the removed field and focus it.
             
@@ -156,6 +157,14 @@ export class MarcEditContext {
                 // Focus the newly recovered field.
                 this.requestFieldFocus(action.position);
             }
+
+            // When inserting chunks, track the location where the
+            // insert was requested so we can return the cursor so we
+            // can return the cursor to the scene of the crime if the
+            // undo is re-done or vice versa.  This is primarily useful
+            // when performing global inserts like add00X, which can be
+            // done without the 00X field itself having focus.
+            action.prevFocus = this.lastFocused;
         }
 
         action.wasAddition = !action.wasAddition;
@@ -191,6 +200,10 @@ export class MarcEditContext {
         action.position = position;
         action.prevPosition = prevPos;
 
+        // For bulk adds (e.g. add a whole row) the field focused at
+        // time of action will be different than the added field.
+        action.prevFocus = this.lastFocused;
+
         this.undoStack.unshift(action);
     }
 
index e1c1c2e..4880530 100644 (file)
@@ -113,6 +113,11 @@ export class MarcEditorComponent implements OnInit {
 
     // Remember the last used tab as the preferred tab.
     tabChange(evt: NgbTabChangeEvent) {
+
+        // Avoid undo persistence across tabs since that could result
+        // in changes getting lost.
+        this.context.resetUndos();
+
         if (evt.nextId === 'flat') {
             this.store.setItem('cat.marcedit.flateditor', true);
         } else {
index 52c332b..856e56d 100644 (file)
@@ -10,8 +10,8 @@
     <input 
       [attr.aria-labelledby]="'label-' + randId"
       class="form-control rounded-0 flex-5" type="text" 
-      (change)="valueChange()"
-      [(ngModel)]="fieldValue" 
+      (change)="valueChange($event.target.value)"
+      [ngModel]="fieldValue" 
       [attr.maxlength]="fieldLength" [attr.size]="fieldLength"
       [egContextMenu]="fieldValues"
       (menuItemSelected)="valueChange($event.value)"
index f57bda5..5f32ef6 100644 (file)
@@ -63,7 +63,7 @@
     <!-- LEADER -->
     <div class="row pt-0 pb-0 pl-3 form-horizontal">
       <eg-marc-editable-content [context]="context" fieldType="tag" 
-        fieldText="LDR" i18n-fieldText moreClasses="p-1">
+        fieldText="LDR" i18n-fieldText moreClasses="p-1 pr-2">
       </eg-marc-editable-content>
 
       <eg-marc-editable-content [context]="context" fieldType="ldr"