Skip to content

Commit

Permalink
Merge pull request DSpace#1638 from 4Science/CST-5249_suggestion
Browse files Browse the repository at this point in the history
Openaire suggestions (publication claim)
  • Loading branch information
tdonohue authored Feb 15, 2024
2 parents e1c639e + 75f5462 commit eb433c8
Show file tree
Hide file tree
Showing 107 changed files with 6,494 additions and 135 deletions.
10 changes: 8 additions & 2 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ cache:
anonymousCache:
# Maximum number of pages to cache. Default is zero (0) which means anonymous user cache is disabled.
# As all pages are cached in server memory, increasing this value will increase memory needs.
# Individual cached pages are usually small (<100KB), so a value of max=1000 would only require ~100MB of memory.
# Individual cached pages are usually small (<100KB), so a value of max=1000 would only require ~100MB of memory.
max: 0
# Amount of time after which cached pages are considered stale (in ms). After becoming stale, the cached
# copy is automatically refreshed on the next request.
Expand Down Expand Up @@ -382,7 +382,13 @@ vocabularies:
vocabulary: 'srsc'
enabled: true

# Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query.
# Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query.
comcolSelectionSort:
sortField: 'dc.title'
sortDirection: 'ASC'

# Example of fallback collection for suggestions import
# suggestion:
# - collectionId: 8f7df5ca-f9c2-47a4-81ec-8a6393d6e5af
# source: "openaire"

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';

/**
* Interface for the route parameters.
*/
export interface AdminNotificationsPublicationClaimPageParams {
pageId?: string;
pageSize?: number;
currentPage?: number;
}

