Merge branch 'w2p-121550_refactor-menu-resolvers-7.6_option-1' into refactor-menu-resolvers-7.6_sketch-branch

This commit is contained in:
Yana De Pauw
2025-01-02 17:42:51 +01:00
12 changed files with 96 additions and 33 deletions

View File

@@ -27,10 +27,8 @@ import { RegistriesMenuProvider } from './shared/menu/providers/registries.menu'
import { StatisticsMenuProvider } from './shared/menu/providers/statistics.menu';
import { SystemWideAlertMenuProvider } from './shared/menu/providers/system-wide-alert.menu';
import { WorkflowMenuProvider } from './shared/menu/providers/workflow.menu';
import { COMMUNITY_MODULE_PATH } from './community-page/community-page-routing-paths';
import { COLLECTION_MODULE_PATH } from './collection-page/collection-page-routing-paths';
import { ENTITY_MODULE_PATH, ITEM_MODULE_PATH } from './item-page/item-page-routing-paths';
import { DsoOptionMenu } from './shared/menu/providers/dso-option.menu';
import { MenuRoute } from './shared/menu/menu-route.model';
export const MENUS = buildMenuStructure({
[MenuID.PUBLIC]: [
@@ -54,11 +52,29 @@ export const MENUS = buildMenuStructure({
],
[MenuID.DSO_EDIT]: [
DsoOptionMenu.withSubs([
SubscribeMenuProvider.onRoute(COMMUNITY_MODULE_PATH, COLLECTION_MODULE_PATH),
DSpaceObjectEditMenuProvider.onRoute(COMMUNITY_MODULE_PATH, COLLECTION_MODULE_PATH, ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
VersioningMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
OrcidMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
ClaimMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH, COLLECTION_MODULE_PATH),
SubscribeMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,
),
DSpaceObjectEditMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
VersioningMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
OrcidMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
ClaimMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,
),
]),
],
});

View File

@@ -19,6 +19,7 @@ import { DeleteCollectionPageComponent } from './delete-collection-page/delete-c
import { ItemTemplatePageResolver } from './edit-item-template-page/item-template-page.resolver';
import { ThemedEditItemTemplatePageComponent } from './edit-item-template-page/themed-edit-item-template-page.component';
import { ThemedCollectionPageComponent } from './themed-collection-page.component';
import { MenuRoute } from '../shared/menu/menu-route.model';
@NgModule({
imports: [
@@ -62,6 +63,9 @@ import { ThemedCollectionPageComponent } from './themed-collection-page.componen
path: '',
component: ThemedCollectionPageComponent,
pathMatch: 'full',
data: {
menuRoute: MenuRoute.SIMPLE_COLLECTION_PAGE,
},
}
],
},

View File

@@ -15,6 +15,7 @@ import { CreateCommunityPageComponent } from './create-community-page/create-com
import { CreateCommunityPageGuard } from './create-community-page/create-community-page.guard';
import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component';
import { ThemedCommunityPageComponent } from './themed-community-page.component';
import { MenuRoute } from '../shared/menu/menu-route.model';
@NgModule({
imports: [
@@ -48,6 +49,9 @@ import { ThemedCommunityPageComponent } from './themed-community-page.component'
path: '',
component: ThemedCommunityPageComponent,
pathMatch: 'full',
data: {
menuRoute: MenuRoute.SIMPLE_COMMUNITY_PAGE,
},
}
],
},

View File

