LP#1863387: multi-select now allows filtering shelving locations by owner user/gmcharlt/lp1863387_tune_location_multi_select
authorGalen Charlton <gmc@equinoxOLI.org>
Fri, 9 Sep 2022 16:55:22 +0000 (12:55 -0400)
committerGalen Charlton <gmc@equinoxOLI.org>
Fri, 9 Sep 2022 17:01:59 +0000 (13:01 -0400)
The Angular multi-select component now has a special case for
shelving locations: when the IDL class of "acpl" is selected,
rather than just displaying a combobox, the item-location-select
component followed by an org selector is displayed. The org select
defaults to workstation OU and is used to restrict the list of
shelving locations displayed in the shelving location combobox.

The effect of this is to allow large consortial to more efficiently
select the shelving locations to be used by a carousel.

To test
-------
[1] Apply the patch.
[2] Create or edit carousel definitions. Verify that the widget
    for the carousel's shelving locations now displays both a
    combobox for the location selector as well as one for the
    location owning library. Further verify that when the OU
    selector for the owning library is changed, that the list
    of available shelving locations reflects the locations available
    at the ancestors and descendants of the filter OU.

Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Open-ILS/src/eg2/src/app/share/item-location-select/item-location-select.component.ts
Open-ILS/src/eg2/src/app/share/multi-select/multi-select.component.html
Open-ILS/src/eg2/src/app/share/multi-select/multi-select.component.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts

index 82490a2..f20a268 100644 (file)
@@ -61,6 +61,8 @@ export class ItemLocationSelectComponent
 
     // Emits an acpl object or null on combobox value change
     @Output() valueChange: EventEmitter<IdlObject>;
+    // Emits the combobox entry or null on value change
+    @Output() entryChange: EventEmitter<ComboboxEntry>;
 
     @Input() required: boolean;
 
@@ -85,6 +87,7 @@ export class ItemLocationSelectComponent
         private pcrud: PcrudService
     ) {
         this.valueChange = new EventEmitter<IdlObject>();
+        this.entryChange = new EventEmitter<ComboboxEntry>();
     }
 
     ngOnInit() {
@@ -155,6 +158,7 @@ export class ItemLocationSelectComponent
         const id = entry ? entry.id : null;
         this.propagateChange(id);
         this.valueChange.emit(id ? this.cache[id] : null);
+        this.entryChange.emit(entry ? entry : null);
     }
 
     writeValue(id: number) {
@@ -179,7 +183,7 @@ export class ItemLocationSelectComponent
     setFilterOrgs(): Promise<number[]> {
         let contextOrgIds: number[] = [];
 
-        if (this.contextOrgIds) {
+        if (this.contextOrgIds.length) {
             contextOrgIds = this.contextOrgIds;
         } else {
             contextOrgIds = [this.contextOrgId || this.auth.user().ws_ou()];
index 1926abf..8a77455 100644 (file)
@@ -1,9 +1,22 @@
 <div>
   <div class="row">
-    <eg-combobox [idlBaseQuery]="idlBaseQuery" [idlClass]="idlClass" 
-      [idlIncludeLibraryInLabel]="linkedLibraryLabel" [asyncSupportsEmptyTermClick]="true"
-      (onChange)="valueSelected($event)">
-    </eg-combobox>
+    <ng-container *ngIf="idlClass === 'acpl'">
+      <eg-item-location-select (entryChange)="valueSelected($event)"
+        [contextOrgId]="acplContextOrgId"
+        domId='location-input'>
+      </eg-item-location-select>
+      <span class="m-1" i18n>Owned by</span>
+      <eg-org-select
+       [applyDefault]="true"
+       (onChange)="acplContextOrgId = $event.id()">
+      </eg-org-select>
+    </ng-container>
+    <ng-container *ngIf="idlClass !== 'acpl'">
+      <eg-combobox [idlBaseQuery]="idlBaseQuery" [idlClass]="idlClass"
+        [idlIncludeLibraryInLabel]="linkedLibraryLabel" [asyncSupportsEmptyTermClick]="true"
+        (onChange)="valueSelected($event)">
+      </eg-combobox>
+    </ng-container>
     <button class="btn btn-outline-dark" (click)="addSelectedValue()" [disabled]="!this.selected" i18n>Add</button>
   </div>
   <div class="row" *ngFor="let entry of entrylist">
index 3496f55..9d7f8e2 100644 (file)
@@ -7,7 +7,9 @@ import {map} from 'rxjs/operators';
 import {Observable, of, Subject} from 'rxjs';
 import {StoreService} from '@eg/core/store.service';
 import {PcrudService} from '@eg/core/pcrud.service';
+import {OrgService} from '@eg/core/org.service';
 import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {ItemLocationSelectComponent} from '@eg/share/item-location-select/item-location-select.component';
 
 @Component({
   selector: 'eg-multi-select',
@@ -30,9 +32,12 @@ export class MultiSelectComponent implements OnInit {
 
     @Output() onChange: EventEmitter<string>;
 
+    acplContextOrgId: number;
+
     constructor(
       private store: StoreService,
       private pcrud: PcrudService,
+      private org: OrgService,
     ) {
         this.entrylist = [];
         this.onChange = new EventEmitter<string>();
@@ -45,7 +50,22 @@ export class MultiSelectComponent implements OnInit {
             this.selected = null;
         }
     }
+
+    getOrgShortname(ou: any) {
+        if (typeof ou === 'object') {
+            return ou.shortname();
+        } else {
+            return this.org.get(ou).shortname();
+        }
+    }
+
     addSelectedValue() {
+        // special case to format the label
+        if (this.idlClass === 'acpl' && this.selected.userdata) {
+            this.selected.label =
+                this.selected.userdata.name() + ' (' +
+                this.getOrgShortname(this.selected.userdata.owning_lib()) + ')';
+        }
         this.entrylist.push(this.selected);
         this.onChange.emit(this.compileCurrentValue());
     }
index 280f92a..ef64b86 100644 (file)
@@ -21,6 +21,7 @@ import {PatronBarcodeValidatorDirective} from '@eg/share/validators/patron_barco
 import {BroadcastService} from '@eg/share/util/broadcast.service';
 import {CourseService} from './share/course.service';
 import {FileExportService} from '@eg/share/util/file-export.service';
+import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module';
 
 /**
  * Imports the EG common modules and adds modules common to all staff UI's.
@@ -46,7 +47,8 @@ import {FileExportService} from '@eg/share/util/file-export.service';
     EgCommonModule,
     CommonWidgetsModule,
     GridModule,
-    CatalogCommonModule
+    CatalogCommonModule,
+    ItemLocationSelectModule
   ],
   exports: [
     EgCommonModule,