contact addresses
authorMike Rylander <mrylander@gmail.com>
Wed, 1 Apr 2020 16:32:26 +0000 (12:32 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Wed, 1 Apr 2020 18:01:44 +0000 (14:01 -0400)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/eg2/src/app/staff/acq/provider/acq-provider.module.ts
Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contacts.component.html
Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contacts.component.ts
Open-ILS/src/eg2/src/app/staff/acq/provider/provider-record.service.ts

index 4ff63ac..437f828 100644 (file)
@@ -8968,8 +8968,10 @@ SELECT  usr,
                        <field reporter:label="Role" name="role" reporter:datatype="text"/>
                        <field reporter:label="Email" name="email" reporter:datatype="text"/>
                        <field reporter:label="Phone" name="phone" reporter:datatype="text"/>
+                       <field reporter:label="Addresses" name="addresses" oils_persist:virtual="true" reporter:datatype="link"/>
         </fields>
                <links>
+                       <link field="addresses" reltype="has_many" key="contact" map="" class="acqpca"/>
                        <link field="provider" reltype="has_a" key="id" map="" class="acqpro"/>
                </links>
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
index 01fca1d..fe1a25c 100644 (file)
@@ -8,6 +8,7 @@ import {ProviderResultsComponent} from './provider-results.component';
 import {ProviderDetailsComponent} from './provider-details.component';
 import {ProviderAddressesComponent} from './provider-addresses.component';
 import {ProviderContactsComponent} from './provider-contacts.component';
+import {ProviderContactAddressesComponent} from './provider-contact-addresses.component';
 import {ProviderHoldingsComponent} from './provider-holdings.component';
 import {ProviderAttributesComponent} from './provider-attributes.component';
 import {ProviderInvoicesComponent} from './provider-invoices.component';
@@ -25,6 +26,7 @@ import {ProviderRecordService} from './provider-record.service';
     ProviderDetailsComponent,
     ProviderAddressesComponent,
     ProviderContactsComponent,
+    ProviderContactAddressesComponent,
     ProviderHoldingsComponent,
     ProviderAttributesComponent,
     ProviderInvoicesComponent,
diff --git a/Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.html b/Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.html
new file mode 100644 (file)
index 0000000..cbfd8d3
--- /dev/null
@@ -0,0 +1,28 @@
+<eg-string #createString i18n-text text="New Contact Address Added"></eg-string>
+<eg-string #createErrString i18n-text text="Failed to Create New Contact Address"></eg-string>
+<eg-string #successString i18n-text text="Contact Address Update Succeeded"></eg-string>
+<eg-string #updateFailedString i18n-text text="Contact Address Update Failed"></eg-string>
+<eg-string #deleteFailedString i18n-text text="Delete of Contact Address failed or was not allowed"></eg-string>
+<eg-string #deleteSuccessString i18n-text text="Delete of Contact Address succeeded"></eg-string>
+
+<eg-grid #acqProviderContactAddressesGrid
+  persistKey="acq.provider.contact.addresses.grid"
+  idlClass="acqpca" [dataSource]="gridSource"
+  [sortable]="true"
+  hideFields="contact"
+  [cellTextGenerator]="cellTextGenerator">
+    <eg-grid-toolbar-button 
+      label="New Contact Address" i18n-label (onClick)="createNew()">
+    </eg-grid-toolbar-button>
+    <eg-grid-toolbar-action label="Edit Selected" i18n-label (onClick)="editSelected($event)">
+    </eg-grid-toolbar-action>
+    <eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)">
+    </eg-grid-toolbar-action>
+</eg-grid>
+
+<eg-fm-record-editor #editDialog
+  idlClass="acqpca"
+  readonlyFields="id,contact"
+  fieldOrder="id,valid,address_type,contact,street1,street2,city,county,state,country,post_code,fax_phone">
+</eg-fm-record-editor>
+
diff --git a/Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.ts b/Open-ILS/src/eg2/src/app/staff/acq/provider/provider-contact-addresses.component.ts
new file mode 100644 (file)
index 0000000..e4cb436
--- /dev/null
@@ -0,0 +1,180 @@
+import {Component, OnInit, AfterViewInit, Input, ViewChild} from '@angular/core';
+import {empty, throwError, Observable, from} from 'rxjs';
+import {map} from 'rxjs/operators';
+import {Router, ActivatedRoute, ParamMap} from '@angular/router';
+import {Pager} from '@eg/share/util/pager';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {NetService} from '@eg/core/net.service';
+import {AuthService} from '@eg/core/auth.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {GridComponent} from '@eg/share/grid/grid.component';
+import {GridDataSource, GridCellTextGenerator} from '@eg/share/grid/grid';
+import {ProviderRecord, ProviderRecordService} from './provider-record.service';
+import {AcqProviderSearchFormComponent} from './acq-provider-search-form.component';
+import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {StringComponent} from '@eg/share/string/string.component';
+import {ToastService} from '@eg/share/toast/toast.service';
+
+@Component({
+  selector: 'eg-provider-contact-addresses',
+  templateUrl: 'provider-contact-addresses.component.html',
+})
+export class ProviderContactAddressesComponent implements OnInit, AfterViewInit {
+
+    addresses: any[] = [];
+
+    gridSource: GridDataSource;
+    @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
+    @ViewChild('acqProviderContactAddressesGrid', { static: true }) providerContactAddressesGrid: GridComponent;
+    @ViewChild('successString', { static: true }) successString: StringComponent;
+    @ViewChild('createString', { static: false }) createString: StringComponent;
+    @ViewChild('createErrString', { static: false }) createErrString: StringComponent;
+    @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent;
+    @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent;
+    @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent;
+
+    cellTextGenerator: GridCellTextGenerator;
+
+    canCreate: boolean;
+    canDelete: boolean;
+    deleteSelected: (rows: IdlObject[]) => void;
+    reloadGrid: () => void;
+
+    permissions: {[name: string]: boolean};
+
+    // Size of create/edito dialog.  Uses large by default.
+    @Input() dialogSize: 'sm' | 'lg' = 'lg';
+    @Input() contact: IdlObject;
+
+    constructor(
+        private router: Router,
+        private route: ActivatedRoute,
+        private net: NetService,
+        private idl: IdlService,
+        private auth: AuthService,
+        private providerRecord: ProviderRecordService,
+        private toast: ToastService,
+        private pcrud: PcrudService) {
+    }
+
+    ngOnInit() {
+        this.gridSource = this.getDataSource()
+        this.cellTextGenerator = {};
+        this.reloadGrid = () => this.providerContactAddressesGrid.reload();
+        this.deleteSelected = (idlThings: IdlObject[]) => {
+            idlThings.forEach(idlThing => idlThing.isdeleted(true));
+            this.pcrud.autoApply(idlThings).subscribe(
+                val => {
+                    console.debug('deleted: ' + val);
+                    this.deleteSuccessString.current()
+                        .then(str => this.toast.success(str));
+                },
+                err => {
+                    this.deleteFailedString.current()
+                        .then(str => this.toast.danger(str));
+                },
+                ()  => {
+                    this.providerRecord.refreshCurrent().then(
+                        () => this.providerContactAddressesGrid.reload()
+                    );
+                }
+            );
+        };
+        this.providerContactAddressesGrid.onRowActivate.subscribe(
+            (idlThing: IdlObject) => this.showEditDialog(idlThing)
+        );
+    }
+
+
+    ngAfterViewInit() {
+        console.log('this.contact',this.contact);
+    }
+
+    getDataSource(): GridDataSource {
+        const gridSource = new GridDataSource();
+
+        gridSource.getRows = (pager: Pager, sort: any[]) => {
+            if (!this.contact) {
+                return empty();
+            }
+            let addresses = this.contact.addresses()
+
+            if (sort.length > 0) {
+                addresses = addresses.sort((a, b) => {
+                    for (let i = 0; i < sort.length; i++) {
+                        let lt = -1;
+                        let sfield = sort[i].name;
+                        if (sort[i].dir.substring(0,1).toLowerCase() === 'd') {
+                            lt *= -1;
+                        }
+                        if (a[sfield]() < b[sfield]()) { return lt }
+                        if (a[sfield]() > b[sfield]()) { return lt * -1 }
+                    }
+                    return 0;
+                });
+
+            }
+
+            return from(addresses.slice(pager.offset, pager.offset + pager.limit - 1));
+        };
+        return gridSource;
+    }
+
+    showEditDialog(providerContactAddress: IdlObject): Promise<any> {
+        this.editDialog.mode = 'update';
+        this.editDialog.recordId = providerContactAddress['id']();
+        return new Promise((resolve, reject) => {
+            this.editDialog.open({size: this.dialogSize}).subscribe(
+                result => {
+                    this.successString.current()
+                        .then(str => this.toast.success(str));
+                    this.providerRecord.refreshCurrent().then(
+                        () => this.providerContactAddressesGrid.reload()
+                    );
+                    resolve(result);
+                },
+                error => {
+                    this.updateFailedString.current()
+                        .then(str => this.toast.danger(str));
+                    reject(error);
+                }
+            );
+        });
+    }
+
+    editSelected(providerContactAddressFields: IdlObject[]) {
+        // Edit each IDL thing one at a time
+        const editOneThing = (providerContactAddress: IdlObject) => {
+            if (!providerContactAddress) { return; }
+
+            this.showEditDialog(providerContactAddress).then(
+                () => editOneThing(providerContactAddressFields.shift()));
+        };
+
+        editOneThing(providerContactAddressFields.shift());
+    }
+
+    createNew() {
+        this.editDialog.mode = 'create';
+        const address = this.idl.create('acqpca');
+        address.contact(this.contact.id());
+        address.valid(true);
+        this.editDialog.record = address;
+        this.editDialog.recordId = null;
+        this.editDialog.open({size: this.dialogSize}).subscribe(
+            ok => {
+                this.createString.current()
+                    .then(str => this.toast.success(str));
+                this.providerRecord.refreshCurrent().then(
+                    () => this.providerContactAddressesGrid.reload()
+                );
+            },
+            rejection => {
+                if (!rejection.dismissed) {
+                    this.createErrString.current()
+                        .then(str => this.toast.danger(str));
+                }
+            }
+        );
+    }
+}
index fc0f733..bc7987b 100644 (file)
@@ -18,6 +18,7 @@
   persistKey="acq.provider.contacts.grid"
   idlClass="acqpc" [dataSource]="gridSource"
   [sortable]="true"
