From 203bc8962e839966992f88d47c2883c35325a87b Mon Sep 17 00:00:00 2001 From: Chris Sharp Date: Tue, 16 Nov 2021 17:12:16 -0500 Subject: [PATCH] Revert "LP1929741 Finetuning LMOR based on LP comments" This reverts commit f7d72c50822df9cd8e75a8abaa03ae0335c67721. --- .../app/staff/acq/picklist/upload.component.html | 49 ++++---- .../src/app/staff/acq/picklist/upload.component.ts | 129 +++++++++++++-------- .../src/app/staff/acq/picklist/upload.service.ts | 110 ++++++++++++------ 3 files changed, 178 insertions(+), 110 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.html b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.html index 567b8fc1f8..3feac3fe55 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.html +++ b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.html @@ -5,6 +5,15 @@
Legacy Upload Interface
+
+
+ +
+
@@ -69,6 +78,7 @@
@@ -94,7 +104,6 @@ id="year-select" [startId]="selectedFiscalYear" [entries]="formatEntries('fiscalYears')" - [required]="true" (onChange)="selectEntry($event, 'fiscalYears')">
@@ -109,8 +118,7 @@ id="sl-select" [startId]="selectedSelectionList" [entries]="formatEntries('selectionLists')" - (onChange)="selectedSelectionList=$event" i18n-placeholder - [allowFreeText]="true"> + (onChange)="selectEntry($event, 'selectionLists')"> @@ -120,13 +128,14 @@
- +
@@ -135,6 +144,7 @@
@@ -149,6 +159,7 @@ id="match-set-select" [entries]="formatEntries('matchSets')" [disabled]="(selectedQueue && !selectedQueue.freetext) || importSelection()" + [required]="true" [startId]="selectedMatchSet || defaultMatchSet" (onChange)="selectEntry($event, 'matchSets')"> @@ -169,6 +180,7 @@
@@ -232,7 +244,9 @@
@@ -271,30 +285,21 @@ (click)="upload()" i18n>Upload
-
+
- +
- -
-

+
+
- -
-
-

