1
0

fixed issue that didn't allow to select tree node after a search

This commit is contained in:
Giuseppe Digilio
2020-07-22 17:40:03 +02:00
parent 47ab023e7a
commit d88a863a0d
4 changed files with 48 additions and 27 deletions

View File

@@ -34,6 +34,7 @@ export class TreeviewFlatNode {
constructor(public item: VocabularyEntryDetail, constructor(public item: VocabularyEntryDetail,
public level = 1, public level = 1,
public expandable = false, public expandable = false,
public childrenLoaded = false,
public pageInfo: PageInfo = new PageInfo(), public pageInfo: PageInfo = new PageInfo(),
public loadMoreParentItem: VocabularyEntryDetail | null = null, public loadMoreParentItem: VocabularyEntryDetail | null = null,
public isSearchNode = false, public isSearchNode = false,

View File

@@ -143,6 +143,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
node.item, node.item,
level, level,
node.hasChildren, node.hasChildren,
(node.hasChildren && isNotEmpty(node.children)),
node.pageInfo, node.pageInfo,
node.loadMoreParentItem, node.loadMoreParentItem,
node.isSearchNode, node.isSearchNode,
@@ -150,7 +151,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
); );
this.nodeMap.set(node.item.id, newNode); 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) { if (!newNode.isSearchNode) {
this.loadChildren(newNode); this.loadChildren(newNode);
} }

View File

