diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts index 60473c77ca..2ed21cbdf0 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts @@ -34,6 +34,7 @@ export class TreeviewFlatNode { constructor(public item: VocabularyEntryDetail, public level = 1, public expandable = false, + public childrenLoaded = false, public pageInfo: PageInfo = new PageInfo(), public loadMoreParentItem: VocabularyEntryDetail | null = null, public isSearchNode = false, diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 6de1a11e00..cbd9c25a9b 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -143,6 +143,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { node.item, level, node.hasChildren, + (node.hasChildren && isNotEmpty(node.children)), node.pageInfo, node.loadMoreParentItem, node.isSearchNode, @@ -150,7 +151,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { ); this.nodeMap.set(node.item.id, newNode); - if ((((level + 1) < this.preloadLevel) && newNode.expandable) || newNode.isSearchNode || newNode.isInInitValueHierarchy) { + if ((((level + 1) < this.preloadLevel) && newNode.childrenLoaded) + || (newNode.isSearchNode && newNode.childrenLoaded) + || newNode.isInInitValueHierarchy) { if (!newNode.isSearchNode) { this.loadChildren(newNode); } diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts index 2f03549898..944ca0bfb0 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts @@ -13,6 +13,7 @@ import { PageInfo } from '../../core/shared/page-info.model'; import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; +import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model'; describe('VocabularyTreeviewService test suite', () => { @@ -34,6 +35,7 @@ describe('VocabularyTreeviewService test suite', () => { let childNode: TreeviewNode; let child2: VocabularyEntryDetail; let childNode2: TreeviewNode; + let childEntry3: VocabularyEntry; let child3: VocabularyEntryDetail; let childNode3: TreeviewNode; let searchItemNode: TreeviewNode; @@ -71,37 +73,46 @@ describe('VocabularyTreeviewService test suite', () => { }); loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item); loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null); - loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, new PageInfo(), null); + loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, false, new PageInfo(), null); item = new VocabularyEntryDetail(); - item.id = item.value = item.display = 'root1'; + item.id = 'vocabularyTest:root1'; + item.value = item.display = 'root1'; item.otherInformation = { hasChildren: 'true', id: 'root1' }; itemNode = new TreeviewNode(item, true, pageInfo); searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true); item2 = new VocabularyEntryDetail(); - item2.id = item2.value = item2.display = 'root2'; + item2.id = 'vocabularyTest:root2'; + item2.value = item2.display = 'root2'; item2.otherInformation = { id: 'root2' }; itemNode2 = new TreeviewNode(item2, false, pageInfo); item3 = new VocabularyEntryDetail(); - item3.id = item3.value = item3.display = 'root3'; + item3.id = 'vocabularyTest:root3'; + item3.value = item3.display = 'root3'; item3.otherInformation = { id: 'root3' }; itemNode3 = new TreeviewNode(item3, false, pageInfo); child = new VocabularyEntryDetail(); - child.id = child.value = child.display = 'root1-child1'; + child.id = 'vocabularyTest:root1-child1'; + child.value = child.display = 'root1-child1'; child.otherInformation = { parent: 'root1', hasChildren: 'true', id: 'root1-child1' }; childNode = new TreeviewNode(child); searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true); + childEntry3 = new VocabularyEntry(); + childEntry3.value = childEntry3.display = 'root1-child1-child1'; + childEntry3.otherInformation = { parent: 'root1-child1', id: 'root1-child1-child1' }; child3 = new VocabularyEntryDetail(); - child3.id = child3.value = child3.display = 'root1-child1-child1'; + child3.id = 'vocabularyTest:root1-child1-child1'; + child3.value = child3.display = 'root1-child1-child1'; child3.otherInformation = { parent: 'root1-child1', id: 'root1-child1-child1' }; childNode3 = new TreeviewNode(child3); searchChildNode3 = new TreeviewNode(child3, false, new PageInfo(), child, true); child2 = new VocabularyEntryDetail(); - child2.id = child2.value = child2.display = 'root1-child2'; + child2.id = 'vocabularyTest:root1-child2'; + child2.value = child2.display = 'root1-child2'; child2.otherInformation = { parent: 'root1', id: 'root1-child2' }; childNode2 = new TreeviewNode(child2, true); initValueChildNode2 = new TreeviewNode(child2, false, new PageInfo(), item, false, true); @@ -184,7 +195,6 @@ describe('VocabularyTreeviewService test suite', () => { expect(serviceAsAny.vocabularyName).toEqual(vocabularyOptions.name); expect(serviceAsAny.pageInfo).toEqual(pageInfo); - console.log(serviceAsAny.dataChange.value[0].pageInfo, itemNode.pageInfo); expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]); }); @@ -290,7 +300,11 @@ describe('VocabularyTreeviewService test suite', () => { currentPage: 1 }); serviceAsAny.vocabularyService.getVocabularyEntriesByValue.and.returnValue(hot('-a', { - a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [child3])) + a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [childEntry3])) + })); + + serviceAsAny.vocabularyService.findEntryDetailByValue.and.returnValue(hot('-a', { + a: createSuccessfulRemoteDataObject(child3) })); serviceAsAny.vocabularyService.getEntryDetailParent.and.returnValues( @@ -305,6 +319,7 @@ describe('VocabularyTreeviewService test suite', () => { scheduler.schedule(() => service.searchByQuery(vocabularyOptions)); scheduler.flush(); + searchChildNode.childrenChange.next([searchChildNode3]); searchItemNode.childrenChange.next([searchChildNode]); expect(serviceAsAny.dataChange.value.length).toEqual(1); diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts index 836ce7672a..698f5bb0d2 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts @@ -134,13 +134,13 @@ export class VocabularyTreeviewService { * @param onlyFirstTime */ loadMore(item: VocabularyEntryDetail, onlyFirstTime = false) { - if (!this.nodeMap.has(item.id)) { + if (!this.nodeMap.has(item.otherInformation.id)) { return; } - const parent: TreeviewNode = this.nodeMap.get(item.id)!; - const children = this.nodeMap.get(item.id)!.children || []; + const parent: TreeviewNode = this.nodeMap.get(item.otherInformation.id)!; + const children = this.nodeMap.get(item.otherInformation.id)!.children || []; children.pop(); - this.getChildrenNodesByParent(item.id, parent.pageInfo).subscribe((list: PaginatedList) => { + this.getChildrenNodesByParent(item.otherInformation.id, parent.pageInfo).subscribe((list: PaginatedList) => { if (onlyFirstTime && parent.children!.length > 0) { return; @@ -187,9 +187,14 @@ export class VocabularyTreeviewService { this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, new PageInfo()).pipe( getFirstSucceededRemoteListPayload(), flatMap((result: VocabularyEntry[]) => (result.length > 0) ? result : observableOf(null)), - flatMap((entry: VocabularyEntry) => this.getNodeHierarchy(entry)), + flatMap((entry: VocabularyEntry) => + this.vocabularyService.findEntryDetailByValue(entry.otherInformation.id, this.vocabularyName).pipe( + getFirstSucceededRemoteDataPayload() + ) + ), + flatMap((entry: VocabularyEntryDetail) => this.getNodeHierarchy(entry)), scan((acc: TreeviewNode[], value: TreeviewNode) => { - if (isEmpty(value) || findIndex(acc, (node) => node.item.id === value.item.id) !== -1) { + if (isEmpty(value) || findIndex(acc, (node) => node.item.otherInformation.id === value.item.otherInformation.id) !== -1) { return acc; } else { return [...acc, value] @@ -217,24 +222,21 @@ export class VocabularyTreeviewService { /** * Generate a {@link TreeviewNode} object from vocabulary entry * - * @param entry The vocabulary entry + * @param entry The vocabulary entry detail * @param isSearchNode A Boolean representing if given entry is the result of a search * @param toStore A Boolean representing if the node created is to store or not * @return TreeviewNode */ - private _generateNode(entry: VocabularyEntry, isSearchNode = false, toStore = true): TreeviewNode { + private _generateNode(entry: VocabularyEntryDetail, isSearchNode = false, toStore = true): TreeviewNode { const entryId = entry.otherInformation.id; if (this.nodeMap.has(entryId)) { return this.nodeMap.get(entryId)!; } - const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, { - id: entryId - }); const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren === 'true'; const pageInfo: PageInfo = this.pageInfo; const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId); const result = new TreeviewNode( - entryDetail, + entry, hasChildren, pageInfo, null, @@ -328,7 +330,7 @@ export class VocabularyTreeviewService { * @param toStore A Boolean representing if the node created is to store or not * @return Observable */ - private getNodeHierarchy(item: VocabularyEntry, children?: TreeviewNode[], toStore = true): Observable { + private getNodeHierarchy(item: VocabularyEntryDetail, children?: TreeviewNode[], toStore = true): Observable { if (isEmpty(item)) { return observableOf(null); } @@ -337,7 +339,7 @@ export class VocabularyTreeviewService { if (isNotEmpty(children)) { const newChildren = children .filter((entry: TreeviewNode) => { - return findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id) === -1; + return findIndex(node.children, (nodeEntry) => nodeEntry.item.otherInformation.id === entry.item.otherInformation.id) === -1; }); newChildren.forEach((entry: TreeviewNode) => { entry.loadMoreParentItem = node.item @@ -346,7 +348,7 @@ export class VocabularyTreeviewService { } if (node.item.hasOtherInformation() && isNotEmpty(node.item.otherInformation.parent)) { - return this.getParentNode(node.item.id).pipe( + return this.getParentNode(node.item.otherInformation.id).pipe( flatMap((parentItem: VocabularyEntryDetail) => this.getNodeHierarchy(parentItem, [node], toStore)) ) } else { @@ -362,8 +364,8 @@ export class VocabularyTreeviewService { * @return string[] */ private getNodeHierarchyIds(node: TreeviewNode, hierarchyIds: string[] = []): string[] { - if (!hierarchyIds.includes(node.item.id)) { - hierarchyIds.push(node.item.id); + if (!hierarchyIds.includes(node.item.otherInformation.id)) { + hierarchyIds.push(node.item.otherInformation.id); } if (isNotEmpty(node.children)) { return this.getNodeHierarchyIds(node.children[0], hierarchyIds);