Add statistics pages - add support for parameters in menu sections and add id params

This commit is contained in:
Samuel
2020-09-23 15:59:26 +02:00
parent e7e408dacb
commit 6ff9429bc0
8 changed files with 64 additions and 21 deletions

View File

@@ -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: {

View File

@@ -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: {

View File

@@ -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: {

View File

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

View File

@@ -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<Action> = 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;
}
}

View File

@@ -12,5 +12,10 @@
[report]="report"
class="m-2 {{ report.id }}">
</ds-statistics-table>
<ng-container *ngIf="!!hasData$">
<div *ngIf="!(hasData$ | async)">
{{ 'statistics.page.no-data' | translate }}
</div>
</ng-container>
</div>

View File

@@ -29,6 +29,8 @@ export abstract class StatisticsPageComponent<T extends DSpaceObject> implements
*/
reports$: Observable<UsageReport[]>;
hasData$: Observable<boolean>;
constructor(
protected route: ActivatedRoute,
protected router: Router,
@@ -40,6 +42,11 @@ export abstract class StatisticsPageComponent<T extends DSpaceObject> 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
)),
);
}
/**

View File

@@ -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",