LP1922120: Add to carousel action in angular catalog
authorJane Sandberg <sandbej@linnbenton.edu>
Fri, 28 May 2021 02:32:27 +0000 (19:32 -0700)
committerGalen Charlton <gmc@equinoxOLI.org>
Wed, 2 Jun 2021 14:48:24 +0000 (10:48 -0400)
To test:

1) Create several manual carousels, and make sure they are
set to active.
2) Open a bib record in the Angular staff catalog.
3) Under Other Actions, choose the "Add to Carousel" action
4) Choose your preferred carousel.
5) Click Add to carousel.
6) Go back to carousel administration (or look at the carousel
itself), and confirm that the record has been added to the
carousel in question.

Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>

Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/actions.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.ts [new file with mode: 0644]

index 9b7d57a..cff15a1 100644 (file)
@@ -21,6 +21,7 @@ import {RecordActionsComponent} from './record/actions.component';
 import {BasketActionsComponent} from './basket-actions.component';
 import {HoldComponent} from './hold/hold.component';
 import {PartsComponent} from './record/parts.component';
+import {AddToCarouselDialogComponent} from './record/add-to-carousel-dialog.component';
 import {PartMergeDialogComponent} from './record/part-merge-dialog.component';
 import {BrowseComponent} from './browse.component';
 import {BrowseResultsComponent} from './browse/results.component';
@@ -47,6 +48,7 @@ import {PreferencesComponent} from './prefs.component';
     BasketActionsComponent,
     HoldComponent,
     PartsComponent,
+    AddToCarouselDialogComponent,
     PartMergeDialogComponent,
     BrowseComponent,
     BrowseResultsComponent,
index 9a64f73..2b5bc7f 100644 (file)
@@ -1,18 +1,21 @@
 
-<eg-string key="catalog.record.toast.conjoined" 
+<eg-string key="catalog.record.toast.conjoined"
   i18n-text text="Conjoined Record Target Set"></eg-string>
-<eg-string key="catalog.record.toast.overlay" 
+<eg-string key="catalog.record.toast.overlay"
   i18n-text text="Record Overlay Target Set"></eg-string>
-<eg-string key="catalog.record.toast.holdTransfer" 
+<eg-string key="catalog.record.toast.holdTransfer"
   i18n-text text="Hold Transfer Target Set"></eg-string>
-<eg-string key="catalog.record.toast.holdingTransfer" 
+<eg-string key="catalog.record.toast.holdingTransfer"
   i18n-text text="Holding Transfer Target Set"></eg-string>
-<eg-string key="catalog.record.toast.cleared" 
+<eg-string key="catalog.record.toast.cleared"
   text="Record Marks Cleared"></eg-string>
 
 <eg-bucket-dialog #recordBucketDialog bucketClass="biblio" [itemIds]="[recId]">
 </eg-bucket-dialog>
 
+<eg-add-to-carousel-dialog #recordCarouselDialog [recordIds]="[recId]">
+</eg-add-to-carousel-dialog>
+
 <div class="row ml-0 mr-0">
 
   <a routerLink="/staff/catalog/hold/T" [queryParams]="{target: recId}">
     <div ngbDropdownMenu aria-labelledby="actionsForDd">
       <button class="dropdown-item" (click)="mark('conjoined')">
         <span i18n>
-          Conjoined Items<ng-container *ngIf="targets.conjoined.current"> 
+          Conjoined Items<ng-container *ngIf="targets.conjoined.current">
             (Currently {{targets.conjoined.current}})</ng-container>
         </span>
       </button>
       <button class="dropdown-item" (click)="mark('overlay')">
         <span i18n>
-          Overlay Target<ng-container *ngIf="targets.overlay.current"> 
+          Overlay Target<ng-container *ngIf="targets.overlay.current">
             (Currently {{targets.overlay.current}})</ng-container>
         </span>
       </button>
       <button class="dropdown-item" (click)="mark('holdTransfer')">
         <span i18n>
-          Title Hold Transfer<ng-container *ngIf="targets.holdTransfer.current"> 
+          Title Hold Transfer<ng-container *ngIf="targets.holdTransfer.current">
             (Currently {{targets.holdTransfer.current}})</ng-container>
         </span>
       </button>
       <button class="dropdown-item" (click)="recordBucketDialog.open({size: 'lg'})">
         <span i18n>Add To Bucket</span>
       </button>