@@ -18,6 +18,7 @@ import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
import { VersionPageComponent } from './version-page/version-page/version-page.component';
import { VersionResolver } from './version-page/version.resolver';
import { MenuRoute } from '../shared/menu/menu-route.model';
@NgModule({
imports: [
@@ -34,10 +35,16 @@ import { VersionResolver } from './version-page/version.resolver';
path: '',
component: ThemedItemPageComponent,
pathMatch: 'full',
data: {
menuRoute: MenuRoute.SIMPLE_ITEM_PAGE,
},
},
{
path: 'full',
component: ThemedFullItemPageComponent,
data: {
menuRoute: MenuRoute.FULL_ITEM_PAGE,
},
},
{
path: ITEM_EDIT_PATH,

View File

@@ -11,6 +11,7 @@ import { Observable, } from 'rxjs';
import { MenuID } from './menu-id.model';
import { MenuItemModels } from './menu-section.model';
import { Type } from '@angular/core';
import { MenuRoute } from './menu-route.model';
/**
* Partial menu section
@@ -52,7 +53,7 @@ export interface MenuProvider {
*/
export class MenuProviderTypeWithOptions {
providerType: Type<MenuProvider>;
paths?: string[];
paths?: MenuRoute[];
childProviderTypes?: (Type<MenuProvider> | MenuProviderTypeWithOptions)[];
}
@@ -90,7 +91,7 @@ export abstract class AbstractMenuProvider implements MenuProvider {
* This will be automatically set based on the paths added based on the paths provided through the 'onRoute' static
* method in the app.menus.ts file
*/
activePaths?: string[];
activePaths?: MenuRoute[];
/**
* The ID of the parent provider of this provider.
@@ -110,7 +111,7 @@ export abstract class AbstractMenuProvider implements MenuProvider {
* Static method to be called from the app.menus.ts file to define paths on which this provider should the active
* @param paths - The paths on which the sections of this provider should be active
*/
public static onRoute(...paths: string[]): MenuProviderTypeWithOptions {
public static onRoute(...paths: MenuRoute[]): MenuProviderTypeWithOptions {
if (!AbstractMenuProvider.isPrototypeOf(this)) {
throw new Error(
'onRoute should only be called from concrete subclasses of AbstractMenuProvider'

View File

@@ -7,7 +7,7 @@ import { waitForAsync } from '@angular/core/testing';
import { MenuProviderService } from './menu-provider.service';
import { MenuService } from './menu.service';
import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths';
import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths';
import { MenuRoute } from './menu-route.model';
describe('MenuProviderService', () => {
@@ -18,7 +18,7 @@ describe('MenuProviderService', () => {
public shouldPersistOnRouteChange: boolean,
public menuProviderId: string,
public index: number,
public activePaths: string[],
public activePaths: MenuRoute[],
public parentID: string,
public alwaysRenderExpandable: boolean,
public sections: PartialMenuSection[]
@@ -36,7 +36,12 @@ describe('MenuProviderService', () => {
let menuService: MenuService;
const router = {
events: observableOf(new ResolveEnd(1, 'test-url', 'test-url-after-redirect',{url: 'test-url', root: {url: [new UrlSegment('test-url', {})]}} as any ))
events: observableOf(new ResolveEnd(1, 'test-url', 'test-url-after-redirect', {
url: 'test-url',
root: {url: [new UrlSegment('test-url', {})], data: {}
},
data: {}
} as any))
};
const section = {
@@ -59,7 +64,7 @@ describe('MenuProviderService', () => {
const persistentProvider2 = new TestMenuProvider(MenuID.PUBLIC, true, 'provider2', 1, undefined, 'provider1', false, [section]);
const nonPersistentProvider3 = new TestMenuProvider(MenuID.PUBLIC, false, 'provider3', 2, undefined, undefined, false, [section]);
const nonPersistentProvider4 = new TestMenuProvider(MenuID.PUBLIC, false, 'provider4', 3, undefined, 'provider3', false, [section]);
const nonPersistentProvider5WithRoutes = new TestMenuProvider(MenuID.PUBLIC, false, 'provider4', 3, [COMMUNITY_MODULE_PATH, COLLECTION_MODULE_PATH], undefined, false, [section]);
const nonPersistentProvider5WithRoutes = new TestMenuProvider(MenuID.PUBLIC, false, 'provider4', 3, [MenuRoute.SIMPLE_COMMUNITY_PAGE, MenuRoute.SIMPLE_COLLECTION_PAGE,], undefined, false, [section]);
const listOfProvider = [persistentProvider1, persistentProvider2, nonPersistentProvider3, nonPersistentProvider4, nonPersistentProvider5WithRoutes];
@@ -110,7 +115,7 @@ describe('MenuProviderService', () => {
describe('resolveRouteMenus with no matching path specific providers', () => {
it('should remove the current non persistent menus and add the general non persistent menus', () => {
const route = {};
const route = {data:{}};
const state = {url: 'test-url'};
menuProviderService.resolveRouteMenus(route as any, state as any).subscribe();
@@ -128,7 +133,7 @@ describe('MenuProviderService', () => {
describe('resolveRouteMenus with a matching path specific provider', () => {
it('should remove the current non persistent menus and add the general non persistent menus', () => {
const route = {};
const route = {data:{ menuRoute: MenuRoute.SIMPLE_COMMUNITY_PAGE}};
const state = {url: `xxxx/${COMMUNITY_MODULE_PATH}/xxxxxx`};
menuProviderService.resolveRouteMenus(route as any, state as any).subscribe();

View File

@@ -16,6 +16,7 @@ import { AbstractMenuProvider, PartialMenuSection } from './menu-provider.model'
import { MenuState } from './menu-state.model';
import { MenuService } from './menu.service';
import { MENU_PROVIDER } from './menu.structure';
import { MenuRoute } from './menu-route.model';
/**
* Service that is responsible for adding and removing the menu sections created by the providers, both for
@@ -126,8 +127,8 @@ export class MenuProviderService {
.filter(provider => {
let shouldUpdate = false;
if (!provider.shouldPersistOnRouteChange && isNotEmpty(provider.activePaths)) {
provider.activePaths.forEach((path) => {
if (state.url.includes(path)) {
provider.activePaths.forEach((path: MenuRoute) => {
if (route.data.menuRoute === path) {
shouldUpdate = true;
}
});

View File

@@ -0,0 +1,9 @@
/**
* The menu route IDs that can be used for route resolvers
*/
export enum MenuRoute {
SIMPLE_COMMUNITY_PAGE = 'simple-community-page',
SIMPLE_COLLECTION_PAGE = 'simple-collection-page',
SIMPLE_ITEM_PAGE = 'simple-item-page',
FULL_ITEM_PAGE = 'full-item-page',
}

View File

@@ -3,8 +3,6 @@ import { CommunityListMenuProvider } from './providers/community-list.menu';
import { NewMenuProvider } from './providers/new.menu';
import { DsoOptionMenu } from './providers/dso-option.menu';
import { SubscribeMenuProvider } from './providers/comcol-subscribe.menu';
import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths';
import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths';
import { buildMenuStructure } from './menu.structure';
import { MenuProviderService } from './menu-provider.service';
import { BrowseMenuProvider } from './providers/browse.menu';
@@ -21,10 +19,10 @@ import { WorkflowMenuProvider } from './providers/workflow.menu';
import { HealthMenuProvider } from './providers/health.menu';
import { SystemWideAlertMenuProvider } from './providers/system-wide-alert.menu';
import { DSpaceObjectEditMenuProvider } from './providers/dso-edit.menu';
import { ENTITY_MODULE_PATH, ITEM_MODULE_PATH } from '../../item-page/item-page-routing-paths';
import { VersioningMenuProvider } from './providers/item-versioning.menu';
import { OrcidMenuProvider } from './providers/item-orcid.menu';
import { ClaimMenuProvider } from './providers/item-claim.menu';
import { MenuRoute } from './menu-route.model';
describe('buildMenuStructure', () => {
const providerStructure =
@@ -50,11 +48,29 @@ describe('buildMenuStructure', () => {
],
[MenuID.DSO_EDIT]: [
DsoOptionMenu.withSubs([
SubscribeMenuProvider.onRoute(COMMUNITY_MODULE_PATH, COLLECTION_MODULE_PATH),
DSpaceObjectEditMenuProvider.onRoute(COMMUNITY_MODULE_PATH, COLLECTION_MODULE_PATH, ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
VersioningMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
OrcidMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH),
ClaimMenuProvider.onRoute(ITEM_MODULE_PATH, ENTITY_MODULE_PATH, COLLECTION_MODULE_PATH),
SubscribeMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE
),
DSpaceObjectEditMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
VersioningMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
OrcidMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
),
ClaimMenuProvider.onRoute(
MenuRoute.SIMPLE_ITEM_PAGE,
MenuRoute.FULL_ITEM_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,
),
]),
],
};

View File

@@ -10,6 +10,7 @@ import { MenuID } from './menu-id.model';
import { AbstractMenuProvider, MenuProviderTypeWithOptions } from './menu-provider.model';
import { MenuProviderService } from './menu-provider.service';
import { hasValue, isNotEmpty } from '../empty.util';
import { MenuRoute } from './menu-route.model';
export const MENU_PROVIDER = new InjectionToken<AbstractMenuProvider>('MENU_PROVIDER');
@@ -75,7 +76,7 @@ function processProviderType(providers: Provider[], menuID: string, providerType
* @param hasSubProviders - Whether this provider has sub providers
* @param paths - The paths this provider should be active on if relevant
*/
function addProviderToList(providers: Provider[], providerType: Type<AbstractMenuProvider>, menuID: string, index: number, parentID?: string, hasSubProviders?: boolean, paths?: string[]) {
function addProviderToList(providers: Provider[], providerType: Type<AbstractMenuProvider>, menuID: string, index: number, parentID?: string, hasSubProviders?: boolean, paths?: MenuRoute[]) {
const resolvedProvider = {
provide: MENU_PROVIDER,
multi: true,

View File

@@ -12,7 +12,6 @@ import { MenuItemType } from '../menu-item-type.model';
import { PartialMenuSection } from '../menu-provider.model';
import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu';
import { DSpaceObject } from 'src/app/core/shared/dspace-object.model';
import { hasValue } from '../../empty.util';
/**
* Menu provider to create the parent wrapper menu of the various DSO page menu sections
@@ -23,10 +22,6 @@ export class DsoOptionMenu extends DSpaceObjectPageMenuProvider {
alwaysRenderExpandable = true;
protected isApplicable(dso: DSpaceObject): boolean {
return hasValue(dso);
}
getSectionsForContext(dso: DSpaceObject): Observable<PartialMenuSection[]> {
return of([
{

View File

@@ -40,4 +40,8 @@ export abstract class DSpaceObjectPageMenuProvider extends AbstractRouteContextM
return dso.type.toString().toLowerCase();
}
}
protected isApplicable(dso: DSpaceObject): boolean {
return hasValue(dso);
}
}