/**
* This class represents a resolver that retrieve the route data before the route is activated.
*/
@Injectable()
export class AdminNotificationsPublicationClaimPageResolver implements Resolve<AdminNotificationsPublicationClaimPageParams> {

/**
* Method for resolving the parameters in the current route.
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns AdminNotificationsSuggestionTargetsPageParams Emits the route parameters
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsPublicationClaimPageParams {
return {
pageId: route.queryParams.pageId,
pageSize: parseInt(route.queryParams.pageSize, 10),
currentPage: parseInt(route.queryParams.page, 10)
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ds-publication-claim [source]="'openaire'"></ds-publication-claim>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';

describe('AdminNotificationsPublicationClaimPageComponent', () => {
let component: AdminNotificationsPublicationClaimPageComponent;
let fixture: ComponentFixture<AdminNotificationsPublicationClaimPageComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CommonModule,
TranslateModule.forRoot()
],
declarations: [
AdminNotificationsPublicationClaimPageComponent
],
providers: [
AdminNotificationsPublicationClaimPageComponent
],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Component } from '@angular/core';

@Component({
selector: 'ds-admin-notifications-publication-claim-page',
templateUrl: './admin-notifications-publication-claim-page.component.html',
styleUrls: ['./admin-notifications-publication-claim-page.component.scss']
})
export class AdminNotificationsPublicationClaimPageComponent {

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getNotificationsModuleRoute } from '../admin-routing-paths';

export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance';
export const PUBLICATION_CLAIMS_PATH = 'publication-claim';

export function getQualityAssuranceRoute(id: string) {
return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { RouterModule } from '@angular/router';
import { AuthenticatedGuard } from '../../core/auth/authenticated.guard';
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service';
import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths';
import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component';
import { AdminNotificationsPublicationClaimPageResolver } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service';
import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths';
import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component';
import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component';
Expand All @@ -20,6 +23,21 @@ import {
@NgModule({
imports: [
RouterModule.forChild([
{
canActivate: [ AuthenticatedGuard ],
path: `${PUBLICATION_CLAIMS_PATH}`,
component: AdminNotificationsPublicationClaimPageComponent,
pathMatch: 'full',
resolve: {
breadcrumb: I18nBreadcrumbResolver,
suggestionTargetParams: AdminNotificationsPublicationClaimPageResolver
},
data: {
title: 'admin.notifications.publicationclaim.page.title',
breadcrumbKey: 'admin.notifications.publicationclaim',
showBreadcrumbsFluid: false
}
},
{
canActivate: [ AuthenticatedGuard ],
path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId`,
Expand Down Expand Up @@ -71,7 +89,9 @@ import {
providers: [
I18nBreadcrumbResolver,
I18nBreadcrumbsService,
AdminNotificationsPublicationClaimPageResolver,
SourceDataResolver,
AdminQualityAssuranceSourcePageResolver,
AdminQualityAssuranceTopicsPageResolver,
AdminQualityAssuranceEventsPageResolver,
AdminQualityAssuranceSourcePageResolver,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { NgModule } from '@angular/core';
import { CoreModule } from '../../core/core.module';
import { SharedModule } from '../../shared/shared.module';
import { AdminNotificationsRoutingModule } from './admin-notifications-routing.module';
import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component';
import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component';
import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component';
import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component';
import {NotificationsModule} from '../../notifications/notifications.module';
import { NotificationsModule } from '../../notifications/notifications.module';

@NgModule({
imports: [
Expand All @@ -17,6 +18,7 @@ import {NotificationsModule} from '../../notifications/notifications.module';
NotificationsModule
],
declarations: [
AdminNotificationsPublicationClaimPageComponent,
AdminQualityAssuranceTopicsPageComponent,
AdminQualityAssuranceEventsPageComponent,
AdminQualityAssuranceSourcePageComponent
Expand Down
6 changes: 6 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
ThemedPageInternalServerErrorComponent
} from './page-internal-server-error/themed-page-internal-server-error.component';
import { ServerCheckGuard } from './core/server-check/server-check.guard';
import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths';
import { MenuResolver } from './menu.resolver';
import { ThemedPageErrorComponent } from './page-error/themed-page-error.component';
import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-check-guard.guard';
Expand Down Expand Up @@ -206,6 +207,11 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c
.then((m) => m.ProcessPageModule),
canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard]
},
{ path: SUGGESTION_MODULE_PATH,
loadChildren: () => import('./suggestions-page/suggestions-page.module')
.then((m) => m.SuggestionsPageModule),
canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard]
},
{
path: INFO_MODULE_PATH,
loadChildren: () => import('./info/info.module').then((m) => m.InfoModule)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PublicationClaimBreadcrumbResolver } from './publication-claim-breadcrumb.resolver';

describe('PublicationClaimBreadcrumbResolver', () => {
describe('resolve', () => {
let resolver: PublicationClaimBreadcrumbResolver;
let publicationClaimBreadcrumbService: any;
const fullPath = '/test/publication-claim/openaire:6bee076d-4f2a-4555-a475-04a267769b2a';
const expectedKey = '6bee076d-4f2a-4555-a475-04a267769b2a';
const expectedId = 'openaire:6bee076d-4f2a-4555-a475-04a267769b2a';
let route;

beforeEach(() => {
route = {
paramMap: {
get: function (param) {
return this[param];
},
targetId: expectedId,
}
};
publicationClaimBreadcrumbService = {};
resolver = new PublicationClaimBreadcrumbResolver(publicationClaimBreadcrumbService);
});

it('should resolve the breadcrumb config', () => {
const resolvedConfig = resolver.resolve(route as any, {url: fullPath } as any);
const expectedConfig = { provider: publicationClaimBreadcrumbService, key: expectedKey };
expect(resolvedConfig).toEqual(expectedConfig);
});
});
});
24 changes: 24 additions & 0 deletions src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import {BreadcrumbConfig} from '../../breadcrumbs/breadcrumb/breadcrumb-config.model';
import { PublicationClaimBreadcrumbService } from './publication-claim-breadcrumb.service';

@Injectable({
providedIn: 'root'
})
export class PublicationClaimBreadcrumbResolver implements Resolve<BreadcrumbConfig<string>> {
constructor(protected breadcrumbService: PublicationClaimBreadcrumbService) {
}

/**
* Method that resolve Publication Claim item into a breadcrumb
* The parameter are retrieved by the url since part of the Publication Claim route config
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig<string> {
const targetId = route.paramMap.get('targetId').split(':')[1];
return { provider: this.breadcrumbService, key: targetId };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { getTestScheduler } from 'jasmine-marbles';
import { PublicationClaimBreadcrumbService } from './publication-claim-breadcrumb.service';
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
import { of } from 'rxjs';

describe('PublicationClaimBreadcrumbService', () => {
let service: PublicationClaimBreadcrumbService;
let dsoNameService: any = {
getName: (str) => str
};
let translateService: any = {
instant: (str) => str,
};

let dataService: any = {
findById: (str) => createSuccessfulRemoteDataObject$(str),
};

let authorizationService: any = {
isAuthorized: (str) => of(true),
};

let exampleKey;

const ADMIN_PUBLICATION_CLAIMS_PATH = 'admin/notifications/publication-claim';
const ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY = 'admin.notifications.publicationclaim.page.title';

function init() {
exampleKey = 'suggestion.suggestionFor.breadcrumb';
}

beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({}).compileComponents();
}));

beforeEach(() => {
service = new PublicationClaimBreadcrumbService(dataService,dsoNameService,translateService, authorizationService);
});

describe('getBreadcrumbs', () => {
it('should return a breadcrumb based on a string', () => {
const breadcrumbs = service.getBreadcrumbs(exampleKey);
getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: [new Breadcrumb(ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY, ADMIN_PUBLICATION_CLAIMS_PATH),
new Breadcrumb(exampleKey, undefined)]
});
});
});
});
46 changes: 46 additions & 0 deletions src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { BreadcrumbsProviderService } from './breadcrumbsProviderService';
import { combineLatest, Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { ItemDataService } from '../data/item-data.service';
import { getFirstCompletedRemoteData } from '../shared/operators';
import { map } from 'rxjs/operators';
import { DSONameService } from './dso-name.service';
import { TranslateService } from '@ngx-translate/core';
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
import { FeatureID } from '../data/feature-authorization/feature-id';



/**
* Service to calculate Publication claims breadcrumbs
*/
@Injectable({
providedIn: 'root'
})
export class PublicationClaimBreadcrumbService implements BreadcrumbsProviderService<string> {
private ADMIN_PUBLICATION_CLAIMS_PATH = 'admin/notifications/publication-claim';
private ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY = 'admin.notifications.publicationclaim.page.title';

constructor(private dataService: ItemDataService,
private dsoNameService: DSONameService,
private tranlsateService: TranslateService,
protected authorizationService: AuthorizationDataService) {
}


/**
* Method to calculate the breadcrumbs
* @param key The key used to resolve the breadcrumb
*/
getBreadcrumbs(key: string): Observable<Breadcrumb[]> {
return combineLatest([this.dataService.findById(key).pipe(getFirstCompletedRemoteData()),this.authorizationService.isAuthorized(FeatureID.AdministratorOf)]).pipe(
map(([item, isAdmin]) => {
const itemName = this.dsoNameService.getName(item.payload);
return isAdmin ? [new Breadcrumb(this.tranlsateService.instant(this.ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY), this.ADMIN_PUBLICATION_CLAIMS_PATH),
new Breadcrumb(this.tranlsateService.instant('suggestion.suggestionFor.breadcrumb', {name: itemName}), undefined)] :
[new Breadcrumb(this.tranlsateService.instant('suggestion.suggestionFor.breadcrumb', {name: itemName}), undefined)];
})
);
}
}
14 changes: 13 additions & 1 deletion src/app/core/cache/builders/build-decorators.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HALLink } from '../../shared/hal-link.model';
import { HALResource } from '../../shared/hal-resource.model';
import { ResourceType } from '../../shared/resource-type';
import { getLinkDefinition, link } from './build-decorators';
import { dataService, getDataServiceFor, getLinkDefinition, link } from './build-decorators';

class TestHALResource implements HALResource {
_links: {
Expand Down Expand Up @@ -46,5 +46,17 @@ describe('build decorators', () => {
expect(result).toBeUndefined();
});
});

describe(`set data service`, () => {
it(`should throw error`, () => {
expect(dataService(null)).toThrow();
});

it(`should set properly data service for type`, () => {
const target = new TestHALResource();
dataService(testType)(target);
expect(getDataServiceFor(testType)).toEqual(target);
});
});
});
});
Loading

0 comments on commit eb433c8

Please sign in to comment.