[required]="true"
[smallFormControl]="true"
(onChange)="applyVolValue(volNode.target, 'prefix', $event ? $event.id : null)">
+ <eg-combobox-entry
+ [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
+ </eg-combobox-entry>
<eg-combobox-entry *ngFor="let pfx of volPrefixes"
[entryId]="pfx.id()" [entryLabel]="pfx.label()">
</eg-combobox-entry>
[required]="true"
[smallFormControl]="true"
(onChange)="applyVolValue(volNode.target, 'suffix', $event ? $event.id : null)">
+ <eg-combobox-entry
+ [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
+ </eg-combobox-entry>
<eg-combobox-entry *ngFor="let sfx of volSuffixes"
[entryId]="sfx.id()" [entryLabel]="sfx.label()">
</eg-combobox-entry>
constructor(
private renderer: Renderer2,
private idl: IdlService,
+ private org: OrgService,
private pcrud: PcrudService,
private net: NetService,
private auth: AuthService,
.then(_ => this.fetchBibParts())
.then(_ => this.addStubCopies());
- // TODO: Filter these to only show org-scoped values
- // plus any values otherwise needed for the current
- // holdings tree.
-
this.holdings.fetchCallNumberClasses().then(
classes => this.volClasses = classes);
- this.holdings.fetchCallNumberPrefixes().then(prefixes => {
- this.volPrefixes = prefixes.filter(pfx => pfx.id() !== -1)
- });
+ const myOrgs = this.org.fullPath(this.auth.user().ws_ou(), true);
+
+ // The batch edit controls only include values for "here"
+ this.holdings.fetchCallNumberPrefixes().then(prefixes =>
+ this.volPrefixes = prefixes
+ .filter(sfx => sfx.id() !== -1)
+ .filter(pfx => myOrgs.includes(pfx.owning_lib()))
+ );
this.holdings.fetchCallNumberSuffixes().then(suffixes =>
- this.volSuffixes = suffixes.filter(pfx => pfx.id() !== -1));
+ this.volSuffixes = suffixes
+ .filter(sfx => sfx.id() !== -1)
+ .filter(sfx => myOrgs.includes(sfx.owning_lib()))
+ );
}
createVols(orgNode: HoldingsTreeNode, count: number) {
+ const vols = [];
for (let i = 0; i < count; i++) {
// This will vivify the volNode if needed.
const vol = this.volcopy.createStubVol(
this.context.recordId, orgNode.target.id())
+ vols.push(vol);
+
// Our context assumes copies are fleshed with volumes
const copy = this.volcopy.createStubCopy(vol);
copy.call_number(vol);
this.context.findOrCreateCopyNode(copy);
}
+
+ this.volcopy.setVolClassLabels(vols);
}
// This only removes vols that were created during the
}
}
- // Empty volumes get a stub copy
+ // When editing existing vols, be sure each has at least one copy.
addStubCopies(volNode?: HoldingsTreeNode) {
const nodes = volNode ? [volNode] : this.context.volNodes();
</div>
</div>
-<ng-container *ngIf="!loading">
+<div class="row" *ngIf="sessionExpired">
+ <div class="col-lg-6 mt-4 offset-lg-3 alert alert-danger d-flex justify-content-center" i18n>
+ Holdings Editor Session Expired
+ </div>
+</div>
+
+<ng-container *ngIf="!loading && !sessionExpired">
<eg-bib-summary *ngIf="context.recordId" [recordId]="context.recordId"></eg-bib-summary>
context: VolCopyContext;
loading = true;
+ sessionExpired = false;
@ViewChild('loadingProgress', {static: false})
loadingProgress: ProgressInlineComponent;
this.load();
}
- load() {
+ load(copyIds?: number[]) {
+ this.sessionExpired = false;
this.loading = true;
this.context.reset();
- this.fetchHoldings()
+ this.fetchHoldings(copyIds)
.then(_ => this.volcopy.applyVolLabels(
this.context.volNodes().map(n => n.target)))
.then(_ => this.holdings.fetchCallNumberClasses())
.then(_ => this.loading = false);
}
- fetchHoldings(): Promise<any> {
+ fetchHoldings(copyIds?: number[]): Promise<any> {
- if (this.context.session) {
+ if (copyIds && copyIds.length > 0) {
+ // Reloading copies that were just edited.
+ return this.fetchCopies(copyIds);
+
+ } else if (this.context.session) {
this.context.sessionType = 'mixed';
return this.fetchSession(this.context.session);
return this.cache.getItem(session, 'edit-these-copies')
.then((editSession: EditSession) => {
- if (!editSession) { return; }
+ if (!editSession) {
+ this.loading = false;
+ this.sessionExpired = true;
+ return Promise.reject('Session Expired');
+ }
this.context.recordId = editSession.record_id;
this.context.hideVols = editSession.hide_vols === true;
return this.volcopy.setCopyStatus(copies, this.context.fastAdd);
}
-
fetchCopies(copyIds: number | number[]): Promise<any> {
const ids = [].concat(copyIds);
return this.pcrud.search('acp', {id: ids}, COPY_FLESH)
let method = 'open-ils.cat.asset.volume.fleshed.batch.update';
if (override) { method += '.override'; }
- this.net.request('open-ils.cat', method, this.auth.token(),
- volumes, 1, {auto_merge_vols: 1, create_parts: 1}).toPromise()
+ this.net.request('open-ils.cat', method, this.auth.token(), volumes, true,
+ {auto_merge_vols: true, create_parts: true, return_copy_ids: true})
- .then(resp => {
+ .toPromise().then(copyIds => {
- const evt = this.evt.parse(resp);
+ const evt = this.evt.parse(copyIds);
// TODO: confirm / handle overrides
return;
}
- return this.load();
+ // In addition to the copies edited in this update call,
+ // reload any other copies that were previously loaded.
+
+ const ids: any = {}; // dedupe
+ this.context.copyList()
+ .map(c => c.id())
+ .concat(copyIds)
+ .forEach(id => ids[id] = true);
+
+ return this.load(Object.keys(ids).map(id => Number(id)));
});
}
}
});
}
- createStubVol(recordId: number, orgId: number): IdlObject {
+ createStubVol(recordId: number, orgId: number, options?: any): IdlObject {
+ if (!options) { options = {}; }
const vol = this.idl.create('acn');
vol.id(this.autoId--);
vol.label(null);
vol.owning_lib(Number(orgId));
+ vol.prefix(options.prefix || -1);
+ vol.suffix(options.suffix || -1);
+
return vol;
}
// apply it here and bypass the network call.
const volsWantLabels = [];
- Object.keys(orgIds).forEach(orgId => {
+ Object.keys(orgIds).map(orgId => Number(orgId)).forEach(orgId => {
promise = promise.then(_ => {
return this.org.settings(
- 'cat.default_classification_scheme', Number(orgId))
+ 'cat.default_classification_scheme', orgId)
.then(sets => {
const orgVols = vols.filter(v => v.owning_lib() === orgId);
});
});
- return promise;
+ return promise.then(_ => this.applyVolLabels(volsWantLabels));
}
// Apply labels to volumes based on the appropriate MARC call number.