From: Bill Erickson Date: Tue, 19 Mar 2019 15:48:03 +0000 (-0400) Subject: lpxxx Angular holdings maintenance wip X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=a07c9f92cf4348b76b7946319d1ece4f8566301d;p=working%2FEvergreen.git lpxxx Angular holdings maintenance wip Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html index 64f36e5520..bf52735ced 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html @@ -1,4 +1,6 @@ + +
@@ -18,6 +20,7 @@
+ @@ -30,6 +33,7 @@ +
+ - + - @@ -78,31 +84,59 @@ - + + + - + - + - + + + - + + + + + + path="copy.age_protect.name" name="age_protect.name"> + + + + - + + + + +
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts index 3bb2efa739..2ced83bbd3 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts @@ -61,7 +61,6 @@ class HoldingsEntry { }) export class HoldingsMaintenanceComponent implements OnInit { - recId: number; initDone = false; gridDataSource: GridDataSource; gridTemplateContext: any; @@ -81,10 +80,17 @@ export class HoldingsMaintenanceComponent implements OnInit { @ViewChild('markMissingDialog') private markMissingDialog: MarkMissingDialogComponent; - contextOrg: IdlObject; + holdingsTree: HoldingsTree; - holdingsTreeOrgCache: {[id: number]: HoldingsTreeNode}; + + // nodeType => id => tree node cache + treeNodeCache: {[nodeType: string]: {[id: number]: HoldingsTreeNode}}; + + // When true and a grid reload is called, the holdings data will be + // re-fetched from the server. refreshHoldings: boolean; + + // Used as a row identifier in th grid, since we're mixing object types. gridIndex: number; // List of copies whose due date we need to retrieve. @@ -94,17 +100,33 @@ export class HoldingsMaintenanceComponent implements OnInit { // When not true, render based on the current "expanded" state of each node. // Rendering from prefs happens on initial load and when any prefs change. renderFromPrefs: boolean; + rowClassCallback: (row: any) => string; + private _recId: number; @Input() set recordId(id: number) { - this.recId = id; + this._recId = id; // Only force new data collection when recordId() // is invoked after ngInit() has already run. if (this.initDone) { - this.refreshHoldings = true; - this.holdingsGrid.reload(); + this.hardRefresh(); + } + } + get recordId(): number { + return this._recId; + } + + // Allows the caller to update the context org unit + private _co: IdlObject; + @Input() set contextOrg(org: IdlObject) { + this._co = org; + if (this.initDone) { + this.hardRefresh(); } } + get contextOrg(): IdlObject { + return this._co; + } constructor( private net: NetService, @@ -115,7 +137,6 @@ export class HoldingsMaintenanceComponent implements OnInit { private store: ServerStoreService ) { // Set some sane defaults before settings are loaded. - this.contextOrg = this.org.get(this.auth.user().ws_ou()); this.gridDataSource = new GridDataSource(); this.refreshHoldings = true; this.renderFromPrefs = true; @@ -154,6 +175,10 @@ export class HoldingsMaintenanceComponent implements OnInit { ngOnInit() { this.initDone = true; + if (!this.contextOrg) { + this.contextOrg = this.org.get(this.auth.user().ws_ou()); + } + // These are pre-cached via the resolver. const settings = this.store.getItemBatchCached([ 'cat.holdings_show_empty_org', @@ -173,8 +198,11 @@ export class HoldingsMaintenanceComponent implements OnInit { }; } - ngAfterViewInit() { - + hardRefresh() { + this.renderFromPrefs = true; + this.refreshHoldings = true; + this.initHoldingsTree(); + this.holdingsGrid.reload(); } toggleShowCopies(value: boolean) { @@ -223,33 +251,40 @@ export class HoldingsMaintenanceComponent implements OnInit { initHoldingsTree() { + const visibleOrgs = this.org.fullPath(this.contextOrg, true); + // The initial tree simply matches the org unit tree const traverseOrg = (node: HoldingsTreeNode) => { - node.expanded = true; node.target.children().forEach((org: IdlObject) => { + if (visibleOrgs.indexOf(org.id()) == -1) { + return; // Org is outside of scope + } const nodeChild = new HoldingsTreeNode(); nodeChild.nodeType = 'org'; nodeChild.target = org; nodeChild.parentNode = node; node.children.push(nodeChild); - this.holdingsTreeOrgCache[org.id()] = nodeChild; + this.treeNodeCache.org[org.id()] = nodeChild; traverseOrg(nodeChild); }); } + this.treeNodeCache = { + org: {}, + volume: {}, + copy: {} + }; + this.holdingsTree = new HoldingsTree(); this.holdingsTree.root.nodeType = 'org'; this.holdingsTree.root.target = this.org.root(); - - this.holdingsTreeOrgCache = {}; - this.holdingsTreeOrgCache[this.org.root().id()] = this.holdingsTree.root; + this.treeNodeCache.org[this.org.root().id()] = this.holdingsTree.root; traverseOrg(this.holdingsTree.root); } // Org node children are sorted with any child org nodes pushed to the // front, followed by the call number nodes sorted alphabetcially by label. - // TODO: prefix/suffix sortOrgNodeChildren(node: HoldingsTreeNode) { node.children = node.children.sort((a, b) => { if (a.nodeType === 'org') { @@ -261,7 +296,9 @@ export class HoldingsMaintenanceComponent implements OnInit { } else if (b.nodeType === 'org') { return 1; } else { - return a.target.label() < b.target.label() ? -1 : 1; + // TODO: should this use label sortkey instead of + // the compiled volume label? + return a.target._label < b.target._label ? -1 : 1; } }); } @@ -322,7 +359,7 @@ export class HoldingsMaintenanceComponent implements OnInit { switch(node.nodeType) { case 'org': - if (this.renderFromPrefs && node.volumeCount === 0 + if (node.volumeCount === 0 && !this.emptyLibsCheckbox.checked()) { return; } @@ -334,7 +371,16 @@ export class HoldingsMaintenanceComponent implements OnInit { break; case 'volume': - entry.locationLabel = node.target.label(); // TODO prefix/suffix + if (this.renderFromPrefs) { + if (!this.volsCheckbox.checked()) { + return; + } + if (node.copyCount === 0 + && !this.emptyVolsCheckbox.checked()) { + return; + } + } + entry.locationLabel = node.target._label; entry.locationDepth = node.parentNode.target.ou_type().depth() + 1; entry.callNumberLabel = entry.locationLabel; entry.volume = node.target; @@ -370,29 +416,9 @@ export class HoldingsMaintenanceComponent implements OnInit { this.renderFromPrefs = false; } - // Find an existing tree node by id and type - findNode(targetId: number, nodeType: string): HoldingsTreeNode { - const id = Number(targetId); - - const search = (node: HoldingsTreeNode): HoldingsTreeNode => { - if (!node) return null; - - if (node.nodeType === nodeType && Number(node.target.id()) === id) { - return node; - } - // for loop for early exit - for (let idx = 0; idx < node.children.length; idx++) { - const found = search(node.children[idx]); - if (found) { return found; } - } - } - - return search(this.holdingsTree.root); - } - - + // Grab volumes, copies, and related data. fetchHoldings(pager: Pager): Observable { - if (!this.recId) { return of([]); } + if (!this.recordId) { return of([]); } return new Observable(observer => { @@ -404,8 +430,8 @@ export class HoldingsMaintenanceComponent implements OnInit { this.itemCircsNeeded = []; this.pcrud.search('acn', - { record: this.recId, - owning_lib: this.org.ancestors(this.contextOrg, true), + { record: this.recordId, + owning_lib: this.org.fullPath(this.contextOrg, true), deleted: 'f', label: {'!=' : '##URI##'} }, { @@ -446,13 +472,23 @@ export class HoldingsMaintenanceComponent implements OnInit { })).toPromise(); } + // Compile prefix + label + suffix into field volume._label; + setVolumeLabel(volume: IdlObject) { + const pfx = volume.prefix() ? volume.prefix().label() : ''; + const sfx = volume.suffix() ? volume.suffix().label() : ''; + volume._label = pfx ? pfx + ' ' : ''; + volume._label += volume.label(); + volume._label += sfx ? ' ' + sfx : ''; + } + // Create the tree node for the volume if it doesn't already exist. // Do the same for its linked copies. appendVolume(volume: IdlObject) { + let volNode = this.treeNodeCache.volume[volume.id()]; + this.setVolumeLabel(volume); - let volNode = this.findNode(volume.id(), 'volume'); if (volNode) { - const pNode = this.holdingsTreeOrgCache[volume.owning_lib()]; + const pNode = this.treeNodeCache.org[volume.owning_lib()] if (volNode.parentNode.target.id() !== pNode.target.id()) { // Volume owning library changed. Un-link it from the previous // org unit collection before adding to the new one. @@ -463,8 +499,9 @@ export class HoldingsMaintenanceComponent implements OnInit { } else { volNode = new HoldingsTreeNode(); volNode.nodeType = 'volume'; - volNode.parentNode = this.holdingsTreeOrgCache[volume.owning_lib()]; + volNode.parentNode = this.treeNodeCache.org[volume.owning_lib()] volNode.parentNode.children.push(volNode); + this.treeNodeCache.volume[volume.id()] = volNode; } volNode.target = volume; @@ -474,8 +511,9 @@ export class HoldingsMaintenanceComponent implements OnInit { .forEach((copy: IdlObject) => this.appendCopy(volNode, copy)); } + // Find or create a copy node. appendCopy(volNode: HoldingsTreeNode, copy: IdlObject) { - let copyNode = this.findNode(copy.id(), 'copy'); + let copyNode = this.treeNodeCache.copy[copy.id()]; if (copyNode) { const oldParent = copyNode.parentNode; @@ -491,6 +529,7 @@ export class HoldingsMaintenanceComponent implements OnInit { copyNode.nodeType = 'copy'; volNode.children.push(copyNode); copyNode.parentNode = volNode; + this.treeNodeCache.copy[copy.id()] = copyNode; } copyNode.target = copy; @@ -502,6 +541,7 @@ export class HoldingsMaintenanceComponent implements OnInit { } } + // Which copies in the grid are selected. selectedCopyIds(rows: HoldingsEntry[], skipStatus?: number): number[] { let copyRows = rows.filter(r => Boolean(r.copy)).map(r => r.copy); if (skipStatus) { diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html index b583cf7e71..d43a8bbf89 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html @@ -66,7 +66,8 @@ - +