LP1840050 FM Editor WIP
authorBill Erickson <berickxx@gmail.com>
Wed, 14 Aug 2019 20:45:20 +0000 (16:45 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 16 Aug 2019 20:40:32 +0000 (16:40 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor-action.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html
Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.module.ts

diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor-action.component.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor-action.component.ts
new file mode 100644 (file)
index 0000000..298856d
--- /dev/null
@@ -0,0 +1,31 @@
+import {Component, Input, Output, EventEmitter, Host, OnInit} from '@angular/core';
+import {FmRecordEditorComponent} from './fm-editor.component';
+
+@Component({
+  selector: 'eg-fm-record-editor-action',
+  template: '<ng-template></ng-template>' // no-op
+})
+
+export class FmRecordEditorActionComponent implements OnInit {
+
+    // unique identifier
+    @Input() key: string;
+
+    @Input() label: string;
+
+    @Input() buttonCss = 'btn-outline-dark';
+
+    // Emits the 'key' of the clicked action.
+    @Output() actionClick: EventEmitter<string>;
+
+    @Input() disabled: boolean;
+
+    constructor(@Host() private editor: FmRecordEditorComponent) {
+        this.actionClick = new EventEmitter<string>();
+    }
+
+    ngOnInit() {
+        this.editor.actions.push(this);
+    }
+}
+
index 2621b3e..afae0ef 100644 (file)
@@ -4,6 +4,11 @@
 <eg-string #successStr text="Update Succeeded" i18n-text></eg-string>
 <eg-string #failStr text="Update Failed" i18n-text></eg-string>
 
+<eg-confirm-dialog #confirmDel
+  dialogTitle="Delete?" i18n-dialogTitle
+  dialogBody="Delete {{recordLabel}}?" i18n-dialogBody>
+</eg-confirm-dialog>
+
 <ng-template #dialogContent>
   <div class="modal-header bg-info" *ngIf="!hideBanner">
     <h4 class="modal-title" i18n>Record Editor: {{recordLabel}}</h4>
                 [required]="field.isRequired()"
                 [entries]="field.linkedValues"
                 [asyncDataSource]="field.linkedValuesSource"
-                [startId]="record[field.name]()"
+                [selectedId]="record[field.name]()"
                 (onChange)="record[field.name]($event ? $event.id : null)">
               </eg-combobox>
             </ng-container>
     </form>
   </div>
   <div class="modal-footer">
+    <button type="button" class="btn {{action.buttonCss}}"
+      *ngFor="let action of actions" [disabled]="action.disabled"
+      (click)="action.actionClick.emit({action: action.key, record: record})">
+      {{action.label}}
+    </button>
     <ng-container *ngIf="isDialog()">
       <button type="button" class="btn btn-success" *ngIf="mode == 'view'"
         (click)="close()" i18n>Close</button>
       <button type="button" class="btn btn-warning ml-2" *ngIf="mode != 'view'"
         (click)="cancel()" i18n>Cancel</button>
     </ng-container>
+
+    <ng-container *ngIf="showDelete && mode != 'view'">
+      <button type="button" class="btn btn-warning" (click)="remove()"
+        [disabled]="record && record.isnew()" i18n>Delete</button>
+    </ng-container>
+
     <button type="button" class="btn btn-info" 
       [disabled]="fmEditForm.invalid" *ngIf="mode != 'view'"
       (click)="save()" i18n>Save</button>
index 674d348..aa65a93 100644 (file)
@@ -11,6 +11,8 @@ 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/share/translate/translate.component';
+import {FmRecordEditorActionComponent} from './fm-editor-action.component';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 
 
 interface CustomFieldTemplate {
@@ -125,6 +127,9 @@ export class FmRecordEditorComponent
     // Emit the modified object when the save action completes.
     @Output() recordSaved = new EventEmitter<IdlObject>();
 
+    // Emit the modified object when the save action completes.
+    @Output() recordDeleted = new EventEmitter<IdlObject>();
+
     // Emit the original object when the save action is canceled.
     @Output() recordCanceled = new EventEmitter<IdlObject>();
 
@@ -134,6 +139,7 @@ export class FmRecordEditorComponent
     @ViewChild('translator') private translator: TranslateComponent;
     @ViewChild('successStr') successStr: StringComponent;
     @ViewChild('failStr') failStr: StringComponent;
+    @ViewChild('confirmDel') confirmDel: ConfirmDialogComponent;
 
     // IDL info for the the selected IDL class
     idlDef: any;
@@ -159,7 +165,7 @@ export class FmRecordEditorComponent
     // is actionable.  This allows the caller to use both @Input()'s
     // without each clobbering the other.
 
-    // Record ID to view/update.  
+    // Record ID to view/update.
     _recordId: any = null;
     @Input() set recordId(id: any) {
         if (id) {
@@ -195,6 +201,8 @@ export class FmRecordEditorComponent
         return this._record;
     }
 
+    actions: FmRecordEditorActionComponent[] = [];
+
     initDone: boolean;
 
     // Comma-separated list of field names defining the order in which
@@ -202,6 +210,9 @@ export class FmRecordEditorComponent
     // will be rendered alphabetically by label after the named fields.
     @Input() fieldOrder: string;
 
+    // When true, show a delete button and support delete operations.
+    @Input() showDelete: boolean;
+
     constructor(
       private modal: NgbModal, // required for passing to parent
       private idl: IdlService,
@@ -332,7 +343,8 @@ export class FmRecordEditorComponent
     // Modifies the provided FM record in place, replacing JS values
     // with IDL-compatible values.
     convertDatatypesToIdl(rec: IdlObject) {
-        const fields = this.idlDef.fields;
+        const fields = this.idlDef.fields.filter(f => !f.virtual);
+
         fields.forEach(field => {
             if (field.datatype === 'bool') {
                 if (rec[field.name]() === true) {
@@ -566,6 +578,25 @@ export class FmRecordEditorComponent
         );
     }
 
+    remove() {
+        this.confirmDel.open().subscribe(confirmed => {
+            if (!confirmed) { return; }
+            const recToRemove = this.idl.clone(this.record);
+            this.pcrud.remove(recToRemove).toPromise().then(
+                result => {
+                    this.recordDeleted.emit(result);
+                    this.successStr.current().then(msg => this.toast.success(msg));
+                    if (this.isDialog()) { this.close(result); }
+                },
+                error => {
+                    this.recordError.emit(error);
+                    this.failStr.current().then(msg => this.toast.warning(msg));
+                    if (this.isDialog()) { this.error(error); }
+                }
+            );
+        });
+    }
+
     cancel() {
         this.recordCanceled.emit(this.record);
         this.close();
index 7be4cf8..6e9c5c3 100644 (file)
@@ -4,11 +4,13 @@ import {CommonWidgetsModule} from '@eg/share/common-widgets.module';
 import {StringModule} from '@eg/share/string/string.module';
 import {TranslateModule} from '@eg/share/translate/translate.module';
 import {FmRecordEditorComponent} from './fm-editor.component';
+import {FmRecordEditorActionComponent} from './fm-editor-action.component';
 
 
 @NgModule({
     declarations: [
-        FmRecordEditorComponent
+        FmRecordEditorComponent,
+        FmRecordEditorActionComponent
     ],
     imports: [
         EgCommonModule,
@@ -17,7 +19,8 @@ import {FmRecordEditorComponent} from './fm-editor.component';
         CommonWidgetsModule
     ],
     exports: [
-        FmRecordEditorComponent
+        FmRecordEditorComponent,
+        FmRecordEditorActionComponent
     ],
     providers: [
     ]