[open-ils-commits] [GIT] Evergreen ILS branch master updated. a068f53292d2c31fb3a102e12f8aeaacdabdd276

Evergreen Git git at git.evergreen-ils.org
Sun Jul 19 12:23:26 EDT 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  a068f53292d2c31fb3a102e12f8aeaacdabdd276 (commit)
       via  83588f6da7ae99489803d756749e777909db75d9 (commit)
      from  145f3da58aef1ef4163c29cd9d56a13146145090 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a068f53292d2c31fb3a102e12f8aeaacdabdd276
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed May 20 16:36:23 2020 -0400

    LP1850555 Item location selector improvements
    
    * Ensure that the desired location is always available in the selector
      regardless of whether the staff have permission to use the location.
    
    * Display org unit short name for selected locations simimilar to how
      they are displayed in the selector dropdown.
    
    * Adds an <Unset> option in cases where the new 'required' flag is set
      to false.  This explicitly makes it possible for staff to clear the
      value.
    
    * Gracefully handle cases where locations from no org units are eligible
      for display.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
index b5ad4da982..99bd3906f9 100644
--- a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
+++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
@@ -1,12 +1,16 @@
 
 <ng-template #displayTemplate let-r="result" i18n>
-  {{r.label}} ({{orgName(r.userdata.owning_lib())}})
+  {{r.label}} <ng-container *ngIf="r.userdata">
+    ({{orgName(r.userdata.owning_lib())}})</ng-container>
 </ng-template>
 
+<eg-string #unsetString text="<Unset>" i18n-text></eg-string>
+
 <eg-combobox #comboBox
   [startId]="startId"
   [displayTemplate]="displayTemplate"
   (onChange)="cboxChanged($event)"
+  [required]="required"
   (blur)="propagateTouch()"
   placeholder="Shelving Location..."
   i18n-placeholder>
diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
index 082aa80ccf..2f41a1080b 100644
--- a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
+++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
@@ -1,4 +1,5 @@
-import {Component, OnInit, Input, Output, ViewChild, EventEmitter, forwardRef} from '@angular/core';
+import {Component, OnInit, AfterViewInit, Input, Output, ViewChild,
+    EventEmitter, forwardRef} from '@angular/core';
 import {ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {Observable} from 'rxjs';
 import {map} from 'rxjs/operators';
@@ -8,6 +9,7 @@ import {AuthService} from '@eg/core/auth.service';
 import {PermService} from '@eg/core/perm.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {StringComponent} from '@eg/share/string/string.component';
 
 /**
  * Item (Copy) Location Selector.
@@ -26,7 +28,8 @@ import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.comp
       multi: true
   }]
 })
-export class ItemLocationSelectComponent implements OnInit, ControlValueAccessor {
+export class ItemLocationSelectComponent
+    implements OnInit, AfterViewInit, ControlValueAccessor {
 
     // Limit copy locations to those owned at or above org units where
     // the user has work permissions for the provided permission code.
@@ -40,12 +43,16 @@ export class ItemLocationSelectComponent implements OnInit, ControlValueAccessor
     // Emits an acpl object or null on combobox value change
     @Output() valueChange: EventEmitter<IdlObject>;
 
+    @Input() required: boolean;
+
     @ViewChild('comboBox', {static: false}) comboBox: ComboboxComponent;
+    @ViewChild('unsetString', {static: false}) unsetString: StringComponent;
 
     startId: number = null;
-    filterOrgs: number[];
+    filterOrgs: number[] = [];
     cache: {[id: number]: IdlObject} = {};
 
+    initDone = false; // true after first data load
     propagateChange = (id: number) => {};
     propagateTouch = () => {};
 
@@ -59,12 +66,51 @@ export class ItemLocationSelectComponent implements OnInit, ControlValueAccessor
     }
 
     ngOnInit() {
-        this.setFilterOrgs().then(_ => this.getLocations());
+        this.setFilterOrgs()
+        .then(_ => this.getLocations())
+        .then(_ => this.initDone = true);
+    }
+
+    ngAfterViewInit() {
+
+        // Format the display of locations to include the org unit
+        this.comboBox.formatDisplayString = (result: ComboboxEntry) => {
+            let display = result.label || result.id;
+            display = (display + '').trim();
+            if (result.userdata) {
+                display += ' (' +
+                    this.orgName(result.userdata.owning_lib()) + ')';
+            }
+            return display;
+        };
     }
 
     getLocations(): Promise<any> {
+
+        if (this.filterOrgs.length === 0) {
+            this.comboBox.entries = [];
+            return Promise.resolve();
+        }
+
+        const search: any = {deleted: 'f'};
+
+        if (this.startId) {
+            // Guarantee we have the load-time copy location, which
+            // may not be included in the org-scoped set of locations
+            // we fetch by default.
+            search['-or'] = [
+                {id: this.startId},
+                {owning_lib: this.filterOrgs}
+            ];
+        } else {
+            search.owning_lib = this.filterOrgs;
+        }
+
         const entries: ComboboxEntry[] = [];
-        const search = {owning_lib: this.filterOrgs, deleted: 'f'};
+
+        if (!this.required) {
+            entries.push({id: null, label: this.unsetString.text});
+        }
 
         return this.pcrud.search('acpl', search, {order_by: {acpl: 'name'}}
         ).pipe(map(loc => {
@@ -90,13 +136,24 @@ export class ItemLocationSelectComponent implements OnInit, ControlValueAccessor
     }
 
     writeValue(id: number) {
-        if (this.comboBox) { // May not yet be initialized
-            this.comboBox.selectedId = id;
-        } else if (id) {
+        if (this.initDone) {
+            this.getOneLocation(id).then(_ => this.comboBox.selectedId = id);
+        } else {
             this.startId = id;
         }
     }
 
+    getOneLocation(id: number) {
+        if (!id || this.cache[id]) { return Promise.resolve(); }
+
+        return this.pcrud.retrieve('acpl', id).toPromise()
+        .then(loc => {
+            this.cache[loc.id()] = loc;
+            this.comboBox.entries.push(
+                {id: loc.id(), label: loc.name(), userdata: loc});
+        });
+    }
+
     setFilterOrgs(): Promise<number[]> {
         if (this.permFilter) {
             return this.perm.hasWorkPermAt([this.permFilter], true)
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
index 7f98f45087..da1155ee99 100644
--- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
@@ -420,8 +420,8 @@
 <div class="mt-4 mb-4">
   <h4>Item (Copy) Location Selector</h4>
   <div class="row">
-    <div class="col-lg-3">
-      <eg-item-location-select permFilter="CREATE_WORKSTATION" 
+    <div class="col-lg-3 form-validated">
+      <eg-item-location-select permFilter="UPDATE_COPY"
         [(ngModel)]="locId" (valueChange)="aLocation = $event">
       </eg-item-location-select>
     </div>

commit 83588f6da7ae99489803d756749e777909db75d9
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Nov 6 12:41:32 2019 -0500

    LP1850555 Angular Item (Copy) Location Select Component
    
    <eg-item-location-select .../>
    
    Adds a new item location select component which filters the list of
    displayed locations based on a permission-check org or a specific
    context org unit.
    
    Values in the selector are decorated with the org unit short name in
    parens after the location name to clarify the owning lib.
    
    Sandbox example included.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts b/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts
index 41d2b30cec..3f5aab8501 100644
--- a/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts
+++ b/Open-ILS/src/eg2/src/app/share/combobox/combobox.component.ts
@@ -18,6 +18,7 @@ export interface ComboboxEntry {
   // If no label is provided, the 'id' value is used.
   label?: string;
   freetext?: boolean;
+  userdata?: any; // opaque external value; ignored by this component.
 }
 
 @Component({
diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
new file mode 100644
index 0000000000..b5ad4da982
--- /dev/null
+++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
@@ -0,0 +1,13 @@
+
+<ng-template #displayTemplate let-r="result" i18n>
+  {{r.label}} ({{orgName(r.userdata.owning_lib())}})
+</ng-template>
+
+<eg-combobox #comboBox
+  [startId]="startId"
+  [displayTemplate]="displayTemplate"
+  (onChange)="cboxChanged($event)"
+  (blur)="propagateTouch()"
+  placeholder="Shelving Location..."
+  i18n-placeholder>
+</eg-combobox>
diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
new file mode 100644
index 0000000000..082aa80ccf
--- /dev/null
+++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
@@ -0,0 +1,118 @@
+import {Component, OnInit, Input, Output, ViewChild, EventEmitter, forwardRef} from '@angular/core';
+import {ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
+import {Observable} from 'rxjs';
+import {map} from 'rxjs/operators';
+import {IdlObject} from '@eg/core/idl.service';
+import {OrgService} from '@eg/core/org.service';
+import {AuthService} from '@eg/core/auth.service';
+import {PermService} from '@eg/core/perm.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
+
+/**
+ * Item (Copy) Location Selector.
+ *
+ * <eg-item-location-select [(ngModel)]="myAcplId"
+    [contextOrgId]="anOrgId" permFilter="ADMIN_STUFF">
+ * </eg-item-location-select>
+ */
+
+ at Component({
+  selector: 'eg-item-location-select',
+  templateUrl: './item-location-select.component.html',
+  providers: [{
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => ItemLocationSelectComponent),
+      multi: true
+  }]
+})
+export class ItemLocationSelectComponent implements OnInit, ControlValueAccessor {
+
+    // Limit copy locations to those owned at or above org units where
+    // the user has work permissions for the provided permission code.
+    @Input() permFilter: string;
+
+    // Limit copy locations to those owned at or above this org unit.
+    @Input() contextOrgId: number;
+
+    @Input() orgUnitLabelField = 'shortname';
+
+    // Emits an acpl object or null on combobox value change
+    @Output() valueChange: EventEmitter<IdlObject>;
+
+    @ViewChild('comboBox', {static: false}) comboBox: ComboboxComponent;
+
+    startId: number = null;
+    filterOrgs: number[];
+    cache: {[id: number]: IdlObject} = {};
+
+    propagateChange = (id: number) => {};
+    propagateTouch = () => {};
+
+    constructor(
+        private org: OrgService,
+        private auth: AuthService,
+        private perm: PermService,
+        private pcrud: PcrudService
+    ) {
+        this.valueChange = new EventEmitter<IdlObject>();
+    }
+
+    ngOnInit() {
+        this.setFilterOrgs().then(_ => this.getLocations());
+    }
+
+    getLocations(): Promise<any> {
+        const entries: ComboboxEntry[] = [];
+        const search = {owning_lib: this.filterOrgs, deleted: 'f'};
+
+        return this.pcrud.search('acpl', search, {order_by: {acpl: 'name'}}
+        ).pipe(map(loc => {
+            this.cache[loc.id()] = loc;
+            entries.push({id: loc.id(), label: loc.name(), userdata: loc});
+        })).toPromise().then(_ => {
+            this.comboBox.entries = entries;
+        });
+    }
+
+    registerOnChange(fn) {
+        this.propagateChange = fn;
+    }
+
+    registerOnTouched(fn) {
+        this.propagateTouch = fn;
+    }
+
+    cboxChanged(entry: ComboboxEntry) {
+        const id = entry ? entry.id : null;
+        this.propagateChange(id);
+        this.valueChange.emit(id ? this.cache[id] : null);
+    }
+
+    writeValue(id: number) {
+        if (this.comboBox) { // May not yet be initialized
+            this.comboBox.selectedId = id;
+        } else if (id) {
+            this.startId = id;
+        }
+    }
+
+    setFilterOrgs(): Promise<number[]> {
+        if (this.permFilter) {
+            return this.perm.hasWorkPermAt([this.permFilter], true)
+                .then(values => this.filterOrgs = values[this.permFilter]);
+        }
+
+        const org = this.contextOrgId || this.auth.user().ws_ou();
+        this.filterOrgs = this.org.ancestors(this.contextOrgId, true);
+
+        return Promise.resolve(this.filterOrgs);
+    }
+
+    orgName(orgId: number): string {
+        return this.org.get(orgId)[this.orgUnitLabelField]();
+    }
+}
+
+
+
diff --git a/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.module.ts b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.module.ts
new file mode 100644
index 0000000000..f82989a852
--- /dev/null
+++ b/Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.module.ts
@@ -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 {ItemLocationSelectComponent} from './item-location-select.component';
+import {ReactiveFormsModule} from '@angular/forms';
+
+ at NgModule({
+    declarations: [
+        ItemLocationSelectComponent
+    ],
+    imports: [
+        EgCommonModule,
+        EgCoreModule,
+        CommonWidgetsModule,
+        ReactiveFormsModule
+    ],
+    exports: [
+        ItemLocationSelectComponent
+    ],
+    providers: [
+    ]
+})
+
+export class ItemLocationSelectModule { }
+
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
index 3b9609b399..7f98f45087 100644
--- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
@@ -416,3 +416,18 @@
     <eg-grid-column name="hook"></eg-grid-column>
   </eg-grid>
 </div>
