LP1840050 Modularize various standalone components + more.
authorBill Erickson <berickxx@gmail.com>
Fri, 16 Aug 2019 21:00:11 +0000 (17:00 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Fri, 6 Sep 2019 17:00:03 +0000 (13:00 -0400)
Create container modules for the String, Translate, FM record editor, and
Admin Page components & services.  This simplifies imports and allows us
to avoid requiring these modules on pages that don't need them.  In
particular, the staff splash page now loads fewer imports, which should
improve initial load/login time.

Additionally some components were enhanced.

FM record editor now has a eg-fm-record-editor-action component so users
can pass in an action, rendered as a button at the bottom of the editor.

FM record editor gets a delete record option and hideBanner option.

FM record editor now better handles real-time updates of its underlying
recordId and record values, including updates to some editor callers to
migrate to the modified API (replace recId with recordId).

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
26 files changed:
Open-ILS/src/eg2/src/app/common.module.ts
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 [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/org-family-select/org-family-select.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/string/string.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/translate/translate.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/translate/translate.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/translate/translate.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/admin/common.module.ts
Open-ILS/src/eg2/src/app/staff/booking/booking.module.ts
Open-ILS/src/eg2/src/app/staff/booking/create-reservation.component.ts
Open-ILS/src/eg2/src/app/staff/booking/reservations-grid.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/parts.component.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts
Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html [deleted file]
Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.ts [deleted file]

index af1f2b0..d61eeab 100644 (file)
@@ -28,8 +28,7 @@ import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
 import {BoolDisplayComponent} from '@eg/share/util/bool.component';
 import {ToastService} from '@eg/share/toast/toast.service';
 import {ToastComponent} from '@eg/share/toast/toast.component';
-import {StringComponent} from '@eg/share/string/string.component';
-import {StringService} from '@eg/share/string/string.service';
+import {StringModule} from '@eg/share/string/string.module';
 
 
 @NgModule({
@@ -42,7 +41,6 @@ import {StringService} from '@eg/share/string/string.service';
     ProgressInlineComponent,
     ProgressDialogComponent,
     ToastComponent,
-    StringComponent,
     BoolDisplayComponent
   ],
   imports: [
@@ -51,7 +49,8 @@ import {StringService} from '@eg/share/string/string.service';
     ReactiveFormsModule,
     RouterModule,
     NgbModule,
-    EgCoreModule
+    EgCoreModule,
+    StringModule
   ],
   exports: [
     CommonModule,
@@ -59,6 +58,7 @@ import {StringService} from '@eg/share/string/string.service';
     NgbModule,
     FormsModule,
     EgCoreModule,
+    StringModule,
     ReactiveFormsModule,
     PrintComponent,
     DialogComponent,
@@ -68,8 +68,7 @@ import {StringService} from '@eg/share/string/string.service';
     ProgressInlineComponent,
     ProgressDialogComponent,
     BoolDisplayComponent,
-    ToastComponent,
-    StringComponent
+    ToastComponent
   ]
 })
 
@@ -82,7 +81,6 @@ export class EgCommonModule {
             providers: [
                 HatchService,
                 PrintService,
-                StringService,
                 ToastService
             ]
         };
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 bb0e347..e1ba382 100644 (file)
@@ -4,8 +4,13 @@
 <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">
+  <div class="modal-header bg-info" *ngIf="!hideBanner">
     <h4 class="modal-title" i18n>Record Editor: {{recordLabel}}</h4>
     <ng-container *ngIf="isDialog()">
       <button type="button" class="close" 
@@ -79,7 +84,7 @@
                 [limitPerms]="modePerms[mode]"
                 [readOnly]="field.readOnly"
                 [applyDefault]="field.orgDefaultAllowed"
-                [initialOrgId]="record[field.name]()"
+                [applyOrgId]="record[field.name]()"
                 (onChange)="record[field.name]($event)">
               </eg-org-select>
             </ng-container>
                 [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)="closeEditor()" 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 730084a..a4fc62b 100644 (file)
@@ -10,8 +10,10 @@ import {ToastService} from '@eg/share/toast/toast.service';
 import {StringComponent} from '@eg/share/string/string.component';
 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
-import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
 import {FormatService} from '@eg/core/format.service';
+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 {
     template: TemplateRef<any>;
@@ -82,14 +84,9 @@ export class FmRecordEditorComponent
     // IDL class hint (e.g. "aou")
     @Input() idlClass: string;
 
-    recId: any;
-
     // Show datetime fields in this particular timezone
     timezone: string = this.format.wsOrgTimezone;
 
-    // IDL record we are editing
-    record: IdlObject;
-
     // Permissions extracted from the permacrud defs in the IDL
     // for the current IDL class
     modePerms: {[mode: string]: string};
@@ -130,18 +127,26 @@ export class FmRecordEditorComponent
     // Display within a modal dialog window or inline in the page.
     @Input() displayMode: 'dialog' | 'inline' = 'dialog';
 
+    // Hide the top 'Record Editor: ...' banner.  Primarily useful
+    // for displayMode === 'inline'
+    @Input() hideBanner: boolean;
+
+    // Emit the modified object when the save action completes.
+    @Output() recordSaved = new EventEmitter<IdlObject>();
+
     // Emit the modified object when the save action completes.
-    @Output() onSave$ = new EventEmitter<IdlObject>();
+    @Output() recordDeleted = new EventEmitter<IdlObject>();
 
     // Emit the original object when the save action is canceled.
-    @Output() onCancel$ = new EventEmitter<IdlObject>();
+    @Output() recordCanceled = new EventEmitter<IdlObject>();
 
     // Emit an error message when the save action fails.
-    @Output() onError$ = new EventEmitter<string>();
+    @Output() recordError = new EventEmitter<string>();
 
     @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;
@@ -161,16 +166,64 @@ export class FmRecordEditorComponent
     //       '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.
-    @Input() set recordId(id: any) {
-        if (id) { this.recId = id; }
-    }
-
     // custom function for munging the record before it gets saved;
     // will get passed mode and the record itself
     @Input() preSave: Function;
 
+    // recordId and record getters and setters.
+    // Note that setting the this.recordId to NULL does not clear the
+    // current value of this.record and vice versa.  Only viable data
+    // is actionable.  This allows the caller to use both @Input()'s
+    // without each clobbering the other.
+
+    // Record ID to view/update.
+    _recordId: any = null;
+    @Input() set recordId(id: any) {
+        if (id) {
+            if (id !== this._recordId) {
+                this._recordId = id;
+                this._record = null; // force re-fetch
+                this.handleRecordChange();
+            }
+        } else {
+            this._recordId = null;
+        }
+    }
+
+    get recordId(): any {
+        return this._recordId;
+    }
+
+    // IDL record we are editing
+    _record: IdlObject = null;
+    @Input() set record(r: IdlObject) {
+        if (r) {
+            if (!this.idl.pkeyMatches(this.record, r)) {
+                this._record = r;
+                this._recordId = null; // avoid mismatch
+                this.handleRecordChange();
+            }
+        } else {
+            this._record = null;
+        }
+    }
+
+    get record(): IdlObject {
+        return this._record;
+    }
+
+    actions: FmRecordEditorActionComponent[] = [];
+
+    initDone: boolean;
+
+    // Comma-separated list of field names defining the order in which
+    // fields should be rendered in the form.  Any fields not represented
+    // 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,
@@ -200,6 +253,16 @@ export class FmRecordEditorComponent
         } else {
             this.initRecord();
         }
+        this.initDone = true;
+    }
+
+    // If the record ID changes after ngOnInit has been called
+    // and we're using displayMode=inline, force the data to
+    // resync in real time
+    handleRecordChange() {
+        if (this.initDone && !this.isDialog()) {
+            this.initRecord();
+        }
     }
 
     open(args?: NgbModalOptions): Observable<any> {
@@ -219,11 +282,11 @@ export class FmRecordEditorComponent
         return this.displayMode === 'dialog';
     }
 
