From bb9f8f3a4db4a5f08b2bcc6d7f10885443731502 Mon Sep 17 00:00:00 2001 From: Bill Erickson <berickxx@gmail.com> Date: Thu, 7 Mar 2019 13:55:04 -0500 Subject: [PATCH] LP1819053 Angular staff catalog basket export Adds a new "Export Records" option to the staff catalog basket menu. When selected, the user is directed to the Vandelay record export interface, which will be set to "basket export" mode. Staff can then apply export preferences (usmarc, marxml, etc.) and export the basket records. In "basket export" mode, Vandley provides a link to return to the catalog (preserving search params). Signed-off-by: Bill Erickson <berickxx@gmail.com> Signed-off-by: Dan Wells <dbw2@calvin.edu> --- .../app/staff/cat/vandelay/export.component.html | 115 ++++++++++++--------- .../src/app/staff/cat/vandelay/export.component.ts | 68 +++++++++--- .../src/app/staff/cat/vandelay/routing.module.ts | 3 + .../staff/catalog/basket-actions.component.html | 1 + .../app/staff/catalog/basket-actions.component.ts | 8 +- 5 files changed, 127 insertions(+), 68 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.html b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.html index 53f36e6813..b6fb361799 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.html @@ -3,60 +3,73 @@ <div class="common-form striped-even form-validated"> <div class="row"> <div class="col-lg-6"> - <div class="row"><label>Select a Record Source</label></div> - <ngb-accordion [closeOthers]="true" activeIds="csv" - (panelChange)="sourceChange($event)"> - <ngb-panel id="csv" title="CSV File"> - <ng-template ngbPanelContent> - <div class="row"> - <div class="col-lg-6"> - <label for="csv-input" i18n>Use Field Number</label> - </div> - <div class="col-lg-6"> - <input id='csv-input' type="number" class="form-control" - [(ngModel)]="fieldNumber" - i18n-placeholder placeholder="Starts at 0..."/> - </div> - </div> - <div class="row"> - <div class="col-lg-6"> - <label for="use-csv-file" i18n>From CSV file</label> - </div> - <div class="col-lg-6"> - <input #fileSelector (change)="fileSelected($event)" - id="use-csv-file" class="form-control" type="file"/> - </div> - </div> - </ng-template> - </ngb-panel> - <ngb-panel id="record-id" title="Record ID"> - <ng-template ngbPanelContent> - <div class="row"> - <div class="col-lg-6"> - <label for="record-id-input" i18n>Record ID</label> + <ng-container *ngIf="exportingBasket"> + <div class="alert alert-info" i18n> + Exporting {{basketRecords.length}} Records from Catalog Basket. + </div> + <div> + <a routerLink="/staff/catalog/search" queryParamsHandling="merge"> + <button class="btn btn-info" i18n>Return to Catalog</button> + </a> + </div> + </ng-container> + <ng-container *ngIf="!exportingBasket"> + <div class="row"><label>Select a Record Source</label></div> + <ngb-accordion [closeOthers]="true" activeIds="csv" + (panelChange)="sourceChange($event)"> + <ngb-panel id="csv" title="CSV File"> + <ng-template ngbPanelContent> + <div class="row"> + <div class="col-lg-6"> + <label for="csv-input" i18n>Use Field Number</label> + </div> + <div class="col-lg-6"> + <input id='csv-input' type="number" class="form-control" + [(ngModel)]="fieldNumber" + i18n-placeholder placeholder="Starts at 0..."/> + </div> </div> - <div class="col-lg-6"> - <input id='record-id-input' type="number" - class="form-control" [(ngModel)]="recordId"/> + <div class="row"> + <div class="col-lg-6"> + <label for="use-csv-file" i18n>From CSV file</label> + </div> + <div class="col-lg-6"> + <input #fileSelector (change)="fileSelected($event)" + id="use-csv-file" class="form-control" type="file"/> + </div> </div> - </div> - </ng-template> - </ngb-panel> - <ngb-panel id="bucket-id" title="Bucket"> - <ng-template ngbPanelContent> - <div class="row"> - <div class="col-lg-6"> - <label for="bucket-id-input" i18n>Bucket ID</label> + </ng-template> + </ngb-panel> + <ngb-panel id="record-id" title="Record ID"> + <ng-template ngbPanelContent> + <div class="row"> + <div class="col-lg-6"> + <label for="record-id-input" i18n>Record ID</label> + </div> + <div class="col-lg-6"> + <input id='record-id-input' type="number" + class="form-control" [(ngModel)]="recordId"/> + </div> </div> - <div class="col-lg-6"> - <input id='bucket-id-input' type="number" - class="form-control" [(ngModel)]="bucketId"/> + </ng-template> + </ngb-panel> + <ngb-panel id="bucket-id" title="Bucket"> + <ng-template ngbPanelContent> + <div class="row"> + <div class="col-lg-6"> + <label for="bucket-id-input" i18n>Bucket ID</label> + </div> + <div class="col-lg-6"> + <input id='bucket-id-input' type="number" + class="form-control" [(ngModel)]="bucketId"/> + </div> </div> - </div> - </ng-template> - </ngb-panel> - </ngb-accordion> + </ng-template> + </ngb-panel> + </ngb-accordion> + </ng-container> </div><!-- col --> + <div class="col-lg-6"> <div class="row"> <div class="col-lg-6"> @@ -64,6 +77,7 @@ </div> <div class="col-lg-6"> <select class="form-control" + [disabled]="exportingBasket" [(ngModel)]="recordType" id="record-type"> <option i18n value="biblio">Bibliographic Records</option> <option i18n value="authority">Authority Records</option> @@ -121,5 +135,6 @@ </div> </div><!-- left col --> </div><!-- row --> -</div> +</div><!-- form --> + diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.ts index d980e02bd2..648f4d58b6 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/export.component.ts @@ -1,4 +1,5 @@ -import {Component, AfterViewInit, ViewChild, Renderer2} from '@angular/core'; +import {Component, AfterViewInit, ViewChild, Renderer2, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; import {NgbPanelChangeEvent} from '@ng-bootstrap/ng-bootstrap'; import {HttpClient, HttpRequest, HttpEventType} from '@angular/common/http'; import {HttpResponse, HttpErrorResponse} from '@angular/common/http'; @@ -6,13 +7,14 @@ import {saveAs} from 'file-saver'; import {AuthService} from '@eg/core/auth.service'; import {ToastService} from '@eg/share/toast/toast.service'; import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component'; -import {VandelayService, VANDELAY_EXPORT_PATH} from './vandelay.service'; +import {VANDELAY_EXPORT_PATH} from './vandelay.service'; +import {BasketService} from '@eg/share/catalog/basket.service'; @Component({ templateUrl: 'export.component.html' }) -export class ExportComponent implements AfterViewInit { +export class ExportComponent implements AfterViewInit, OnInit { recordSource: string; fieldNumber: number; @@ -24,6 +26,8 @@ export class ExportComponent implements AfterViewInit { recordEncoding: string; includeHoldings: boolean; isExporting: boolean; + exportingBasket: boolean; + basketRecords: number[]; @ViewChild('fileSelector') private fileSelector; @ViewChild('exportProgress') @@ -31,23 +35,44 @@ export class ExportComponent implements AfterViewInit { constructor( private renderer: Renderer2, + private route: ActivatedRoute, private http: HttpClient, private toast: ToastService, - private auth: AuthService + private auth: AuthService, + private basket: BasketService ) { this.recordType = 'biblio'; this.recordFormat = 'USMARC'; this.recordEncoding = 'UTF-8'; this.includeHoldings = false; + this.basketRecords = []; + } + + ngOnInit() { + const segments = this.route.snapshot.url.length; + if (segments > 0 && + this.route.snapshot.url[segments - 1].path === 'basket') { + this.exportingBasket = true; + this.basket.getRecordIds().then( + ids => this.basketRecords = ids + ); + } } ngAfterViewInit() { + if (this.exportingBasket) { + return; // no source to focus + } this.renderer.selectRootElement('#csv-input').focus(); } sourceChange($event: NgbPanelChangeEvent) { this.recordSource = $event.panelId; + if (this.exportingBasket) { + return; // no source to focus + } + if ($event.nextState) { // panel opened // give the panel a chance to render before focusing input @@ -64,7 +89,10 @@ export class ExportComponent implements AfterViewInit { hasNeededData(): boolean { return Boolean( - this.selectedFile || this.recordId || this.bucketId + this.selectedFile || + this.recordId || + this.bucketId || + (this.exportingBasket && this.basketRecords.length > 0) ); } @@ -83,21 +111,27 @@ export class ExportComponent implements AfterViewInit { formData.append('holdings', '1'); } - switch (this.recordSource) { + if (this.exportingBasket) { + this.basketRecords.forEach(id => formData.append('id', '' + id)); + + } else { - case 'csv': - formData.append('idcolumn', '' + this.fieldNumber); - formData.append('idfile', - this.selectedFile, this.selectedFile.name); - break; + switch (this.recordSource) { - case 'record-id': - formData.append('id', '' + this.recordId); - break; + case 'csv': + formData.append('idcolumn', '' + this.fieldNumber); + formData.append('idfile', + this.selectedFile, this.selectedFile.name); + break; - case 'bucket-id': - formData.append('containerid', '' + this.bucketId); - break; + case 'record-id': + formData.append('id', '' + this.recordId); + break; + + case 'bucket-id': + formData.append('containerid', '' + this.bucketId); + break; + } } this.sendExportRequest(formData); diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/routing.module.ts index 707b92b9ca..f4095a4825 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/routing.module.ts @@ -28,6 +28,9 @@ const routes: Routes = [{ path: 'export', component: ExportComponent }, { + path: 'export/basket', + component: ExportComponent + }, { path: 'queue', component: QueueListComponent }, { diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.html index 4857db8cc1..9fcd873cee 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.html @@ -22,6 +22,7 @@ <option value="print" i18n>Print Title Details</option> <option value="email" i18n>Email Title Details</option> <option value="bucket" i18n>Add Basket to Bucket</option> + <option value="export_marc" i18n>Export Records</option> <option value="clear" i18n>Clear Basket</option> </select> </div> diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts index f96df6fd75..da3f793625 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts @@ -1,6 +1,5 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import {BasketService} from '@eg/share/catalog/basket.service'; -import {Subscription} from 'rxjs'; import {Router} from '@angular/router'; import {NetService} from '@eg/core/net.service'; import {AuthService} from '@eg/core/auth.service'; @@ -87,6 +86,13 @@ export class BasketActionsComponent implements OnInit { }); break; + case 'export_marc': + this.router.navigate( + ['/staff/cat/vandelay/export/basket'], + {queryParamsHandling: 'merge'} + ); + break; + case 'bucket': this.basket.getRecordIds().then(ids => { this.addToBucketDialog.bucketClass = 'biblio'; -- 2.11.0