@@ -13,6 +13,7 @@ import { PageInfo } from '../../core/shared/page-info.model';
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import { PaginatedList } from '../../core/data/paginated-list'; import { PaginatedList } from '../../core/data/paginated-list';
import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
describe('VocabularyTreeviewService test suite', () => { describe('VocabularyTreeviewService test suite', () => {
@@ -34,6 +35,7 @@ describe('VocabularyTreeviewService test suite', () => {
let childNode: TreeviewNode; let childNode: TreeviewNode;
let child2: VocabularyEntryDetail; let child2: VocabularyEntryDetail;
let childNode2: TreeviewNode; let childNode2: TreeviewNode;
let childEntry3: VocabularyEntry;
let child3: VocabularyEntryDetail; let child3: VocabularyEntryDetail;
let childNode3: TreeviewNode; let childNode3: TreeviewNode;
let searchItemNode: TreeviewNode; let searchItemNode: TreeviewNode;
@@ -71,37 +73,46 @@ describe('VocabularyTreeviewService test suite', () => {
}); });
loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item); loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item);
loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null); 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 = new VocabularyEntryDetail();
item.id = item.value = item.display = 'root1'; item.id = 'vocabularyTest:root1';
item.value = item.display = 'root1';
item.otherInformation = { hasChildren: 'true', id: 'root1' }; item.otherInformation = { hasChildren: 'true', id: 'root1' };
itemNode = new TreeviewNode(item, true, pageInfo); itemNode = new TreeviewNode(item, true, pageInfo);
searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true); searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true);
item2 = new VocabularyEntryDetail(); item2 = new VocabularyEntryDetail();
item2.id = item2.value = item2.display = 'root2'; item2.id = 'vocabularyTest:root2';
item2.value = item2.display = 'root2';
item2.otherInformation = { id: 'root2' }; item2.otherInformation = { id: 'root2' };
itemNode2 = new TreeviewNode(item2, false, pageInfo); itemNode2 = new TreeviewNode(item2, false, pageInfo);
item3 = new VocabularyEntryDetail(); item3 = new VocabularyEntryDetail();
item3.id = item3.value = item3.display = 'root3'; item3.id = 'vocabularyTest:root3';
item3.value = item3.display = 'root3';
item3.otherInformation = { id: 'root3' }; item3.otherInformation = { id: 'root3' };
itemNode3 = new TreeviewNode(item3, false, pageInfo); itemNode3 = new TreeviewNode(item3, false, pageInfo);
child = new VocabularyEntryDetail(); 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' }; child.otherInformation = { parent: 'root1', hasChildren: 'true', id: 'root1-child1' };
childNode = new TreeviewNode(child); childNode = new TreeviewNode(child);
searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true); 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 = 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' }; child3.otherInformation = { parent: 'root1-child1', id: 'root1-child1-child1' };
childNode3 = new TreeviewNode(child3); childNode3 = new TreeviewNode(child3);
searchChildNode3 = new TreeviewNode(child3, false, new PageInfo(), child, true); searchChildNode3 = new TreeviewNode(child3, false, new PageInfo(), child, true);
child2 = new VocabularyEntryDetail(); 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' }; child2.otherInformation = { parent: 'root1', id: 'root1-child2' };
childNode2 = new TreeviewNode(child2, true); childNode2 = new TreeviewNode(child2, true);
initValueChildNode2 = new TreeviewNode(child2, false, new PageInfo(), item, false, 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.vocabularyName).toEqual(vocabularyOptions.name);
expect(serviceAsAny.pageInfo).toEqual(pageInfo); expect(serviceAsAny.pageInfo).toEqual(pageInfo);
console.log(serviceAsAny.dataChange.value[0].pageInfo, itemNode.pageInfo);
expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]); expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]);
}); });
@@ -290,7 +300,11 @@ describe('VocabularyTreeviewService test suite', () => {
currentPage: 1 currentPage: 1
}); });
serviceAsAny.vocabularyService.getVocabularyEntriesByValue.and.returnValue(hot('-a', { 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( serviceAsAny.vocabularyService.getEntryDetailParent.and.returnValues(
@@ -305,6 +319,7 @@ describe('VocabularyTreeviewService test suite', () => {
scheduler.schedule(() => service.searchByQuery(vocabularyOptions)); scheduler.schedule(() => service.searchByQuery(vocabularyOptions));
scheduler.flush(); scheduler.flush();
searchChildNode.childrenChange.next([searchChildNode3]); searchChildNode.childrenChange.next([searchChildNode3]);
searchItemNode.childrenChange.next([searchChildNode]); searchItemNode.childrenChange.next([searchChildNode]);
expect(serviceAsAny.dataChange.value.length).toEqual(1); expect(serviceAsAny.dataChange.value.length).toEqual(1);

View File

@@ -134,13 +134,13 @@ export class VocabularyTreeviewService {
* @param onlyFirstTime * @param onlyFirstTime
*/ */
loadMore(item: VocabularyEntryDetail, onlyFirstTime = false) { loadMore(item: VocabularyEntryDetail, onlyFirstTime = false) {
if (!this.nodeMap.has(item.id)) { if (!this.nodeMap.has(item.otherInformation.id)) {
return; return;
} }
const parent: TreeviewNode = this.nodeMap.get(item.id)!; const parent: TreeviewNode = this.nodeMap.get(item.otherInformation.id)!;
const children = this.nodeMap.get(item.id)!.children || []; const children = this.nodeMap.get(item.otherInformation.id)!.children || [];
children.pop(); children.pop();
this.getChildrenNodesByParent(item.id, parent.pageInfo).subscribe((list: PaginatedList<VocabularyEntryDetail>) => { this.getChildrenNodesByParent(item.otherInformation.id, parent.pageInfo).subscribe((list: PaginatedList<VocabularyEntryDetail>) => {
if (onlyFirstTime && parent.children!.length > 0) { if (onlyFirstTime && parent.children!.length > 0) {
return; return;
@@ -187,9 +187,14 @@ export class VocabularyTreeviewService {
this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, new PageInfo()).pipe( this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, new PageInfo()).pipe(
getFirstSucceededRemoteListPayload(), getFirstSucceededRemoteListPayload(),
flatMap((result: VocabularyEntry[]) => (result.length > 0) ? result : observableOf(null)), 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) => { 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; return acc;
} else { } else {
return [...acc, value] return [...acc, value]
@@ -217,24 +222,21 @@ export class VocabularyTreeviewService {
/** /**
* Generate a {@link TreeviewNode} object from vocabulary entry * 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 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 * @param toStore A Boolean representing if the node created is to store or not
* @return TreeviewNode * @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; const entryId = entry.otherInformation.id;
if (this.nodeMap.has(entryId)) { if (this.nodeMap.has(entryId)) {
return this.nodeMap.get(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 hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren === 'true';
const pageInfo: PageInfo = this.pageInfo; const pageInfo: PageInfo = this.pageInfo;
const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId); const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId);
const result = new TreeviewNode( const result = new TreeviewNode(
entryDetail, entry,
hasChildren, hasChildren,
pageInfo, pageInfo,
null, null,
@@ -328,7 +330,7 @@ export class VocabularyTreeviewService {
* @param toStore A Boolean representing if the node created is to store or not * @param toStore A Boolean representing if the node created is to store or not
* @return Observable<string[]> * @return Observable<string[]>
*/ */
private getNodeHierarchy(item: VocabularyEntry, children?: TreeviewNode[], toStore = true): Observable<TreeviewNode> { private getNodeHierarchy(item: VocabularyEntryDetail, children?: TreeviewNode[], toStore = true): Observable<TreeviewNode> {
if (isEmpty(item)) { if (isEmpty(item)) {
return observableOf(null); return observableOf(null);
} }
@@ -337,7 +339,7 @@ export class VocabularyTreeviewService {
if (isNotEmpty(children)) { if (isNotEmpty(children)) {
const newChildren = children const newChildren = children
.filter((entry: TreeviewNode) => { .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) => { newChildren.forEach((entry: TreeviewNode) => {
entry.loadMoreParentItem = node.item entry.loadMoreParentItem = node.item
@@ -346,7 +348,7 @@ export class VocabularyTreeviewService {
} }
if (node.item.hasOtherInformation() && isNotEmpty(node.item.otherInformation.parent)) { 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)) flatMap((parentItem: VocabularyEntryDetail) => this.getNodeHierarchy(parentItem, [node], toStore))
) )
} else { } else {
@@ -362,8 +364,8 @@ export class VocabularyTreeviewService {
* @return string[] * @return string[]
*/ */
private getNodeHierarchyIds(node: TreeviewNode, hierarchyIds: string[] = []): string[] { private getNodeHierarchyIds(node: TreeviewNode, hierarchyIds: string[] = []): string[] {
if (!hierarchyIds.includes(node.item.id)) { if (!hierarchyIds.includes(node.item.otherInformation.id)) {
hierarchyIds.push(node.item.id); hierarchyIds.push(node.item.otherInformation.id);
} }
if (isNotEmpty(node.children)) { if (isNotEmpty(node.children)) {
return this.getNodeHierarchyIds(node.children[0], hierarchyIds); return this.getNodeHierarchyIds(node.children[0], hierarchyIds);