LP1899406 Basket view allows for (de)select all operation
authorBill Erickson <berickxx@gmail.com>
Wed, 10 Feb 2021 20:15:13 +0000 (15:15 -0500)
committerMichele Morgan <mmorgan@noblenet.org>
Fri, 14 May 2021 19:27:05 +0000 (19:27 +0000)
Within the staff client catalog basket view page, users can now select
and deselect all items in the basket for basket actions, without otherwise
affecting the contents of the basket.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/basket-selection.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/result/record.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/result/results.component.html
Open-ILS/src/eg2/src/app/staff/catalog/result/results.component.ts

index bcd5dfe..13bf25d 100644 (file)
@@ -35,7 +35,7 @@ export class BasketActionsComponent implements OnInit {
         private printer: PrintService,
         private basket: BasketService,
         private cat: CatalogService,
-        private staffCat: StaffCatalogService
+        private staffCat: StaffCatalogService,
         private basketSelect: BasketSelectionService
     ) {
         this.basketAction = '';
index 892de60..ce9001e 100644 (file)
@@ -13,6 +13,8 @@ export class BasketSelectionService {
 
     idList: number[];
 
+    onChange: EventEmitter<number[]> = new EventEmitter<number[]>();
+
     constructor(private basket: BasketService) {
         this.idList = [];
     }
@@ -35,6 +37,7 @@ export class BasketSelectionService {
 
     setRecordIds(ids: number[]): Promise<number[]> {
         this.idList = ids;
+        this.onChange.emit(this.idList);
         return Promise.resolve(this.idList);
     }
 
index eb22bd8..0501c5f 100644 (file)
@@ -29,7 +29,7 @@ export class ResultRecordComponent implements OnInit, OnDestroy {
 
     searchContext: CatalogSearchContext;
     isRecordSelected: boolean;
-    basketSub: Subscription;
+    selectorSub: Subscription;
     hasCourse = false;
     courses: any[] = [];
 
@@ -49,22 +49,24 @@ export class ResultRecordComponent implements OnInit, OnDestroy {
     ngOnInit() {
         this.searchContext = this.staffCat.searchContext;
         this.loadCourseInformation(this.summary.id);
-        this.isRecordSelected = this.basket.hasRecordId(this.summary.id);
-
-        // Watch for basket changes caused by other components
-        this.basketSub = this.basket.onChange.subscribe(() => {
-            this.isRecordSelected = this.basket.hasRecordId(this.summary.id);
-        });
 
         if (this.searchContext.showBasket) {
             this.recordSelector = this.basketSelect;
         } else {
             this.recordSelector = this.basket;
         }
+
+        this.isRecordSelected = this.recordSelector.hasRecordId(this.summary.id);
+
+        // Watch for basket changes caused by other components
+        this.selectorSub = this.recordSelector.onChange.subscribe(() => {
+            this.isRecordSelected =
+                this.recordSelector.hasRecordId(this.summary.id);
+        });
     }
 
     ngOnDestroy() {
-        this.basketSub.unsubscribe();
+        this.selectorSub.unsubscribe();
     }
 
     loadCourseInformation(recordId) {
index 8ca7b0f..515121d 100644 (file)
       <h3 i18n>Basket View</h3>
     </div>
     <div class="col-lg-2">
+      <label class="checkbox" *ngIf="searchContext.showBasket">
+        <input type='checkbox' [(ngModel)]="allRecsSelected" 
+            (change)="toggleAllRecsSelected()"/>
+        <span class="pl-1" i18n>Select All</span>
+      </label>
       <label class="checkbox" *ngIf="!searchContext.showBasket">
         <input type='checkbox' [(ngModel)]="allRecsSelected" 
             (change)="toggleAllRecsSelected()"/>
index 2cc6604..c9a1edc 100644 (file)
@@ -29,6 +29,8 @@ export class ResultsComponent implements OnInit, OnDestroy {
     searchSub: Subscription;
     routeSub: Subscription;
     basketSub: Subscription;
+    basketSelectSub: Subscription;
+    showingBasket = false;
 
     recordSelector: BasketService |  BasketSelectionService;
 
@@ -53,16 +55,26 @@ export class ResultsComponent implements OnInit, OnDestroy {
         // searches.
         //
         // This will also fire on page load.
-        this.routeSub =
-            this.route.queryParamMap.subscribe((params: ParamMap) => {
-
-              // TODO: Angular docs suggest using switchMap(), but
-              // it's not firing for some reason.  Also, could avoid
-              // firing unnecessary searches when a param unrelated to
-              // searching is changed by .map()'ing out only the desired
-              // params and running through .distinctUntilChanged(), but
-              // .map() is not firing either.  I'm missing something.
-              this.searchByUrl(params);
+        this.routeSub = this.route.queryParamMap.subscribe((params: ParamMap) => {
+
+            // TODO: Angular docs suggest using switchMap(), but
+            // it's not firing for some reason.  Also, could avoid
+            // firing unnecessary searches when a param unrelated to
+            // searching is changed by .map()'ing out only the desired
+            // params and running through .distinctUntilChanged(), but
+            // .map() is not firing either.  I'm missing something.
+            this.searchByUrl(params);
+
+            if (this.searchContext.showBasket) {
+                if (!this.showingBasket) {
+                    // Only init the basket selector when navigating
+                    // to the basket view from a non-basket view.
+                    this.basketSelect.init();
+                    this.showingBasket = true;
+                }
+            } else {
+                this.showingBasket = false;
+            }
         });
 
         // After each completed search, update the record selector.
@@ -73,9 +85,11 @@ export class ResultsComponent implements OnInit, OnDestroy {
         this.basketSub = this.basket.onChange.subscribe(
             () => this.applyRecordSelection());
 
+        this.basketSelectSub = this.basketSelect.onChange.subscribe(
+            () => this.applyRecordSelection());
+
         if (this.searchContext.showBasket) {
             this.recordSelector = this.basketSelect;
-            this.basketSelect.init();
         } else {
             this.recordSelector = this.basket;
         }
@@ -86,13 +100,16 @@ export class ResultsComponent implements OnInit, OnDestroy {
             this.routeSub.unsubscribe();
             this.searchSub.unsubscribe();
             this.basketSub.unsubscribe();
+            this.basketSelectSub.unsubscribe();
         }
     }
 
     // Apply the select-all checkbox when all visible records
     // are selected.
     applyRecordSelection() {
-        const ids = this.searchContext.currentResultIds();
+        const ids = this.showingBasket ? this.basket.idList :
+            this.searchContext.currentResultIds();
+
         let allChecked = true;
         ids.forEach(id => {
             if (!this.recordSelector.hasRecordId(id)) {
@@ -129,12 +146,23 @@ export class ResultsComponent implements OnInit, OnDestroy {
     }
 
     toggleAllRecsSelected() {
-        const ids = this.searchContext.currentResultIds();
 
-        if (this.allRecsSelected) {
-            this.recordSelector.addRecordIds(ids);
+        if (this.showingBasket) {
+            if (this.allRecsSelected) {
+                this.basketSelect.init();
+            } else {
+                this.basketSelect.removeAllRecordIds();
+            }
+
         } else {
-            this.recordSelector.removeRecordIds(ids);
+
+            const ids = this.searchContext.currentResultIds();
+
+            if (this.allRecsSelected) {
+                this.recordSelector.addRecordIds(ids);
+            } else {
+                this.recordSelector.removeRecordIds(ids);
+            }
         }
     }
 }