-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()};
+ });
+ }
}
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';
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,
.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() {}
}
@Injectable()
export class VandelayService {
- // Data that may change within the vandelay UI is propagated
- // via EventEmitters
- onQueueListUpdate$: EventEmitter<any>;
- onItemImportDefsUpdate$: EventEmitter<IdlObject[]>;
- onMatchSetsUpdate$: EventEmitter<IdlObject[]>;
- onAttrDefsUpdate$: EventEmitter<any>;
-
- // 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,
private pcrud: PcrudService,
private perm: PermService
) {
- this.onQueueListUpdate$ = new EventEmitter<any>();
- this.onItemImportDefsUpdate$ = new EventEmitter<IdlObject[]>();
- this.onMatchSetsUpdate$ = new EventEmitter<IdlObject[]>();
- this.onAttrDefsUpdate$ = new EventEmitter<any>();
- }
-
- loadStartupData(dialog: ProgressDialogComponent): Promise<any> {
-
- 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<IdlObject> {
+ getAttrDefs(dtype: string): Promise<IdlObject[]> {
+ 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<IdlObject> {
- const qt = (qtype === 'bib') ? qtype : 'authority';
- const queues = [];
+ getActiveQueues(qtype: string): Promise<IdlObject[]> {
+ 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<any> {
+ getBibSources(): Promise<IdlObject[]> {
+ 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<IdlObject> {
- const defs = [];
- const owners = this.org.ancestors(this.auth.user().ws_ou(), true);
+ getItemImportDefs(): Promise<IdlObject[]> {
+ 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<IdlObject[]> {
- 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<any> {
- this.bibBuckets = [];
+ getBibBuckets(): Promise<IdlObject[]> {
+ 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<any> {
+ 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<any> {
+ if (this.bibTrashGroups) {
+ return Promise.resolve(this.bibTrashGroups);
+ }
+
const owners = this.org.ancestors(this.auth.user().ws_ou(), true);
return this.pcrud.search('vibtg',
{vibtg : ['label']},
{atomic: true}
).toPromise().then(groups => {
- console.debug(`Fetched ${groups.length} bib trash field group(s)`);
this.bibTrashGroups = groups;
+ return groups;
});
}
-
}