-
-
-
-
- -
- - - +
+
+ Queue
+
+
\ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.ts b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.ts index 86b691874e..9c1a32d10d 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.component.ts @@ -26,7 +26,6 @@ const TEMPLATE_SETTING_NAME = 'eg.acq.picklist.upload.templates'; const TEMPLATE_ATTRS = [ 'createPurchaseOrder', 'activatePurchaseOrder', - 'selectedProvider', 'orderingAgency', 'selectedFiscalYear', 'loadItems', @@ -56,6 +55,11 @@ const ORG_SETTINGS = [ 'acq.upload.default.vandelay.quality_ratio' ]; +interface ImportOptions { + session_key: string; + overlay_map?: {[qrId: number]: /* breId */ number}; + exit_early: boolean; +} @Component({ templateUrl: './upload.component.html' @@ -64,14 +68,16 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { settings: Object = {}; recordType: string; - selectedQueue: ComboboxEntry; + selectedQueue: ComboboxEntry; // freetext enabled + // used for applying a default queue ID value when we have + // a load-time queue before the queue combobox entries exist. + startQueueId: number; - activeSelectionListId: number; activeQueueId: number; orderingAgency: number; selectedFiscalYear: number; - selectedSelectionList: ComboboxEntry; + selectedSelectionList: number; selectedBibSource: number; selectedProvider: number; selectedMatchSet: number; @@ -79,7 +85,6 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { selectedMergeProfile: number; selectedFallThruMergeProfile: number; selectedFile: File; - newPO: number; defaultMatchSet: string; @@ -93,13 +98,20 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { mergeOnBestMatch: boolean; minQualityRatio: number; + // True after the first upload, then remains true. + showProgress: boolean; + + // Upload in progress. isUploading: boolean; - uploadProcessing: boolean; + + // True only after successful upload uploadComplete: boolean; + // Upload / processsing session key // Generated by the server sessionKey: string; + selectedTemplate: string; formTemplates: {[name: string]: any}; newTemplateName: string; @@ -108,6 +120,7 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('uploadProgress', { static: true }) private uploadProgress: ProgressInlineComponent; + // Need these refs so values can be applied via external stimuli @ViewChild('formTemplateSelector', { static: true }) private formTemplateSelector: ComboboxComponent; @ViewChild('bibSourceSelector', { static: true }) @@ -162,6 +175,7 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { this.minQualityRatio = 0; this.recordType = 'bib'; this.formTemplates = {}; +//To-do add default for fiscal year if (this.vlagent.importSelection) { if (!this.vlagent.importSelection.queue) { @@ -171,8 +185,14 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { } const queue = this.vlagent.importSelection.queue; + this.recordType = queue.queue_type(); this.selectedMatchSet = queue.match_set(); + // This will be propagated to selectedQueue as a combobox + // entry via the combobox + this.startQueueId = queue.id(); + + } } @@ -183,6 +203,8 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { } ngOnDestroy() { + // Always clear the import selection when navigating away from + // the import page. this.clearSelection(); } @@ -202,8 +224,8 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { this.vlagent.getProvidersList(), this.vlagent.getSelectionLists(), this.vlagent.getItemImportDefs(), - this.org.settings(['vandelay.default_match_set']).then( - s => this.defaultMatchSet = s['vandelay.default_match_set']), + this.org.settings(['vandelay.default_match_set']).then( + s => this.defaultMatchSet = s['vandelay.default_match_set']), this.loadTemplates() ]; @@ -238,6 +260,7 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { return entries; } + // Format typeahead data sets formatEntries(etype: string): ComboboxEntry[] { const rtype = this.recordType; let list; @@ -267,7 +290,8 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { break; case 'activeQueues': - list = (this.vlagent.allQueues[rtype] || []); + list = (this.vlagent.allQueues[rtype] || []) + .filter(q => q.complete() === 'f'); break; case 'matchSets': @@ -332,22 +356,34 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { this.selectedFile = $event.target.files[0]; } + // Required form data varies depending on context. hasNeededData(): boolean { - return this.selectedQueue && - Boolean(this.selectedFile) && - Boolean(this.selectedFiscalYear) && - Boolean(this.selectedProvider) && - Boolean(this.orderingAgency); + if (this.vlagent.importSelection) { + return this.importActionSelected(); + } else { + return this.selectedQueue && + Boolean(this.recordType) && Boolean(this.selectedFile); + } + } + + importActionSelected(): boolean { + return this.importNonMatching + || this.mergeOnExact + || this.mergeOnSingleMatch + || this.mergeOnBestMatch; } - - + + // 1. create queue if necessary + // 2. upload MARC file + // 3. Enqueue MARC records + // 4. Import records upload() { this.sessionKey = null; + this.showProgress = true; this.isUploading = true; this.uploadComplete = false; this.resetProgressBars(); - this.resolveSelectionList(), this.resolveQueue() .then( queueId => { @@ -376,9 +412,13 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { this.uploadProgress.update({value: 0, max: 1}); } + // 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.vlagent.createQueue( this.selectedQueue.label, this.recordType, @@ -404,28 +444,10 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { } } - resolveSelectionList(): Promise { - if (!this.selectedSelectionList) { - return Promise.resolve() - } - if (this.selectedSelectionList.id) { - this.activeSelectionListId = this.selectedSelectionList.id - } - if (this.selectedSelectionList.freetext) { - - return this.vlagent.createSelectionList( - this.selectedSelectionList.label, - this.orderingAgency - ).then( - value => this.activeSelectionListId = value - ); - } - return Promise.resolve(this.activeSelectionListId); - } - uploadFile(): Promise { if (this.vlagent.importSelection) { + // Nothing to upload when processing pre-queued records. return Promise.resolve(); } @@ -464,12 +486,10 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { processUpload(): Promise { - this.uploadProcessing = true; - if (this.vlagent.importSelection) { return Promise.resolve(); } - + let spoolType = this.recordType; const vandelayOptions = { @@ -483,8 +503,10 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { bib_source: this.selectedBibSource, create_assets: this.loadItems, queue_name: this.selectedQueue.label + } + const args = { provider: this.selectedProvider, @@ -492,7 +514,7 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { create_po: this.createPurchaseOrder, activate_po: this.activatePurchaseOrder, fiscal_year: this.selectedFiscalYear, - picklist: this.activeSelectionListId, + picklist: this.selectedSelectionList, vandelay: vandelayOptions } @@ -504,15 +526,9 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { 'open-ils.acq', method, this.auth.token(), this.sessionKey, args ).subscribe( - progress => { - const resp = this.evt.parse(progress); - console.log(progress); - if (resp) { console.error(resp); return reject();} - if (progress.complete) { - this.uploadProcessing = false; - this.uploadComplete = true; - } - if (progress.purchase_order) {this.newPO = progress.purchase_order.id();} + tracker => { + const e = this.evt.parse(tracker); + if (e) { console.error(e); return reject(); } } ); }); @@ -520,9 +536,12 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { clearSelection() { this.vlagent.importSelection = null; - this.activeSelectionListId = null; + this.startQueueId = null; } + openQueue() { + console.log('opening queue ' + this.activeQueueId); + } saveTemplate() { @@ -556,19 +575,27 @@ export class UploadComponent implements OnInit, AfterViewInit, OnDestroy { this.selectedTemplate = entry.label; // label == name if (entry.freetext) { + // User is entering a new template name. + // Nothing to apply. return; } + // User selected an existing template, apply it to the form. + const template = this.formTemplates[entry.id]; + // Copy the template values into "this" TEMPLATE_ATTRS.forEach(key => this[key] = template[key]); + // Some values must be manually passed to the combobox'es + this.bibSourceSelector.applyEntryId(this.selectedBibSource); this.matchSetSelector.applyEntryId(this.selectedMatchSet); this.providerSelector.applyEntryId(this.selectedProvider); this.fiscalYearSelector.applyEntryId(this.selectedFiscalYear); this.mergeProfileSelector.applyEntryId(this.selectedMergeProfile); - this.fallThruMergeProfileSelector.applyEntryId(this.selectedFallThruMergeProfile); + this.fallThruMergeProfileSelector + .applyEntryId(this.selectedFallThruMergeProfile); } deleteTemplate() { diff --git a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.service.ts b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.service.ts index 0cf0718f36..a5861660cd 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/picklist/upload.service.ts @@ -11,7 +11,7 @@ import {PcrudService} from '@eg/core/pcrud.service'; import {PermService} from '@eg/core/perm.service'; import {EventService} from '@eg/core/event.service'; import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; -import {VandelayImportSelection} from '@eg/staff/cat/vandelay/vandelay.service' +import {VandelayImportSelection, VANDELAY_EXPORT_PATH} from '@eg/staff/cat/vandelay/vandelay.service' @Injectable() @@ -26,12 +26,16 @@ export class PicklistUploadService { providersList: IdlObject[]; fiscalYears: IdlObject[]; selectionLists: IdlObject[]; - queueType: string; - recordType: string; - + // Used for tracking records between the queue page and + // the import page. Fields managed externally. importSelection: VandelayImportSelection; + // Track the last grid offset in the queue page so we + // can return the user to the same page of data after + // going to the matches page. + queuePageOffset: number; + constructor( private http: HttpClient, private idl: IdlService, @@ -46,8 +50,7 @@ export class PicklistUploadService { this.allQueues = {}; this.matchSets = {}; this.importSelection = null; - this.queueType = 'acq'; - this.recordType = 'bib'; + this.queuePageOffset = 0; } getAttrDefs(dtype: string): Promise { @@ -106,7 +109,7 @@ export class PicklistUploadService { return lists; }); } - + // Returns a promise resolved with the list of queues. getAllQueues(qtype: string): Promise { if (this.allQueues[qtype]) { return Promise.resolve(this.allQueues[qtype]); @@ -114,9 +117,10 @@ export class PicklistUploadService { this.allQueues[qtype] = []; } + // could be a big list, invoke in streaming mode return this.net.request( 'open-ils.vandelay', - `open-ils.vandelay.bib_queue.owner.retrieve`, + `open-ils.vandelay.${qtype}_queue.owner.retrieve`, this.auth.token() ).pipe(tap( queue => this.allQueues[qtype].push(queue) @@ -164,9 +168,10 @@ export class PicklistUploadService { }); } + // todo: differentiate between biblio and authority a la queue api getMatchSets(mtype: string): Promise { - const mstype = 'biblio' + const mstype = mtype.match(/bib/) ? 'biblio' : 'authority'; if (this.matchSets[mtype]) { return Promise.resolve(this.matchSets[mtype]); @@ -185,57 +190,88 @@ export class PicklistUploadService { } + + + + + // Create a queue and return the ID of the new queue via promise. createQueue( queueName: string, - queueType: string, + recordType: string, importDefId: number, matchSet: number): Promise { - const method = `open-ils.vandelay.bib_queue.create`; - queueType = 'acq'; + const method = `open-ils.vandelay.${recordType}_queue.create`; + let qType = recordType; + if (recordType.match(/acq/)) { + qType = 'bib'; + } return new Promise((resolve, reject) => { this.net.request( 'open-ils.vandelay', method, - this.auth.token(), queueName, null, queueType, + this.auth.token(), queueName, null, qType, matchSet, importDefId ).subscribe(queue => { const e = this.evt.parse(queue); if (e) { reject(e); } else { - this.allQueues['bib'].push(queue); + // createQueue is always called after queues have + // been fetched and cached. + this.allQueues[qType].push(queue); resolve(queue.id()); } }); }); } - createSelectionList( - picklistName: string, - picklistOrg: number - ): Promise { + getQueuedRecords(queueId: number, queueType: string, + options?: any, limitToMatches?: boolean): Observable { - const newpicklist = this.idl.create('acqpl'); - newpicklist.owner(this.auth.user().id()); - newpicklist.name(picklistName); - newpicklist.org_unit(picklistOrg) - - return new Promise((resolve, reject) => { - this.net.request( - 'open-ils.acq', 'open-ils.acq.picklist.create', - this.auth.token(), newpicklist - ).subscribe((picklist) => { - if (this.evt.parse(picklist)) { - console.error(picklist); - } else { - console.log(picklist); - resolve(picklist); - } - }); - }); + const qtype = queueType.match(/bib/) ? 'bib' : 'auth'; + + let method = + `open-ils.vandelay.${qtype}_queue.records.retrieve`; + + if (limitToMatches) { + method = + `open-ils.vandelay.${qtype}_queue.records.matches.retrieve`; + } + + return this.net.request('open-ils.vandelay', + method, this.auth.token(), queueId, options); + } + + // Download a queue as a MARC file. + exportQueue(queue: IdlObject, nonImported?: boolean) { + + const etype = queue.queue_type().match(/auth/) ? 'auth' : 'bib'; + + let url = + `${VANDELAY_EXPORT_PATH}?type=bib&queueid=${queue.id()}`; + + let saveName = queue.name(); + + if (nonImported) { + url += '&nonimported=1'; + saveName += '_nonimported'; + } + + saveName += '.mrc'; + + this.http.get(url, {responseType: 'text'}).subscribe( + data => { + saveAs( + new Blob([data], {type: 'application/octet-stream'}), + saveName + ); + }, + err => { + console.error(err); + } + ); } - } -- 2.11.0