<div class="ml-auto mr-3"><a i18n href="/eg/staff/acq/legacy/picklist/upload">Legacy Upload Interface</a></div>
</div>
-<div class="row mb-3" *ngIf="importSelection()">
- <div class="col-lg-2" *ngIf="selectedQueue">
- <button class="btn btn-info label-with-material-icon"
- routerLink="/staff/cat/vandelay/queue/{{recordType}}/{{selectedQueue.id}}">
- <span class="material-icons">arrow_back</span>
- <span i18n>Return to Queue</span>
- </button>
- </div>
-</div>
<eg-alert-dialog #dupeQueueAlert i18n-dialogBody
dialogBody="A queue with the requested name already exists.">
</div>
<div class="col-lg-3">
<eg-org-select
- [initialOrgId]="1"
[applyOrgId]="orderingAgency"
(onChange)="orgOnChange($event)">
</eg-org-select>
id="year-select"
[startId]="selectedFiscalYear"
[entries]="formatEntries('fiscalYears')"
+ [required]="true"
(onChange)="selectEntry($event, 'fiscalYears')">
</eg-combobox>
</div>
id="sl-select"
[startId]="selectedSelectionList"
[entries]="formatEntries('selectionLists')"
- (onChange)="selectEntry($event, 'selectionLists')">
+ (onChange)="selectedSelectionList=$event" i18n-placeholder
+ [allowFreeText]="true">
</eg-combobox>
</div>
</div>
<div class="row">
<div class="col-lg-3">
- <label for="source-select" i18n>Select a Record Source</label>
+ <label for="source-select" i18n>Record Source</label>
</div>
<div class="col-lg-3">
<eg-combobox #bibSourceSelector
id="source-select"
[entries]="formatEntries('bibSources')"
(onChange)="selectEntry($event, 'bibSources')"
- [required]="true"
[startId]="selectedBibSource">
</eg-combobox>
</div>
</div>
<div class="col-lg-3">
<input class="form-check-input" type="checkbox"
- [required]="true"
id="import-non-matching"
[(ngModel)]="importNonMatching">
</div>
id="match-set-select"
[entries]="formatEntries('matchSets')"
[disabled]="(selectedQueue && !selectedQueue.freetext) || importSelection()"
- [required]="true"
[startId]="selectedMatchSet || defaultMatchSet"
(onChange)="selectEntry($event, 'matchSets')">
</eg-combobox>
<div class="col-lg-3">
<eg-combobox #mergeProfileSelector
id="merge-profiles"
- [required]="true"
[entries]="formatEntries('mergeProfiles')"
(onChange)="selectEntry($event, 'mergeProfiles')"
[startId]="selectedMergeProfile">
<div class="col-lg-3">
<eg-combobox [entries]="formatEntries('activeQueues')"
id="queue-select"
- [startId]="startQueueId"
[startIdFiresOnChange]="true"
- [disabled]="startQueueId"
(onChange)="selectedQueue=$event" i18n-placeholder
[required]="true"
[allowFreeText]="true">
(click)="upload()" i18n>Upload</button>
</div>
</div>
- <div class="row" [hidden]="!showProgress || importSelection()">
+ <div class="row" [hidden]="!showProgress || uploadComplete">
<div class="col-lg-3">
- <label i18n>Upload to Server</label>
+ <label i18n>Upload File to Server</label>
</div>
<div class="col-lg-6">
<eg-progress-inline #uploadProgress></eg-progress-inline>
</div>
</div>
- <div class="col-lg-6" [hidden]="!isUploading">
- <label i18n>Go To:</label>
+
+ <div class="col-lg-6 offset-lg-3" [hidden]="!uploadProcessing || uploadComplete">
+ <h2><label i18n><i>Processing...</i></label></h2>
</div>
- <div class="row" [hidden]="!isUploading">
- <div class="col-lg-6 offset-lg-3">
- <a routerLink="/staff/cat/vandelay/queue/{{recordType}}/{{activeQueueId}}" target="_blank" i18n>Queue</a>
+
+ <div class="row" [hidden]="!uploadComplete">
+ <div class="col-lg-3 offset-lg-3">
+ <h2><label i18n>Upload Complete!</label></h2>
+ </div>
+ </div>
+ <div class="row" [hidden]="!uploadComplete">
+ <div class="col-sm-1 offset-lg-3">
+ <label i18n>Go to:</label>
+ </div>
+ <div><a routerLink="/staff/cat/vandelay/queue/{{recordType}}/{{activeQueueId}}" target="_blank" i18n>Queue</a></div>
+ <div class="col-sm-1" [hidden]="!selectedSelectionList"><a href="/eg/staff/acq/legacy/picklist/view/{{activeSelectionListId}}" target="_blank">Selection List</a></div>
+ <div class="col-sm-2" [hidden]="!createPurchaseOrder"><a href="/eg/staff/acq/legacy/po/view/{{newPO}}" target="_blank">Purchase Order</a></div>
</div>
- </div>
-</div>
\ No newline at end of file
const TEMPLATE_ATTRS = [
'createPurchaseOrder',
'activatePurchaseOrder',
+ 'selectedProvider',
'orderingAgency',
'selectedFiscalYear',
'loadItems',
'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'
settings: Object = {};
recordType: string;
- selectedQueue: ComboboxEntry; // freetext enabled
+ selectedQueue: ComboboxEntry;
- // 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: number;
+ selectedSelectionList: ComboboxEntry;
selectedBibSource: number;
selectedProvider: number;
selectedMatchSet: number;
selectedMergeProfile: number;
selectedFallThruMergeProfile: number;
selectedFile: File;
+ newPO: number;
defaultMatchSet: string;
mergeOnBestMatch: boolean;
minQualityRatio: number;
- // True after the first upload, then remains true.
- showProgress: boolean;
-
- // Upload in progress.
isUploading: boolean;
-
- // True only after successful upload
+ uploadProcessing: boolean;
uploadComplete: boolean;
- // Upload / processsing session key
// Generated by the server
sessionKey: string;
-
selectedTemplate: string;
formTemplates: {[name: string]: any};
newTemplateName: string;
@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 })
this.minQualityRatio = 0;
this.recordType = 'bib';
this.formTemplates = {};
-//To-do add default for fiscal year
if (this.vlagent.importSelection) {
if (!this.vlagent.importSelection.queue) {
}
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();
-
-
}
}
}
ngOnDestroy() {
- // Always clear the import selection when navigating away from
- // the import page.
this.clearSelection();
}
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()
];
return entries;
}
- // Format typeahead data sets
formatEntries(etype: string): ComboboxEntry[] {
const rtype = this.recordType;
let list;
break;
case 'activeQueues':
- list = (this.vlagent.allQueues[rtype] || [])
- .filter(q => q.complete() === 'f');
+ list = (this.vlagent.allQueues[rtype] || []);
break;
case 'matchSets':
this.selectedFile = $event.target.files[0];
}
- // Required form data varies depending on context.
hasNeededData(): boolean {
- 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;
+ return this.selectedQueue &&
+ Boolean(this.selectedFile) &&
+ Boolean(this.selectedFiscalYear) &&
+ Boolean(this.selectedProvider) &&
+ Boolean(this.orderingAgency);
}
-
- // 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 => {
this.uploadProgress.update({value: 0, max: 1});
}
- // Extract selected queue ID or create a new queue when requested.
resolveQueue(): Promise<number> {
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,
}
}
+ resolveSelectionList(): Promise<any> {
+ 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<any> {
if (this.vlagent.importSelection) {
- // Nothing to upload when processing pre-queued records.
return Promise.resolve();
}
processUpload(): Promise<any> {
+ this.uploadProcessing = true;
+
if (this.vlagent.importSelection) {
return Promise.resolve();
}
-
+
let spoolType = this.recordType;
const vandelayOptions = {
bib_source: this.selectedBibSource,
create_assets: this.loadItems,
queue_name: this.selectedQueue.label
-
}
-
const args = {
provider: this.selectedProvider,
create_po: this.createPurchaseOrder,
activate_po: this.activatePurchaseOrder,
fiscal_year: this.selectedFiscalYear,
- picklist: this.selectedSelectionList,
+ picklist: this.activeSelectionListId,
vandelay: vandelayOptions
}
'open-ils.acq', method,
this.auth.token(), this.sessionKey, args
).subscribe(
- tracker => {
- const e = this.evt.parse(tracker);
- if (e) { console.error(e); return reject(); }
+ 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();}
}
);
});
clearSelection() {
this.vlagent.importSelection = null;
- this.startQueueId = null;
+ this.activeSelectionListId = null;
}
- openQueue() {
- console.log('opening queue ' + this.activeQueueId);
- }
saveTemplate() {
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() {
import {PermService} from '@eg/core/perm.service';
import {EventService} from '@eg/core/event.service';
import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
-import {VandelayImportSelection, VANDELAY_EXPORT_PATH} from '@eg/staff/cat/vandelay/vandelay.service'
+import {VandelayImportSelection} from '@eg/staff/cat/vandelay/vandelay.service'
@Injectable()
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;
+ importSelection: VandelayImportSelection;
constructor(
private http: HttpClient,
this.allQueues = {};
this.matchSets = {};
this.importSelection = null;
- this.queuePageOffset = 0;
+ this.queueType = 'acq';
+ this.recordType = 'bib';
}
getAttrDefs(dtype: string): Promise<IdlObject[]> {
return lists;
});
}
- // Returns a promise resolved with the list of queues.
+
getAllQueues(qtype: string): Promise<IdlObject[]> {
if (this.allQueues[qtype]) {
return Promise.resolve(this.allQueues[qtype]);
this.allQueues[qtype] = [];
}
- // could be a big list, invoke in streaming mode
return this.net.request(
'open-ils.vandelay',
- `open-ils.vandelay.${qtype}_queue.owner.retrieve`,
+ `open-ils.vandelay.bib_queue.owner.retrieve`,
this.auth.token()
).pipe(tap(
queue => this.allQueues[qtype].push(queue)
});
}
- // todo: differentiate between biblio and authority a la queue api
getMatchSets(mtype: string): Promise<IdlObject[]> {
- const mstype = mtype.match(/bib/) ? 'biblio' : 'authority';
+ const mstype = 'biblio'
if (this.matchSets[mtype]) {
return Promise.resolve(this.matchSets[mtype]);
}
-
-
-
-
- // Create a queue and return the ID of the new queue via promise.
createQueue(
queueName: string,
- recordType: string,
+ queueType: string,
importDefId: number,
matchSet: number): Promise<number> {
- const method = `open-ils.vandelay.${recordType}_queue.create`;
+ const method = `open-ils.vandelay.bib_queue.create`;
+ queueType = 'acq';
- 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, qType,
+ this.auth.token(), queueName, null, queueType,
matchSet, importDefId
).subscribe(queue => {
const e = this.evt.parse(queue);
if (e) {
reject(e);
} else {
- // createQueue is always called after queues have
- // been fetched and cached.
- this.allQueues[qType].push(queue);
+ this.allQueues['bib'].push(queue);
resolve(queue.id());
}
});
});
}
- getQueuedRecords(queueId: number, queueType: string,
- options?: any, limitToMatches?: boolean): Observable<any> {
-
- 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';
- }
+ createSelectionList(
+ picklistName: string,
+ picklistOrg: number
+ ): Promise<number> {
- saveName += '.mrc';
-
- this.http.get(url, {responseType: 'text'}).subscribe(
- data => {
- saveAs(
- new Blob([data], {type: 'application/octet-stream'}),
- saveName
- );
- },
- err => {
- console.error(err);
- }
- );
+ 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);
+ }
+ });
+ });
}
+
}