diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index 4e65d2c96b6..af2612911bd 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -75,7 +75,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; data: { menu: { public: [{ - id: 'statistics_collection', + id: 'statistics_collection_:id', active: true, visible: true, model: { diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index a8e79e662fe..66a5a73198e 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -51,7 +51,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; data: { menu: { public: [{ - id: 'statistics_community', + id: 'statistics_community_:id', active: true, visible: true, model: { diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index 3e6cf26b1be..e4f17326a42 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -48,7 +48,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; data: { menu: { public: [{ - id: 'statistics_item', + id: 'statistics_item_:id', active: true, visible: true, model: { diff --git a/src/app/shared/menu/menu.effects.spec.ts b/src/app/shared/menu/menu.effects.spec.ts index 11b468eded4..911dbe1de6a 100644 --- a/src/app/shared/menu/menu.effects.spec.ts +++ b/src/app/shared/menu/menu.effects.spec.ts @@ -14,6 +14,7 @@ import { MenuEffects } from './menu.effects'; describe('MenuEffects', () => { let menuEffects: MenuEffects; let routeDataMenuSection: MenuSection; + let routeDataMenuSectionResolved: MenuSection; let routeDataMenuChildSection: MenuSection; let toBeRemovedMenuSection: MenuSection; let alreadyPresentMenuSection: MenuSection; @@ -23,13 +24,23 @@ describe('MenuEffects', () => { function init() { routeDataMenuSection = { - id: 'mockSection', + id: 'mockSection_:idparam', active: false, visible: true, model: { type: MenuItemType.LINK, text: 'menu.section.mockSection', - link: '' + link: 'path/:linkparam' + } as LinkMenuItemModel + }; + routeDataMenuSectionResolved = { + id: 'mockSection_id_param_resolved', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.mockSection', + link: 'path/link_param_resolved' } as LinkMenuItemModel }; routeDataMenuChildSection = { @@ -70,6 +81,10 @@ describe('MenuEffects', () => { menu: { [MenuID.PUBLIC]: [routeDataMenuSection, alreadyPresentMenuSection] } + }, + params: { + idparam: 'id_param_resolved', + linkparam: 'link_param_resolved', } }, firstChild: { @@ -120,7 +135,7 @@ describe('MenuEffects', () => { }); expect(menuEffects.buildRouteMenuSections$).toBeObservable(expected); - expect(menuService.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuSection); + expect(menuService.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuSectionResolved); expect(menuService.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuChildSection); expect(menuService.addSection).not.toHaveBeenCalledWith(MenuID.PUBLIC, alreadyPresentMenuSection); expect(menuService.removeSection).toHaveBeenCalledWith(MenuID.PUBLIC, toBeRemovedMenuSection.id); diff --git a/src/app/shared/menu/menu.effects.ts b/src/app/shared/menu/menu.effects.ts index ea5f569da38..d8aa64f862e 100644 --- a/src/app/shared/menu/menu.effects.ts +++ b/src/app/shared/menu/menu.effects.ts @@ -19,7 +19,7 @@ export class MenuEffects { /** * On route change, build menu sections for every menu type depending on the current route data */ - @Effect({ dispatch: false }) + @Effect({dispatch: false}) public buildRouteMenuSections$: Observable = this.actions$ .pipe( ofType(ROUTER_NAVIGATED), @@ -73,20 +73,8 @@ export class MenuEffects { if (hasValue(data) && hasValue(data.menu) && hasValue(data.menu[menuID])) { - const menuSections = data.menu[menuID]; - [...menuSections] - .forEach((menuSection) => { - - if (hasValue(menuSection.model) && hasValue(menuSection.model.link)) { - let substitute: RegExpMatchArray; - do { - substitute = menuSection.model.link.match(/\/:(.*?)\//); - if (substitute) { - menuSection.model.link = menuSection.model.link.replace(substitute[0], `/${params[substitute[1]]}/`); - } - } while (substitute); - } - }); + let menuSections: MenuSection[] | MenuSection = data.menu[menuID]; + menuSections = this.resolveSubstitutions(menuSections, params); if (!last) { return [...menuSections, ...this.resolveRouteMenuSections(route.firstChild, menuID)] @@ -98,4 +86,30 @@ export class MenuEffects { return !last ? this.resolveRouteMenuSections(route.firstChild, menuID) : []; } + private resolveSubstitutions(object, params) { + + if (typeof object === 'string') { + let match: RegExpMatchArray; + do { + match = object.match(/:(\w+)/); + if (match) { + const substitute = params[match[1]]; + if (hasValue(substitute)) { + object = object.replace(match[0], `${substitute}`); + } + } + } while (match); + } else if (Array.isArray(object)) { + object.forEach((entry, index) => { + object[index] = this.resolveSubstitutions(object[index], params); + }); + } else { + Object.keys(object).forEach((key) => { + object = Object.assign({}, object, { + [key]: this.resolveSubstitutions(object[key], params) + }); + }); + } + return object; + } } diff --git a/src/app/statistics-page/statistics-page/statistics-page.component.html b/src/app/statistics-page/statistics-page/statistics-page.component.html index 56b880ec3fb..5c3f67ac828 100644 --- a/src/app/statistics-page/statistics-page/statistics-page.component.html +++ b/src/app/statistics-page/statistics-page/statistics-page.component.html @@ -12,5 +12,10 @@ [report]="report" class="m-2 {{ report.id }}"> + +
+ {{ 'statistics.page.no-data' | translate }} +
+
diff --git a/src/app/statistics-page/statistics-page/statistics-page.component.ts b/src/app/statistics-page/statistics-page/statistics-page.component.ts index 756385ce6cf..07748ebd1fb 100644 --- a/src/app/statistics-page/statistics-page/statistics-page.component.ts +++ b/src/app/statistics-page/statistics-page/statistics-page.component.ts @@ -29,6 +29,8 @@ export abstract class StatisticsPageComponent implements */ reports$: Observable; + hasData$: Observable; + constructor( protected route: ActivatedRoute, protected router: Router, @@ -40,6 +42,11 @@ export abstract class StatisticsPageComponent implements ngOnInit(): void { this.scope$ = this.getScope$(); this.reports$ = this.getReports$(); + this.hasData$ = this.reports$.pipe( + map((reports) => reports.some( + (report) => report.points.length > 0 + )), + ); } /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 37cc2050384..2984ce24065 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2783,6 +2783,8 @@ "statistics.breadcrumbs": "Statistics", + "statistics.page.no-data": "No data available", + "statistics.table.no-data": "No data available", "statistics.table.title.TotalVisits": "Total visits",