LP1825851 Server managed/processed print templates
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / fm-editor / fm-editor.component.ts
index 3e41fa2..6c079b8 100644 (file)
@@ -1,4 +1,4 @@
-import {Component, OnInit, Input,
+import {Component, OnInit, Input, ViewChild,
     Output, EventEmitter, TemplateRef} from '@angular/core';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {Observable} from 'rxjs';
@@ -6,8 +6,12 @@ import {map} from 'rxjs/operators';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
-import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {StringComponent} from '@eg/share/string/string.component';
+import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
+
 
 interface CustomFieldTemplate {
     template: TemplateRef<any>;
@@ -18,7 +22,7 @@ interface CustomFieldTemplate {
     context?: {[fields: string]: any};
 }
 
-interface CustomFieldContext {
+export interface CustomFieldContext {
     // Current create/edit/view record
     record: IdlObject;
 
@@ -78,14 +82,9 @@ export class FmRecordEditorComponent
     // IDL class hint (e.g. "aou")
     @Input() idlClass: string;
 
-    // mode: 'create' for creating a new record,
-    //       'update' for editing an existing record
-    //       'view' for viewing an existing record without editing
-    mode: 'create' | 'update' | 'view' = 'create';
     recId: any;
 
     // IDL record we are editing
-    // TODO: allow this to be update in real time by the caller?
     record: IdlObject;
 
     // Permissions extracted from the permacrud defs in the IDL
@@ -121,6 +120,9 @@ export class FmRecordEditorComponent
     // for all combobox fields.  See also FmFieldOptions.
     @Input() preloadLinkedValues: boolean;
 
+    // Display within a modal dialog window or inline in the page.
+    @Input() displayMode: 'dialog' | 'inline' = 'dialog';
+
     // Emit the modified object when the save action completes.
     @Output() onSave$ = new EventEmitter<IdlObject>();
 
@@ -130,6 +132,10 @@ export class FmRecordEditorComponent
     // Emit an error message when the save action fails.
     @Output() onError$ = new EventEmitter<string>();
 
+    @ViewChild('translator') private translator: TranslateComponent;
+    @ViewChild('successStr') successStr: StringComponent;
+    @ViewChild('failStr') failStr: StringComponent;
+
     // IDL info for the the selected IDL class
     idlDef: any;
 
@@ -143,9 +149,10 @@ export class FmRecordEditorComponent
     // DOM id prefix to prevent id collisions.
     idPrefix: string;
 
-    @Input() editMode(mode: 'create' | 'update' | 'view') {
-        this.mode = mode;
-    }
+    // mode: 'create' for creating a new record,
+    //       'update' for editing an existing record
+    //       'view' for viewing an existing record without editing
+    @Input() mode: 'create' | 'update' | 'view' = 'create';
 
     // Record ID to view/update.  Value is dynamic.  Records are not
     // fetched until .open() is called.
@@ -157,6 +164,7 @@ export class FmRecordEditorComponent
       private modal: NgbModal, // required for passing to parent
       private idl: IdlService,
       private auth: AuthService,
+      private toast: ToastService,
       private pcrud: PcrudService) {
       super(modal);
     }
@@ -170,14 +178,23 @@ export class FmRecordEditorComponent
 
         // Add some randomness to the generated DOM IDs to ensure against clobbering
         this.idPrefix = 'fm-editor-' + Math.floor(Math.random() * 100000);
+
+        if (this.isDialog()) {
+            this.onOpen$.subscribe(() => this.initRecord());
+        } else {
+            this.initRecord();
+        }
     }
 
-    // Opening dialog, fetch data.
-    open(options?: NgbModalOptions): Promise<any> {
-        return this.initRecord().then(
-            ok => super.open(options),
-            err => console.warn(`Error fetching FM data: ${err}`)
-        );
+    isDialog(): boolean {
+        return this.displayMode === 'dialog';
+    }
+
+    // Set the record value and clear the recId value to
+    // indicate the record is our current source of data.
+    setRecord(record: IdlObject) {
+        this.record = record;
+        this.recId = null;
     }
 
     // Translate comma-separated string versions of various inputs
@@ -206,9 +223,19 @@ export class FmRecordEditorComponent
             update: pc.update ? pc.update.perms : [],
         };
 
+        this.pkeyIsEditable = !('pkey_sequence' in this.idlDef);
+
         if (this.mode === 'update' || this.mode === 'view') {
-            return this.pcrud.retrieve(this.idlClass, this.recId)
-            .toPromise().then(rec => {
+
+            let promise;
+            if (this.record && this.recId === null) {
+                promise = Promise.resolve(this.record);
+            } else {
+                promise =
+                    this.pcrud.retrieve(this.idlClass, this.recId).toPromise();
+            }
+
+            return promise.then(rec => {
 
                 if (!rec) {
                     return Promise.reject(`No '${this.idlClass}'
@@ -221,12 +248,12 @@ export class FmRecordEditorComponent
             });
         }
 
-        // create a new record from scratch or from a stub record
-        // provided by the caller.
-        this.pkeyIsEditable = !('pkey_sequence' in this.idlDef);
-        if (!this.record) {
-            this.record = this.idl.create(this.idlClass);
-        }
+        // In 'create' mode.
+        //
+        // Create a new record from the stub record provided by the
+        // caller or a new from-scratch record
+        this.setRecord(this.record || this.idl.create(this.idlClass));
+
         return this.getFieldList();
     }
 
@@ -446,13 +473,22 @@ export class FmRecordEditorComponent
         const recToSave = this.idl.clone(this.record);
         this.convertDatatypesToIdl(recToSave);
         this.pcrud[this.mode]([recToSave]).toPromise().then(
-            result => this.close(result),
-            error  => this.dismiss(error)
+            result => {
+                this.onSave$.emit(result);
+                this.successStr.current().then(msg => this.toast.success(msg));
+                if (this.isDialog()) { this.close(result); }
+            },
+            error => {
+                this.onError$.emit(error);
+                this.failStr.current().then(msg => this.toast.warning(msg));
+                if (this.isDialog()) { this.error(error); }
+            }
         );
     }
 
     cancel() {
-        this.dismiss('canceled');
+        this.onCancel$.emit(this.record);
+        this.close();
     }
 
     // Returns a string describing the type of input to display
@@ -501,6 +537,19 @@ export class FmRecordEditorComponent
         // datatype == text / interval / editable-pkey
         return 'text';
     }
+
+    openTranslator(field: string) {
+        this.translator.fieldName = field;
+        this.translator.idlObject = this.record;
+
+        this.translator.open().subscribe(
+            newValue => {
+                if (newValue) {
+                    this.record[field](newValue);
+                }
+            }
+        );
+    }
 }