+
+<div class="mt-4 mb-4">
+  <h4>Item (Copy) Location Selector</h4>
+  <div class="row">
+    <div class="col-lg-3">
+      <eg-item-location-select permFilter="CREATE_WORKSTATION" 
+        [(ngModel)]="locId" (valueChange)="aLocation = $event">
+      </eg-item-location-select>
+    </div>
+    <div class="col-lg-2">Selected ID: {{locId}}</div>
+    <div class="col-lg-4">
+      valueChange Handler Produced: {{aLocation ? aLocation.name() : '(none)'}}
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
index c44a7f7a0b..caf86fa8d2 100644
--- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
@@ -109,6 +109,9 @@ export class SandboxComponent implements OnInit {
 
     myTimeForm: FormGroup;
 
+    locId = 1; // Stacks
+    aLocation: IdlObject; // acpl
+
     constructor(
         private idl: IdlService,
         private org: OrgService,
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts
index a33deb86ce..15be7f31d5 100644
--- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts
+++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts
@@ -7,6 +7,7 @@ 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';
+import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module';
 
 @NgModule({
   declarations: [
@@ -17,6 +18,7 @@ import {OrgFamilySelectModule} from '@eg/share/org-family-select/org-family-sele
     TranslateModule,
     FmRecordEditorModule,
     OrgFamilySelectModule,
+    ItemLocationSelectModule,
     SandboxRoutingModule,
     ReactiveFormsModule
   ],

-----------------------------------------------------------------------

Summary of changes:
 .../src/app/share/combobox/combobox.component.ts   |   1 +
 .../item-location-select.component.html            |  17 ++
 .../item-location-select.component.ts              | 175 +++++++++++++++++++++
 .../item-location-select.module.ts}                |   8 +-
 .../src/app/staff/sandbox/sandbox.component.html   |  15 ++
 .../eg2/src/app/staff/sandbox/sandbox.component.ts |   3 +
 .../eg2/src/app/staff/sandbox/sandbox.module.ts    |   2 +
 7 files changed, 217 insertions(+), 4 deletions(-)
 create mode 100644 Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.html
 create mode 100644 Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
 copy Open-ILS/src/eg2/src/app/share/{org-family-select/org-family-select.module.ts => item-location-select/item-location-select.module.ts} (71%)


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list