+  [disableMultiSelect]="true"
   hideFields="provider"
   [cellTextGenerator]="cellTextGenerator">
 
   <eg-grid-column path="phone" [cellTemplate]="phoneTmpl" [disableTooltip]="true"></eg-grid-column>
 </eg-grid>
 
+<ng-container *ngIf="selectedContact">
+  <hr><h3 i18n>Addresses for: {{selectedContact.name()}}</h3>
+  <eg-provider-contact-addresses
+    #providerContactAddresses
+    [contact]="selectedContact">
+  </eg-provider-contact-addresses>
+</ng-container>
+
 <eg-fm-record-editor #editDialog
   idlClass="acqpc"
   readonlyFields="id,provider"
index 238bafe..83bcd6c 100644 (file)
@@ -9,6 +9,7 @@ import {AuthService} from '@eg/core/auth.service';
 import {GridComponent} from '@eg/share/grid/grid.component';
 import {GridDataSource, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {ProviderRecordService} from './provider-record.service';
+import {ProviderContactAddressesComponent} from './provider-contact-addresses.component';
 import {AcqProviderSearchFormComponent} from './acq-provider-search-form.component';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {StringComponent} from '@eg/share/string/string.component';
@@ -26,6 +27,7 @@ export class ProviderContactsComponent implements OnInit, AfterViewInit {
 
     gridSource: GridDataSource;
     @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
+    @ViewChild('providerContactAddresses', { static: true }) providerContactAddresses: ProviderContactAddressesComponent;
     @ViewChild('acqProviderContactsGrid', { static: true }) providerContactsGrid: GridComponent;
     @ViewChild('successString', { static: true }) successString: StringComponent;
     @ViewChild('createString', { static: false }) createString: StringComponent;
@@ -36,6 +38,7 @@ export class ProviderContactsComponent implements OnInit, AfterViewInit {
 
     cellTextGenerator: GridCellTextGenerator;
     provider: IdlObject;
+    selectedContact: IdlObject;
 
     canCreate: boolean;
     canDelete: boolean;
@@ -86,6 +89,14 @@ export class ProviderContactsComponent implements OnInit, AfterViewInit {
 
     ngAfterViewInit() {
         console.log('this.providerRecord',this.providerRecord);
+        console.log('this.providerContactAddresses',this.providerContactAddresses);
+        this.providerContactsGrid.onRowClick.subscribe(
+            (idlThing: IdlObject) => {
+                this.selectedContact = idlThing;
+                console.debug('selected contact',this.selectedContact);
+                this.providerContactAddresses.reloadGrid();
+            }
+        );
     }
 
     getDataSource(): GridDataSource {
index a0886cb..bf97196 100644 (file)
@@ -41,7 +41,7 @@ export class ProviderRecordService {
                 flesh: 3,
                 flesh_fields: { acqpro:  ['attributes','holdings_subfields', 'contacts', 'addresses', 'provider_notes'],
                                 acqpa:   ['provider'],
-                                acqpc:   ['provider'],
+                                acqpc:   ['provider','addresses'],
                                 acqphsm: ['provider'],
                                 acqlipad:['provider'],
                               }