From 62629ed23336cc08cd05136ca3aee132fc2ed1d3 Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 15:38:39 +0100 Subject: [PATCH 1/6] Adjust code style --- .../resources/view/state/navigation-path.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/desktop/src/app/components/resources/view/state/navigation-path.ts b/desktop/src/app/components/resources/view/state/navigation-path.ts index 715917f787..4b41ae198e 100644 --- a/desktop/src/app/components/resources/view/state/navigation-path.ts +++ b/desktop/src/app/components/resources/view/state/navigation-path.ts @@ -134,14 +134,12 @@ export module NavigationPath { export function shorten(navPath: NavigationPath, firstToBeExcluded: NavigationPathSegment): NavigationPath { const oldNavPath = NavigationPath.clone(navPath); - navPath.segments - = takeWhile(differentFrom(firstToBeExcluded), oldNavPath.segments); + navPath.segments = takeWhile(differentFrom(firstToBeExcluded), oldNavPath.segments); if (navPath.selectedSegmentId) { - - const stillSelectedSegment = navPath.segments - .find(_ => _.document.resource.id === navPath.selectedSegmentId); - + const stillSelectedSegment: NavigationPathSegment = navPath.segments.find(segment => { + return segment.document.resource.id === navPath.selectedSegmentId; + }); if (!stillSelectedSegment) navPath.selectedSegmentId = undefined; } @@ -180,8 +178,7 @@ export module NavigationPath { } return (!navPath.selectedSegmentId && operationId !== undefined - && Document.hasRelationTarget(document, 'isRecordedIn', - operationId) + && Document.hasRelationTarget(document, 'isRecordedIn',operationId) && !Document.hasRelations(document, 'liesWithin')); } @@ -204,8 +201,7 @@ export module NavigationPath { } - export function replaceSegmentsIfNecessary(navPath: NavigationPath, - newSegments: Array, + export function replaceSegmentsIfNecessary(navPath: NavigationPath, newSegments: Array, newSelectedSegmentId: string): NavigationPath { if (!NavigationPath.segmentNotPresent(navPath, newSelectedSegmentId)) { @@ -243,8 +239,7 @@ export module NavigationPath { } - function rebuildElements(oldSegments: Array, - oldSelectedSegmentId: string|undefined, + function rebuildElements(oldSegments: Array, oldSelectedSegmentId: string|undefined, newSelectedSegmentDoc: FieldDocument): Array { return oldSegments.map(toResourceId).includes(newSelectedSegmentDoc.resource.id) From 11578867b0f770bab1382b092de782478e2e2d4d Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 15:41:44 +0100 Subject: [PATCH 2/6] Clean up NavigationPath code --- .../resources/view/state/navigation-path.ts | 93 ++++++++++--------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/desktop/src/app/components/resources/view/state/navigation-path.ts b/desktop/src/app/components/resources/view/state/navigation-path.ts index 4b41ae198e..a41ec5ae6c 100644 --- a/desktop/src/app/components/resources/view/state/navigation-path.ts +++ b/desktop/src/app/components/resources/view/state/navigation-path.ts @@ -39,10 +39,10 @@ export module NavigationPath { } - export function getSelectedSegment(navPath: NavigationPath): NavigationPathSegment { + export function getSelectedSegment(path: NavigationPath): NavigationPathSegment { - return navPath.segments - .find(on(['document', 'resource', 'id'], is(navPath.selectedSegmentId))) as NavigationPathSegment; + return path.segments + .find(on(['document', 'resource', 'id'], is(path.selectedSegmentId))) as NavigationPathSegment; } @@ -55,22 +55,22 @@ export module NavigationPath { * V * SEGMENT1, SEGMENT2, SEGMENT3 * - * setNewSelectedSegmentDoc(navpath, document4) changes the situation to + * setNewSelectedSegmentDoc(path, document4) changes the situation to * * V * NP: SEGMENT1, SEGMENT2, SEGMENT4 * - * from there, setNewSelectedSegmentDoc(navpath, document5) changes the situation to + * from there, setNewSelectedSegmentDoc(path, document5) changes the situation to * * V * SEGMENT1, SEGMENT2, SEGMENT4, SEGMENT5 * - * from there, setNewSelectedSegmentDoc(navpath, document1) changes the situation to + * from there, setNewSelectedSegmentDoc(path, document1) changes the situation to * * V * SEGMENT1, SEGMENT2, SEGMENT4, SEGMENT5 * - * from there, setNewSelectedSegmentDoc(navpath, undefined) changes the situation to + * from there, setNewSelectedSegmentDoc(path, undefined) changes the situation to * * (NO SELECTED SEGMENT) * SEGMENT1, SEGMENT2, SEGMENT4, SEGMENT5 @@ -84,7 +84,8 @@ export module NavigationPath { navigationPath.segments = rebuildElements( navigationPath.segments, navigationPath.selectedSegmentId, - newSelectedSegmentDoc); + newSelectedSegmentDoc + ); } navigationPath.selectedSegmentId = newSelectedSegmentDoc @@ -95,71 +96,71 @@ export module NavigationPath { } - export function setSelectedDocument(navPath: NavigationPath, document: FieldDocument|undefined) { + export function setSelectedDocument(path: NavigationPath, document: FieldDocument|undefined) { - getViewContext(navPath).selected = document; + getViewContext(path).selected = document; } - export function getSelectedDocument(navPath: NavigationPath): FieldDocument|undefined { + export function getSelectedDocument(path: NavigationPath): FieldDocument|undefined { - return getViewContext(navPath).selected; + return getViewContext(path).selected; } - export function setQueryString(navPath: NavigationPath, q: string) { + export function setQueryString(path: NavigationPath, q: string) { - getViewContext(navPath).q = q; + getViewContext(path).q = q; } - export function getQueryString(navPath: NavigationPath): string { + export function getQueryString(path: NavigationPath): string { - return getViewContext(navPath).q; + return getViewContext(path).q; } - export function setCategoryFilters(navPath: NavigationPath, categories: string[]) { + export function setCategoryFilters(path: NavigationPath, categories: string[]) { - getViewContext(navPath).categories = categories; + getViewContext(path).categories = categories; } - export function getCategoryFilters(navPath: NavigationPath): string[] { + export function getCategoryFilters(path: NavigationPath): string[] { - return getViewContext(navPath).categories; + return getViewContext(path).categories; } - export function shorten(navPath: NavigationPath, firstToBeExcluded: NavigationPathSegment): NavigationPath { + export function shorten(path: NavigationPath, firstToBeExcluded: NavigationPathSegment): NavigationPath { - const oldNavPath = NavigationPath.clone(navPath); - navPath.segments = takeWhile(differentFrom(firstToBeExcluded), oldNavPath.segments); + const oldPath: NavigationPath = NavigationPath.clone(path); + path.segments = takeWhile(differentFrom(firstToBeExcluded), oldPath.segments); - if (navPath.selectedSegmentId) { - const stillSelectedSegment: NavigationPathSegment = navPath.segments.find(segment => { - return segment.document.resource.id === navPath.selectedSegmentId; + if (path.selectedSegmentId) { + const stillSelectedSegment: NavigationPathSegment = path.segments.find(segment => { + return segment.document.resource.id === path.selectedSegmentId; }); - if (!stillSelectedSegment) navPath.selectedSegmentId = undefined; + if (!stillSelectedSegment) path.selectedSegmentId = undefined; } - return navPath; + return path; } - export function segmentNotPresent(navPath: NavigationPath, segmentId: string) { + export function segmentNotPresent(path: NavigationPath, segmentId: string) { - return !segmentId || navPath.segments.map(toResourceId).includes(segmentId); + return !segmentId || path.segments.map(toResourceId).includes(segmentId); } - export function findInvalidSegment(operationId: string|undefined, navPath: NavigationPath, + export function findInvalidSegment(operationId: string|undefined, path: NavigationPath, validNonRecordedInCategories: string[], exists: (_: string) => boolean): NavigationPathSegment|undefined { - for (let segment of navPath.segments) { + for (let segment of path.segments) { if (!NavigationPathSegment.isValid( - operationId, segment, navPath.segments, validNonRecordedInCategories, exists + operationId, segment, path.segments, validNonRecordedInCategories, exists )) { return segment; } @@ -169,15 +170,14 @@ export module NavigationPath { } - export function isPartOfNavigationPath(document: FieldDocument, navPath: NavigationPath, + export function isPartOfNavigationPath(document: FieldDocument, path: NavigationPath, operationId: string|undefined): boolean { - if (navPath.selectedSegmentId && Document.hasRelationTarget(document, 'liesWithin', - navPath.selectedSegmentId)) { + if (path.selectedSegmentId && Document.hasRelationTarget(document, 'liesWithin', path.selectedSegmentId)) { return true; } - return (!navPath.selectedSegmentId && operationId !== undefined + return (!path.selectedSegmentId && operationId !== undefined && Document.hasRelationTarget(document, 'isRecordedIn',operationId) && !Document.hasRelations(document, 'liesWithin')); } @@ -191,6 +191,7 @@ export module NavigationPath { let currentResourceId: string|undefined = documentAsContext ? document.resource.id : ModelUtil.getRelationTargetId(document, 'liesWithin', 0); + while (currentResourceId) { const currentSegmentDoc = await get(currentResourceId); currentResourceId = ModelUtil.getRelationTargetId(currentSegmentDoc, 'liesWithin', 0); @@ -201,15 +202,15 @@ export module NavigationPath { } - export function replaceSegmentsIfNecessary(navPath: NavigationPath, newSegments: Array, + export function replaceSegmentsIfNecessary(path: NavigationPath, newSegments: Array, newSelectedSegmentId: string): NavigationPath { - if (!NavigationPath.segmentNotPresent(navPath, newSelectedSegmentId)) { - navPath.segments = newSegments; + if (!NavigationPath.segmentNotPresent(path, newSelectedSegmentId)) { + path.segments = newSegments; } - navPath.selectedSegmentId = newSelectedSegmentId; - return navPath; + path.selectedSegmentId = newSelectedSegmentId; + return path; } @@ -231,11 +232,11 @@ export module NavigationPath { } - function getViewContext(navPath: NavigationPath): ViewContext { + function getViewContext(path: NavigationPath): ViewContext { - return navPath.selectedSegmentId - ? getSelectedSegment(navPath) - : navPath.basicContext; + return path.selectedSegmentId + ? getSelectedSegment(path) + : path.basicContext; } From 595b0a444a26131e255a25ce9db91d73adc88dc5 Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 15:42:37 +0100 Subject: [PATCH 3/6] Rename parameter --- .../resources/view/state/navigation-path.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/desktop/src/app/components/resources/view/state/navigation-path.ts b/desktop/src/app/components/resources/view/state/navigation-path.ts index a41ec5ae6c..bb00fc6538 100644 --- a/desktop/src/app/components/resources/view/state/navigation-path.ts +++ b/desktop/src/app/components/resources/view/state/navigation-path.ts @@ -77,22 +77,22 @@ export module NavigationPath { * * @return a new path object with updated state */ - export function setNewSelectedSegmentDoc(navigationPath: NavigationPath, + export function setNewSelectedSegmentDoc(path: NavigationPath, newSelectedSegmentDoc: FieldDocument|undefined): NavigationPath { if (newSelectedSegmentDoc) { - navigationPath.segments = rebuildElements( - navigationPath.segments, - navigationPath.selectedSegmentId, + path.segments = rebuildElements( + path.segments, + path.selectedSegmentId, newSelectedSegmentDoc ); } - navigationPath.selectedSegmentId = newSelectedSegmentDoc + path.selectedSegmentId = newSelectedSegmentDoc ? newSelectedSegmentDoc.resource.id : undefined; - return navigationPath; + return path; } From ea9191a40edcdb6cc8ca2bc45063d7bd137a54ea Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 15:55:50 +0100 Subject: [PATCH 4/6] Always scroll to resource of last selected navigation path segment --- .../src/app/components/resources/base-list.ts | 9 +++++---- .../resources/list/list.component.ts | 4 ++-- .../map/list/sidebar-list.component.ts | 4 ++-- .../resources/view/state/navigation-path.ts | 18 ------------------ 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/desktop/src/app/components/resources/base-list.ts b/desktop/src/app/components/resources/base-list.ts index 107dc59280..42bfb5e702 100644 --- a/desktop/src/app/components/resources/base-list.ts +++ b/desktop/src/app/components/resources/base-list.ts @@ -32,6 +32,7 @@ export class BaseList implements AfterViewChecked { private scrollTarget: FieldDocument; private scrollToBottomElement: boolean = false; private scrollOnlyIfInvisible: boolean = false; + private lastSelectedSegment: NavigationPathSegment; constructor(public resourcesComponent: ResourcesComponent, @@ -41,7 +42,8 @@ export class BaseList implements AfterViewChecked { this.navigationPath = this.viewFacade.getNavigationPath(); this.viewFacade.navigationPathNotifications().subscribe(path => { - this.navigationPath = path; + if (this.navigationPath) this.lastSelectedSegment = NavigationPath.getSelectedSegment(this.navigationPath); + this.navigationPath = path; }); } @@ -84,10 +86,9 @@ export class BaseList implements AfterViewChecked { } - protected scrollToNextNavigationPathSegmentResource(path: NavigationPath) { + protected scrollToLastSelectedSegmentResource() { - const segment: NavigationPathSegment = NavigationPath.getNextSegment(path); - if (segment) this.scrollTo(segment.document, false, false, true); + if (this.lastSelectedSegment) this.scrollTo(this.lastSelectedSegment.document, false, false, true); } diff --git a/desktop/src/app/components/resources/list/list.component.ts b/desktop/src/app/components/resources/list/list.component.ts index 0e87869a71..102f25e7dd 100644 --- a/desktop/src/app/components/resources/list/list.component.ts +++ b/desktop/src/app/components/resources/list/list.component.ts @@ -42,8 +42,8 @@ export class ListComponent extends BaseList implements OnChanges { super(resourcesComponent, viewFacade, loading, menuService); - this.viewFacade.navigationPathNotifications().subscribe(path => { - if (!this.selectedDocument) this.scrollToNextNavigationPathSegmentResource(path); + this.viewFacade.navigationPathNotifications().subscribe(() => { + if (!this.selectedDocument) this.scrollToLastSelectedSegmentResource(); }); } diff --git a/desktop/src/app/components/resources/map/list/sidebar-list.component.ts b/desktop/src/app/components/resources/map/list/sidebar-list.component.ts index 0b475657b5..e85cf05b15 100644 --- a/desktop/src/app/components/resources/map/list/sidebar-list.component.ts +++ b/desktop/src/app/components/resources/map/list/sidebar-list.component.ts @@ -56,10 +56,10 @@ export class SidebarListComponent extends BaseList implements AfterViewInit, OnC resourcesComponent.listenToClickEvents().subscribe(event => this.handleClick(event)); - this.viewFacade.navigationPathNotifications().subscribe(path => { + this.viewFacade.navigationPathNotifications().subscribe(() => { this.contextMenu.close(); this.sidebarElement.nativeElement.focus(); - if (!this.selectedDocument) this.scrollToNextNavigationPathSegmentResource(path); + if (!this.selectedDocument) this.scrollToLastSelectedSegmentResource(); }); } diff --git a/desktop/src/app/components/resources/view/state/navigation-path.ts b/desktop/src/app/components/resources/view/state/navigation-path.ts index bb00fc6538..bfe7e3e5db 100644 --- a/desktop/src/app/components/resources/view/state/navigation-path.ts +++ b/desktop/src/app/components/resources/view/state/navigation-path.ts @@ -214,24 +214,6 @@ export module NavigationPath { } - /* - * @returns The next segment in the given navigation path following the currently selected segment - */ - export function getNextSegment(path: NavigationPath) { - - if (!path.segments.length) return undefined; - - const selectedSegment: NavigationPathSegment = NavigationPath.getSelectedSegment(path); - const index: number = path.segments.indexOf(selectedSegment); - - return index === path.segments.length - 1 - ? undefined - : index === -1 - ? path.segments[0] - : path.segments[index + 1]; - } - - function getViewContext(path: NavigationPath): ViewContext { return path.selectedSegmentId From 4d2a65999c9cb5ee2e79ebfe04135cfbb109fcbc Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 16:08:40 +0100 Subject: [PATCH 5/6] Set scroll target to undefined after populating documents [build] --- desktop/src/app/components/resources/base-list.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/desktop/src/app/components/resources/base-list.ts b/desktop/src/app/components/resources/base-list.ts index 42bfb5e702..57e739d73f 100644 --- a/desktop/src/app/components/resources/base-list.ts +++ b/desktop/src/app/components/resources/base-list.ts @@ -10,6 +10,7 @@ import { MenuContext } from '../../services/menu-context'; import { Menus } from '../../services/menus'; import { scrollTo } from '../../angular/scrolling'; import { NavigationPathSegment } from './view/state/navigation-path-segment'; +import { AngularUtility } from '../../angular/angular-utility'; @Component({ @@ -41,10 +42,16 @@ export class BaseList implements AfterViewChecked { protected menuService: Menus) { this.navigationPath = this.viewFacade.getNavigationPath(); + this.viewFacade.navigationPathNotifications().subscribe(path => { if (this.navigationPath) this.lastSelectedSegment = NavigationPath.getSelectedSegment(this.navigationPath); this.navigationPath = path; }); + + this.viewFacade.populateDocumentsNotifications().subscribe(async () => { + await AngularUtility.refresh(); + this.scrollTarget = undefined; + }); } From e27694eceae2eb46ad757e9111e36380069ccc70 Mon Sep 17 00:00:00 2001 From: tkleinke Date: Fri, 21 Feb 2025 16:20:04 +0100 Subject: [PATCH 6/6] Fix BaseList unit tests [build] --- desktop/test/unit/components/resources/base-list.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/test/unit/components/resources/base-list.spec.ts b/desktop/test/unit/components/resources/base-list.spec.ts index c23e424d37..590cf53b96 100644 --- a/desktop/test/unit/components/resources/base-list.spec.ts +++ b/desktop/test/unit/components/resources/base-list.spec.ts @@ -19,6 +19,7 @@ describe('BaseList', () => { viewFacade = { isInExtendedSearchMode: jest.fn(), navigationPathNotifications: jest.fn().mockReturnValue({ subscribe: () => {} }), + populateDocumentsNotifications: jest.fn().mockReturnValue({ subscribe: () => {} }), getNavigationPath: jest.fn().mockReturnValue({}), isInOverview: jest.fn().mockReturnValue(true), getSelectedOperations: jest.fn().mockReturnValue([]),