1 import {IdlObject} from '@eg/core/idl.service';
2 import {OrgService} from '@eg/core/org.service';
4 /* Models the holdings tree and manages related data shared
5 * volcopy across components. */
7 export class HoldingsTreeNode {
8 children: HoldingsTreeNode[];
9 nodeType: 'org' | 'vol' | 'copy';
11 parentNode: HoldingsTreeNode;
18 root: HoldingsTreeNode;
20 this.root = new HoldingsTreeNode();
24 export class VolCopyContext {
26 holdings: HoldingsTree = new HoldingsTree();
27 org: OrgService; // injected
29 sessionType: 'copy' | 'vol' | 'record' | 'mixed';
31 // Edit content comes from a cached session
34 // Note in multi-record mode this value will be unset.
37 // Load specific call number by ID.
40 // Load specific copy by ID.
45 volsToDelete: IdlObject[] = [];
46 copiesToDelete: IdlObject[] = [];
49 this.holdings = new HoldingsTree();
50 this.volsToDelete = [];
51 this.copiesToDelete = [];
54 orgNodes(): HoldingsTreeNode[] {
55 return this.holdings.root.children;
58 volNodes(): HoldingsTreeNode[] {
60 this.orgNodes().forEach(orgNode =>
61 vols = vols.concat(orgNode.children));
65 copyList(): IdlObject[] {
67 this.volNodes().forEach(volNode => {
68 copies = copies.concat(volNode.children.map(c => c.target));
73 // Returns IDs for all bib records represented in our holdings tree.
74 getRecordIds(): number[] {
75 const idHash: {[id: number]: boolean} = {};
77 this.volNodes().forEach(volNode =>
78 idHash[volNode.target.record()] = true);
80 return Object.keys(idHash).map(id => Number(id));
83 // When working on exactly one record, set our recordId value.
86 const ids = this.getRecordIds();
87 if (ids.length === 1) {
88 this.recordId = ids[0];
93 // Adds an org unit node; unsorted.
94 findOrCreateOrgNode(orgId: number): HoldingsTreeNode {
96 const existing: HoldingsTreeNode =
97 this.orgNodes().filter(n => n.target.id() === orgId)[0];
99 if (existing) { return existing; }
101 const node: HoldingsTreeNode = new HoldingsTreeNode();
102 node.nodeType = 'org';
103 node.target = this.org.get(orgId);
104 node.parentNode = this.holdings.root;
106 this.orgNodes().push(node);
111 findOrCreateVolNode(vol: IdlObject): HoldingsTreeNode {
112 const orgId = vol.owning_lib();
113 const orgNode = this.findOrCreateOrgNode(orgId);
115 const existing = orgNode.children.filter(
116 n => n.target.id() === vol.id())[0];
118 if (existing) { return existing; }
120 const node: HoldingsTreeNode = new HoldingsTreeNode();
121 node.nodeType = 'vol';
123 node.parentNode = orgNode;
125 orgNode.children.push(node);
131 findOrCreateCopyNode(copy: IdlObject): HoldingsTreeNode {
132 const volNode = this.findOrCreateVolNode(copy.call_number());
134 const existing = volNode.children.filter(
135 c => c.target.id() === copy.id())[0];
137 if (existing) { return existing; }
139 const node: HoldingsTreeNode = new HoldingsTreeNode();
140 node.nodeType = 'copy';
142 node.parentNode = volNode;
144 volNode.children.push(node);
149 removeVolNode(volId: number) {
150 this.orgNodes().forEach(orgNode => {
151 for (let idx = 0; idx < orgNode.children.length; idx++) {
152 if (orgNode.children[idx].target.id() === volId) {
153 orgNode.children.splice(idx, 1);
160 removeCopyNode(copyId: number) {
161 this.volNodes().forEach(volNode => {
162 for (let idx = 0; idx < volNode.children.length; idx++) {
163 if (volNode.children[idx].target.id() === copyId) {
164 volNode.children.splice(idx, 1);
173 this.orgNodes().forEach(orgNode => {
174 orgNode.children.forEach(volNode => {
176 // Sort copys by barcode code
177 volNode.children = volNode.children.sort((c1, c2) =>
178 c1.target.barcode() < c2.target.barcode() ? -1 : 1);
182 // Sort call numbers by label
183 orgNode.children = orgNode.children.sort((c1, c2) =>
184 c1.target.label() < c2.target.label() ? -1 : 1);
187 // sort org units by shortname
188 this.holdings.root.children = this.orgNodes().sort((o1, o2) =>
189 o1.target.shortname() < o2.target.shortname() ? -1 : 1);
192 changesPending(): boolean {
193 const modified = (o: IdlObject): boolean => {
194 return o.isnew() || o.ischanged() || o.isdeleted();
197 if (this.volNodes().filter(n => modified(n.target)).length > 0) {
201 if (this.copyList().filter(c => modified(c)).length > 0) {