target: any;
parentNode: HoldingsTreeNode;
expanded: boolean;
+ copyCount: number;
+ volumeCount: number;
constructor() {
this.children = [];
}
holdingsTree: HoldingsTree;
holdingsTreeOrgCache: {[id: number]: HoldingsTreeNode};
refreshHoldings: boolean;
+ gridIndex: number;
rowClassCallback: (row: any) => string;
+ // TODO XXXX The checkbox toggles will change to @Output handlers
+ // in a pending catalog working branch.
+ toggleShowVolumes: (value: boolean) => void;
+
@Input() set recordId(id: number) {
this.recId = id;
// Only force new data collection when recordId()
this.rowClassCallback = (row: any): string => {
if (row.volume && !row.copy) {
- return 'border border-info';
+ return 'bg-info';
}
}
this.holdingsGrid.reload();
}
}
+
+
+ // TODO XXXX The checkbox toggles will change to @Output handlers
+ // in a pending catalog working branch.
+ this.toggleShowVolumes = (value: boolean) => {
+ console.log('SHOW VOLS', value);
+ this.showVolumes = value;
+ this.holdingsGrid.reload();
+ }
+ }
+
+ onRowActivate(row: any) {
+ if (row.copy) {
+ // Launch copy editor?
+ } else {
+ this.gridTemplateContext.toggleExpandRow(row);
+ }
}
ngOnInit() {
traverseOrg(this.holdingsTree.root);
}
- flattenHoldingsTree(observer: Observer<HoldingsEntry>) {
-
- let index = 0;
-
- const traverseTree = (node: HoldingsTreeNode) => {
-
- const entry = new HoldingsEntry();
- entry.treeNode = node;
- entry.index = index++;
-
- switch(node.nodeType) {
- case 'org':
- entry.locationLabel = node.target.shortname();
- entry.locationDepth = node.target.ou_type().depth();
-
- // 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
- node.children = node.children.sort((a, b) => {
- if (a.nodeType === 'org') {
- if (b.nodeType === 'org') {
- return a.target.shortname() < b.target.shortname() ? -1 : 1;
- } else {
- return -1;
- }
- } else if (b.nodeType === 'org') {
- return 1;
- } else {
- return a.target.label() < b.target.label() ? -1 : 1;
- }
- });
-
- break;
-
- case 'volume':
- entry.locationLabel = node.target.label(); // TODO prefix/suffix
- entry.locationDepth = node.parentNode.target.ou_type().depth() + 1;
- entry.callNumberLabel = entry.locationLabel;
- entry.volume = node.target;
- break;
-
- case 'copy':
- entry.locationLabel = node.target.barcode();
- entry.locationDepth = node.parentNode.parentNode.target.ou_type().depth() + 2;
- entry.callNumberLabel = node.parentNode.target.label() // TODO
- entry.volume = node.parentNode.target;
- entry.copy = node.target;
+ // 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') {
+ if (b.nodeType === 'org') {
+ return a.target.shortname() < b.target.shortname() ? -1 : 1;
+ } else {
+ return -1;
+ }
+ } else if (b.nodeType === 'org') {
+ return 1;
+ } else {
+ return a.target.label() < b.target.label() ? -1 : 1;
}
+ });
+ }
+
+ // Sets call number and copy count sums to nodes that need it.
+ setTreeCounts(node: HoldingsTreeNode) {
+
+ if (node.nodeType === 'org') {
+ node.copyCount = 0;
+ node.volumeCount = 0;
+ } else if(node.nodeType === 'volume') {
+ node.copyCount = 0;
+ }
- observer.next(entry);
- if (node.expanded) {
- node.children.forEach(traverseTree);
+ node.children.forEach(child => {
+ this.setTreeCounts(child);
+ if (node.nodeType === 'org') {
+ node.copyCount += child.copyCount;
+ if (child.nodeType === 'volume') {
+ node.volumeCount++;
+ } else {
+ node.volumeCount += child.volumeCount;
+ }
+ } else if (node.nodeType === 'volume') {
+ node.copyCount = node.children.length;
}
+ });
+ }
+
+ // Create HoldingsEntry objects for tree nodes that should be displayed
+ // and relays them to the grid via the observer.
+ propagateTreeEntries(observer: Observer<HoldingsEntry>, node: HoldingsTreeNode) {
+ const entry = new HoldingsEntry();
+ entry.treeNode = node;
+ entry.index = this.gridIndex++;
+
+ switch(node.nodeType) {
+ case 'org':
+ // Confirm the user wants to see this node
+ if (!this.showEmptyLibs) {
+ if (node.volumeCount === 0) {
+ return;
+ }
+ }
+ entry.locationLabel = node.target.shortname();
+ entry.locationDepth = node.target.ou_type().depth();
+ entry.copyCount = node.copyCount;
+ entry.volumeCount = node.volumeCount;
+ this.sortOrgNodeChildren(node);
+ break;
+
+ case 'volume':
+ // Confirm the user wants to see this node
+ if (!this.showVolumes) {
+ return;
+ }
+ if (!this.showEmptyVolumes && node.copyCount === 0) {
+ return;
+ }
+
+ entry.locationLabel = node.target.label(); // TODO prefix/suffix
+ entry.locationDepth = node.parentNode.target.ou_type().depth() + 1;
+ entry.callNumberLabel = entry.locationLabel;
+ entry.volume = node.target;
+ entry.copyCount = node.copyCount;
+ break;
+
+ case 'copy':
+ entry.locationLabel = node.target.barcode();
+ entry.locationDepth = node.parentNode.parentNode.target.ou_type().depth() + 2;
+ entry.callNumberLabel = node.parentNode.target.label() // TODO
+ entry.volume = node.parentNode.target;
+ entry.copy = node.target;
+ break;
}
- traverseTree(this.holdingsTree.root);
+ // Tell the grid about the node entry
+ observer.next(entry);
+
+ if (node.expanded) {
+ // Process the child nodes.
+ node.children.forEach(child =>
+ this.propagateTreeEntries(observer, child));
+ }
+ }
+
+ // Turns the tree into a list of entries for grid display
+ flattenHoldingsTree(observer: Observer<HoldingsEntry>) {
+ this.gridIndex = 0;
+ this.setTreeCounts(this.holdingsTree.root);
+ this.propagateTreeEntries(observer, this.holdingsTree.root);
observer.complete();
}