From 09651b9142e4f4557a2ed297c3312317330dff70 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 2 Jul 2018 16:38:44 -0400 Subject: [PATCH] LP#1779158 Ang vandelay import create queue, process spool Signed-off-by: Bill Erickson --- .../app/staff/cat/vandelay/import.component.html | 18 +++- .../src/app/staff/cat/vandelay/import.component.ts | 120 +++++++++++++++++++-- .../src/app/staff/cat/vandelay/vandelay.service.ts | 32 ++++++ 3 files changed, 163 insertions(+), 7 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html index ca70ad2a57..9bfc50d36e 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.html @@ -136,7 +136,7 @@
+ [disabled]="isUploading" (click)="upload()" i18n>Upload
@@ -148,6 +148,22 @@ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts index ee49b5fe27..8f933ef0f6 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/import.component.ts @@ -1,6 +1,10 @@ import {Component, OnInit, AfterViewInit, Input, ViewChild} from '@angular/core'; +import {tap} from 'rxjs/operators/tap'; import {IdlObject} from '@eg/core/idl.service'; +import {NetService} from '@eg/core/net.service'; +import {EventService} from '@eg/core/event.service'; import {OrgService} from '@eg/core/org.service'; +import {AuthService} from '@eg/core/auth.service'; import {ToastService} from '@eg/share/toast/toast.service'; import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; import {VandelayService} from './vandelay.service'; @@ -37,15 +41,30 @@ export class ImportComponent implements OnInit, AfterViewInit { minQualityRatio: number; autoOverlayAcqCopies: boolean; + // True after the first upload, then remains true. showProgress: boolean; + // Upload in progress. + isUploading: boolean; + + // Upload / processsing session key + // Generated by the server + sessionKey: string; + @ViewChild('fileSelector') private fileSelector; @ViewChild('uploadProgress') private uploadProgress: ProgressInlineComponent; + @ViewChild('enqueueProgress') + private enqueueProgress: ProgressInlineComponent; + @ViewChild('importProgress') + private importProgress: ProgressInlineComponent; constructor( private http: HttpClient, private toast: ToastService, + private evt: EventService, + private net: NetService, + private auth: AuthService, private org: OrgService, private vandelay: VandelayService ) { @@ -125,27 +144,90 @@ export class ImportComponent implements OnInit, AfterViewInit { this.selectedFile = $event.target.files[0]; } + // Required form data varies depending on context. + confirmNeededData(): boolean { + if (!this.selectedQueue) { + return false; + } + return true; + } + + // 1. create queue if necessary + // 2. upload MARC file + // 3. Enqueue MARC records + // 4. Import records upload() { + if (!this.confirmNeededData()) { return; } + + this.sessionKey = null; this.showProgress = true; + this.isUploading = true; this.uploadProgress.reset(); + this.enqueueProgress.update({value: 0, max: 1}); + this.importProgress.update({value: 0, max: 1}); + + let useQueueId; // find or create + + this.resolveQueue() + .then( + queueId => { + useQueueId = queueId; + return this.uploadFile(); + }, + err => { + this.isUploading = false; + } + ).then( + ok => this.processSpool(useQueueId), + err => { + this.isUploading = false; + } + ); + } + + // Extract selected queue ID or create a new queue when requested. + resolveQueue(): Promise { + if (this.selectedQueue.freetext) { + // Free text queue selector means create a new entry. + // TODO: first check for name dupes + + return this.vandelay.createQueue( + this.selectedQueue.label, + this.recordType, + this.selectedHoldingsProfile, + this.selectedMatchSet, + this.selectedBucket + ); + + } else { + return Promise.resolve(this.selectedQueue.id); + } + } + + uploadFile(): Promise { const formData: FormData = new FormData(); - formData.append( - 'marc_upload', this.selectedFile, this.selectedFile.name); - // TODO: fill in other fields + formData.append('marc_upload', + this.selectedFile, this.selectedFile.name); + + if (this.selectedBibSource) { + formData.append('bib_source', ''+this.selectedBibSource); + } const req = new HttpRequest('POST', VAND_UPLOAD_URL, formData, {reportProgress: true, responseType: 'text'}); - this.http.request(req).subscribe( + return this.http.request(req).pipe(tap( evt => { if (evt.type === HttpEventType.UploadProgress) { this.uploadProgress.update( {value: evt.loaded, max: evt.total}); } else if (evt instanceof HttpResponse) { - console.log('file uploaded OK'); + this.sessionKey = evt.body as string; + console.log( + 'Vandelay file uploaded OK with key '+this.sessionKey); } }, @@ -154,8 +236,34 @@ export class ImportComponent implements OnInit, AfterViewInit { console.error(err); this.toast.danger(err.error.error); } - ); + )).toPromise(); + } + //processSpool(key, queueId, type, onload) { + processSpool(queueId: number): Promise { + const rtype = this.recordType === 'bib' ? 'bib' : 'authority'; + const method = `open-ils.vandelay.${rtype}.process_spool`; + + return this.net.request( + 'open-ils.vandelay', method, + this.auth.token(), this.sessionKey, queueId + ).pipe(tap( + resp => { + const e = this.evt.parse(resp); + if (e) { + console.log(e); + return; + } + + // the enqeueu process currently only returns the + // number of items processed. + this.enqueueProgress.update({max: null, value: resp}); + }, + err => {}, + () => this.enqueueProgress.update({max: 1, value: 1}) + + )).toPromise(); } + } diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.service.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.service.ts index caa7ca3256..99cc673575 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.service.ts @@ -1,6 +1,7 @@ import {Injectable, EventEmitter} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import {tap} from 'rxjs/operators/tap'; +import {map} from 'rxjs/operators/map'; import {IdlService, IdlObject} from '@eg/core/idl.service'; import {OrgService} from '@eg/core/org.service'; import {NetService} from '@eg/core/net.service'; @@ -180,5 +181,36 @@ export class VandelayService { }); } + + // Create a queue and return the ID of the new queue via promise. + createQueue( + queueName: string, + recordType: string, + importDefId: number, + matchSet: number, + matchBucket: number): Promise { + + const name = recordType === 'bib' ? 'bib' : 'authority'; + const method = `open-ils.vandelay.${name}_queue.create`; + + let qType = name; + if (recordType.match(/acq/)) { + let qType = 'acq'; + } + + return this.net.request( + 'open-ils.vandelay', method, + this.auth.token(), queueName, null, qType, + matchSet, importDefId, matchBucket + ).pipe(map(queue => { + const e = this.evt.parse(queue); + if (e) { + console.error(e); + return null; + } + return queue.id(); + })).toPromise(); + } + } -- 2.11.0