Skip to content

Commit

Permalink
Merge branch '3.5.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
tkleinke committed Feb 21, 2025
2 parents fb0904a + e27694e commit a5b1eac
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 86 deletions.
16 changes: 12 additions & 4 deletions desktop/src/app/components/resources/base-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -32,6 +33,7 @@ export class BaseList implements AfterViewChecked {
private scrollTarget: FieldDocument;
private scrollToBottomElement: boolean = false;
private scrollOnlyIfInvisible: boolean = false;
private lastSelectedSegment: NavigationPathSegment;


constructor(public resourcesComponent: ResourcesComponent,
Expand All @@ -40,8 +42,15 @@ export class BaseList implements AfterViewChecked {
protected menuService: Menus) {

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;
});

this.viewFacade.populateDocumentsNotifications().subscribe(async () => {
await AngularUtility.refresh();
this.scrollTarget = undefined;
});
}

Expand Down Expand Up @@ -84,10 +93,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);
}


Expand Down
4 changes: 2 additions & 2 deletions desktop/src/app/components/resources/list/list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
}

Expand Down
134 changes: 56 additions & 78 deletions desktop/src/app/components/resources/view/state/navigation-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand All @@ -55,113 +55,112 @@ 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
*
* @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,
newSelectedSegmentDoc);
path.segments = rebuildElements(
path.segments,
path.selectedSegmentId,
newSelectedSegmentDoc
);
}

navigationPath.selectedSegmentId = newSelectedSegmentDoc
path.selectedSegmentId = newSelectedSegmentDoc
? newSelectedSegmentDoc.resource.id
: undefined;

return navigationPath;
return path;
}


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 = navPath.segments
.find(_ => _.document.resource.id === navPath.selectedSegmentId);

if (!stillSelectedSegment) navPath.selectedSegmentId = undefined;
if (path.selectedSegmentId) {
const stillSelectedSegment: NavigationPathSegment = path.segments.find(segment => {
return segment.document.resource.id === path.selectedSegmentId;
});
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;
}
Expand All @@ -171,17 +170,15 @@ 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
&& Document.hasRelationTarget(document, 'isRecordedIn',
operationId)
return (!path.selectedSegmentId && operationId !== undefined
&& Document.hasRelationTarget(document, 'isRecordedIn',operationId)
&& !Document.hasRelations(document, 'liesWithin'));
}

Expand All @@ -194,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);
Expand All @@ -204,47 +202,27 @@ export module NavigationPath {
}


export function replaceSegmentsIfNecessary(navPath: NavigationPath,
newSegments: Array<NavigationPathSegment>,
export function replaceSegmentsIfNecessary(path: NavigationPath, newSegments: Array<NavigationPathSegment>,
newSelectedSegmentId: string): NavigationPath {

if (!NavigationPath.segmentNotPresent(navPath, newSelectedSegmentId)) {
navPath.segments = newSegments;
if (!NavigationPath.segmentNotPresent(path, newSelectedSegmentId)) {
path.segments = newSegments;
}

navPath.selectedSegmentId = newSelectedSegmentId;
return navPath;
}


/*
* @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];
path.selectedSegmentId = newSelectedSegmentId;
return path;
}


function getViewContext(navPath: NavigationPath): ViewContext {
function getViewContext(path: NavigationPath): ViewContext {

return navPath.selectedSegmentId
? getSelectedSegment(navPath)
: navPath.basicContext;
return path.selectedSegmentId
? getSelectedSegment(path)
: path.basicContext;
}


function rebuildElements(oldSegments: Array<NavigationPathSegment>,
oldSelectedSegmentId: string|undefined,
function rebuildElements(oldSegments: Array<NavigationPathSegment>, oldSelectedSegmentId: string|undefined,
newSelectedSegmentDoc: FieldDocument): Array<NavigationPathSegment> {

return oldSegments.map(toResourceId).includes(newSelectedSegmentDoc.resource.id)
Expand Down
1 change: 1 addition & 0 deletions desktop/test/unit/components/resources/base-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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([]),
Expand Down

0 comments on commit a5b1eac

Please sign in to comment.