LP#626157 Ang2 experiments
authorBill Erickson <berickxx@gmail.com>
Sun, 10 Dec 2017 22:31:24 +0000 (17:31 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 11 Dec 2017 17:39:51 +0000 (12:39 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/webby-src/src/app/core/org.ts
Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.html
Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.ts
Open-ILS/webby-src/src/app/staff/catalog/search-form.component.html
Open-ILS/webby-src/src/app/staff/share/org-select.component.ts

index 236a368..44eddd6 100644 (file)
@@ -5,6 +5,12 @@ import {EgPcrudService} from './pcrud';
 
 type EgOrgNodeOrId = number | EgIdlObject;
 
+interface OrgFilter {
+    canHaveUsers?: boolean;
+    canHaveVolumes?: boolean;
+    opacVisible?: boolean;
+}
+
 @Injectable()
 export class EgOrgService {
 
@@ -26,6 +32,33 @@ export class EgOrgService {
         return this.orgList;
     };
 
+    /**
+     * Returns a list of org units that match the selected criteria.
+     * Unset filter options are ignored.
+     */
+    filterList(filter: OrgFilter, asId: boolean): any[] {
+        let list = [];
+        this.list().forEach(org => {
+
+            let chu = filter.canHaveUsers;
+            if (chu && !this.canHaveUsers(org)) return;
+            if (chu === false && this.canHaveUsers(org)) return;
+
+            let chv = filter.canHaveVolumes;
+            if (chv && !this.canHaveVolumes(org)) return;
+            if (chv === false && this.canHaveVolumes(org)) return;
+
+            let ov = filter.opacVisible;
+            if (ov && !this.opacVisible(org)) return;
+            if (ov === false && this.opacVisible(org)) return;
+
+            // All filter tests passed.  Add it to the list
+            list.push(asId ? org.id() : org);
+        });
+
+        return list;
+    }
+
     tree(): EgIdlObject {
         return this.orgTree;
     }
@@ -36,19 +69,18 @@ export class EgOrgService {
     }
 
     // list of org_unit objects or IDs for ancestors + me
-    ancestors(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] {
+    ancestors(nodeOrId: EgOrgNodeOrId, asId?: boolean): any[] {
         let node = this.get(nodeOrId);
         if (!node) return [];
         let nodes = [node];
         while( (node = this.get(node.parent_ou())))
             nodes.push(node);
-        if (asId) 
-            return nodes.map(function(n){return n.id()});
+        if (asId) return nodes.map(n => n.id());
         return nodes;
     };
 
     // tests that a node can have users
-    canHaveUsers(nodeOrId): Boolean {
+    canHaveUsers(nodeOrId): boolean {
            return this
             .get(nodeOrId)
             .ou_type()
@@ -56,15 +88,19 @@ export class EgOrgService {
     }
 
     // tests that a node can have volumes
-    canHaveVolumes(nodeOrId): Boolean {
+    canHaveVolumes(nodeOrId): boolean {
         return this
             .get(nodeOrId)
             .ou_type()
             .can_have_vols() == 't';
     }
 
+    opacVisible(nodeOrId): boolean {
+        return this.get(nodeOrId).opac_visible() == 't';
+    }
+
     // list of org_unit objects  or IDs for me + descendants
-    descendants(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] {
+    descendants(nodeOrId: EgOrgNodeOrId, asId?: boolean): any[] {
         let node = this.get(nodeOrId);
         if (!node) return [];
         let nodes = [];
@@ -79,7 +115,7 @@ export class EgOrgService {
     }
 
     // list of org_unit objects or IDs for ancestors + me + descendants
-    fullPath(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] {
+    fullPath(nodeOrId: EgOrgNodeOrId, asId?: boolean): any[] {
         let list = this.ancestors(nodeOrId, false).concat(
           this.descendants(nodeOrId, false).slice(1));
         if (asId) 
index c5ec3fd..5b95268 100644 (file)
@@ -13,9 +13,9 @@
     <div class="row mt-2">
       <div class="col-2">
         <eg-org-select 
-          [onChange]="orgOnChange"
-          [shouldHide]="shouldHideOrg"
-          [shouldDisable]="shouldDisableOrg"
+          (onChange)="orgOnChange"
+          [hideOrgs]="hideOrgs"
+          [disableOrgs]="disableOrgs"
           [initialOrg]="initialOrg"
           [placeholder]="'Owner'" >
         </eg-org-select>
index 27574b3..0006a1b 100644 (file)
@@ -24,18 +24,10 @@ export class EgWorkstationsComponent implements OnInit {
     newOwner: EgIdlObject;
     newName: String;
 
-    //initialOrg: EgIdlObject; // XXX testing
-
-    // Org selector callbacks
-    shouldDisableOrg = (org: EgIdlObject): boolean => {
-        // TODO: check register perms too
-        return !this.org.canHaveUsers(org);
-    }
-
-    shouldHideOrg = (org: EgIdlObject): boolean => {
-        return org.id() == 1; // XXX TESTING
-    }
 
+    // Org selector options.
+    hideOrgs: number[];
+    disableOrgs: number[];
     orgOnChange = (org: EgIdlObject): void => {
         this.newOwner = org;
     }
@@ -52,7 +44,8 @@ export class EgWorkstationsComponent implements OnInit {
         this.store.getItem('eg.workstation.all')
         .then(res => this.workstations = res);
 
-        // this.initialOrg = this.org.root().children()[0];
+        // TODO: perm limits required here too
+        this.disableOrgs = this.org.filterList({canHaveUsers : true}, true);
     }
 
     selected(): Workstation {
index 6955f28..3ee4d21 100644 (file)
@@ -94,7 +94,7 @@ TODO focus search input
     <div class="col-9 d-flex flex-row">
       <div class="flex-1">
         <eg-org-select 
-          [onChange]="orgOnChange"
+          (onChange)="orgOnChange($event)"
           [initialOrg]="searchContext.searchOrg"
           [placeholder]="'Library'" >
         </eg-org-select>
index d16d7b0..7738215 100644 (file)
@@ -1,4 +1,4 @@
-import {Component, OnInit, Input} from '@angular/core';
+import {Component, OnInit, Input, Output, EventEmitter} from '@angular/core';
 import {Observable} from 'rxjs/Observable';
 import {map, debounceTime} from 'rxjs/operators';
 import {EgAuthService} from '@eg/core/auth';
@@ -24,19 +24,31 @@ interface OrgDisplay {
 export class EgOrgSelectComponent implements OnInit {
 
     selected: OrgDisplay;
+    startOrg: EgIdlObject;
+    hidden: number[] = [];
+    disabled: number[] = [];
 
     // Read-only properties optionally provided by the calling component.
     @Input() placeholder: string;
-    @Input() initialOrg: EgIdlObject;
     @Input() stickySetting: string;
     @Input() displayField: string = 'shortname';
 
-    // Call-backs
-    // Note: onChange could be handled via an EventEmitter, but
-    // should* functions require real time two-way communication.
-    @Input() onChange: (org:EgIdlObject) => void;
-    @Input() shouldDisable: (org:EgIdlObject) => boolean;
-    @Input() shouldHide: (org:EgIdlObject) => boolean;
+    @Input() set initialOrg(org: EgIdlObject) {
+        if (org) this.startOrg = org;
+    }
+
+    @Input() set hideOrgs(ids: number[]) {
+        if (ids) this.hidden = ids;
+    }
+
+    @Input() set disableOrgs(ids: number[]) {
+        if (ids) this.disabled = ids;
+    }
+
+    /** Emitted when the org unit value is changed via the selector.
+      * Does not fire on initialOrg.
+      */
+    @Output() onChange = new EventEmitter<EgIdlObject>();
 
     constructor(
       private auth: EgAuthService,
@@ -45,8 +57,8 @@ export class EgOrgSelectComponent implements OnInit {
     ) {}
     
     ngOnInit() {
-        if (this.initialOrg) {
-            this.selected = this.formatForDisplay(this.initialOrg);
+        if (this.startOrg) {
+            this.selected = this.formatForDisplay(this.startOrg);
         }
     }
 
@@ -60,9 +72,7 @@ export class EgOrgSelectComponent implements OnInit {
     }
 
     orgChanged(selEvent: NgbTypeaheadSelectItemEvent) {
-        if (this.onChange) {
-            this.onChange(this.org.get(selEvent.item.id));
-        }
+        this.onChange.emit(this.org.get(selEvent.item.id));
     }
 
     // Formats the selected value
@@ -80,11 +90,11 @@ export class EgOrgSelectComponent implements OnInit {
                     return org[this.displayField]()
                       .toLowerCase().indexOf(term.toLowerCase()) > -1
 
-                }).filter(org => {
-                    // Exclude hidden orgs
-                    return !this.shouldHide || !this.shouldHide(org)
+                }).filter(org => { // Exclude hidden orgs
+                    return this.hidden.filter(
+                        id => {return org.id() == id}).length == 0;
 
-                }).map(org => { return this.formatForDisplay(org) })
+                }).map(org => {return this.formatForDisplay(org)})
             });
     }
 }