-      <a class="dropdown-item" 
+      <button class="dropdown-item" (click)="recordCarouselDialog.open({size: 'lg'})">
+        <span i18n>Add To Carousel</span>
+      </button>
+      <a class="dropdown-item"
         href="/eg/staff/acq/legacy/lineitem/related/{{recId}}?target=bib">
         <span i18n>View/Place Orders</span>
       </a>
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.html
new file mode 100644 (file)
index 0000000..9199bd9
--- /dev/null
@@ -0,0 +1,31 @@
+<eg-string #successMsg text="Successfully added to carousel" i18n-text></eg-string>
+<eg-string #errorMsg text="Failed to add to carousel" i18n-text></eg-string>
+
+<ng-template #dialogContent>
+  <div class="modal-header bg-info">
+    <h4 class="modal-title">
+      <span i18n>Add to Carousel</span>
+    </h4>
+    <button type="button" class="close"
+    i18n-aria-label aria-label="Close" (click)="close(false)">
+    <span aria-hidden="true">&times;</span>
+  </button>
+</div>
+<div class="modal-body">
+  <div *ngIf="!carousels.length">
+    <p i18n>There are no eligible carousels.</p>
+    <p> <a routerLink="/staff/admin/local/container/carousel" i18n>Would you like to add one?</a></p>
+  </div>
+  <div class="row" *ngIf="carousels.length">
+    <div class="col-lg-3 font-weight-bold" i18n>Carousel</div>
+    <div class="col-lg-5">
+      <eg-combobox [entries]="formatCarouselEntries()" [formControl]="selectedCarousel">
+      </eg-combobox>
+    </div>
+  </div>
+</div>
+<div class="modal-footer">
+  <button type="button" class="btn btn-success"
+  (click)="addToCarousel()" i18n>Add to carousel</button>
+</div>
+</ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/add-to-carousel-dialog.component.ts
new file mode 100644 (file)
index 0000000..6941bef
--- /dev/null
@@ -0,0 +1,86 @@
+import {Component, Input, OnInit, ViewChild} from '@angular/core';
+import {FormControl} from '@angular/forms';
+import {takeLast} from 'rxjs/operators';
+import {DialogComponent} from '@eg/share/dialog/dialog.component';
+import {AuthService} from '@eg/core/auth.service';
+import {NetService} from '@eg/core/net.service';
+import {EventService} from '@eg/core/event.service';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
+import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {StringComponent} from '@eg/share/string/string.component';
+
+@Component({
+  selector: 'eg-add-to-carousel-dialog',
+  templateUrl: './add-to-carousel-dialog.component.html'
+})
+
+
+export class AddToCarouselDialogComponent extends DialogComponent implements OnInit {
+
+    // IDs of records to add to the carousel
+    @Input() recordIds: number[];
+
+
+    @ViewChild('successMsg', { static: true }) private successMsg: StringComponent;
+    @ViewChild('errorMsg', { static: true }) private errorMsg: StringComponent;
+
+    selectedCarousel = new FormControl('');
+
+    private carousels = [];
+
+    public addToCarousel: () => void;
+    private reset: () => void;
+
+    constructor(
+        private modal: NgbModal,
+        private auth: AuthService,
+        private evt: EventService,
+        private net: NetService,
+        private toast: ToastService
+    ) {
+        super(modal);
+    }
+
+    ngOnInit() {
+        this.onOpen$.subscribe(ok => {
+            this.reset();
+            this.net.request(
+                'open-ils.actor',
+                'open-ils.actor.carousel.retrieve_manual_by_staff',
+                this.auth.token()
+            ).subscribe(carousels => this.carousels = carousels);
+        });
+
+        this.reset = () => {
+            this.carousels = [];
+        };
+
+        this.addToCarousel = () => {
+            this.net.request(
+                'open-ils.actor',
+                'open-ils.actor.container.item.create.batch',
+                this.auth.token(),
+                'biblio_record_entry',
+                this.selectedCarousel.value['id'],
+                this.recordIds
+            ).pipe(takeLast(1))
+            .subscribe(
+                result => {
+                    const evt = this.evt.parse(result);
+                    if (evt) {
+                        this.errorMsg.current().then(m => this.toast.danger(m));
+                    } else {
+                        this.successMsg.current().then(m => this.toast.success(m));
+                        this.close(true);
+                    }
+                }
+            );
+        };
+    }
+
+    formatCarouselEntries(): ComboboxEntry[] {
+        return this.carousels.map(carousel => ({id: carousel['bucket'], label: carousel['name']}));
+    }
+
+}