LP#1775466 Generic admin page; sms carriers
authorBill Erickson <berickxx@gmail.com>
Fri, 25 May 2018 15:34:24 +0000 (11:34 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 6 Jun 2018 20:59:40 +0000 (16:59 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
13 files changed:
Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts
Open-ILS/src/eg2/src/app/staff/admin/admin.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/config/billing_type.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/config/billing_type.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/config/config.module.ts
Open-ILS/src/eg2/src/app/staff/admin/server/config/hard_due_date.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/config/hard_due_date.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/config/routing.module.ts
Open-ILS/src/eg2/src/app/staff/admin/server/config/sms_carrier.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/routing.module.ts
Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts [new file with mode: 0644]

index 8d6434e..e670414 100644 (file)
@@ -40,15 +40,13 @@ export class EgDateSelectComponent implements OnInit {
             this.initialDate = new Date(this.initialIso);
         }
 
-        if (!this.initialDate) {
-            this.initialDate = new Date();
+        if (this.initialDate) {
+            this.current = {
+                year: this.initialDate.getFullYear(),
+                month: this.initialDate.getMonth() + 1,
+                day: this.initialDate.getDate()
+            };
         }
-
-        this.current = {
-            year: this.initialDate.getFullYear(),
-            month: this.initialDate.getMonth() + 1,
-            day: this.initialDate.getDate()
-        };
     }
 
     onDateSelect(evt) {
diff --git a/Open-ILS/src/eg2/src/app/staff/admin/admin.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/admin.module.ts
new file mode 100644 (file)
index 0000000..a31826b
--- /dev/null
@@ -0,0 +1,21 @@
+import {NgModule} from '@angular/core';
+import {EgStaffCommonModule} from '@eg/staff/common.module';
+import {EgAdminRoutingModule} from './routing.module';
+
+@NgModule({
+  declarations: [
+  ],
+  imports: [
+    EgStaffCommonModule,
+    EgAdminRoutingModule
+  ],
+  exports: [
+  ],
+  providers: [
+  ]
+})
+
+export class EgAdminModule {
+}
+
+
index 0fa942d..8de396c 100644 (file)
@@ -84,7 +84,7 @@
     <eg-link-table-link i18n-label label="Remote Accounts"  
       url="/eg/staff/admin/server/config/remote_account"></eg-link-table-link>
     <eg-link-table-link i18n-label label="SMS Carriers"  
-      url="/eg/staff/admin/server/config/sms_carrier"></eg-link-table-link>
+      routerLink="/staff/admin/server/config/sms_carrier"></eg-link-table-link>
     <eg-link-table-link i18n-label label="User Activity Types"  
       url="/eg/staff/admin/server/config/usr_activity_type"></eg-link-table-link>
     <eg-link-table-link i18n-label label="User Setting Types"  
index 8409d23..bf2a988 100644 (file)
 
 <hr/>
 
-
-<eg-grid #btGrid idlClass="cbt" [dataSource]="dataSource" 
-    [isSortable]="true" persistKey="admin.server.config.billing_type">
-  <eg-grid-toolbar-button label="New Billing Type" i18n-label [action]="createBillingType">
-  </eg-grid-toolbar-button>
-  <eg-grid-toolbar-action label="Delete Selected" i18n-label [action]="deleteSelected">
-  </eg-grid-toolbar-action>
-</eg-grid>
-
-<eg-fm-record-editor #btEditDialog idlClass="cbt" requiredFields="name,org_unit">
-</eg-fm-record-editor>
-
-<ng-template #successStrTmpl i18n>Billing Type Update Succeeded</ng-template>
-<eg-string #successString [template]="successStrTmpl"></eg-string>
-
-<ng-template #createStrTmpl i18n>Billing Type Succeessfully Created</ng-template>
-<eg-string #createString [template]="createStrTmpl"></eg-string>
-
-
+<eg-admin-page #adminPage idlClass="cbt" [dataSource]="dataSource">
+</eg-admin-page>
index 00f2011..587526f 100644 (file)
@@ -1,14 +1,11 @@
 import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
 import {EgIdlObject} from '@eg/core/idl.service';
 import {EgGridDataSource} from '@eg/share/grid/grid';
-import {EgGridComponent} from '@eg/share/grid/grid.component';
-import {EgToastService} from '@eg/share/toast/toast.service';
 import {Pager} from '@eg/share/util/pager';
 import {EgPcrudService} from '@eg/core/pcrud.service';
 import {EgOrgService} from '@eg/core/org.service';
 import {EgAuthService} from '@eg/core/auth.service';
-import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
-import {EgStringComponent} from '@eg/share/string/string.component';
+import {EgAdminPageComponent} from '@eg/staff/share/admin-page/admin-page.component';
 
 @Component({
     templateUrl: './billing_type.component.html'
@@ -17,37 +14,32 @@ import {EgStringComponent} from '@eg/share/string/string.component';
 export class BillingTypeComponent implements OnInit {
 
     dataSource: EgGridDataSource;
-    @ViewChild('btGrid') btGrid: EgGridComponent;
-    @ViewChild('btEditDialog') btEditDialog: FmRecordEditorComponent;
-    @ViewChild('successString') successString: EgStringComponent;
-    @ViewChild('createString') createString: EgStringComponent;
     contextOrg: EgIdlObject;
-    createBillingType: () => void;
-    deleteSelected: (rows: any) => void;
+    @ViewChild('adminPage') adminPage: EgAdminPageComponent;
 
     constructor(
         private org: EgOrgService,
         private auth: EgAuthService,
-        private pcrud: EgPcrudService,
-        private toast: EgToastService
+        private pcrud: EgPcrudService
     ) {
         this.dataSource = new EgGridDataSource();
     }
 
     orgOnChange(org: EgIdlObject) {
         this.contextOrg = org;
-        this.btGrid.reload();
+        this.adminPage.grid.reload();
     }
 
     ngOnInit() {
         this.contextOrg = this.org.get(this.auth.user().ws_ou());
 
         this.dataSource.getRows = (pager: Pager, sort: any[]) => {
-            let searchOrgs = this.org.fullPath(this.contextOrg, true);
+            const searchOrgs = this.org.fullPath(this.contextOrg, true);
 
-            let orderBy = {};
-            if (sort.length)
-                orderBy = {cbt: sort[0].name + ' ' + sort[0].dir};
+            const orderBy = {cbt: 'name'};
+            if (sort.length) {
+                orderBy.cbt = sort[0].name + ' ' + sort[0].dir;
+            }
 
             return this.pcrud.search('cbt', {owner : searchOrgs}, {
                 offset: pager.offset,
@@ -55,42 +47,6 @@ export class BillingTypeComponent implements OnInit {
                 order_by: orderBy
             });
         }
-
-        this.btGrid.onRowActivate$.subscribe(
-            bt => {
-                this.btEditDialog.mode = 'update';
-                this.btEditDialog.recId = bt.id();
-                this.btEditDialog.open().then(
-                    ok => {
-                        this.successString.current()
-                            .then(str => this.toast.success(str));
-                        this.btGrid.reload();
-                    },
-                    err => { }
-                );
-            }
-        );
-
-        this.createBillingType = () => {
-            this.btEditDialog.mode = 'create';
-            this.btEditDialog.open().then(
-                ok => {
-                    this.createString.current()
-                        .then(str => this.toast.success(str));
-                    this.btGrid.reload();
-                },
-                err => { }
-            );
-        }
-
-        this.deleteSelected = (billingTypes) => {
-            billingTypes.forEach(bt => bt.isdeleted(true));
-            this.pcrud.autoApply(billingTypes).subscribe(
-                val => console.debug('deleted: ' + val),
-                err => {},
-                ()  => this.btGrid.reload()
-            );
-        }
     }
 }
 
index 0a2b455..1a322d4 100644 (file)
@@ -1,14 +1,18 @@
 import {NgModule} from '@angular/core';
 import {EgStaffCommonModule} from '@eg/staff/common.module';
 import {EgAdminServerConfigRoutingModule} from './routing.module';
-import {EgGridModule} from '@eg/share/grid/grid.module';
+import {EgAdminPageComponent} from '@eg/staff/share/admin-page/admin-page.component';
 import {BillingTypeComponent} from './billing_type.component';
 import {HardDueDateComponent} from './hard_due_date.component';
+import {SmsCarrierComponent} from './sms_carrier.component';
+import {EgGridModule} from '@eg/share/grid/grid.module';
 
 @NgModule({
   declarations: [
+      EgAdminPageComponent,
       BillingTypeComponent,
-      HardDueDateComponent
+      HardDueDateComponent,
+      SmsCarrierComponent
   ],
   imports: [
     EgStaffCommonModule,
index da10d0d..8eb19c4 100644 (file)
 
 <hr/>
 
-<eg-grid #hddGrid idlClass="chdd" [dataSource]="dataSource" 
-    [isSortable]="true" persistKey="admin.server.config.hard_due_date">
-  <eg-grid-toolbar-button label="New Hard Due Date" i18n-label [action]="createHardDueDate">
-  </eg-grid-toolbar-button>
-  <eg-grid-toolbar-action label="Delete Selected" i18n-label [action]="deleteSelected">
-  </eg-grid-toolbar-action>
-</eg-grid>
-
-<eg-fm-record-editor #hddEditDialog idlClass="chdd" requiredFields="name,org_unit">
-</eg-fm-record-editor>
-
-<ng-template #successStrTmpl i18n>Hard Due Date Update Succeeded</ng-template>
-<eg-string #successString [template]="successStrTmpl"></eg-string>
-
-<ng-template #createStrTmpl i18n>Hard Due Date Succeessfully Created</ng-template>
-<eg-string #createString [template]="createStrTmpl"></eg-string>
-
+<eg-admin-page #adminPage idlClass="chdd" [dataSource]="dataSource">
+</eg-admin-page>
 
index fdbf781..2d8463f 100644 (file)
@@ -1,14 +1,11 @@
 import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
 import {EgIdlObject} from '@eg/core/idl.service';
 import {EgGridDataSource} from '@eg/share/grid/grid';
-import {EgGridComponent} from '@eg/share/grid/grid.component';
-import {EgToastService} from '@eg/share/toast/toast.service';
 import {Pager} from '@eg/share/util/pager';
 import {EgPcrudService} from '@eg/core/pcrud.service';
 import {EgOrgService} from '@eg/core/org.service';
 import {EgAuthService} from '@eg/core/auth.service';
-import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
-import {EgStringComponent} from '@eg/share/string/string.component';
+import {EgAdminPageComponent} from '@eg/staff/share/admin-page/admin-page.component';
 
 @Component({
     templateUrl: './hard_due_date.component.html'
@@ -17,37 +14,32 @@ import {EgStringComponent} from '@eg/share/string/string.component';
 export class HardDueDateComponent implements OnInit {
 
     dataSource: EgGridDataSource;
-    @ViewChild('hddGrid') hddGrid: EgGridComponent;
-    @ViewChild('hddEditDialog') hddEditDialog: FmRecordEditorComponent;
-    @ViewChild('successString') successString: EgStringComponent;
-    @ViewChild('createString') createString: EgStringComponent;
     contextOrg: EgIdlObject;
-    createHardDueDate: () => void;
-    deleteSelected: (rows: any) => void;
+    @ViewChild('adminPage') adminPage: EgAdminPageComponent;
 
     constructor(
         private org: EgOrgService,
         private auth: EgAuthService,
-        private pcrud: EgPcrudService,
-        private toast: EgToastService
+        private pcrud: EgPcrudService
     ) {
         this.dataSource = new EgGridDataSource();
     }
 
     orgOnChange(org: EgIdlObject) {
         this.contextOrg = org;
-        this.hddGrid.reload();
+        this.adminPage.grid.reload();
     }
 
     ngOnInit() {
         this.contextOrg = this.org.get(this.auth.user().ws_ou());
 
         this.dataSource.getRows = (pager: Pager, sort: any[]) => {
-            let searchOrgs = this.org.fullPath(this.contextOrg, true);
+            const searchOrgs = this.org.fullPath(this.contextOrg, true);
 
-            let orderBy = {};
-            if (sort.length)
-                orderBy = {chdd: sort[0].name + ' ' + sort[0].dir};
+            const orderBy = {chdd: 'name'};
+            if (sort.length) {
+                orderBy.chdd = sort[0].name + ' ' + sort[0].dir;
+            }
 
             return this.pcrud.search('chdd', {owner : searchOrgs}, {
                 offset: pager.offset,
@@ -55,42 +47,6 @@ export class HardDueDateComponent implements OnInit {
                 order_by: orderBy
             });
         }
-
-        this.hddGrid.onRowActivate$.subscribe(
-            bt => {
-                this.hddEditDialog.mode = 'update';
-                this.hddEditDialog.recId = bt.id();
-                this.hddEditDialog.open().then(
-                    ok => {
-                        this.successString.current()
-                            .then(str => this.toast.success(str));
-                        this.hddGrid.reload();
-                    },
-                    err => { }
-                );
-            }
-        );
-
-        this.createHardDueDate = () => {
-            this.hddEditDialog.mode = 'create';
-            this.hddEditDialog.open().then(
-                ok => {
-                    this.createString.current()
-                        .then(str => this.toast.success(str));
-                    this.hddGrid.reload();
-                },
-                err => { }
-            );
-        }
-
-        this.deleteSelected = (hardDueDates) => {
-            hardDueDates.forEach(hdd => hdd.isdeleted(true));
-            this.pcrud.autoApply(hardDueDates).subscribe(
-                val => console.debug('deleted: ' + val),
-                err => {},
-                ()  => this.hddGrid.reload()
-            );
-        }
     }
 }
 
index 23e485e..64dc8b6 100644 (file)
@@ -1,7 +1,8 @@
-import {NgModule}             from '@angular/core';
+import {NgModule} from '@angular/core';
 import {RouterModule, Routes} from '@angular/router';
 import {BillingTypeComponent} from './billing_type.component';
 import {HardDueDateComponent} from './hard_due_date.component';
+import {SmsCarrierComponent} from './sms_carrier.component';
 
 const routes: Routes = [{
   path: 'billing_type',
@@ -9,6 +10,9 @@ const routes: Routes = [{
 }, {
   path: 'hard_due_date',
   component: HardDueDateComponent
+}, {
+  path: 'sms_carrier',
+  component: SmsCarrierComponent
 }];
 
 @NgModule({
diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/config/sms_carrier.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/config/sms_carrier.component.ts
new file mode 100644 (file)
index 0000000..d0ea6ad
--- /dev/null
@@ -0,0 +1,14 @@
+import {Component, OnInit} from '@angular/core';
+
+@Component({
+    template: `
+      <eg-staff-banner bannerText="SMS Carrier Configuration" i18n-bannerText>
+      </eg-staff-banner>
+      <eg-admin-page idlClass="csc" sortField="name">
+      </eg-admin-page>
+    `
+})
+
+export class SmsCarrierComponent {}
+
+
index 92f3d0a..3b6578f 100644 (file)
@@ -34,7 +34,7 @@ const routes: Routes = [{
     loadChildren : '@eg/staff/sandbox/sandbox.module#EgSandboxModule'
   }, {
     path: 'admin',
-    loadChildren : '@eg/staff/admin/routing.module#EgAdminRoutingModule'
+    loadChildren : '@eg/staff/admin/admin.module#EgAdminModule'
   }]
 }];
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html
new file mode 100644 (file)
index 0000000..b0b0012
--- /dev/null
@@ -0,0 +1,18 @@
+<ng-template #successStrTmpl i18n>{{idlClassDef.label}} Update Succeeded</ng-template>
+<eg-string #successString [template]="successStrTmpl"></eg-string>
+
+<ng-template #createStrTmpl i18n>{{idlClassDef.label}} Succeessfully Created</ng-template>
+<eg-string #createString [template]="createStrTmpl"></eg-string>
+
+<eg-grid #grid idlClass="{{idlClass}}" [dataSource]="dataSource" 
+    [isSortable]="true" persistKey="{{persistKey}}">
+  <eg-grid-toolbar-button label="New {{idlClassDef.label}}" i18n-label [action]="createNew">
+  </eg-grid-toolbar-button>
+  <eg-grid-toolbar-action label="Delete Selected" i18n-label [action]="deleteSelected">
+  </eg-grid-toolbar-action>
+</eg-grid>
+
+<eg-fm-record-editor #editDialog idlClass="{{idlClass}}">
+</eg-fm-record-editor>
+
+
diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
new file mode 100644 (file)
index 0000000..3554834
--- /dev/null
@@ -0,0 +1,124 @@
+import {Component, Input, OnInit, TemplateRef, ViewChild} from '@angular/core';
+import {EgIdlService, EgIdlObject} from '@eg/core/idl.service';
+import {EgGridDataSource} from '@eg/share/grid/grid';
+import {EgGridComponent} from '@eg/share/grid/grid.component';
+import {EgToastService} from '@eg/share/toast/toast.service';
+import {Pager} from '@eg/share/util/pager';
+import {EgPcrudService} from '@eg/core/pcrud.service';
+import {EgOrgService} from '@eg/core/org.service';
+import {EgAuthService} from '@eg/core/auth.service';
+import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {EgStringComponent} from '@eg/share/string/string.component';
+
+/**
+ * General purpose CRUD interface for IDL objects
+ *
+ * Object types using this component must be editable via PCRUD.
+ */
+
+@Component({
+    selector: 'eg-admin-page',
+    templateUrl: './admin-page.component.html'
+})
+
+export class EgAdminPageComponent implements OnInit {
+
+    @Input() idlClass: string;
+
+    // Default sort field, used when no grid sorting is applied.
+    @Input() sortField: string;
+
+    // Data source may be provided by the caller.  This gives the caller
+    // complete control over the contents of the grid.  If no data source
+    // is provided, a generic one is create which is sufficient for data
+    // that requires no special handling, filtering, etc.
+    @Input() dataSource: EgGridDataSource;
+
+    @ViewChild('grid') grid: EgGridComponent;
+    @ViewChild('editDialog') editDialog: FmRecordEditorComponent;
+    @ViewChild('successString') successString: EgStringComponent;
+    @ViewChild('createString') createString: EgStringComponent;
+
+    persistKey: string;
+    idlClassDef: any;
+    pkeyField: string;
+    createNew: () => void;
+    deleteSelected: (rows: EgIdlObject[]) => void;
+
+    constructor(
+        private idl: EgIdlService,
+        private org: EgOrgService,
+        private auth: EgAuthService,
+        private pcrud: EgPcrudService,
+        private toast: EgToastService
+    ) {}
+
+    ngOnInit() {
+        this.idlClassDef = this.idl.classes[this.idlClass];
+        this.pkeyField = this.idlClassDef.pkey || 'id';
+        this.persistKey = 'admin.' + this.idlClassDef.table;
+
+        // If the caller provides not data source, create a generic one.
+        if (!this.dataSource) {
+            this.initDataSource();
+        }
+
+        this.grid.onRowActivate$.subscribe(
+            (idlThing: EgIdlObject) => {
+                this.editDialog.mode = 'update';
+                this.editDialog.recId = idlThing[this.pkeyField]();
+                this.editDialog.open().then(
+                    ok => {
+                        this.successString.current()
+                            .then(str => this.toast.success(str));
+                        this.grid.reload();
+                    },
+                    err => {}
+                );
+            }
+        );
+
+        this.createNew = () => {
+            this.editDialog.mode = 'create';
+            this.editDialog.open().then(
+                ok => {
+                    this.createString.current()
+                        .then(str => this.toast.success(str));
+                    this.grid.reload();
+                },
+                err => {}
+            );
+        }
+
+        this.deleteSelected = (idlThings: EgIdlObject[]) => {
+            idlThings.forEach(idlThing => idlThing.isdeleted(true));
+            this.pcrud.autoApply(idlThings).subscribe(
+                val => console.debug('deleted: ' + val),
+                err => {},
+                ()  => this.grid.reload()
+            );
+        }
+    }
+
+    initDataSource() {
+        this.dataSource = new EgGridDataSource();
+
+        this.dataSource.getRows = (pager: Pager, sort: any[]) => {
+
+            const orderBy: any = {};
+            if (sort.length) {
+                orderBy[this.idlClass] = sort[0].name + ' ' + sort[0].dir;
+            } else if (this.sortField) {
+                orderBy[this.idlClass] = this.sortField;
+            }
+
+            return this.pcrud.retrieveAll(this.idlClass, {
+                offset: pager.offset,
+                limit: pager.limit,
+                order_by: orderBy
+            });
+        }
+    }
+}
+
+