From: Bill Erickson Date: Fri, 29 Jun 2018 22:30:15 +0000 (-0400) Subject: LP#1779158 Angular vandelay starting import form X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=2dfaa500ac235c647e3fbd385ed8d1b0de1f444e;p=working%2FEvergreen.git LP#1779158 Angular vandelay starting import form Signed-off-by: Bill Erickson --- 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 41a4880ddd..944a368ac8 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 @@ -1 +1 @@ -EXPORT COMPONENT +EXPORT 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 83bbc2d19a..e8b65e4e2c 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 @@ -1,2 +1,36 @@ -IMPORT COMPONENT + + +
+

MARC File Upload

+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + 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 40c65a5c6d..7ae7ee3710 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,14 +1,88 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, AfterViewInit, Input, ViewChild} from '@angular/core'; +import {IdlObject} from '@eg/core/idl.service'; +import {OrgService} from '@eg/core/org.service'; +import {TypeaheadEntry} from '@eg/share/typeahead/typeahead.component'; +import {VandelayService} from './vandelay.service'; +import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; @Component({ templateUrl: 'import.component.html' }) -export class ImportComponent implements OnInit { +export class ImportComponent implements OnInit, AfterViewInit { - constructor() {} + recordType: string; + newQueueName: string; + queueEntries: TypeaheadEntry[]; + allQueues: {[qtype: string]: IdlObject[]}; + activeQueues: {[qtype: string]: IdlObject[]}; + attrDefs: {[atype: string]: IdlObject[]}; + bibSources: IdlObject[]; + bibBuckets: IdlObject[]; + matchSets: {[stype: string]: IdlObject[]}; + defaultMatchSet: string; - ngOnInit() { + @ViewChild('progressDialog') + private progressDialog: ProgressDialogComponent; + + constructor( + private org: OrgService, + private vandelay: VandelayService + ) { + this.recordType = 'bib'; + this.queueEntries = []; + this.attrDefs = {}; + this.matchSets = {}; + this.activeQueues = {}; + } + + ngOnInit() {} + + ngAfterViewInit() { + // loading startup data changes our data in the midst of a + // lifecycle hook. Run after timeout. + setTimeout(() => this.loadStartupData()); + } + + // Display record-typ appropriate data when the record type changes + recordTypeChanged($event) { + //this.formatQueueSelector(); } + loadStartupData() { + this.progressDialog.open(); + + const promises = [ + this.vandelay.getAttrDefs('bib') + .then(defs => this.attrDefs.bib = defs), + this.vandelay.getAttrDefs('auth') + .then(defs => this.attrDefs.auth = defs), + this.vandelay.getActiveQueues('bib') + .then(queues => { + this.activeQueues.bib = queues; + this.formatQueueSelector(); + }), + this.vandelay.getActiveQueues('auth') + .then(queues => this.activeQueues.auth = queues), + this.vandelay.getMatchSets() + .then(sets => this.matchSets = sets), + this.vandelay.getBibBuckets() + .then(bkts => this.bibBuckets = bkts), + this.vandelay.getBibSources() + .then(srcs => this.bibSources = srcs), + this.org.settings(['vandelay.default_match_set']).then( + s => this.defaultMatchSet = s['vandelay.default_match_set']) + ]; + + this.progressDialog.update({value: 0, max: promises.length}); + promises.forEach(p => p.then(() => this.progressDialog.increment())); + Promise.all(promises).then(() => this.progressDialog.close()); + } + + formatQueueSelector() { + const queues = this.activeQueues[this.recordType]; + this.queueEntries = queues.map(q => { + return {id: q.id(), label: q.name()}; + }); + } } 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 232f51f9a3..c37e172ff3 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 @@ -7,7 +7,6 @@ import {ExportComponent} from './export.component'; const routes: Routes = [{ path: '', component: VandelayComponent, - //resolve: {vandelayResolver : VandelayResolver}, children: [{ path: '', pathMatch: 'full', diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.html b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.html index 07db35f2be..e399b43206 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.html @@ -1,3 +1,5 @@ + + - - + diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.ts index 9239f11453..0bfad42d5c 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/vandelay.component.ts @@ -1,7 +1,6 @@ import {Component, OnInit, AfterViewInit, ViewChild} from '@angular/core'; import {Router, ActivatedRoute, NavigationEnd} from "@angular/router"; import {take} from 'rxjs/operators/take'; -import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; import {VandelayService} from './vandelay.service'; import {IdlObject} from '@eg/core/idl.service'; @@ -9,22 +8,8 @@ import {IdlObject} from '@eg/core/idl.service'; templateUrl: 'vandelay.component.html' }) export class VandelayComponent implements OnInit, AfterViewInit { - tab: string; - attrDefs = {bib: [], auth: []}; - allQueues = {bib: [], auth: []}; - activeQueues = {bib: [], auth: []}; // complete === 'f' - bibSources: IdlObject[]; - bibBuckets: IdlObject[]; - bibTrashGroups: IdlObject[]; - copyStatuses: IdlObject[]; - importItemDefs: IdlObject[]; - matchSets: {[stype: string]: IdlObject[]}; - - @ViewChild('progressDialog') - private progressDialog: ProgressDialogComponent; - constructor( private router: Router, private route: ActivatedRoute, @@ -40,68 +25,10 @@ export class VandelayComponent implements OnInit, AfterViewInit { .subscribe(segments => this.tab = segments[0].path); } }); - - this.attachDataListeners(); - } - - ngOnInit() { - } - - // Manage the shared data here so it persists across tabs. - // Load the shared data after view init so the page can initialize - // first and display the loading message. - ngAfterViewInit() { - - // loading startup data causes data in this component to change - // inside its own lifecycle hook, which is a no-no. Run after - // the hook. - setTimeout(() => { - - this.vandelay.loadStartupData(this.progressDialog).then(ok => { - - // Pull data that does not change during a vandelay - // UI directly from the service. - this.bibSources = this.vandelay.bibSources; - this.bibBuckets = this.vandelay.bibBuckets; - this.bibTrashGroups = this.vandelay.bibTrashGroups; - this.copyStatuses = this.vandelay.copyStatuses; - }); - }); } + ngOnInit() {} - // Listen for global data changes, store data locally so it - // may be propagated to child components. - attachDataListeners() { - - this.vandelay.onAttrDefsUpdate$.subscribe(collection => { - const dtype = collection.dtype; - this.attrDefs[dtype] = collection.defs; - }); - - // Bib/auth queue list - this.vandelay.onQueueListUpdate$.subscribe(collection => { - const qtype = collection.qtype; - collection.queues.forEach(q => { - this.allQueues[qtype] = q; - if (q.complete() === 'f') { - this.activeQueues[qtype] = q; - } - }); - }); - - this.vandelay.onItemImportDefsUpdate$.subscribe( - defs => this.importItemDefs = defs - ); - - this.vandelay.onMatchSetsUpdate$.subscribe(sets => { - sets.forEach(s => { - if (!this.matchSets[s.mtype()]) { - this.matchSets[s.mtype()] = []; - } - this.matchSets[s.mtype()].push(s); - }); - }); - } + ngAfterViewInit() {} } 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 cf8e7fbcd4..44133262ba 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 @@ -13,21 +13,15 @@ import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; @Injectable() export class VandelayService { - // Data that may change within the vandelay UI is propagated - // via EventEmitters - onQueueListUpdate$: EventEmitter; - onItemImportDefsUpdate$: EventEmitter; - onMatchSetsUpdate$: EventEmitter; - onAttrDefsUpdate$: EventEmitter; - - // Data that persists during a vandelay session needs no emitters. + allQueues: {[qtype: string]: IdlObject[]}; + activeQueues: {[qtype: string]: IdlObject[]}; + attrDefs: {[atype: string]: IdlObject[]}; bibSources: IdlObject[]; bibBuckets: IdlObject[]; - bibTrashGroups: IdlObject[]; copyStatuses: IdlObject[]; - - // Settings to retrieve (and cache) at load time. - orgSettings = ['vandelay.default_match_set']; + matchSets: {[stype: string]: IdlObject[]}; + importItemAttrDefs: IdlObject[]; + bibTrashGroups: IdlObject[]; constructor( private idl: IdlService, @@ -38,141 +32,126 @@ export class VandelayService { private pcrud: PcrudService, private perm: PermService ) { - this.onQueueListUpdate$ = new EventEmitter(); - this.onItemImportDefsUpdate$ = new EventEmitter(); - this.onMatchSetsUpdate$ = new EventEmitter(); - this.onAttrDefsUpdate$ = new EventEmitter(); - } - - loadStartupData(dialog: ProgressDialogComponent): Promise { - - dialog.open(); - - const promises = [ - this.getAttrDefs('bib').toPromise(), - this.getAttrDefs('auth').toPromise(), - this.getQueueList('bib').toPromise(), - this.getQueueList('auth').toPromise(), - this.getItemImportDefs().toPromise(), - this.getMatchSets().toPromise(), - this.getBibBuckets(), - this.getBibSources(), - this.getBibTrashGroups(), - this.getCopyStatuses(), - this.org.settings(this.orgSettings) - ]; - - dialog.update({value: 0, max: promises.length}); - promises.forEach(p => p.then(_ => dialog.increment())); - - return Promise.all(promises).then(ok => dialog.close()); + this.attrDefs = {}; + this.activeQueues = {}; + this.allQueues = {}; + this.matchSets = {}; } - getAttrDefs(dtype: string): Observable { + getAttrDefs(dtype: string): Promise { + if (this.attrDefs[dtype]) { + return Promise.resolve(this.attrDefs[dtype]); + } const cls = (dtype === 'bib') ? 'vqbrad' : 'vqarad'; - const defs = []; - const orderBy = {}; orderBy[cls] = 'id' - - return this.pcrud.retrieveAll(cls, {order_by: orderBy}) - .pipe(tap( - def => defs.push(def), - err => {}, - () => { - console.debug(`Fetched ${defs.length} ${dtype} attr def(s)`); - this.onAttrDefsUpdate$.emit({dtype: dtype, defs: defs}); - } - )); + return this.pcrud.retrieveAll(cls, + {order_by: orderBy}, {atomic: true}).toPromise() + .then(list => { + this.attrDefs[dtype] = list; + return list; + }); } // Returns a promise resolved with the list of queues. // Also emits the onQueueListUpdate event so listeners // can detect queue content changes. - getQueueList(qtype: string, filters?: any): Observable { - const qt = (qtype === 'bib') ? qtype : 'authority'; - const queues = []; + getActiveQueues(qtype: string): Promise { + if (this.activeQueues[qtype]) { + return Promise.resolve(this.activeQueues[qtype]); + } + // could be a big list, invoke in streaming mode + const queues = []; + const qt = (qtype === 'bib') ? qtype : 'authority'; return this.net.request( 'open-ils.vandelay', `open-ils.vandelay.${qt}_queue.owner.retrieve`, - this.auth.token(), null, filters + this.auth.token(), null, {complete: 'f'} ).pipe(tap( queue => { - const evt = this.evt.parse(queue); - if (evt) { return alert(evt); } // should not happen - queues.push(queue); - }, - err => {console.error(err)}, - () => { - console.debug(`Fetched ${queues.length} "${qtype}" queue(s)`); - this.onQueueListUpdate$.emit({qtype: qtype, queues: queues}); + if (!this.activeQueues[qtype]) { + this.activeQueues[qtype] = []; + } + this.activeQueues[qtype].push(queue); } - )); + )).toPromise().then(() => queues); } - getBibSources(): Promise { + getBibSources(): Promise { + if (this.bibSources) { + return Promise.resolve(this.bibSources); + } + return this.pcrud.retrieveAll('cbs', {order_by: {cbs: 'id'}}, {atomic: true} ).toPromise().then(sources => { - console.debug(`Fetched ${sources.length} bib source(s)`); this.bibSources = sources; + return sources; }); } - getItemImportDefs(): Observable { - const defs = []; - const owners = this.org.ancestors(this.auth.user().ws_ou(), true); + getItemImportDefs(): Promise { + if (this.importItemAttrDefs) { + return Promise.resolve(this.importItemAttrDefs); + } - return this.pcrud.search('viiad', {owner: owners}) - .pipe(tap( - def => defs.push(def), - err => {}, - () => { - console.debug(`Fetched ${defs.length} import item def(s)`); - this.onItemImportDefsUpdate$.emit(defs); - } - )); + const owners = this.org.ancestors(this.auth.user().ws_ou(), true); + return this.pcrud.search('viiad', {owner: owners}, {atomic: true}) + .toPromise().then(defs => { + this.importItemAttrDefs = defs; + return defs; + }); } - getMatchSets(): Observable { - const sets = []; + getMatchSets(): Promise<{[mtype:string]: IdlObject[]}> { + if (this.matchSets) { + return Promise.resolve(this.matchSets); + } + const owners = this.org.ancestors(this.auth.user().ws_ou(), true); return this.pcrud.search('vms', {owner: owners}) - .pipe(tap( - s => sets.push(s), - err => {}, - () => { - console.debug(`Fetched ${sets.length} match set(s)`); - this.onMatchSetsUpdate$.emit(sets); - } - )); + .toPromise().then(sets => { + sets.forEach(s => { + if (!this.matchSets[s.mtype()]) { + this.matchSets[s.mtype()] = []; + } + this.matchSets[s.mtype()].push(s); + }); + return this.matchSets; + }); } - getBibBuckets(): Promise { - this.bibBuckets = []; + getBibBuckets(): Promise { + if (this.bibBuckets) { + return Promise.resolve(this.bibBuckets); + } + const bkts = []; return this.net.request( 'open-ils.actor', 'open-ils.actor.container.retrieve_by_class', this.auth.token(), this.auth.user().id(), 'biblio', 'staff_client' - ).pipe(tap( - bkt => this.bibBuckets.push(bkt), - err => {}, - () => console.debug(`Fetched ${this.bibBuckets.length} bucket(s)`) - )).toPromise(); + ).pipe(tap(bkt => bkts.push(bkt))).toPromise().then(() => bkts); } getCopyStatuses(): Promise { + if (this.copyStatuses) { + return Promise.resolve(this.copyStatuses); + } return this.pcrud.retrieveAll('ccs', {}, {atomic: true}) .toPromise().then(stats => { - console.debug(`Fetched ${stats.length} copy status(es)`); this.copyStatuses = stats; + return stats; }); } getBibTrashGroups(): Promise { + if (this.bibTrashGroups) { + return Promise.resolve(this.bibTrashGroups); + } + const owners = this.org.ancestors(this.auth.user().ws_ou(), true); return this.pcrud.search('vibtg', @@ -180,11 +159,10 @@ export class VandelayService { {vibtg : ['label']}, {atomic: true} ).toPromise().then(groups => { - console.debug(`Fetched ${groups.length} bib trash field group(s)`); this.bibTrashGroups = groups; + return groups; }); } - }