-    // Set the record value and clear the recId value to
-    // indicate the record is our current source of data.
+    // DEPRECATED: This is a duplicate of this.record = abc;
     setRecord(record: IdlObject) {
-        this.record = record;
-        this.recId = null;
+        console.warn('fm-editor:setRecord() is deprecated. ' +
+            'Use editor.record = abc or [record]="abc" instead');
+        this.record = record; // this calls the setter
     }
 
     // Translate comma-separated string versions of various inputs
@@ -260,21 +323,25 @@ export class FmRecordEditorComponent
         if (this.mode === 'update' || this.mode === 'view') {
 
             let promise;
-            if (this.record && this.recId === null) {
+            if (this.record && this.recordId === null) {
                 promise = Promise.resolve(this.record);
-            } else {
+            } else if (this.recordId) {
                 promise =
-                    this.pcrud.retrieve(this.idlClass, this.recId).toPromise();
+                    this.pcrud.retrieve(this.idlClass, this.recordId).toPromise();
+            } else {
+                // Not enough data yet to fetch anything
+                return Promise.resolve();
             }
 
             return promise.then(rec => {
 
                 if (!rec) {
                     return Promise.reject(`No '${this.idlClass}'
-                        record found with id ${this.recId}`);
+                        record found with id ${this.recordId}`);
                 }
 
-                this.record = rec;
+                // Set this._record (not this.record) to avoid loop in initRecord()
+                this._record = rec;
                 this.convertDatatypesToJs();
                 return this.getFieldList();
             });
@@ -284,7 +351,9 @@ export class FmRecordEditorComponent
         //
         // 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));
+        // Set this._record (not this.record) to avoid loop in initRecord()
+        this._record = this.record || this.idl.create(this.idlClass);
+        this._recordId = null; // avoid future confusion
 
         return this.getFieldList();
     }
@@ -306,7 +375,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) {
@@ -350,13 +420,35 @@ export class FmRecordEditorComponent
 
     private getFieldList(): Promise<any> {
 
-        this.fields = this.idlDef.fields.filter(f =>
-            !f.virtual && !this.hiddenFieldsList.includes(f.name)
-        );
+        const fields = this.idlDef.fields.filter(f =>
+            !f.virtual && !this.hiddenFieldsList.includes(f.name));
 
         // Wait for all network calls to complete
         return Promise.all(
-            this.fields.map(field => this.constructOneField(field)));
+            fields.map(field => this.constructOneField(field))
+
+        ).then(() => {
+
+            if (!this.fieldOrder) {
+                this.fields = fields.sort((a, b) => a.label < b.label ? -1 : 1);
+                return;
+            }
+
+            let newList = [];
+            const ordered = this.fieldOrder.split(/,/);
+
+            ordered.forEach(name => {
+                const f1 = fields.filter(f2 => f2.name === name)[0];
+                if (f1) { newList.push(f1); }
+            });
+
+            // Sort remaining fields by label
+            const remainder = fields.filter(f => !ordered.includes(f.name));
+            remainder.sort((a, b) => a.label < b.label ? -1 : 1);
+            newList = newList.concat(remainder);
+
+            this.fields = newList;
+        });
     }
 
     private constructOneField(field: any): Promise<any> {
@@ -511,20 +603,39 @@ export class FmRecordEditorComponent
         this.convertDatatypesToIdl(recToSave);
         this.pcrud[this.mode]([recToSave]).toPromise().then(
             result => {
-                this.onSave$.emit(result);
+                this.recordSaved.emit(result);
                 this.successStr.current().then(msg => this.toast.success(msg));
                 if (this.isDialog()) { this.record = undefined; this.close(result); }
             },
             error => {
-                this.onError$.emit(error);
+                this.recordError.emit(error);
                 this.failStr.current().then(msg => this.toast.warning(msg));
                 if (this.isDialog()) { this.error(error); }
             }
         );
     }
 
+    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.onCancel$.emit(this.record);
+        this.recordCanceled.emit(this.record);
         this.record = undefined;
         this.close();
     }
diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.module.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.module.ts
new file mode 100644 (file)
index 0000000..6e9c5c3
--- /dev/null
@@ -0,0 +1,30 @@
+import {NgModule} from '@angular/core';
+import {EgCommonModule} from '@eg/common.module';
+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,
+        FmRecordEditorActionComponent
+    ],
+    imports: [
+        EgCommonModule,
+        StringModule,
+        TranslateModule,
+        CommonWidgetsModule
+    ],
+    exports: [
+        FmRecordEditorComponent,
+        FmRecordEditorActionComponent
+    ],
+    providers: [
+    ]
+})
+
+export class FmRecordEditorModule { }
+
diff --git a/Open-ILS/src/eg2/src/app/share/org-family-select/org-family-select.module.ts b/Open-ILS/src/eg2/src/app/share/org-family-select/org-family-select.module.ts
new file mode 100644 (file)
index 0000000..ea5fc2f
--- /dev/null
@@ -0,0 +1,26 @@
+import {NgModule} from '@angular/core';
+import {EgCommonModule} from '@eg/common.module';
+import {EgCoreModule} from '@eg/core/core.module';
+import {CommonWidgetsModule} from '@eg/share/common-widgets.module';
+import {OrgFamilySelectComponent} from './org-family-select.component';
+import {ReactiveFormsModule} from '@angular/forms';
+
+@NgModule({
+    declarations: [
+        OrgFamilySelectComponent
+    ],
+    imports: [
+        EgCommonModule,
+        EgCoreModule,
+        CommonWidgetsModule,
+        ReactiveFormsModule
+    ],
+    exports: [
+        OrgFamilySelectComponent
+    ],
+    providers: [
+    ]
+})
+
+export class OrgFamilySelectModule { }
+
diff --git a/Open-ILS/src/eg2/src/app/share/string/string.module.ts b/Open-ILS/src/eg2/src/app/share/string/string.module.ts
new file mode 100644 (file)
index 0000000..286e642
--- /dev/null
@@ -0,0 +1,23 @@
+import {NgModule} from '@angular/core';
+import {EgCoreModule} from '@eg/core/core.module';
+import {StringComponent} from '@eg/share/string/string.component';
+import {StringService} from '@eg/share/string/string.service';
+
+
+@NgModule({
+    declarations: [
+        StringComponent
+    ],
+    imports: [
+        EgCoreModule
+    ],
+    exports: [
+        StringComponent
+    ],
+    providers: [
+        StringService
+    ]
+})
+
+export class StringModule { }
+
diff --git a/Open-ILS/src/eg2/src/app/share/translate/translate.component.html b/Open-ILS/src/eg2/src/app/share/translate/translate.component.html
new file mode 100644 (file)
index 0000000..61b9cb4
--- /dev/null
@@ -0,0 +1,62 @@
+<ng-template #dialogContent>
+  <div class="modal-header bg-info">
+    <h4 class="modal-title" i18n>
+      {{idlClassDef.label}}
+    </h4>
+    <button type="button" class="close" 
+      i18n-aria-label aria-label="Close" (click)="close()">
+      <span aria-hidden="true">&times;</span>
+    </button>
+  </div>
+  <div class="modal-body form-common form-validated" *ngIf="idlObj">
+    <div class="form-group row">
+      <label class="col-lg-4 text-right font-weight-bold" 
+        i18n>Field Name</label>
+      <input 
+        type="text" 
+        [disabled]="true"
+        class="form-control col-lg-7"
+        value="{{idlClassDef.field_map[field].label}}">
+    </div>
+    <div class="form-group row">
+      <label class="col-lg-4 text-right font-weight-bold" 
+        i18n>Current Value</label>
+      <input 
+        type="text" 
+        [disabled]="true"
+        class="form-control col-lg-7"
+        value="{{idlObj[field]()}}">
+    </div>
+    <div class="form-group row">
+      <label class="col-lg-4 text-right font-weight-bold" 
+        i18n>Select Locale</label>
+      <select class="form-control col-lg-7" 
+        (change)="localeChanged($event)"
+        [(ngModel)]="selectedLocale">
+        <option value="{{locale.code()}}" *ngFor="let locale of locales">
+          {{locale.name()}}
+        </option>
+      </select>
+    </div>
+    <div class="form-group row">
+      <label class="col-lg-4 text-right font-weight-bold" i18n>Translation</label>
+      <input 
+        id='translation-input'
+        type="text" 
+        class="form-control col-lg-7"
+        required
+        i18n-placeholder
+        (keyup.enter)="translate()"
+        placeholder="Translation..." 
+        [(ngModel)]="translatedValue"/>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button *ngIf="prevString" (click)="prevString()" 
+      class="btn btn-info" i18n>Prev String</button>
+    <button *ngIf="nextString" (click)="nextString()" 
+      class="btn btn-info mr-3" i18n>Next String</button>
+    <button (click)="translate()" class="btn btn-info" i18n>Apply</button>
+    <button (click)="close()" class="btn btn-warning ml-2" i18n>Cancel</button>
+  </div>
+</ng-template>
diff --git a/Open-ILS/src/eg2/src/app/share/translate/translate.component.ts b/Open-ILS/src/eg2/src/app/share/translate/translate.component.ts
new file mode 100644 (file)
index 0000000..4880973
--- /dev/null
@@ -0,0 +1,145 @@
+import {Component, OnInit, Input, Renderer2} from '@angular/core';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {LocaleService} from '@eg/core/locale.service';
+import {AuthService} from '@eg/core/auth.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {DialogComponent} from '@eg/share/dialog/dialog.component';
+import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+  selector: 'eg-translate',
+  templateUrl: 'translate.component.html'
+})
+
+export class TranslateComponent
+    extends DialogComponent implements OnInit {
+
+    idlClassDef: any;
+    locales: IdlObject[];
+    selectedLocale: string;
+    translatedValue: string;
+    existingTranslation: IdlObject;
+
+    // These actions should update the idlObject and/or fieldName values,
+    // forcing the dialog to load a new string to translate.  When set,
+    // applying a translation in the dialog will leave the dialog window open
+    // so the next/prev buttons can be used to fetch the next string.
+    nextString: () => void;
+    prevString: () => void;
+
+    idlObj: IdlObject;
+    @Input() set idlObject(o: IdlObject) {
+        if (o) {
+            this.idlObj = o;
+            this.idlClassDef = this.idl.classes[o.classname];
+            this.fetchTranslation();
+        }
+    }
+
+    field: string;
+    @Input() set fieldName(n: string) {
+        this.field = n;
+    }
+
+    constructor(
+        private modal: NgbModal, // required for passing to parent
+        private renderer: Renderer2,
+        private idl: IdlService,
+        private toast: ToastService,
+        private locale: LocaleService,
+        private pcrud: PcrudService,
+        private auth: AuthService) {
+        super(modal);
+    }
+
+    ngOnInit() {
+        // Default to the login locale
+        this.selectedLocale = this.locale.currentLocaleCode();
+        this.locales = [];
+        this.locale.supportedLocales().subscribe(l => this.locales.push(l));
+
+        this.onOpen$.subscribe(() => {
+            const elm = this.renderer.selectRootElement('#translation-input');
+            if (elm) {
+                elm.focus();
+                elm.select();
+            }
+        });
+    }
+
+    localeChanged(code: string) {
+        this.fetchTranslation();
+    }
+
+    fetchTranslation() {
+        const exist = this.existingTranslation;
+
+        if (exist
+            && exist.fq_field() === this.fqField()
+            && exist.identity_value() === this.identValue()) {
+            // Already have the current translation object.
+            return;
+        }
+
+        this.translatedValue = '';
+        this.existingTranslation = null;
+
+        this.pcrud.search('i18n', {
+            translation: this.selectedLocale,
+            fq_field : this.fqField(),
+            identity_value: this.identValue()
+        }).subscribe(tr => {
+            this.existingTranslation = tr;
+            this.translatedValue = tr.string();
+            console.debug('found existing translation ', tr);
+        });
+    }
+
+    fqField(): string {
+        return this.idlClassDef.classname + '.' + this.field;
+    }
+
+    identValue(): string {
+        return this.idlObj[this.idlClassDef.pkey || 'id']();
+    }
+
+    translate() {
+        if (!this.translatedValue) { return; }
+
+        let entry;
+
+        if (this.existingTranslation) {
+            entry = this.existingTranslation;
+            entry.string(this.translatedValue);
+
+            this.pcrud.update(entry).toPromise().then(
+                ok => {
+                    if (!this.nextString) {
+                        this.close(this.translatedValue);
+                    }
+                },
+                err => console.error(err)
+            );
+
+            return;
+        }
+
+        entry = this.idl.create('i18n');
+        entry.fq_field(this.fqField());
+        entry.identity_value(this.identValue());
+        entry.translation(this.selectedLocale);
+        entry.string(this.translatedValue);
+
+        this.pcrud.create(entry).toPromise().then(
+            ok => {
+                if (!this.nextString) {
+                    this.close(this.translatedValue);
+                }
+            },
+            err => console.error('Translation creation failed')
+        );
+    }
+}
+
+
diff --git a/Open-ILS/src/eg2/src/app/share/translate/translate.module.ts b/Open-ILS/src/eg2/src/app/share/translate/translate.module.ts
new file mode 100644 (file)
index 0000000..41dbd5d
--- /dev/null
@@ -0,0 +1,23 @@
+import {NgModule} from '@angular/core';
+import {EgCommonModule} from '@eg/common.module';
+import {EgCoreModule} from '@eg/core/core.module';
+import {TranslateComponent} from './translate.component';
+
+
+@NgModule({
+    declarations: [
+        TranslateComponent
+    ],
+    imports: [
+        EgCommonModule,
+        EgCoreModule
+    ],
+    exports: [
+        TranslateComponent
+    ],
+    providers: [
+    ]
+})
+
+export class TranslateModule { }
+
index 5bd71d3..4bb5b30 100644 (file)
@@ -1,6 +1,9 @@
 import {NgModule} from '@angular/core';
 import {StaffCommonModule} from '@eg/staff/common.module';
 import {LinkTableComponent, LinkTableLinkComponent} from '@eg/staff/share/link-table/link-table.component';
+import {TranslateModule} from '@eg/share/translate/translate.module';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
+import {AdminPageModule} from '@eg/staff/share/admin-page/admin-page.module';
 import {BasicAdminPageComponent} from '@eg/staff/admin/basic-admin-page.component';
 
 @NgModule({
@@ -10,10 +13,16 @@ import {BasicAdminPageComponent} from '@eg/staff/admin/basic-admin-page.componen
     BasicAdminPageComponent
   ],
   imports: [
-    StaffCommonModule
+    StaffCommonModule,
+    TranslateModule,
+    FmRecordEditorModule,
+    AdminPageModule
   ],
   exports: [
     StaffCommonModule,
+    TranslateModule,
+    FmRecordEditorModule,
+    AdminPageModule,
     LinkTableComponent,
     LinkTableLinkComponent,
     BasicAdminPageComponent
index 65da637..9b14137 100644 (file)
@@ -13,6 +13,8 @@ import {ReturnComponent} from './return.component';
 import {NoTimezoneSetComponent} from './no-timezone-set.component';
 import {PatronService} from '@eg/staff/share/patron.service';
 import {BookingResourceBarcodeValidatorDirective} from './booking_resource_validator.directive';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
+import {OrgFamilySelectModule} from '@eg/share/org-family-select/org-family-select.module';
 
 
 @NgModule({
@@ -20,6 +22,8 @@ import {BookingResourceBarcodeValidatorDirective} from './booking_resource_valid
         StaffCommonModule,
         BookingRoutingModule,
         ReactiveFormsModule,
+        FmRecordEditorModule,
+        OrgFamilySelectModule
     ],
     providers: [PatronService],
     declarations: [
index 6dcfe7c..bb38c92 100644 (file)
@@ -375,7 +375,7 @@ export class CreateReservationComponent implements OnInit, AfterViewInit, OnDest
 
     openReservationViewer = (id: number): void => {
         this.viewReservation.mode = 'view';
-        this.viewReservation.recId = id;
+        this.viewReservation.recordId = id;
         this.viewReservation.open({ size: 'lg' });
     }
 
index d4e3973..12dcc47 100644 (file)
@@ -281,7 +281,7 @@ export class ReservationsGridComponent implements OnInit {
     }
 
     showEditDialog(idlThing: IdlObject) {
-        this.editDialog.recId = idlThing.id();
+        this.editDialog.recordId = idlThing.id();
         this.editDialog.timezone = idlThing['timezone'];
         return new Promise((resolve, reject) => {
             this.editDialog.open({size: 'lg'}).subscribe(
index c33999a..8efe6b5 100644 (file)
@@ -59,7 +59,7 @@ export class MatchSetListComponent implements AfterViewInit {
         this.grid.onRowActivate.subscribe(
             (matchSet: IdlObject) => {
                 this.editDialog.mode = 'update';
-                this.editDialog.recId = matchSet.id();
+                this.editDialog.recordId = matchSet.id();
                 this.editDialog.open({size: 'lg'})
                     .subscribe(() => this.grid.reload());
             }
index 9bbfd46..0f39428 100644 (file)
@@ -1,8 +1,10 @@
 import {NgModule} from '@angular/core';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
 import {StaffCommonModule} from '@eg/staff/common.module';
 import {CatalogCommonModule} from '@eg/share/catalog/catalog-common.module';
 import {HttpClientModule} from '@angular/common/http';
 import {TreeModule} from '@eg/share/tree/tree.module';
+import {AdminPageModule} from '@eg/staff/share/admin-page/admin-page.module';
 import {VandelayRoutingModule} from './routing.module';
 import {VandelayService} from './vandelay.service';
 import {VandelayComponent} from './vandelay.component';
@@ -48,6 +50,8 @@ import {RecentImportsComponent} from './recent-imports.component';
   imports: [
     TreeModule,
     StaffCommonModule,
+    FmRecordEditorModule,
+    AdminPageModule,
     CatalogCommonModule,
     VandelayRoutingModule,
     HttpClientModule,
index 064c215..d561689 100644 (file)
@@ -1,4 +1,5 @@
 import {NgModule} from '@angular/core';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
 import {StaffCommonModule} from '@eg/staff/common.module';
 import {CatalogCommonModule} from '@eg/share/catalog/catalog-common.module';
 import {CatalogRoutingModule} from './routing.module';
@@ -55,6 +56,7 @@ import {MarcEditModule} from '@eg/staff/share/marc-edit/marc-edit.module';
   ],
   imports: [
     StaffCommonModule,
+    FmRecordEditorModule,
     CatalogCommonModule,
     CatalogRoutingModule,
     HoldsModule,
index 2f59374..9766c7f 100644 (file)
@@ -80,7 +80,7 @@ export class PartsComponent implements OnInit {
         this.partsGrid.onRowActivate.subscribe(
             (part: IdlObject) => {
                 this.editDialog.mode = 'update';
-                this.editDialog.recId = part.id();
+                this.editDialog.recordId = part.id();
                 this.editDialog.open()
                     .subscribe(ok => this.partsGrid.reload());
             }
@@ -89,7 +89,7 @@ export class PartsComponent implements OnInit {
         this.createNew = () => {
 
             const part = this.idl.create('bmp');
-            part.record(this.recId);
+            part.record(this.recordId);
             this.editDialog.record = part;
 
             this.editDialog.mode = 'create';
index 458b0f5..c0fe41b 100644 (file)
@@ -4,17 +4,13 @@ import {CommonWidgetsModule} from '@eg/share/common-widgets.module';
 import {AudioService} from '@eg/share/util/audio.service';
 import {GridModule} from '@eg/share/grid/grid.module';
 import {StaffBannerComponent} from './share/staff-banner.component';
-import {OrgFamilySelectComponent} from '@eg/share/org-family-select/org-family-select.component';
 import {AccessKeyDirective} from '@eg/share/accesskey/accesskey.directive';
 import {AccessKeyService} from '@eg/share/accesskey/accesskey.service';
 import {AccessKeyInfoComponent} from '@eg/share/accesskey/accesskey-info.component';
 import {OpChangeComponent} from '@eg/staff/share/op-change/op-change.component';
 import {TitleComponent} from '@eg/share/title/title.component';
-import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {BucketDialogComponent} from '@eg/staff/share/buckets/bucket-dialog.component';
 import {BibSummaryComponent} from '@eg/staff/share/bib-summary/bib-summary.component';
-import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
-import {AdminPageComponent} from '@eg/staff/share/admin-page/admin-page.component';
 import {EgHelpPopoverComponent} from '@eg/share/eg-help-popover/eg-help-popover.component';
 import {DatetimeValidatorDirective} from '@eg/share/validators/datetime_validator.directive';
 import {MultiSelectComponent} from '@eg/share/multi-select/multi-select.component';
@@ -28,16 +24,12 @@ import {PatronBarcodeValidatorDirective} from '@eg/share/validators/patron_barco
 @NgModule({
   declarations: [
     StaffBannerComponent,
-    OrgFamilySelectComponent,
     AccessKeyDirective,
     AccessKeyInfoComponent,
     TitleComponent,
     OpChangeComponent,
-    FmRecordEditorComponent,
     BucketDialogComponent,
     BibSummaryComponent,
-    TranslateComponent,
-    AdminPageComponent,
     EgHelpPopoverComponent,
     DatetimeValidatorDirective,
     MultiSelectComponent,
@@ -54,16 +46,12 @@ import {PatronBarcodeValidatorDirective} from '@eg/share/validators/patron_barco
     CommonWidgetsModule,
     GridModule,
     StaffBannerComponent,
-    OrgFamilySelectComponent,
     AccessKeyDirective,
     AccessKeyInfoComponent,
     TitleComponent,
     OpChangeComponent,
-    FmRecordEditorComponent,
     BucketDialogComponent,
     BibSummaryComponent,
-    TranslateComponent,
-    AdminPageComponent,
     EgHelpPopoverComponent,
     DatetimeValidatorDirective,
     MultiSelectComponent,
index 88716f3..ee46d1e 100644 (file)
   <!-- note: fieldOptions would be best defined in the .ts file, but
       want to demostrate it can be set in the template as well -->
   <eg-fm-record-editor #fmRecordEditor 
-      idlClass="cmrcfld" mode="create" 
-      [fieldOptions]="{marc_record_type:{customValues:[{id:'biblio'},{id:'serial'},{id:'authority'}]},description:{customTemplate:{template:descriptionTemplate,context:{'hello':'goodbye'}}}}"
-      recordId="1" orgDefaultAllowed="owner">
+    idlClass="cmrcfld" mode="create" hiddenFields="id"
+    fieldOrder="owner,name,description,marc_format,marc_record_type,tag"
+    [fieldOptions]="{marc_record_type:{customValues:[{id:'biblio'},{id:'serial'},{id:'authority'}]},description:{customTemplate:{template:descriptionTemplate,context:{'hello':'goodbye'}}}}"
+    recordId="1" orgDefaultAllowed="owner">
   </eg-fm-record-editor>
   <button class="btn btn-dark" (click)="openEditor()">
       Fm Record Editor
index 7b17c2d..3557532 100644 (file)
@@ -385,7 +385,7 @@ export class SandboxComponent implements OnInit {
 
     showEditDialog(idlThing: IdlObject): Promise<any> {
         this.editDialog.mode = 'update';
-        this.editDialog.recId = idlThing['id']();
+        this.editDialog.recordId = idlThing['id']();
         return new Promise((resolve, reject) => {
             this.editDialog.open({size: 'lg'}).subscribe(
                 ok => {
index 0fc739e..a33deb8 100644 (file)
@@ -1,9 +1,12 @@
 import {NgModule} from '@angular/core';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
 import {StaffCommonModule} from '@eg/staff/common.module';
+import {TranslateModule} from '@eg/share/translate/translate.module';
 import {SandboxRoutingModule} from './routing.module';
 import {SandboxComponent} from './sandbox.component';
 import {ReactiveFormsModule} from '@angular/forms';
 import {SampleDataService} from '@eg/share/util/sample-data.service';
+import {OrgFamilySelectModule} from '@eg/share/org-family-select/org-family-select.module';
 
 @NgModule({
   declarations: [
@@ -11,6 +14,9 @@ import {SampleDataService} from '@eg/share/util/sample-data.service';
   ],
   imports: [
     StaffCommonModule,
+    TranslateModule,
+    FmRecordEditorModule,
+    OrgFamilySelectModule,
     SandboxRoutingModule,
     ReactiveFormsModule
   ],
index b853a6a..9c76b4d 100644 (file)
@@ -3,7 +3,7 @@ import {ActivatedRoute} from '@angular/router';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {GridDataSource} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
-import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
+import {TranslateComponent} from '@eg/share/translate/translate.component';
 import {ToastService} from '@eg/share/toast/toast.service';
 import {Pager} from '@eg/share/util/pager';
 import {PcrudService} from '@eg/core/pcrud.service';
@@ -246,7 +246,7 @@ export class AdminPageComponent implements OnInit {
 
     showEditDialog(idlThing: IdlObject): Promise<any> {
         this.editDialog.mode = 'update';
-        this.editDialog.recId = idlThing[this.pkeyField]();
+        this.editDialog.recordId = idlThing[this.pkeyField]();
         return new Promise((resolve, reject) => {
             this.editDialog.open({size: this.dialogSize}).subscribe(
                 result => {
@@ -297,7 +297,7 @@ export class AdminPageComponent implements OnInit {
         this.editDialog.mode = 'create';
         // We reuse the same editor for all actions.  Be sure
         // create action does not try to modify an existing record.
-        this.editDialog.recId = null;
+        this.editDialog.recordId = null;
         this.editDialog.record = null;
         this.editDialog.open({size: this.dialogSize}).subscribe(
             ok => {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.module.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.module.ts
new file mode 100644 (file)
index 0000000..af6df24
--- /dev/null
@@ -0,0 +1,34 @@
+import {NgModule} from '@angular/core';
+import {EgCommonModule} from '@eg/common.module';
+import {EgCoreModule} from '@eg/core/core.module';
+import {GridModule} from '@eg/share/grid/grid.module';
+import {StringModule} from '@eg/share/string/string.module';
+import {TranslateModule} from '@eg/share/translate/translate.module';
+import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module';
+import {AdminPageComponent} from './admin-page.component';
+import {OrgFamilySelectModule} from '@eg/share/org-family-select/org-family-select.module';
+
+
+@NgModule({
+    declarations: [
+        AdminPageComponent
+    ],
+    imports: [
+        EgCommonModule,
+        EgCoreModule,
+        StringModule,
+        OrgFamilySelectModule,
+        TranslateModule,
+        FmRecordEditorModule,
+        GridModule
+    ],
+    exports: [
+        OrgFamilySelectModule,
+        AdminPageComponent
+    ],
+    providers: [
+    ]
+})
+
+export class AdminPageModule { }
+
diff --git a/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html b/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html
deleted file mode 100644 (file)
index 61b9cb4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<ng-template #dialogContent>
-  <div class="modal-header bg-info">
-    <h4 class="modal-title" i18n>
-      {{idlClassDef.label}}
-    </h4>
-    <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" (click)="close()">
-      <span aria-hidden="true">&times;</span>
-    </button>
-  </div>
-  <div class="modal-body form-common form-validated" *ngIf="idlObj">
-    <div class="form-group row">
-      <label class="col-lg-4 text-right font-weight-bold" 
-        i18n>Field Name</label>
-      <input 
-        type="text" 
-        [disabled]="true"
-        class="form-control col-lg-7"
-        value="{{idlClassDef.field_map[field].label}}">
-    </div>
-    <div class="form-group row">
-      <label class="col-lg-4 text-right font-weight-bold" 
-        i18n>Current Value</label>
-      <input 
-        type="text" 
-        [disabled]="true"
-        class="form-control col-lg-7"
-        value="{{idlObj[field]()}}">
-    </div>
-    <div class="form-group row">
-      <label class="col-lg-4 text-right font-weight-bold" 
-        i18n>Select Locale</label>
-      <select class="form-control col-lg-7" 
-        (change)="localeChanged($event)"
-        [(ngModel)]="selectedLocale">
-        <option value="{{locale.code()}}" *ngFor="let locale of locales">
-          {{locale.name()}}
-        </option>
-      </select>
-    </div>
-    <div class="form-group row">
-      <label class="col-lg-4 text-right font-weight-bold" i18n>Translation</label>
-      <input 
-        id='translation-input'
-        type="text" 
-        class="form-control col-lg-7"
-        required
-        i18n-placeholder
-        (keyup.enter)="translate()"
-        placeholder="Translation..." 
-        [(ngModel)]="translatedValue"/>
-    </div>
-  </div>
-  <div class="modal-footer">
-    <button *ngIf="prevString" (click)="prevString()" 
-      class="btn btn-info" i18n>Prev String</button>
-    <button *ngIf="nextString" (click)="nextString()" 
-      class="btn btn-info mr-3" i18n>Next String</button>
-    <button (click)="translate()" class="btn btn-info" i18n>Apply</button>
-    <button (click)="close()" class="btn btn-warning ml-2" i18n>Cancel</button>
-  </div>
-</ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.ts b/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.ts
deleted file mode 100644 (file)
index 4880973..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-import {Component, OnInit, Input, Renderer2} from '@angular/core';
-import {IdlService, IdlObject} from '@eg/core/idl.service';
-import {ToastService} from '@eg/share/toast/toast.service';
-import {LocaleService} from '@eg/core/locale.service';
-import {AuthService} from '@eg/core/auth.service';
-import {PcrudService} from '@eg/core/pcrud.service';
-import {DialogComponent} from '@eg/share/dialog/dialog.component';
-import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
-
-@Component({
-  selector: 'eg-translate',
-  templateUrl: 'translate.component.html'
-})
-
-export class TranslateComponent
-    extends DialogComponent implements OnInit {
-
-    idlClassDef: any;
-    locales: IdlObject[];
-    selectedLocale: string;
-    translatedValue: string;
-    existingTranslation: IdlObject;
-
-    // These actions should update the idlObject and/or fieldName values,
-    // forcing the dialog to load a new string to translate.  When set,
-    // applying a translation in the dialog will leave the dialog window open
-    // so the next/prev buttons can be used to fetch the next string.
-    nextString: () => void;
-    prevString: () => void;
-
-    idlObj: IdlObject;
-    @Input() set idlObject(o: IdlObject) {
-        if (o) {
-            this.idlObj = o;
-            this.idlClassDef = this.idl.classes[o.classname];
-            this.fetchTranslation();
-        }
-    }
-
-    field: string;
-    @Input() set fieldName(n: string) {
-        this.field = n;
-    }
-
-    constructor(
-        private modal: NgbModal, // required for passing to parent
-        private renderer: Renderer2,
-        private idl: IdlService,
-        private toast: ToastService,
-        private locale: LocaleService,
-        private pcrud: PcrudService,
-        private auth: AuthService) {
-        super(modal);
-    }
-
-    ngOnInit() {
-        // Default to the login locale
-        this.selectedLocale = this.locale.currentLocaleCode();
-        this.locales = [];
-        this.locale.supportedLocales().subscribe(l => this.locales.push(l));
-
-        this.onOpen$.subscribe(() => {
-            const elm = this.renderer.selectRootElement('#translation-input');
-            if (elm) {
-                elm.focus();
-                elm.select();
-            }
-        });
-    }
-
-    localeChanged(code: string) {
-        this.fetchTranslation();
-    }
-
-    fetchTranslation() {
-        const exist = this.existingTranslation;
-
-        if (exist
-            && exist.fq_field() === this.fqField()
-            && exist.identity_value() === this.identValue()) {
-            // Already have the current translation object.
-            return;
-        }
-
-        this.translatedValue = '';
-        this.existingTranslation = null;
-
-        this.pcrud.search('i18n', {
-            translation: this.selectedLocale,
-            fq_field : this.fqField(),
-            identity_value: this.identValue()
-        }).subscribe(tr => {
-            this.existingTranslation = tr;
-            this.translatedValue = tr.string();
-            console.debug('found existing translation ', tr);
-        });
-    }
-
-    fqField(): string {
-        return this.idlClassDef.classname + '.' + this.field;
-    }
-
-    identValue(): string {
-        return this.idlObj[this.idlClassDef.pkey || 'id']();
-    }
-
-    translate() {
-        if (!this.translatedValue) { return; }
-
-        let entry;
-
-        if (this.existingTranslation) {
-            entry = this.existingTranslation;
-            entry.string(this.translatedValue);
-
-            this.pcrud.update(entry).toPromise().then(
-                ok => {
-                    if (!this.nextString) {
-                        this.close(this.translatedValue);
-                    }
-                },
-                err => console.error(err)
-            );
-
-            return;
-        }
-
-        entry = this.idl.create('i18n');
-        entry.fq_field(this.fqField());
-        entry.identity_value(this.identValue());
-        entry.translation(this.selectedLocale);
-        entry.string(this.translatedValue);
-
-        this.pcrud.create(entry).toPromise().then(
-            ok => {
-                if (!this.nextString) {
-                    this.close(this.translatedValue);
-                }
-            },
-            err => console.error('Translation creation failed')
-        );
-    }
-}
-
-