LP1825851 Print template admin misc. repairs/improvements
authorBill Erickson <berickxx@gmail.com>
Thu, 1 Aug 2019 20:36:31 +0000 (16:36 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Thu, 8 Aug 2019 19:47:31 +0000 (15:47 -0400)
1. When cloning a template, be sure the cloned template is available in
   the template selector regardless of whether it would have been given
   the current filters.

2. When cloning, set the 'active' flag explicitly to false so the user
   is forced to manually activate.  This prevent unintentional
   activation on in-process templtes.

3. When cloning, clear the owner value so the user is forced to select
   an owner value.

4. Allow the template editor textaread to expand vertically as the
   template gets longer (i.e. adds more new lines).

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/print-template.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/print-template.component.ts

index 67d73e9..2664112 100644 (file)
@@ -3,7 +3,7 @@
  *  <!-- see also <eg-combobox-entry> -->
  * </eg-combobox>
  */
  *  <!-- see also <eg-combobox-entry> -->
  * </eg-combobox>
  */
-import {Component, OnInit, Input, Output, ViewChild, 
+import {Component, OnInit, Input, Output, ViewChild,
     TemplateRef, EventEmitter, ElementRef, forwardRef} from '@angular/core';
 import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {Observable, of, Subject} from 'rxjs';
     TemplateRef, EventEmitter, ElementRef, forwardRef} from '@angular/core';
 import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {Observable, of, Subject} from 'rxjs';
@@ -210,6 +210,10 @@ export class ComboboxComponent implements ControlValueAccessor, OnInit {
         }
     }
 
         }
     }
 
+    hasEntry(entryId: any): boolean {
+        return this.entrylist.filter(e => e.id === entryId)[0] !== undefined;
+    }
+
     onBlur() {
         // When the selected value is a string it means we have either
         // no value (user cleared the input) or a free-text value.
     onBlur() {
         // When the selected value is a string it means we have either
         // no value (user cleared the input) or a free-text value.
index 585a7af..1293bc1 100644 (file)
@@ -81,7 +81,7 @@
               (Inactive)
             </span>
           </h4>
               (Inactive)
             </span>
           </h4>
-         <textarea rows="30" class="form-control"
+         <textarea rows="{{templateRowCount()}}" class="form-control"
            spellcheck="false"
            [ngModel]="template.template()"
            (ngModelChange)="template.template($event); template.ischanged(true)">
            spellcheck="false"
            [ngModel]="template.template()"
            (ngModelChange)="template.template($event); template.ischanged(true)">
index f57df1e..782efb4 100644 (file)
@@ -175,10 +175,17 @@ export class PrintTemplateComponent implements OnInit {
     }
 
     getOwnerName(id: number): string {
     }
 
     getOwnerName(id: number): string {
-        return this.org.get(this.templateCache[id].owner()).shortname();
+        if (this.templateCache[id]) {
+            return this.org.get(this.templateCache[id].owner()).shortname();
+        }
+        return '';
     }
 
     }
 
-    selectTemplate(id: number) {
+    // If the selected template changes through means other than the
+    // template selecdtor, setting updateSelector=true will force the
+    // template to appear in the selector and get selected, regardless
+    // of whether it would have been fetched with current filters.
+    selectTemplate(id: number, updateSelector?: boolean) {
 
         if (id === null) {
             this.template = null;
 
         if (id === null) {
             this.template = null;
@@ -187,7 +194,15 @@ export class PrintTemplateComponent implements OnInit {
         }
 
         this.pcrud.retrieve('cpt', id).subscribe(t => {
         }
 
         this.pcrud.retrieve('cpt', id).subscribe(t => {
-            this.template = t;
+            this.template = this.templateCache[id] = t;
+
+            if (updateSelector) {
+                if (!this.templateSelector.hasEntry(id)) {
+                    this.templateSelector.addEntry({id: id, label: t.label()});
+                }
+                this.templateSelector.applyEntryId(id);
+            }
+
             const data = this.sampleData[t.name()];
             if (data) {
                 this.sampleJson = JSON.stringify(data, null, 2);
             const data = this.sampleData[t.name()];
             if (data) {
                 this.sampleJson = JSON.stringify(data, null, 2);
@@ -196,6 +211,17 @@ export class PrintTemplateComponent implements OnInit {
         });
     }
 
         });
     }
 
+    // Allow the template editor textarea to expand vertically as
+    // content is added, with a sane minimum row count
+    templateRowCount(): number {
+        const def = 25;
+        if (this.template && this.template.template()) {
+            return Math.max(def,
+                this.template.template().split(/\n/).length + 2);
+        }
+        return def;
+    }
+
     refreshPreview() {
         if (!this.sampleJson) { return; }
         this.compiledContent = '';
     refreshPreview() {
         if (!this.sampleJson) { return; }
         this.compiledContent = '';
@@ -216,11 +242,13 @@ export class PrintTemplateComponent implements OnInit {
         }).then(response => {
 
             this.compiledContent = response.content;
         }).then(response => {
 
             this.compiledContent = response.content;
-            if (response.contentType === 'text/html') {
-                this.container().innerHTML = response.content;
-            } else {
-                // Assumes text/plain or similar
-                this.container().innerHTML = '<pre>' + response.content + '</pre>';
+            if (this.container()) { // null if on alternate tab
+                if (response.contentType === 'text/html') {
+                    this.container().innerHTML = response.content;
+                } else {
+                    // Assumes text/plain or similar
+                    this.container().innerHTML = '<pre>' + response.content + '</pre>';
+                }
             }
         });
     }
             }
         });
     }
@@ -247,12 +275,14 @@ export class PrintTemplateComponent implements OnInit {
     cloneTemplate() {
         const tmpl = this.idl.clone(this.template);
         tmpl.id(null);
     cloneTemplate() {
         const tmpl = this.idl.clone(this.template);
         tmpl.id(null);
+        tmpl.active(false); // Cloning requires manual activation
+        tmpl.owner(null);
         this.editDialog.setRecord(tmpl);
         this.editDialog.mode = 'create';
         this.editDialog.open({size: 'lg'}).toPromise().then(newTmpl => {
             if (newTmpl !== undefined) {
                 this.setTemplateInfo().toPromise()
         this.editDialog.setRecord(tmpl);
         this.editDialog.mode = 'create';
         this.editDialog.open({size: 'lg'}).toPromise().then(newTmpl => {
             if (newTmpl !== undefined) {
                 this.setTemplateInfo().toPromise()
-                    .then(_ => this.selectTemplate(newTmpl.id()));
+                    .then(_ => this.selectTemplate(newTmpl.id(), true));
             }
         });
     }
             }
         });
     }