From b8e9f620b6da41b4bcdd31f565096b58f1779675 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 18 Feb 2022 16:40:45 +0100 Subject: [PATCH 001/153] [CST-5249] Migration of OPENAIRE correction service --- ...ations-openaire-events-page.component.html | 1 + ...ons-openaire-events-page.component.spec.ts | 26 + ...ications-openaire-events-page.component.ts | 9 + ...fications-openaire-events-page.resolver.ts | 32 + ...s-openaire-topics-page-resolver.service.ts | 32 + ...ations-openaire-topics-page.component.html | 1 + ...ons-openaire-topics-page.component.spec.ts | 26 + ...ications-openaire-topics-page.component.ts | 9 + .../admin-notifications-routing-paths.ts | 8 + .../admin-notifications-routing.module.ts | 60 + .../admin-notifications.module.ts | 29 + src/app/admin/admin-routing-paths.ts | 5 + src/app/admin/admin-routing.module.ts | 7 +- .../admin-sidebar/admin-sidebar.component.ts | 39 +- src/app/core/core.module.ts | 4 + src/app/core/data/data.service.ts | 49 +- ...openaire-broker-event-rest.service.spec.ts | 246 +++ .../openaire-broker-event-rest.service.ts | 185 ++ ...naire-broker-event-object.resource-type.ts | 9 + .../models/openaire-broker-event.model.ts | 157 ++ ...naire-broker-topic-object.resource-type.ts | 9 + .../models/openaire-broker-topic.model.ts | 58 + ...openaire-broker-topic-rest.service.spec.ts | 127 ++ .../openaire-broker-topic-rest.service.ts | 133 ++ .../openaire-broker-events.component.html | 207 ++ .../openaire-broker-events.component.spec.ts | 332 +++ .../openaire-broker-events.component.ts | 464 +++++ .../openaire-broker-events.scomponent.scss | 21 + .../project-entry-import-modal.component.html | 70 + .../project-entry-import-modal.component.scss | 3 + ...oject-entry-import-modal.component.spec.ts | 210 ++ .../project-entry-import-modal.component.ts | 274 +++ .../topics/openaire-broker-topics.actions.ts | 99 + .../openaire-broker-topics.component.html | 57 + .../openaire-broker-topics.component.scss | 0 .../openaire-broker-topics.component.spec.ts | 152 ++ .../openaire-broker-topics.component.ts | 142 ++ .../topics/openaire-broker-topics.effects.ts | 87 + .../openaire-broker-topics.reducer.spec.ts | 68 + .../topics/openaire-broker-topics.reducer.ts | 72 + .../openaire-broker-topics.service.spec.ts | 67 + .../topics/openaire-broker-topics.service.ts | 55 + .../openaire/openaire-state.service.spec.ts | 275 +++ src/app/openaire/openaire-state.service.ts | 116 ++ src/app/openaire/openaire.effects.ts | 5 + src/app/openaire/openaire.module.ts | 74 + src/app/openaire/openaire.reducer.ts | 16 + src/app/openaire/selectors.ts | 79 + src/app/shared/mocks/openaire.mock.ts | 1796 +++++++++++++++++ .../pagination/pagination.component.html | 6 +- .../shared/pagination/pagination.component.ts | 5 + src/app/shared/selector.util.ts | 27 + src/assets/i18n/en.json5 | 137 ++ 53 files changed, 6165 insertions(+), 12 deletions(-) create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-routing-paths.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-routing.module.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications.module.ts create mode 100644 src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts create mode 100644 src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts create mode 100644 src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts create mode 100644 src/app/core/openaire/broker/models/openaire-broker-event.model.ts create mode 100644 src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts create mode 100644 src/app/core/openaire/broker/models/openaire-broker-topic.model.ts create mode 100644 src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts create mode 100644 src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts create mode 100644 src/app/openaire/broker/events/openaire-broker-events.component.html create mode 100644 src/app/openaire/broker/events/openaire-broker-events.component.spec.ts create mode 100644 src/app/openaire/broker/events/openaire-broker-events.component.ts create mode 100644 src/app/openaire/broker/events/openaire-broker-events.scomponent.scss create mode 100644 src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html create mode 100644 src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss create mode 100644 src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts create mode 100644 src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.actions.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.component.html create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.component.scss create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.component.spec.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.component.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.effects.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.reducer.spec.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.reducer.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.service.spec.ts create mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.service.ts create mode 100644 src/app/openaire/openaire-state.service.spec.ts create mode 100644 src/app/openaire/openaire-state.service.ts create mode 100644 src/app/openaire/openaire.effects.ts create mode 100644 src/app/openaire/openaire.module.ts create mode 100644 src/app/openaire/openaire.reducer.ts create mode 100644 src/app/openaire/selectors.ts create mode 100644 src/app/shared/mocks/openaire.mock.ts create mode 100644 src/app/shared/selector.util.ts diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html new file mode 100644 index 0000000000..5c8f8820a0 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts new file mode 100644 index 0000000000..ab7a08a695 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page.component'; + +describe('AdminNotificationsOpenaireEventsPageComponent', () => { + let component: AdminNotificationsOpenaireEventsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminNotificationsOpenaireEventsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminNotificationsOpenaireEventsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminNotificationsOpenaireEventsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts new file mode 100644 index 0000000000..df7b21dbda --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notification-openaire-events-page', + templateUrl: './admin-notifications-openaire-events-page.component.html' +}) +export class AdminNotificationsOpenaireEventsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts new file mode 100644 index 0000000000..b215013e11 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; + +/** + * Interface for the route parameters. + */ +export interface AdminNotificationsOpenaireEventsPageParams { + pageId?: string; + pageSize?: number; + currentPage?: number; +} + +/** + * This class represents a resolver that retrieve the route data before the route is activated. + */ +@Injectable() +export class AdminNotificationsOpenaireEventsPageResolver implements Resolve { + + /** + * Method for resolving the parameters in the current route. + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns AdminNotificationsOpenaireEventsPageParams Emits the route parameters + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsOpenaireEventsPageParams { + return { + pageId: route.queryParams.pageId, + pageSize: parseInt(route.queryParams.pageSize, 10), + currentPage: parseInt(route.queryParams.page, 10) + }; + } +} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts new file mode 100644 index 0000000000..f8e02cabbf --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; + +/** + * Interface for the route parameters. + */ +export interface AdminNotificationsOpenaireTopicsPageParams { + pageId?: string; + pageSize?: number; + currentPage?: number; +} + +/** + * This class represents a resolver that retrieve the route data before the route is activated. + */ +@Injectable() +export class AdminNotificationsOpenaireTopicsPageResolver implements Resolve { + + /** + * Method for resolving the parameters in the current route. + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns AdminNotificationsOpenaireTopicsPageParams Emits the route parameters + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsOpenaireTopicsPageParams { + return { + pageId: route.queryParams.pageId, + pageSize: parseInt(route.queryParams.pageSize, 10), + currentPage: parseInt(route.queryParams.page, 10) + }; + } +} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html new file mode 100644 index 0000000000..b1616cfe78 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts new file mode 100644 index 0000000000..712c7ba2c3 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page.component'; + +describe('AdminNotificationsOpenaireTopicsPageComponent', () => { + let component: AdminNotificationsOpenaireTopicsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminNotificationsOpenaireTopicsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminNotificationsOpenaireTopicsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminNotificationsOpenaireTopicsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts new file mode 100644 index 0000000000..5bf1832c59 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notification-openairebroker-page', + templateUrl: './admin-notifications-openaire-topics-page.component.html' +}) +export class AdminNotificationsOpenaireTopicsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts new file mode 100644 index 0000000000..ea7242adcb --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -0,0 +1,8 @@ +import { URLCombiner } from '../../core/url-combiner/url-combiner'; +import { getNotificationsModuleRoute } from '../admin-routing-paths'; + +export const NOTIFICATIONS_EDIT_PATH = 'openaire-broker'; + +export function getNotificationsOpenairebrokerRoute(id: string) { + return new URLCombiner(getNotificationsModuleRoute(), NOTIFICATIONS_EDIT_PATH, id).toString(); +} diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts new file mode 100644 index 0000000000..2dfa938c4f --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -0,0 +1,60 @@ +import { NgModule } from '@angular/core'; +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 { NOTIFICATIONS_EDIT_PATH } from './admin-notifications-routing-paths'; +import { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component'; +import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component'; +import { AdminNotificationsOpenaireTopicsPageResolver } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service'; +import { AdminNotificationsOpenaireEventsPageResolver } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + canActivate: [ AuthenticatedGuard ], + path: `${NOTIFICATIONS_EDIT_PATH}`, + component: AdminNotificationsOpenaireTopicsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireBrokerTopicsParams: AdminNotificationsOpenaireTopicsPageResolver + }, + data: { + title: 'admin.notifications.openairebroker.page.title', + breadcrumbKey: 'admin.notifications.openairebroker', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ AuthenticatedGuard ], + path: `${NOTIFICATIONS_EDIT_PATH}/:id`, + component: AdminNotificationsOpenaireEventsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireBrokerEventsParams: AdminNotificationsOpenaireEventsPageResolver + }, + data: { + title: 'admin.notifications.openaireevent.page.title', + breadcrumbKey: 'admin.notifications.openaireevent', + showBreadcrumbsFluid: false + } + } + ]) + ], + providers: [ + I18nBreadcrumbResolver, + I18nBreadcrumbsService, + AdminNotificationsOpenaireTopicsPageResolver, + AdminNotificationsOpenaireEventsPageResolver + ] +}) +/** + * Routing module for the Notifications section of the admin sidebar + */ +export class AdminNotificationsRoutingModule { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts new file mode 100644 index 0000000000..9894dac233 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -0,0 +1,29 @@ +import { CommonModule } from '@angular/common'; +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 { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component'; +import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component'; +import { OpenaireModule } from '../../openaire/openaire.module'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + AdminNotificationsRoutingModule, + OpenaireModule + ], + declarations: [ + AdminNotificationsOpenaireTopicsPageComponent, + AdminNotificationsOpenaireEventsPageComponent + ], + entryComponents: [] +}) +/** + * This module handles all components related to the notifications pages + */ +export class AdminNotificationsModule { + +} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 3168ea93c9..30f801cecb 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -2,7 +2,12 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getAdminModuleRoute } from '../app-routing-paths'; export const REGISTRIES_MODULE_PATH = 'registries'; +export const NOTIFICATIONS_MODULE_PATH = 'notifications'; export function getRegistriesModuleRoute() { return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString(); } + +export function getNotificationsModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index ee5cb8737b..782a7faa38 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,11 +6,16 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; -import { REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; @NgModule({ imports: [ RouterModule.forChild([ + { + path: NOTIFICATIONS_MODULE_PATH, + loadChildren: () => import('./admin-notifications/admin-notifications.module') + .then((m) => m.AdminNotificationsModule), + }, { path: REGISTRIES_MODULE_PATH, loadChildren: () => import('./admin-registries/admin-registries.module') diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.ts index c81b2e6e93..a2a7eb30b5 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -276,7 +276,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { // link: '' // } as LinkMenuItemModel, // icon: 'chart-bar', - // index: 8 + // index: 9 // }, /* Control Panel */ @@ -291,7 +291,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { // link: '' // } as LinkMenuItemModel, // icon: 'cogs', - // index: 9 + // index: 10 // }, /* Processes */ @@ -305,7 +305,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '/processes' } as LinkMenuItemModel, icon: 'terminal', - index: 10 + index: 11 }, ]; menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { @@ -464,6 +464,29 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { createSiteAdministratorMenuSections() { this.authorizationService.isAuthorized(FeatureID.AdministratorOf).subscribe((authorized) => { const menuList = [ + /* Notifications */ + { + id: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications' + } as TextMenuItemModel, + icon: 'bell', + index: 4 + }, + { + id: 'notifications_openair_broker', + parentID: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_openaire_broker', + link: '/admin/notifications/openaire-broker' + } as LinkMenuItemModel, + }, /* Admin Search */ { id: 'admin_search', @@ -475,7 +498,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '/admin/search' } as LinkMenuItemModel, icon: 'search', - index: 5 + index: 6 }, /* Registries */ { @@ -487,7 +510,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { text: 'menu.section.registries' } as TextMenuItemModel, icon: 'list', - index: 6 + index: 7 }, { id: 'registries_metadata', @@ -523,7 +546,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: 'admin/curation-tasks' } as LinkMenuItemModel, icon: 'filter', - index: 7 + index: 8 }, /* Workflow */ @@ -537,7 +560,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '/admin/workflow' } as LinkMenuItemModel, icon: 'user-check', - index: 11 + index: 12 }, ]; @@ -600,7 +623,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { text: 'menu.section.access_control' } as TextMenuItemModel, icon: 'key', - index: 4 + index: 5 }, ]; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 8d8a614a89..928d34c48e 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -162,6 +162,8 @@ import { SearchConfig } from './shared/search/search-filters/search-config.model import { SequenceService } from './shared/sequence.service'; import { GroupDataService } from './eperson/group-data.service'; import { SubmissionAccessesModel } from './config/models/config-submission-accesses.model'; +import { OpenaireBrokerTopicObject } from './openaire/broker/models/openaire-broker-topic.model'; +import { OpenaireBrokerEventObject } from './openaire/broker/models/openaire-broker-event.model'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -343,6 +345,8 @@ export const models = ShortLivedToken, Registration, UsageReport, + OpenaireBrokerTopicObject, + OpenaireBrokerEventObject, Root, SearchConfig, SubmissionAccessesModel diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 6bad02e776..0b4f3af4b4 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -38,7 +38,7 @@ import { FindListOptions, PatchRequest, PutRequest, - DeleteRequest + DeleteRequest, DeleteByIDRequest, PostRequest } from './request.models'; import { RequestService } from './request.service'; import { RestRequestMethod } from './rest-request-method'; @@ -579,6 +579,53 @@ export abstract class DataService implements UpdateDa return result$; } + /** + * Perform a post on an endpoint related item with ID. Ex.: endpoint//related?item= + * @param itemId The item id + * @param relatedItemId The related item Id + * @param body The optional POST body + * @return the RestResponse as an Observable + */ + public postOnRelated(itemId: string, relatedItemId: string, body?: any) { + const requestId = this.requestService.generateRequestId(); + const hrefObs = this.getIDHrefObs(itemId); + + hrefObs.pipe( + take(1) + ).subscribe((href: string) => { + const request = new PostRequest(requestId, href + '/related?item=' + relatedItemId, body); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + }); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + /** + * Perform a delete on an endpoint related item. Ex.: endpoint//related + * @param itemId The item id + * @return the RestResponse as an Observable + */ + public deleteOnRelated(itemId: string): Observable> { + const requestId = this.requestService.generateRequestId(); + const hrefObs = this.getIDHrefObs(itemId); + + hrefObs.pipe( + find((href: string) => hasValue(href)), + map((href: string) => { + const request = new DeleteByIDRequest(requestId, href + '/related', itemId); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + }) + ).subscribe(); + + return this.rdbService.buildFromRequestUUID(requestId); + } + /** * Delete an existing DSpace Object on the server * @param objectId The id of the object to be removed diff --git a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts b/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts new file mode 100644 index 0000000000..2d0d236330 --- /dev/null +++ b/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts @@ -0,0 +1,246 @@ +import { HttpClient } from '@angular/common/http'; + +import { TestScheduler } from 'rxjs/testing'; +import { of as observableOf } from 'rxjs'; +import { cold, getTestScheduler } from 'jasmine-marbles'; + +import { RequestService } from '../../../data/request.service'; +import { buildPaginatedList } from '../../../data/paginated-list.model'; +import { RequestEntry } from '../../../data/request.reducer'; +import { FindListOptions } from '../../../data/request.models'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { RestResponse } from '../../../cache/response.models'; +import { PageInfo } from '../../../shared/page-info.model'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; +import { OpenaireBrokerEventRestService } from './openaire-broker-event-rest.service'; +import { + openaireBrokerEventObjectMissingPid, + openaireBrokerEventObjectMissingPid2, + openaireBrokerEventObjectMissingProjectFound +} from '../../../../shared/mocks/openaire.mock'; +import { ReplaceOperation } from 'fast-json-patch'; + +describe('OpenaireBrokerEventRestService', () => { + let scheduler: TestScheduler; + let service: OpenaireBrokerEventRestService; + let serviceASAny: any; + let responseCacheEntry: RequestEntry; + let responseCacheEntryB: RequestEntry; + let responseCacheEntryC: RequestEntry; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparator: any; + + const endpointURL = 'https://rest.api/rest/api/integration/nbtopics'; + const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; + const topic = 'ENRICH!MORE!PID'; + + const pageInfo = new PageInfo(); + const array = [ openaireBrokerEventObjectMissingPid, openaireBrokerEventObjectMissingPid2 ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const brokerEventObjectRD = createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingPid); + const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingProjectFound); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + + const status = 'ACCEPTED'; + const operation: ReplaceOperation[] = [ + { + path: '/status', + op: 'replace', + value: status + } + ]; + + beforeEach(() => { + scheduler = getTestScheduler(); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: jasmine.createSpy('getByHref'), + getByUUID: jasmine.createSpy('getByUUID') + }); + + responseCacheEntryB = new RequestEntry(); + responseCacheEntryB.request = { href: 'https://rest.api/' } as any; + responseCacheEntryB.response = new RestResponse(true, 201, 'Created'); + + responseCacheEntryC = new RequestEntry(); + responseCacheEntryC.request = { href: 'https://rest.api/' } as any; + responseCacheEntryC.response = new RestResponse(true, 204, 'No Content'); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: cold('(a)', { + a: brokerEventObjectRD + }), + buildList: cold('(a)', { + a: paginatedListRD + }), + buildFromRequestUUID: jasmine.createSpy('buildFromRequestUUID') + }); + + objectCache = {} as ObjectCacheService; + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a|', { a: endpointURL }) + }); + + notificationsService = {} as NotificationsService; + http = {} as HttpClient; + comparator = {} as any; + + service = new OpenaireBrokerEventRestService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + http, + comparator + ); + + serviceASAny = service; + + spyOn(serviceASAny.dataService, 'searchBy').and.callThrough(); + spyOn(serviceASAny.dataService, 'findById').and.callThrough(); + spyOn(serviceASAny.dataService, 'patch').and.callThrough(); + spyOn(serviceASAny.dataService, 'postOnRelated').and.callThrough(); + spyOn(serviceASAny.dataService, 'deleteOnRelated').and.callThrough(); + }); + + describe('getEventsByTopic', () => { + beforeEach(() => { + serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + }); + + it('should proxy the call to dataservice.searchBy', () => { + const options: FindListOptions = { + searchParams: [ + { + fieldName: 'topic', + fieldValue: topic + } + ] + }; + service.getEventsByTopic(topic); + expect(serviceASAny.dataService.searchBy).toHaveBeenCalledWith('findByTopic', options, true, true); + }); + + it('should return a RemoteData> for the object with the given Topic', () => { + const result = service.getEventsByTopic(topic); + const expected = cold('(a)', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getEvent', () => { + beforeEach(() => { + serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + }); + + it('should proxy the call to dataservice.findById', () => { + service.getEvent(openaireBrokerEventObjectMissingPid.id).subscribe( + (res) => { + expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(openaireBrokerEventObjectMissingPid.id, true, true); + } + ); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getEvent(openaireBrokerEventObjectMissingPid.id); + const expected = cold('(a)', { + a: brokerEventObjectRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('patchEvent', () => { + beforeEach(() => { + serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + }); + + it('should proxy the call to dataservice.patch', () => { + service.patchEvent(status, openaireBrokerEventObjectMissingPid).subscribe( + (res) => { + expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(openaireBrokerEventObjectMissingPid, operation); + } + ); + }); + + it('should return a RemoteData with HTTP 200', () => { + const result = service.patchEvent(status, openaireBrokerEventObjectMissingPid); + const expected = cold('(a|)', { + a: createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingPid) + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('boundProject', () => { + beforeEach(() => { + serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntryB)); + serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntryB)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectMissingProjectRD)); + }); + + it('should proxy the call to dataservice.postOnRelated', () => { + service.boundProject(openaireBrokerEventObjectMissingProjectFound.id, requestUUID).subscribe( + (res) => { + expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(openaireBrokerEventObjectMissingProjectFound.id, requestUUID); + } + ); + }); + + it('should return a RestResponse with HTTP 201', () => { + const result = service.boundProject(openaireBrokerEventObjectMissingProjectFound.id, requestUUID); + const expected = cold('(a|)', { + a: createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingProjectFound) + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('removeProject', () => { + beforeEach(() => { + serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntryC)); + serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntryC)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(createSuccessfulRemoteDataObject({}))); + }); + + it('should proxy the call to dataservice.deleteOnRelated', () => { + service.removeProject(openaireBrokerEventObjectMissingProjectFound.id).subscribe( + (res) => { + expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(openaireBrokerEventObjectMissingProjectFound.id); + } + ); + }); + + it('should return a RestResponse with HTTP 204', () => { + const result = service.removeProject(openaireBrokerEventObjectMissingProjectFound.id); + const expected = cold('(a|)', { + a: createSuccessfulRemoteDataObject({}) + }); + expect(result).toBeObservable(expected); + }); + }); + +}); diff --git a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts b/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts new file mode 100644 index 0000000000..6e944c8038 --- /dev/null +++ b/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts @@ -0,0 +1,185 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Store } from '@ngrx/store'; + +import { Observable } from 'rxjs'; + +import { CoreState } from '../../../core.reducers'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { RestResponse } from '../../../cache/response.models'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { dataService } from '../../../cache/builders/build-decorators'; +import { RequestService } from '../../../data/request.service'; +import { FindListOptions } from '../../../data/request.models'; +import { DataService } from '../../../data/data.service'; +import { ChangeAnalyzer } from '../../../data/change-analyzer'; +import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { RemoteData } from '../../../data/remote-data'; +import { OpenaireBrokerEventObject } from '../models/openaire-broker-event.model'; +import { OPENAIRE_BROKER_EVENT_OBJECT } from '../models/openaire-broker-event-object.resource-type'; +import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../../../data/paginated-list.model'; +import { ReplaceOperation } from 'fast-json-patch'; +import { NoContent } from '../../../shared/NoContent.model'; + +/* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ +class DataServiceImpl extends DataService { + /** + * The REST endpoint. + */ + protected linkPath = 'nbevents'; + + /** + * Initialize service variables + * @param {RequestService} requestService + * @param {RemoteDataBuildService} rdbService + * @param {Store} store + * @param {ObjectCacheService} objectCache + * @param {HALEndpointService} halService + * @param {NotificationsService} notificationsService + * @param {HttpClient} http + * @param {ChangeAnalyzer} comparator + */ + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } +} + +/** + * The service handling all OpenAIRE Broker topic REST requests. + */ +@Injectable() +@dataService(OPENAIRE_BROKER_EVENT_OBJECT) +export class OpenaireBrokerEventRestService { + /** + * A private DataService implementation to delegate specific methods to. + */ + private dataService: DataServiceImpl; + + /** + * Initialize service variables + * @param {RequestService} requestService + * @param {RemoteDataBuildService} rdbService + * @param {ObjectCacheService} objectCache + * @param {HALEndpointService} halService + * @param {NotificationsService} notificationsService + * @param {HttpClient} http + * @param {DefaultChangeAnalyzer} comparator + */ + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: DefaultChangeAnalyzer) { + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + } + + /** + * Return the list of OpenAIRE Broker events by topic. + * + * @param topic + * The OpenAIRE Broker topic + * @param options + * Find list options object. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable>> + * The list of OpenAIRE Broker events. + */ + public getEventsByTopic(topic: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + options.searchParams = [ + { + fieldName: 'topic', + fieldValue: topic + } + ]; + return this.dataService.searchBy('findByTopic', options, true, true, ...linksToFollow); + } + + /** + * Clear findByTopic requests from cache + */ + public clearFindByTopicRequests() { + this.requestService.removeByHrefSubstring('findByTopic'); + } + + /** + * Return a single OpenAIRE Broker event. + * + * @param id + * The OpenAIRE Broker event id + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return Observable> + * The OpenAIRE Broker event. + */ + public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.dataService.findById(id, true, true, ...linksToFollow); + } + + /** + * Save the new status of an OpenAIRE Broker event. + * + * @param status + * The new status + * @param dso OpenaireBrokerEventObject + * The event item + * @param reason + * The optional reason (not used for now; for future implementation) + * @return Observable + * The REST response. + */ + public patchEvent(status, dso, reason?: string): Observable> { + const operation: ReplaceOperation[] = [ + { + path: '/status', + op: 'replace', + value: status + } + ]; + return this.dataService.patch(dso, operation); + } + + /** + * Bound a project to an OpenAIRE Broker event publication. + * + * @param itemId + * The Id of the OpenAIRE Broker event + * @param projectId + * The project Id to bound + * @return Observable + * The REST response. + */ + public boundProject(itemId: string, projectId: string): Observable> { + return this.dataService.postOnRelated(itemId, projectId); + } + + /** + * Remove a project from an OpenAIRE Broker event publication. + * + * @param itemId + * The Id of the OpenAIRE Broker event + * @return Observable + * The REST response. + */ + public removeProject(itemId: string): Observable> { + return this.dataService.deleteOnRelated(itemId); + } +} diff --git a/src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts b/src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts new file mode 100644 index 0000000000..c0be0071eb --- /dev/null +++ b/src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for the OpenAIRE Broker event + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const OPENAIRE_BROKER_EVENT_OBJECT = new ResourceType('nbevent'); diff --git a/src/app/core/openaire/broker/models/openaire-broker-event.model.ts b/src/app/core/openaire/broker/models/openaire-broker-event.model.ts new file mode 100644 index 0000000000..40c65412f5 --- /dev/null +++ b/src/app/core/openaire/broker/models/openaire-broker-event.model.ts @@ -0,0 +1,157 @@ +import { Observable } from 'rxjs'; +import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { OPENAIRE_BROKER_EVENT_OBJECT } from './openaire-broker-event-object.resource-type'; +import { excludeFromEquals } from '../../../utilities/equals.decorators'; +import { ResourceType } from '../../../shared/resource-type'; +import { HALLink } from '../../../shared/hal-link.model'; +import { Item } from '../../../shared/item.model'; +import { ITEM } from '../../../shared/item.resource-type'; +import { link, typedObject } from '../../../cache/builders/build-decorators'; +import { RemoteData } from '../../../data/remote-data'; + +/** + * The interface representing the OpenAIRE Broker event message + */ +export interface OpenaireBrokerEventMessageObject { + /** + * The type of 'value' + */ + type: string; + + /** + * The value suggested by OpenAIRE + */ + value: string; + + /** + * The abstract suggested by OpenAIRE + */ + abstract: string; + + /** + * The project acronym suggested by OpenAIRE + */ + acronym: string; + + /** + * The project code suggested by OpenAIRE + */ + code: string; + + /** + * The project funder suggested by OpenAIRE + */ + funder: string; + + /** + * The project program suggested by OpenAIRE + */ + fundingProgram?: string; + + /** + * The project jurisdiction suggested by OpenAIRE + */ + jurisdiction: string; + + /** + * The project title suggested by OpenAIRE + */ + title: string; + + /** + * The OpenAIRE ID. + */ + openaireId: string; + +} + +/** + * The interface representing the OpenAIRE Broker event model + */ +@typedObject +export class OpenaireBrokerEventObject implements CacheableObject { + /** + * A string representing the kind of object, e.g. community, item, … + */ + static type = OPENAIRE_BROKER_EVENT_OBJECT; + + /** + * The OpenAIRE Broker event uuid inside DSpace + */ + @autoserialize + id: string; + + /** + * The universally unique identifier of this OpenAIRE Broker event + */ + @autoserializeAs(String, 'id') + uuid: string; + + /** + * The OpenAIRE Broker event original id (ex.: the source archive OAI-PMH identifier) + */ + @autoserialize + originalId: string; + + /** + * The title of the article to which the suggestion refers + */ + @autoserialize + title: string; + + /** + * Reliability of the suggestion (of the data inside 'message') + */ + @autoserialize + trust: number; + + /** + * The timestamp OpenAIRE Broker event was saved in DSpace + */ + @autoserialize + eventDate: string; + + /** + * The OpenAIRE Broker event status (ACCEPTED, REJECTED, DISCARDED, PENDING) + */ + @autoserialize + status: string; + + /** + * The suggestion data. Data may vary depending on the topic + */ + @autoserialize + message: OpenaireBrokerEventMessageObject; + + /** + * The type of this ConfigObject + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + /** + * The links to all related resources returned by the rest api. + */ + @deserialize + _links: { + self: HALLink, + target: HALLink, + related: HALLink + }; + + /** + * The related publication DSpace item + * Will be undefined unless the {@item HALLink} has been resolved. + */ + @link(ITEM) + target?: Observable>; + + /** + * The related project for this Event + * Will be undefined unless the {@related HALLink} has been resolved. + */ + @link(ITEM) + related?: Observable>; +} diff --git a/src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts b/src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts new file mode 100644 index 0000000000..58ceb4e671 --- /dev/null +++ b/src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for the OpenAIRE Broker topic + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const OPENAIRE_BROKER_TOPIC_OBJECT = new ResourceType('nbtopic'); diff --git a/src/app/core/openaire/broker/models/openaire-broker-topic.model.ts b/src/app/core/openaire/broker/models/openaire-broker-topic.model.ts new file mode 100644 index 0000000000..3f286e5fea --- /dev/null +++ b/src/app/core/openaire/broker/models/openaire-broker-topic.model.ts @@ -0,0 +1,58 @@ +import { autoserialize, deserialize } from 'cerialize'; + +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { OPENAIRE_BROKER_TOPIC_OBJECT } from './openaire-broker-topic-object.resource-type'; +import { excludeFromEquals } from '../../../utilities/equals.decorators'; +import { ResourceType } from '../../../shared/resource-type'; +import { HALLink } from '../../../shared/hal-link.model'; +import { typedObject } from '../../../cache/builders/build-decorators'; + +/** + * The interface representing the OpenAIRE Broker topic model + */ +@typedObject +export class OpenaireBrokerTopicObject implements CacheableObject { + /** + * A string representing the kind of object, e.g. community, item, … + */ + static type = OPENAIRE_BROKER_TOPIC_OBJECT; + + /** + * The OpenAIRE Broker topic id + */ + @autoserialize + id: string; + + /** + * The OpenAIRE Broker topic name to display + */ + @autoserialize + name: string; + + /** + * The date of the last udate from OpenAIRE + */ + @autoserialize + lastEvent: string; + + /** + * The total number of suggestions provided by OpenAIRE for this topic + */ + @autoserialize + totalEvents: number; + + /** + * The type of this ConfigObject + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + /** + * The links to all related resources returned by the rest api. + */ + @deserialize + _links: { + self: HALLink, + }; +} diff --git a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts b/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts new file mode 100644 index 0000000000..87aa0b42f0 --- /dev/null +++ b/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts @@ -0,0 +1,127 @@ +import { HttpClient } from '@angular/common/http'; + +import { TestScheduler } from 'rxjs/testing'; +import { of as observableOf } from 'rxjs'; +import { cold, getTestScheduler } from 'jasmine-marbles'; + +import { RequestService } from '../../../data/request.service'; +import { buildPaginatedList } from '../../../data/paginated-list.model'; +import { RequestEntry } from '../../../data/request.reducer'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { RestResponse } from '../../../cache/response.models'; +import { PageInfo } from '../../../shared/page-info.model'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; +import { OpenaireBrokerTopicRestService } from './openaire-broker-topic-rest.service'; +import { + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMorePid +} from '../../../../shared/mocks/openaire.mock'; + +describe('OpenaireBrokerTopicRestService', () => { + let scheduler: TestScheduler; + let service: OpenaireBrokerTopicRestService; + let responseCacheEntry: RequestEntry; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparator: any; + + const endpointURL = 'https://rest.api/rest/api/integration/nbtopics'; + const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; + + const pageInfo = new PageInfo(); + const array = [ openaireBrokerTopicObjectMorePid, openaireBrokerTopicObjectMoreAbstract ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const brokerTopicObjectRD = createSuccessfulRemoteDataObject(openaireBrokerTopicObjectMorePid); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + + beforeEach(() => { + scheduler = getTestScheduler(); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: cold('(a)', { + a: brokerTopicObjectRD + }), + buildList: cold('(a)', { + a: paginatedListRD + }), + }); + + objectCache = {} as ObjectCacheService; + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a|', { a: endpointURL }) + }); + + notificationsService = {} as NotificationsService; + http = {} as HttpClient; + comparator = {} as any; + + service = new OpenaireBrokerTopicRestService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + http, + comparator + ); + + spyOn((service as any).dataService, 'findAllByHref').and.callThrough(); + spyOn((service as any).dataService, 'findByHref').and.callThrough(); + }); + + describe('getTopics', () => { + it('should proxy the call to dataservice.findAllByHref', (done) => { + service.getTopics().subscribe( + (res) => { + expect((service as any).dataService.findAllByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + } + ); + done(); + }); + + it('should return a RemoteData> for the object with the given URL', () => { + const result = service.getTopics(); + const expected = cold('(a)', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getTopic', () => { + it('should proxy the call to dataservice.findByHref', (done) => { + service.getTopic(openaireBrokerTopicObjectMorePid.id).subscribe( + (res) => { + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + openaireBrokerTopicObjectMorePid.id, true, true); + } + ); + done(); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getTopic(openaireBrokerTopicObjectMorePid.id); + const expected = cold('(a)', { + a: brokerTopicObjectRD + }); + expect(result).toBeObservable(expected); + }); + }); + +}); diff --git a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts b/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts new file mode 100644 index 0000000000..3fe3917485 --- /dev/null +++ b/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts @@ -0,0 +1,133 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Store } from '@ngrx/store'; + +import { Observable } from 'rxjs'; +import { mergeMap, take } from 'rxjs/operators'; + +import { CoreState } from '../../../core.reducers'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { dataService } from '../../../cache/builders/build-decorators'; +import { RequestService } from '../../../data/request.service'; +import { FindListOptions } from '../../../data/request.models'; +import { DataService } from '../../../data/data.service'; +import { ChangeAnalyzer } from '../../../data/change-analyzer'; +import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { RemoteData } from '../../../data/remote-data'; +import { OpenaireBrokerTopicObject } from '../models/openaire-broker-topic.model'; +import { OPENAIRE_BROKER_TOPIC_OBJECT } from '../models/openaire-broker-topic-object.resource-type'; +import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../../../data/paginated-list.model'; + +/* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ +class DataServiceImpl extends DataService { + /** + * The REST endpoint. + */ + protected linkPath = 'nbtopics'; + + /** + * Initialize service variables + * @param {RequestService} requestService + * @param {RemoteDataBuildService} rdbService + * @param {Store} store + * @param {ObjectCacheService} objectCache + * @param {HALEndpointService} halService + * @param {NotificationsService} notificationsService + * @param {HttpClient} http + * @param {ChangeAnalyzer} comparator + */ + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } +} + +/** + * The service handling all OpenAIRE Broker topic REST requests. + */ +@Injectable() +@dataService(OPENAIRE_BROKER_TOPIC_OBJECT) +export class OpenaireBrokerTopicRestService { + /** + * A private DataService implementation to delegate specific methods to. + */ + private dataService: DataServiceImpl; + + /** + * Initialize service variables + * @param {RequestService} requestService + * @param {RemoteDataBuildService} rdbService + * @param {ObjectCacheService} objectCache + * @param {HALEndpointService} halService + * @param {NotificationsService} notificationsService + * @param {HttpClient} http + * @param {DefaultChangeAnalyzer} comparator + */ + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: DefaultChangeAnalyzer) { + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + } + + /** + * Return the list of OpenAIRE Broker topics. + * + * @param options + * Find list options object. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable>> + * The list of OpenAIRE Broker topics. + */ + public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( + take(1), + mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), + ); + } + + /** + * Clear FindAll topics requests from cache + */ + public clearFindAllTopicsRequests() { + this.requestService.setStaleByHrefSubstring('nbtopics'); + } + + /** + * Return a single OpenAIRE Broker topic. + * + * @param id + * The OpenAIRE Broker topic id + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable> + * The OpenAIRE Broker topic. + */ + public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + const options = {}; + return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( + take(1), + mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) + ); + } +} diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.html b/src/app/openaire/broker/events/openaire-broker-events.component.html new file mode 100644 index 0000000000..05d7722291 --- /dev/null +++ b/src/app/openaire/broker/events/openaire-broker-events.component.html @@ -0,0 +1,207 @@ +
+
+
+

{{'openaire.events.title'| translate}}

+

{{'openaire.broker.events.description'| translate}}

+

+ + + {{'openaire.broker.events.back' | translate}} + +

+
+
+
+
+

+ {{'openaire.broker.events.topic' | translate}} {{this.showTopic}} +

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
{{'openaire.broker.event.table.trust' | translate}}{{'openaire.broker.event.table.publication' | translate}}{{'openaire.broker.event.table.details' | translate}}{{'openaire.broker.event.table.project-details' | translate}}{{'openaire.broker.event.table.actions' | translate}}
{{eventElement?.event?.trust}} + {{eventElement.title}} + {{eventElement.title}} + +

{{'openaire.broker.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

+

{{'openaire.broker.event.table.pidvalue' | translate}}
+ + {{eventElement.event.message.value}} + + {{eventElement.event.message.value}} +

+
+

{{'openaire.broker.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

+
+

+ {{'openaire.broker.event.table.abstract' | translate}}
+ {{eventElement.event.message.abstract}} +

+ +
+

+ {{'openaire.broker.event.table.suggestedProject' | translate}} +

+

+ {{'openaire.broker.event.table.project' | translate}}
+ {{eventElement.event.message.title}} +

+

+ {{'openaire.broker.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
+ {{'openaire.broker.event.table.code' | translate}} {{eventElement.event.message.code}}
+ {{'openaire.broker.event.table.funder' | translate}} {{eventElement.event.message.funder}}
+ {{'openaire.broker.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
+ {{'openaire.broker.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}} +

+
+
+ {{(eventElement.hasProject ? 'openaire.broker.event.project.found' : 'openaire.broker.event.project.notFound') | translate}} + {{eventElement.handle}} +
+ + +
+
+
+
+ + + + +
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.spec.ts b/src/app/openaire/broker/events/openaire-broker-events.component.spec.ts new file mode 100644 index 0000000000..267f6a8242 --- /dev/null +++ b/src/app/openaire/broker/events/openaire-broker-events.component.spec.ts @@ -0,0 +1,332 @@ +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { of as observableOf } from 'rxjs'; +import { OpenaireBrokerEventRestService } from '../../../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { OpenaireBrokerEventsComponent } from './openaire-broker-events.component'; +import { + getMockOpenaireBrokerEventRestService, + ItemMockPid10, + ItemMockPid8, + ItemMockPid9, + openaireBrokerEventObjectMissingProjectFound, + openaireBrokerEventObjectMissingProjectNotFound, + OpenaireMockDspaceObject +} from '../../../shared/mocks/openaire.mock'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { OpenaireBrokerEventObject } from '../../../core/openaire/broker/models/openaire-broker-event.model'; +import { OpenaireBrokerEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { followLink } from '../../../shared/utils/follow-link-config.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { + createNoContentRemoteDataObject$, + createSuccessfulRemoteDataObject, + createSuccessfulRemoteDataObject$ +} from '../../../shared/remote-data.utils'; +import { FindListOptions } from '../../../core/data/request.models'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; + +describe('OpenaireBrokerEventsComponent test suite', () => { + let fixture: ComponentFixture; + let comp: OpenaireBrokerEventsComponent; + let compAsAny: any; + let scheduler: TestScheduler; + + const modalStub = { + open: () => ( {result: new Promise((res, rej) => 'do')} ), + close: () => null, + dismiss: () => null + }; + const openaireBrokerEventRestServiceStub: any = getMockOpenaireBrokerEventRestService(); + const activatedRouteParams = { + openaireBrokerEventsParams: { + currentPage: 0, + pageSize: 10 + } + }; + const activatedRouteParamsMap = { + id: 'ENRICH!MISSING!PROJECT' + }; + + const events: OpenaireBrokerEventObject[] = [ + openaireBrokerEventObjectMissingProjectFound, + openaireBrokerEventObjectMissingProjectNotFound + ]; + const paginationService = new PaginationServiceStub(); + + function getOpenAireBrokerEventData1(): OpenaireBrokerEventData { + return { + event: openaireBrokerEventObjectMissingProjectFound, + id: openaireBrokerEventObjectMissingProjectFound.id, + title: openaireBrokerEventObjectMissingProjectFound.title, + hasProject: true, + projectTitle: openaireBrokerEventObjectMissingProjectFound.message.title, + projectId: ItemMockPid10.id, + handle: ItemMockPid10.handle, + reason: null, + isRunning: false, + target: ItemMockPid8 + }; + } + + function getOpenAireBrokerEventData2(): OpenaireBrokerEventData { + return { + event: openaireBrokerEventObjectMissingProjectNotFound, + id: openaireBrokerEventObjectMissingProjectNotFound.id, + title: openaireBrokerEventObjectMissingProjectNotFound.title, + hasProject: false, + projectTitle: null, + projectId: null, + handle: null, + reason: null, + isRunning: false, + target: ItemMockPid9 + }; + } + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot(), + ], + declarations: [ + OpenaireBrokerEventsComponent, + TestComponent, + ], + providers: [ + { provide: ActivatedRoute, useValue: new ActivatedRouteStub(activatedRouteParamsMap, activatedRouteParams) }, + { provide: OpenaireBrokerEventRestService, useValue: openaireBrokerEventRestServiceStub }, + { provide: NgbModal, useValue: modalStub }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: TranslateService, useValue: getMockTranslateService() }, + { provide: PaginationService, useValue: paginationService }, + OpenaireBrokerEventsComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + scheduler = getTestScheduler(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create OpenaireBrokerEventsComponent', inject([OpenaireBrokerEventsComponent], (app: OpenaireBrokerEventsComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('Main tests', () => { + beforeEach(() => { + fixture = TestBed.createComponent(OpenaireBrokerEventsComponent); + comp = fixture.componentInstance; + compAsAny = comp; + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + describe('setEventUpdated', () => { + it('should update events', () => { + const expected = [ + getOpenAireBrokerEventData1(), + getOpenAireBrokerEventData2() + ]; + scheduler.schedule(() => { + compAsAny.setEventUpdated(events); + }); + scheduler.flush(); + + expect(comp.eventsUpdated$.value).toEqual(expected); + }); + }); + + describe('modalChoice', () => { + beforeEach(() => { + spyOn(comp, 'executeAction'); + spyOn(comp, 'openModal'); + }); + + it('should call executeAction if a project is present', () => { + const action = 'ACCEPTED'; + comp.modalChoice(action, getOpenAireBrokerEventData1(), modalStub); + expect(comp.executeAction).toHaveBeenCalledWith(action, getOpenAireBrokerEventData1()); + }); + + it('should call openModal if a project is not present', () => { + const action = 'ACCEPTED'; + comp.modalChoice(action, getOpenAireBrokerEventData2(), modalStub); + expect(comp.openModal).toHaveBeenCalledWith(action, getOpenAireBrokerEventData2(), modalStub); + }); + }); + + describe('openModal', () => { + it('should call modalService.open', () => { + const action = 'ACCEPTED'; + comp.selectedReason = null; + spyOn(compAsAny.modalService, 'open').and.returnValue({ result: new Promise((res, rej) => 'do' ) }); + spyOn(comp, 'executeAction'); + + comp.openModal(action, getOpenAireBrokerEventData1(), modalStub); + expect(compAsAny.modalService.open).toHaveBeenCalled(); + }); + }); + + describe('openModalLookup', () => { + it('should call modalService.open', () => { + spyOn(comp, 'boundProject'); + spyOn(compAsAny.modalService, 'open').and.returnValue( + { + componentInstance: { + externalSourceEntry: null, + label: null, + importedObject: observableOf({ + indexableObject: OpenaireMockDspaceObject + }) + } + } + ); + scheduler.schedule(() => { + comp.openModalLookup(getOpenAireBrokerEventData1()); + }); + scheduler.flush(); + + expect(compAsAny.modalService.open).toHaveBeenCalled(); + expect(compAsAny.boundProject).toHaveBeenCalled(); + }); + }); + + describe('executeAction', () => { + it('should call getOpenaireBrokerEvents on 200 response from REST', () => { + const action = 'ACCEPTED'; + spyOn(compAsAny, 'getOpenaireBrokerEvents'); + openaireBrokerEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); + + scheduler.schedule(() => { + comp.executeAction(action, getOpenAireBrokerEventData1()); + }); + scheduler.flush(); + + expect(compAsAny.getOpenaireBrokerEvents).toHaveBeenCalled(); + }); + }); + + describe('boundProject', () => { + it('should populate the project data inside "eventData"', () => { + const eventData = getOpenAireBrokerEventData2(); + const projectId = 'UUID-23943-34u43-38344'; + const projectName = 'Test Project'; + const projectHandle = '1000/1000'; + openaireBrokerEventRestServiceStub.boundProject.and.returnValue(createSuccessfulRemoteDataObject$({})); + + scheduler.schedule(() => { + comp.boundProject(eventData, projectId, projectName, projectHandle); + }); + scheduler.flush(); + + expect(eventData.hasProject).toEqual(true); + expect(eventData.projectId).toEqual(projectId); + expect(eventData.projectTitle).toEqual(projectName); + expect(eventData.handle).toEqual(projectHandle); + }); + }); + + describe('removeProject', () => { + it('should remove the project data inside "eventData"', () => { + const eventData = getOpenAireBrokerEventData1(); + openaireBrokerEventRestServiceStub.removeProject.and.returnValue(createNoContentRemoteDataObject$()); + + scheduler.schedule(() => { + comp.removeProject(eventData); + }); + scheduler.flush(); + + expect(eventData.hasProject).toEqual(false); + expect(eventData.projectId).toBeNull(); + expect(eventData.projectTitle).toBeNull(); + expect(eventData.handle).toBeNull(); + }); + }); + + describe('getOpenaireBrokerEvents', () => { + it('should call the "openaireBrokerEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { + comp.paginationConfig = new PaginationComponentOptions(); + comp.paginationConfig.currentPage = 1; + comp.paginationConfig.pageSize = 20; + comp.paginationSortConfig = new SortOptions('trust', SortDirection.DESC); + comp.topic = activatedRouteParamsMap.id; + const options: FindListOptions = Object.assign(new FindListOptions(), { + currentPage: comp.paginationConfig.currentPage, + elementsPerPage: comp.paginationConfig.pageSize + }); + + const pageInfo = new PageInfo({ + elementsPerPage: comp.paginationConfig.pageSize, + totalElements: 0, + totalPages: 1, + currentPage: comp.paginationConfig.currentPage + }); + const array = [ + openaireBrokerEventObjectMissingProjectFound, + openaireBrokerEventObjectMissingProjectNotFound, + ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + openaireBrokerEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); + spyOn(compAsAny, 'setEventUpdated'); + + scheduler.schedule(() => { + compAsAny.getOpenaireBrokerEvents(); + }); + scheduler.flush(); + + expect(compAsAny.openaireBrokerEventRestService.getEventsByTopic).toHaveBeenCalledWith( + activatedRouteParamsMap.id, + options, + followLink('target'),followLink('related') + ); + expect(compAsAny.setEventUpdated).toHaveBeenCalled(); + }); + }); + + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.ts b/src/app/openaire/broker/events/openaire-broker-events.component.ts new file mode 100644 index 0000000000..14ad175e80 --- /dev/null +++ b/src/app/openaire/broker/events/openaire-broker-events.component.ts @@ -0,0 +1,464 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { BehaviorSubject, from, Observable, of as observableOf, Subscription } from 'rxjs'; +import { distinctUntilChanged, map, mergeMap, scan, switchMap, take } from 'rxjs/operators'; + +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { FindListOptions } from '../../../core/data/request.models'; +import { + OpenaireBrokerEventMessageObject, + OpenaireBrokerEventObject +} from '../../../core/openaire/broker/models/openaire-broker-event.model'; +import { OpenaireBrokerEventRestService } from '../../../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { Metadata } from '../../../core/shared/metadata.utils'; +import { followLink } from '../../../shared/utils/follow-link-config.model'; +import { hasValue } from '../../../shared/empty.util'; +import { ItemSearchResult } from '../../../shared/object-collection/shared/item-search-result.model'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { + OpenaireBrokerEventData, + ProjectEntryImportModalComponent +} from '../project-entry-import-modal/project-entry-import-modal.component'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { combineLatest } from 'rxjs/internal/observable/combineLatest'; +import { Item } from '../../../core/shared/item.model'; + +/** + * Component to display the OpenAIRE Broker event list. + */ +@Component({ + selector: 'ds-openaire-broker-events', + templateUrl: './openaire-broker-events.component.html', + styleUrls: ['./openaire-broker-events.scomponent.scss'], +}) +export class OpenaireBrokerEventsComponent implements OnInit { + /** + * The pagination system configuration for HTML listing. + * @type {PaginationComponentOptions} + */ + public paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'bep', + currentPage: 1, + pageSize: 10, + pageSizeOptions: [5, 10, 20, 40, 60] + }); + /** + * The OpenAIRE Broker event list sort options. + * @type {SortOptions} + */ + public paginationSortConfig: SortOptions = new SortOptions('trust', SortDirection.DESC); + /** + * Array to save the presence of a project inside an OpenAIRE Broker event. + * @type {OpenaireBrokerEventData[]>} + */ + public eventsUpdated$: BehaviorSubject = new BehaviorSubject([]); + /** + * The total number of OpenAIRE Broker events. + * @type {Observable} + */ + public totalElements$: Observable; + /** + * The topic of the OpenAIRE Broker events; suitable for displaying. + * @type {string} + */ + public showTopic: string; + /** + * The topic of the OpenAIRE Broker events; suitable for HTTP calls. + * @type {string} + */ + public topic: string; + /** + * The rejected/ignore reason. + * @type {string} + */ + public selectedReason: string; + /** + * Contains the information about the loading status of the page. + * @type {Observable} + */ + public isEventPageLoading: BehaviorSubject = new BehaviorSubject(false); + /** + * Contains the information about the loading status of the events inside the pagination component. + * @type {Observable} + */ + public isEventLoading: BehaviorSubject = new BehaviorSubject(false); + /** + * The modal reference. + * @type {any} + */ + public modalRef: any; + /** + * Used to store the status of the 'Show more' button of the abstracts. + * @type {boolean} + */ + public showMore = false; + /** + * The FindListOptions object + */ + protected defaultConfig: FindListOptions = Object.assign(new FindListOptions(), {sort: this.paginationSortConfig}); + /** + * Array to track all the component subscriptions. Useful to unsubscribe them with 'onDestroy'. + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * Initialize the component variables. + * @param {ActivatedRoute} activatedRoute + * @param {NgbModal} modalService + * @param {NotificationsService} notificationsService + * @param {OpenaireBrokerEventRestService} openaireBrokerEventRestService + * @param {PaginationService} paginationService + * @param {TranslateService} translateService + */ + constructor( + private activatedRoute: ActivatedRoute, + private modalService: NgbModal, + private notificationsService: NotificationsService, + private openaireBrokerEventRestService: OpenaireBrokerEventRestService, + private paginationService: PaginationService, + private translateService: TranslateService + ) { + } + + /** + * Component initialization. + */ + ngOnInit(): void { + this.isEventPageLoading.next(true); + + this.activatedRoute.paramMap.pipe( + map((params) => params.get('id')), + take(1) + ).subscribe((id: string) => { + const regEx = /!/g; + this.showTopic = id.replace(regEx, '/'); + this.topic = id; + this.isEventPageLoading.next(false); + this.getOpenaireBrokerEvents(); + }); + } + + /** + * Check if table have a detail column + */ + public hasDetailColumn(): boolean { + return (this.showTopic.indexOf('/PROJECT') !== -1 || + this.showTopic.indexOf('/PID') !== -1 || + this.showTopic.indexOf('/SUBJECT') !== -1 || + this.showTopic.indexOf('/ABSTRACT') !== -1 + ); + } + + /** + * Open a modal or run the executeAction directly based on the presence of the project. + * + * @param {string} action + * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event data + * @param {any} content + * Reference to the modal + */ + public modalChoice(action: string, eventData: OpenaireBrokerEventData, content: any): void { + if (eventData.hasProject) { + this.executeAction(action, eventData); + } else { + this.openModal(action, eventData, content); + } + } + + /** + * Open the selected modal and performs the action if needed. + * + * @param {string} action + * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event data + * @param {any} content + * Reference to the modal + */ + public openModal(action: string, eventData: OpenaireBrokerEventData, content: any): void { + this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then( + (result) => { + if (result === 'do') { + eventData.reason = this.selectedReason; + this.executeAction(action, eventData); + } + this.selectedReason = null; + }, + (_reason) => { + this.selectedReason = null; + } + ); + } + + /** + * Open a modal where the user can select the project. + * + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event item data + */ + public openModalLookup(eventData: OpenaireBrokerEventData): void { + this.modalRef = this.modalService.open(ProjectEntryImportModalComponent, { + size: 'lg' + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = eventData; + modalComp.label = 'project'; + this.subs.push( + modalComp.importedObject.pipe(take(1)) + .subscribe((object: ItemSearchResult) => { + const projectTitle = Metadata.first(object.indexableObject.metadata, 'dc.title'); + this.boundProject( + eventData, + object.indexableObject.id, + projectTitle.value, + object.indexableObject.handle + ); + }) + ); + } + + /** + * Performs the choosen action calling the REST service. + * + * @param {string} action + * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event data + */ + public executeAction(action: string, eventData: OpenaireBrokerEventData): void { + eventData.isRunning = true; + this.subs.push( + this.openaireBrokerEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { + if (rd.isSuccess && rd.statusCode === 200) { + this.notificationsService.success( + this.translateService.instant('openaire.broker.event.action.saved') + ); + this.getOpenaireBrokerEvents(); + } else { + this.notificationsService.error( + this.translateService.instant('openaire.broker.event.action.error') + ); + } + eventData.isRunning = false; + }) + ); + } + + /** + * Bound a project to the publication described in the OpenAIRE Broker event calling the REST service. + * + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event item data + * @param {string} projectId + * the project Id to bound + * @param {string} projectTitle + * the project title + * @param {string} projectHandle + * the project handle + */ + public boundProject(eventData: OpenaireBrokerEventData, projectId: string, projectTitle: string, projectHandle: string): void { + eventData.isRunning = true; + this.subs.push( + this.openaireBrokerEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { + if (rd.isSuccess) { + this.notificationsService.success( + this.translateService.instant('openaire.broker.event.project.bounded') + ); + eventData.hasProject = true; + eventData.projectTitle = projectTitle; + eventData.handle = projectHandle; + eventData.projectId = projectId; + } else { + this.notificationsService.error( + this.translateService.instant('openaire.broker.event.project.error') + ); + } + eventData.isRunning = false; + }) + ); + } + + /** + * Remove the bounded project from the publication described in the OpenAIRE Broker event calling the REST service. + * + * @param {OpenaireBrokerEventData} eventData + * the OpenAIRE Broker event data + */ + public removeProject(eventData: OpenaireBrokerEventData): void { + eventData.isRunning = true; + this.subs.push( + this.openaireBrokerEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { + if (rd.isSuccess) { + this.notificationsService.success( + this.translateService.instant('openaire.broker.event.project.removed') + ); + eventData.hasProject = false; + eventData.projectTitle = null; + eventData.handle = null; + eventData.projectId = null; + } else { + this.notificationsService.error( + this.translateService.instant('openaire.broker.event.project.error') + ); + } + eventData.isRunning = false; + }) + ); + } + + /** + * Check if the event has a valid href. + * @param event + */ + public hasPIDHref(event: OpenaireBrokerEventMessageObject): boolean { + return this.getPIDHref(event) !== null; + } + + /** + * Get the event pid href. + * @param event + */ + public getPIDHref(event: OpenaireBrokerEventMessageObject): string { + return this.computePIDHref(event); + } + + + /** + * Dispatch the OpenAIRE Broker events retrival. + */ + public getOpenaireBrokerEvents(): void { + this.paginationService.getFindListOptions(this.paginationConfig.id, this.defaultConfig).pipe( + distinctUntilChanged(), + switchMap((options: FindListOptions) => this.openaireBrokerEventRestService.getEventsByTopic( + this.topic, + options, + followLink('target'), followLink('related') + )), + getFirstCompletedRemoteData(), + ).subscribe((rd: RemoteData>) => { + if (rd.hasSucceeded) { + this.isEventLoading.next(false); + this.totalElements$ = observableOf(rd.payload.totalElements); + this.setEventUpdated(rd.payload.page); + } else { + throw new Error('Can\'t retrieve OpenAIRE Broker events from the Broker events REST service'); + } + this.openaireBrokerEventRestService.clearFindByTopicRequests(); + }); + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + + /** + * Set the project status for the OpenAIRE Broker events. + * + * @param {OpenaireBrokerEventObject[]} events + * the OpenAIRE Broker event item + */ + protected setEventUpdated(events: OpenaireBrokerEventObject[]): void { + this.subs.push( + from(events).pipe( + mergeMap((event: OpenaireBrokerEventObject) => { + const related$ = event.related.pipe( + getFirstCompletedRemoteData(), + ); + const target$ = event.target.pipe( + getFirstCompletedRemoteData() + ); + return combineLatest([related$, target$]).pipe( + map(([relatedItemRD, targetItemRD]: [RemoteData, RemoteData]) => { + const data: OpenaireBrokerEventData = { + event: event, + id: event.id, + title: event.title, + hasProject: false, + projectTitle: null, + projectId: null, + handle: null, + reason: null, + isRunning: false, + target: (targetItemRD?.hasSucceeded) ? targetItemRD.payload : null, + }; + if (relatedItemRD?.hasSucceeded && relatedItemRD?.payload?.id) { + data.hasProject = true; + data.projectTitle = event.message.title; + data.projectId = relatedItemRD?.payload?.id; + data.handle = relatedItemRD?.payload?.handle; + } + return data; + }) + ); + }), + scan((acc: any, value: any) => [...acc, value], []), + take(events.length) + ).subscribe( + (eventsReduced) => { + this.eventsUpdated$.next(eventsReduced); + } + ) + ); + } + + protected computePIDHref(event: OpenaireBrokerEventMessageObject) { + const type = event.type.toLowerCase(); + const pid = event.value; + let prefix = null; + switch (type) { + case 'arxiv': { + prefix = 'https://arxiv.org/abs/'; + break; + } + case 'handle': { + prefix = 'https://hdl.handle.net/'; + break; + } + case 'urn': { + prefix = ''; + break; + } + case 'doi': { + prefix = 'https://doi.org/'; + break; + } + case 'pmc': { + prefix = 'https://www.ncbi.nlm.nih.gov/pmc/articles/'; + break; + } + case 'pmid': { + prefix = 'https://pubmed.ncbi.nlm.nih.gov/'; + break; + } + case 'ncid': { + prefix = 'https://ci.nii.ac.jp/ncid/'; + break; + } + default: { + break; + } + } + if (prefix === null) { + return null; + } + return prefix + pid; + } +} diff --git a/src/app/openaire/broker/events/openaire-broker-events.scomponent.scss b/src/app/openaire/broker/events/openaire-broker-events.scomponent.scss new file mode 100644 index 0000000000..b38da70f37 --- /dev/null +++ b/src/app/openaire/broker/events/openaire-broker-events.scomponent.scss @@ -0,0 +1,21 @@ +.button-rows { + min-width: 200px; +} + +.button-width { + width: 100%; +} + +.abstract-container { + height: 76px; + overflow: hidden; +} + +.text-ellipsis { + text-overflow: ellipsis; +} + +.show { + overflow: visible; + height: auto; +} diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html new file mode 100644 index 0000000000..1090fd22fc --- /dev/null +++ b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html @@ -0,0 +1,70 @@ + + + diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss new file mode 100644 index 0000000000..7db9839e38 --- /dev/null +++ b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss @@ -0,0 +1,3 @@ +.modal-footer { + justify-content: space-between; +} diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts new file mode 100644 index 0000000000..e19d0a7c86 --- /dev/null +++ b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts @@ -0,0 +1,210 @@ +import { CommonModule } from '@angular/common'; +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; +import { SearchService } from '../../../core/shared/search/search.service'; +import { Item } from '../../../core/shared/item.model'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { ImportType, ProjectEntryImportModalComponent } from './project-entry-import-modal.component'; +import { SelectableListService } from '../../../shared/object-list/selectable-list/selectable-list.service'; +import { getMockSearchService } from '../../../shared/mocks/search-service.mock'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { + ItemMockPid10, + openaireBrokerEventObjectMissingProjectFound, + OpenaireMockDspaceObject +} from '../../../shared/mocks/openaire.mock'; + +const eventData = { + event: openaireBrokerEventObjectMissingProjectFound, + id: openaireBrokerEventObjectMissingProjectFound.id, + title: openaireBrokerEventObjectMissingProjectFound.title, + hasProject: true, + projectTitle: openaireBrokerEventObjectMissingProjectFound.message.title, + projectId: ItemMockPid10.id, + handle: ItemMockPid10.handle, + reason: null, + isRunning: false +}; + +const searchString = 'Test project to search'; +const pagination = Object.assign( + new PaginationComponentOptions(), { + id: 'openaire-project-bound', + pageSize: 3 + } +); +const searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: 'funding', + query: searchString, + pagination: pagination + } +)); +const pageInfo = new PageInfo({ + elementsPerPage: 3, + totalElements: 1, + totalPages: 1, + currentPage: 1 +}); +const array = [ + OpenaireMockDspaceObject, +]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + +describe('ProjectEntryImportModalComponent test suite', () => { + let fixture: ComponentFixture; + let comp: ProjectEntryImportModalComponent; + let compAsAny: any; + + const modalStub = jasmine.createSpyObj('modal', ['close', 'dismiss']); + const uuid = '123e4567-e89b-12d3-a456-426614174003'; + const searchServiceStub: any = getMockSearchService(); + + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot(), + ], + declarations: [ + ProjectEntryImportModalComponent, + TestComponent, + ], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { provide: SearchService, useValue: searchServiceStub }, + { provide: SelectableListService, useValue: jasmine.createSpyObj('selectableListService', ['deselect', 'select', 'deselectAll']) }, + ProjectEntryImportModalComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + searchServiceStub.search.and.returnValue(observableOf(paginatedListRD)); + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create ProjectEntryImportModalComponent', inject([ProjectEntryImportModalComponent], (app: ProjectEntryImportModalComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('Main tests', () => { + beforeEach(() => { + fixture = TestBed.createComponent(ProjectEntryImportModalComponent); + comp = fixture.componentInstance; + compAsAny = comp; + + }); + + describe('close', () => { + it('should close the modal', () => { + comp.close(); + expect(modalStub.close).toHaveBeenCalled(); + }); + }); + + describe('search', () => { + it('should call SearchService.search', () => { + + (searchServiceStub as any).search.and.returnValue(observableOf(paginatedListRD)); + comp.pagination = pagination; + + comp.search(searchString); + expect(comp.searchService.search).toHaveBeenCalledWith(searchOptions); + }); + }); + + describe('bound', () => { + it('should call close, deselectAllLists and importedObject.emit', () => { + spyOn(comp, 'deselectAllLists'); + spyOn(comp, 'close'); + spyOn(comp.importedObject, 'emit'); + comp.selectedEntity = OpenaireMockDspaceObject; + comp.bound(); + + expect(comp.importedObject.emit).toHaveBeenCalled(); + expect(comp.deselectAllLists).toHaveBeenCalled(); + expect(comp.close).toHaveBeenCalled(); + }); + }); + + describe('selectEntity', () => { + const entity = Object.assign(new Item(), { uuid: uuid }); + beforeEach(() => { + comp.selectEntity(entity); + }); + + it('should set selected entity', () => { + expect(comp.selectedEntity).toBe(entity); + }); + + it('should set the import type to local entity', () => { + expect(comp.selectedImportType).toEqual(ImportType.LocalEntity); + }); + }); + + describe('deselectEntity', () => { + const entity = Object.assign(new Item(), { uuid: uuid }); + beforeEach(() => { + comp.selectedImportType = ImportType.LocalEntity; + comp.selectedEntity = entity; + comp.deselectEntity(); + }); + + it('should remove the selected entity', () => { + expect(comp.selectedEntity).toBeUndefined(); + }); + + it('should set the import type to none', () => { + expect(comp.selectedImportType).toEqual(ImportType.None); + }); + }); + + describe('deselectAllLists', () => { + it('should call SelectableListService.deselectAll', () => { + comp.deselectAllLists(); + expect(compAsAny.selectService.deselectAll).toHaveBeenCalledWith(comp.entityListId); + expect(compAsAny.selectService.deselectAll).toHaveBeenCalledWith(comp.authorityListId); + }); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + eventData = eventData; +} diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts new file mode 100644 index 0000000000..5d8cb20c6d --- /dev/null +++ b/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts @@ -0,0 +1,274 @@ +import { Component, EventEmitter, Input, OnInit } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Observable, of as observableOf, Subscription } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { SearchResult } from '../../../shared/search/models/search-result.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; +import { CollectionElementLinkType } from '../../../shared/object-collection/collection-element-link.type'; +import { Context } from '../../../core/shared/context.model'; +import { SelectableListService } from '../../../shared/object-list/selectable-list/selectable-list.service'; +import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SearchService } from '../../../core/shared/search/search.service'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { OpenaireBrokerEventObject } from '../../../core/openaire/broker/models/openaire-broker-event.model'; +import { hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { Item } from '../../../core/shared/item.model'; + +/** + * The possible types of import for the external entry + */ +export enum ImportType { + None = 'None', + LocalEntity = 'LocalEntity', + LocalAuthority = 'LocalAuthority', + NewEntity = 'NewEntity', + NewAuthority = 'NewAuthority' +} + +/** + * The data type passed from the parent page + */ +export interface OpenaireBrokerEventData { + /** + * The OpenAIRE Broker event + */ + event: OpenaireBrokerEventObject; + /** + * The OpenAIRE Broker event Id (uuid) + */ + id: string; + /** + * The publication title + */ + title: string; + /** + * Contains the boolean that indicates if a project is present + */ + hasProject: boolean; + /** + * The project title, if present + */ + projectTitle: string; + /** + * The project id (uuid), if present + */ + projectId: string; + /** + * The project handle, if present + */ + handle: string; + /** + * The reject/discard reason + */ + reason: string; + /** + * Contains the boolean that indicates if there is a running operation (REST call) + */ + isRunning: boolean; + /** + * The related publication DSpace item + */ + target?: Item; +} + +@Component({ + selector: 'ds-project-entry-import-modal', + styleUrls: ['./project-entry-import-modal.component.scss'], + templateUrl: './project-entry-import-modal.component.html' +}) +/** + * Component to display a modal window for linking a project to an OpenAIRE Broker event + * Shows information about the selected project and a selectable list. + */ +export class ProjectEntryImportModalComponent implements OnInit { + /** + * The external source entry + */ + @Input() externalSourceEntry: OpenaireBrokerEventData; + /** + * The number of results per page + */ + pageSize = 3; + /** + * The prefix for every i18n key within this modal + */ + labelPrefix = 'openaire.broker.event.modal.'; + /** + * The search configuration to retrieve project + */ + configuration = 'funding'; + /** + * The label to use for all messages (added to the end of relevant i18n keys) + */ + label: string; + /** + * The project title from the parent object + */ + projectTitle: string; + /** + * The search results + */ + localEntitiesRD$: Observable>>>; + /** + * Information about the data loading status + */ + isLoading$ = observableOf(true); + /** + * Search options to use for fetching projects + */ + searchOptions: PaginatedSearchOptions; + /** + * The context we're currently in (submission) + */ + context = Context.EntitySearchModalWithNameVariants; + /** + * List ID for selecting local entities + */ + entityListId = 'openaire-project-bound'; + /** + * List ID for selecting local authorities + */ + authorityListId = 'openaire-project-bound-authority'; + /** + * ImportType enum + */ + importType = ImportType; + /** + * The type of link to render in listable elements + */ + linkTypes = CollectionElementLinkType; + /** + * The type of import the user currently has selected + */ + selectedImportType = ImportType.None; + /** + * The selected local entity + */ + selectedEntity: ListableObject; + /** + * An project has been selected, send it to the parent component + */ + importedObject: EventEmitter = new EventEmitter(); + /** + * Pagination options + */ + pagination: PaginationComponentOptions; + /** + * Array to track all the component subscriptions. Useful to unsubscribe them with 'onDestroy'. + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * Initialize the component variables. + * @param {NgbActiveModal} modal + * @param {SearchService} searchService + * @param {SelectableListService} selectService + */ + constructor(public modal: NgbActiveModal, + public searchService: SearchService, + private selectService: SelectableListService) { } + + /** + * Component intitialization. + */ + public ngOnInit(): void { + this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'openaire-project-bound', pageSize: this.pageSize }); + this.projectTitle = (this.externalSourceEntry.projectTitle !== null) ? this.externalSourceEntry.projectTitle : this.externalSourceEntry.event.message.title; + this.searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: this.configuration, + query: this.projectTitle, + pagination: this.pagination + } + )); + this.localEntitiesRD$ = this.searchService.search(this.searchOptions); + this.subs.push( + this.localEntitiesRD$.subscribe( + () => this.isLoading$ = observableOf(false) + ) + ); + } + + /** + * Close the modal. + */ + public close(): void { + this.deselectAllLists(); + this.modal.close(); + } + + /** + * Perform a project search by title. + */ + public search(searchTitle): void { + if (isNotEmpty(searchTitle)) { + const filterRegEx = /[:]/g; + this.isLoading$ = observableOf(true); + this.searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: this.configuration, + query: (searchTitle) ? searchTitle.replace(filterRegEx, '') : searchTitle, + pagination: this.pagination + } + )); + this.localEntitiesRD$ = this.searchService.search(this.searchOptions); + this.subs.push( + this.localEntitiesRD$.subscribe( + () => this.isLoading$ = observableOf(false) + ) + ); + } + } + + /** + * Perform the bound of the project. + */ + public bound(): void { + if (this.selectedEntity !== undefined) { + this.importedObject.emit(this.selectedEntity); + } + this.selectedImportType = ImportType.None; + this.deselectAllLists(); + this.close(); + } + + /** + * Deselected a local entity + */ + public deselectEntity(): void { + this.selectedEntity = undefined; + if (this.selectedImportType === ImportType.LocalEntity) { + this.selectedImportType = ImportType.None; + } + } + + /** + * Selected a local entity + * @param entity + */ + public selectEntity(entity): void { + this.selectedEntity = entity; + this.selectedImportType = ImportType.LocalEntity; + } + + /** + * Deselect every element from both entity and authority lists + */ + public deselectAllLists(): void { + this.selectService.deselectAll(this.entityListId); + this.selectService.deselectAll(this.authorityListId); + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.deselectAllLists(); + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } +} diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.actions.ts b/src/app/openaire/broker/topics/openaire-broker-topics.actions.ts new file mode 100644 index 0000000000..fd98c6acb8 --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.actions.ts @@ -0,0 +1,99 @@ +import { Action } from '@ngrx/store'; +import { type } from '../../../shared/ngrx/type'; +import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; + +/** + * For each action type in an action group, make a simple + * enum object for all of this group's action types. + * + * The 'type' utility function coerces strings into string + * literal types and runs a simple check to guarantee all + * action types in the application are unique. + */ +export const OpenaireBrokerTopicActionTypes = { + ADD_TOPICS: type('dspace/integration/openaire/broker/topic/ADD_TOPICS'), + RETRIEVE_ALL_TOPICS: type('dspace/integration/openaire/broker/topic/RETRIEVE_ALL_TOPICS'), + RETRIEVE_ALL_TOPICS_ERROR: type('dspace/integration/openaire/broker/topic/RETRIEVE_ALL_TOPICS_ERROR'), +}; + +/* tslint:disable:max-classes-per-file */ + +/** + * An ngrx action to retrieve all the OpenAIRE Broker topics. + */ +export class RetrieveAllTopicsAction implements Action { + type = OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS; + payload: { + elementsPerPage: number; + currentPage: number; + }; + + /** + * Create a new RetrieveAllTopicsAction. + * + * @param elementsPerPage + * the number of topics per page + * @param currentPage + * The page number to retrieve + */ + constructor(elementsPerPage: number, currentPage: number) { + this.payload = { + elementsPerPage, + currentPage + }; + } +} + +/** + * An ngrx action for retrieving 'all OpenAIRE Broker topics' error. + */ +export class RetrieveAllTopicsErrorAction implements Action { + type = OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR; +} + +/** + * An ngrx action to load the OpenAIRE Broker topic objects. + * Called by the ??? effect. + */ +export class AddTopicsAction implements Action { + type = OpenaireBrokerTopicActionTypes.ADD_TOPICS; + payload: { + topics: OpenaireBrokerTopicObject[]; + totalPages: number; + currentPage: number; + totalElements: number; + }; + + /** + * Create a new AddTopicsAction. + * + * @param topics + * the list of topics + * @param totalPages + * the total available pages of topics + * @param currentPage + * the current page + * @param totalElements + * the total available OpenAIRE Broker topics + */ + constructor(topics: OpenaireBrokerTopicObject[], totalPages: number, currentPage: number, totalElements: number) { + this.payload = { + topics, + totalPages, + currentPage, + totalElements + }; + } + +} + +/* tslint:enable:max-classes-per-file */ + +/** + * Export a type alias of all actions in this action group + * so that reducers can easily compose action types. + */ +export type OpenaireBrokerTopicsActions + = AddTopicsAction + |RetrieveAllTopicsAction + |RetrieveAllTopicsErrorAction; diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.component.html b/src/app/openaire/broker/topics/openaire-broker-topics.component.html new file mode 100644 index 0000000000..d8321bc932 --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.component.html @@ -0,0 +1,57 @@ +
+
+
+

{{'openaire.broker.title'| translate}}

+

{{'openaire.broker.topics.description'| translate}}

+
+
+
+
+

{{'openaire.broker.topics'| translate}}

+ + + + + + + +
+ + + + + + + + + + + + + + + +
{{'openaire.broker.table.topic' | translate}}{{'openaire.broker.table.last-event' | translate}}{{'openaire.broker.table.actions' | translate}}
{{topicElement.name}}{{topicElement.lastEvent}} +
+ +
+
+
+
+
+
+
+
diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.component.scss b/src/app/openaire/broker/topics/openaire-broker-topics.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.component.spec.ts b/src/app/openaire/broker/topics/openaire-broker-topics.component.spec.ts new file mode 100644 index 0000000000..00ea772ff9 --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.component.spec.ts @@ -0,0 +1,152 @@ +import { CommonModule } from '@angular/common'; +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; +import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { + getMockOpenaireStateService, + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMorePid +} from '../../../shared/mocks/openaire.mock'; +import { OpenaireBrokerTopicsComponent } from './openaire-broker-topics.component'; +import { OpenaireStateService } from '../../openaire-state.service'; +import { cold } from 'jasmine-marbles'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../../core/pagination/pagination.service'; + +describe('OpenaireBrokerTopicsComponent test suite', () => { + let fixture: ComponentFixture; + let comp: OpenaireBrokerTopicsComponent; + let compAsAny: any; + const mockOpenaireStateService = getMockOpenaireStateService(); + const activatedRouteParams = { + openaireBrokerTopicsParams: { + currentPage: 0, + pageSize: 5 + } + }; + const paginationService = new PaginationServiceStub(); + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot(), + ], + declarations: [ + OpenaireBrokerTopicsComponent, + TestComponent, + ], + providers: [ + { provide: OpenaireStateService, useValue: mockOpenaireStateService }, + { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), params: observableOf({}) } }, + { provide: PaginationService, useValue: paginationService }, + OpenaireBrokerTopicsComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(() => { + mockOpenaireStateService.getOpenaireBrokerTopics.and.returnValue(observableOf([ + openaireBrokerTopicObjectMorePid, + openaireBrokerTopicObjectMoreAbstract + ])); + mockOpenaireStateService.getOpenaireBrokerTopicsTotalPages.and.returnValue(observableOf(1)); + mockOpenaireStateService.getOpenaireBrokerTopicsCurrentPage.and.returnValue(observableOf(0)); + mockOpenaireStateService.getOpenaireBrokerTopicsTotals.and.returnValue(observableOf(2)); + mockOpenaireStateService.isOpenaireBrokerTopicsLoaded.and.returnValue(observableOf(true)); + mockOpenaireStateService.isOpenaireBrokerTopicsLoading.and.returnValue(observableOf(false)); + mockOpenaireStateService.isOpenaireBrokerTopicsProcessing.and.returnValue(observableOf(false)); + }); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create OpenaireBrokerTopicsComponent', inject([OpenaireBrokerTopicsComponent], (app: OpenaireBrokerTopicsComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('Main tests running with two topics', () => { + beforeEach(() => { + fixture = TestBed.createComponent(OpenaireBrokerTopicsComponent); + comp = fixture.componentInstance; + compAsAny = comp; + + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it(('Should init component properly'), () => { + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.topics$).toBeObservable(cold('(a|)', { + a: [ + openaireBrokerTopicObjectMorePid, + openaireBrokerTopicObjectMoreAbstract + ] + })); + expect(comp.totalElements$).toBeObservable(cold('(a|)', { + a: 2 + })); + }); + + it(('Should set data properly after the view init'), () => { + spyOn(compAsAny, 'getOpenaireBrokerTopics'); + + comp.ngAfterViewInit(); + fixture.detectChanges(); + + expect(compAsAny.getOpenaireBrokerTopics).toHaveBeenCalled(); + }); + + it(('isTopicsLoading should return FALSE'), () => { + expect(comp.isTopicsLoading()).toBeObservable(cold('(a|)', { + a: false + })); + }); + + it(('isTopicsProcessing should return FALSE'), () => { + expect(comp.isTopicsProcessing()).toBeObservable(cold('(a|)', { + a: false + })); + }); + + it(('getOpenaireBrokerTopics should call the service to dispatch a STATE change'), () => { + comp.ngOnInit(); + fixture.detectChanges(); + + compAsAny.openaireStateService.dispatchRetrieveOpenaireBrokerTopics(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); + expect(compAsAny.openaireStateService.dispatchRetrieveOpenaireBrokerTopics).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.component.ts b/src/app/openaire/broker/topics/openaire-broker-topics.component.ts new file mode 100644 index 0000000000..408e21d946 --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.component.ts @@ -0,0 +1,142 @@ +import { Component, OnInit } from '@angular/core'; + +import { Observable, Subscription } from 'rxjs'; +import { distinctUntilChanged, take } from 'rxjs/operators'; + +import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; +import { hasValue } from '../../../shared/empty.util'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { OpenaireStateService } from '../../openaire-state.service'; +import { AdminNotificationsOpenaireTopicsPageParams } from '../../../admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; + +/** + * Component to display the OpenAIRE Broker topic list. + */ +@Component({ + selector: 'ds-openaire-broker-topic', + templateUrl: './openaire-broker-topics.component.html', + styleUrls: ['./openaire-broker-topics.component.scss'], +}) +export class OpenaireBrokerTopicsComponent implements OnInit { + /** + * The pagination system configuration for HTML listing. + * @type {PaginationComponentOptions} + */ + public paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'btp', + pageSize: 10, + pageSizeOptions: [5, 10, 20, 40, 60] + }); + /** + * The OpenAIRE Broker topic list sort options. + * @type {SortOptions} + */ + public paginationSortConfig: SortOptions; + /** + * The OpenAIRE Broker topic list. + */ + public topics$: Observable; + /** + * The total number of OpenAIRE Broker topics. + */ + public totalElements$: Observable; + /** + * Array to track all the component subscriptions. Useful to unsubscribe them with 'onDestroy'. + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * Initialize the component variables. + * @param {PaginationService} paginationService + * @param {OpenaireStateService} openaireStateService + */ + constructor( + private paginationService: PaginationService, + private openaireStateService: OpenaireStateService, + ) { } + + /** + * Component initialization. + */ + ngOnInit(): void { + this.topics$ = this.openaireStateService.getOpenaireBrokerTopics(); + this.totalElements$ = this.openaireStateService.getOpenaireBrokerTopicsTotals(); + } + + /** + * First OpenAIRE Broker topics loading after view initialization. + */ + ngAfterViewInit(): void { + this.subs.push( + this.openaireStateService.isOpenaireBrokerTopicsLoaded().pipe( + take(1) + ).subscribe(() => { + this.getOpenaireBrokerTopics(); + }) + ); + } + + /** + * Returns the information about the loading status of the OpenAIRE Broker topics (if it's running or not). + * + * @return Observable + * 'true' if the topics are loading, 'false' otherwise. + */ + public isTopicsLoading(): Observable { + return this.openaireStateService.isOpenaireBrokerTopicsLoading(); + } + + /** + * Returns the information about the processing status of the OpenAIRE Broker topics (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the topics (ex.: a REST call), 'false' otherwise. + */ + public isTopicsProcessing(): Observable { + return this.openaireStateService.isOpenaireBrokerTopicsProcessing(); + } + + /** + * Dispatch the OpenAIRE Broker topics retrival. + */ + public getOpenaireBrokerTopics(): void { + this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( + distinctUntilChanged(), + ).subscribe((options: PaginationComponentOptions) => { + this.openaireStateService.dispatchRetrieveOpenaireBrokerTopics( + options.pageSize, + options.currentPage + ); + }); + } + + /** + * Update pagination Config from route params + * + * @param eventsRouteParams + */ + protected updatePaginationFromRouteParams(eventsRouteParams: AdminNotificationsOpenaireTopicsPageParams) { + if (eventsRouteParams.currentPage) { + this.paginationConfig.currentPage = eventsRouteParams.currentPage; + } + if (eventsRouteParams.pageSize) { + if (this.paginationConfig.pageSizeOptions.includes(eventsRouteParams.pageSize)) { + this.paginationConfig.pageSize = eventsRouteParams.pageSize; + } else { + this.paginationConfig.pageSize = this.paginationConfig.pageSizeOptions[0]; + } + } + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } +} diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.effects.ts b/src/app/openaire/broker/topics/openaire-broker-topics.effects.ts new file mode 100644 index 0000000000..b590b122f5 --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.effects.ts @@ -0,0 +1,87 @@ +import { Injectable } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { TranslateService } from '@ngx-translate/core'; +import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; +import { of as observableOf } from 'rxjs'; +import { + AddTopicsAction, + OpenaireBrokerTopicActionTypes, + RetrieveAllTopicsAction, + RetrieveAllTopicsErrorAction, +} from './openaire-broker-topics.actions'; + +import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { OpenaireBrokerTopicsService } from './openaire-broker-topics.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { OpenaireBrokerTopicRestService } from '../../../core/openaire/broker/topics/openaire-broker-topic-rest.service'; + +/** + * Provides effect methods for the OpenAIRE Broker topics actions. + */ +@Injectable() +export class OpenaireBrokerTopicsEffects { + + /** + * Retrieve all OpenAIRE Broker topics managing pagination and errors. + */ + @Effect() retrieveAllTopics$ = this.actions$.pipe( + ofType(OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS), + withLatestFrom(this.store$), + switchMap(([action, currentState]: [RetrieveAllTopicsAction, any]) => { + return this.openaireBrokerTopicService.getTopics( + action.payload.elementsPerPage, + action.payload.currentPage + ).pipe( + map((topics: PaginatedList) => + new AddTopicsAction(topics.page, topics.totalPages, topics.currentPage, topics.totalElements) + ), + catchError((error: Error) => { + if (error) { + console.error(error.message); + } + return observableOf(new RetrieveAllTopicsErrorAction()); + }) + ); + }) + ); + + /** + * Show a notification on error. + */ + @Effect({ dispatch: false }) retrieveAllTopicsErrorAction$ = this.actions$.pipe( + ofType(OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR), + tap(() => { + this.notificationsService.error(null, this.translate.get('openaire.broker.topic.error.service.retrieve')); + }) + ); + + /** + * Clear find all topics requests from cache. + */ + @Effect({ dispatch: false }) addTopicsAction$ = this.actions$.pipe( + ofType(OpenaireBrokerTopicActionTypes.ADD_TOPICS), + tap(() => { + this.openaireBrokerTopicDataService.clearFindAllTopicsRequests(); + }) + ); + + /** + * Initialize the effect class variables. + * @param {Actions} actions$ + * @param {Store} store$ + * @param {TranslateService} translate + * @param {NotificationsService} notificationsService + * @param {OpenaireBrokerTopicsService} openaireBrokerTopicService + * @param {OpenaireBrokerTopicRestService} openaireBrokerTopicDataService + */ + constructor( + private actions$: Actions, + private store$: Store, + private translate: TranslateService, + private notificationsService: NotificationsService, + private openaireBrokerTopicService: OpenaireBrokerTopicsService, + private openaireBrokerTopicDataService: OpenaireBrokerTopicRestService + ) { } +} diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.reducer.spec.ts b/src/app/openaire/broker/topics/openaire-broker-topics.reducer.spec.ts new file mode 100644 index 0000000000..b4ee60558b --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.reducer.spec.ts @@ -0,0 +1,68 @@ +import { + AddTopicsAction, + RetrieveAllTopicsAction, + RetrieveAllTopicsErrorAction +} from './openaire-broker-topics.actions'; +import { openaireBrokerTopicsReducer, OpenaireBrokerTopicState } from './openaire-broker-topics.reducer'; +import { + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMorePid +} from '../../../shared/mocks/openaire.mock'; + +describe('openaireBrokerTopicsReducer test suite', () => { + let openaireBrokerTopicInitialState: OpenaireBrokerTopicState; + const elementPerPage = 3; + const currentPage = 0; + + beforeEach(() => { + openaireBrokerTopicInitialState = { + topics: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }; + }); + + it('Action RETRIEVE_ALL_TOPICS should set the State property "processing" to TRUE', () => { + const expectedState = openaireBrokerTopicInitialState; + expectedState.processing = true; + + const action = new RetrieveAllTopicsAction(elementPerPage, currentPage); + const newState = openaireBrokerTopicsReducer(openaireBrokerTopicInitialState, action); + + expect(newState).toEqual(expectedState); + }); + + it('Action RETRIEVE_ALL_TOPICS_ERROR should change the State to initial State but processing, loaded, and currentPage', () => { + const expectedState = openaireBrokerTopicInitialState; + expectedState.processing = false; + expectedState.loaded = true; + expectedState.currentPage = 0; + + const action = new RetrieveAllTopicsErrorAction(); + const newState = openaireBrokerTopicsReducer(openaireBrokerTopicInitialState, action); + + expect(newState).toEqual(expectedState); + }); + + it('Action ADD_TOPICS should populate the State with OpenAIRE Broker topics', () => { + const expectedState = { + topics: [ openaireBrokerTopicObjectMorePid, openaireBrokerTopicObjectMoreAbstract ], + processing: false, + loaded: true, + totalPages: 1, + currentPage: 0, + totalElements: 2 + }; + + const action = new AddTopicsAction( + [ openaireBrokerTopicObjectMorePid, openaireBrokerTopicObjectMoreAbstract ], + 1, 0, 2 + ); + const newState = openaireBrokerTopicsReducer(openaireBrokerTopicInitialState, action); + + expect(newState).toEqual(expectedState); + }); +}); diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.reducer.ts b/src/app/openaire/broker/topics/openaire-broker-topics.reducer.ts new file mode 100644 index 0000000000..6ae596117f --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.reducer.ts @@ -0,0 +1,72 @@ +import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; +import { OpenaireBrokerTopicActionTypes, OpenaireBrokerTopicsActions } from './openaire-broker-topics.actions'; + +/** + * The interface representing the OpenAIRE Broker topic state. + */ +export interface OpenaireBrokerTopicState { + topics: OpenaireBrokerTopicObject[]; + processing: boolean; + loaded: boolean; + totalPages: number; + currentPage: number; + totalElements: number; +} + +/** + * Used for the OpenAIRE Broker topic state initialization. + */ +const openaireBrokerTopicInitialState: OpenaireBrokerTopicState = { + topics: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 +}; + +/** + * The OpenAIRE Broker Topic Reducer + * + * @param state + * the current state initialized with openaireBrokerTopicInitialState + * @param action + * the action to perform on the state + * @return OpenaireBrokerTopicState + * the new state + */ +export function openaireBrokerTopicsReducer(state = openaireBrokerTopicInitialState, action: OpenaireBrokerTopicsActions): OpenaireBrokerTopicState { + switch (action.type) { + case OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS: { + return Object.assign({}, state, { + topics: [], + processing: true + }); + } + + case OpenaireBrokerTopicActionTypes.ADD_TOPICS: { + return Object.assign({}, state, { + topics: action.payload.topics, + processing: false, + loaded: true, + totalPages: action.payload.totalPages, + currentPage: state.currentPage, + totalElements: action.payload.totalElements + }); + } + + case OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR: { + return Object.assign({}, state, { + processing: false, + loaded: true, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }); + } + + default: { + return state; + } + } +} diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.service.spec.ts b/src/app/openaire/broker/topics/openaire-broker-topics.service.spec.ts new file mode 100644 index 0000000000..3daed2c3bf --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.service.spec.ts @@ -0,0 +1,67 @@ +import { TestBed } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; +import { OpenaireBrokerTopicsService } from './openaire-broker-topics.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { OpenaireBrokerTopicRestService } from '../../../core/openaire/broker/topics/openaire-broker-topic-rest.service'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { + getMockOpenaireBrokerTopicRestService, + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMorePid +} from '../../../shared/mocks/openaire.mock'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { cold } from 'jasmine-marbles'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; + +describe('OpenaireBrokerTopicsService', () => { + let service: OpenaireBrokerTopicsService; + let restService: OpenaireBrokerTopicRestService; + let serviceAsAny: any; + let restServiceAsAny: any; + + const pageInfo = new PageInfo(); + const array = [ openaireBrokerTopicObjectMorePid, openaireBrokerTopicObjectMoreAbstract ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + const elementsPerPage = 3; + const currentPage = 0; + + beforeEach(async () => { + TestBed.configureTestingModule({ + providers: [ + { provide: OpenaireBrokerTopicRestService, useClass: getMockOpenaireBrokerTopicRestService }, + { provide: OpenaireBrokerTopicsService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + restService = TestBed.get(OpenaireBrokerTopicRestService); + restServiceAsAny = restService; + restServiceAsAny.getTopics.and.returnValue(observableOf(paginatedListRD)); + service = new OpenaireBrokerTopicsService(restService); + serviceAsAny = service; + }); + + describe('getTopics', () => { + it('Should proxy the call to openaireBrokerTopicRestService.getTopics', () => { + const sortOptions = new SortOptions('name', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + const result = service.getTopics(elementsPerPage, currentPage); + expect((service as any).openaireBrokerTopicRestService.getTopics).toHaveBeenCalledWith(findListOptions); + }); + + it('Should return a paginated list of OpenAIRE Broker topics', () => { + const expected = cold('(a|)', { + a: paginatedList + }); + const result = service.getTopics(elementsPerPage, currentPage); + expect(result).toBeObservable(expected); + }); + }); +}); diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.service.ts b/src/app/openaire/broker/topics/openaire-broker-topics.service.ts new file mode 100644 index 0000000000..17f189922f --- /dev/null +++ b/src/app/openaire/broker/topics/openaire-broker-topics.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { find, map } from 'rxjs/operators'; +import { OpenaireBrokerTopicRestService } from '../../../core/openaire/broker/topics/openaire-broker-topic-rest.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; + +/** + * The service handling all OpenAIRE Broker topic requests to the REST service. + */ +@Injectable() +export class OpenaireBrokerTopicsService { + + /** + * Initialize the service variables. + * @param {OpenaireBrokerTopicRestService} openaireBrokerTopicRestService + */ + constructor( + private openaireBrokerTopicRestService: OpenaireBrokerTopicRestService + ) { } + + /** + * Return the list of OpenAIRE Broker topics managing pagination and errors. + * + * @param elementsPerPage + * The number of the topics per page + * @param currentPage + * The page number to retrieve + * @return Observable> + * The list of OpenAIRE Broker topics. + */ + public getTopics(elementsPerPage, currentPage): Observable> { + const sortOptions = new SortOptions('name', SortDirection.ASC); + + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + + return this.openaireBrokerTopicRestService.getTopics(findListOptions).pipe( + find((rd: RemoteData>) => !rd.isResponsePending), + map((rd: RemoteData>) => { + if (rd.hasSucceeded) { + return rd.payload; + } else { + throw new Error('Can\'t retrieve OpenAIRE Broker topics from the Broker topics REST service'); + } + }) + ); + } +} diff --git a/src/app/openaire/openaire-state.service.spec.ts b/src/app/openaire/openaire-state.service.spec.ts new file mode 100644 index 0000000000..874d4b4e1a --- /dev/null +++ b/src/app/openaire/openaire-state.service.spec.ts @@ -0,0 +1,275 @@ +import { TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { provideMockStore } from '@ngrx/store/testing'; +import { cold } from 'jasmine-marbles'; +import { openaireReducers } from './openaire.reducer'; +import { OpenaireStateService } from './openaire-state.service'; +import { + openaireBrokerTopicObjectMissingPid, + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMorePid +} from '../shared/mocks/openaire.mock'; +import { RetrieveAllTopicsAction } from './broker/topics/openaire-broker-topics.actions'; + +describe('OpenaireStateService', () => { + let service: OpenaireStateService; + let serviceAsAny: any; + let store: any; + let initialState: any; + + function init(mode: string) { + if (mode === 'empty') { + initialState = { + openaire: { + brokerTopic: { + topics: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0, + totalLoadedPages: 0 + } + } + }; + } else { + initialState = { + openaire: { + brokerTopic: { + topics: [ + openaireBrokerTopicObjectMorePid, + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMissingPid + ], + processing: false, + loaded: true, + totalPages: 1, + currentPage: 1, + totalElements: 3, + totalLoadedPages: 1 + } + } + }; + } + } + + describe('Testing methods with empty topic objects', () => { + beforeEach(async () => { + init('empty'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ openaire: openaireReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: OpenaireStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new OpenaireStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getOpenaireBrokerTopics', () => { + it('Should return an empty array', () => { + const result = service.getOpenaireBrokerTopics(); + const expected = cold('(a)', { + a: [] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsTotalPages', () => { + it('Should return zero (0)', () => { + const result = service.getOpenaireBrokerTopicsTotalPages(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsCurrentPage', () => { + it('Should return minus one (0)', () => { + const result = service.getOpenaireBrokerTopicsCurrentPage(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsTotals', () => { + it('Should return zero (0)', () => { + const result = service.getOpenaireBrokerTopicsTotals(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsLoading', () => { + it('Should return TRUE', () => { + const result = service.isOpenaireBrokerTopicsLoading(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsLoaded', () => { + it('Should return FALSE', () => { + const result = service.isOpenaireBrokerTopicsLoaded(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsProcessing', () => { + it('Should return FALSE', () => { + const result = service.isOpenaireBrokerTopicsProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + }); + + describe('Testing methods with topic objects', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ openaire: openaireReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: OpenaireStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new OpenaireStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getOpenaireBrokerTopics', () => { + it('Should return an array of topics', () => { + const result = service.getOpenaireBrokerTopics(); + const expected = cold('(a)', { + a: [ + openaireBrokerTopicObjectMorePid, + openaireBrokerTopicObjectMoreAbstract, + openaireBrokerTopicObjectMissingPid + ] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsTotalPages', () => { + it('Should return one (1)', () => { + const result = service.getOpenaireBrokerTopicsTotalPages(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsCurrentPage', () => { + it('Should return minus zero (1)', () => { + const result = service.getOpenaireBrokerTopicsCurrentPage(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getOpenaireBrokerTopicsTotals', () => { + it('Should return three (3)', () => { + const result = service.getOpenaireBrokerTopicsTotals(); + const expected = cold('(a)', { + a: 3 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsLoading', () => { + it('Should return FALSE', () => { + const result = service.isOpenaireBrokerTopicsLoading(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsLoaded', () => { + it('Should return TRUE', () => { + const result = service.isOpenaireBrokerTopicsLoaded(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isOpenaireBrokerTopicsProcessing', () => { + it('Should return FALSE', () => { + const result = service.isOpenaireBrokerTopicsProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + }); + + describe('Testing the topic dispatch methods', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ openaire: openaireReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: OpenaireStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new OpenaireStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('dispatchRetrieveOpenaireBrokerTopics', () => { + it('Should call store.dispatch', () => { + const elementsPerPage = 3; + const currentPage = 1; + const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage); + service.dispatchRetrieveOpenaireBrokerTopics(elementsPerPage, currentPage); + expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); + }); + }); + }); +}); diff --git a/src/app/openaire/openaire-state.service.ts b/src/app/openaire/openaire-state.service.ts new file mode 100644 index 0000000000..10dd739ae5 --- /dev/null +++ b/src/app/openaire/openaire-state.service.ts @@ -0,0 +1,116 @@ +import { Injectable } from '@angular/core'; +import { select, Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { + getOpenaireBrokerTopicsCurrentPageSelector, + getOpenaireBrokerTopicsTotalPagesSelector, + getOpenaireBrokerTopicsTotalsSelector, + isOpenaireBrokerTopicsLoadedSelector, + openaireBrokerTopicsObjectSelector, + sOpenaireBrokerTopicsProcessingSelector +} from './selectors'; +import { OpenaireBrokerTopicObject } from '../core/openaire/broker/models/openaire-broker-topic.model'; +import { OpenaireState } from './openaire.reducer'; +import { RetrieveAllTopicsAction } from './broker/topics/openaire-broker-topics.actions'; + +/** + * The service handling the OpenAIRE State. + */ +@Injectable() +export class OpenaireStateService { + + /** + * Initialize the service variables. + * @param {Store} store + */ + constructor(private store: Store) { } + + // OpenAIRE Broker topics + // -------------------------------------------------------------------------- + + /** + * Returns the list of OpenAIRE Broker topics from the state. + * + * @return Observable + * The list of OpenAIRE Broker topics. + */ + public getOpenaireBrokerTopics(): Observable { + return this.store.pipe(select(openaireBrokerTopicsObjectSelector())); + } + + /** + * Returns the information about the loading status of the OpenAIRE Broker topics (if it's running or not). + * + * @return Observable + * 'true' if the topics are loading, 'false' otherwise. + */ + public isOpenaireBrokerTopicsLoading(): Observable { + return this.store.pipe( + select(isOpenaireBrokerTopicsLoadedSelector), + map((loaded: boolean) => !loaded) + ); + } + + /** + * Returns the information about the loading status of the OpenAIRE Broker topics (whether or not they were loaded). + * + * @return Observable + * 'true' if the topics are loaded, 'false' otherwise. + */ + public isOpenaireBrokerTopicsLoaded(): Observable { + return this.store.pipe(select(isOpenaireBrokerTopicsLoadedSelector)); + } + + /** + * Returns the information about the processing status of the OpenAIRE Broker topics (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the topics (ex.: a REST call), 'false' otherwise. + */ + public isOpenaireBrokerTopicsProcessing(): Observable { + return this.store.pipe(select(sOpenaireBrokerTopicsProcessingSelector)); + } + + /** + * Returns, from the state, the total available pages of the OpenAIRE Broker topics. + * + * @return Observable + * The number of the OpenAIRE Broker topics pages. + */ + public getOpenaireBrokerTopicsTotalPages(): Observable { + return this.store.pipe(select(getOpenaireBrokerTopicsTotalPagesSelector)); + } + + /** + * Returns the current page of the OpenAIRE Broker topics, from the state. + * + * @return Observable + * The number of the current OpenAIRE Broker topics page. + */ + public getOpenaireBrokerTopicsCurrentPage(): Observable { + return this.store.pipe(select(getOpenaireBrokerTopicsCurrentPageSelector)); + } + + /** + * Returns the total number of the OpenAIRE Broker topics. + * + * @return Observable + * The number of the OpenAIRE Broker topics. + */ + public getOpenaireBrokerTopicsTotals(): Observable { + return this.store.pipe(select(getOpenaireBrokerTopicsTotalsSelector)); + } + + /** + * Dispatch a request to change the OpenAIRE Broker topics state, retrieving the topics from the server. + * + * @param elementsPerPage + * The number of the topics per page. + * @param currentPage + * The number of the current page. + */ + public dispatchRetrieveOpenaireBrokerTopics(elementsPerPage: number, currentPage: number): void { + this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage)); + } +} diff --git a/src/app/openaire/openaire.effects.ts b/src/app/openaire/openaire.effects.ts new file mode 100644 index 0000000000..9861c1a921 --- /dev/null +++ b/src/app/openaire/openaire.effects.ts @@ -0,0 +1,5 @@ +import { OpenaireBrokerTopicsEffects } from './broker/topics/openaire-broker-topics.effects'; + +export const openaireEffects = [ + OpenaireBrokerTopicsEffects +]; diff --git a/src/app/openaire/openaire.module.ts b/src/app/openaire/openaire.module.ts new file mode 100644 index 0000000000..ac5d4e7287 --- /dev/null +++ b/src/app/openaire/openaire.module.ts @@ -0,0 +1,74 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Action, StoreConfig, StoreModule } from '@ngrx/store'; +import { EffectsModule } from '@ngrx/effects'; + +import { CoreModule } from '../core/core.module'; +import { SharedModule } from '../shared/shared.module'; +import { storeModuleConfig } from '../app.reducer'; +import { OpenaireBrokerTopicsComponent } from './broker/topics/openaire-broker-topics.component'; +import { OpenaireBrokerEventsComponent } from './broker/events/openaire-broker-events.component'; +import { OpenaireStateService } from './openaire-state.service'; +import { openaireReducers, OpenaireState } from './openaire.reducer'; +import { openaireEffects } from './openaire.effects'; +import { OpenaireBrokerTopicsService } from './broker/topics/openaire-broker-topics.service'; +import { OpenaireBrokerTopicRestService } from '../core/openaire/broker/topics/openaire-broker-topic-rest.service'; +import { OpenaireBrokerEventRestService } from '../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { ProjectEntryImportModalComponent } from './broker/project-entry-import-modal/project-entry-import-modal.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { SearchModule } from '../shared/search/search.module'; + +const MODULES = [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + StoreModule.forFeature('openaire', openaireReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(openaireEffects), + TranslateModule +]; + +const COMPONENTS = [ + OpenaireBrokerTopicsComponent, + OpenaireBrokerEventsComponent +]; + +const DIRECTIVES = [ ]; + +const ENTRY_COMPONENTS = [ + ProjectEntryImportModalComponent +]; + +const PROVIDERS = [ + OpenaireStateService, + OpenaireBrokerTopicsService, + OpenaireBrokerTopicRestService, + OpenaireBrokerEventRestService +]; + +@NgModule({ + imports: [ + ...MODULES, + SearchModule + ], + declarations: [ + ...COMPONENTS, + ...DIRECTIVES, + ...ENTRY_COMPONENTS + ], + providers: [ + ...PROVIDERS + ], + entryComponents: [ + ...ENTRY_COMPONENTS + ], + exports: [ + ...COMPONENTS, + ...DIRECTIVES + ] +}) + +/** + * This module handles all components that are necessary for the OpenAIRE components + */ +export class OpenaireModule { +} diff --git a/src/app/openaire/openaire.reducer.ts b/src/app/openaire/openaire.reducer.ts new file mode 100644 index 0000000000..9ead098329 --- /dev/null +++ b/src/app/openaire/openaire.reducer.ts @@ -0,0 +1,16 @@ +import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; + +import { openaireBrokerTopicsReducer, OpenaireBrokerTopicState, } from './broker/topics/openaire-broker-topics.reducer'; + +/** + * The OpenAIRE State + */ +export interface OpenaireState { + 'brokerTopic': OpenaireBrokerTopicState; +} + +export const openaireReducers: ActionReducerMap = { + brokerTopic: openaireBrokerTopicsReducer, +}; + +export const openaireSelector = createFeatureSelector('openaire'); diff --git a/src/app/openaire/selectors.ts b/src/app/openaire/selectors.ts new file mode 100644 index 0000000000..fc3508eef4 --- /dev/null +++ b/src/app/openaire/selectors.ts @@ -0,0 +1,79 @@ +import { createSelector, MemoizedSelector } from '@ngrx/store'; +import { subStateSelector } from '../shared/selector.util'; +import { openaireSelector, OpenaireState } from './openaire.reducer'; +import { OpenaireBrokerTopicObject } from '../core/openaire/broker/models/openaire-broker-topic.model'; +import { OpenaireBrokerTopicState } from './broker/topics/openaire-broker-topics.reducer'; + +/** + * Returns the OpenAIRE state. + * @function _getOpenaireState + * @param {AppState} state Top level state. + * @return {OpenaireState} + */ +const _getOpenaireState = (state: any) => state.openaire; + +// OpenAIRE Broker topics +// ---------------------------------------------------------------------------- + +/** + * Returns the OpenAIRE Broker topics State. + * @function openaireBrokerTopicsStateSelector + * @return {OpenaireBrokerTopicState} + */ +export function openaireBrokerTopicsStateSelector(): MemoizedSelector { + return subStateSelector(openaireSelector, 'brokerTopic'); +} + +/** + * Returns the OpenAIRE Broker topics list. + * @function openaireBrokerTopicsObjectSelector + * @return {OpenaireBrokerTopicObject[]} + */ +export function openaireBrokerTopicsObjectSelector(): MemoizedSelector { + return subStateSelector(openaireBrokerTopicsStateSelector(), 'topics'); +} + +/** + * Returns true if the OpenAIRE Broker topics are loaded. + * @function isOpenaireBrokerTopicsLoadedSelector + * @return {boolean} + */ +export const isOpenaireBrokerTopicsLoadedSelector = createSelector(_getOpenaireState, + (state: OpenaireState) => state.brokerTopic.loaded +); + +/** + * Returns true if the deduplication sets are processing. + * @function isDeduplicationSetsProcessingSelector + * @return {boolean} + */ +export const sOpenaireBrokerTopicsProcessingSelector = createSelector(_getOpenaireState, + (state: OpenaireState) => state.brokerTopic.processing +); + +/** + * Returns the total available pages of OpenAIRE Broker topics. + * @function getOpenaireBrokerTopicsTotalPagesSelector + * @return {number} + */ +export const getOpenaireBrokerTopicsTotalPagesSelector = createSelector(_getOpenaireState, + (state: OpenaireState) => state.brokerTopic.totalPages +); + +/** + * Returns the current page of OpenAIRE Broker topics. + * @function getOpenaireBrokerTopicsCurrentPageSelector + * @return {number} + */ +export const getOpenaireBrokerTopicsCurrentPageSelector = createSelector(_getOpenaireState, + (state: OpenaireState) => state.brokerTopic.currentPage +); + +/** + * Returns the total number of OpenAIRE Broker topics. + * @function getOpenaireBrokerTopicsTotalsSelector + * @return {number} + */ +export const getOpenaireBrokerTopicsTotalsSelector = createSelector(_getOpenaireState, + (state: OpenaireState) => state.brokerTopic.totalElements +); diff --git a/src/app/shared/mocks/openaire.mock.ts b/src/app/shared/mocks/openaire.mock.ts new file mode 100644 index 0000000000..908aae1f67 --- /dev/null +++ b/src/app/shared/mocks/openaire.mock.ts @@ -0,0 +1,1796 @@ +import { of as observableOf } from 'rxjs'; +import { ResourceType } from '../../core/shared/resource-type'; +import { OpenaireBrokerTopicObject } from '../../core/openaire/broker/models/openaire-broker-topic.model'; +import { OpenaireBrokerEventObject } from '../../core/openaire/broker/models/openaire-broker-event.model'; +import { OpenaireBrokerTopicRestService } from '../../core/openaire/broker/topics/openaire-broker-topic-rest.service'; +import { OpenaireBrokerEventRestService } from '../../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { OpenaireStateService } from '../../openaire/openaire-state.service'; +import { Item } from '../../core/shared/item.model'; +import { + createNoContentRemoteDataObject$, + createSuccessfulRemoteDataObject, + createSuccessfulRemoteDataObject$ +} from '../remote-data.utils'; +import { SearchResult } from '../search/models/search-result.model'; + +// REST Mock --------------------------------------------------------------------- +// ------------------------------------------------------------------------------- + +// Items +// ------------------------------------------------------------------------------- + +const ItemMockPid1: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174001', + uuid: 'ITEM4567-e89b-12d3-a456-426614174001', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Index nominum et rerum' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid2: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174004', + uuid: 'ITEM4567-e89b-12d3-a456-426614174004', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'UNA NUOVA RILETTURA DELL\u0027 ARISTOTELE DI FRANZ BRENTANO ALLA LUCE DI ALCUNI INEDITI' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid3: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174005', + uuid: 'ITEM4567-e89b-12d3-a456-426614174005', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Sustainable development' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid4: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174006', + uuid: 'ITEM4567-e89b-12d3-a456-426614174006', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Reply to Critics' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid5: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174007', + uuid: 'ITEM4567-e89b-12d3-a456-426614174007', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'PROGETTAZIONE, SINTESI E VALUTAZIONE DELL\u0027ATTIVITA\u0027 ANTIMICOBATTERICA ED ANTIFUNGINA DI NUOVI DERIVATI ETEROCICLICI' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid6: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174008', + uuid: 'ITEM4567-e89b-12d3-a456-426614174008', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Donald Davidson' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +const ItemMockPid7: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174009', + uuid: 'ITEM4567-e89b-12d3-a456-426614174009', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Missing abstract article' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +export const ItemMockPid8: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174002', + uuid: 'ITEM4567-e89b-12d3-a456-426614174002', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Egypt, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +export const ItemMockPid9: Item = Object.assign( + new Item(), + { + handle: '10077/21486', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'ITEM4567-e89b-12d3-a456-426614174003', + uuid: 'ITEM4567-e89b-12d3-a456-426614174003', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Morocco, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +export const ItemMockPid10: Item = Object.assign( + new Item(), + { + handle: '10713/29832', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'P23e4567-e89b-12d3-a456-426614174002', + uuid: 'P23e4567-e89b-12d3-a456-426614174002', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Tracking Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +export const OpenaireMockDspaceObject: SearchResult = Object.assign( + new SearchResult(), + { + handle: '10713/29832', + lastModified: '2017-04-24T19:44:08.178+0000', + isArchived: true, + isDiscoverable: true, + isWithdrawn: false, + _links:{ + self: { + href: 'https://rest.api/rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, + id: 'P23e4567-e89b-12d3-a456-426614174002', + uuid: 'P23e4567-e89b-12d3-a456-426614174002', + type: 'item', + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Tracking Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + } + } +); + +// Topics +// ------------------------------------------------------------------------------- + +export const openaireBrokerTopicObjectMorePid: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MORE!PID', + name: 'ENRICH/MORE/PID', + lastEvent: '2020/10/09 10:11 UTC', + totalEvents: 33, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MORE!PID' + } + } +}; + +export const openaireBrokerTopicObjectMoreAbstract: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MORE!ABSTRACT', + name: 'ENRICH/MORE/ABSTRACT', + lastEvent: '2020/09/08 21:14 UTC', + totalEvents: 5, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MORE!ABSTRACT' + } + } +}; + +export const openaireBrokerTopicObjectMissingPid: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MISSING!PID', + name: 'ENRICH/MISSING/PID', + lastEvent: '2020/10/01 07:36 UTC', + totalEvents: 4, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MISSING!PID' + } + } +}; + +export const openaireBrokerTopicObjectMissingAbstract: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MISSING!ABSTRACT', + name: 'ENRICH/MISSING/ABSTRACT', + lastEvent: '2020/10/08 16:14 UTC', + totalEvents: 71, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MISSING!ABSTRACT' + } + } +}; + +export const openaireBrokerTopicObjectMissingAcm: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MISSING!SUBJECT!ACM', + name: 'ENRICH/MISSING/SUBJECT/ACM', + lastEvent: '2020/09/21 17:51 UTC', + totalEvents: 18, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MISSING!SUBJECT!ACM' + } + } +}; + +export const openaireBrokerTopicObjectMissingProject: OpenaireBrokerTopicObject = { + type: new ResourceType('nbtopic'), + id: 'ENRICH!MISSING!PROJECT', + name: 'ENRICH/MISSING/PROJECT', + lastEvent: '2020/09/17 10:28 UTC', + totalEvents: 6, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbtopics/ENRICH!MISSING!PROJECT' + } + } +}; + +// Events +// ------------------------------------------------------------------------------- + +export const openaireBrokerEventObjectMissingPid: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174001', + uuid: '123e4567-e89b-12d3-a456-426614174001', + type: new ResourceType('nbevent'), + originalId: 'oai:www.openstarts.units.it:10077/21486', + title: 'Index nominum et rerum', + trust: 0.375, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'doi', + value: '10.18848/1447-9494/cgp/v15i09/45934', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174001', + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174001/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174001/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid1)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingPid2: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174004', + uuid: '123e4567-e89b-12d3-a456-426614174004', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/21486', + title: 'UNA NUOVA RILETTURA DELL\u0027 ARISTOTELE DI FRANZ BRENTANO ALLA LUCE DI ALCUNI INEDITI', + trust: 1.0, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'urn', + value: 'http://thesis2.sba.units.it/store/handle/item/12238', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174004' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174004/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174004/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid2)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingPid3: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174005', + uuid: '123e4567-e89b-12d3-a456-426614174005', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/554', + title: 'Sustainable development', + trust: 0.375, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'doi', + value: '10.4324/9780203408889', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174005' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174005/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174005/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid3)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingPid4: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174006', + uuid: '123e4567-e89b-12d3-a456-426614174006', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/10787', + title: 'Reply to Critics', + trust: 1.0, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'doi', + value: '10.1080/13698230.2018.1430104', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174006' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174006/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174006/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid4)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingPid5: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174007', + uuid: '123e4567-e89b-12d3-a456-426614174007', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/11339', + title: 'PROGETTAZIONE, SINTESI E VALUTAZIONE DELL\u0027ATTIVITA\u0027 ANTIMICOBATTERICA ED ANTIFUNGINA DI NUOVI DERIVATI ETEROCICLICI', + trust: 0.375, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'urn', + value: 'http://thesis2.sba.units.it/store/handle/item/12477', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174007' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174007/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174007/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid5)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingPid6: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174008', + uuid: '123e4567-e89b-12d3-a456-426614174008', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/29860', + title: 'Donald Davidson', + trust: 0.375, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: 'doi', + value: '10.1111/j.1475-4975.2004.00098.x', + abstract: null, + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174008' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174008/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174008/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid6)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingAbstract: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174009', + uuid: '123e4567-e89b-12d3-a456-426614174009', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/21110', + title: 'Missing abstract article', + trust: 0.751, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: null, + value: null, + abstract: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque vestibulum tellus sed lacinia. Aenean vitae sapien a quam congue ultrices. Sed vehicula sollicitudin ligula, vitae lacinia velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque vestibulum tellus sed lacinia. Aenean vitae sapien a quam congue ultrices. Sed vehicula sollicitudin ligula, vitae lacinia velit.', + openaireId: null, + acronym: null, + code: null, + funder: null, + fundingProgram: null, + jurisdiction: null, + title: null + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174009' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174009/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174009/related' + } + }, + target: observableOf(createSuccessfulRemoteDataObject(ItemMockPid7)), + related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) +}; + +export const openaireBrokerEventObjectMissingProjectFound: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174002', + uuid: '123e4567-e89b-12d3-a456-426614174002', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/21838', + title: 'Egypt, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature', + trust: 1.0, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: null, + value: null, + abstract: null, + openaireId: null, + acronym: 'PAThs', + code: '687567', + funder: 'EC', + fundingProgram: 'H2020', + jurisdiction: 'EU', + title: 'Tracking Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174002' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174002/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174002/related' + } + }, + target: createSuccessfulRemoteDataObject$(ItemMockPid8), + related: createSuccessfulRemoteDataObject$(ItemMockPid10) +}; + +export const openaireBrokerEventObjectMissingProjectNotFound: OpenaireBrokerEventObject = { + id: '123e4567-e89b-12d3-a456-426614174003', + uuid: '123e4567-e89b-12d3-a456-426614174003', + type: new ResourceType('openaireBrokerEvent'), + originalId: 'oai:www.openstarts.units.it:10077/21838', + title: 'Morocco, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature', + trust: 1.0, + eventDate: '2020/10/09 10:11 UTC', + status: 'PENDING', + message: { + type: null, + value: null, + abstract: null, + openaireId: null, + acronym: 'PAThs', + code: '687567B', + funder: 'EC', + fundingProgram: 'H2021', + jurisdiction: 'EU', + title: 'Tracking Unknown Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' + }, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174003' + }, + target: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174003/target' + }, + related: { + href: 'https://rest.api/rest/api/integration/nbevents/123e4567-e89b-12d3-a456-426614174003/related' + } + }, + target: createSuccessfulRemoteDataObject$(ItemMockPid9), + related: createNoContentRemoteDataObject$() +}; + +// Classes +// ------------------------------------------------------------------------------- + +/** + * Mock for [[OpenaireStateService]] + */ +export function getMockOpenaireStateService(): any { + return jasmine.createSpyObj('OpenaireStateService', { + getOpenaireBrokerTopics: jasmine.createSpy('getOpenaireBrokerTopics'), + isOpenaireBrokerTopicsLoading: jasmine.createSpy('isOpenaireBrokerTopicsLoading'), + isOpenaireBrokerTopicsLoaded: jasmine.createSpy('isOpenaireBrokerTopicsLoaded'), + isOpenaireBrokerTopicsProcessing: jasmine.createSpy('isOpenaireBrokerTopicsProcessing'), + getOpenaireBrokerTopicsTotalPages: jasmine.createSpy('getOpenaireBrokerTopicsTotalPages'), + getOpenaireBrokerTopicsCurrentPage: jasmine.createSpy('getOpenaireBrokerTopicsCurrentPage'), + getOpenaireBrokerTopicsTotals: jasmine.createSpy('getOpenaireBrokerTopicsTotals'), + dispatchRetrieveOpenaireBrokerTopics: jasmine.createSpy('dispatchRetrieveOpenaireBrokerTopics'), + dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') + }); +} + +/** + * Mock for [[OpenaireBrokerTopicRestService]] + */ +export function getMockOpenaireBrokerTopicRestService(): OpenaireBrokerTopicRestService { + return jasmine.createSpyObj('OpenaireBrokerTopicRestService', { + getTopics: jasmine.createSpy('getTopics'), + getTopic: jasmine.createSpy('getTopic'), + }); +} + +/** + * Mock for [[OpenaireBrokerEventRestService]] + */ +export function getMockOpenaireBrokerEventRestService(): OpenaireBrokerEventRestService { + return jasmine.createSpyObj('OpenaireBrokerEventRestService', { + getEventsByTopic: jasmine.createSpy('getEventsByTopic'), + getEvent: jasmine.createSpy('getEvent'), + patchEvent: jasmine.createSpy('patchEvent'), + boundProject: jasmine.createSpy('boundProject'), + removeProject: jasmine.createSpy('removeProject'), + clearFindByTopicRequests: jasmine.createSpy('.clearFindByTopicRequests') + }); +} + +/** + * Mock for [[OpenaireBrokerEventRestService]] + */ +export function getMockSuggestionsService(): any { + return jasmine.createSpyObj('SuggestionsService', { + getTargets: jasmine.createSpy('getTargets'), + getSuggestions: jasmine.createSpy('getSuggestions'), + clearSuggestionRequests: jasmine.createSpy('clearSuggestionRequests'), + deleteReviewedSuggestion: jasmine.createSpy('deleteReviewedSuggestion'), + retrieveCurrentUserSuggestions: jasmine.createSpy('retrieveCurrentUserSuggestions'), + getTargetUuid: jasmine.createSpy('getTargetUuid'), + }); +} diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 2a9aa1a062..e980e73313 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -11,8 +11,10 @@
- - + + + +
diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 8f1c6bf26f..50210c4794 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -93,6 +93,11 @@ export class PaginationComponent implements OnDestroy, OnInit { */ @Input() public hideGear = false; + /** + * Option for hiding the gear + */ + @Input() public hideSortOptions = false; + /** * Option for hiding the pager when there is less than 2 pages */ diff --git a/src/app/shared/selector.util.ts b/src/app/shared/selector.util.ts new file mode 100644 index 0000000000..2343e12f1a --- /dev/null +++ b/src/app/shared/selector.util.ts @@ -0,0 +1,27 @@ +import { createSelector, MemoizedSelector, Selector } from '@ngrx/store'; +import { hasValue } from './empty.util'; + +/** + * Export a function to return a subset of the state by key + */ +export function keySelector(parentSelector: Selector, subState: string, key: string): MemoizedSelector { + return createSelector(parentSelector, (state: T) => { + if (hasValue(state) && hasValue(state[subState])) { + return state[subState][key]; + } else { + return undefined; + } + }); +} +/** + * Export a function to return a subset of the state + */ +export function subStateSelector(parentSelector: Selector, subState: string): MemoizedSelector { + return createSelector(parentSelector, (state: T) => { + if (hasValue(state) && hasValue(state[subState])) { + return state[subState]; + } else { + return undefined; + } + }); +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f742273edb..360e50790a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -479,7 +479,13 @@ "admin.access-control.groups.form.return": "Back", + "admin.notifications.openairebroker.breadcrumbs": "OpenAIRE Broker", + "admin.notifications.openairebroker.page.title": "OpenAIRE Broker", + + "admin.notifications.openaireevent.breadcrumbs": "OpenAIRE Broker Suggestions", + + "admin.notifications.openaireevent.page.title": "OpenAIRE Broker Suggestions", "admin.search.breadcrumbs": "Administrative Search", @@ -2408,6 +2414,7 @@ + "menu.header.admin": "Management", "menu.header.image.logo": "Repository logo", @@ -2510,6 +2517,8 @@ "menu.section.icon.unpin": "Unpin sidebar", + "menu.section.icon.notifications": "Notifications menu section", + "menu.section.import": "Import", @@ -2533,6 +2542,12 @@ "menu.section.new_process": "Process", + "menu.section.notifications": "Notifications", + + "menu.section.notifications_openaire_broker": "OpenAIRE Broker", + + "menu.section.notifications_reciter": "Publication Claim", + "menu.section.pin": "Pin sidebar", @@ -2698,6 +2713,126 @@ "none.listelement.badge": "Item", + "openaire.broker.title": "OpenAIRE Broker", + + "openaire.broker.topics.description": "Below you can see all the topics received from the subscriptions to OpenAIRE.", + + "openaire.broker.topics": "Current Topics", + + "openaire.broker.table.topic": "Topic", + + "openaire.broker.table.last-event": "Last Event", + + "openaire.broker.table.actions": "Actions", + + "openaire.broker.button.detail": "Show details", + + "openaire.broker.noTopics": "No topics found.", + + "openaire.broker.topic.error.service.retrieve": "An error occurred while loading the OpenAIRE Broker topics", + + "openaire.broker.loading": "Loading ...", + + "openaire.events.title": "OpenAIRE Broker Suggestions", + + "openaire.broker.events.description": "Below the list of all the suggestions, received from OpenAIRE, for the selected topic.", + + "openaire.broker.events.topic": "Topic:", + + "openaire.broker.noEvents": "No suggestions found.", + + "openaire.broker.event.table.trust": "Trust", + + "openaire.broker.event.table.publication": "Publication", + + "openaire.broker.event.table.details": "Details", + + "openaire.broker.event.table.project-details": "Project details", + + "openaire.broker.event.table.actions": "Actions", + + "openaire.broker.event.action.accept": "Accept suggestion", + + "openaire.broker.event.action.ignore": "Ignore suggestion", + + "openaire.broker.event.action.reject": "Reject suggestion", + + "openaire.broker.event.action.import": "Import project and accept suggestion", + + "openaire.broker.event.table.pidtype": "PID Type:", + + "openaire.broker.event.table.pidvalue": "PID Value:", + + "openaire.broker.event.table.subjectValue": "Subject Value:", + + "openaire.broker.event.table.abstract": "Abstract:", + + "openaire.broker.event.table.suggestedProject": "OpenAIRE Suggested Project data", + + "openaire.broker.event.table.project": "Project title:", + + "openaire.broker.event.table.acronym": "Acronym:", + + "openaire.broker.event.table.code": "Code:", + + "openaire.broker.event.table.funder": "Funder:", + + "openaire.broker.event.table.fundingProgram": "Funding program:", + + "openaire.broker.event.table.jurisdiction": "Jurisdiction:", + + "openaire.broker.events.back": "Back to topics", + + "openaire.broker.event.table.less": "Show less", + + "openaire.broker.event.table.more": "Show more", + + "openaire.broker.event.project.found": "Bound to the local record:", + + "openaire.broker.event.project.notFound": "No local record found", + + "openaire.broker.event.sure": "Are you sure?", + + "openaire.broker.event.ignore.description": "This operation can't be undone. Ignore this suggestion?", + + "openaire.broker.event.reject.description": "This operation can't be undone. Reject this suggestion?", + + "openaire.broker.event.accept.description": "No DSpace project selected. A new project will be created based on the suggestion data.", + + "openaire.broker.event.action.cancel": "Cancel", + + "openaire.broker.event.action.saved": "Your decision has been saved successfully.", + + "openaire.broker.event.action.error": "An error has occurred. Your decision has not been saved.", + + "openaire.broker.event.modal.project.title": "Choose a project to bound", + + "openaire.broker.event.modal.project.publication": "Publication:", + + "openaire.broker.event.modal.project.bountToLocal": "Bound to the local record:", + + "openaire.broker.event.modal.project.select": "Project search", + + "openaire.broker.event.modal.project.search": "Search", + + "openaire.broker.event.modal.project.clear": "Clear", + + "openaire.broker.event.modal.project.cancel": "Cancel", + + "openaire.broker.event.modal.project.bound": "Bound project", + + "openaire.broker.event.modal.project.placeholder": "Enter a project name", + + "openaire.broker.event.modal.project.notFound": "No project found.", + + "openaire.broker.event.project.bounded": "The project has been linked successfully.", + + "openaire.broker.event.project.removed": "The project has been successfully unlinked.", + + "openaire.broker.event.project.error": "An error has occurred. No operation performed.", + + "openaire.broker.event.reason": "Reason", + "orgunit.listelement.badge": "Organizational Unit", @@ -3362,7 +3497,9 @@ "search.filters.filter.submitter.label": "Search submitter", + "search.filters.filter.funding.head": "Funding", + "search.filters.filter.funding.placeholder": "Funding", "search.filters.entityType.JournalIssue": "Journal Issue", From 4ca51387d1e60b7068eeed2f13ed105922a15455 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 18 Feb 2022 19:01:30 +0100 Subject: [PATCH 002/153] [CST-5246] Correction service should support multiple providers --- ...ications-broker-events-page.component.html | 1 + ...tions-broker-events-page.component.spec.ts | 26 ++++ ...ifications-broker-events-page.component.ts | 9 ++ ...ifications-broker-events-page.resolver.ts} | 8 +- ...ns-broker-topics-page-resolver.service.ts} | 8 +- ...ications-broker-topics-page.component.html | 1 + ...tions-broker-topics-page.component.spec.ts | 26 ++++ ...ifications-broker-topics-page.component.ts | 9 ++ ...ations-openaire-events-page.component.html | 1 - ...ons-openaire-events-page.component.spec.ts | 26 ---- ...ications-openaire-events-page.component.ts | 9 -- ...ations-openaire-topics-page.component.html | 1 - ...ons-openaire-topics-page.component.spec.ts | 26 ---- ...ications-openaire-topics-page.component.ts | 9 -- .../admin-notifications-routing-paths.ts | 4 +- .../admin-notifications-routing.module.ts | 28 ++-- .../admin-notifications.module.ts | 12 +- .../admin-sidebar/admin-sidebar.component.ts | 4 +- src/app/core/core.module.ts | 8 +- ...cations-broker-event-rest.service.spec.ts} | 54 ++++---- ...otifications-broker-event-rest.service.ts} | 56 ++++---- ...ions-broker-event-object.resource-type.ts} | 4 +- .../notifications-broker-event.model.ts} | 49 ++++--- ...ions-broker-topic-object.resource-type.ts} | 4 +- .../notifications-broker-topic.model.ts} | 16 +-- ...cations-broker-topic-rest.service.spec.ts} | 28 ++-- ...otifications-broker-topic-rest.service.ts} | 38 ++--- ...otifications-broker-events.component.html} | 94 ++++++------- ...fications-broker-events.component.spec.ts} | 114 +++++++-------- .../notifications-broker-events.component.ts} | 130 +++++++++--------- ...tifications-broker-events.scomponent.scss} | 0 .../project-entry-import-modal.component.html | 0 .../project-entry-import-modal.component.scss | 0 ...oject-entry-import-modal.component.spec.ts | 20 +-- .../project-entry-import-modal.component.ts | 29 ++-- .../notifications-broker-topics.actions.ts} | 30 ++-- ...otifications-broker-topics.component.html} | 22 +-- ...otifications-broker-topics.component.scss} | 0 ...fications-broker-topics.component.spec.ts} | 66 ++++----- .../notifications-broker-topics.component.ts} | 54 ++++---- .../notifications-broker-topics.effects.ts} | 38 ++--- ...otifications-broker-topics.reducer.spec.ts | 68 +++++++++ .../notifications-broker-topics.reducer.ts | 72 ++++++++++ ...tifications-broker-topics.service.spec.ts} | 34 ++--- .../notifications-broker-topics.service.ts | 55 ++++++++ .../notifications-state.service.spec.ts} | 112 +++++++-------- .../notifications-state.service.ts | 116 ++++++++++++++++ .../notifications/notifications.effects.ts | 5 + .../notifications.module.ts} | 34 ++--- .../notifications/notifications.reducer.ts | 16 +++ src/app/notifications/selectors.ts | 79 +++++++++++ .../openaire-broker-topics.reducer.spec.ts | 68 --------- .../topics/openaire-broker-topics.reducer.ts | 72 ---------- .../topics/openaire-broker-topics.service.ts | 55 -------- src/app/openaire/openaire-state.service.ts | 116 ---------------- src/app/openaire/openaire.effects.ts | 5 - src/app/openaire/openaire.reducer.ts | 16 --- src/app/openaire/selectors.ts | 79 ----------- ...openaire.mock.ts => notifications.mock.ts} | 94 ++++++------- src/assets/i18n/en.json5 | 130 +++++++++--------- 60 files changed, 1150 insertions(+), 1138 deletions(-) create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts rename src/app/admin/admin-notifications/{admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts => admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts} (72%) rename src/app/admin/admin-notifications/{admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts => admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts} (72%) create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts rename src/app/core/{openaire/broker/events/openaire-broker-event-rest.service.spec.ts => notifications/broker/events/notifications-broker-event-rest.service.spec.ts} (78%) rename src/app/core/{openaire/broker/events/openaire-broker-event-rest.service.ts => notifications/broker/events/notifications-broker-event-rest.service.ts} (73%) rename src/app/core/{openaire/broker/models/openaire-broker-event-object.resource-type.ts => notifications/broker/models/notifications-broker-event-object.resource-type.ts} (53%) rename src/app/core/{openaire/broker/models/openaire-broker-event.model.ts => notifications/broker/models/notifications-broker-event.model.ts} (61%) rename src/app/core/{openaire/broker/models/openaire-broker-topic-object.resource-type.ts => notifications/broker/models/notifications-broker-topic-object.resource-type.ts} (53%) rename src/app/core/{openaire/broker/models/openaire-broker-topic.model.ts => notifications/broker/models/notifications-broker-topic.model.ts} (64%) rename src/app/core/{openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts => notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts} (77%) rename src/app/core/{openaire/broker/topics/openaire-broker-topic-rest.service.ts => notifications/broker/topics/notifications-broker-topic-rest.service.ts} (75%) rename src/app/{openaire/broker/events/openaire-broker-events.component.html => notifications/broker/events/notifications-broker-events.component.html} (60%) rename src/app/{openaire/broker/events/openaire-broker-events.component.spec.ts => notifications/broker/events/notifications-broker-events.component.spec.ts} (66%) rename src/app/{openaire/broker/events/openaire-broker-events.component.ts => notifications/broker/events/notifications-broker-events.component.ts} (71%) rename src/app/{openaire/broker/events/openaire-broker-events.scomponent.scss => notifications/broker/events/notifications-broker-events.scomponent.scss} (100%) rename src/app/{openaire => notifications}/broker/project-entry-import-modal/project-entry-import-modal.component.html (100%) rename src/app/{openaire => notifications}/broker/project-entry-import-modal/project-entry-import-modal.component.scss (100%) rename src/app/{openaire => notifications}/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts (92%) rename src/app/{openaire => notifications}/broker/project-entry-import-modal/project-entry-import-modal.component.ts (89%) rename src/app/{openaire/broker/topics/openaire-broker-topics.actions.ts => notifications/broker/topics/notifications-broker-topics.actions.ts} (60%) rename src/app/{openaire/broker/topics/openaire-broker-topics.component.html => notifications/broker/topics/notifications-broker-topics.component.html} (66%) rename src/app/{openaire/broker/topics/openaire-broker-topics.component.scss => notifications/broker/topics/notifications-broker-topics.component.scss} (100%) rename src/app/{openaire/broker/topics/openaire-broker-topics.component.spec.ts => notifications/broker/topics/notifications-broker-topics.component.spec.ts} (53%) rename src/app/{openaire/broker/topics/openaire-broker-topics.component.ts => notifications/broker/topics/notifications-broker-topics.component.ts} (60%) rename src/app/{openaire/broker/topics/openaire-broker-topics.effects.ts => notifications/broker/topics/notifications-broker-topics.effects.ts} (57%) create mode 100644 src/app/notifications/broker/topics/notifications-broker-topics.reducer.spec.ts create mode 100644 src/app/notifications/broker/topics/notifications-broker-topics.reducer.ts rename src/app/{openaire/broker/topics/openaire-broker-topics.service.spec.ts => notifications/broker/topics/notifications-broker-topics.service.spec.ts} (56%) create mode 100644 src/app/notifications/broker/topics/notifications-broker-topics.service.ts rename src/app/{openaire/openaire-state.service.spec.ts => notifications/notifications-state.service.spec.ts} (59%) create mode 100644 src/app/notifications/notifications-state.service.ts create mode 100644 src/app/notifications/notifications.effects.ts rename src/app/{openaire/openaire.module.ts => notifications/notifications.module.ts} (50%) create mode 100644 src/app/notifications/notifications.reducer.ts create mode 100644 src/app/notifications/selectors.ts delete mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.reducer.spec.ts delete mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.reducer.ts delete mode 100644 src/app/openaire/broker/topics/openaire-broker-topics.service.ts delete mode 100644 src/app/openaire/openaire-state.service.ts delete mode 100644 src/app/openaire/openaire.effects.ts delete mode 100644 src/app/openaire/openaire.reducer.ts delete mode 100644 src/app/openaire/selectors.ts rename src/app/shared/mocks/{openaire.mock.ts => notifications.mock.ts} (92%) diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html new file mode 100644 index 0000000000..89ef1bfc88 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts new file mode 100644 index 0000000000..57a79e017b --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page.component'; + +describe('AdminNotificationsBrokerEventsPageComponent', () => { + let component: AdminNotificationsBrokerEventsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminNotificationsBrokerEventsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminNotificationsBrokerEventsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminNotificationsBrokerEventsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts new file mode 100644 index 0000000000..f014b4d133 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notifications-broker-events-page', + templateUrl: './admin-notifications-broker-events-page.component.html' +}) +export class AdminNotificationsBrokerEventsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts similarity index 72% rename from src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts rename to src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts index b215013e11..dcf530858c 100644 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver.ts +++ b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts @@ -4,7 +4,7 @@ import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsOpenaireEventsPageParams { +export interface AdminNotificationsBrokerEventsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,15 +14,15 @@ export interface AdminNotificationsOpenaireEventsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsOpenaireEventsPageResolver implements Resolve { +export class AdminNotificationsBrokerEventsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns AdminNotificationsOpenaireEventsPageParams Emits the route parameters + * @returns AdminNotificationsBrokerEventsPageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsOpenaireEventsPageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsBrokerEventsPageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts similarity index 72% rename from src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts rename to src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts index f8e02cabbf..d4fd354d92 100644 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsOpenaireTopicsPageParams { +export interface AdminNotificationsBrokerTopicsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,15 +14,15 @@ export interface AdminNotificationsOpenaireTopicsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsOpenaireTopicsPageResolver implements Resolve { +export class AdminNotificationsBrokerTopicsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns AdminNotificationsOpenaireTopicsPageParams Emits the route parameters + * @returns AdminNotificationsBrokerTopicsPageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsOpenaireTopicsPageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsBrokerTopicsPageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html new file mode 100644 index 0000000000..dbdae2e6b9 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts new file mode 100644 index 0000000000..c21e0ce73b --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page.component'; + +describe('AdminNotificationsBrokerTopicsPageComponent', () => { + let component: AdminNotificationsBrokerTopicsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminNotificationsBrokerTopicsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminNotificationsBrokerTopicsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminNotificationsBrokerTopicsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts new file mode 100644 index 0000000000..4f60ffd3fd --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notification-broker-page', + templateUrl: './admin-notifications-broker-topics-page.component.html' +}) +export class AdminNotificationsBrokerTopicsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html deleted file mode 100644 index 5c8f8820a0..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts deleted file mode 100644 index ab7a08a695..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page.component'; - -describe('AdminNotificationsOpenaireEventsPageComponent', () => { - let component: AdminNotificationsOpenaireEventsPageComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AdminNotificationsOpenaireEventsPageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsOpenaireEventsPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminNotificationsOpenaireEventsPageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts deleted file mode 100644 index df7b21dbda..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ds-notification-openaire-events-page', - templateUrl: './admin-notifications-openaire-events-page.component.html' -}) -export class AdminNotificationsOpenaireEventsPageComponent { - -} diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html deleted file mode 100644 index b1616cfe78..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts deleted file mode 100644 index 712c7ba2c3..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page.component'; - -describe('AdminNotificationsOpenaireTopicsPageComponent', () => { - let component: AdminNotificationsOpenaireTopicsPageComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AdminNotificationsOpenaireTopicsPageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsOpenaireTopicsPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminNotificationsOpenaireTopicsPageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts deleted file mode 100644 index 5bf1832c59..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ds-notification-openairebroker-page', - templateUrl: './admin-notifications-openaire-topics-page.component.html' -}) -export class AdminNotificationsOpenaireTopicsPageComponent { - -} diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts index ea7242adcb..469cbb980f 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -1,8 +1,8 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { getNotificationsModuleRoute } from '../admin-routing-paths'; -export const NOTIFICATIONS_EDIT_PATH = 'openaire-broker'; +export const NOTIFICATIONS_EDIT_PATH = 'notifications-broker'; -export function getNotificationsOpenairebrokerRoute(id: string) { +export function getNotificationsBrokerbrokerRoute(id: string) { return new URLCombiner(getNotificationsModuleRoute(), NOTIFICATIONS_EDIT_PATH, id).toString(); } diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 2dfa938c4f..f1f46ca4f1 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -5,10 +5,10 @@ import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { NOTIFICATIONS_EDIT_PATH } from './admin-notifications-routing-paths'; -import { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component'; -import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component'; -import { AdminNotificationsOpenaireTopicsPageResolver } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page-resolver.service'; -import { AdminNotificationsOpenaireEventsPageResolver } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.resolver'; +import { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component'; +import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page/admin-notifications-broker-events-page.component'; +import { AdminNotificationsBrokerTopicsPageResolver } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service'; +import { AdminNotificationsBrokerEventsPageResolver } from './admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver'; @NgModule({ imports: [ @@ -16,30 +16,30 @@ import { AdminNotificationsOpenaireEventsPageResolver } from './admin-notificati { canActivate: [ AuthenticatedGuard ], path: `${NOTIFICATIONS_EDIT_PATH}`, - component: AdminNotificationsOpenaireTopicsPageComponent, + component: AdminNotificationsBrokerTopicsPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerTopicsParams: AdminNotificationsOpenaireTopicsPageResolver + openaireBrokerTopicsParams: AdminNotificationsBrokerTopicsPageResolver }, data: { - title: 'admin.notifications.openairebroker.page.title', - breadcrumbKey: 'admin.notifications.openairebroker', + title: 'admin.notifications.broker.page.title', + breadcrumbKey: 'admin.notifications.broker', showBreadcrumbsFluid: false } }, { canActivate: [ AuthenticatedGuard ], path: `${NOTIFICATIONS_EDIT_PATH}/:id`, - component: AdminNotificationsOpenaireEventsPageComponent, + component: AdminNotificationsBrokerEventsPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerEventsParams: AdminNotificationsOpenaireEventsPageResolver + openaireBrokerEventsParams: AdminNotificationsBrokerEventsPageResolver }, data: { - title: 'admin.notifications.openaireevent.page.title', - breadcrumbKey: 'admin.notifications.openaireevent', + title: 'admin.notifications.event.page.title', + breadcrumbKey: 'admin.notifications.event', showBreadcrumbsFluid: false } } @@ -48,8 +48,8 @@ import { AdminNotificationsOpenaireEventsPageResolver } from './admin-notificati providers: [ I18nBreadcrumbResolver, I18nBreadcrumbsService, - AdminNotificationsOpenaireTopicsPageResolver, - AdminNotificationsOpenaireEventsPageResolver + AdminNotificationsBrokerTopicsPageResolver, + AdminNotificationsBrokerEventsPageResolver ] }) /** diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index 9894dac233..350e9de800 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -3,9 +3,9 @@ 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 { AdminNotificationsOpenaireTopicsPageComponent } from './admin-notifications-openaire-topics-page/admin-notifications-openaire-topics-page.component'; -import { AdminNotificationsOpenaireEventsPageComponent } from './admin-notifications-openaire-events-page/admin-notifications-openaire-events-page.component'; -import { OpenaireModule } from '../../openaire/openaire.module'; +import { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component'; +import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page/admin-notifications-broker-events-page.component'; +import { NotificationsModule } from '../../notifications/notifications.module'; @NgModule({ imports: [ @@ -13,11 +13,11 @@ import { OpenaireModule } from '../../openaire/openaire.module'; SharedModule, CoreModule.forRoot(), AdminNotificationsRoutingModule, - OpenaireModule + NotificationsModule ], declarations: [ - AdminNotificationsOpenaireTopicsPageComponent, - AdminNotificationsOpenaireEventsPageComponent + AdminNotificationsBrokerTopicsPageComponent, + AdminNotificationsBrokerEventsPageComponent ], entryComponents: [] }) diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.ts index a2a7eb30b5..3e989f16f3 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -483,8 +483,8 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { visible: authorized, model: { type: MenuItemType.LINK, - text: 'menu.section.notifications_openaire_broker', - link: '/admin/notifications/openaire-broker' + text: 'menu.section.notifications_broker', + link: '/admin/notifications/notifications-broker' } as LinkMenuItemModel, }, /* Admin Search */ diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 928d34c48e..f5a959592f 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -162,8 +162,8 @@ import { SearchConfig } from './shared/search/search-filters/search-config.model import { SequenceService } from './shared/sequence.service'; import { GroupDataService } from './eperson/group-data.service'; import { SubmissionAccessesModel } from './config/models/config-submission-accesses.model'; -import { OpenaireBrokerTopicObject } from './openaire/broker/models/openaire-broker-topic.model'; -import { OpenaireBrokerEventObject } from './openaire/broker/models/openaire-broker-event.model'; +import { NotificationsBrokerTopicObject } from './notifications/broker/models/notifications-broker-topic.model'; +import { NotificationsBrokerEventObject } from './notifications/broker/models/notifications-broker-event.model'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -345,8 +345,8 @@ export const models = ShortLivedToken, Registration, UsageReport, - OpenaireBrokerTopicObject, - OpenaireBrokerEventObject, + NotificationsBrokerTopicObject, + NotificationsBrokerEventObject, Root, SearchConfig, SubmissionAccessesModel diff --git a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts b/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts similarity index 78% rename from src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts rename to src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts index 2d0d236330..16d55479ae 100644 --- a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.spec.ts +++ b/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts @@ -15,17 +15,17 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { OpenaireBrokerEventRestService } from './openaire-broker-event-rest.service'; +import { NotificationsBrokerEventRestService } from './notifications-broker-event-rest.service'; import { - openaireBrokerEventObjectMissingPid, - openaireBrokerEventObjectMissingPid2, - openaireBrokerEventObjectMissingProjectFound -} from '../../../../shared/mocks/openaire.mock'; + notificationsBrokerEventObjectMissingPid, + notificationsBrokerEventObjectMissingPid2, + notificationsBrokerEventObjectMissingProjectFound +} from '../../../../shared/mocks/notifications.mock'; import { ReplaceOperation } from 'fast-json-patch'; -describe('OpenaireBrokerEventRestService', () => { +describe('NotificationsBrokerEventRestService', () => { let scheduler: TestScheduler; - let service: OpenaireBrokerEventRestService; + let service: NotificationsBrokerEventRestService; let serviceASAny: any; let responseCacheEntry: RequestEntry; let responseCacheEntryB: RequestEntry; @@ -43,10 +43,10 @@ describe('OpenaireBrokerEventRestService', () => { const topic = 'ENRICH!MORE!PID'; const pageInfo = new PageInfo(); - const array = [ openaireBrokerEventObjectMissingPid, openaireBrokerEventObjectMissingPid2 ]; + const array = [ notificationsBrokerEventObjectMissingPid, notificationsBrokerEventObjectMissingPid2 ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerEventObjectRD = createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingPid); - const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingProjectFound); + const brokerEventObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingPid); + const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingProjectFound); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); const status = 'ACCEPTED'; @@ -99,7 +99,7 @@ describe('OpenaireBrokerEventRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new OpenaireBrokerEventRestService( + service = new NotificationsBrokerEventRestService( requestService, rdbService, objectCache, @@ -138,7 +138,7 @@ describe('OpenaireBrokerEventRestService', () => { expect(serviceASAny.dataService.searchBy).toHaveBeenCalledWith('findByTopic', options, true, true); }); - it('should return a RemoteData> for the object with the given Topic', () => { + it('should return a RemoteData> for the object with the given Topic', () => { const result = service.getEventsByTopic(topic); const expected = cold('(a)', { a: paginatedListRD @@ -155,15 +155,15 @@ describe('OpenaireBrokerEventRestService', () => { }); it('should proxy the call to dataservice.findById', () => { - service.getEvent(openaireBrokerEventObjectMissingPid.id).subscribe( + service.getEvent(notificationsBrokerEventObjectMissingPid.id).subscribe( (res) => { - expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(openaireBrokerEventObjectMissingPid.id, true, true); + expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingPid.id, true, true); } ); }); - it('should return a RemoteData for the object with the given URL', () => { - const result = service.getEvent(openaireBrokerEventObjectMissingPid.id); + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getEvent(notificationsBrokerEventObjectMissingPid.id); const expected = cold('(a)', { a: brokerEventObjectRD }); @@ -179,17 +179,17 @@ describe('OpenaireBrokerEventRestService', () => { }); it('should proxy the call to dataservice.patch', () => { - service.patchEvent(status, openaireBrokerEventObjectMissingPid).subscribe( + service.patchEvent(status, notificationsBrokerEventObjectMissingPid).subscribe( (res) => { - expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(openaireBrokerEventObjectMissingPid, operation); + expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingPid, operation); } ); }); it('should return a RemoteData with HTTP 200', () => { - const result = service.patchEvent(status, openaireBrokerEventObjectMissingPid); + const result = service.patchEvent(status, notificationsBrokerEventObjectMissingPid); const expected = cold('(a|)', { - a: createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingPid) + a: createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingPid) }); expect(result).toBeObservable(expected); }); @@ -203,17 +203,17 @@ describe('OpenaireBrokerEventRestService', () => { }); it('should proxy the call to dataservice.postOnRelated', () => { - service.boundProject(openaireBrokerEventObjectMissingProjectFound.id, requestUUID).subscribe( + service.boundProject(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID).subscribe( (res) => { - expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(openaireBrokerEventObjectMissingProjectFound.id, requestUUID); + expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID); } ); }); it('should return a RestResponse with HTTP 201', () => { - const result = service.boundProject(openaireBrokerEventObjectMissingProjectFound.id, requestUUID); + const result = service.boundProject(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID); const expected = cold('(a|)', { - a: createSuccessfulRemoteDataObject(openaireBrokerEventObjectMissingProjectFound) + a: createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingProjectFound) }); expect(result).toBeObservable(expected); }); @@ -227,15 +227,15 @@ describe('OpenaireBrokerEventRestService', () => { }); it('should proxy the call to dataservice.deleteOnRelated', () => { - service.removeProject(openaireBrokerEventObjectMissingProjectFound.id).subscribe( + service.removeProject(notificationsBrokerEventObjectMissingProjectFound.id).subscribe( (res) => { - expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(openaireBrokerEventObjectMissingProjectFound.id); + expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingProjectFound.id); } ); }); it('should return a RestResponse with HTTP 204', () => { - const result = service.removeProject(openaireBrokerEventObjectMissingProjectFound.id); + const result = service.removeProject(notificationsBrokerEventObjectMissingProjectFound.id); const expected = cold('(a|)', { a: createSuccessfulRemoteDataObject({}) }); diff --git a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts b/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts similarity index 73% rename from src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts rename to src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts index 6e944c8038..7f4761009d 100644 --- a/src/app/core/openaire/broker/events/openaire-broker-event-rest.service.ts +++ b/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts @@ -17,8 +17,8 @@ import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; -import { OpenaireBrokerEventObject } from '../models/openaire-broker-event.model'; -import { OPENAIRE_BROKER_EVENT_OBJECT } from '../models/openaire-broker-event-object.resource-type'; +import { NotificationsBrokerEventObject } from '../models/notifications-broker-event.model'; +import { NOTIFICATIONS_BROKER_EVENT_OBJECT } from '../models/notifications-broker-event-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; import { ReplaceOperation } from 'fast-json-patch'; @@ -29,7 +29,7 @@ import { NoContent } from '../../../shared/NoContent.model'; /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class DataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -44,7 +44,7 @@ class DataServiceImpl extends DataService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator + * @param {ChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -54,17 +54,17 @@ class DataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { + protected comparator: ChangeAnalyzer) { super(); } } /** - * The service handling all OpenAIRE Broker topic REST requests. + * The service handling all Notifications Broker topic REST requests. */ @Injectable() -@dataService(OPENAIRE_BROKER_EVENT_OBJECT) -export class OpenaireBrokerEventRestService { +@dataService(NOTIFICATIONS_BROKER_EVENT_OBJECT) +export class NotificationsBrokerEventRestService { /** * A private DataService implementation to delegate specific methods to. */ @@ -78,7 +78,7 @@ export class OpenaireBrokerEventRestService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator + * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -87,23 +87,23 @@ export class OpenaireBrokerEventRestService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { + protected comparator: DefaultChangeAnalyzer) { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** - * Return the list of OpenAIRE Broker events by topic. + * Return the list of Notifications Broker events by topic. * * @param topic - * The OpenAIRE Broker topic + * The Notifications Broker topic * @param options * Find list options object. * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of OpenAIRE Broker events. + * @return Observable>> + * The list of Notifications Broker events. */ - public getEventsByTopic(topic: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + public getEventsByTopic(topic: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { options.searchParams = [ { fieldName: 'topic', @@ -121,32 +121,32 @@ export class OpenaireBrokerEventRestService { } /** - * Return a single OpenAIRE Broker event. + * Return a single Notifications Broker event. * * @param id - * The OpenAIRE Broker event id + * The Notifications Broker event id * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - * @return Observable> - * The OpenAIRE Broker event. + * @return Observable> + * The Notifications Broker event. */ - public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { return this.dataService.findById(id, true, true, ...linksToFollow); } /** - * Save the new status of an OpenAIRE Broker event. + * Save the new status of a Notifications Broker event. * * @param status * The new status - * @param dso OpenaireBrokerEventObject + * @param dso NotificationsBrokerEventObject * The event item * @param reason * The optional reason (not used for now; for future implementation) * @return Observable * The REST response. */ - public patchEvent(status, dso, reason?: string): Observable> { + public patchEvent(status, dso, reason?: string): Observable> { const operation: ReplaceOperation[] = [ { path: '/status', @@ -158,24 +158,24 @@ export class OpenaireBrokerEventRestService { } /** - * Bound a project to an OpenAIRE Broker event publication. + * Bound a project to a Notifications Broker event publication. * * @param itemId - * The Id of the OpenAIRE Broker event + * The Id of the Notifications Broker event * @param projectId * The project Id to bound * @return Observable * The REST response. */ - public boundProject(itemId: string, projectId: string): Observable> { + public boundProject(itemId: string, projectId: string): Observable> { return this.dataService.postOnRelated(itemId, projectId); } /** - * Remove a project from an OpenAIRE Broker event publication. + * Remove a project from a Notifications Broker event publication. * * @param itemId - * The Id of the OpenAIRE Broker event + * The Id of the Notifications Broker event * @return Observable * The REST response. */ diff --git a/src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts b/src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts similarity index 53% rename from src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts rename to src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts index c0be0071eb..2493ae02d1 100644 --- a/src/app/core/openaire/broker/models/openaire-broker-event-object.resource-type.ts +++ b/src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts @@ -1,9 +1,9 @@ import { ResourceType } from '../../../shared/resource-type'; /** - * The resource type for the OpenAIRE Broker event + * The resource type for the Notifications Broker event * * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const OPENAIRE_BROKER_EVENT_OBJECT = new ResourceType('nbevent'); +export const NOTIFICATIONS_BROKER_EVENT_OBJECT = new ResourceType('nbevent'); diff --git a/src/app/core/openaire/broker/models/openaire-broker-event.model.ts b/src/app/core/notifications/broker/models/notifications-broker-event.model.ts similarity index 61% rename from src/app/core/openaire/broker/models/openaire-broker-event.model.ts rename to src/app/core/notifications/broker/models/notifications-broker-event.model.ts index 40c65412f5..ed73168e6d 100644 --- a/src/app/core/openaire/broker/models/openaire-broker-event.model.ts +++ b/src/app/core/notifications/broker/models/notifications-broker-event.model.ts @@ -1,7 +1,7 @@ import { Observable } from 'rxjs'; import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; import { CacheableObject } from '../../../cache/object-cache.reducer'; -import { OPENAIRE_BROKER_EVENT_OBJECT } from './openaire-broker-event-object.resource-type'; +import { NOTIFICATIONS_BROKER_EVENT_OBJECT } from './notifications-broker-event-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; @@ -11,85 +11,92 @@ import { link, typedObject } from '../../../cache/builders/build-decorators'; import { RemoteData } from '../../../data/remote-data'; /** - * The interface representing the OpenAIRE Broker event message + * The interface representing the Notifications Broker event message */ -export interface OpenaireBrokerEventMessageObject { +export interface NotificationsBrokerEventMessageObject { + +} + +/** + * The interface representing the Notifications Broker event message + */ +export interface OpenaireBrokerEventMessageObject{ /** * The type of 'value' */ type: string; /** - * The value suggested by OpenAIRE + * The value suggested by Notifications */ value: string; /** - * The abstract suggested by OpenAIRE + * The abstract suggested by Notifications */ abstract: string; /** - * The project acronym suggested by OpenAIRE + * The project acronym suggested by Notifications */ acronym: string; /** - * The project code suggested by OpenAIRE + * The project code suggested by Notifications */ code: string; /** - * The project funder suggested by OpenAIRE + * The project funder suggested by Notifications */ funder: string; /** - * The project program suggested by OpenAIRE + * The project program suggested by Notifications */ fundingProgram?: string; /** - * The project jurisdiction suggested by OpenAIRE + * The project jurisdiction suggested by Notifications */ jurisdiction: string; /** - * The project title suggested by OpenAIRE + * The project title suggested by Notifications */ title: string; /** - * The OpenAIRE ID. + * The OPENAIRE ID. */ openaireId: string; } /** - * The interface representing the OpenAIRE Broker event model + * The interface representing the Notifications Broker event model */ @typedObject -export class OpenaireBrokerEventObject implements CacheableObject { +export class NotificationsBrokerEventObject implements CacheableObject { /** * A string representing the kind of object, e.g. community, item, … */ - static type = OPENAIRE_BROKER_EVENT_OBJECT; + static type = NOTIFICATIONS_BROKER_EVENT_OBJECT; /** - * The OpenAIRE Broker event uuid inside DSpace + * The Notifications Broker event uuid inside DSpace */ @autoserialize id: string; /** - * The universally unique identifier of this OpenAIRE Broker event + * The universally unique identifier of this Notifications Broker event */ @autoserializeAs(String, 'id') uuid: string; /** - * The OpenAIRE Broker event original id (ex.: the source archive OAI-PMH identifier) + * The Notifications Broker event original id (ex.: the source archive OAI-PMH identifier) */ @autoserialize originalId: string; @@ -107,19 +114,19 @@ export class OpenaireBrokerEventObject implements CacheableObject { trust: number; /** - * The timestamp OpenAIRE Broker event was saved in DSpace + * The timestamp Notifications Broker event was saved in DSpace */ @autoserialize eventDate: string; /** - * The OpenAIRE Broker event status (ACCEPTED, REJECTED, DISCARDED, PENDING) + * The Notifications Broker event status (ACCEPTED, REJECTED, DISCARDED, PENDING) */ @autoserialize status: string; /** - * The suggestion data. Data may vary depending on the topic + * The suggestion data. Data may vary depending on the source */ @autoserialize message: OpenaireBrokerEventMessageObject; diff --git a/src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts b/src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts similarity index 53% rename from src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts rename to src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts index 58ceb4e671..e7012eee4f 100644 --- a/src/app/core/openaire/broker/models/openaire-broker-topic-object.resource-type.ts +++ b/src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts @@ -1,9 +1,9 @@ import { ResourceType } from '../../../shared/resource-type'; /** - * The resource type for the OpenAIRE Broker topic + * The resource type for the Notifications Broker topic * * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const OPENAIRE_BROKER_TOPIC_OBJECT = new ResourceType('nbtopic'); +export const NOTIFICATIONS_BROKER_TOPIC_OBJECT = new ResourceType('nbtopic'); diff --git a/src/app/core/openaire/broker/models/openaire-broker-topic.model.ts b/src/app/core/notifications/broker/models/notifications-broker-topic.model.ts similarity index 64% rename from src/app/core/openaire/broker/models/openaire-broker-topic.model.ts rename to src/app/core/notifications/broker/models/notifications-broker-topic.model.ts index 3f286e5fea..d1f2e6ff50 100644 --- a/src/app/core/openaire/broker/models/openaire-broker-topic.model.ts +++ b/src/app/core/notifications/broker/models/notifications-broker-topic.model.ts @@ -1,42 +1,42 @@ import { autoserialize, deserialize } from 'cerialize'; import { CacheableObject } from '../../../cache/object-cache.reducer'; -import { OPENAIRE_BROKER_TOPIC_OBJECT } from './openaire-broker-topic-object.resource-type'; +import { NOTIFICATIONS_BROKER_TOPIC_OBJECT } from './notifications-broker-topic-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; import { typedObject } from '../../../cache/builders/build-decorators'; /** - * The interface representing the OpenAIRE Broker topic model + * The interface representing the Notifications Broker topic model */ @typedObject -export class OpenaireBrokerTopicObject implements CacheableObject { +export class NotificationsBrokerTopicObject implements CacheableObject { /** * A string representing the kind of object, e.g. community, item, … */ - static type = OPENAIRE_BROKER_TOPIC_OBJECT; + static type = NOTIFICATIONS_BROKER_TOPIC_OBJECT; /** - * The OpenAIRE Broker topic id + * The Notifications Broker topic id */ @autoserialize id: string; /** - * The OpenAIRE Broker topic name to display + * The Notifications Broker topic name to display */ @autoserialize name: string; /** - * The date of the last udate from OpenAIRE + * The date of the last udate from Notifications */ @autoserialize lastEvent: string; /** - * The total number of suggestions provided by OpenAIRE for this topic + * The total number of suggestions provided by Notifications for this topic */ @autoserialize totalEvents: number; diff --git a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts b/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts similarity index 77% rename from src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts rename to src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts index 87aa0b42f0..06931e2032 100644 --- a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.spec.ts +++ b/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts @@ -14,15 +14,15 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { OpenaireBrokerTopicRestService } from './openaire-broker-topic-rest.service'; +import { NotificationsBrokerTopicRestService } from './notifications-broker-topic-rest.service'; import { - openaireBrokerTopicObjectMoreAbstract, - openaireBrokerTopicObjectMorePid -} from '../../../../shared/mocks/openaire.mock'; + notificationsBrokerTopicObjectMoreAbstract, + notificationsBrokerTopicObjectMorePid +} from '../../../../shared/mocks/notifications.mock'; -describe('OpenaireBrokerTopicRestService', () => { +describe('NotificationsBrokerTopicRestService', () => { let scheduler: TestScheduler; - let service: OpenaireBrokerTopicRestService; + let service: NotificationsBrokerTopicRestService; let responseCacheEntry: RequestEntry; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -36,9 +36,9 @@ describe('OpenaireBrokerTopicRestService', () => { const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); - const array = [ openaireBrokerTopicObjectMorePid, openaireBrokerTopicObjectMoreAbstract ]; + const array = [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerTopicObjectRD = createSuccessfulRemoteDataObject(openaireBrokerTopicObjectMorePid); + const brokerTopicObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerTopicObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); beforeEach(() => { @@ -72,7 +72,7 @@ describe('OpenaireBrokerTopicRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new OpenaireBrokerTopicRestService( + service = new NotificationsBrokerTopicRestService( requestService, rdbService, objectCache, @@ -96,7 +96,7 @@ describe('OpenaireBrokerTopicRestService', () => { done(); }); - it('should return a RemoteData> for the object with the given URL', () => { + it('should return a RemoteData> for the object with the given URL', () => { const result = service.getTopics(); const expected = cold('(a)', { a: paginatedListRD @@ -107,16 +107,16 @@ describe('OpenaireBrokerTopicRestService', () => { describe('getTopic', () => { it('should proxy the call to dataservice.findByHref', (done) => { - service.getTopic(openaireBrokerTopicObjectMorePid.id).subscribe( + service.getTopic(notificationsBrokerTopicObjectMorePid.id).subscribe( (res) => { - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + openaireBrokerTopicObjectMorePid.id, true, true); + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + notificationsBrokerTopicObjectMorePid.id, true, true); } ); done(); }); - it('should return a RemoteData for the object with the given URL', () => { - const result = service.getTopic(openaireBrokerTopicObjectMorePid.id); + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getTopic(notificationsBrokerTopicObjectMorePid.id); const expected = cold('(a)', { a: brokerTopicObjectRD }); diff --git a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts b/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts similarity index 75% rename from src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts rename to src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts index 3fe3917485..9f0b93cfb3 100644 --- a/src/app/core/openaire/broker/topics/openaire-broker-topic-rest.service.ts +++ b/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts @@ -17,8 +17,8 @@ import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; -import { OpenaireBrokerTopicObject } from '../models/openaire-broker-topic.model'; -import { OPENAIRE_BROKER_TOPIC_OBJECT } from '../models/openaire-broker-topic-object.resource-type'; +import { NotificationsBrokerTopicObject } from '../models/notifications-broker-topic.model'; +import { NOTIFICATIONS_BROKER_TOPIC_OBJECT } from '../models/notifications-broker-topic-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; @@ -27,7 +27,7 @@ import { PaginatedList } from '../../../data/paginated-list.model'; /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class DataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -42,7 +42,7 @@ class DataServiceImpl extends DataService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator + * @param {ChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -52,17 +52,17 @@ class DataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { + protected comparator: ChangeAnalyzer) { super(); } } /** - * The service handling all OpenAIRE Broker topic REST requests. + * The service handling all Notifications Broker topic REST requests. */ @Injectable() -@dataService(OPENAIRE_BROKER_TOPIC_OBJECT) -export class OpenaireBrokerTopicRestService { +@dataService(NOTIFICATIONS_BROKER_TOPIC_OBJECT) +export class NotificationsBrokerTopicRestService { /** * A private DataService implementation to delegate specific methods to. */ @@ -76,7 +76,7 @@ export class OpenaireBrokerTopicRestService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator + * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -85,21 +85,21 @@ export class OpenaireBrokerTopicRestService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { + protected comparator: DefaultChangeAnalyzer) { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** - * Return the list of OpenAIRE Broker topics. + * Return the list of Notifications Broker topics. * * @param options * Find list options object. * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of OpenAIRE Broker topics. + * @return Observable>> + * The list of Notifications Broker topics. */ - public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), @@ -114,16 +114,16 @@ export class OpenaireBrokerTopicRestService { } /** - * Return a single OpenAIRE Broker topic. + * Return a single Notifications Broker topic. * * @param id - * The OpenAIRE Broker topic id + * The Notifications Broker topic id * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable> - * The OpenAIRE Broker topic. + * @return Observable> + * The Notifications Broker topic. */ - public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( take(1), diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.html b/src/app/notifications/broker/events/notifications-broker-events.component.html similarity index 60% rename from src/app/openaire/broker/events/openaire-broker-events.component.html rename to src/app/notifications/broker/events/notifications-broker-events.component.html index 05d7722291..a9f51cefd0 100644 --- a/src/app/openaire/broker/events/openaire-broker-events.component.html +++ b/src/app/notifications/broker/events/notifications-broker-events.component.html @@ -1,12 +1,12 @@
-

{{'openaire.events.title'| translate}}

-

{{'openaire.broker.events.description'| translate}}

+

{{'notifications.events.title'| translate}}

+

{{'notifications.broker.events.description'| translate}}

- + - {{'openaire.broker.events.back' | translate}} + {{'notifications.broker.events.back' | translate}}

@@ -14,31 +14,31 @@

- {{'openaire.broker.events.topic' | translate}} {{this.showTopic}} + {{'notifications.broker.events.topic' | translate}} {{this.showTopic}}

- + + (paginationChange)="getNotificationsBrokerEvents()"> - +
- - - - - + + + + + @@ -51,8 +51,8 @@ {{eventElement.title}} @@ -140,9 +140,9 @@ @@ -150,58 +150,58 @@ diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.spec.ts b/src/app/notifications/broker/events/notifications-broker-events.component.spec.ts similarity index 66% rename from src/app/openaire/broker/events/openaire-broker-events.component.spec.ts rename to src/app/notifications/broker/events/notifications-broker-events.component.spec.ts index 267f6a8242..40be083567 100644 --- a/src/app/openaire/broker/events/openaire-broker-events.component.spec.ts +++ b/src/app/notifications/broker/events/notifications-broker-events.component.spec.ts @@ -5,25 +5,25 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/t import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { of as observableOf } from 'rxjs'; -import { OpenaireBrokerEventRestService } from '../../../core/openaire/broker/events/openaire-broker-event-rest.service'; -import { OpenaireBrokerEventsComponent } from './openaire-broker-events.component'; +import { NotificationsBrokerEventRestService } from '../../../core/notifications/broker/events/notifications-broker-event-rest.service'; +import { NotificationsBrokerEventsComponent } from './notifications-broker-events.component'; import { - getMockOpenaireBrokerEventRestService, + getMockNotificationsBrokerEventRestService, ItemMockPid10, ItemMockPid8, ItemMockPid9, - openaireBrokerEventObjectMissingProjectFound, - openaireBrokerEventObjectMissingProjectNotFound, - OpenaireMockDspaceObject -} from '../../../shared/mocks/openaire.mock'; + notificationsBrokerEventObjectMissingProjectFound, + notificationsBrokerEventObjectMissingProjectNotFound, + NotificationsMockDspaceObject +} from '../../../shared/mocks/notifications.mock'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; import { createTestComponent } from '../../../shared/testing/utils.test'; import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { OpenaireBrokerEventObject } from '../../../core/openaire/broker/models/openaire-broker-event.model'; -import { OpenaireBrokerEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; +import { NotificationsBrokerEventObject } from '../../../core/notifications/broker/models/notifications-broker-event.model'; +import { NotificationsBrokerEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -39,9 +39,9 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; -describe('OpenaireBrokerEventsComponent test suite', () => { - let fixture: ComponentFixture; - let comp: OpenaireBrokerEventsComponent; +describe('NotificationsBrokerEventsComponent test suite', () => { + let fixture: ComponentFixture; + let comp: NotificationsBrokerEventsComponent; let compAsAny: any; let scheduler: TestScheduler; @@ -50,9 +50,9 @@ describe('OpenaireBrokerEventsComponent test suite', () => { close: () => null, dismiss: () => null }; - const openaireBrokerEventRestServiceStub: any = getMockOpenaireBrokerEventRestService(); + const notificationsBrokerEventRestServiceStub: any = getMockNotificationsBrokerEventRestService(); const activatedRouteParams = { - openaireBrokerEventsParams: { + notificationsBrokerEventsParams: { currentPage: 0, pageSize: 10 } @@ -61,19 +61,19 @@ describe('OpenaireBrokerEventsComponent test suite', () => { id: 'ENRICH!MISSING!PROJECT' }; - const events: OpenaireBrokerEventObject[] = [ - openaireBrokerEventObjectMissingProjectFound, - openaireBrokerEventObjectMissingProjectNotFound + const events: NotificationsBrokerEventObject[] = [ + notificationsBrokerEventObjectMissingProjectFound, + notificationsBrokerEventObjectMissingProjectNotFound ]; const paginationService = new PaginationServiceStub(); - function getOpenAireBrokerEventData1(): OpenaireBrokerEventData { + function getNotificationsBrokerEventData1(): NotificationsBrokerEventData { return { - event: openaireBrokerEventObjectMissingProjectFound, - id: openaireBrokerEventObjectMissingProjectFound.id, - title: openaireBrokerEventObjectMissingProjectFound.title, + event: notificationsBrokerEventObjectMissingProjectFound, + id: notificationsBrokerEventObjectMissingProjectFound.id, + title: notificationsBrokerEventObjectMissingProjectFound.title, hasProject: true, - projectTitle: openaireBrokerEventObjectMissingProjectFound.message.title, + projectTitle: notificationsBrokerEventObjectMissingProjectFound.message.title, projectId: ItemMockPid10.id, handle: ItemMockPid10.handle, reason: null, @@ -82,11 +82,11 @@ describe('OpenaireBrokerEventsComponent test suite', () => { }; } - function getOpenAireBrokerEventData2(): OpenaireBrokerEventData { + function getNotificationsBrokerEventData2(): NotificationsBrokerEventData { return { - event: openaireBrokerEventObjectMissingProjectNotFound, - id: openaireBrokerEventObjectMissingProjectNotFound.id, - title: openaireBrokerEventObjectMissingProjectNotFound.title, + event: notificationsBrokerEventObjectMissingProjectNotFound, + id: notificationsBrokerEventObjectMissingProjectNotFound.id, + title: notificationsBrokerEventObjectMissingProjectNotFound.title, hasProject: false, projectTitle: null, projectId: null, @@ -104,17 +104,17 @@ describe('OpenaireBrokerEventsComponent test suite', () => { TranslateModule.forRoot(), ], declarations: [ - OpenaireBrokerEventsComponent, + NotificationsBrokerEventsComponent, TestComponent, ], providers: [ { provide: ActivatedRoute, useValue: new ActivatedRouteStub(activatedRouteParamsMap, activatedRouteParams) }, - { provide: OpenaireBrokerEventRestService, useValue: openaireBrokerEventRestServiceStub }, + { provide: NotificationsBrokerEventRestService, useValue: notificationsBrokerEventRestServiceStub }, { provide: NgbModal, useValue: modalStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, { provide: PaginationService, useValue: paginationService }, - OpenaireBrokerEventsComponent + NotificationsBrokerEventsComponent ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(); @@ -129,7 +129,7 @@ describe('OpenaireBrokerEventsComponent test suite', () => { // synchronous beforeEach beforeEach(() => { const html = ` - `; + `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); @@ -138,14 +138,14 @@ describe('OpenaireBrokerEventsComponent test suite', () => { testFixture.destroy(); }); - it('should create OpenaireBrokerEventsComponent', inject([OpenaireBrokerEventsComponent], (app: OpenaireBrokerEventsComponent) => { + it('should create NotificationsBrokerEventsComponent', inject([NotificationsBrokerEventsComponent], (app: NotificationsBrokerEventsComponent) => { expect(app).toBeDefined(); })); }); describe('Main tests', () => { beforeEach(() => { - fixture = TestBed.createComponent(OpenaireBrokerEventsComponent); + fixture = TestBed.createComponent(NotificationsBrokerEventsComponent); comp = fixture.componentInstance; compAsAny = comp; }); @@ -159,8 +159,8 @@ describe('OpenaireBrokerEventsComponent test suite', () => { describe('setEventUpdated', () => { it('should update events', () => { const expected = [ - getOpenAireBrokerEventData1(), - getOpenAireBrokerEventData2() + getNotificationsBrokerEventData1(), + getNotificationsBrokerEventData2() ]; scheduler.schedule(() => { compAsAny.setEventUpdated(events); @@ -179,14 +179,14 @@ describe('OpenaireBrokerEventsComponent test suite', () => { it('should call executeAction if a project is present', () => { const action = 'ACCEPTED'; - comp.modalChoice(action, getOpenAireBrokerEventData1(), modalStub); - expect(comp.executeAction).toHaveBeenCalledWith(action, getOpenAireBrokerEventData1()); + comp.modalChoice(action, getNotificationsBrokerEventData1(), modalStub); + expect(comp.executeAction).toHaveBeenCalledWith(action, getNotificationsBrokerEventData1()); }); it('should call openModal if a project is not present', () => { const action = 'ACCEPTED'; - comp.modalChoice(action, getOpenAireBrokerEventData2(), modalStub); - expect(comp.openModal).toHaveBeenCalledWith(action, getOpenAireBrokerEventData2(), modalStub); + comp.modalChoice(action, getNotificationsBrokerEventData2(), modalStub); + expect(comp.openModal).toHaveBeenCalledWith(action, getNotificationsBrokerEventData2(), modalStub); }); }); @@ -197,7 +197,7 @@ describe('OpenaireBrokerEventsComponent test suite', () => { spyOn(compAsAny.modalService, 'open').and.returnValue({ result: new Promise((res, rej) => 'do' ) }); spyOn(comp, 'executeAction'); - comp.openModal(action, getOpenAireBrokerEventData1(), modalStub); + comp.openModal(action, getNotificationsBrokerEventData1(), modalStub); expect(compAsAny.modalService.open).toHaveBeenCalled(); }); }); @@ -211,13 +211,13 @@ describe('OpenaireBrokerEventsComponent test suite', () => { externalSourceEntry: null, label: null, importedObject: observableOf({ - indexableObject: OpenaireMockDspaceObject + indexableObject: NotificationsMockDspaceObject }) } } ); scheduler.schedule(() => { - comp.openModalLookup(getOpenAireBrokerEventData1()); + comp.openModalLookup(getNotificationsBrokerEventData1()); }); scheduler.flush(); @@ -227,27 +227,27 @@ describe('OpenaireBrokerEventsComponent test suite', () => { }); describe('executeAction', () => { - it('should call getOpenaireBrokerEvents on 200 response from REST', () => { + it('should call getNotificationsBrokerEvents on 200 response from REST', () => { const action = 'ACCEPTED'; - spyOn(compAsAny, 'getOpenaireBrokerEvents'); - openaireBrokerEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); + spyOn(compAsAny, 'getNotificationsBrokerEvents'); + notificationsBrokerEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); scheduler.schedule(() => { - comp.executeAction(action, getOpenAireBrokerEventData1()); + comp.executeAction(action, getNotificationsBrokerEventData1()); }); scheduler.flush(); - expect(compAsAny.getOpenaireBrokerEvents).toHaveBeenCalled(); + expect(compAsAny.getNotificationsBrokerEvents).toHaveBeenCalled(); }); }); describe('boundProject', () => { it('should populate the project data inside "eventData"', () => { - const eventData = getOpenAireBrokerEventData2(); + const eventData = getNotificationsBrokerEventData2(); const projectId = 'UUID-23943-34u43-38344'; const projectName = 'Test Project'; const projectHandle = '1000/1000'; - openaireBrokerEventRestServiceStub.boundProject.and.returnValue(createSuccessfulRemoteDataObject$({})); + notificationsBrokerEventRestServiceStub.boundProject.and.returnValue(createSuccessfulRemoteDataObject$({})); scheduler.schedule(() => { comp.boundProject(eventData, projectId, projectName, projectHandle); @@ -263,8 +263,8 @@ describe('OpenaireBrokerEventsComponent test suite', () => { describe('removeProject', () => { it('should remove the project data inside "eventData"', () => { - const eventData = getOpenAireBrokerEventData1(); - openaireBrokerEventRestServiceStub.removeProject.and.returnValue(createNoContentRemoteDataObject$()); + const eventData = getNotificationsBrokerEventData1(); + notificationsBrokerEventRestServiceStub.removeProject.and.returnValue(createNoContentRemoteDataObject$()); scheduler.schedule(() => { comp.removeProject(eventData); @@ -278,8 +278,8 @@ describe('OpenaireBrokerEventsComponent test suite', () => { }); }); - describe('getOpenaireBrokerEvents', () => { - it('should call the "openaireBrokerEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { + describe('getNotificationsBrokerEvents', () => { + it('should call the "notificationsBrokerEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { comp.paginationConfig = new PaginationComponentOptions(); comp.paginationConfig.currentPage = 1; comp.paginationConfig.pageSize = 20; @@ -297,20 +297,20 @@ describe('OpenaireBrokerEventsComponent test suite', () => { currentPage: comp.paginationConfig.currentPage }); const array = [ - openaireBrokerEventObjectMissingProjectFound, - openaireBrokerEventObjectMissingProjectNotFound, + notificationsBrokerEventObjectMissingProjectFound, + notificationsBrokerEventObjectMissingProjectNotFound, ]; const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - openaireBrokerEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); + notificationsBrokerEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); spyOn(compAsAny, 'setEventUpdated'); scheduler.schedule(() => { - compAsAny.getOpenaireBrokerEvents(); + compAsAny.getNotificationsBrokerEvents(); }); scheduler.flush(); - expect(compAsAny.openaireBrokerEventRestService.getEventsByTopic).toHaveBeenCalledWith( + expect(compAsAny.notificationsBrokerEventRestService.getEventsByTopic).toHaveBeenCalledWith( activatedRouteParamsMap.id, options, followLink('target'),followLink('related') diff --git a/src/app/openaire/broker/events/openaire-broker-events.component.ts b/src/app/notifications/broker/events/notifications-broker-events.component.ts similarity index 71% rename from src/app/openaire/broker/events/openaire-broker-events.component.ts rename to src/app/notifications/broker/events/notifications-broker-events.component.ts index 14ad175e80..b416664fca 100644 --- a/src/app/openaire/broker/events/openaire-broker-events.component.ts +++ b/src/app/notifications/broker/events/notifications-broker-events.component.ts @@ -11,10 +11,10 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; import { FindListOptions } from '../../../core/data/request.models'; import { - OpenaireBrokerEventMessageObject, - OpenaireBrokerEventObject -} from '../../../core/openaire/broker/models/openaire-broker-event.model'; -import { OpenaireBrokerEventRestService } from '../../../core/openaire/broker/events/openaire-broker-event-rest.service'; + NotificationsBrokerEventObject, + OpenaireBrokerEventMessageObject +} from '../../../core/notifications/broker/models/notifications-broker-event.model'; +import { NotificationsBrokerEventRestService } from '../../../core/notifications/broker/events/notifications-broker-event-rest.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { Metadata } from '../../../core/shared/metadata.utils'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -22,7 +22,7 @@ import { hasValue } from '../../../shared/empty.util'; import { ItemSearchResult } from '../../../shared/object-collection/shared/item-search-result.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { - OpenaireBrokerEventData, + NotificationsBrokerEventData, ProjectEntryImportModalComponent } from '../project-entry-import-modal/project-entry-import-modal.component'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; @@ -31,14 +31,14 @@ import { combineLatest } from 'rxjs/internal/observable/combineLatest'; import { Item } from '../../../core/shared/item.model'; /** - * Component to display the OpenAIRE Broker event list. + * Component to display the Notifications Broker event list. */ @Component({ - selector: 'ds-openaire-broker-events', - templateUrl: './openaire-broker-events.component.html', - styleUrls: ['./openaire-broker-events.scomponent.scss'], + selector: 'ds-notifications-broker-events', + templateUrl: './notifications-broker-events.component.html', + styleUrls: ['./notifications-broker-events.scomponent.scss'], }) -export class OpenaireBrokerEventsComponent implements OnInit { +export class NotificationsBrokerEventsComponent implements OnInit { /** * The pagination system configuration for HTML listing. * @type {PaginationComponentOptions} @@ -50,27 +50,27 @@ export class OpenaireBrokerEventsComponent implements OnInit { pageSizeOptions: [5, 10, 20, 40, 60] }); /** - * The OpenAIRE Broker event list sort options. + * The Notifications Broker event list sort options. * @type {SortOptions} */ public paginationSortConfig: SortOptions = new SortOptions('trust', SortDirection.DESC); /** - * Array to save the presence of a project inside an OpenAIRE Broker event. - * @type {OpenaireBrokerEventData[]>} + * Array to save the presence of a project inside an Notifications Broker event. + * @type {NotificationsBrokerEventData[]>} */ - public eventsUpdated$: BehaviorSubject = new BehaviorSubject([]); + public eventsUpdated$: BehaviorSubject = new BehaviorSubject([]); /** - * The total number of OpenAIRE Broker events. + * The total number of Notifications Broker events. * @type {Observable} */ public totalElements$: Observable; /** - * The topic of the OpenAIRE Broker events; suitable for displaying. + * The topic of the Notifications Broker events; suitable for displaying. * @type {string} */ public showTopic: string; /** - * The topic of the OpenAIRE Broker events; suitable for HTTP calls. + * The topic of the Notifications Broker events; suitable for HTTP calls. * @type {string} */ public topic: string; @@ -114,7 +114,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { * @param {ActivatedRoute} activatedRoute * @param {NgbModal} modalService * @param {NotificationsService} notificationsService - * @param {OpenaireBrokerEventRestService} openaireBrokerEventRestService + * @param {NotificationsBrokerEventRestService} notificationsBrokerEventRestService * @param {PaginationService} paginationService * @param {TranslateService} translateService */ @@ -122,7 +122,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { private activatedRoute: ActivatedRoute, private modalService: NgbModal, private notificationsService: NotificationsService, - private openaireBrokerEventRestService: OpenaireBrokerEventRestService, + private notificationsBrokerEventRestService: NotificationsBrokerEventRestService, private paginationService: PaginationService, private translateService: TranslateService ) { @@ -142,7 +142,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { this.showTopic = id.replace(regEx, '/'); this.topic = id; this.isEventPageLoading.next(false); - this.getOpenaireBrokerEvents(); + this.getNotificationsBrokerEvents(); }); } @@ -162,12 +162,12 @@ export class OpenaireBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event data * @param {any} content * Reference to the modal */ - public modalChoice(action: string, eventData: OpenaireBrokerEventData, content: any): void { + public modalChoice(action: string, eventData: NotificationsBrokerEventData, content: any): void { if (eventData.hasProject) { this.executeAction(action, eventData); } else { @@ -180,12 +180,12 @@ export class OpenaireBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event data * @param {any} content * Reference to the modal */ - public openModal(action: string, eventData: OpenaireBrokerEventData, content: any): void { + public openModal(action: string, eventData: NotificationsBrokerEventData, content: any): void { this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then( (result) => { if (result === 'do') { @@ -203,10 +203,10 @@ export class OpenaireBrokerEventsComponent implements OnInit { /** * Open a modal where the user can select the project. * - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event item data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event item data */ - public openModalLookup(eventData: OpenaireBrokerEventData): void { + public openModalLookup(eventData: NotificationsBrokerEventData): void { this.modalRef = this.modalService.open(ProjectEntryImportModalComponent, { size: 'lg' }); @@ -232,22 +232,22 @@ export class OpenaireBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event data */ - public executeAction(action: string, eventData: OpenaireBrokerEventData): void { + public executeAction(action: string, eventData: NotificationsBrokerEventData): void { eventData.isRunning = true; this.subs.push( - this.openaireBrokerEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.notificationsBrokerEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess && rd.statusCode === 200) { this.notificationsService.success( - this.translateService.instant('openaire.broker.event.action.saved') + this.translateService.instant('notifications.broker.event.action.saved') ); - this.getOpenaireBrokerEvents(); + this.getNotificationsBrokerEvents(); } else { this.notificationsService.error( - this.translateService.instant('openaire.broker.event.action.error') + this.translateService.instant('notifications.broker.event.action.error') ); } eventData.isRunning = false; @@ -256,10 +256,10 @@ export class OpenaireBrokerEventsComponent implements OnInit { } /** - * Bound a project to the publication described in the OpenAIRE Broker event calling the REST service. + * Bound a project to the publication described in the Notifications Broker event calling the REST service. * - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event item data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event item data * @param {string} projectId * the project Id to bound * @param {string} projectTitle @@ -267,14 +267,14 @@ export class OpenaireBrokerEventsComponent implements OnInit { * @param {string} projectHandle * the project handle */ - public boundProject(eventData: OpenaireBrokerEventData, projectId: string, projectTitle: string, projectHandle: string): void { + public boundProject(eventData: NotificationsBrokerEventData, projectId: string, projectTitle: string, projectHandle: string): void { eventData.isRunning = true; this.subs.push( - this.openaireBrokerEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.notificationsBrokerEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( - this.translateService.instant('openaire.broker.event.project.bounded') + this.translateService.instant('notifications.broker.event.project.bounded') ); eventData.hasProject = true; eventData.projectTitle = projectTitle; @@ -282,7 +282,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { eventData.projectId = projectId; } else { this.notificationsService.error( - this.translateService.instant('openaire.broker.event.project.error') + this.translateService.instant('notifications.broker.event.project.error') ); } eventData.isRunning = false; @@ -291,19 +291,19 @@ export class OpenaireBrokerEventsComponent implements OnInit { } /** - * Remove the bounded project from the publication described in the OpenAIRE Broker event calling the REST service. + * Remove the bounded project from the publication described in the Notifications Broker event calling the REST service. * - * @param {OpenaireBrokerEventData} eventData - * the OpenAIRE Broker event data + * @param {NotificationsBrokerEventData} eventData + * the Notifications Broker event data */ - public removeProject(eventData: OpenaireBrokerEventData): void { + public removeProject(eventData: NotificationsBrokerEventData): void { eventData.isRunning = true; this.subs.push( - this.openaireBrokerEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.notificationsBrokerEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( - this.translateService.instant('openaire.broker.event.project.removed') + this.translateService.instant('notifications.broker.event.project.removed') ); eventData.hasProject = false; eventData.projectTitle = null; @@ -311,7 +311,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { eventData.projectId = null; } else { this.notificationsService.error( - this.translateService.instant('openaire.broker.event.project.error') + this.translateService.instant('notifications.broker.event.project.error') ); } eventData.isRunning = false; @@ -337,26 +337,26 @@ export class OpenaireBrokerEventsComponent implements OnInit { /** - * Dispatch the OpenAIRE Broker events retrival. + * Dispatch the Notifications Broker events retrival. */ - public getOpenaireBrokerEvents(): void { + public getNotificationsBrokerEvents(): void { this.paginationService.getFindListOptions(this.paginationConfig.id, this.defaultConfig).pipe( distinctUntilChanged(), - switchMap((options: FindListOptions) => this.openaireBrokerEventRestService.getEventsByTopic( + switchMap((options: FindListOptions) => this.notificationsBrokerEventRestService.getEventsByTopic( this.topic, options, followLink('target'), followLink('related') )), getFirstCompletedRemoteData(), - ).subscribe((rd: RemoteData>) => { + ).subscribe((rd: RemoteData>) => { if (rd.hasSucceeded) { this.isEventLoading.next(false); this.totalElements$ = observableOf(rd.payload.totalElements); this.setEventUpdated(rd.payload.page); } else { - throw new Error('Can\'t retrieve OpenAIRE Broker events from the Broker events REST service'); + throw new Error('Can\'t retrieve Notifications Broker events from the Broker events REST service'); } - this.openaireBrokerEventRestService.clearFindByTopicRequests(); + this.notificationsBrokerEventRestService.clearFindByTopicRequests(); }); } @@ -370,15 +370,15 @@ export class OpenaireBrokerEventsComponent implements OnInit { } /** - * Set the project status for the OpenAIRE Broker events. + * Set the project status for the Notifications Broker events. * - * @param {OpenaireBrokerEventObject[]} events - * the OpenAIRE Broker event item + * @param {NotificationsBrokerEventObject[]} events + * the Notifications Broker event item */ - protected setEventUpdated(events: OpenaireBrokerEventObject[]): void { + protected setEventUpdated(events: NotificationsBrokerEventObject[]): void { this.subs.push( from(events).pipe( - mergeMap((event: OpenaireBrokerEventObject) => { + mergeMap((event: NotificationsBrokerEventObject) => { const related$ = event.related.pipe( getFirstCompletedRemoteData(), ); @@ -387,7 +387,7 @@ export class OpenaireBrokerEventsComponent implements OnInit { ); return combineLatest([related$, target$]).pipe( map(([relatedItemRD, targetItemRD]: [RemoteData, RemoteData]) => { - const data: OpenaireBrokerEventData = { + const data: NotificationsBrokerEventData = { event: event, id: event.id, title: event.title, diff --git a/src/app/openaire/broker/events/openaire-broker-events.scomponent.scss b/src/app/notifications/broker/events/notifications-broker-events.scomponent.scss similarity index 100% rename from src/app/openaire/broker/events/openaire-broker-events.scomponent.scss rename to src/app/notifications/broker/events/notifications-broker-events.scomponent.scss diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.html similarity index 100% rename from src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.html rename to src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.html diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.scss similarity index 100% rename from src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.scss rename to src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.scss diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts similarity index 92% rename from src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts rename to src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts index e19d0a7c86..7cac576844 100644 --- a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts +++ b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts @@ -17,16 +17,16 @@ import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { PageInfo } from '../../../core/shared/page-info.model'; import { ItemMockPid10, - openaireBrokerEventObjectMissingProjectFound, - OpenaireMockDspaceObject -} from '../../../shared/mocks/openaire.mock'; + notificationsBrokerEventObjectMissingProjectFound, + NotificationsMockDspaceObject +} from '../../../shared/mocks/notifications.mock'; const eventData = { - event: openaireBrokerEventObjectMissingProjectFound, - id: openaireBrokerEventObjectMissingProjectFound.id, - title: openaireBrokerEventObjectMissingProjectFound.title, + event: notificationsBrokerEventObjectMissingProjectFound, + id: notificationsBrokerEventObjectMissingProjectFound.id, + title: notificationsBrokerEventObjectMissingProjectFound.title, hasProject: true, - projectTitle: openaireBrokerEventObjectMissingProjectFound.message.title, + projectTitle: notificationsBrokerEventObjectMissingProjectFound.message.title, projectId: ItemMockPid10.id, handle: ItemMockPid10.handle, reason: null, @@ -36,7 +36,7 @@ const eventData = { const searchString = 'Test project to search'; const pagination = Object.assign( new PaginationComponentOptions(), { - id: 'openaire-project-bound', + id: 'notifications-project-bound', pageSize: 3 } ); @@ -54,7 +54,7 @@ const pageInfo = new PageInfo({ currentPage: 1 }); const array = [ - OpenaireMockDspaceObject, + NotificationsMockDspaceObject, ]; const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); @@ -143,7 +143,7 @@ describe('ProjectEntryImportModalComponent test suite', () => { spyOn(comp, 'deselectAllLists'); spyOn(comp, 'close'); spyOn(comp.importedObject, 'emit'); - comp.selectedEntity = OpenaireMockDspaceObject; + comp.selectedEntity = NotificationsMockDspaceObject; comp.bound(); expect(comp.importedObject.emit).toHaveBeenCalled(); diff --git a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts similarity index 89% rename from src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts rename to src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts index 5d8cb20c6d..64672fa1fa 100644 --- a/src/app/openaire/broker/project-entry-import-modal/project-entry-import-modal.component.ts +++ b/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts @@ -12,7 +12,11 @@ import { ListableObject } from '../../../shared/object-collection/shared/listabl import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { SearchService } from '../../../core/shared/search/search.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { OpenaireBrokerEventObject } from '../../../core/openaire/broker/models/openaire-broker-event.model'; +import { + NotificationsBrokerEventObject, + NotificationsBrokerEventMessageObject, + OpenaireBrokerEventMessageObject, +} from '../../../core/notifications/broker/models/notifications-broker-event.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { Item } from '../../../core/shared/item.model'; @@ -30,13 +34,13 @@ export enum ImportType { /** * The data type passed from the parent page */ -export interface OpenaireBrokerEventData { +export interface NotificationsBrokerEventData { /** - * The OpenAIRE Broker event + * The Notifications Broker event */ - event: OpenaireBrokerEventObject; + event: NotificationsBrokerEventObject; /** - * The OpenAIRE Broker event Id (uuid) + * The Notifications Broker event Id (uuid) */ id: string; /** @@ -79,14 +83,14 @@ export interface OpenaireBrokerEventData { templateUrl: './project-entry-import-modal.component.html' }) /** - * Component to display a modal window for linking a project to an OpenAIRE Broker event + * Component to display a modal window for linking a project to an Notifications Broker event * Shows information about the selected project and a selectable list. */ export class ProjectEntryImportModalComponent implements OnInit { /** * The external source entry */ - @Input() externalSourceEntry: OpenaireBrokerEventData; + @Input() externalSourceEntry: NotificationsBrokerEventData; /** * The number of results per page */ @@ -94,7 +98,7 @@ export class ProjectEntryImportModalComponent implements OnInit { /** * The prefix for every i18n key within this modal */ - labelPrefix = 'openaire.broker.event.modal.'; + labelPrefix = 'notifications.broker.event.modal.'; /** * The search configuration to retrieve project */ @@ -126,11 +130,11 @@ export class ProjectEntryImportModalComponent implements OnInit { /** * List ID for selecting local entities */ - entityListId = 'openaire-project-bound'; + entityListId = 'notifications-project-bound'; /** * List ID for selecting local authorities */ - authorityListId = 'openaire-project-bound-authority'; + authorityListId = 'notifications-project-bound-authority'; /** * ImportType enum */ @@ -175,8 +179,9 @@ export class ProjectEntryImportModalComponent implements OnInit { * Component intitialization. */ public ngOnInit(): void { - this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'openaire-project-bound', pageSize: this.pageSize }); - this.projectTitle = (this.externalSourceEntry.projectTitle !== null) ? this.externalSourceEntry.projectTitle : this.externalSourceEntry.event.message.title; + this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'notifications-project-bound', pageSize: this.pageSize }); + this.projectTitle = (this.externalSourceEntry.projectTitle !== null) ? this.externalSourceEntry.projectTitle + : (this.externalSourceEntry.event.message as OpenaireBrokerEventMessageObject).title; this.searchOptions = Object.assign(new PaginatedSearchOptions( { configuration: this.configuration, diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.actions.ts b/src/app/notifications/broker/topics/notifications-broker-topics.actions.ts similarity index 60% rename from src/app/openaire/broker/topics/openaire-broker-topics.actions.ts rename to src/app/notifications/broker/topics/notifications-broker-topics.actions.ts index fd98c6acb8..622ecc8141 100644 --- a/src/app/openaire/broker/topics/openaire-broker-topics.actions.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.actions.ts @@ -1,6 +1,6 @@ import { Action } from '@ngrx/store'; import { type } from '../../../shared/ngrx/type'; -import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/openaire-broker-topic.model'; +import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; /** * For each action type in an action group, make a simple @@ -10,19 +10,19 @@ import { OpenaireBrokerTopicObject } from '../../../core/openaire/broker/models/ * literal types and runs a simple check to guarantee all * action types in the application are unique. */ -export const OpenaireBrokerTopicActionTypes = { - ADD_TOPICS: type('dspace/integration/openaire/broker/topic/ADD_TOPICS'), - RETRIEVE_ALL_TOPICS: type('dspace/integration/openaire/broker/topic/RETRIEVE_ALL_TOPICS'), - RETRIEVE_ALL_TOPICS_ERROR: type('dspace/integration/openaire/broker/topic/RETRIEVE_ALL_TOPICS_ERROR'), +export const NotificationsBrokerTopicActionTypes = { + ADD_TOPICS: type('dspace/integration/notifications/broker/topic/ADD_TOPICS'), + RETRIEVE_ALL_TOPICS: type('dspace/integration/notifications/broker/topic/RETRIEVE_ALL_TOPICS'), + RETRIEVE_ALL_TOPICS_ERROR: type('dspace/integration/notifications/broker/topic/RETRIEVE_ALL_TOPICS_ERROR'), }; /* tslint:disable:max-classes-per-file */ /** - * An ngrx action to retrieve all the OpenAIRE Broker topics. + * An ngrx action to retrieve all the Notifications Broker topics. */ export class RetrieveAllTopicsAction implements Action { - type = OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS; + type = NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS; payload: { elementsPerPage: number; currentPage: number; @@ -45,20 +45,20 @@ export class RetrieveAllTopicsAction implements Action { } /** - * An ngrx action for retrieving 'all OpenAIRE Broker topics' error. + * An ngrx action for retrieving 'all Notifications Broker topics' error. */ export class RetrieveAllTopicsErrorAction implements Action { - type = OpenaireBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR; + type = NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR; } /** - * An ngrx action to load the OpenAIRE Broker topic objects. + * An ngrx action to load the Notifications Broker topic objects. * Called by the ??? effect. */ export class AddTopicsAction implements Action { - type = OpenaireBrokerTopicActionTypes.ADD_TOPICS; + type = NotificationsBrokerTopicActionTypes.ADD_TOPICS; payload: { - topics: OpenaireBrokerTopicObject[]; + topics: NotificationsBrokerTopicObject[]; totalPages: number; currentPage: number; totalElements: number; @@ -74,9 +74,9 @@ export class AddTopicsAction implements Action { * @param currentPage * the current page * @param totalElements - * the total available OpenAIRE Broker topics + * the total available Notifications Broker topics */ - constructor(topics: OpenaireBrokerTopicObject[], totalPages: number, currentPage: number, totalElements: number) { + constructor(topics: NotificationsBrokerTopicObject[], totalPages: number, currentPage: number, totalElements: number) { this.payload = { topics, totalPages, @@ -93,7 +93,7 @@ export class AddTopicsAction implements Action { * Export a type alias of all actions in this action group * so that reducers can easily compose action types. */ -export type OpenaireBrokerTopicsActions +export type NotificationsBrokerTopicsActions = AddTopicsAction |RetrieveAllTopicsAction |RetrieveAllTopicsErrorAction; diff --git a/src/app/openaire/broker/topics/openaire-broker-topics.component.html b/src/app/notifications/broker/topics/notifications-broker-topics.component.html similarity index 66% rename from src/app/openaire/broker/topics/openaire-broker-topics.component.html rename to src/app/notifications/broker/topics/notifications-broker-topics.component.html index d8321bc932..02371a8a6b 100644 --- a/src/app/openaire/broker/topics/openaire-broker-topics.component.html +++ b/src/app/notifications/broker/topics/notifications-broker-topics.component.html @@ -1,34 +1,34 @@
-

{{'openaire.broker.title'| translate}}

-

{{'openaire.broker.topics.description'| translate}}

+

{{'notifications.broker.title'| translate}}

+

{{'notifications.broker.topics.description'| translate}}

-

{{'openaire.broker.topics'| translate}}

+

{{'notifications.broker.topics'| translate}}

- + + (paginationChange)="getNotificationsBrokerTopics()"> - +
{{'openaire.broker.event.table.trust' | translate}}{{'openaire.broker.event.table.publication' | translate}}{{'openaire.broker.event.table.details' | translate}}{{'openaire.broker.event.table.project-details' | translate}}{{'openaire.broker.event.table.actions' | translate}}{{'notifications.broker.event.table.trust' | translate}}{{'notifications.broker.event.table.publication' | translate}}{{'notifications.broker.event.table.details' | translate}}{{'notifications.broker.event.table.project-details' | translate}}{{'notifications.broker.event.table.actions' | translate}}
-

{{'openaire.broker.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

-

{{'openaire.broker.event.table.pidvalue' | translate}}
+

{{'notifications.broker.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

+

{{'notifications.broker.event.table.pidvalue' | translate}}
{{eventElement.event.message.value}} @@ -60,37 +60,37 @@

-

{{'openaire.broker.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

+

{{'notifications.broker.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

- {{'openaire.broker.event.table.abstract' | translate}}
+ {{'notifications.broker.event.table.abstract' | translate}}
{{eventElement.event.message.abstract}}

- {{'openaire.broker.event.table.suggestedProject' | translate}} + {{'notifications.broker.event.table.suggestedProject' | translate}}

- {{'openaire.broker.event.table.project' | translate}}
+ {{'notifications.broker.event.table.project' | translate}}
{{eventElement.event.message.title}}

- {{'openaire.broker.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
- {{'openaire.broker.event.table.code' | translate}} {{eventElement.event.message.code}}
- {{'openaire.broker.event.table.funder' | translate}} {{eventElement.event.message.funder}}
- {{'openaire.broker.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
- {{'openaire.broker.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}} + {{'notifications.broker.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
+ {{'notifications.broker.event.table.code' | translate}} {{eventElement.event.message.code}}
+ {{'notifications.broker.event.table.funder' | translate}} {{eventElement.event.message.funder}}
+ {{'notifications.broker.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
+ {{'notifications.broker.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}}


- {{(eventElement.hasProject ? 'openaire.broker.event.project.found' : 'openaire.broker.event.project.notFound') | translate}} + {{(eventElement.hasProject ? 'notifications.broker.event.project.found' : 'notifications.broker.event.project.notFound') | translate}} {{eventElement.handle}}
- - - + + + @@ -39,7 +39,7 @@
{{'openaire.broker.table.topic' | translate}}{{'openaire.broker.table.last-event' | translate}}{{'openaire.broker.table.actions' | translate}}{{'notifications.broker.table.topic' | translate}}{{'notifications.broker.table.last-event' | translate}}{{'notifications.broker.table.actions' | translate}}
+ + + + + + + + + + + + + + +
{{'notifications.broker.table.source' | translate}}{{'notifications.broker.table.last-event' | translate}}{{'notifications.broker.table.actions' | translate}}
{{sourceElement.id}}{{sourceElement.lastEvent}} +
+ +
+
+
+
+
+
+
+
+ diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.scss b/src/app/notifications/broker/source/notifications-broker-source.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts b/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts new file mode 100644 index 0000000000..7d18c726c5 --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationsBrokerSourceComponent } from './notifications-broker-source.component'; + +describe('NotificationsBrokerSourceComponent', () => { + let component: NotificationsBrokerSourceComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationsBrokerSourceComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.ts b/src/app/notifications/broker/source/notifications-broker-source.component.ts new file mode 100644 index 0000000000..070e03f396 --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.component.ts @@ -0,0 +1,139 @@ +import { Component, OnInit } from '@angular/core'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { Observable, Subscription } from 'rxjs'; +import { distinctUntilChanged, take } from 'rxjs/operators'; +import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { NotificationsStateService } from '../../notifications-state.service'; +import { AdminNotificationsBrokerSourcePageParams } from '../../../admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service'; +import { hasValue } from '../../../shared/empty.util'; + +@Component({ + selector: 'ds-notifications-broker-source', + templateUrl: './notifications-broker-source.component.html', + styleUrls: ['./notifications-broker-source.component.scss'] +}) +export class NotificationsBrokerSourceComponent implements OnInit { + + /** + * The pagination system configuration for HTML listing. + * @type {PaginationComponentOptions} + */ + public paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'btp', + pageSize: 10, + pageSizeOptions: [5, 10, 20, 40, 60] + }); + /** + * The Notifications Broker source list sort options. + * @type {SortOptions} + */ + public paginationSortConfig: SortOptions; + /** + * The Notifications Broker source list. + */ + public sources$: Observable; + /** + * The total number of Notifications Broker sources. + */ + public totalElements$: Observable; + /** + * Array to track all the component subscriptions. Useful to unsubscribe them with 'onDestroy'. + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * Initialize the component variables. + * @param {PaginationService} paginationService + * @param {NotificationsStateService} notificationsStateService + */ + constructor( + private paginationService: PaginationService, + private notificationsStateService: NotificationsStateService, + ) { } + + /** + * Component initialization. + */ + ngOnInit(): void { + this.sources$ = this.notificationsStateService.getNotificationsBrokerSource(); + this.totalElements$ = this.notificationsStateService.getNotificationsBrokerSourceTotals(); + } + + /** + * First Notifications Broker source loading after view initialization. + */ + ngAfterViewInit(): void { + this.subs.push( + this.notificationsStateService.isNotificationsBrokerSourceLoaded().pipe( + take(1) + ).subscribe(() => { + this.getNotificationsBrokerSource(); + }) + ); + } + + /** + * Returns the information about the loading status of the Notifications Broker source (if it's running or not). + * + * @return Observable + * 'true' if the source are loading, 'false' otherwise. + */ + public isSourceLoading(): Observable { + return this.notificationsStateService.isNotificationsBrokerSourceLoading(); + } + + /** + * Returns the information about the processing status of the Notifications Broker source (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the source (ex.: a REST call), 'false' otherwise. + */ + public isSourceProcessing(): Observable { + return this.notificationsStateService.isNotificationsBrokerSourceProcessing(); + } + + /** + * Dispatch the Notifications Broker source retrival. + */ + public getNotificationsBrokerSource(): void { + this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( + distinctUntilChanged(), + ).subscribe((options: PaginationComponentOptions) => { + this.notificationsStateService.dispatchRetrieveNotificationsBrokerSource( + options.pageSize, + options.currentPage + ); + }); + } + + /** + * Update pagination Config from route params + * + * @param eventsRouteParams + */ + protected updatePaginationFromRouteParams(eventsRouteParams: AdminNotificationsBrokerSourcePageParams) { + if (eventsRouteParams.currentPage) { + this.paginationConfig.currentPage = eventsRouteParams.currentPage; + } + if (eventsRouteParams.pageSize) { + if (this.paginationConfig.pageSizeOptions.includes(eventsRouteParams.pageSize)) { + this.paginationConfig.pageSize = eventsRouteParams.pageSize; + } else { + this.paginationConfig.pageSize = this.paginationConfig.pageSizeOptions[0]; + } + } + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + +} diff --git a/src/app/notifications/broker/source/notifications-broker-source.effects.ts b/src/app/notifications/broker/source/notifications-broker-source.effects.ts new file mode 100644 index 0000000000..bd8b3f00cd --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.effects.ts @@ -0,0 +1,87 @@ +import { Injectable } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { TranslateService } from '@ngx-translate/core'; +import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; +import { of as observableOf } from 'rxjs'; +import { + AddSourceAction, + NotificationsBrokerSourceActionTypes, + RetrieveAllSourceAction, + RetrieveAllSourceErrorAction, +} from './notifications-broker-source.actions'; + +import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NotificationsBrokerSourceService } from './notifications-broker-source.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; + +/** + * Provides effect methods for the Notifications Broker source actions. + */ +@Injectable() +export class NotificationsBrokerSourceEffects { + + /** + * Retrieve all Notifications Broker source managing pagination and errors. + */ + @Effect() retrieveAllSource$ = this.actions$.pipe( + ofType(NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE), + withLatestFrom(this.store$), + switchMap(([action, currentState]: [RetrieveAllSourceAction, any]) => { + return this.notificationsBrokerSourceService.getSources( + action.payload.elementsPerPage, + action.payload.currentPage + ).pipe( + map((sources: PaginatedList) => + new AddSourceAction(sources.page, sources.totalPages, sources.currentPage, sources.totalElements) + ), + catchError((error: Error) => { + if (error) { + console.error(error.message); + } + return observableOf(new RetrieveAllSourceErrorAction()); + }) + ); + }) + ); + + /** + * Show a notification on error. + */ + @Effect({ dispatch: false }) retrieveAllSourceErrorAction$ = this.actions$.pipe( + ofType(NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR), + tap(() => { + this.notificationsService.error(null, this.translate.get('notifications.broker.source.error.service.retrieve')); + }) + ); + + /** + * Clear find all source requests from cache. + */ + @Effect({ dispatch: false }) addSourceAction$ = this.actions$.pipe( + ofType(NotificationsBrokerSourceActionTypes.ADD_SOURCE), + tap(() => { + this.notificationsBrokerSourceDataService.clearFindAllSourceRequests(); + }) + ); + + /** + * Initialize the effect class variables. + * @param {Actions} actions$ + * @param {Store} store$ + * @param {TranslateService} translate + * @param {NotificationsService} notificationsService + * @param {NotificationsBrokerSourceService} notificationsBrokerSourceService + * @param {NotificationsBrokerSourceRestService} notificationsBrokerSourceDataService + */ + constructor( + private actions$: Actions, + private store$: Store, + private translate: TranslateService, + private notificationsService: NotificationsService, + private notificationsBrokerSourceService: NotificationsBrokerSourceService, + private notificationsBrokerSourceDataService: NotificationsBrokerSourceRestService + ) { } +} diff --git a/src/app/notifications/broker/source/notifications-broker-source.reducer.ts b/src/app/notifications/broker/source/notifications-broker-source.reducer.ts new file mode 100644 index 0000000000..5395796380 --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.reducer.ts @@ -0,0 +1,72 @@ +import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { NotificationsBrokerSourceActionTypes, NotificationsBrokerSourceActions } from './notifications-broker-source.actions'; + +/** + * The interface representing the Notifications Broker source state. + */ +export interface NotificationsBrokerSourceState { + source: NotificationsBrokerSourceObject[]; + processing: boolean; + loaded: boolean; + totalPages: number; + currentPage: number; + totalElements: number; +} + +/** + * Used for the Notifications Broker source state initialization. + */ +const notificationsBrokerSourceInitialState: NotificationsBrokerSourceState = { + source: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 +}; + +/** + * The Notifications Broker Source Reducer + * + * @param state + * the current state initialized with notificationsBrokerSourceInitialState + * @param action + * the action to perform on the state + * @return NotificationsBrokerSourceState + * the new state + */ +export function notificationsBrokerSourceReducer(state = notificationsBrokerSourceInitialState, action: NotificationsBrokerSourceActions): NotificationsBrokerSourceState { + switch (action.type) { + case NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE: { + return Object.assign({}, state, { + source: [], + processing: true + }); + } + + case NotificationsBrokerSourceActionTypes.ADD_SOURCE: { + return Object.assign({}, state, { + source: action.payload.source, + processing: false, + loaded: true, + totalPages: action.payload.totalPages, + currentPage: state.currentPage, + totalElements: action.payload.totalElements + }); + } + + case NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR: { + return Object.assign({}, state, { + processing: false, + loaded: true, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }); + } + + default: { + return state; + } + } +} diff --git a/src/app/notifications/broker/source/notifications-broker-source.service.ts b/src/app/notifications/broker/source/notifications-broker-source.service.ts new file mode 100644 index 0000000000..e80643049c --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { find, map } from 'rxjs/operators'; +import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; + +/** + * The service handling all Notifications Broker source requests to the REST service. + */ +@Injectable() +export class NotificationsBrokerSourceService { + + /** + * Initialize the service variables. + * @param {NotificationsBrokerSourceRestService} notificationsBrokerSourceRestService + */ + constructor( + private notificationsBrokerSourceRestService: NotificationsBrokerSourceRestService + ) { } + + /** + * Return the list of Notifications Broker source managing pagination and errors. + * + * @param elementsPerPage + * The number of the source per page + * @param currentPage + * The page number to retrieve + * @return Observable> + * The list of Notifications Broker source. + */ + public getSources(elementsPerPage, currentPage): Observable> { + const sortOptions = new SortOptions('name', SortDirection.ASC); + + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + + return this.notificationsBrokerSourceRestService.getSources(findListOptions).pipe( + find((rd: RemoteData>) => !rd.isResponsePending), + map((rd: RemoteData>) => { + if (rd.hasSucceeded) { + return rd.payload; + } else { + throw new Error('Can\'t retrieve Notifications Broker source from the Broker source REST service'); + } + }) + ); + } +} diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.html b/src/app/notifications/broker/topics/notifications-broker-topics.component.html index 02371a8a6b..8b27778ee9 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.html +++ b/src/app/notifications/broker/topics/notifications-broker-topics.component.html @@ -2,7 +2,7 @@

{{'notifications.broker.title'| translate}}

-

{{'notifications.broker.topics.description'| translate}}

+

{{'notifications.broker.topics.description'| translate:{source: sourceId} }}

diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts b/src/app/notifications/broker/topics/notifications-broker-topics.component.ts index 3bedf6b9d0..f33d3c2fb1 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; -import { distinctUntilChanged, take } from 'rxjs/operators'; +import { distinctUntilChanged, map, take } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; @@ -10,6 +10,8 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { NotificationsStateService } from '../../notifications-state.service'; import { AdminNotificationsBrokerTopicsPageParams } from '../../../admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { ActivatedRoute } from '@angular/router'; +import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; /** * Component to display the Notifications Broker topic list. @@ -48,6 +50,12 @@ export class NotificationsBrokerTopicsComponent implements OnInit { */ protected subs: Subscription[] = []; + /** + * This property represents a sourceId which is used to retrive a topic + * @type {string} + */ + public sourceId: string; + /** * Initialize the component variables. * @param {PaginationService} paginationService @@ -55,8 +63,18 @@ export class NotificationsBrokerTopicsComponent implements OnInit { */ constructor( private paginationService: PaginationService, + private activatedRoute: ActivatedRoute, private notificationsStateService: NotificationsStateService, - ) { } + private notificationsBrokerTopicsService: NotificationsBrokerTopicsService + ) { + this.activatedRoute.paramMap.pipe( + map((params) => params.get('sourceId')), + take(1) + ).subscribe((id: string) => { + this.sourceId = id; + this.notificationsBrokerTopicsService.setSourceId(this.sourceId); + }); + } /** * Component initialization. diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.service.ts b/src/app/notifications/broker/topics/notifications-broker-topics.service.ts index b04229e0d9..80c52a70a9 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.service.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.service.ts @@ -7,6 +7,7 @@ import { FindListOptions } from '../../../core/data/request.models'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; /** * The service handling all Notifications Broker topic requests to the REST service. @@ -22,6 +23,11 @@ export class NotificationsBrokerTopicsService { private notificationsBrokerTopicRestService: NotificationsBrokerTopicRestService ) { } + /** + * sourceId used to get topics + */ + sourceId: string; + /** * Return the list of Notifications Broker topics managing pagination and errors. * @@ -38,7 +44,8 @@ export class NotificationsBrokerTopicsService { const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, currentPage: currentPage, - sort: sortOptions + sort: sortOptions, + searchParams: [new RequestParam('source', this.sourceId)] }; return this.notificationsBrokerTopicRestService.getTopics(findListOptions).pipe( @@ -52,4 +59,12 @@ export class NotificationsBrokerTopicsService { }) ); } + + /** + * set sourceId which is used to get topics + * @param sourceId string + */ + setSourceId(sourceId: string) { + this.sourceId = sourceId; + } } diff --git a/src/app/notifications/notifications-state.service.ts b/src/app/notifications/notifications-state.service.ts index c81c924465..cbee503acd 100644 --- a/src/app/notifications/notifications-state.service.ts +++ b/src/app/notifications/notifications-state.service.ts @@ -8,11 +8,19 @@ import { getNotificationsBrokerTopicsTotalsSelector, isNotificationsBrokerTopicsLoadedSelector, notificationsBrokerTopicsObjectSelector, - isNotificationsBrokerTopicsProcessingSelector + isNotificationsBrokerTopicsProcessingSelector, + notificationsBrokerSourceObjectSelector, + isNotificationsBrokerSourceLoadedSelector, + isNotificationsBrokerSourceProcessingSelector, + getNotificationsBrokerSourceTotalPagesSelector, + getNotificationsBrokerSourceCurrentPageSelector, + getNotificationsBrokerSourceTotalsSelector } from './selectors'; import { NotificationsBrokerTopicObject } from '../core/notifications/broker/models/notifications-broker-topic.model'; import { NotificationsState } from './notifications.reducer'; import { RetrieveAllTopicsAction } from './broker/topics/notifications-broker-topics.actions'; +import { NotificationsBrokerSourceObject } from '../core/notifications/broker/models/notifications-broker-source.model'; +import { RetrieveAllSourceAction } from './broker/source/notifications-broker-source.actions'; /** * The service handling the Notifications State. @@ -113,4 +121,92 @@ export class NotificationsStateService { public dispatchRetrieveNotificationsBrokerTopics(elementsPerPage: number, currentPage: number): void { this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage)); } + + // Notifications Broker source + // -------------------------------------------------------------------------- + + /** + * Returns the list of Notifications Broker source from the state. + * + * @return Observable + * The list of Notifications Broker source. + */ + public getNotificationsBrokerSource(): Observable { + return this.store.pipe(select(notificationsBrokerSourceObjectSelector())); + } + + /** + * Returns the information about the loading status of the Notifications Broker source (if it's running or not). + * + * @return Observable + * 'true' if the source are loading, 'false' otherwise. + */ + public isNotificationsBrokerSourceLoading(): Observable { + return this.store.pipe( + select(isNotificationsBrokerSourceLoadedSelector), + map((loaded: boolean) => !loaded) + ); + } + + /** + * Returns the information about the loading status of the Notifications Broker source (whether or not they were loaded). + * + * @return Observable + * 'true' if the source are loaded, 'false' otherwise. + */ + public isNotificationsBrokerSourceLoaded(): Observable { + return this.store.pipe(select(isNotificationsBrokerSourceLoadedSelector)); + } + + /** + * Returns the information about the processing status of the Notifications Broker source (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the source (ex.: a REST call), 'false' otherwise. + */ + public isNotificationsBrokerSourceProcessing(): Observable { + return this.store.pipe(select(isNotificationsBrokerSourceProcessingSelector)); + } + + /** + * Returns, from the state, the total available pages of the Notifications Broker source. + * + * @return Observable + * The number of the Notifications Broker source pages. + */ + public getNotificationsBrokerSourceTotalPages(): Observable { + return this.store.pipe(select(getNotificationsBrokerSourceTotalPagesSelector)); + } + + /** + * Returns the current page of the Notifications Broker source, from the state. + * + * @return Observable + * The number of the current Notifications Broker source page. + */ + public getNotificationsBrokerSourceCurrentPage(): Observable { + return this.store.pipe(select(getNotificationsBrokerSourceCurrentPageSelector)); + } + + /** + * Returns the total number of the Notifications Broker source. + * + * @return Observable + * The number of the Notifications Broker source. + */ + public getNotificationsBrokerSourceTotals(): Observable { + return this.store.pipe(select(getNotificationsBrokerSourceTotalsSelector)); + } + + /** + * Dispatch a request to change the Notifications Broker source state, retrieving the source from the server. + * + * @param elementsPerPage + * The number of the source per page. + * @param currentPage + * The number of the current page. + */ + public dispatchRetrieveNotificationsBrokerSource(elementsPerPage: number, currentPage: number): void { + this.store.dispatch(new RetrieveAllSourceAction(elementsPerPage, currentPage)); + } } diff --git a/src/app/notifications/notifications.effects.ts b/src/app/notifications/notifications.effects.ts index cbc76a5b3e..39ecded797 100644 --- a/src/app/notifications/notifications.effects.ts +++ b/src/app/notifications/notifications.effects.ts @@ -1,5 +1,7 @@ +import { NotificationsBrokerSourceEffects } from './broker/source/notifications-broker-source.effects'; import { NotificationsBrokerTopicsEffects } from './broker/topics/notifications-broker-topics.effects'; export const notificationsEffects = [ - NotificationsBrokerTopicsEffects + NotificationsBrokerTopicsEffects, + NotificationsBrokerSourceEffects ]; diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index 4b0ba3cfd1..63224fdd81 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -17,6 +17,9 @@ import { NotificationsBrokerEventRestService } from '../core/notifications/broke import { ProjectEntryImportModalComponent } from './broker/project-entry-import-modal/project-entry-import-modal.component'; import { TranslateModule } from '@ngx-translate/core'; import { SearchModule } from '../shared/search/search.module'; +import { NotificationsBrokerSourceComponent } from './broker/source/notifications-broker-source.component'; +import { NotificationsBrokerSourceService } from './broker/source/notifications-broker-source.service'; +import { NotificationsBrokerSourceRestService } from '../core/notifications/broker/source/notifications-broker-source-rest.service'; const MODULES = [ CommonModule, @@ -29,7 +32,8 @@ const MODULES = [ const COMPONENTS = [ NotificationsBrokerTopicsComponent, - NotificationsBrokerEventsComponent + NotificationsBrokerEventsComponent, + NotificationsBrokerSourceComponent ]; const DIRECTIVES = [ ]; @@ -41,7 +45,9 @@ const ENTRY_COMPONENTS = [ const PROVIDERS = [ NotificationsStateService, NotificationsBrokerTopicsService, + NotificationsBrokerSourceService, NotificationsBrokerTopicRestService, + NotificationsBrokerSourceRestService, NotificationsBrokerEventRestService ]; diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index b3dc54d524..27bebbea20 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -1,5 +1,5 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; - +import { notificationsBrokerSourceReducer, NotificationsBrokerSourceState } from './broker/source/notifications-broker-source.reducer'; import { notificationsBrokerTopicsReducer, NotificationsBrokerTopicState, } from './broker/topics/notifications-broker-topics.reducer'; /** @@ -7,10 +7,12 @@ import { notificationsBrokerTopicsReducer, NotificationsBrokerTopicState, } from */ export interface NotificationsState { 'brokerTopic': NotificationsBrokerTopicState; + 'brokerSource': NotificationsBrokerSourceState; } export const notificationsReducers: ActionReducerMap = { brokerTopic: notificationsBrokerTopicsReducer, + brokerSource: notificationsBrokerSourceReducer }; export const notificationsSelector = createFeatureSelector('notifications'); diff --git a/src/app/notifications/selectors.ts b/src/app/notifications/selectors.ts index 7474aa3adc..0436a35eb3 100644 --- a/src/app/notifications/selectors.ts +++ b/src/app/notifications/selectors.ts @@ -3,6 +3,8 @@ import { subStateSelector } from '../shared/selector.util'; import { notificationsSelector, NotificationsState } from './notifications.reducer'; import { NotificationsBrokerTopicObject } from '../core/notifications/broker/models/notifications-broker-topic.model'; import { NotificationsBrokerTopicState } from './broker/topics/notifications-broker-topics.reducer'; +import { NotificationsBrokerSourceState } from './broker/source/notifications-broker-source.reducer'; +import { NotificationsBrokerSourceObject } from '../core/notifications/broker/models/notifications-broker-source.model'; /** * Returns the Notifications state. @@ -77,3 +79,69 @@ export const getNotificationsBrokerTopicsCurrentPageSelector = createSelector(_g export const getNotificationsBrokerTopicsTotalsSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.totalElements ); + +// Notifications Broker source +// ---------------------------------------------------------------------------- + +/** + * Returns the Notifications Broker source State. + * @function notificationsBrokerSourceStateSelector + * @return {NotificationsBrokerSourceState} + */ + export function notificationsBrokerSourceStateSelector(): MemoizedSelector { + return subStateSelector(notificationsSelector, 'brokerSource'); +} + +/** + * Returns the Notifications Broker source list. + * @function notificationsBrokerSourceObjectSelector + * @return {NotificationsBrokerSourceObject[]} + */ +export function notificationsBrokerSourceObjectSelector(): MemoizedSelector { + return subStateSelector(notificationsBrokerSourceStateSelector(), 'source'); +} + +/** + * Returns true if the Notifications Broker source are loaded. + * @function isNotificationsBrokerSourceLoadedSelector + * @return {boolean} + */ +export const isNotificationsBrokerSourceLoadedSelector = createSelector(_getNotificationsState, + (state: NotificationsState) => state.brokerSource.loaded +); + +/** + * Returns true if the deduplication sets are processing. + * @function isDeduplicationSetsProcessingSelector + * @return {boolean} + */ +export const isNotificationsBrokerSourceProcessingSelector = createSelector(_getNotificationsState, + (state: NotificationsState) => state.brokerSource.processing +); + +/** + * Returns the total available pages of Notifications Broker source. + * @function getNotificationsBrokerSourceTotalPagesSelector + * @return {number} + */ +export const getNotificationsBrokerSourceTotalPagesSelector = createSelector(_getNotificationsState, + (state: NotificationsState) => state.brokerSource.totalPages +); + +/** + * Returns the current page of Notifications Broker source. + * @function getNotificationsBrokerSourceCurrentPageSelector + * @return {number} + */ +export const getNotificationsBrokerSourceCurrentPageSelector = createSelector(_getNotificationsState, + (state: NotificationsState) => state.brokerSource.currentPage +); + +/** + * Returns the total number of Notifications Broker source. + * @function getNotificationsBrokerSourceTotalsSelector + * @return {number} + */ +export const getNotificationsBrokerSourceTotalsSelector = createSelector(_getNotificationsState, + (state: NotificationsState) => state.brokerSource.totalElements +); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 674254e605..e04792273b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -487,6 +487,8 @@ "admin.notifications.broker.page.title": "Notifications Broker", + "admin.notifications.source.breadcrumbs": "Notifications Source", + "admin.search.breadcrumbs": "Administrative Search", "admin.search.collection.edit": "Edit", @@ -2713,14 +2715,20 @@ "none.listelement.badge": "Item", - "notifications.broker.title": "{{source}} Broker", + "notifications.broker.title": "Broker Title", "notifications.broker.topics.description": "Below you can see all the topics received from the subscriptions to {{source}}.", + "notifications.broker.source.description": "Below you can see all the sources.", + "notifications.broker.topics": "Current Topics", + "notifications.broker.source": "Current Sources", + "notifications.broker.table.topic": "Topic", + "notifications.broker.table.source": "Source", + "notifications.broker.table.last-event": "Last Event", "notifications.broker.table.actions": "Actions", @@ -2729,10 +2737,14 @@ "notifications.broker.noTopics": "No topics found.", + "notifications.broker.noSource": "No sources found.", + "notifications.events.title": "{{source}} Broker Suggestions", "notifications.broker.topic.error.service.retrieve": "An error occurred while loading the Notifications Broker topics", + "notifications.broker.source.error.service.retrieve": "An error occurred while loading the Notifications Broker source", + "notifications.broker.events.description": "Below the list of all the suggestions, received from {{source}}, for the selected topic.", "notifications.broker.loading": "Loading ...", From 00f7fa97f1462d5370a50025c63e2dd97cc27d74 Mon Sep 17 00:00:00 2001 From: Pratik Rajkotiya Date: Thu, 10 Mar 2022 11:49:12 +0530 Subject: [PATCH 004/153] [CST-5337] test cases done. --- config/config.yml | 4 +- ...tions-broker-source-page.component.spec.ts | 6 +- ...cations-broker-source-rest.service.spec.ts | 127 +++ ...ifications-broker-source.component.spec.ts | 159 +++- ...otifications-broker-source.reducer.spec.ts | 68 ++ ...otifications-broker-source.service.spec.ts | 68 ++ ...ifications-broker-topics.component.spec.ts | 15 +- .../notifications-broker-topics.component.ts | 9 +- ...otifications-broker-topics.service.spec.ts | 5 +- .../notifications-state.service.spec.ts | 732 ++++++++++++------ src/app/shared/mocks/notifications.mock.ts | 58 ++ 11 files changed, 986 insertions(+), 265 deletions(-) create mode 100644 src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts create mode 100644 src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts create mode 100644 src/app/notifications/broker/source/notifications-broker-source.service.spec.ts diff --git a/config/config.yml b/config/config.yml index b5eecd112f..3866797f5d 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,5 +1,5 @@ rest: - ssl: true - host: api7.dspace.org + ssl: false + host: localhost:8080 port: 443 nameSpace: /server diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts index c4a3611c58..f6d3eb20fe 100644 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts +++ b/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts @@ -1,3 +1,4 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AdminNotificationsBrokerSourcePageComponent } from './admin-notifications-broker-source-page.component'; @@ -8,7 +9,8 @@ describe('AdminNotificationsBrokerSourcePageComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ AdminNotificationsBrokerSourcePageComponent ] + declarations: [ AdminNotificationsBrokerSourcePageComponent ], + schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); }); @@ -19,7 +21,7 @@ describe('AdminNotificationsBrokerSourcePageComponent', () => { fixture.detectChanges(); }); - it('should create', () => { + it('should create AdminNotificationsBrokerSourcePageComponent', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts b/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts new file mode 100644 index 0000000000..984f44bd15 --- /dev/null +++ b/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts @@ -0,0 +1,127 @@ +import { HttpClient } from '@angular/common/http'; + +import { TestScheduler } from 'rxjs/testing'; +import { of as observableOf } from 'rxjs'; +import { cold, getTestScheduler } from 'jasmine-marbles'; + +import { RequestService } from '../../../data/request.service'; +import { buildPaginatedList } from '../../../data/paginated-list.model'; +import { RequestEntry } from '../../../data/request.reducer'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { RestResponse } from '../../../cache/response.models'; +import { PageInfo } from '../../../shared/page-info.model'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; +import { NotificationsBrokerSourceRestService } from './notifications-broker-source-rest.service'; +import { + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMorePid +} from '../../../../shared/mocks/notifications.mock'; + +describe('NotificationsBrokerSourceRestService', () => { + let scheduler: TestScheduler; + let service: NotificationsBrokerSourceRestService; + let responseCacheEntry: RequestEntry; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparator: any; + + const endpointURL = 'https://rest.api/rest/api/integration/nbsources'; + const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; + + const pageInfo = new PageInfo(); + const array = [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const brokerSourceObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerSourceObjectMorePid); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + + beforeEach(() => { + scheduler = getTestScheduler(); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: cold('(a)', { + a: brokerSourceObjectRD + }), + buildList: cold('(a)', { + a: paginatedListRD + }), + }); + + objectCache = {} as ObjectCacheService; + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a|', { a: endpointURL }) + }); + + notificationsService = {} as NotificationsService; + http = {} as HttpClient; + comparator = {} as any; + + service = new NotificationsBrokerSourceRestService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + http, + comparator + ); + + spyOn((service as any).dataService, 'findAllByHref').and.callThrough(); + spyOn((service as any).dataService, 'findByHref').and.callThrough(); + }); + + describe('getSources', () => { + it('should proxy the call to dataservice.findAllByHref', (done) => { + service.getSources().subscribe( + (res) => { + expect((service as any).dataService.findAllByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + } + ); + done(); + }); + + it('should return a RemoteData> for the object with the given URL', () => { + const result = service.getSources(); + const expected = cold('(a)', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getSource', () => { + it('should proxy the call to dataservice.findByHref', (done) => { + service.getSource(notificationsBrokerSourceObjectMorePid.id).subscribe( + (res) => { + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + notificationsBrokerSourceObjectMorePid.id, true, true); + } + ); + done(); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getSource(notificationsBrokerSourceObjectMorePid.id); + const expected = cold('(a)', { + a: brokerSourceObjectRD + }); + expect(result).toBeObservable(expected); + }); + }); + +}); diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts b/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts index 7d18c726c5..6c0ad42ce8 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts +++ b/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts @@ -1,25 +1,152 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - +import { CommonModule } from '@angular/common'; +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; +import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { + getMockNotificationsStateService, + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMorePid +} from '../../../shared/mocks/notifications.mock'; import { NotificationsBrokerSourceComponent } from './notifications-broker-source.component'; +import { NotificationsStateService } from '../../notifications-state.service'; +import { cold } from 'jasmine-marbles'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../../core/pagination/pagination.service'; -describe('NotificationsBrokerSourceComponent', () => { - let component: NotificationsBrokerSourceComponent; +describe('NotificationsBrokerSourceComponent test suite', () => { let fixture: ComponentFixture; + let comp: NotificationsBrokerSourceComponent; + let compAsAny: any; + const mockNotificationsStateService = getMockNotificationsStateService(); + const activatedRouteParams = { + notificationsBrokerSourceParams: { + currentPage: 0, + pageSize: 5 + } + }; + const paginationService = new PaginationServiceStub(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ NotificationsBrokerSourceComponent ] - }) - .compileComponents(); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot(), + ], + declarations: [ + NotificationsBrokerSourceComponent, + TestComponent, + ], + providers: [ + { provide: NotificationsStateService, useValue: mockNotificationsStateService }, + { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), params: observableOf({}) } }, + { provide: PaginationService, useValue: paginationService }, + NotificationsBrokerSourceComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(() => { + mockNotificationsStateService.getNotificationsBrokerSource.and.returnValue(observableOf([ + notificationsBrokerSourceObjectMorePid, + notificationsBrokerSourceObjectMoreAbstract + ])); + mockNotificationsStateService.getNotificationsBrokerSourceTotalPages.and.returnValue(observableOf(1)); + mockNotificationsStateService.getNotificationsBrokerSourceCurrentPage.and.returnValue(observableOf(0)); + mockNotificationsStateService.getNotificationsBrokerSourceTotals.and.returnValue(observableOf(2)); + mockNotificationsStateService.isNotificationsBrokerSourceLoaded.and.returnValue(observableOf(true)); + mockNotificationsStateService.isNotificationsBrokerSourceLoading.and.returnValue(observableOf(false)); + mockNotificationsStateService.isNotificationsBrokerSourceProcessing.and.returnValue(observableOf(false)); + }); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create NotificationsBrokerSourceComponent', inject([NotificationsBrokerSourceComponent], (app: NotificationsBrokerSourceComponent) => { + expect(app).toBeDefined(); + })); }); - beforeEach(() => { - fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + describe('Main tests running with two Source', () => { + beforeEach(() => { + fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); + comp = fixture.componentInstance; + compAsAny = comp; - it('should create', () => { - expect(component).toBeTruthy(); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it(('Should init component properly'), () => { + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.sources$).toBeObservable(cold('(a|)', { + a: [ + notificationsBrokerSourceObjectMorePid, + notificationsBrokerSourceObjectMoreAbstract + ] + })); + expect(comp.totalElements$).toBeObservable(cold('(a|)', { + a: 2 + })); + }); + + it(('Should set data properly after the view init'), () => { + spyOn(compAsAny, 'getNotificationsBrokerSource'); + + comp.ngAfterViewInit(); + fixture.detectChanges(); + + expect(compAsAny.getNotificationsBrokerSource).toHaveBeenCalled(); + }); + + it(('isSourceLoading should return FALSE'), () => { + expect(comp.isSourceLoading()).toBeObservable(cold('(a|)', { + a: false + })); + }); + + it(('isSourceProcessing should return FALSE'), () => { + expect(comp.isSourceProcessing()).toBeObservable(cold('(a|)', { + a: false + })); + }); + + it(('getNotificationsBrokerSource should call the service to dispatch a STATE change'), () => { + comp.ngOnInit(); + fixture.detectChanges(); + + compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerSource(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); + expect(compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerSource).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); + }); }); }); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts b/src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts new file mode 100644 index 0000000000..74bc77d3ec --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts @@ -0,0 +1,68 @@ +import { + AddSourceAction, + RetrieveAllSourceAction, + RetrieveAllSourceErrorAction + } from './notifications-broker-source.actions'; + import { notificationsBrokerSourceReducer, NotificationsBrokerSourceState } from './notifications-broker-source.reducer'; + import { + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMorePid + } from '../../../shared/mocks/notifications.mock'; + + describe('notificationsBrokerSourceReducer test suite', () => { + let notificationsBrokerSourceInitialState: NotificationsBrokerSourceState; + const elementPerPage = 3; + const currentPage = 0; + + beforeEach(() => { + notificationsBrokerSourceInitialState = { + source: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }; + }); + + it('Action RETRIEVE_ALL_SOURCE should set the State property "processing" to TRUE', () => { + const expectedState = notificationsBrokerSourceInitialState; + expectedState.processing = true; + + const action = new RetrieveAllSourceAction(elementPerPage, currentPage); + const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + + expect(newState).toEqual(expectedState); + }); + + it('Action RETRIEVE_ALL_SOURCE_ERROR should change the State to initial State but processing, loaded, and currentPage', () => { + const expectedState = notificationsBrokerSourceInitialState; + expectedState.processing = false; + expectedState.loaded = true; + expectedState.currentPage = 0; + + const action = new RetrieveAllSourceErrorAction(); + const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + + expect(newState).toEqual(expectedState); + }); + + it('Action ADD_SOURCE should populate the State with Notifications Broker source', () => { + const expectedState = { + source: [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ], + processing: false, + loaded: true, + totalPages: 1, + currentPage: 0, + totalElements: 2 + }; + + const action = new AddSourceAction( + [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ], + 1, 0, 2 + ); + const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + + expect(newState).toEqual(expectedState); + }); + }); diff --git a/src/app/notifications/broker/source/notifications-broker-source.service.spec.ts b/src/app/notifications/broker/source/notifications-broker-source.service.spec.ts new file mode 100644 index 0000000000..e94804cbf6 --- /dev/null +++ b/src/app/notifications/broker/source/notifications-broker-source.service.spec.ts @@ -0,0 +1,68 @@ +import { TestBed } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; +import { NotificationsBrokerSourceService } from './notifications-broker-source.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { + getMockNotificationsBrokerSourceRestService, + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMorePid +} from '../../../shared/mocks/notifications.mock'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { cold } from 'jasmine-marbles'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; + +describe('NotificationsBrokerSourceService', () => { + let service: NotificationsBrokerSourceService; + let restService: NotificationsBrokerSourceRestService; + let serviceAsAny: any; + let restServiceAsAny: any; + + const pageInfo = new PageInfo(); + const array = [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ]; + const paginatedList = buildPaginatedList(pageInfo, array); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + const elementsPerPage = 3; + const currentPage = 0; + + beforeEach(async () => { + TestBed.configureTestingModule({ + providers: [ + { provide: NotificationsBrokerSourceRestService, useClass: getMockNotificationsBrokerSourceRestService }, + { provide: NotificationsBrokerSourceService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + restService = TestBed.get(NotificationsBrokerSourceRestService); + restServiceAsAny = restService; + restServiceAsAny.getSources.and.returnValue(observableOf(paginatedListRD)); + service = new NotificationsBrokerSourceService(restService); + serviceAsAny = service; + }); + + describe('getSources', () => { + it('Should proxy the call to notificationsBrokerSourceRestService.getSources', () => { + const sortOptions = new SortOptions('name', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + const result = service.getSources(elementsPerPage, currentPage); + expect((service as any).notificationsBrokerSourceRestService.getSources).toHaveBeenCalledWith(findListOptions); + }); + + it('Should return a paginated list of Notifications Broker Source', () => { + const expected = cold('(a|)', { + a: paginatedList + }); + const result = service.getSources(elementsPerPage, currentPage); + expect(result).toBeObservable(expected); + }); + }); +}); diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts b/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts index 5bbe3b2907..dbb8137321 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts @@ -1,8 +1,8 @@ import { CommonModule } from '@angular/common'; import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; import { createTestComponent } from '../../../shared/testing/utils.test'; import { @@ -15,6 +15,7 @@ import { NotificationsStateService } from '../../notifications-state.service'; import { cold } from 'jasmine-marbles'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; describe('NotificationsBrokerTopicsComponent test suite', () => { let fixture: ComponentFixture; @@ -41,9 +42,15 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { ], providers: [ { provide: NotificationsStateService, useValue: mockNotificationsStateService }, - { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), params: observableOf({}) } }, + { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), snapshot: { + paramMap: { + get: () => 'openaire', + }, + }}}, { provide: PaginationService, useValue: paginationService }, - NotificationsBrokerTopicsComponent + NotificationsBrokerTopicsComponent, + // tslint:disable-next-line: no-empty + { provide: NotificationsBrokerTopicsService, useValue: { setSourceId: (sourceId: string) => { } }} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(() => { diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts b/src/app/notifications/broker/topics/notifications-broker-topics.component.ts index f33d3c2fb1..a740ca5c1e 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.component.ts @@ -67,19 +67,14 @@ export class NotificationsBrokerTopicsComponent implements OnInit { private notificationsStateService: NotificationsStateService, private notificationsBrokerTopicsService: NotificationsBrokerTopicsService ) { - this.activatedRoute.paramMap.pipe( - map((params) => params.get('sourceId')), - take(1) - ).subscribe((id: string) => { - this.sourceId = id; - this.notificationsBrokerTopicsService.setSourceId(this.sourceId); - }); } /** * Component initialization. */ ngOnInit(): void { + this.sourceId = this.activatedRoute.snapshot.paramMap.get('sourceId'); + this.notificationsBrokerTopicsService.setSourceId(this.sourceId); this.topics$ = this.notificationsStateService.getNotificationsBrokerTopics(); this.totalElements$ = this.notificationsStateService.getNotificationsBrokerTopicsTotals(); } diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts b/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts index 3b780fc173..e5616df320 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts +++ b/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts @@ -13,6 +13,7 @@ import { import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; describe('NotificationsBrokerTopicsService', () => { let service: NotificationsBrokerTopicsService; @@ -50,8 +51,10 @@ describe('NotificationsBrokerTopicsService', () => { const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, currentPage: currentPage, - sort: sortOptions + sort: sortOptions, + searchParams: [new RequestParam('source', 'ENRICH!MORE!ABSTRACT')] }; + service.setSourceId('ENRICH!MORE!ABSTRACT'); const result = service.getTopics(elementsPerPage, currentPage); expect((service as any).notificationsBrokerTopicRestService.getTopics).toHaveBeenCalledWith(findListOptions); }); diff --git a/src/app/notifications/notifications-state.service.spec.ts b/src/app/notifications/notifications-state.service.spec.ts index 97d958e243..91048a93ef 100644 --- a/src/app/notifications/notifications-state.service.spec.ts +++ b/src/app/notifications/notifications-state.service.spec.ts @@ -5,11 +5,15 @@ import { cold } from 'jasmine-marbles'; import { notificationsReducers } from './notifications.reducer'; import { NotificationsStateService } from './notifications-state.service'; import { + notificationsBrokerSourceObjectMissingPid, + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMorePid, notificationsBrokerTopicObjectMissingPid, notificationsBrokerTopicObjectMoreAbstract, notificationsBrokerTopicObjectMorePid } from '../shared/mocks/notifications.mock'; import { RetrieveAllTopicsAction } from './broker/topics/notifications-broker-topics.actions'; +import { RetrieveAllSourceAction } from './broker/source/notifications-broker-source.actions'; describe('NotificationsStateService', () => { let service: NotificationsStateService; @@ -17,259 +21,521 @@ describe('NotificationsStateService', () => { let store: any; let initialState: any; - function init(mode: string) { - if (mode === 'empty') { - initialState = { - notifications: { - brokerTopic: { - topics: [], - processing: false, - loaded: false, - totalPages: 0, - currentPage: 0, - totalElements: 0, - totalLoadedPages: 0 + describe('Topis State', () => { + function init(mode: string) { + if (mode === 'empty') { + initialState = { + notifications: { + brokerTopic: { + topics: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0, + totalLoadedPages: 0 + } } - } - }; - } else { - initialState = { - notifications: { - brokerTopic: { - topics: [ + }; + } else { + initialState = { + notifications: { + brokerTopic: { + topics: [ + notificationsBrokerTopicObjectMorePid, + notificationsBrokerTopicObjectMoreAbstract, + notificationsBrokerTopicObjectMissingPid + ], + processing: false, + loaded: true, + totalPages: 1, + currentPage: 1, + totalElements: 3, + totalLoadedPages: 1 + } + } + }; + } + } + + describe('Testing methods with empty topic objects', () => { + beforeEach(async () => { + init('empty'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getNotificationsBrokerTopics', () => { + it('Should return an empty array', () => { + const result = service.getNotificationsBrokerTopics(); + const expected = cold('(a)', { + a: [] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsTotalPages', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerTopicsTotalPages(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsCurrentPage', () => { + it('Should return minus one (0)', () => { + const result = service.getNotificationsBrokerTopicsCurrentPage(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsTotals', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerTopicsTotals(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsLoading', () => { + it('Should return TRUE', () => { + const result = service.isNotificationsBrokerTopicsLoading(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsLoaded', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerTopicsLoaded(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsProcessing', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerTopicsProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + }); + + describe('Testing methods with topic objects', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getNotificationsBrokerTopics', () => { + it('Should return an array of topics', () => { + const result = service.getNotificationsBrokerTopics(); + const expected = cold('(a)', { + a: [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract, notificationsBrokerTopicObjectMissingPid - ], - processing: false, - loaded: true, - totalPages: 1, - currentPage: 1, - totalElements: 3, - totalLoadedPages: 1 - } - } - }; - } - } - - describe('Testing methods with empty topic objects', () => { - beforeEach(async () => { - init('empty'); - TestBed.configureTestingModule({ - imports: [ - StoreModule.forRoot({ notifications: notificationsReducers } as any), - ], - providers: [ - provideMockStore({ initialState }), - { provide: NotificationsStateService, useValue: service } - ] - }).compileComponents(); - }); - - beforeEach(() => { - store = TestBed.get(Store); - service = new NotificationsStateService(store); - serviceAsAny = service; - spyOn(store, 'dispatch'); - }); - - describe('getNotificationsBrokerTopics', () => { - it('Should return an empty array', () => { - const result = service.getNotificationsBrokerTopics(); - const expected = cold('(a)', { - a: [] + ] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsTotalPages', () => { + it('Should return one (1)', () => { + const result = service.getNotificationsBrokerTopicsTotalPages(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsCurrentPage', () => { + it('Should return minus zero (1)', () => { + const result = service.getNotificationsBrokerTopicsCurrentPage(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerTopicsTotals', () => { + it('Should return three (3)', () => { + const result = service.getNotificationsBrokerTopicsTotals(); + const expected = cold('(a)', { + a: 3 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsLoading', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerTopicsLoading(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsLoaded', () => { + it('Should return TRUE', () => { + const result = service.isNotificationsBrokerTopicsLoaded(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerTopicsProcessing', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerTopicsProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); }); - describe('getNotificationsBrokerTopicsTotalPages', () => { - it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); - const expected = cold('(a)', { - a: 0 - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('getNotificationsBrokerTopicsCurrentPage', () => { - it('Should return minus one (0)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); - const expected = cold('(a)', { - a: 0 - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('getNotificationsBrokerTopicsTotals', () => { - it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); - const expected = cold('(a)', { - a: 0 - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsLoading', () => { - it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); - const expected = cold('(a)', { - a: true - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsLoaded', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); - const expected = cold('(a)', { - a: false - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsProcessing', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); - const expected = cold('(a)', { - a: false - }); - expect(result).toBeObservable(expected); - }); - }); - }); - - describe('Testing methods with topic objects', () => { - beforeEach(async () => { - init('full'); - TestBed.configureTestingModule({ - imports: [ - StoreModule.forRoot({ notifications: notificationsReducers } as any), - ], - providers: [ - provideMockStore({ initialState }), - { provide: NotificationsStateService, useValue: service } - ] - }).compileComponents(); - }); - - beforeEach(() => { - store = TestBed.get(Store); - service = new NotificationsStateService(store); - serviceAsAny = service; - spyOn(store, 'dispatch'); - }); - - describe('getNotificationsBrokerTopics', () => { - it('Should return an array of topics', () => { - const result = service.getNotificationsBrokerTopics(); - const expected = cold('(a)', { - a: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMissingPid + describe('Testing the topic dispatch methods', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } ] - }); - expect(result).toBeObservable(expected); + }).compileComponents(); }); - }); - describe('getNotificationsBrokerTopicsTotalPages', () => { - it('Should return one (1)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); - const expected = cold('(a)', { - a: 1 - }); - expect(result).toBeObservable(expected); + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); }); - }); - describe('getNotificationsBrokerTopicsCurrentPage', () => { - it('Should return minus zero (1)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); - const expected = cold('(a)', { - a: 1 + describe('dispatchRetrieveNotificationsBrokerTopics', () => { + it('Should call store.dispatch', () => { + const elementsPerPage = 3; + const currentPage = 1; + const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage); + service.dispatchRetrieveNotificationsBrokerTopics(elementsPerPage, currentPage); + expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); }); - expect(result).toBeObservable(expected); - }); - }); - - describe('getNotificationsBrokerTopicsTotals', () => { - it('Should return three (3)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); - const expected = cold('(a)', { - a: 3 - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsLoading', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); - const expected = cold('(a)', { - a: false - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsLoaded', () => { - it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); - const expected = cold('(a)', { - a: true - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('isNotificationsBrokerTopicsProcessing', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); - const expected = cold('(a)', { - a: false - }); - expect(result).toBeObservable(expected); }); }); }); - describe('Testing the topic dispatch methods', () => { - beforeEach(async () => { - init('full'); - TestBed.configureTestingModule({ - imports: [ - StoreModule.forRoot({ notifications: notificationsReducers } as any), - ], - providers: [ - provideMockStore({ initialState }), - { provide: NotificationsStateService, useValue: service } - ] - }).compileComponents(); - }); + describe('Source State', () => { + function init(mode: string) { + if (mode === 'empty') { + initialState = { + notifications: { + brokerSource: { + source: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0, + totalLoadedPages: 0 + } + } + }; + } else { + initialState = { + notifications: { + brokerSource: { + source: [ + notificationsBrokerSourceObjectMorePid, + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMissingPid + ], + processing: false, + loaded: true, + totalPages: 1, + currentPage: 1, + totalElements: 3, + totalLoadedPages: 1 + } + } + }; + } + } - beforeEach(() => { - store = TestBed.get(Store); - service = new NotificationsStateService(store); - serviceAsAny = service; - spyOn(store, 'dispatch'); - }); + describe('Testing methods with empty source objects', () => { + beforeEach(async () => { + init('empty'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } + ] + }).compileComponents(); + }); - describe('dispatchRetrieveNotificationsBrokerTopics', () => { - it('Should call store.dispatch', () => { - const elementsPerPage = 3; - const currentPage = 1; - const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage); - service.dispatchRetrieveNotificationsBrokerTopics(elementsPerPage, currentPage); - expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getNotificationsBrokerSource', () => { + it('Should return an empty array', () => { + const result = service.getNotificationsBrokerSource(); + const expected = cold('(a)', { + a: [] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourceTotalPages', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerSourceTotalPages(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourcesCurrentPage', () => { + it('Should return minus one (0)', () => { + const result = service.getNotificationsBrokerSourceCurrentPage(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourceTotals', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerSourceTotals(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceLoading', () => { + it('Should return TRUE', () => { + const result = service.isNotificationsBrokerSourceLoading(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceLoaded', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceLoaded(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceProcessing', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); }); }); - }); + + describe('Testing methods with Source objects', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('getNotificationsBrokerSource', () => { + it('Should return an array of Source', () => { + const result = service.getNotificationsBrokerSource(); + const expected = cold('(a)', { + a: [ + notificationsBrokerSourceObjectMorePid, + notificationsBrokerSourceObjectMoreAbstract, + notificationsBrokerSourceObjectMissingPid + ] + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourceTotalPages', () => { + it('Should return one (1)', () => { + const result = service.getNotificationsBrokerSourceTotalPages(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourceCurrentPage', () => { + it('Should return minus zero (1)', () => { + const result = service.getNotificationsBrokerSourceCurrentPage(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('getNotificationsBrokerSourceTotals', () => { + it('Should return three (3)', () => { + const result = service.getNotificationsBrokerSourceTotals(); + const expected = cold('(a)', { + a: 3 + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceLoading', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceLoading(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceLoaded', () => { + it('Should return TRUE', () => { + const result = service.isNotificationsBrokerSourceLoaded(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('isNotificationsBrokerSourceProcessing', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); + }); + }); + }); + + describe('Testing the Source dispatch methods', () => { + beforeEach(async () => { + init('full'); + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({ notifications: notificationsReducers } as any), + ], + providers: [ + provideMockStore({ initialState }), + { provide: NotificationsStateService, useValue: service } + ] + }).compileComponents(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + describe('dispatchRetrieveNotificationsBrokerSource', () => { + it('Should call store.dispatch', () => { + const elementsPerPage = 3; + const currentPage = 1; + const action = new RetrieveAllSourceAction(elementsPerPage, currentPage); + service.dispatchRetrieveNotificationsBrokerSource(elementsPerPage, currentPage); + expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); + }); + }); + }); + }); + + }); diff --git a/src/app/shared/mocks/notifications.mock.ts b/src/app/shared/mocks/notifications.mock.ts index 2e9303c3a3..8af034ea32 100644 --- a/src/app/shared/mocks/notifications.mock.ts +++ b/src/app/shared/mocks/notifications.mock.ts @@ -13,6 +13,7 @@ import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { SearchResult } from '../search/models/search-result.model'; +import { NotificationsBrokerSourceObject } from '../../core/notifications/broker/models/notifications-broker-source.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- @@ -1329,6 +1330,45 @@ export const NotificationsMockDspaceObject: SearchResult = Object. } ); +// Sources +// ------------------------------------------------------------------------------- + +export const notificationsBrokerSourceObjectMorePid: NotificationsBrokerSourceObject = { + type: new ResourceType('nbsource'), + id: 'ENRICH!MORE!PID', + lastEvent: '2020/10/09 10:11 UTC', + totalEvents: 33, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbsources/ENRICH!MORE!PID' + } + } +}; + +export const notificationsBrokerSourceObjectMoreAbstract: NotificationsBrokerSourceObject = { + type: new ResourceType('nbsource'), + id: 'ENRICH!MORE!ABSTRACT', + lastEvent: '2020/09/08 21:14 UTC', + totalEvents: 5, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbsources/ENRICH!MORE!ABSTRACT' + } + } +}; + +export const notificationsBrokerSourceObjectMissingPid: NotificationsBrokerSourceObject = { + type: new ResourceType('nbsource'), + id: 'ENRICH!MISSING!PID', + lastEvent: '2020/10/01 07:36 UTC', + totalEvents: 4, + _links: { + self: { + href: 'https://rest.api/rest/api/integration/nbsources/ENRICH!MISSING!PID' + } + } +}; + // Topics // ------------------------------------------------------------------------------- @@ -1753,10 +1793,28 @@ export function getMockNotificationsStateService(): any { getNotificationsBrokerTopicsCurrentPage: jasmine.createSpy('getNotificationsBrokerTopicsCurrentPage'), getNotificationsBrokerTopicsTotals: jasmine.createSpy('getNotificationsBrokerTopicsTotals'), dispatchRetrieveNotificationsBrokerTopics: jasmine.createSpy('dispatchRetrieveNotificationsBrokerTopics'), + getNotificationsBrokerSource: jasmine.createSpy('getNotificationsBrokerSource'), + isNotificationsBrokerSourceLoading: jasmine.createSpy('isNotificationsBrokerSourceLoading'), + isNotificationsBrokerSourceLoaded: jasmine.createSpy('isNotificationsBrokerSourceLoaded'), + isNotificationsBrokerSourceProcessing: jasmine.createSpy('isNotificationsBrokerSourceProcessing'), + getNotificationsBrokerSourceTotalPages: jasmine.createSpy('getNotificationsBrokerSourceTotalPages'), + getNotificationsBrokerSourceCurrentPage: jasmine.createSpy('getNotificationsBrokerSourceCurrentPage'), + getNotificationsBrokerSourceTotals: jasmine.createSpy('getNotificationsBrokerSourceTotals'), + dispatchRetrieveNotificationsBrokerSource: jasmine.createSpy('dispatchRetrieveNotificationsBrokerSource'), dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') }); } +/** + * Mock for [[NotificationsBrokerSourceRestService]] + */ + export function getMockNotificationsBrokerSourceRestService(): NotificationsBrokerTopicRestService { + return jasmine.createSpyObj('NotificationsBrokerSourceRestService', { + getSources: jasmine.createSpy('getSources'), + getSource: jasmine.createSpy('getSource'), + }); +} + /** * Mock for [[NotificationsBrokerTopicRestService]] */ From d63bf55458bd9cab6a417107c14325b3add16b85 Mon Sep 17 00:00:00 2001 From: Pratik Rajkotiya Date: Thu, 10 Mar 2022 11:56:39 +0530 Subject: [PATCH 005/153] [CST-5337] change end point. --- config/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.yml b/config/config.yml index 3866797f5d..b5eecd112f 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,5 +1,5 @@ rest: - ssl: false - host: localhost:8080 + ssl: true + host: api7.dspace.org port: 443 nameSpace: /server From 6dfeb1a06b0310f3a087fb3c10b7f5d2f10aecc7 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Thu, 17 Mar 2022 16:53:59 +0100 Subject: [PATCH 006/153] [CST-5337] Fixed notifications labels --- src/assets/i18n/en.json5 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 72d22fb502..873fad622c 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2716,11 +2716,11 @@ "none.listelement.badge": "Item", - "notifications.broker.title": "Broker Title", + "notifications.broker.title": "Notifications", "notifications.broker.topics.description": "Below you can see all the topics received from the subscriptions to {{source}}.", - "notifications.broker.source.description": "Below you can see all the sources.", + "notifications.broker.source.description": "Below you can see all the notification's sources.", "notifications.broker.topics": "Current Topics", @@ -2740,13 +2740,13 @@ "notifications.broker.noSource": "No sources found.", - "notifications.events.title": "{{source}} Broker Suggestions", + "notifications.events.title": "Broker Suggestions", "notifications.broker.topic.error.service.retrieve": "An error occurred while loading the Notifications Broker topics", "notifications.broker.source.error.service.retrieve": "An error occurred while loading the Notifications Broker source", - "notifications.broker.events.description": "Below the list of all the suggestions, received from {{source}}, for the selected topic.", + "notifications.broker.events.description": "Below the list of all the suggestions for the selected topic.", "notifications.broker.loading": "Loading ...", From d5c1b11d77a67e29e687f94d529764b2bbb410b5 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Wed, 6 Jul 2022 17:04:11 +0200 Subject: [PATCH 007/153] [CST-5337] Replace Notifications broker with Quality assurance --- ...ications-broker-events-page.component.html | 1 - ...tions-broker-events-page.component.spec.ts | 26 --- ...ifications-broker-events-page.component.ts | 9 - ...ications-broker-source-page.component.html | 1 - ...tions-broker-source-page.component.spec.ts | 27 --- ...ifications-broker-source-page.component.ts | 7 - ...ications-broker-topics-page.component.html | 1 - ...tions-broker-topics-page.component.spec.ts | 26 --- ...ifications-broker-topics-page.component.ts | 9 - .../admin-notifications-routing-paths.ts | 6 +- .../admin-notifications-routing.module.ts | 40 ++--- .../admin-notifications.module.ts | 12 +- ...ality-assurance-events-page.component.html | 1 + ...ty-assurance-events-page.component.spec.ts | 26 +++ ...quality-assurance-events-page.component.ts | 9 + ...quality-assurance-events-page.resolver.ts} | 8 +- ...quality-assurance-source-data.reslover.ts} | 18 +- ...assurance-source-page-resolver.service.ts} | 8 +- ...ality-assurance-source-page.component.html | 1 + ...ty-assurance-source-page.component.spec.ts | 27 +++ ...quality-assurance-source-page.component.ts | 7 + ...assurance-topics-page-resolver.service.ts} | 8 +- ...ality-assurance-topics-page.component.html | 1 + ...ty-assurance-topics-page.component.spec.ts | 26 +++ ...quality-assurance-topics-page.component.ts | 9 + src/app/core/core.module.ts | 12 +- ...lity-assurance-event-rest.service.spec.ts} | 56 +++--- .../quality-assurance-event-rest.service.ts} | 60 +++---- ...y-assurance-event-object.resource-type.ts} | 4 +- .../models/quality-assurance-event.model.ts} | 10 +- ...-assurance-source-object.resource-type.ts} | 4 +- .../models/quality-assurance-source.model.ts} | 12 +- ...y-assurance-topic-object.resource-type.ts} | 4 +- .../models/quality-assurance-topic.model.ts} | 14 +- ...ity-assurance-source-rest.service.spec.ts} | 28 +-- .../quality-assurance-source-rest.service.ts} | 42 ++--- ...lity-assurance-topic-rest.service.spec.ts} | 28 +-- .../quality-assurance-topic-rest.service.ts} | 42 ++--- .../notifications-broker-source.reducer.ts | 72 -------- .../notifications-broker-source.service.ts | 55 ------ .../notifications-broker-topics.reducer.ts | 72 -------- .../notifications-state.service.spec.ts | 160 +++++++++--------- .../notifications-state.service.ts | 148 ++++++++-------- .../notifications/notifications.effects.ts | 8 +- src/app/notifications/notifications.module.ts | 34 ++-- .../notifications/notifications.reducer.ts | 12 +- .../quality-assurance-events.component.html} | 6 +- ...uality-assurance-events.component.spec.ts} | 110 ++++++------ .../quality-assurance-events.component.ts} | 118 ++++++------- .../quality-assurance-events.scomponent.scss} | 0 .../project-entry-import-modal.component.html | 0 .../project-entry-import-modal.component.scss | 0 ...oject-entry-import-modal.component.spec.ts | 10 +- .../project-entry-import-modal.component.ts | 18 +- .../quality-assurance-source.actions.ts} | 30 ++-- .../quality-assurance-source.component.html} | 8 +- .../quality-assurance-source.component.scss} | 0 ...uality-assurance-source.component.spec.ts} | 56 +++--- .../quality-assurance-source.component.ts} | 46 ++--- .../quality-assurance-source.effects.ts} | 36 ++-- .../quality-assurance-source.reducer.spec.ts} | 30 ++-- .../quality-assurance-source.reducer.ts | 72 ++++++++ .../quality-assurance-source.service.spec.ts} | 34 ++-- .../quality-assurance-source.service.ts | 55 ++++++ .../quality-assurance-topics.actions.ts} | 30 ++-- .../quality-assurance-topics.component.html} | 2 +- .../quality-assurance-topics.component.scss} | 0 ...uality-assurance-topics.component.spec.ts} | 60 +++---- .../quality-assurance-topics.component.ts} | 54 +++--- .../quality-assurance-topics.effects.ts} | 36 ++-- .../quality-assurance-topics.reducer.spec.ts} | 30 ++-- .../quality-assurance-topics.reducer.ts | 72 ++++++++ .../quality-assurance-topics.service.spec.ts} | 34 ++-- .../quality-assurance-topics.service.ts} | 30 ++-- src/app/notifications/selectors.ts | 104 ++++++------ src/app/shared/mocks/notifications.mock.ts | 114 ++++++------- src/assets/i18n/en.json5 | 10 +- 77 files changed, 1198 insertions(+), 1198 deletions(-) delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.html delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts rename src/app/admin/admin-notifications/{admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts => admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts} (72%) rename src/app/admin/admin-notifications/{admin-notifications-broker-source-page-component/admin-notifications-broker-source-data.reslover.ts => admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.reslover.ts} (61%) rename src/app/admin/admin-notifications/{admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts => admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service.ts} (72%) create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts rename src/app/admin/admin-notifications/{admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service.ts => admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts} (72%) create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts rename src/app/core/notifications/{broker/events/notifications-broker-event-rest.service.spec.ts => qa/events/quality-assurance-event-rest.service.spec.ts} (77%) rename src/app/core/notifications/{broker/events/notifications-broker-event-rest.service.ts => qa/events/quality-assurance-event-rest.service.ts} (71%) rename src/app/core/notifications/{broker/models/notifications-broker-topic-object.resource-type.ts => qa/models/quality-assurance-event-object.resource-type.ts} (53%) rename src/app/core/notifications/{broker/models/notifications-broker-event.model.ts => qa/models/quality-assurance-event.model.ts} (90%) rename src/app/core/notifications/{broker/models/notifications-broker-event-object.resource-type.ts => qa/models/quality-assurance-source-object.resource-type.ts} (53%) rename src/app/core/notifications/{broker/models/notifications-broker-source.model.ts => qa/models/quality-assurance-source.model.ts} (69%) rename src/app/core/notifications/{broker/models/notifications-broker-source-object.resource-type.ts => qa/models/quality-assurance-topic-object.resource-type.ts} (53%) rename src/app/core/notifications/{broker/models/notifications-broker-topic.model.ts => qa/models/quality-assurance-topic.model.ts} (68%) rename src/app/core/notifications/{broker/source/notifications-broker-source-rest.service.spec.ts => qa/source/quality-assurance-source-rest.service.spec.ts} (78%) rename src/app/core/notifications/{broker/source/notifications-broker-source-rest.service.ts => qa/source/quality-assurance-source-rest.service.ts} (72%) rename src/app/core/notifications/{broker/topics/notifications-broker-topic-rest.service.spec.ts => qa/topics/quality-assurance-topic-rest.service.spec.ts} (76%) rename src/app/core/notifications/{broker/topics/notifications-broker-topic-rest.service.ts => qa/topics/quality-assurance-topic-rest.service.ts} (73%) delete mode 100644 src/app/notifications/broker/source/notifications-broker-source.reducer.ts delete mode 100644 src/app/notifications/broker/source/notifications-broker-source.service.ts delete mode 100644 src/app/notifications/broker/topics/notifications-broker-topics.reducer.ts rename src/app/notifications/{broker/events/notifications-broker-events.component.html => qa/events/quality-assurance-events.component.html} (98%) rename src/app/notifications/{broker/events/notifications-broker-events.component.spec.ts => qa/events/quality-assurance-events.component.spec.ts} (66%) rename src/app/notifications/{broker/events/notifications-broker-events.component.ts => qa/events/quality-assurance-events.component.ts} (74%) rename src/app/notifications/{broker/events/notifications-broker-events.scomponent.scss => qa/events/quality-assurance-events.scomponent.scss} (100%) rename src/app/notifications/{broker => qa}/project-entry-import-modal/project-entry-import-modal.component.html (100%) rename src/app/notifications/{broker => qa}/project-entry-import-modal/project-entry-import-modal.component.scss (100%) rename src/app/notifications/{broker => qa}/project-entry-import-modal/project-entry-import-modal.component.spec.ts (95%) rename src/app/notifications/{broker => qa}/project-entry-import-modal/project-entry-import-modal.component.ts (94%) rename src/app/notifications/{broker/source/notifications-broker-source.actions.ts => qa/source/quality-assurance-source.actions.ts} (62%) rename src/app/notifications/{broker/source/notifications-broker-source.component.html => qa/source/quality-assurance-source.component.html} (97%) rename src/app/notifications/{broker/source/notifications-broker-source.component.scss => qa/source/quality-assurance-source.component.scss} (100%) rename src/app/notifications/{broker/source/notifications-broker-source.component.spec.ts => qa/source/quality-assurance-source.component.spec.ts} (60%) rename src/app/notifications/{broker/source/notifications-broker-source.component.ts => qa/source/quality-assurance-source.component.ts} (64%) rename src/app/notifications/{broker/source/notifications-broker-source.effects.ts => qa/source/quality-assurance-source.effects.ts} (59%) rename src/app/notifications/{broker/source/notifications-broker-source.reducer.spec.ts => qa/source/quality-assurance-source.reducer.spec.ts} (52%) create mode 100644 src/app/notifications/qa/source/quality-assurance-source.reducer.ts rename src/app/notifications/{broker/source/notifications-broker-source.service.spec.ts => qa/source/quality-assurance-source.service.spec.ts} (56%) create mode 100644 src/app/notifications/qa/source/quality-assurance-source.service.ts rename src/app/notifications/{broker/topics/notifications-broker-topics.actions.ts => qa/topics/quality-assurance-topics.actions.ts} (62%) rename src/app/notifications/{broker/topics/notifications-broker-topics.component.html => qa/topics/quality-assurance-topics.component.html} (97%) rename src/app/notifications/{broker/topics/notifications-broker-topics.component.scss => qa/topics/quality-assurance-topics.component.scss} (100%) rename src/app/notifications/{broker/topics/notifications-broker-topics.component.spec.ts => qa/topics/quality-assurance-topics.component.spec.ts} (59%) rename src/app/notifications/{broker/topics/notifications-broker-topics.component.ts => qa/topics/quality-assurance-topics.component.ts} (63%) rename src/app/notifications/{broker/topics/notifications-broker-topics.effects.ts => qa/topics/quality-assurance-topics.effects.ts} (59%) rename src/app/notifications/{broker/topics/notifications-broker-topics.reducer.spec.ts => qa/topics/quality-assurance-topics.reducer.spec.ts} (51%) create mode 100644 src/app/notifications/qa/topics/quality-assurance-topics.reducer.ts rename src/app/notifications/{broker/topics/notifications-broker-topics.service.spec.ts => qa/topics/quality-assurance-topics.service.spec.ts} (58%) rename src/app/notifications/{broker/topics/notifications-broker-topics.service.ts => qa/topics/quality-assurance-topics.service.ts} (51%) diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html deleted file mode 100644 index 89ef1bfc88..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts deleted file mode 100644 index 57a79e017b..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page.component'; - -describe('AdminNotificationsBrokerEventsPageComponent', () => { - let component: AdminNotificationsBrokerEventsPageComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AdminNotificationsBrokerEventsPageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsBrokerEventsPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminNotificationsBrokerEventsPageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts deleted file mode 100644 index f014b4d133..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ds-notifications-broker-events-page', - templateUrl: './admin-notifications-broker-events-page.component.html' -}) -export class AdminNotificationsBrokerEventsPageComponent { - -} diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.html b/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.html deleted file mode 100644 index 57f635d5da..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts deleted file mode 100644 index f6d3eb20fe..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { AdminNotificationsBrokerSourcePageComponent } from './admin-notifications-broker-source-page.component'; - -describe('AdminNotificationsBrokerSourcePageComponent', () => { - let component: AdminNotificationsBrokerSourcePageComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ AdminNotificationsBrokerSourcePageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsBrokerSourcePageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminNotificationsBrokerSourcePageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.ts deleted file mode 100644 index 1ec0894827..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'ds-admin-notifications-broker-source-page-component', - templateUrl: './admin-notifications-broker-source-page.component.html', -}) -export class AdminNotificationsBrokerSourcePageComponent {} diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html deleted file mode 100644 index dbdae2e6b9..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts deleted file mode 100644 index c21e0ce73b..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page.component'; - -describe('AdminNotificationsBrokerTopicsPageComponent', () => { - let component: AdminNotificationsBrokerTopicsPageComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AdminNotificationsBrokerTopicsPageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsBrokerTopicsPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminNotificationsBrokerTopicsPageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts deleted file mode 100644 index 4f60ffd3fd..0000000000 --- a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ds-notification-broker-page', - templateUrl: './admin-notifications-broker-topics-page.component.html' -}) -export class AdminNotificationsBrokerTopicsPageComponent { - -} diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts index 469cbb980f..2820a9a2c7 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -1,8 +1,8 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { getNotificationsModuleRoute } from '../admin-routing-paths'; -export const NOTIFICATIONS_EDIT_PATH = 'notifications-broker'; +export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance'; -export function getNotificationsBrokerbrokerRoute(id: string) { - return new URLCombiner(getNotificationsModuleRoute(), NOTIFICATIONS_EDIT_PATH, id).toString(); +export function getQualityAssuranceRoute(id: string) { + return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString(); } diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 4e5997e203..c9cca6d8d8 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -4,26 +4,26 @@ 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 { NOTIFICATIONS_EDIT_PATH } from './admin-notifications-routing-paths'; -import { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component'; -import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page/admin-notifications-broker-events-page.component'; -import { AdminNotificationsBrokerTopicsPageResolver } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service'; -import { AdminNotificationsBrokerEventsPageResolver } from './admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver'; -import { AdminNotificationsBrokerSourcePageComponent } from './admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component'; -import { AdminNotificationsBrokerSourcePageResolver } from './admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service'; -import { SourceDataResolver } from './admin-notifications-broker-source-page-component/admin-notifications-broker-source-data.reslover'; +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'; +import { AdminQualityAssuranceTopicsPageResolver } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service'; +import { AdminQualityAssuranceEventsPageResolver } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver'; +import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; +import { AdminQualityAssuranceSourcePageResolver } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service'; +import { SourceDataResolver } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.reslover'; @NgModule({ imports: [ RouterModule.forChild([ { canActivate: [ AuthenticatedGuard ], - path: `${NOTIFICATIONS_EDIT_PATH}/:sourceId`, - component: AdminNotificationsBrokerTopicsPageComponent, + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId`, + component: AdminQualityAssuranceTopicsPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerTopicsParams: AdminNotificationsBrokerTopicsPageResolver + openaireBrokerTopicsParams: AdminQualityAssuranceTopicsPageResolver }, data: { title: 'admin.notifications.broker.page.title', @@ -33,12 +33,12 @@ import { SourceDataResolver } from './admin-notifications-broker-source-page-com }, { canActivate: [ AuthenticatedGuard ], - path: `${NOTIFICATIONS_EDIT_PATH}`, - component: AdminNotificationsBrokerSourcePageComponent, + path: `${QUALITY_ASSURANCE_EDIT_PATH}`, + component: AdminQualityAssuranceSourcePageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerSourceParams: AdminNotificationsBrokerSourcePageResolver, + openaireBrokerSourceParams: AdminQualityAssuranceSourcePageResolver, sourceData: SourceDataResolver }, data: { @@ -49,12 +49,12 @@ import { SourceDataResolver } from './admin-notifications-broker-source-page-com }, { canActivate: [ AuthenticatedGuard ], - path: `${NOTIFICATIONS_EDIT_PATH}/:sourceId/:topicId`, - component: AdminNotificationsBrokerEventsPageComponent, + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/:topicId`, + component: AdminQualityAssuranceEventsPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerEventsParams: AdminNotificationsBrokerEventsPageResolver + openaireBrokerEventsParams: AdminQualityAssuranceEventsPageResolver }, data: { title: 'admin.notifications.event.page.title', @@ -68,9 +68,9 @@ import { SourceDataResolver } from './admin-notifications-broker-source-page-com I18nBreadcrumbResolver, I18nBreadcrumbsService, SourceDataResolver, - AdminNotificationsBrokerTopicsPageResolver, - AdminNotificationsBrokerEventsPageResolver, - AdminNotificationsBrokerSourcePageResolver + AdminQualityAssuranceTopicsPageResolver, + AdminQualityAssuranceEventsPageResolver, + AdminQualityAssuranceSourcePageResolver ] }) /** diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index 6351498dc5..ba0c6eee58 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -3,10 +3,10 @@ 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 { AdminNotificationsBrokerTopicsPageComponent } from './admin-notifications-broker-topics-page/admin-notifications-broker-topics-page.component'; -import { AdminNotificationsBrokerEventsPageComponent } from './admin-notifications-broker-events-page/admin-notifications-broker-events-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 { NotificationsModule } from '../../notifications/notifications.module'; -import { AdminNotificationsBrokerSourcePageComponent } from './admin-notifications-broker-source-page-component/admin-notifications-broker-source-page.component'; +import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; @NgModule({ imports: [ @@ -17,9 +17,9 @@ import { AdminNotificationsBrokerSourcePageComponent } from './admin-notificatio NotificationsModule ], declarations: [ - AdminNotificationsBrokerTopicsPageComponent, - AdminNotificationsBrokerEventsPageComponent, - AdminNotificationsBrokerSourcePageComponent + AdminQualityAssuranceTopicsPageComponent, + AdminQualityAssuranceEventsPageComponent, + AdminQualityAssuranceSourcePageComponent ], entryComponents: [] }) diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html new file mode 100644 index 0000000000..315209d342 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts new file mode 100644 index 0000000000..b952078215 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page.component'; + +describe('AdminQualityAssuranceEventsPageComponent', () => { + let component: AdminQualityAssuranceEventsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminQualityAssuranceEventsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminQualityAssuranceEventsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminQualityAssuranceEventsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts new file mode 100644 index 0000000000..a1e15d5bdb --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-quality-assurance-events-page', + templateUrl: './admin-quality-assurance-events-page.component.html' +}) +export class AdminQualityAssuranceEventsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts similarity index 72% rename from src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts rename to src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts index dcf530858c..3139355629 100644 --- a/src/app/admin/admin-notifications/admin-notifications-broker-events-page/admin-notifications-broker-events-page.resolver.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts @@ -4,7 +4,7 @@ import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsBrokerEventsPageParams { +export interface AdminQualityAssuranceEventsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,15 +14,15 @@ export interface AdminNotificationsBrokerEventsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsBrokerEventsPageResolver implements Resolve { +export class AdminQualityAssuranceEventsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns AdminNotificationsBrokerEventsPageParams Emits the route parameters + * @returns AdminQualityAssuranceEventsPageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsBrokerEventsPageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminQualityAssuranceEventsPageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-data.reslover.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.reslover.ts similarity index 61% rename from src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-data.reslover.ts rename to src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.reslover.ts index 114f5f7df1..6201e0a743 100644 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-data.reslover.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.reslover.ts @@ -3,30 +3,30 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot, Router } from '@a import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; -import { NotificationsBrokerSourceService } from '../../../notifications/broker/source/notifications-broker-source.service'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; +import { QualityAssuranceSourceService } from '../../../notifications/qa/source/quality-assurance-source.service'; /** * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class SourceDataResolver implements Resolve> { +export class SourceDataResolver implements Resolve> { /** * Initialize the effect class variables. - * @param {NotificationsBrokerSourceService} notificationsBrokerSourceService + * @param {QualityAssuranceSourceService} qualityAssuranceSourceService */ constructor( - private notificationsBrokerSourceService: NotificationsBrokerSourceService, + private qualityAssuranceSourceService: QualityAssuranceSourceService, private router: Router ) { } /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns Observable + * @returns Observable */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.notificationsBrokerSourceService.getSources(5,0).pipe( - map((sources: PaginatedList) => { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.qualityAssuranceSourceService.getSources(5,0).pipe( + map((sources: PaginatedList) => { if (sources.page.length === 1) { this.router.navigate([this.getResolvedUrl(route) + '/' + sources.page[0].id]); } diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service.ts similarity index 72% rename from src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts rename to src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service.ts index d4fd354d92..ac9bdb48d6 100644 --- a/src/app/admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsBrokerTopicsPageParams { +export interface AdminQualityAssuranceSourcePageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,15 +14,15 @@ export interface AdminNotificationsBrokerTopicsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsBrokerTopicsPageResolver implements Resolve { +export class AdminQualityAssuranceSourcePageResolver implements Resolve { /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns AdminNotificationsBrokerTopicsPageParams Emits the route parameters + * @returns AdminQualityAssuranceSourcePageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsBrokerTopicsPageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminQualityAssuranceSourcePageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.html b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.html new file mode 100644 index 0000000000..709103cf3d --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts new file mode 100644 index 0000000000..451c911c4c --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts @@ -0,0 +1,27 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page.component'; + +describe('AdminQualityAssuranceSourcePageComponent', () => { + let component: AdminQualityAssuranceSourcePageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AdminQualityAssuranceSourcePageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminQualityAssuranceSourcePageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminQualityAssuranceSourcePageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts new file mode 100644 index 0000000000..624e71f281 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts @@ -0,0 +1,7 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'ds-admin-quality-assurance-source-page-component', + templateUrl: './admin-quality-assurance-source-page.component.html', +}) +export class AdminQualityAssuranceSourcePageComponent {} diff --git a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts similarity index 72% rename from src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service.ts rename to src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts index 8450e20c3c..47500d1878 100644 --- a/src/app/admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsBrokerSourcePageParams { +export interface AdminQualityAssuranceTopicsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,15 +14,15 @@ export interface AdminNotificationsBrokerSourcePageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsBrokerSourcePageResolver implements Resolve { +export class AdminQualityAssuranceTopicsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot - * @returns AdminNotificationsBrokerSourcePageParams Emits the route parameters + * @returns AdminQualityAssuranceTopicsPageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsBrokerSourcePageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminQualityAssuranceTopicsPageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.html b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.html new file mode 100644 index 0000000000..fc905ad724 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts new file mode 100644 index 0000000000..a32f60f017 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page.component'; + +describe('AdminQualityAssuranceTopicsPageComponent', () => { + let component: AdminQualityAssuranceTopicsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminQualityAssuranceTopicsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminQualityAssuranceTopicsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create AdminQualityAssuranceTopicsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts new file mode 100644 index 0000000000..53f951ba54 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notification-broker-page', + templateUrl: './admin-quality-assurance-topics-page.component.html' +}) +export class AdminQualityAssuranceTopicsPageComponent { + +} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index a2ee9abc2d..fcc8160f88 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -167,9 +167,9 @@ import { SequenceService } from './shared/sequence.service'; import { CoreState } from './core-state.model'; import { GroupDataService } from './eperson/group-data.service'; import { SubmissionAccessesModel } from './config/models/config-submission-accesses.model'; -import { NotificationsBrokerTopicObject } from './notifications/broker/models/notifications-broker-topic.model'; -import { NotificationsBrokerEventObject } from './notifications/broker/models/notifications-broker-event.model'; -import { NotificationsBrokerSourceObject } from './notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceTopicObject } from './notifications/qa/models/quality-assurance-topic.model'; +import { QualityAssuranceEventObject } from './notifications/qa/models/quality-assurance-event.model'; +import { QualityAssuranceSourceObject } from './notifications/qa/models/quality-assurance-source.model'; import { AccessStatusObject } from '../shared/object-list/access-status-badge/access-status.model'; import { AccessStatusDataService } from './data/access-status-data.service'; import { LinkHeadService } from './services/link-head.service'; @@ -369,12 +369,12 @@ export const models = ShortLivedToken, Registration, UsageReport, - NotificationsBrokerTopicObject, - NotificationsBrokerEventObject, + QualityAssuranceTopicObject, + QualityAssuranceEventObject, Root, SearchConfig, SubmissionAccessesModel, - NotificationsBrokerSourceObject, + QualityAssuranceSourceObject, AccessStatusObject, ResearcherProfile, OrcidQueue, diff --git a/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts similarity index 77% rename from src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts rename to src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts index 16d55479ae..556665adbd 100644 --- a/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.spec.ts +++ b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts @@ -6,8 +6,6 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; import { RequestService } from '../../../data/request.service'; import { buildPaginatedList } from '../../../data/paginated-list.model'; -import { RequestEntry } from '../../../data/request.reducer'; -import { FindListOptions } from '../../../data/request.models'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { RestResponse } from '../../../cache/response.models'; @@ -15,17 +13,19 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { NotificationsBrokerEventRestService } from './notifications-broker-event-rest.service'; +import { QualityAssuranceEventRestService } from './quality-assurance-event-rest.service'; import { - notificationsBrokerEventObjectMissingPid, - notificationsBrokerEventObjectMissingPid2, - notificationsBrokerEventObjectMissingProjectFound + qualityAssuranceEventObjectMissingPid, + qualityAssuranceEventObjectMissingPid2, + qualityAssuranceEventObjectMissingProjectFound } from '../../../../shared/mocks/notifications.mock'; import { ReplaceOperation } from 'fast-json-patch'; +import {RequestEntry} from '../../../data/request-entry.model'; +import {FindListOptions} from '../../../data/find-list-options.model'; -describe('NotificationsBrokerEventRestService', () => { +describe('QualityAssuranceEventRestService', () => { let scheduler: TestScheduler; - let service: NotificationsBrokerEventRestService; + let service: QualityAssuranceEventRestService; let serviceASAny: any; let responseCacheEntry: RequestEntry; let responseCacheEntryB: RequestEntry; @@ -43,10 +43,10 @@ describe('NotificationsBrokerEventRestService', () => { const topic = 'ENRICH!MORE!PID'; const pageInfo = new PageInfo(); - const array = [ notificationsBrokerEventObjectMissingPid, notificationsBrokerEventObjectMissingPid2 ]; + const array = [ qualityAssuranceEventObjectMissingPid, qualityAssuranceEventObjectMissingPid2 ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerEventObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingPid); - const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingProjectFound); + const brokerEventObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingPid); + const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingProjectFound); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); const status = 'ACCEPTED'; @@ -99,7 +99,7 @@ describe('NotificationsBrokerEventRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new NotificationsBrokerEventRestService( + service = new QualityAssuranceEventRestService( requestService, rdbService, objectCache, @@ -138,7 +138,7 @@ describe('NotificationsBrokerEventRestService', () => { expect(serviceASAny.dataService.searchBy).toHaveBeenCalledWith('findByTopic', options, true, true); }); - it('should return a RemoteData> for the object with the given Topic', () => { + it('should return a RemoteData> for the object with the given Topic', () => { const result = service.getEventsByTopic(topic); const expected = cold('(a)', { a: paginatedListRD @@ -155,15 +155,15 @@ describe('NotificationsBrokerEventRestService', () => { }); it('should proxy the call to dataservice.findById', () => { - service.getEvent(notificationsBrokerEventObjectMissingPid.id).subscribe( + service.getEvent(qualityAssuranceEventObjectMissingPid.id).subscribe( (res) => { - expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingPid.id, true, true); + expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid.id, true, true); } ); }); - it('should return a RemoteData for the object with the given URL', () => { - const result = service.getEvent(notificationsBrokerEventObjectMissingPid.id); + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getEvent(qualityAssuranceEventObjectMissingPid.id); const expected = cold('(a)', { a: brokerEventObjectRD }); @@ -179,17 +179,17 @@ describe('NotificationsBrokerEventRestService', () => { }); it('should proxy the call to dataservice.patch', () => { - service.patchEvent(status, notificationsBrokerEventObjectMissingPid).subscribe( + service.patchEvent(status, qualityAssuranceEventObjectMissingPid).subscribe( (res) => { - expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingPid, operation); + expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid, operation); } ); }); it('should return a RemoteData with HTTP 200', () => { - const result = service.patchEvent(status, notificationsBrokerEventObjectMissingPid); + const result = service.patchEvent(status, qualityAssuranceEventObjectMissingPid); const expected = cold('(a|)', { - a: createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingPid) + a: createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingPid) }); expect(result).toBeObservable(expected); }); @@ -203,17 +203,17 @@ describe('NotificationsBrokerEventRestService', () => { }); it('should proxy the call to dataservice.postOnRelated', () => { - service.boundProject(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID).subscribe( + service.boundProject(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID).subscribe( (res) => { - expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID); + expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID); } ); }); it('should return a RestResponse with HTTP 201', () => { - const result = service.boundProject(notificationsBrokerEventObjectMissingProjectFound.id, requestUUID); + const result = service.boundProject(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID); const expected = cold('(a|)', { - a: createSuccessfulRemoteDataObject(notificationsBrokerEventObjectMissingProjectFound) + a: createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingProjectFound) }); expect(result).toBeObservable(expected); }); @@ -227,15 +227,15 @@ describe('NotificationsBrokerEventRestService', () => { }); it('should proxy the call to dataservice.deleteOnRelated', () => { - service.removeProject(notificationsBrokerEventObjectMissingProjectFound.id).subscribe( + service.removeProject(qualityAssuranceEventObjectMissingProjectFound.id).subscribe( (res) => { - expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(notificationsBrokerEventObjectMissingProjectFound.id); + expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id); } ); }); it('should return a RestResponse with HTTP 204', () => { - const result = service.removeProject(notificationsBrokerEventObjectMissingProjectFound.id); + const result = service.removeProject(qualityAssuranceEventObjectMissingProjectFound.id); const expected = cold('(a|)', { a: createSuccessfulRemoteDataObject({}) }); diff --git a/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts similarity index 71% rename from src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts rename to src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts index 7f4761009d..59f6c31e05 100644 --- a/src/app/core/notifications/broker/events/notifications-broker-event-rest.service.ts +++ b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts @@ -4,7 +4,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { CoreState } from '../../../core.reducers'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; @@ -12,24 +11,25 @@ import { RestResponse } from '../../../cache/response.models'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { dataService } from '../../../cache/builders/build-decorators'; import { RequestService } from '../../../data/request.service'; -import { FindListOptions } from '../../../data/request.models'; import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; -import { NotificationsBrokerEventObject } from '../models/notifications-broker-event.model'; -import { NOTIFICATIONS_BROKER_EVENT_OBJECT } from '../models/notifications-broker-event-object.resource-type'; +import { QualityAssuranceEventObject } from '../models/quality-assurance-event.model'; +import { QUALITY_ASSURANCE_EVENT_OBJECT } from '../models/quality-assurance-event-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; import { ReplaceOperation } from 'fast-json-patch'; import { NoContent } from '../../../shared/NoContent.model'; +import {CoreState} from '../../../core-state.model'; +import {FindListOptions} from '../../../data/find-list-options.model'; /* tslint:disable:max-classes-per-file */ /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class DataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -44,7 +44,7 @@ class DataServiceImpl extends DataService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator + * @param {ChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -54,17 +54,17 @@ class DataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { + protected comparator: ChangeAnalyzer) { super(); } } /** - * The service handling all Notifications Broker topic REST requests. + * The service handling all Quality Assurance topic REST requests. */ @Injectable() -@dataService(NOTIFICATIONS_BROKER_EVENT_OBJECT) -export class NotificationsBrokerEventRestService { +@dataService(QUALITY_ASSURANCE_EVENT_OBJECT) +export class QualityAssuranceEventRestService { /** * A private DataService implementation to delegate specific methods to. */ @@ -78,7 +78,7 @@ export class NotificationsBrokerEventRestService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator + * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -87,23 +87,23 @@ export class NotificationsBrokerEventRestService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { + protected comparator: DefaultChangeAnalyzer) { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** - * Return the list of Notifications Broker events by topic. + * Return the list of Quality Assurance events by topic. * * @param topic - * The Notifications Broker topic + * The Quality Assurance topic * @param options * Find list options object. * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of Notifications Broker events. + * @return Observable>> + * The list of Quality Assurance events. */ - public getEventsByTopic(topic: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + public getEventsByTopic(topic: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { options.searchParams = [ { fieldName: 'topic', @@ -121,32 +121,32 @@ export class NotificationsBrokerEventRestService { } /** - * Return a single Notifications Broker event. + * Return a single Quality Assurance event. * * @param id - * The Notifications Broker event id + * The Quality Assurance event id * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - * @return Observable> - * The Notifications Broker event. + * @return Observable> + * The Quality Assurance event. */ - public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { return this.dataService.findById(id, true, true, ...linksToFollow); } /** - * Save the new status of a Notifications Broker event. + * Save the new status of a Quality Assurance event. * * @param status * The new status - * @param dso NotificationsBrokerEventObject + * @param dso QualityAssuranceEventObject * The event item * @param reason * The optional reason (not used for now; for future implementation) * @return Observable * The REST response. */ - public patchEvent(status, dso, reason?: string): Observable> { + public patchEvent(status, dso, reason?: string): Observable> { const operation: ReplaceOperation[] = [ { path: '/status', @@ -158,24 +158,24 @@ export class NotificationsBrokerEventRestService { } /** - * Bound a project to a Notifications Broker event publication. + * Bound a project to a Quality Assurance event publication. * * @param itemId - * The Id of the Notifications Broker event + * The Id of the Quality Assurance event * @param projectId * The project Id to bound * @return Observable * The REST response. */ - public boundProject(itemId: string, projectId: string): Observable> { + public boundProject(itemId: string, projectId: string): Observable> { return this.dataService.postOnRelated(itemId, projectId); } /** - * Remove a project from a Notifications Broker event publication. + * Remove a project from a Quality Assurance event publication. * * @param itemId - * The Id of the Notifications Broker event + * The Id of the Quality Assurance event * @return Observable * The REST response. */ diff --git a/src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts similarity index 53% rename from src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts rename to src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts index e7012eee4f..33c7b338ed 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-topic-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts @@ -1,9 +1,9 @@ import { ResourceType } from '../../../shared/resource-type'; /** - * The resource type for the Notifications Broker topic + * The resource type for the Quality Assurance event * * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const NOTIFICATIONS_BROKER_TOPIC_OBJECT = new ResourceType('nbtopic'); +export const QUALITY_ASSURANCE_EVENT_OBJECT = new ResourceType('nbevent'); diff --git a/src/app/core/notifications/broker/models/notifications-broker-event.model.ts b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts similarity index 90% rename from src/app/core/notifications/broker/models/notifications-broker-event.model.ts rename to src/app/core/notifications/qa/models/quality-assurance-event.model.ts index 4df326f325..15fbae7821 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-event.model.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts @@ -1,7 +1,6 @@ import { Observable } from 'rxjs'; import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; -import { NOTIFICATIONS_BROKER_EVENT_OBJECT } from './notifications-broker-event-object.resource-type'; +import { QUALITY_ASSURANCE_EVENT_OBJECT } from './quality-assurance-event-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; @@ -9,11 +8,12 @@ import { Item } from '../../../shared/item.model'; import { ITEM } from '../../../shared/item.resource-type'; import { link, typedObject } from '../../../cache/builders/build-decorators'; import { RemoteData } from '../../../data/remote-data'; +import {CacheableObject} from '../../../cache/cacheable-object.model'; /** * The interface representing the Notifications Broker event message */ -export interface NotificationsBrokerEventMessageObject { +export interface QualityAssuranceEventMessageObject { } @@ -77,11 +77,11 @@ export interface OpenaireBrokerEventMessageObject { * The interface representing the Notifications Broker event model */ @typedObject -export class NotificationsBrokerEventObject implements CacheableObject { +export class QualityAssuranceEventObject implements CacheableObject { /** * A string representing the kind of object, e.g. community, item, … */ - static type = NOTIFICATIONS_BROKER_EVENT_OBJECT; + static type = QUALITY_ASSURANCE_EVENT_OBJECT; /** * The Notifications Broker event uuid inside DSpace diff --git a/src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts similarity index 53% rename from src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts rename to src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts index 2493ae02d1..585216c34f 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-event-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts @@ -1,9 +1,9 @@ import { ResourceType } from '../../../shared/resource-type'; /** - * The resource type for the Notifications Broker event + * The resource type for the Quality Assurance source * * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const NOTIFICATIONS_BROKER_EVENT_OBJECT = new ResourceType('nbevent'); +export const QUALITY_ASSURANCE_SOURCE_OBJECT = new ResourceType('nbsource'); diff --git a/src/app/core/notifications/broker/models/notifications-broker-source.model.ts b/src/app/core/notifications/qa/models/quality-assurance-source.model.ts similarity index 69% rename from src/app/core/notifications/broker/models/notifications-broker-source.model.ts rename to src/app/core/notifications/qa/models/quality-assurance-source.model.ts index 3f18c3affb..f59467384f 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-source.model.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-source.model.ts @@ -1,24 +1,24 @@ import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; import { typedObject } from '../../../cache/builders/build-decorators'; -import { NOTIFICATIONS_BROKER_SOURCE_OBJECT } from './notifications-broker-source-object.resource-type'; +import { QUALITY_ASSURANCE_SOURCE_OBJECT } from './quality-assurance-source-object.resource-type'; +import {CacheableObject} from '../../../cache/cacheable-object.model'; /** - * The interface representing the Notifications Broker source model + * The interface representing the Quality Assurance source model */ @typedObject -export class NotificationsBrokerSourceObject implements CacheableObject { +export class QualityAssuranceSourceObject implements CacheableObject { /** * A string representing the kind of object, e.g. community, item, … */ - static type = NOTIFICATIONS_BROKER_SOURCE_OBJECT; + static type = QUALITY_ASSURANCE_SOURCE_OBJECT; /** - * The Notifications Broker source id + * The Quality Assurance source id */ @autoserialize id: string; diff --git a/src/app/core/notifications/broker/models/notifications-broker-source-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts similarity index 53% rename from src/app/core/notifications/broker/models/notifications-broker-source-object.resource-type.ts rename to src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts index e3d10dc5ab..8cd5bec61b 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-source-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts @@ -1,9 +1,9 @@ import { ResourceType } from '../../../shared/resource-type'; /** - * The resource type for the Notifications Broker source + * The resource type for the Quality Assurance topic * * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const NOTIFICATIONS_BROKER_SOURCE_OBJECT = new ResourceType('nbsource'); +export const QUALITY_ASSURANCE_TOPIC_OBJECT = new ResourceType('nbtopic'); diff --git a/src/app/core/notifications/broker/models/notifications-broker-topic.model.ts b/src/app/core/notifications/qa/models/quality-assurance-topic.model.ts similarity index 68% rename from src/app/core/notifications/broker/models/notifications-broker-topic.model.ts rename to src/app/core/notifications/qa/models/quality-assurance-topic.model.ts index d1f2e6ff50..529980e5f7 100644 --- a/src/app/core/notifications/broker/models/notifications-broker-topic.model.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-topic.model.ts @@ -1,30 +1,30 @@ import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; -import { NOTIFICATIONS_BROKER_TOPIC_OBJECT } from './notifications-broker-topic-object.resource-type'; +import { QUALITY_ASSURANCE_TOPIC_OBJECT } from './quality-assurance-topic-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; import { typedObject } from '../../../cache/builders/build-decorators'; +import {CacheableObject} from '../../../cache/cacheable-object.model'; /** - * The interface representing the Notifications Broker topic model + * The interface representing the Quality Assurance topic model */ @typedObject -export class NotificationsBrokerTopicObject implements CacheableObject { +export class QualityAssuranceTopicObject implements CacheableObject { /** * A string representing the kind of object, e.g. community, item, … */ - static type = NOTIFICATIONS_BROKER_TOPIC_OBJECT; + static type = QUALITY_ASSURANCE_TOPIC_OBJECT; /** - * The Notifications Broker topic id + * The Quality Assurance topic id */ @autoserialize id: string; /** - * The Notifications Broker topic name to display + * The Quality Assurance topic name to display */ @autoserialize name: string; diff --git a/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts similarity index 78% rename from src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts rename to src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts index 984f44bd15..dff604b0c4 100644 --- a/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.spec.ts +++ b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts @@ -6,7 +6,6 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; import { RequestService } from '../../../data/request.service'; import { buildPaginatedList } from '../../../data/paginated-list.model'; -import { RequestEntry } from '../../../data/request.reducer'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { RestResponse } from '../../../cache/response.models'; @@ -14,15 +13,16 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { NotificationsBrokerSourceRestService } from './notifications-broker-source-rest.service'; import { - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMorePid + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMorePid } from '../../../../shared/mocks/notifications.mock'; +import {RequestEntry} from '../../../data/request-entry.model'; +import {QualityAssuranceSourceRestService} from './quality-assurance-source-rest.service'; -describe('NotificationsBrokerSourceRestService', () => { +describe('QualityAssuranceSourceRestService', () => { let scheduler: TestScheduler; - let service: NotificationsBrokerSourceRestService; + let service: QualityAssuranceSourceRestService; let responseCacheEntry: RequestEntry; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -36,9 +36,9 @@ describe('NotificationsBrokerSourceRestService', () => { const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); - const array = [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ]; + const array = [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerSourceObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerSourceObjectMorePid); + const brokerSourceObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceSourceObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); beforeEach(() => { @@ -72,7 +72,7 @@ describe('NotificationsBrokerSourceRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new NotificationsBrokerSourceRestService( + service = new QualityAssuranceSourceRestService( requestService, rdbService, objectCache, @@ -96,7 +96,7 @@ describe('NotificationsBrokerSourceRestService', () => { done(); }); - it('should return a RemoteData> for the object with the given URL', () => { + it('should return a RemoteData> for the object with the given URL', () => { const result = service.getSources(); const expected = cold('(a)', { a: paginatedListRD @@ -107,16 +107,16 @@ describe('NotificationsBrokerSourceRestService', () => { describe('getSource', () => { it('should proxy the call to dataservice.findByHref', (done) => { - service.getSource(notificationsBrokerSourceObjectMorePid.id).subscribe( + service.getSource(qualityAssuranceSourceObjectMorePid.id).subscribe( (res) => { - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + notificationsBrokerSourceObjectMorePid.id, true, true); + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceSourceObjectMorePid.id, true, true); } ); done(); }); - it('should return a RemoteData for the object with the given URL', () => { - const result = service.getSource(notificationsBrokerSourceObjectMorePid.id); + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getSource(qualityAssuranceSourceObjectMorePid.id); const expected = cold('(a)', { a: brokerSourceObjectRD }); diff --git a/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.ts b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts similarity index 72% rename from src/app/core/notifications/broker/source/notifications-broker-source-rest.service.ts rename to src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts index ebbbe995d1..85045aebcd 100644 --- a/src/app/core/notifications/broker/source/notifications-broker-source-rest.service.ts +++ b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts @@ -5,29 +5,29 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; -import { CoreState } from '../../../core.reducers'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { dataService } from '../../../cache/builders/build-decorators'; import { RequestService } from '../../../data/request.service'; -import { FindListOptions } from '../../../data/request.models'; import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; -import { NotificationsBrokerSourceObject } from '../models/notifications-broker-source.model'; -import { NOTIFICATIONS_BROKER_SOURCE_OBJECT } from '../models/notifications-broker-source-object.resource-type'; +import { QualityAssuranceSourceObject } from '../models/quality-assurance-source.model'; +import { QUALITY_ASSURANCE_SOURCE_OBJECT } from '../models/quality-assurance-source-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; +import {CoreState} from '../../../core-state.model'; +import {FindListOptions} from '../../../data/find-list-options.model'; /* tslint:disable:max-classes-per-file */ /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class DataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -42,7 +42,7 @@ class DataServiceImpl extends DataService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator + * @param {ChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -52,17 +52,17 @@ class DataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { + protected comparator: ChangeAnalyzer) { super(); } } /** - * The service handling all Notifications Broker source REST requests. + * The service handling all Quality Assurance source REST requests. */ @Injectable() -@dataService(NOTIFICATIONS_BROKER_SOURCE_OBJECT) -export class NotificationsBrokerSourceRestService { +@dataService(QUALITY_ASSURANCE_SOURCE_OBJECT) +export class QualityAssuranceSourceRestService { /** * A private DataService implementation to delegate specific methods to. */ @@ -76,7 +76,7 @@ export class NotificationsBrokerSourceRestService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator + * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -85,21 +85,21 @@ export class NotificationsBrokerSourceRestService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { + protected comparator: DefaultChangeAnalyzer) { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** - * Return the list of Notifications Broker source. + * Return the list of Quality Assurance source. * * @param options * Find list options object. * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of Notifications Broker source. + * @return Observable>> + * The list of Quality Assurance source. */ - public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.dataService.getBrowseEndpoint(options, 'nbsources').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), @@ -114,16 +114,16 @@ export class NotificationsBrokerSourceRestService { } /** - * Return a single Notifications Broker source. + * Return a single Quality Assurance source. * * @param id - * The Notifications Broker source id + * The Quality Assurance source id * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable> - * The Notifications Broker source. + * @return Observable> + * The Quality Assurance source. */ - public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; return this.dataService.getBrowseEndpoint(options, 'nbsources').pipe( take(1), diff --git a/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts similarity index 76% rename from src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts rename to src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts index 06931e2032..cb828141a6 100644 --- a/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.spec.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts @@ -6,7 +6,6 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; import { RequestService } from '../../../data/request.service'; import { buildPaginatedList } from '../../../data/paginated-list.model'; -import { RequestEntry } from '../../../data/request.reducer'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { RestResponse } from '../../../cache/response.models'; @@ -14,15 +13,16 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { NotificationsBrokerTopicRestService } from './notifications-broker-topic-rest.service'; +import { QualityAssuranceTopicRestService } from './quality-assurance-topic-rest.service'; import { - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMorePid + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMorePid } from '../../../../shared/mocks/notifications.mock'; +import {RequestEntry} from '../../../data/request-entry.model'; -describe('NotificationsBrokerTopicRestService', () => { +describe('QualityAssuranceTopicRestService', () => { let scheduler: TestScheduler; - let service: NotificationsBrokerTopicRestService; + let service: QualityAssuranceTopicRestService; let responseCacheEntry: RequestEntry; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -36,9 +36,9 @@ describe('NotificationsBrokerTopicRestService', () => { const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); - const array = [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract ]; + const array = [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerTopicObjectRD = createSuccessfulRemoteDataObject(notificationsBrokerTopicObjectMorePid); + const brokerTopicObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceTopicObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); beforeEach(() => { @@ -72,7 +72,7 @@ describe('NotificationsBrokerTopicRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new NotificationsBrokerTopicRestService( + service = new QualityAssuranceTopicRestService( requestService, rdbService, objectCache, @@ -96,7 +96,7 @@ describe('NotificationsBrokerTopicRestService', () => { done(); }); - it('should return a RemoteData> for the object with the given URL', () => { + it('should return a RemoteData> for the object with the given URL', () => { const result = service.getTopics(); const expected = cold('(a)', { a: paginatedListRD @@ -107,16 +107,16 @@ describe('NotificationsBrokerTopicRestService', () => { describe('getTopic', () => { it('should proxy the call to dataservice.findByHref', (done) => { - service.getTopic(notificationsBrokerTopicObjectMorePid.id).subscribe( + service.getTopic(qualityAssuranceTopicObjectMorePid.id).subscribe( (res) => { - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + notificationsBrokerTopicObjectMorePid.id, true, true); + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceTopicObjectMorePid.id, true, true); } ); done(); }); - it('should return a RemoteData for the object with the given URL', () => { - const result = service.getTopic(notificationsBrokerTopicObjectMorePid.id); + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getTopic(qualityAssuranceTopicObjectMorePid.id); const expected = cold('(a)', { a: brokerTopicObjectRD }); diff --git a/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts similarity index 73% rename from src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts rename to src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts index 9f0b93cfb3..da90126709 100644 --- a/src/app/core/notifications/broker/topics/notifications-broker-topic-rest.service.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts @@ -5,29 +5,29 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; -import { CoreState } from '../../../core.reducers'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { dataService } from '../../../cache/builders/build-decorators'; import { RequestService } from '../../../data/request.service'; -import { FindListOptions } from '../../../data/request.models'; import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; -import { NotificationsBrokerTopicObject } from '../models/notifications-broker-topic.model'; -import { NOTIFICATIONS_BROKER_TOPIC_OBJECT } from '../models/notifications-broker-topic-object.resource-type'; +import { QualityAssuranceTopicObject } from '../models/quality-assurance-topic.model'; +import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; +import {CoreState} from '../../../core-state.model'; +import {FindListOptions} from '../../../data/find-list-options.model'; /* tslint:disable:max-classes-per-file */ /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class DataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -42,7 +42,7 @@ class DataServiceImpl extends DataService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator + * @param {ChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -52,17 +52,17 @@ class DataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { + protected comparator: ChangeAnalyzer) { super(); } } /** - * The service handling all Notifications Broker topic REST requests. + * The service handling all Quality Assurance topic REST requests. */ @Injectable() -@dataService(NOTIFICATIONS_BROKER_TOPIC_OBJECT) -export class NotificationsBrokerTopicRestService { +@dataService(QUALITY_ASSURANCE_TOPIC_OBJECT) +export class QualityAssuranceTopicRestService { /** * A private DataService implementation to delegate specific methods to. */ @@ -76,7 +76,7 @@ export class NotificationsBrokerTopicRestService { * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator + * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, @@ -85,21 +85,21 @@ export class NotificationsBrokerTopicRestService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { + protected comparator: DefaultChangeAnalyzer) { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** - * Return the list of Notifications Broker topics. + * Return the list of Quality Assurance topics. * * @param options * Find list options object. * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of Notifications Broker topics. + * @return Observable>> + * The list of Quality Assurance topics. */ - public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { + public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), @@ -114,16 +114,16 @@ export class NotificationsBrokerTopicRestService { } /** - * Return a single Notifications Broker topic. + * Return a single Quality Assurance topic. * * @param id - * The Notifications Broker topic id + * The Quality Assurance topic id * @param linksToFollow * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable> - * The Notifications Broker topic. + * @return Observable> + * The Quality Assurance topic. */ - public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( take(1), diff --git a/src/app/notifications/broker/source/notifications-broker-source.reducer.ts b/src/app/notifications/broker/source/notifications-broker-source.reducer.ts deleted file mode 100644 index 5395796380..0000000000 --- a/src/app/notifications/broker/source/notifications-broker-source.reducer.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; -import { NotificationsBrokerSourceActionTypes, NotificationsBrokerSourceActions } from './notifications-broker-source.actions'; - -/** - * The interface representing the Notifications Broker source state. - */ -export interface NotificationsBrokerSourceState { - source: NotificationsBrokerSourceObject[]; - processing: boolean; - loaded: boolean; - totalPages: number; - currentPage: number; - totalElements: number; -} - -/** - * Used for the Notifications Broker source state initialization. - */ -const notificationsBrokerSourceInitialState: NotificationsBrokerSourceState = { - source: [], - processing: false, - loaded: false, - totalPages: 0, - currentPage: 0, - totalElements: 0 -}; - -/** - * The Notifications Broker Source Reducer - * - * @param state - * the current state initialized with notificationsBrokerSourceInitialState - * @param action - * the action to perform on the state - * @return NotificationsBrokerSourceState - * the new state - */ -export function notificationsBrokerSourceReducer(state = notificationsBrokerSourceInitialState, action: NotificationsBrokerSourceActions): NotificationsBrokerSourceState { - switch (action.type) { - case NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE: { - return Object.assign({}, state, { - source: [], - processing: true - }); - } - - case NotificationsBrokerSourceActionTypes.ADD_SOURCE: { - return Object.assign({}, state, { - source: action.payload.source, - processing: false, - loaded: true, - totalPages: action.payload.totalPages, - currentPage: state.currentPage, - totalElements: action.payload.totalElements - }); - } - - case NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR: { - return Object.assign({}, state, { - processing: false, - loaded: true, - totalPages: 0, - currentPage: 0, - totalElements: 0 - }); - } - - default: { - return state; - } - } -} diff --git a/src/app/notifications/broker/source/notifications-broker-source.service.ts b/src/app/notifications/broker/source/notifications-broker-source.service.ts deleted file mode 100644 index e80643049c..0000000000 --- a/src/app/notifications/broker/source/notifications-broker-source.service.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { find, map } from 'rxjs/operators'; -import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; -import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../core/data/request.models'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; - -/** - * The service handling all Notifications Broker source requests to the REST service. - */ -@Injectable() -export class NotificationsBrokerSourceService { - - /** - * Initialize the service variables. - * @param {NotificationsBrokerSourceRestService} notificationsBrokerSourceRestService - */ - constructor( - private notificationsBrokerSourceRestService: NotificationsBrokerSourceRestService - ) { } - - /** - * Return the list of Notifications Broker source managing pagination and errors. - * - * @param elementsPerPage - * The number of the source per page - * @param currentPage - * The page number to retrieve - * @return Observable> - * The list of Notifications Broker source. - */ - public getSources(elementsPerPage, currentPage): Observable> { - const sortOptions = new SortOptions('name', SortDirection.ASC); - - const findListOptions: FindListOptions = { - elementsPerPage: elementsPerPage, - currentPage: currentPage, - sort: sortOptions - }; - - return this.notificationsBrokerSourceRestService.getSources(findListOptions).pipe( - find((rd: RemoteData>) => !rd.isResponsePending), - map((rd: RemoteData>) => { - if (rd.hasSucceeded) { - return rd.payload; - } else { - throw new Error('Can\'t retrieve Notifications Broker source from the Broker source REST service'); - } - }) - ); - } -} diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.reducer.ts b/src/app/notifications/broker/topics/notifications-broker-topics.reducer.ts deleted file mode 100644 index 2a7be1bf13..0000000000 --- a/src/app/notifications/broker/topics/notifications-broker-topics.reducer.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; -import { NotificationsBrokerTopicActionTypes, NotificationsBrokerTopicsActions } from './notifications-broker-topics.actions'; - -/** - * The interface representing the Notifications Broker topic state. - */ -export interface NotificationsBrokerTopicState { - topics: NotificationsBrokerTopicObject[]; - processing: boolean; - loaded: boolean; - totalPages: number; - currentPage: number; - totalElements: number; -} - -/** - * Used for the Notifications Broker topic state initialization. - */ -const notificationsBrokerTopicInitialState: NotificationsBrokerTopicState = { - topics: [], - processing: false, - loaded: false, - totalPages: 0, - currentPage: 0, - totalElements: 0 -}; - -/** - * The Notifications Broker Topic Reducer - * - * @param state - * the current state initialized with notificationsBrokerTopicInitialState - * @param action - * the action to perform on the state - * @return NotificationsBrokerTopicState - * the new state - */ -export function notificationsBrokerTopicsReducer(state = notificationsBrokerTopicInitialState, action: NotificationsBrokerTopicsActions): NotificationsBrokerTopicState { - switch (action.type) { - case NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS: { - return Object.assign({}, state, { - topics: [], - processing: true - }); - } - - case NotificationsBrokerTopicActionTypes.ADD_TOPICS: { - return Object.assign({}, state, { - topics: action.payload.topics, - processing: false, - loaded: true, - totalPages: action.payload.totalPages, - currentPage: state.currentPage, - totalElements: action.payload.totalElements - }); - } - - case NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR: { - return Object.assign({}, state, { - processing: false, - loaded: true, - totalPages: 0, - currentPage: 0, - totalElements: 0 - }); - } - - default: { - return state; - } - } -} diff --git a/src/app/notifications/notifications-state.service.spec.ts b/src/app/notifications/notifications-state.service.spec.ts index 91048a93ef..cabda48ec5 100644 --- a/src/app/notifications/notifications-state.service.spec.ts +++ b/src/app/notifications/notifications-state.service.spec.ts @@ -5,15 +5,15 @@ import { cold } from 'jasmine-marbles'; import { notificationsReducers } from './notifications.reducer'; import { NotificationsStateService } from './notifications-state.service'; import { - notificationsBrokerSourceObjectMissingPid, - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMorePid, - notificationsBrokerTopicObjectMissingPid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMorePid + qualityAssuranceSourceObjectMissingPid, + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMorePid, + qualityAssuranceTopicObjectMissingPid, + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMorePid } from '../shared/mocks/notifications.mock'; -import { RetrieveAllTopicsAction } from './broker/topics/notifications-broker-topics.actions'; -import { RetrieveAllSourceAction } from './broker/source/notifications-broker-source.actions'; +import { RetrieveAllTopicsAction } from './qa/topics/quality-assurance-topics.actions'; +import { RetrieveAllSourceAction } from './qa/source/quality-assurance-source.actions'; describe('NotificationsStateService', () => { let service: NotificationsStateService; @@ -42,9 +42,9 @@ describe('NotificationsStateService', () => { notifications: { brokerTopic: { topics: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMissingPid + qualityAssuranceTopicObjectMorePid, + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMissingPid ], processing: false, loaded: true, @@ -79,9 +79,9 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('getNotificationsBrokerTopics', () => { + describe('getQualityAssuranceTopics', () => { it('Should return an empty array', () => { - const result = service.getNotificationsBrokerTopics(); + const result = service.getQualityAssuranceTopics(); const expected = cold('(a)', { a: [] }); @@ -89,9 +89,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerTopicsTotalPages', () => { + describe('getQualityAssuranceTopicsTotalPages', () => { it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); + const result = service.getQualityAssuranceTopicsTotalPages(); const expected = cold('(a)', { a: 0 }); @@ -99,9 +99,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerTopicsCurrentPage', () => { + describe('getQualityAssuranceTopicsCurrentPage', () => { it('Should return minus one (0)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); + const result = service.getQualityAssuranceTopicsCurrentPage(); const expected = cold('(a)', { a: 0 }); @@ -109,9 +109,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerTopicsTotals', () => { + describe('getQualityAssuranceTopicsTotals', () => { it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); + const result = service.getQualityAssuranceTopicsTotals(); const expected = cold('(a)', { a: 0 }); @@ -119,9 +119,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsLoading', () => { + describe('isQualityAssuranceTopicsLoading', () => { it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); + const result = service.isQualityAssuranceTopicsLoading(); const expected = cold('(a)', { a: true }); @@ -129,9 +129,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsLoaded', () => { + describe('isQualityAssuranceTopicsLoaded', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); + const result = service.isQualityAssuranceTopicsLoaded(); const expected = cold('(a)', { a: false }); @@ -139,9 +139,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsProcessing', () => { + describe('isQualityAssuranceTopicsProcessing', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); + const result = service.isQualityAssuranceTopicsProcessing(); const expected = cold('(a)', { a: false }); @@ -171,23 +171,23 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('getNotificationsBrokerTopics', () => { + describe('getQualityAssuranceTopics', () => { it('Should return an array of topics', () => { - const result = service.getNotificationsBrokerTopics(); + const result = service.getQualityAssuranceTopics(); const expected = cold('(a)', { a: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMissingPid + qualityAssuranceTopicObjectMorePid, + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMissingPid ] }); expect(result).toBeObservable(expected); }); }); - describe('getNotificationsBrokerTopicsTotalPages', () => { + describe('getQualityAssuranceTopicsTotalPages', () => { it('Should return one (1)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); + const result = service.getQualityAssuranceTopicsTotalPages(); const expected = cold('(a)', { a: 1 }); @@ -195,9 +195,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerTopicsCurrentPage', () => { + describe('getQualityAssuranceTopicsCurrentPage', () => { it('Should return minus zero (1)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); + const result = service.getQualityAssuranceTopicsCurrentPage(); const expected = cold('(a)', { a: 1 }); @@ -205,9 +205,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerTopicsTotals', () => { + describe('getQualityAssuranceTopicsTotals', () => { it('Should return three (3)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); + const result = service.getQualityAssuranceTopicsTotals(); const expected = cold('(a)', { a: 3 }); @@ -215,9 +215,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsLoading', () => { + describe('isQualityAssuranceTopicsLoading', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); + const result = service.isQualityAssuranceTopicsLoading(); const expected = cold('(a)', { a: false }); @@ -225,9 +225,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsLoaded', () => { + describe('isQualityAssuranceTopicsLoaded', () => { it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); + const result = service.isQualityAssuranceTopicsLoaded(); const expected = cold('(a)', { a: true }); @@ -235,9 +235,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerTopicsProcessing', () => { + describe('isQualityAssuranceTopicsProcessing', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); + const result = service.isQualityAssuranceTopicsProcessing(); const expected = cold('(a)', { a: false }); @@ -267,12 +267,12 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('dispatchRetrieveNotificationsBrokerTopics', () => { + describe('dispatchRetrieveQualityAssuranceTopics', () => { it('Should call store.dispatch', () => { const elementsPerPage = 3; const currentPage = 1; const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage); - service.dispatchRetrieveNotificationsBrokerTopics(elementsPerPage, currentPage); + service.dispatchRetrieveQualityAssuranceTopics(elementsPerPage, currentPage); expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); }); }); @@ -300,9 +300,9 @@ describe('NotificationsStateService', () => { notifications: { brokerSource: { source: [ - notificationsBrokerSourceObjectMorePid, - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMissingPid + qualityAssuranceSourceObjectMorePid, + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMissingPid ], processing: false, loaded: true, @@ -337,9 +337,9 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('getNotificationsBrokerSource', () => { + describe('getQualityAssuranceSource', () => { it('Should return an empty array', () => { - const result = service.getNotificationsBrokerSource(); + const result = service.getQualityAssuranceSource(); const expected = cold('(a)', { a: [] }); @@ -347,9 +347,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerSourceTotalPages', () => { + describe('getQualityAssuranceSourceTotalPages', () => { it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerSourceTotalPages(); + const result = service.getQualityAssuranceSourceTotalPages(); const expected = cold('(a)', { a: 0 }); @@ -357,9 +357,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerSourcesCurrentPage', () => { + describe('getQualityAssuranceSourcesCurrentPage', () => { it('Should return minus one (0)', () => { - const result = service.getNotificationsBrokerSourceCurrentPage(); + const result = service.getQualityAssuranceSourceCurrentPage(); const expected = cold('(a)', { a: 0 }); @@ -367,9 +367,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerSourceTotals', () => { + describe('getQualityAssuranceSourceTotals', () => { it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerSourceTotals(); + const result = service.getQualityAssuranceSourceTotals(); const expected = cold('(a)', { a: 0 }); @@ -377,9 +377,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceLoading', () => { + describe('isQualityAssuranceSourceLoading', () => { it('Should return TRUE', () => { - const result = service.isNotificationsBrokerSourceLoading(); + const result = service.isQualityAssuranceSourceLoading(); const expected = cold('(a)', { a: true }); @@ -387,9 +387,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceLoaded', () => { + describe('isQualityAssuranceSourceLoaded', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerSourceLoaded(); + const result = service.isQualityAssuranceSourceLoaded(); const expected = cold('(a)', { a: false }); @@ -397,9 +397,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceProcessing', () => { + describe('isQualityAssuranceSourceProcessing', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerSourceProcessing(); + const result = service.isQualityAssuranceSourceProcessing(); const expected = cold('(a)', { a: false }); @@ -429,23 +429,23 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('getNotificationsBrokerSource', () => { + describe('getQualityAssuranceSource', () => { it('Should return an array of Source', () => { - const result = service.getNotificationsBrokerSource(); + const result = service.getQualityAssuranceSource(); const expected = cold('(a)', { a: [ - notificationsBrokerSourceObjectMorePid, - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMissingPid + qualityAssuranceSourceObjectMorePid, + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMissingPid ] }); expect(result).toBeObservable(expected); }); }); - describe('getNotificationsBrokerSourceTotalPages', () => { + describe('getQualityAssuranceSourceTotalPages', () => { it('Should return one (1)', () => { - const result = service.getNotificationsBrokerSourceTotalPages(); + const result = service.getQualityAssuranceSourceTotalPages(); const expected = cold('(a)', { a: 1 }); @@ -453,9 +453,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerSourceCurrentPage', () => { + describe('getQualityAssuranceSourceCurrentPage', () => { it('Should return minus zero (1)', () => { - const result = service.getNotificationsBrokerSourceCurrentPage(); + const result = service.getQualityAssuranceSourceCurrentPage(); const expected = cold('(a)', { a: 1 }); @@ -463,9 +463,9 @@ describe('NotificationsStateService', () => { }); }); - describe('getNotificationsBrokerSourceTotals', () => { + describe('getQualityAssuranceSourceTotals', () => { it('Should return three (3)', () => { - const result = service.getNotificationsBrokerSourceTotals(); + const result = service.getQualityAssuranceSourceTotals(); const expected = cold('(a)', { a: 3 }); @@ -473,9 +473,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceLoading', () => { + describe('isQualityAssuranceSourceLoading', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerSourceLoading(); + const result = service.isQualityAssuranceSourceLoading(); const expected = cold('(a)', { a: false }); @@ -483,9 +483,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceLoaded', () => { + describe('isQualityAssuranceSourceLoaded', () => { it('Should return TRUE', () => { - const result = service.isNotificationsBrokerSourceLoaded(); + const result = service.isQualityAssuranceSourceLoaded(); const expected = cold('(a)', { a: true }); @@ -493,9 +493,9 @@ describe('NotificationsStateService', () => { }); }); - describe('isNotificationsBrokerSourceProcessing', () => { + describe('isQualityAssuranceSourceProcessing', () => { it('Should return FALSE', () => { - const result = service.isNotificationsBrokerSourceProcessing(); + const result = service.isQualityAssuranceSourceProcessing(); const expected = cold('(a)', { a: false }); @@ -525,12 +525,12 @@ describe('NotificationsStateService', () => { spyOn(store, 'dispatch'); }); - describe('dispatchRetrieveNotificationsBrokerSource', () => { + describe('dispatchRetrieveQualityAssuranceSource', () => { it('Should call store.dispatch', () => { const elementsPerPage = 3; const currentPage = 1; const action = new RetrieveAllSourceAction(elementsPerPage, currentPage); - service.dispatchRetrieveNotificationsBrokerSource(elementsPerPage, currentPage); + service.dispatchRetrieveQualityAssuranceSource(elementsPerPage, currentPage); expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); }); }); diff --git a/src/app/notifications/notifications-state.service.ts b/src/app/notifications/notifications-state.service.ts index cbee503acd..99605a54fa 100644 --- a/src/app/notifications/notifications-state.service.ts +++ b/src/app/notifications/notifications-state.service.ts @@ -3,24 +3,24 @@ import { select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { - getNotificationsBrokerTopicsCurrentPageSelector, - getNotificationsBrokerTopicsTotalPagesSelector, - getNotificationsBrokerTopicsTotalsSelector, - isNotificationsBrokerTopicsLoadedSelector, - notificationsBrokerTopicsObjectSelector, - isNotificationsBrokerTopicsProcessingSelector, - notificationsBrokerSourceObjectSelector, - isNotificationsBrokerSourceLoadedSelector, - isNotificationsBrokerSourceProcessingSelector, - getNotificationsBrokerSourceTotalPagesSelector, - getNotificationsBrokerSourceCurrentPageSelector, - getNotificationsBrokerSourceTotalsSelector + getQualityAssuranceTopicsCurrentPageSelector, + getQualityAssuranceTopicsTotalPagesSelector, + getQualityAssuranceTopicsTotalsSelector, + isQualityAssuranceTopicsLoadedSelector, + qualityAssuranceTopicsObjectSelector, + isQualityAssuranceTopicsProcessingSelector, + qualityAssuranceSourceObjectSelector, + isQualityAssuranceSourceLoadedSelector, + isQualityAssuranceSourceProcessingSelector, + getQualityAssuranceSourceTotalPagesSelector, + getQualityAssuranceSourceCurrentPageSelector, + getQualityAssuranceSourceTotalsSelector } from './selectors'; -import { NotificationsBrokerTopicObject } from '../core/notifications/broker/models/notifications-broker-topic.model'; +import { QualityAssuranceTopicObject } from '../core/notifications/qa/models/quality-assurance-topic.model'; import { NotificationsState } from './notifications.reducer'; -import { RetrieveAllTopicsAction } from './broker/topics/notifications-broker-topics.actions'; -import { NotificationsBrokerSourceObject } from '../core/notifications/broker/models/notifications-broker-source.model'; -import { RetrieveAllSourceAction } from './broker/source/notifications-broker-source.actions'; +import { RetrieveAllTopicsAction } from './qa/topics/quality-assurance-topics.actions'; +import { QualityAssuranceSourceObject } from '../core/notifications/qa/models/quality-assurance-source.model'; +import { RetrieveAllSourceAction } from './qa/source/quality-assurance-source.actions'; /** * The service handling the Notifications State. @@ -34,179 +34,179 @@ export class NotificationsStateService { */ constructor(private store: Store) { } - // Notifications Broker topics + // Quality Assurance topics // -------------------------------------------------------------------------- /** - * Returns the list of Notifications Broker topics from the state. + * Returns the list of Quality Assurance topics from the state. * - * @return Observable - * The list of Notifications Broker topics. + * @return Observable + * The list of Quality Assurance topics. */ - public getNotificationsBrokerTopics(): Observable { - return this.store.pipe(select(notificationsBrokerTopicsObjectSelector())); + public getQualityAssuranceTopics(): Observable { + return this.store.pipe(select(qualityAssuranceTopicsObjectSelector())); } /** - * Returns the information about the loading status of the Notifications Broker topics (if it's running or not). + * Returns the information about the loading status of the Quality Assurance topics (if it's running or not). * * @return Observable * 'true' if the topics are loading, 'false' otherwise. */ - public isNotificationsBrokerTopicsLoading(): Observable { + public isQualityAssuranceTopicsLoading(): Observable { return this.store.pipe( - select(isNotificationsBrokerTopicsLoadedSelector), + select(isQualityAssuranceTopicsLoadedSelector), map((loaded: boolean) => !loaded) ); } /** - * Returns the information about the loading status of the Notifications Broker topics (whether or not they were loaded). + * Returns the information about the loading status of the Quality Assurance topics (whether or not they were loaded). * * @return Observable * 'true' if the topics are loaded, 'false' otherwise. */ - public isNotificationsBrokerTopicsLoaded(): Observable { - return this.store.pipe(select(isNotificationsBrokerTopicsLoadedSelector)); + public isQualityAssuranceTopicsLoaded(): Observable { + return this.store.pipe(select(isQualityAssuranceTopicsLoadedSelector)); } /** - * Returns the information about the processing status of the Notifications Broker topics (if it's running or not). + * Returns the information about the processing status of the Quality Assurance topics (if it's running or not). * * @return Observable * 'true' if there are operations running on the topics (ex.: a REST call), 'false' otherwise. */ - public isNotificationsBrokerTopicsProcessing(): Observable { - return this.store.pipe(select(isNotificationsBrokerTopicsProcessingSelector)); + public isQualityAssuranceTopicsProcessing(): Observable { + return this.store.pipe(select(isQualityAssuranceTopicsProcessingSelector)); } /** - * Returns, from the state, the total available pages of the Notifications Broker topics. + * Returns, from the state, the total available pages of the Quality Assurance topics. * * @return Observable - * The number of the Notifications Broker topics pages. + * The number of the Quality Assurance topics pages. */ - public getNotificationsBrokerTopicsTotalPages(): Observable { - return this.store.pipe(select(getNotificationsBrokerTopicsTotalPagesSelector)); + public getQualityAssuranceTopicsTotalPages(): Observable { + return this.store.pipe(select(getQualityAssuranceTopicsTotalPagesSelector)); } /** - * Returns the current page of the Notifications Broker topics, from the state. + * Returns the current page of the Quality Assurance topics, from the state. * * @return Observable - * The number of the current Notifications Broker topics page. + * The number of the current Quality Assurance topics page. */ - public getNotificationsBrokerTopicsCurrentPage(): Observable { - return this.store.pipe(select(getNotificationsBrokerTopicsCurrentPageSelector)); + public getQualityAssuranceTopicsCurrentPage(): Observable { + return this.store.pipe(select(getQualityAssuranceTopicsCurrentPageSelector)); } /** - * Returns the total number of the Notifications Broker topics. + * Returns the total number of the Quality Assurance topics. * * @return Observable - * The number of the Notifications Broker topics. + * The number of the Quality Assurance topics. */ - public getNotificationsBrokerTopicsTotals(): Observable { - return this.store.pipe(select(getNotificationsBrokerTopicsTotalsSelector)); + public getQualityAssuranceTopicsTotals(): Observable { + return this.store.pipe(select(getQualityAssuranceTopicsTotalsSelector)); } /** - * Dispatch a request to change the Notifications Broker topics state, retrieving the topics from the server. + * Dispatch a request to change the Quality Assurance topics state, retrieving the topics from the server. * * @param elementsPerPage * The number of the topics per page. * @param currentPage * The number of the current page. */ - public dispatchRetrieveNotificationsBrokerTopics(elementsPerPage: number, currentPage: number): void { + public dispatchRetrieveQualityAssuranceTopics(elementsPerPage: number, currentPage: number): void { this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage)); } - // Notifications Broker source + // Quality Assurance source // -------------------------------------------------------------------------- /** - * Returns the list of Notifications Broker source from the state. + * Returns the list of Quality Assurance source from the state. * - * @return Observable - * The list of Notifications Broker source. + * @return Observable + * The list of Quality Assurance source. */ - public getNotificationsBrokerSource(): Observable { - return this.store.pipe(select(notificationsBrokerSourceObjectSelector())); + public getQualityAssuranceSource(): Observable { + return this.store.pipe(select(qualityAssuranceSourceObjectSelector())); } /** - * Returns the information about the loading status of the Notifications Broker source (if it's running or not). + * Returns the information about the loading status of the Quality Assurance source (if it's running or not). * * @return Observable * 'true' if the source are loading, 'false' otherwise. */ - public isNotificationsBrokerSourceLoading(): Observable { + public isQualityAssuranceSourceLoading(): Observable { return this.store.pipe( - select(isNotificationsBrokerSourceLoadedSelector), + select(isQualityAssuranceSourceLoadedSelector), map((loaded: boolean) => !loaded) ); } /** - * Returns the information about the loading status of the Notifications Broker source (whether or not they were loaded). + * Returns the information about the loading status of the Quality Assurance source (whether or not they were loaded). * * @return Observable * 'true' if the source are loaded, 'false' otherwise. */ - public isNotificationsBrokerSourceLoaded(): Observable { - return this.store.pipe(select(isNotificationsBrokerSourceLoadedSelector)); + public isQualityAssuranceSourceLoaded(): Observable { + return this.store.pipe(select(isQualityAssuranceSourceLoadedSelector)); } /** - * Returns the information about the processing status of the Notifications Broker source (if it's running or not). + * Returns the information about the processing status of the Quality Assurance source (if it's running or not). * * @return Observable * 'true' if there are operations running on the source (ex.: a REST call), 'false' otherwise. */ - public isNotificationsBrokerSourceProcessing(): Observable { - return this.store.pipe(select(isNotificationsBrokerSourceProcessingSelector)); + public isQualityAssuranceSourceProcessing(): Observable { + return this.store.pipe(select(isQualityAssuranceSourceProcessingSelector)); } /** - * Returns, from the state, the total available pages of the Notifications Broker source. + * Returns, from the state, the total available pages of the Quality Assurance source. * * @return Observable - * The number of the Notifications Broker source pages. + * The number of the Quality Assurance source pages. */ - public getNotificationsBrokerSourceTotalPages(): Observable { - return this.store.pipe(select(getNotificationsBrokerSourceTotalPagesSelector)); + public getQualityAssuranceSourceTotalPages(): Observable { + return this.store.pipe(select(getQualityAssuranceSourceTotalPagesSelector)); } /** - * Returns the current page of the Notifications Broker source, from the state. + * Returns the current page of the Quality Assurance source, from the state. * * @return Observable - * The number of the current Notifications Broker source page. + * The number of the current Quality Assurance source page. */ - public getNotificationsBrokerSourceCurrentPage(): Observable { - return this.store.pipe(select(getNotificationsBrokerSourceCurrentPageSelector)); + public getQualityAssuranceSourceCurrentPage(): Observable { + return this.store.pipe(select(getQualityAssuranceSourceCurrentPageSelector)); } /** - * Returns the total number of the Notifications Broker source. + * Returns the total number of the Quality Assurance source. * * @return Observable - * The number of the Notifications Broker source. + * The number of the Quality Assurance source. */ - public getNotificationsBrokerSourceTotals(): Observable { - return this.store.pipe(select(getNotificationsBrokerSourceTotalsSelector)); + public getQualityAssuranceSourceTotals(): Observable { + return this.store.pipe(select(getQualityAssuranceSourceTotalsSelector)); } /** - * Dispatch a request to change the Notifications Broker source state, retrieving the source from the server. + * Dispatch a request to change the Quality Assurance source state, retrieving the source from the server. * * @param elementsPerPage * The number of the source per page. * @param currentPage * The number of the current page. */ - public dispatchRetrieveNotificationsBrokerSource(elementsPerPage: number, currentPage: number): void { + public dispatchRetrieveQualityAssuranceSource(elementsPerPage: number, currentPage: number): void { this.store.dispatch(new RetrieveAllSourceAction(elementsPerPage, currentPage)); } } diff --git a/src/app/notifications/notifications.effects.ts b/src/app/notifications/notifications.effects.ts index 39ecded797..bf70a05855 100644 --- a/src/app/notifications/notifications.effects.ts +++ b/src/app/notifications/notifications.effects.ts @@ -1,7 +1,7 @@ -import { NotificationsBrokerSourceEffects } from './broker/source/notifications-broker-source.effects'; -import { NotificationsBrokerTopicsEffects } from './broker/topics/notifications-broker-topics.effects'; +import { QualityAssuranceSourceEffects } from './qa/source/quality-assurance-source.effects'; +import { QualityAssuranceTopicsEffects } from './qa/topics/quality-assurance-topics.effects'; export const notificationsEffects = [ - NotificationsBrokerTopicsEffects, - NotificationsBrokerSourceEffects + QualityAssuranceTopicsEffects, + QualityAssuranceSourceEffects ]; diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index 63224fdd81..27e34c8d51 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -6,20 +6,20 @@ import { EffectsModule } from '@ngrx/effects'; import { CoreModule } from '../core/core.module'; import { SharedModule } from '../shared/shared.module'; import { storeModuleConfig } from '../app.reducer'; -import { NotificationsBrokerTopicsComponent } from './broker/topics/notifications-broker-topics.component'; -import { NotificationsBrokerEventsComponent } from './broker/events/notifications-broker-events.component'; +import { QualityAssuranceTopicsComponent } from './qa/topics/quality-assurance-topics.component'; +import { QualityAssuranceEventsComponent } from './qa/events/quality-assurance-events.component'; import { NotificationsStateService } from './notifications-state.service'; import { notificationsReducers, NotificationsState } from './notifications.reducer'; import { notificationsEffects } from './notifications.effects'; -import { NotificationsBrokerTopicsService } from './broker/topics/notifications-broker-topics.service'; -import { NotificationsBrokerTopicRestService } from '../core/notifications/broker/topics/notifications-broker-topic-rest.service'; -import { NotificationsBrokerEventRestService } from '../core/notifications/broker/events/notifications-broker-event-rest.service'; -import { ProjectEntryImportModalComponent } from './broker/project-entry-import-modal/project-entry-import-modal.component'; +import { QualityAssuranceTopicsService } from './qa/topics/quality-assurance-topics.service'; +import { QualityAssuranceTopicRestService } from '../core/notifications/qa/topics/quality-assurance-topic-rest.service'; +import { QualityAssuranceEventRestService } from '../core/notifications/qa/events/quality-assurance-event-rest.service'; +import { ProjectEntryImportModalComponent } from './qa/project-entry-import-modal/project-entry-import-modal.component'; import { TranslateModule } from '@ngx-translate/core'; import { SearchModule } from '../shared/search/search.module'; -import { NotificationsBrokerSourceComponent } from './broker/source/notifications-broker-source.component'; -import { NotificationsBrokerSourceService } from './broker/source/notifications-broker-source.service'; -import { NotificationsBrokerSourceRestService } from '../core/notifications/broker/source/notifications-broker-source-rest.service'; +import { QualityAssuranceSourceComponent } from './qa/source/quality-assurance-source.component'; +import { QualityAssuranceSourceService } from './qa/source/quality-assurance-source.service'; +import { QualityAssuranceSourceRestService } from '../core/notifications/qa/source/quality-assurance-source-rest.service'; const MODULES = [ CommonModule, @@ -31,9 +31,9 @@ const MODULES = [ ]; const COMPONENTS = [ - NotificationsBrokerTopicsComponent, - NotificationsBrokerEventsComponent, - NotificationsBrokerSourceComponent + QualityAssuranceTopicsComponent, + QualityAssuranceEventsComponent, + QualityAssuranceSourceComponent ]; const DIRECTIVES = [ ]; @@ -44,11 +44,11 @@ const ENTRY_COMPONENTS = [ const PROVIDERS = [ NotificationsStateService, - NotificationsBrokerTopicsService, - NotificationsBrokerSourceService, - NotificationsBrokerTopicRestService, - NotificationsBrokerSourceRestService, - NotificationsBrokerEventRestService + QualityAssuranceTopicsService, + QualityAssuranceSourceService, + QualityAssuranceTopicRestService, + QualityAssuranceSourceRestService, + QualityAssuranceEventRestService ]; @NgModule({ diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index 27bebbea20..5800788c42 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -1,18 +1,18 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; -import { notificationsBrokerSourceReducer, NotificationsBrokerSourceState } from './broker/source/notifications-broker-source.reducer'; -import { notificationsBrokerTopicsReducer, NotificationsBrokerTopicState, } from './broker/topics/notifications-broker-topics.reducer'; +import { qualityAssuranceSourceReducer, QualityAssuranceSourceState } from './qa/source/quality-assurance-source.reducer'; +import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState, } from './qa/topics/quality-assurance-topics.reducer'; /** * The OpenAIRE State */ export interface NotificationsState { - 'brokerTopic': NotificationsBrokerTopicState; - 'brokerSource': NotificationsBrokerSourceState; + 'brokerTopic': QualityAssuranceTopicState; + 'brokerSource': QualityAssuranceSourceState; } export const notificationsReducers: ActionReducerMap = { - brokerTopic: notificationsBrokerTopicsReducer, - brokerSource: notificationsBrokerSourceReducer + brokerTopic: qualityAssuranceTopicsReducer, + brokerSource: qualityAssuranceSourceReducer }; export const notificationsSelector = createFeatureSelector('notifications'); diff --git a/src/app/notifications/broker/events/notifications-broker-events.component.html b/src/app/notifications/qa/events/quality-assurance-events.component.html similarity index 98% rename from src/app/notifications/broker/events/notifications-broker-events.component.html rename to src/app/notifications/qa/events/quality-assurance-events.component.html index a9f51cefd0..40fa75943f 100644 --- a/src/app/notifications/broker/events/notifications-broker-events.component.html +++ b/src/app/notifications/qa/events/quality-assurance-events.component.html @@ -4,7 +4,7 @@

{{'notifications.events.title'| translate}}

{{'notifications.broker.events.description'| translate}}

- + {{'notifications.broker.events.back' | translate}} @@ -23,7 +23,7 @@ [paginationOptions]="paginationConfig" [collectionSize]="(totalElements$ | async)" [sortOptions]="paginationSortConfig" - (paginationChange)="getNotificationsBrokerEvents()"> + (paginationChange)="getQualityAssuranceEvents()"> @@ -140,7 +140,7 @@

- + {{'notifications.broker.events.back' | translate}} diff --git a/src/app/notifications/broker/events/notifications-broker-events.component.spec.ts b/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts similarity index 66% rename from src/app/notifications/broker/events/notifications-broker-events.component.spec.ts rename to src/app/notifications/qa/events/quality-assurance-events.component.spec.ts index 40be083567..976d8540e3 100644 --- a/src/app/notifications/broker/events/notifications-broker-events.component.spec.ts +++ b/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts @@ -5,15 +5,15 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/t import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { of as observableOf } from 'rxjs'; -import { NotificationsBrokerEventRestService } from '../../../core/notifications/broker/events/notifications-broker-event-rest.service'; -import { NotificationsBrokerEventsComponent } from './notifications-broker-events.component'; +import { QualityAssuranceEventRestService } from '../../../core/notifications/qa/events/quality-assurance-event-rest.service'; +import { QualityAssuranceEventsComponent } from './quality-assurance-events.component'; import { - getMockNotificationsBrokerEventRestService, + getMockQualityAssuranceEventRestService, ItemMockPid10, ItemMockPid8, ItemMockPid9, - notificationsBrokerEventObjectMissingProjectFound, - notificationsBrokerEventObjectMissingProjectNotFound, + qualityAssuranceEventObjectMissingProjectFound, + qualityAssuranceEventObjectMissingProjectNotFound, NotificationsMockDspaceObject } from '../../../shared/mocks/notifications.mock'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; @@ -22,8 +22,8 @@ import { getMockTranslateService } from '../../../shared/mocks/translate.service import { createTestComponent } from '../../../shared/testing/utils.test'; import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { NotificationsBrokerEventObject } from '../../../core/notifications/broker/models/notifications-broker-event.model'; -import { NotificationsBrokerEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; +import { QualityAssuranceEventObject } from '../../../core/notifications/qa/models/quality-assurance-event.model'; +import { QualityAssuranceEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -34,14 +34,14 @@ import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { FindListOptions } from '../../../core/data/request.models'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; -describe('NotificationsBrokerEventsComponent test suite', () => { - let fixture: ComponentFixture; - let comp: NotificationsBrokerEventsComponent; +describe('QualityAssuranceEventsComponent test suite', () => { + let fixture: ComponentFixture; + let comp: QualityAssuranceEventsComponent; let compAsAny: any; let scheduler: TestScheduler; @@ -50,9 +50,9 @@ describe('NotificationsBrokerEventsComponent test suite', () => { close: () => null, dismiss: () => null }; - const notificationsBrokerEventRestServiceStub: any = getMockNotificationsBrokerEventRestService(); + const qualityAssuranceEventRestServiceStub: any = getMockQualityAssuranceEventRestService(); const activatedRouteParams = { - notificationsBrokerEventsParams: { + qualityAssuranceEventsParams: { currentPage: 0, pageSize: 10 } @@ -61,19 +61,19 @@ describe('NotificationsBrokerEventsComponent test suite', () => { id: 'ENRICH!MISSING!PROJECT' }; - const events: NotificationsBrokerEventObject[] = [ - notificationsBrokerEventObjectMissingProjectFound, - notificationsBrokerEventObjectMissingProjectNotFound + const events: QualityAssuranceEventObject[] = [ + qualityAssuranceEventObjectMissingProjectFound, + qualityAssuranceEventObjectMissingProjectNotFound ]; const paginationService = new PaginationServiceStub(); - function getNotificationsBrokerEventData1(): NotificationsBrokerEventData { + function getQualityAssuranceEventData1(): QualityAssuranceEventData { return { - event: notificationsBrokerEventObjectMissingProjectFound, - id: notificationsBrokerEventObjectMissingProjectFound.id, - title: notificationsBrokerEventObjectMissingProjectFound.title, + event: qualityAssuranceEventObjectMissingProjectFound, + id: qualityAssuranceEventObjectMissingProjectFound.id, + title: qualityAssuranceEventObjectMissingProjectFound.title, hasProject: true, - projectTitle: notificationsBrokerEventObjectMissingProjectFound.message.title, + projectTitle: qualityAssuranceEventObjectMissingProjectFound.message.title, projectId: ItemMockPid10.id, handle: ItemMockPid10.handle, reason: null, @@ -82,11 +82,11 @@ describe('NotificationsBrokerEventsComponent test suite', () => { }; } - function getNotificationsBrokerEventData2(): NotificationsBrokerEventData { + function getQualityAssuranceEventData2(): QualityAssuranceEventData { return { - event: notificationsBrokerEventObjectMissingProjectNotFound, - id: notificationsBrokerEventObjectMissingProjectNotFound.id, - title: notificationsBrokerEventObjectMissingProjectNotFound.title, + event: qualityAssuranceEventObjectMissingProjectNotFound, + id: qualityAssuranceEventObjectMissingProjectNotFound.id, + title: qualityAssuranceEventObjectMissingProjectNotFound.title, hasProject: false, projectTitle: null, projectId: null, @@ -104,17 +104,17 @@ describe('NotificationsBrokerEventsComponent test suite', () => { TranslateModule.forRoot(), ], declarations: [ - NotificationsBrokerEventsComponent, + QualityAssuranceEventsComponent, TestComponent, ], providers: [ { provide: ActivatedRoute, useValue: new ActivatedRouteStub(activatedRouteParamsMap, activatedRouteParams) }, - { provide: NotificationsBrokerEventRestService, useValue: notificationsBrokerEventRestServiceStub }, + { provide: QualityAssuranceEventRestService, useValue: qualityAssuranceEventRestServiceStub }, { provide: NgbModal, useValue: modalStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, { provide: PaginationService, useValue: paginationService }, - NotificationsBrokerEventsComponent + QualityAssuranceEventsComponent ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(); @@ -129,7 +129,7 @@ describe('NotificationsBrokerEventsComponent test suite', () => { // synchronous beforeEach beforeEach(() => { const html = ` - `; + `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); @@ -138,14 +138,14 @@ describe('NotificationsBrokerEventsComponent test suite', () => { testFixture.destroy(); }); - it('should create NotificationsBrokerEventsComponent', inject([NotificationsBrokerEventsComponent], (app: NotificationsBrokerEventsComponent) => { + it('should create QualityAssuranceEventsComponent', inject([QualityAssuranceEventsComponent], (app: QualityAssuranceEventsComponent) => { expect(app).toBeDefined(); })); }); describe('Main tests', () => { beforeEach(() => { - fixture = TestBed.createComponent(NotificationsBrokerEventsComponent); + fixture = TestBed.createComponent(QualityAssuranceEventsComponent); comp = fixture.componentInstance; compAsAny = comp; }); @@ -159,8 +159,8 @@ describe('NotificationsBrokerEventsComponent test suite', () => { describe('setEventUpdated', () => { it('should update events', () => { const expected = [ - getNotificationsBrokerEventData1(), - getNotificationsBrokerEventData2() + getQualityAssuranceEventData1(), + getQualityAssuranceEventData2() ]; scheduler.schedule(() => { compAsAny.setEventUpdated(events); @@ -179,14 +179,14 @@ describe('NotificationsBrokerEventsComponent test suite', () => { it('should call executeAction if a project is present', () => { const action = 'ACCEPTED'; - comp.modalChoice(action, getNotificationsBrokerEventData1(), modalStub); - expect(comp.executeAction).toHaveBeenCalledWith(action, getNotificationsBrokerEventData1()); + comp.modalChoice(action, getQualityAssuranceEventData1(), modalStub); + expect(comp.executeAction).toHaveBeenCalledWith(action, getQualityAssuranceEventData1()); }); it('should call openModal if a project is not present', () => { const action = 'ACCEPTED'; - comp.modalChoice(action, getNotificationsBrokerEventData2(), modalStub); - expect(comp.openModal).toHaveBeenCalledWith(action, getNotificationsBrokerEventData2(), modalStub); + comp.modalChoice(action, getQualityAssuranceEventData2(), modalStub); + expect(comp.openModal).toHaveBeenCalledWith(action, getQualityAssuranceEventData2(), modalStub); }); }); @@ -197,7 +197,7 @@ describe('NotificationsBrokerEventsComponent test suite', () => { spyOn(compAsAny.modalService, 'open').and.returnValue({ result: new Promise((res, rej) => 'do' ) }); spyOn(comp, 'executeAction'); - comp.openModal(action, getNotificationsBrokerEventData1(), modalStub); + comp.openModal(action, getQualityAssuranceEventData1(), modalStub); expect(compAsAny.modalService.open).toHaveBeenCalled(); }); }); @@ -217,7 +217,7 @@ describe('NotificationsBrokerEventsComponent test suite', () => { } ); scheduler.schedule(() => { - comp.openModalLookup(getNotificationsBrokerEventData1()); + comp.openModalLookup(getQualityAssuranceEventData1()); }); scheduler.flush(); @@ -227,27 +227,27 @@ describe('NotificationsBrokerEventsComponent test suite', () => { }); describe('executeAction', () => { - it('should call getNotificationsBrokerEvents on 200 response from REST', () => { + it('should call getQualityAssuranceEvents on 200 response from REST', () => { const action = 'ACCEPTED'; - spyOn(compAsAny, 'getNotificationsBrokerEvents'); - notificationsBrokerEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); + spyOn(compAsAny, 'getQualityAssuranceEvents'); + qualityAssuranceEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); scheduler.schedule(() => { - comp.executeAction(action, getNotificationsBrokerEventData1()); + comp.executeAction(action, getQualityAssuranceEventData1()); }); scheduler.flush(); - expect(compAsAny.getNotificationsBrokerEvents).toHaveBeenCalled(); + expect(compAsAny.getQualityAssuranceEvents).toHaveBeenCalled(); }); }); describe('boundProject', () => { it('should populate the project data inside "eventData"', () => { - const eventData = getNotificationsBrokerEventData2(); + const eventData = getQualityAssuranceEventData2(); const projectId = 'UUID-23943-34u43-38344'; const projectName = 'Test Project'; const projectHandle = '1000/1000'; - notificationsBrokerEventRestServiceStub.boundProject.and.returnValue(createSuccessfulRemoteDataObject$({})); + qualityAssuranceEventRestServiceStub.boundProject.and.returnValue(createSuccessfulRemoteDataObject$({})); scheduler.schedule(() => { comp.boundProject(eventData, projectId, projectName, projectHandle); @@ -263,8 +263,8 @@ describe('NotificationsBrokerEventsComponent test suite', () => { describe('removeProject', () => { it('should remove the project data inside "eventData"', () => { - const eventData = getNotificationsBrokerEventData1(); - notificationsBrokerEventRestServiceStub.removeProject.and.returnValue(createNoContentRemoteDataObject$()); + const eventData = getQualityAssuranceEventData1(); + qualityAssuranceEventRestServiceStub.removeProject.and.returnValue(createNoContentRemoteDataObject$()); scheduler.schedule(() => { comp.removeProject(eventData); @@ -278,8 +278,8 @@ describe('NotificationsBrokerEventsComponent test suite', () => { }); }); - describe('getNotificationsBrokerEvents', () => { - it('should call the "notificationsBrokerEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { + describe('getQualityAssuranceEvents', () => { + it('should call the "qualityAssuranceEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { comp.paginationConfig = new PaginationComponentOptions(); comp.paginationConfig.currentPage = 1; comp.paginationConfig.pageSize = 20; @@ -297,20 +297,20 @@ describe('NotificationsBrokerEventsComponent test suite', () => { currentPage: comp.paginationConfig.currentPage }); const array = [ - notificationsBrokerEventObjectMissingProjectFound, - notificationsBrokerEventObjectMissingProjectNotFound, + qualityAssuranceEventObjectMissingProjectFound, + qualityAssuranceEventObjectMissingProjectNotFound, ]; const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - notificationsBrokerEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); + qualityAssuranceEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); spyOn(compAsAny, 'setEventUpdated'); scheduler.schedule(() => { - compAsAny.getNotificationsBrokerEvents(); + compAsAny.getQualityAssuranceEvents(); }); scheduler.flush(); - expect(compAsAny.notificationsBrokerEventRestService.getEventsByTopic).toHaveBeenCalledWith( + expect(compAsAny.qualityAssuranceEventRestService.getEventsByTopic).toHaveBeenCalledWith( activatedRouteParamsMap.id, options, followLink('target'),followLink('related') diff --git a/src/app/notifications/broker/events/notifications-broker-events.component.ts b/src/app/notifications/qa/events/quality-assurance-events.component.ts similarity index 74% rename from src/app/notifications/broker/events/notifications-broker-events.component.ts rename to src/app/notifications/qa/events/quality-assurance-events.component.ts index 7639554c55..aa47bfc590 100644 --- a/src/app/notifications/broker/events/notifications-broker-events.component.ts +++ b/src/app/notifications/qa/events/quality-assurance-events.component.ts @@ -9,12 +9,11 @@ import { distinctUntilChanged, map, mergeMap, scan, switchMap, take } from 'rxjs import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; -import { FindListOptions } from '../../../core/data/request.models'; import { - NotificationsBrokerEventObject, + QualityAssuranceEventObject, OpenaireBrokerEventMessageObject -} from '../../../core/notifications/broker/models/notifications-broker-event.model'; -import { NotificationsBrokerEventRestService } from '../../../core/notifications/broker/events/notifications-broker-event-rest.service'; +} from '../../../core/notifications/qa/models/quality-assurance-event.model'; +import { QualityAssuranceEventRestService } from '../../../core/notifications/qa/events/quality-assurance-event-rest.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { Metadata } from '../../../core/shared/metadata.utils'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -22,23 +21,24 @@ import { hasValue } from '../../../shared/empty.util'; import { ItemSearchResult } from '../../../shared/object-collection/shared/item-search-result.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { - NotificationsBrokerEventData, + QualityAssuranceEventData, ProjectEntryImportModalComponent } from '../project-entry-import-modal/project-entry-import-modal.component'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { combineLatest } from 'rxjs/internal/observable/combineLatest'; import { Item } from '../../../core/shared/item.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; /** - * Component to display the Notifications Broker event list. + * Component to display the Quality Assurance event list. */ @Component({ - selector: 'ds-notifications-broker-events', - templateUrl: './notifications-broker-events.component.html', - styleUrls: ['./notifications-broker-events.scomponent.scss'], + selector: 'ds-quality-assurance-events', + templateUrl: './quality-assurance-events.component.html', + styleUrls: ['./quality-assurance-events.scomponent.scss'], }) -export class NotificationsBrokerEventsComponent implements OnInit { +export class QualityAssuranceEventsComponent implements OnInit { /** * The pagination system configuration for HTML listing. * @type {PaginationComponentOptions} @@ -50,27 +50,27 @@ export class NotificationsBrokerEventsComponent implements OnInit { pageSizeOptions: [5, 10, 20, 40, 60] }); /** - * The Notifications Broker event list sort options. + * The Quality Assurance event list sort options. * @type {SortOptions} */ public paginationSortConfig: SortOptions = new SortOptions('trust', SortDirection.DESC); /** - * Array to save the presence of a project inside an Notifications Broker event. - * @type {NotificationsBrokerEventData[]>} + * Array to save the presence of a project inside an Quality Assurance event. + * @type {QualityAssuranceEventData[]>} */ - public eventsUpdated$: BehaviorSubject = new BehaviorSubject([]); + public eventsUpdated$: BehaviorSubject = new BehaviorSubject([]); /** - * The total number of Notifications Broker events. + * The total number of Quality Assurance events. * @type {Observable} */ public totalElements$: Observable; /** - * The topic of the Notifications Broker events; suitable for displaying. + * The topic of the Quality Assurance events; suitable for displaying. * @type {string} */ public showTopic: string; /** - * The topic of the Notifications Broker events; suitable for HTTP calls. + * The topic of the Quality Assurance events; suitable for HTTP calls. * @type {string} */ public topic: string; @@ -114,7 +114,7 @@ export class NotificationsBrokerEventsComponent implements OnInit { * @param {ActivatedRoute} activatedRoute * @param {NgbModal} modalService * @param {NotificationsService} notificationsService - * @param {NotificationsBrokerEventRestService} notificationsBrokerEventRestService + * @param {QualityAssuranceEventRestService} qualityAssuranceEventRestService * @param {PaginationService} paginationService * @param {TranslateService} translateService */ @@ -122,7 +122,7 @@ export class NotificationsBrokerEventsComponent implements OnInit { private activatedRoute: ActivatedRoute, private modalService: NgbModal, private notificationsService: NotificationsService, - private notificationsBrokerEventRestService: NotificationsBrokerEventRestService, + private qualityAssuranceEventRestService: QualityAssuranceEventRestService, private paginationService: PaginationService, private translateService: TranslateService ) { @@ -142,7 +142,7 @@ export class NotificationsBrokerEventsComponent implements OnInit { this.showTopic = id.replace(regEx, '/'); this.topic = id; this.isEventPageLoading.next(false); - this.getNotificationsBrokerEvents(); + this.getQualityAssuranceEvents(); }); } @@ -162,12 +162,12 @@ export class NotificationsBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event data * @param {any} content * Reference to the modal */ - public modalChoice(action: string, eventData: NotificationsBrokerEventData, content: any): void { + public modalChoice(action: string, eventData: QualityAssuranceEventData, content: any): void { if (eventData.hasProject) { this.executeAction(action, eventData); } else { @@ -180,12 +180,12 @@ export class NotificationsBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event data * @param {any} content * Reference to the modal */ - public openModal(action: string, eventData: NotificationsBrokerEventData, content: any): void { + public openModal(action: string, eventData: QualityAssuranceEventData, content: any): void { this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then( (result) => { if (result === 'do') { @@ -203,10 +203,10 @@ export class NotificationsBrokerEventsComponent implements OnInit { /** * Open a modal where the user can select the project. * - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event item data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event item data */ - public openModalLookup(eventData: NotificationsBrokerEventData): void { + public openModalLookup(eventData: QualityAssuranceEventData): void { this.modalRef = this.modalService.open(ProjectEntryImportModalComponent, { size: 'lg' }); @@ -232,19 +232,19 @@ export class NotificationsBrokerEventsComponent implements OnInit { * * @param {string} action * the action (can be: ACCEPTED, REJECTED, DISCARDED, PENDING) - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event data */ - public executeAction(action: string, eventData: NotificationsBrokerEventData): void { + public executeAction(action: string, eventData: QualityAssuranceEventData): void { eventData.isRunning = true; this.subs.push( - this.notificationsBrokerEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.qualityAssuranceEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess && rd.statusCode === 200) { this.notificationsService.success( this.translateService.instant('notifications.broker.event.action.saved') ); - this.getNotificationsBrokerEvents(); + this.getQualityAssuranceEvents(); } else { this.notificationsService.error( this.translateService.instant('notifications.broker.event.action.error') @@ -256,10 +256,10 @@ export class NotificationsBrokerEventsComponent implements OnInit { } /** - * Bound a project to the publication described in the Notifications Broker event calling the REST service. + * Bound a project to the publication described in the Quality Assurance event calling the REST service. * - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event item data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event item data * @param {string} projectId * the project Id to bound * @param {string} projectTitle @@ -267,11 +267,11 @@ export class NotificationsBrokerEventsComponent implements OnInit { * @param {string} projectHandle * the project handle */ - public boundProject(eventData: NotificationsBrokerEventData, projectId: string, projectTitle: string, projectHandle: string): void { + public boundProject(eventData: QualityAssuranceEventData, projectId: string, projectTitle: string, projectHandle: string): void { eventData.isRunning = true; this.subs.push( - this.notificationsBrokerEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.qualityAssuranceEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( this.translateService.instant('notifications.broker.event.project.bounded') @@ -291,16 +291,16 @@ export class NotificationsBrokerEventsComponent implements OnInit { } /** - * Remove the bounded project from the publication described in the Notifications Broker event calling the REST service. + * Remove the bounded project from the publication described in the Quality Assurance event calling the REST service. * - * @param {NotificationsBrokerEventData} eventData - * the Notifications Broker event data + * @param {QualityAssuranceEventData} eventData + * the Quality Assurance event data */ - public removeProject(eventData: NotificationsBrokerEventData): void { + public removeProject(eventData: QualityAssuranceEventData): void { eventData.isRunning = true; this.subs.push( - this.notificationsBrokerEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { + this.qualityAssuranceEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) + .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( this.translateService.instant('notifications.broker.event.project.removed') @@ -337,26 +337,26 @@ export class NotificationsBrokerEventsComponent implements OnInit { /** - * Dispatch the Notifications Broker events retrival. + * Dispatch the Quality Assurance events retrival. */ - public getNotificationsBrokerEvents(): void { + public getQualityAssuranceEvents(): void { this.paginationService.getFindListOptions(this.paginationConfig.id, this.defaultConfig).pipe( distinctUntilChanged(), - switchMap((options: FindListOptions) => this.notificationsBrokerEventRestService.getEventsByTopic( + switchMap((options: FindListOptions) => this.qualityAssuranceEventRestService.getEventsByTopic( this.topic, options, followLink('target'), followLink('related') )), getFirstCompletedRemoteData(), - ).subscribe((rd: RemoteData>) => { + ).subscribe((rd: RemoteData>) => { if (rd.hasSucceeded) { this.isEventLoading.next(false); this.totalElements$ = observableOf(rd.payload.totalElements); this.setEventUpdated(rd.payload.page); } else { - throw new Error('Can\'t retrieve Notifications Broker events from the Broker events REST service'); + throw new Error('Can\'t retrieve Quality Assurance events from the Broker events REST service'); } - this.notificationsBrokerEventRestService.clearFindByTopicRequests(); + this.qualityAssuranceEventRestService.clearFindByTopicRequests(); }); } @@ -370,15 +370,15 @@ export class NotificationsBrokerEventsComponent implements OnInit { } /** - * Set the project status for the Notifications Broker events. + * Set the project status for the Quality Assurance events. * - * @param {NotificationsBrokerEventObject[]} events - * the Notifications Broker event item + * @param {QualityAssuranceEventObject[]} events + * the Quality Assurance event item */ - protected setEventUpdated(events: NotificationsBrokerEventObject[]): void { + protected setEventUpdated(events: QualityAssuranceEventObject[]): void { this.subs.push( from(events).pipe( - mergeMap((event: NotificationsBrokerEventObject) => { + mergeMap((event: QualityAssuranceEventObject) => { const related$ = event.related.pipe( getFirstCompletedRemoteData(), ); @@ -387,7 +387,7 @@ export class NotificationsBrokerEventsComponent implements OnInit { ); return combineLatest([related$, target$]).pipe( map(([relatedItemRD, targetItemRD]: [RemoteData, RemoteData]) => { - const data: NotificationsBrokerEventData = { + const data: QualityAssuranceEventData = { event: event, id: event.id, title: event.title, diff --git a/src/app/notifications/broker/events/notifications-broker-events.scomponent.scss b/src/app/notifications/qa/events/quality-assurance-events.scomponent.scss similarity index 100% rename from src/app/notifications/broker/events/notifications-broker-events.scomponent.scss rename to src/app/notifications/qa/events/quality-assurance-events.scomponent.scss diff --git a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.html b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html similarity index 100% rename from src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.html rename to src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html diff --git a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.scss b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.scss similarity index 100% rename from src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.scss rename to src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.scss diff --git a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.spec.ts similarity index 95% rename from src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts rename to src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.spec.ts index 7cac576844..42a57c2ac5 100644 --- a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.spec.ts +++ b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.spec.ts @@ -17,16 +17,16 @@ import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { PageInfo } from '../../../core/shared/page-info.model'; import { ItemMockPid10, - notificationsBrokerEventObjectMissingProjectFound, + qualityAssuranceEventObjectMissingProjectFound, NotificationsMockDspaceObject } from '../../../shared/mocks/notifications.mock'; const eventData = { - event: notificationsBrokerEventObjectMissingProjectFound, - id: notificationsBrokerEventObjectMissingProjectFound.id, - title: notificationsBrokerEventObjectMissingProjectFound.title, + event: qualityAssuranceEventObjectMissingProjectFound, + id: qualityAssuranceEventObjectMissingProjectFound.id, + title: qualityAssuranceEventObjectMissingProjectFound.title, hasProject: true, - projectTitle: notificationsBrokerEventObjectMissingProjectFound.message.title, + projectTitle: qualityAssuranceEventObjectMissingProjectFound.message.title, projectId: ItemMockPid10.id, handle: ItemMockPid10.handle, reason: null, diff --git a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts similarity index 94% rename from src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts rename to src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts index 64672fa1fa..64a5f6908f 100644 --- a/src/app/notifications/broker/project-entry-import-modal/project-entry-import-modal.component.ts +++ b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts @@ -13,10 +13,10 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SearchService } from '../../../core/shared/search/search.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { - NotificationsBrokerEventObject, - NotificationsBrokerEventMessageObject, + QualityAssuranceEventObject, + QualityAssuranceEventMessageObject, OpenaireBrokerEventMessageObject, -} from '../../../core/notifications/broker/models/notifications-broker-event.model'; +} from '../../../core/notifications/qa/models/quality-assurance-event.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { Item } from '../../../core/shared/item.model'; @@ -34,13 +34,13 @@ export enum ImportType { /** * The data type passed from the parent page */ -export interface NotificationsBrokerEventData { +export interface QualityAssuranceEventData { /** - * The Notifications Broker event + * The Quality Assurance event */ - event: NotificationsBrokerEventObject; + event: QualityAssuranceEventObject; /** - * The Notifications Broker event Id (uuid) + * The Quality Assurance event Id (uuid) */ id: string; /** @@ -83,14 +83,14 @@ export interface NotificationsBrokerEventData { templateUrl: './project-entry-import-modal.component.html' }) /** - * Component to display a modal window for linking a project to an Notifications Broker event + * Component to display a modal window for linking a project to an Quality Assurance event * Shows information about the selected project and a selectable list. */ export class ProjectEntryImportModalComponent implements OnInit { /** * The external source entry */ - @Input() externalSourceEntry: NotificationsBrokerEventData; + @Input() externalSourceEntry: QualityAssuranceEventData; /** * The number of results per page */ diff --git a/src/app/notifications/broker/source/notifications-broker-source.actions.ts b/src/app/notifications/qa/source/quality-assurance-source.actions.ts similarity index 62% rename from src/app/notifications/broker/source/notifications-broker-source.actions.ts rename to src/app/notifications/qa/source/quality-assurance-source.actions.ts index a3fd9240c8..7a22e7a9ae 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.actions.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.actions.ts @@ -1,6 +1,6 @@ import { Action } from '@ngrx/store'; import { type } from '../../../shared/ngrx/type'; -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; /** * For each action type in an action group, make a simple @@ -10,19 +10,19 @@ import { NotificationsBrokerSourceObject } from '../../../core/notifications/bro * literal types and runs a simple check to guarantee all * action types in the application are unique. */ -export const NotificationsBrokerSourceActionTypes = { - ADD_SOURCE: type('dspace/integration/notifications/broker/ADD_SOURCE'), - RETRIEVE_ALL_SOURCE: type('dspace/integration/notifications/broker/RETRIEVE_ALL_SOURCE'), - RETRIEVE_ALL_SOURCE_ERROR: type('dspace/integration/notifications/broker/RETRIEVE_ALL_SOURCE_ERROR'), +export const QualityAssuranceSourceActionTypes = { + ADD_SOURCE: type('dspace/integration/notifications/qa/ADD_SOURCE'), + RETRIEVE_ALL_SOURCE: type('dspace/integration/notifications/qa/RETRIEVE_ALL_SOURCE'), + RETRIEVE_ALL_SOURCE_ERROR: type('dspace/integration/notifications/qa/RETRIEVE_ALL_SOURCE_ERROR'), }; /* tslint:disable:max-classes-per-file */ /** - * An ngrx action to retrieve all the Notifications Broker source. + * An ngrx action to retrieve all the Quality Assurance source. */ export class RetrieveAllSourceAction implements Action { - type = NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE; + type = QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE; payload: { elementsPerPage: number; currentPage: number; @@ -45,20 +45,20 @@ export class RetrieveAllSourceAction implements Action { } /** - * An ngrx action for retrieving 'all Notifications Broker source' error. + * An ngrx action for retrieving 'all Quality Assurance source' error. */ export class RetrieveAllSourceErrorAction implements Action { - type = NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR; + type = QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR; } /** - * An ngrx action to load the Notifications Broker source objects. + * An ngrx action to load the Quality Assurance source objects. * Called by the ??? effect. */ export class AddSourceAction implements Action { - type = NotificationsBrokerSourceActionTypes.ADD_SOURCE; + type = QualityAssuranceSourceActionTypes.ADD_SOURCE; payload: { - source: NotificationsBrokerSourceObject[]; + source: QualityAssuranceSourceObject[]; totalPages: number; currentPage: number; totalElements: number; @@ -74,9 +74,9 @@ export class AddSourceAction implements Action { * @param currentPage * the current page * @param totalElements - * the total available Notifications Broker source + * the total available Quality Assurance source */ - constructor(source: NotificationsBrokerSourceObject[], totalPages: number, currentPage: number, totalElements: number) { + constructor(source: QualityAssuranceSourceObject[], totalPages: number, currentPage: number, totalElements: number) { this.payload = { source, totalPages, @@ -93,7 +93,7 @@ export class AddSourceAction implements Action { * Export a type alias of all actions in this action group * so that reducers can easily compose action types. */ -export type NotificationsBrokerSourceActions +export type QualityAssuranceSourceActions = RetrieveAllSourceAction |RetrieveAllSourceErrorAction |AddSourceAction; diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.html b/src/app/notifications/qa/source/quality-assurance-source.component.html similarity index 97% rename from src/app/notifications/broker/source/notifications-broker-source.component.html rename to src/app/notifications/qa/source/quality-assurance-source.component.html index a7e1e52748..5309098c55 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.component.html +++ b/src/app/notifications/qa/source/quality-assurance-source.component.html @@ -8,15 +8,15 @@

{{'notifications.broker.source'| translate}}

- + - + (paginationChange)="getQualityAssuranceSource()"> +
- + diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.scss b/src/app/notifications/qa/source/quality-assurance-source.component.scss similarity index 100% rename from src/app/notifications/broker/source/notifications-broker-source.component.scss rename to src/app/notifications/qa/source/quality-assurance-source.component.scss diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts b/src/app/notifications/qa/source/quality-assurance-source.component.spec.ts similarity index 60% rename from src/app/notifications/broker/source/notifications-broker-source.component.spec.ts rename to src/app/notifications/qa/source/quality-assurance-source.component.spec.ts index 6c0ad42ce8..ba3a903cc5 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.component.spec.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.component.spec.ts @@ -7,22 +7,22 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/t import { createTestComponent } from '../../../shared/testing/utils.test'; import { getMockNotificationsStateService, - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMorePid + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMorePid } from '../../../shared/mocks/notifications.mock'; -import { NotificationsBrokerSourceComponent } from './notifications-broker-source.component'; +import { QualityAssuranceSourceComponent } from './quality-assurance-source.component'; import { NotificationsStateService } from '../../notifications-state.service'; import { cold } from 'jasmine-marbles'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; -describe('NotificationsBrokerSourceComponent test suite', () => { - let fixture: ComponentFixture; - let comp: NotificationsBrokerSourceComponent; +describe('QualityAssuranceSourceComponent test suite', () => { + let fixture: ComponentFixture; + let comp: QualityAssuranceSourceComponent; let compAsAny: any; const mockNotificationsStateService = getMockNotificationsStateService(); const activatedRouteParams = { - notificationsBrokerSourceParams: { + qualityAssuranceSourceParams: { currentPage: 0, pageSize: 5 } @@ -36,27 +36,27 @@ describe('NotificationsBrokerSourceComponent test suite', () => { TranslateModule.forRoot(), ], declarations: [ - NotificationsBrokerSourceComponent, + QualityAssuranceSourceComponent, TestComponent, ], providers: [ { provide: NotificationsStateService, useValue: mockNotificationsStateService }, { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), params: observableOf({}) } }, { provide: PaginationService, useValue: paginationService }, - NotificationsBrokerSourceComponent + QualityAssuranceSourceComponent ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(() => { - mockNotificationsStateService.getNotificationsBrokerSource.and.returnValue(observableOf([ - notificationsBrokerSourceObjectMorePid, - notificationsBrokerSourceObjectMoreAbstract + mockNotificationsStateService.getQualityAssuranceSource.and.returnValue(observableOf([ + qualityAssuranceSourceObjectMorePid, + qualityAssuranceSourceObjectMoreAbstract ])); - mockNotificationsStateService.getNotificationsBrokerSourceTotalPages.and.returnValue(observableOf(1)); - mockNotificationsStateService.getNotificationsBrokerSourceCurrentPage.and.returnValue(observableOf(0)); - mockNotificationsStateService.getNotificationsBrokerSourceTotals.and.returnValue(observableOf(2)); - mockNotificationsStateService.isNotificationsBrokerSourceLoaded.and.returnValue(observableOf(true)); - mockNotificationsStateService.isNotificationsBrokerSourceLoading.and.returnValue(observableOf(false)); - mockNotificationsStateService.isNotificationsBrokerSourceProcessing.and.returnValue(observableOf(false)); + mockNotificationsStateService.getQualityAssuranceSourceTotalPages.and.returnValue(observableOf(1)); + mockNotificationsStateService.getQualityAssuranceSourceCurrentPage.and.returnValue(observableOf(0)); + mockNotificationsStateService.getQualityAssuranceSourceTotals.and.returnValue(observableOf(2)); + mockNotificationsStateService.isQualityAssuranceSourceLoaded.and.returnValue(observableOf(true)); + mockNotificationsStateService.isQualityAssuranceSourceLoading.and.returnValue(observableOf(false)); + mockNotificationsStateService.isQualityAssuranceSourceProcessing.and.returnValue(observableOf(false)); }); })); @@ -68,7 +68,7 @@ describe('NotificationsBrokerSourceComponent test suite', () => { // synchronous beforeEach beforeEach(() => { const html = ` - `; + `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); @@ -77,14 +77,14 @@ describe('NotificationsBrokerSourceComponent test suite', () => { testFixture.destroy(); }); - it('should create NotificationsBrokerSourceComponent', inject([NotificationsBrokerSourceComponent], (app: NotificationsBrokerSourceComponent) => { + it('should create QualityAssuranceSourceComponent', inject([QualityAssuranceSourceComponent], (app: QualityAssuranceSourceComponent) => { expect(app).toBeDefined(); })); }); describe('Main tests running with two Source', () => { beforeEach(() => { - fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); + fixture = TestBed.createComponent(QualityAssuranceSourceComponent); comp = fixture.componentInstance; compAsAny = comp; @@ -102,8 +102,8 @@ describe('NotificationsBrokerSourceComponent test suite', () => { expect(comp.sources$).toBeObservable(cold('(a|)', { a: [ - notificationsBrokerSourceObjectMorePid, - notificationsBrokerSourceObjectMoreAbstract + qualityAssuranceSourceObjectMorePid, + qualityAssuranceSourceObjectMoreAbstract ] })); expect(comp.totalElements$).toBeObservable(cold('(a|)', { @@ -112,12 +112,12 @@ describe('NotificationsBrokerSourceComponent test suite', () => { }); it(('Should set data properly after the view init'), () => { - spyOn(compAsAny, 'getNotificationsBrokerSource'); + spyOn(compAsAny, 'getQualityAssuranceSource'); comp.ngAfterViewInit(); fixture.detectChanges(); - expect(compAsAny.getNotificationsBrokerSource).toHaveBeenCalled(); + expect(compAsAny.getQualityAssuranceSource).toHaveBeenCalled(); }); it(('isSourceLoading should return FALSE'), () => { @@ -132,12 +132,12 @@ describe('NotificationsBrokerSourceComponent test suite', () => { })); }); - it(('getNotificationsBrokerSource should call the service to dispatch a STATE change'), () => { + it(('getQualityAssuranceSource should call the service to dispatch a STATE change'), () => { comp.ngOnInit(); fixture.detectChanges(); - compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerSource(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); - expect(compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerSource).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); + compAsAny.notificationsStateService.dispatchRetrieveQualityAssuranceSource(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); + expect(compAsAny.notificationsStateService.dispatchRetrieveQualityAssuranceSource).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); }); }); }); diff --git a/src/app/notifications/broker/source/notifications-broker-source.component.ts b/src/app/notifications/qa/source/quality-assurance-source.component.ts similarity index 64% rename from src/app/notifications/broker/source/notifications-broker-source.component.ts rename to src/app/notifications/qa/source/quality-assurance-source.component.ts index 070e03f396..fde1afec43 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.component.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.component.ts @@ -3,18 +3,18 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { NotificationsStateService } from '../../notifications-state.service'; -import { AdminNotificationsBrokerSourcePageParams } from '../../../admin/admin-notifications/admin-notifications-broker-source-page-component/admin-notifications-broker-source-page-resolver.service'; +import { AdminQualityAssuranceSourcePageParams } from '../../../admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service'; import { hasValue } from '../../../shared/empty.util'; @Component({ - selector: 'ds-notifications-broker-source', - templateUrl: './notifications-broker-source.component.html', - styleUrls: ['./notifications-broker-source.component.scss'] + selector: 'ds-quality-assurance-source', + templateUrl: './quality-assurance-source.component.html', + styleUrls: ['./quality-assurance-source.component.scss'] }) -export class NotificationsBrokerSourceComponent implements OnInit { +export class QualityAssuranceSourceComponent implements OnInit { /** * The pagination system configuration for HTML listing. @@ -26,16 +26,16 @@ export class NotificationsBrokerSourceComponent implements OnInit { pageSizeOptions: [5, 10, 20, 40, 60] }); /** - * The Notifications Broker source list sort options. + * The Quality Assurance source list sort options. * @type {SortOptions} */ public paginationSortConfig: SortOptions; /** - * The Notifications Broker source list. + * The Quality Assurance source list. */ - public sources$: Observable; + public sources$: Observable; /** - * The total number of Notifications Broker sources. + * The total number of Quality Assurance sources. */ public totalElements$: Observable; /** @@ -58,51 +58,51 @@ export class NotificationsBrokerSourceComponent implements OnInit { * Component initialization. */ ngOnInit(): void { - this.sources$ = this.notificationsStateService.getNotificationsBrokerSource(); - this.totalElements$ = this.notificationsStateService.getNotificationsBrokerSourceTotals(); + this.sources$ = this.notificationsStateService.getQualityAssuranceSource(); + this.totalElements$ = this.notificationsStateService.getQualityAssuranceSourceTotals(); } /** - * First Notifications Broker source loading after view initialization. + * First Quality Assurance source loading after view initialization. */ ngAfterViewInit(): void { this.subs.push( - this.notificationsStateService.isNotificationsBrokerSourceLoaded().pipe( + this.notificationsStateService.isQualityAssuranceSourceLoaded().pipe( take(1) ).subscribe(() => { - this.getNotificationsBrokerSource(); + this.getQualityAssuranceSource(); }) ); } /** - * Returns the information about the loading status of the Notifications Broker source (if it's running or not). + * Returns the information about the loading status of the Quality Assurance source (if it's running or not). * * @return Observable * 'true' if the source are loading, 'false' otherwise. */ public isSourceLoading(): Observable { - return this.notificationsStateService.isNotificationsBrokerSourceLoading(); + return this.notificationsStateService.isQualityAssuranceSourceLoading(); } /** - * Returns the information about the processing status of the Notifications Broker source (if it's running or not). + * Returns the information about the processing status of the Quality Assurance source (if it's running or not). * * @return Observable * 'true' if there are operations running on the source (ex.: a REST call), 'false' otherwise. */ public isSourceProcessing(): Observable { - return this.notificationsStateService.isNotificationsBrokerSourceProcessing(); + return this.notificationsStateService.isQualityAssuranceSourceProcessing(); } /** - * Dispatch the Notifications Broker source retrival. + * Dispatch the Quality Assurance source retrival. */ - public getNotificationsBrokerSource(): void { + public getQualityAssuranceSource(): void { this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( distinctUntilChanged(), ).subscribe((options: PaginationComponentOptions) => { - this.notificationsStateService.dispatchRetrieveNotificationsBrokerSource( + this.notificationsStateService.dispatchRetrieveQualityAssuranceSource( options.pageSize, options.currentPage ); @@ -114,7 +114,7 @@ export class NotificationsBrokerSourceComponent implements OnInit { * * @param eventsRouteParams */ - protected updatePaginationFromRouteParams(eventsRouteParams: AdminNotificationsBrokerSourcePageParams) { + protected updatePaginationFromRouteParams(eventsRouteParams: AdminQualityAssuranceSourcePageParams) { if (eventsRouteParams.currentPage) { this.paginationConfig.currentPage = eventsRouteParams.currentPage; } diff --git a/src/app/notifications/broker/source/notifications-broker-source.effects.ts b/src/app/notifications/qa/source/quality-assurance-source.effects.ts similarity index 59% rename from src/app/notifications/broker/source/notifications-broker-source.effects.ts rename to src/app/notifications/qa/source/quality-assurance-source.effects.ts index bd8b3f00cd..6d8aa275d5 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.effects.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.effects.ts @@ -6,35 +6,35 @@ import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators' import { of as observableOf } from 'rxjs'; import { AddSourceAction, - NotificationsBrokerSourceActionTypes, + QualityAssuranceSourceActionTypes, RetrieveAllSourceAction, RetrieveAllSourceErrorAction, -} from './notifications-broker-source.actions'; +} from './quality-assurance-source.actions'; -import { NotificationsBrokerSourceObject } from '../../../core/notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerSourceService } from './notifications-broker-source.service'; +import { QualityAssuranceSourceService } from './quality-assurance-source.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; +import { QualityAssuranceSourceRestService } from '../../../core/notifications/qa/source/quality-assurance-source-rest.service'; /** - * Provides effect methods for the Notifications Broker source actions. + * Provides effect methods for the Quality Assurance source actions. */ @Injectable() -export class NotificationsBrokerSourceEffects { +export class QualityAssuranceSourceEffects { /** - * Retrieve all Notifications Broker source managing pagination and errors. + * Retrieve all Quality Assurance source managing pagination and errors. */ @Effect() retrieveAllSource$ = this.actions$.pipe( - ofType(NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE), + ofType(QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE), withLatestFrom(this.store$), switchMap(([action, currentState]: [RetrieveAllSourceAction, any]) => { - return this.notificationsBrokerSourceService.getSources( + return this.qualityAssuranceSourceService.getSources( action.payload.elementsPerPage, action.payload.currentPage ).pipe( - map((sources: PaginatedList) => + map((sources: PaginatedList) => new AddSourceAction(sources.page, sources.totalPages, sources.currentPage, sources.totalElements) ), catchError((error: Error) => { @@ -51,7 +51,7 @@ export class NotificationsBrokerSourceEffects { * Show a notification on error. */ @Effect({ dispatch: false }) retrieveAllSourceErrorAction$ = this.actions$.pipe( - ofType(NotificationsBrokerSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR), + ofType(QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR), tap(() => { this.notificationsService.error(null, this.translate.get('notifications.broker.source.error.service.retrieve')); }) @@ -61,9 +61,9 @@ export class NotificationsBrokerSourceEffects { * Clear find all source requests from cache. */ @Effect({ dispatch: false }) addSourceAction$ = this.actions$.pipe( - ofType(NotificationsBrokerSourceActionTypes.ADD_SOURCE), + ofType(QualityAssuranceSourceActionTypes.ADD_SOURCE), tap(() => { - this.notificationsBrokerSourceDataService.clearFindAllSourceRequests(); + this.qualityAssuranceSourceDataService.clearFindAllSourceRequests(); }) ); @@ -73,15 +73,15 @@ export class NotificationsBrokerSourceEffects { * @param {Store} store$ * @param {TranslateService} translate * @param {NotificationsService} notificationsService - * @param {NotificationsBrokerSourceService} notificationsBrokerSourceService - * @param {NotificationsBrokerSourceRestService} notificationsBrokerSourceDataService + * @param {QualityAssuranceSourceService} qualityAssuranceSourceService + * @param {QualityAssuranceSourceRestService} qualityAssuranceSourceDataService */ constructor( private actions$: Actions, private store$: Store, private translate: TranslateService, private notificationsService: NotificationsService, - private notificationsBrokerSourceService: NotificationsBrokerSourceService, - private notificationsBrokerSourceDataService: NotificationsBrokerSourceRestService + private qualityAssuranceSourceService: QualityAssuranceSourceService, + private qualityAssuranceSourceDataService: QualityAssuranceSourceRestService ) { } } diff --git a/src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts b/src/app/notifications/qa/source/quality-assurance-source.reducer.spec.ts similarity index 52% rename from src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts rename to src/app/notifications/qa/source/quality-assurance-source.reducer.spec.ts index 74bc77d3ec..fcb717067d 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.reducer.spec.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.reducer.spec.ts @@ -2,20 +2,20 @@ import { AddSourceAction, RetrieveAllSourceAction, RetrieveAllSourceErrorAction - } from './notifications-broker-source.actions'; - import { notificationsBrokerSourceReducer, NotificationsBrokerSourceState } from './notifications-broker-source.reducer'; + } from './quality-assurance-source.actions'; + import { qualityAssuranceSourceReducer, QualityAssuranceSourceState } from './quality-assurance-source.reducer'; import { - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMorePid + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMorePid } from '../../../shared/mocks/notifications.mock'; - describe('notificationsBrokerSourceReducer test suite', () => { - let notificationsBrokerSourceInitialState: NotificationsBrokerSourceState; + describe('qualityAssuranceSourceReducer test suite', () => { + let qualityAssuranceSourceInitialState: QualityAssuranceSourceState; const elementPerPage = 3; const currentPage = 0; beforeEach(() => { - notificationsBrokerSourceInitialState = { + qualityAssuranceSourceInitialState = { source: [], processing: false, loaded: false, @@ -26,30 +26,30 @@ import { }); it('Action RETRIEVE_ALL_SOURCE should set the State property "processing" to TRUE', () => { - const expectedState = notificationsBrokerSourceInitialState; + const expectedState = qualityAssuranceSourceInitialState; expectedState.processing = true; const action = new RetrieveAllSourceAction(elementPerPage, currentPage); - const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + const newState = qualityAssuranceSourceReducer(qualityAssuranceSourceInitialState, action); expect(newState).toEqual(expectedState); }); it('Action RETRIEVE_ALL_SOURCE_ERROR should change the State to initial State but processing, loaded, and currentPage', () => { - const expectedState = notificationsBrokerSourceInitialState; + const expectedState = qualityAssuranceSourceInitialState; expectedState.processing = false; expectedState.loaded = true; expectedState.currentPage = 0; const action = new RetrieveAllSourceErrorAction(); - const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + const newState = qualityAssuranceSourceReducer(qualityAssuranceSourceInitialState, action); expect(newState).toEqual(expectedState); }); - it('Action ADD_SOURCE should populate the State with Notifications Broker source', () => { + it('Action ADD_SOURCE should populate the State with Quality Assurance source', () => { const expectedState = { - source: [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ], + source: [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ], processing: false, loaded: true, totalPages: 1, @@ -58,10 +58,10 @@ import { }; const action = new AddSourceAction( - [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ], + [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ], 1, 0, 2 ); - const newState = notificationsBrokerSourceReducer(notificationsBrokerSourceInitialState, action); + const newState = qualityAssuranceSourceReducer(qualityAssuranceSourceInitialState, action); expect(newState).toEqual(expectedState); }); diff --git a/src/app/notifications/qa/source/quality-assurance-source.reducer.ts b/src/app/notifications/qa/source/quality-assurance-source.reducer.ts new file mode 100644 index 0000000000..08e26a177a --- /dev/null +++ b/src/app/notifications/qa/source/quality-assurance-source.reducer.ts @@ -0,0 +1,72 @@ +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; +import { QualityAssuranceSourceActionTypes, QualityAssuranceSourceActions } from './quality-assurance-source.actions'; + +/** + * The interface representing the Quality Assurance source state. + */ +export interface QualityAssuranceSourceState { + source: QualityAssuranceSourceObject[]; + processing: boolean; + loaded: boolean; + totalPages: number; + currentPage: number; + totalElements: number; +} + +/** + * Used for the Quality Assurance source state initialization. + */ +const qualityAssuranceSourceInitialState: QualityAssuranceSourceState = { + source: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 +}; + +/** + * The Quality Assurance Source Reducer + * + * @param state + * the current state initialized with qualityAssuranceSourceInitialState + * @param action + * the action to perform on the state + * @return QualityAssuranceSourceState + * the new state + */ +export function qualityAssuranceSourceReducer(state = qualityAssuranceSourceInitialState, action: QualityAssuranceSourceActions): QualityAssuranceSourceState { + switch (action.type) { + case QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE: { + return Object.assign({}, state, { + source: [], + processing: true + }); + } + + case QualityAssuranceSourceActionTypes.ADD_SOURCE: { + return Object.assign({}, state, { + source: action.payload.source, + processing: false, + loaded: true, + totalPages: action.payload.totalPages, + currentPage: state.currentPage, + totalElements: action.payload.totalElements + }); + } + + case QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR: { + return Object.assign({}, state, { + processing: false, + loaded: true, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }); + } + + default: { + return state; + } + } +} diff --git a/src/app/notifications/broker/source/notifications-broker-source.service.spec.ts b/src/app/notifications/qa/source/quality-assurance-source.service.spec.ts similarity index 56% rename from src/app/notifications/broker/source/notifications-broker-source.service.spec.ts rename to src/app/notifications/qa/source/quality-assurance-source.service.spec.ts index e94804cbf6..06f020be1d 100644 --- a/src/app/notifications/broker/source/notifications-broker-source.service.spec.ts +++ b/src/app/notifications/qa/source/quality-assurance-source.service.spec.ts @@ -1,28 +1,28 @@ import { TestBed } from '@angular/core/testing'; import { of as observableOf } from 'rxjs'; -import { NotificationsBrokerSourceService } from './notifications-broker-source.service'; +import { QualityAssuranceSourceService } from './quality-assurance-source.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { FindListOptions } from '../../../core/data/request.models'; import { - getMockNotificationsBrokerSourceRestService, - notificationsBrokerSourceObjectMoreAbstract, - notificationsBrokerSourceObjectMorePid + getMockQualityAssuranceSourceRestService, + qualityAssuranceSourceObjectMoreAbstract, + qualityAssuranceSourceObjectMorePid } from '../../../shared/mocks/notifications.mock'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerSourceRestService } from '../../../core/notifications/broker/source/notifications-broker-source-rest.service'; +import { QualityAssuranceSourceRestService } from '../../../core/notifications/qa/source/quality-assurance-source-rest.service'; import { RequestParam } from '../../../core/cache/models/request-param.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; -describe('NotificationsBrokerSourceService', () => { - let service: NotificationsBrokerSourceService; - let restService: NotificationsBrokerSourceRestService; +describe('QualityAssuranceSourceService', () => { + let service: QualityAssuranceSourceService; + let restService: QualityAssuranceSourceRestService; let serviceAsAny: any; let restServiceAsAny: any; const pageInfo = new PageInfo(); - const array = [ notificationsBrokerSourceObjectMorePid, notificationsBrokerSourceObjectMoreAbstract ]; + const array = [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); const elementsPerPage = 3; @@ -31,22 +31,22 @@ describe('NotificationsBrokerSourceService', () => { beforeEach(async () => { TestBed.configureTestingModule({ providers: [ - { provide: NotificationsBrokerSourceRestService, useClass: getMockNotificationsBrokerSourceRestService }, - { provide: NotificationsBrokerSourceService, useValue: service } + { provide: QualityAssuranceSourceRestService, useClass: getMockQualityAssuranceSourceRestService }, + { provide: QualityAssuranceSourceService, useValue: service } ] }).compileComponents(); }); beforeEach(() => { - restService = TestBed.get(NotificationsBrokerSourceRestService); + restService = TestBed.get(QualityAssuranceSourceRestService); restServiceAsAny = restService; restServiceAsAny.getSources.and.returnValue(observableOf(paginatedListRD)); - service = new NotificationsBrokerSourceService(restService); + service = new QualityAssuranceSourceService(restService); serviceAsAny = service; }); describe('getSources', () => { - it('Should proxy the call to notificationsBrokerSourceRestService.getSources', () => { + it('Should proxy the call to qualityAssuranceSourceRestService.getSources', () => { const sortOptions = new SortOptions('name', SortDirection.ASC); const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, @@ -54,10 +54,10 @@ describe('NotificationsBrokerSourceService', () => { sort: sortOptions }; const result = service.getSources(elementsPerPage, currentPage); - expect((service as any).notificationsBrokerSourceRestService.getSources).toHaveBeenCalledWith(findListOptions); + expect((service as any).qualityAssuranceSourceRestService.getSources).toHaveBeenCalledWith(findListOptions); }); - it('Should return a paginated list of Notifications Broker Source', () => { + it('Should return a paginated list of Quality Assurance Source', () => { const expected = cold('(a|)', { a: paginatedList }); diff --git a/src/app/notifications/qa/source/quality-assurance-source.service.ts b/src/app/notifications/qa/source/quality-assurance-source.service.ts new file mode 100644 index 0000000000..30a889d3e2 --- /dev/null +++ b/src/app/notifications/qa/source/quality-assurance-source.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { find, map } from 'rxjs/operators'; +import { QualityAssuranceSourceRestService } from '../../../core/notifications/qa/source/quality-assurance-source-rest.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; + +/** + * The service handling all Quality Assurance source requests to the REST service. + */ +@Injectable() +export class QualityAssuranceSourceService { + + /** + * Initialize the service variables. + * @param {QualityAssuranceSourceRestService} qualityAssuranceSourceRestService + */ + constructor( + private qualityAssuranceSourceRestService: QualityAssuranceSourceRestService + ) { } + + /** + * Return the list of Quality Assurance source managing pagination and errors. + * + * @param elementsPerPage + * The number of the source per page + * @param currentPage + * The page number to retrieve + * @return Observable> + * The list of Quality Assurance source. + */ + public getSources(elementsPerPage, currentPage): Observable> { + const sortOptions = new SortOptions('name', SortDirection.ASC); + + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + + return this.qualityAssuranceSourceRestService.getSources(findListOptions).pipe( + find((rd: RemoteData>) => !rd.isResponsePending), + map((rd: RemoteData>) => { + if (rd.hasSucceeded) { + return rd.payload; + } else { + throw new Error('Can\'t retrieve Quality Assurance source from the Broker source REST service'); + } + }) + ); + } +} diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.actions.ts b/src/app/notifications/qa/topics/quality-assurance-topics.actions.ts similarity index 62% rename from src/app/notifications/broker/topics/notifications-broker-topics.actions.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.actions.ts index 622ecc8141..0506806587 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.actions.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.actions.ts @@ -1,6 +1,6 @@ import { Action } from '@ngrx/store'; import { type } from '../../../shared/ngrx/type'; -import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; +import { QualityAssuranceTopicObject } from '../../../core/notifications/qa/models/quality-assurance-topic.model'; /** * For each action type in an action group, make a simple @@ -10,19 +10,19 @@ import { NotificationsBrokerTopicObject } from '../../../core/notifications/brok * literal types and runs a simple check to guarantee all * action types in the application are unique. */ -export const NotificationsBrokerTopicActionTypes = { - ADD_TOPICS: type('dspace/integration/notifications/broker/topic/ADD_TOPICS'), - RETRIEVE_ALL_TOPICS: type('dspace/integration/notifications/broker/topic/RETRIEVE_ALL_TOPICS'), - RETRIEVE_ALL_TOPICS_ERROR: type('dspace/integration/notifications/broker/topic/RETRIEVE_ALL_TOPICS_ERROR'), +export const QualityAssuranceTopicActionTypes = { + ADD_TOPICS: type('dspace/integration/notifications/qa/topic/ADD_TOPICS'), + RETRIEVE_ALL_TOPICS: type('dspace/integration/notifications/qa/topic/RETRIEVE_ALL_TOPICS'), + RETRIEVE_ALL_TOPICS_ERROR: type('dspace/integration/notifications/qa/topic/RETRIEVE_ALL_TOPICS_ERROR'), }; /* tslint:disable:max-classes-per-file */ /** - * An ngrx action to retrieve all the Notifications Broker topics. + * An ngrx action to retrieve all the Quality Assurance topics. */ export class RetrieveAllTopicsAction implements Action { - type = NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS; + type = QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS; payload: { elementsPerPage: number; currentPage: number; @@ -45,20 +45,20 @@ export class RetrieveAllTopicsAction implements Action { } /** - * An ngrx action for retrieving 'all Notifications Broker topics' error. + * An ngrx action for retrieving 'all Quality Assurance topics' error. */ export class RetrieveAllTopicsErrorAction implements Action { - type = NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR; + type = QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR; } /** - * An ngrx action to load the Notifications Broker topic objects. + * An ngrx action to load the Quality Assurance topic objects. * Called by the ??? effect. */ export class AddTopicsAction implements Action { - type = NotificationsBrokerTopicActionTypes.ADD_TOPICS; + type = QualityAssuranceTopicActionTypes.ADD_TOPICS; payload: { - topics: NotificationsBrokerTopicObject[]; + topics: QualityAssuranceTopicObject[]; totalPages: number; currentPage: number; totalElements: number; @@ -74,9 +74,9 @@ export class AddTopicsAction implements Action { * @param currentPage * the current page * @param totalElements - * the total available Notifications Broker topics + * the total available Quality Assurance topics */ - constructor(topics: NotificationsBrokerTopicObject[], totalPages: number, currentPage: number, totalElements: number) { + constructor(topics: QualityAssuranceTopicObject[], totalPages: number, currentPage: number, totalElements: number) { this.payload = { topics, totalPages, @@ -93,7 +93,7 @@ export class AddTopicsAction implements Action { * Export a type alias of all actions in this action group * so that reducers can easily compose action types. */ -export type NotificationsBrokerTopicsActions +export type QualityAssuranceTopicsActions = AddTopicsAction |RetrieveAllTopicsAction |RetrieveAllTopicsErrorAction; diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.html b/src/app/notifications/qa/topics/quality-assurance-topics.component.html similarity index 97% rename from src/app/notifications/broker/topics/notifications-broker-topics.component.html rename to src/app/notifications/qa/topics/quality-assurance-topics.component.html index 8b27778ee9..b563a355f5 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.html +++ b/src/app/notifications/qa/topics/quality-assurance-topics.component.html @@ -15,7 +15,7 @@ [collectionSize]="(totalElements$ | async)" [hideGear]="false" [hideSortOptions]="true" - (paginationChange)="getNotificationsBrokerTopics()"> + (paginationChange)="getQualityAssuranceTopics()"> diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.scss b/src/app/notifications/qa/topics/quality-assurance-topics.component.scss similarity index 100% rename from src/app/notifications/broker/topics/notifications-broker-topics.component.scss rename to src/app/notifications/qa/topics/quality-assurance-topics.component.scss diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts similarity index 59% rename from src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts index dbb8137321..8e154eca99 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts @@ -7,23 +7,23 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/t import { createTestComponent } from '../../../shared/testing/utils.test'; import { getMockNotificationsStateService, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMorePid + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMorePid } from '../../../shared/mocks/notifications.mock'; -import { NotificationsBrokerTopicsComponent } from './notifications-broker-topics.component'; +import { QualityAssuranceTopicsComponent } from './quality-assurance-topics.component'; import { NotificationsStateService } from '../../notifications-state.service'; import { cold } from 'jasmine-marbles'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; -import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; +import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; -describe('NotificationsBrokerTopicsComponent test suite', () => { - let fixture: ComponentFixture; - let comp: NotificationsBrokerTopicsComponent; +describe('QualityAssuranceTopicsComponent test suite', () => { + let fixture: ComponentFixture; + let comp: QualityAssuranceTopicsComponent; let compAsAny: any; const mockNotificationsStateService = getMockNotificationsStateService(); const activatedRouteParams = { - notificationsBrokerTopicsParams: { + qualityAssuranceTopicsParams: { currentPage: 0, pageSize: 5 } @@ -37,7 +37,7 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { TranslateModule.forRoot(), ], declarations: [ - NotificationsBrokerTopicsComponent, + QualityAssuranceTopicsComponent, TestComponent, ], providers: [ @@ -48,22 +48,22 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { }, }}}, { provide: PaginationService, useValue: paginationService }, - NotificationsBrokerTopicsComponent, + QualityAssuranceTopicsComponent, // tslint:disable-next-line: no-empty - { provide: NotificationsBrokerTopicsService, useValue: { setSourceId: (sourceId: string) => { } }} + { provide: QualityAssuranceTopicsService, useValue: { setSourceId: (sourceId: string) => { } }} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(() => { - mockNotificationsStateService.getNotificationsBrokerTopics.and.returnValue(observableOf([ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract + mockNotificationsStateService.getQualityAssuranceTopics.and.returnValue(observableOf([ + qualityAssuranceTopicObjectMorePid, + qualityAssuranceTopicObjectMoreAbstract ])); - mockNotificationsStateService.getNotificationsBrokerTopicsTotalPages.and.returnValue(observableOf(1)); - mockNotificationsStateService.getNotificationsBrokerTopicsCurrentPage.and.returnValue(observableOf(0)); - mockNotificationsStateService.getNotificationsBrokerTopicsTotals.and.returnValue(observableOf(2)); - mockNotificationsStateService.isNotificationsBrokerTopicsLoaded.and.returnValue(observableOf(true)); - mockNotificationsStateService.isNotificationsBrokerTopicsLoading.and.returnValue(observableOf(false)); - mockNotificationsStateService.isNotificationsBrokerTopicsProcessing.and.returnValue(observableOf(false)); + mockNotificationsStateService.getQualityAssuranceTopicsTotalPages.and.returnValue(observableOf(1)); + mockNotificationsStateService.getQualityAssuranceTopicsCurrentPage.and.returnValue(observableOf(0)); + mockNotificationsStateService.getQualityAssuranceTopicsTotals.and.returnValue(observableOf(2)); + mockNotificationsStateService.isQualityAssuranceTopicsLoaded.and.returnValue(observableOf(true)); + mockNotificationsStateService.isQualityAssuranceTopicsLoading.and.returnValue(observableOf(false)); + mockNotificationsStateService.isQualityAssuranceTopicsProcessing.and.returnValue(observableOf(false)); }); })); @@ -75,7 +75,7 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { // synchronous beforeEach beforeEach(() => { const html = ` - `; + `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); @@ -84,14 +84,14 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { testFixture.destroy(); }); - it('should create NotificationsBrokerTopicsComponent', inject([NotificationsBrokerTopicsComponent], (app: NotificationsBrokerTopicsComponent) => { + it('should create QualityAssuranceTopicsComponent', inject([QualityAssuranceTopicsComponent], (app: QualityAssuranceTopicsComponent) => { expect(app).toBeDefined(); })); }); describe('Main tests running with two topics', () => { beforeEach(() => { - fixture = TestBed.createComponent(NotificationsBrokerTopicsComponent); + fixture = TestBed.createComponent(QualityAssuranceTopicsComponent); comp = fixture.componentInstance; compAsAny = comp; @@ -109,8 +109,8 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { expect(comp.topics$).toBeObservable(cold('(a|)', { a: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract + qualityAssuranceTopicObjectMorePid, + qualityAssuranceTopicObjectMoreAbstract ] })); expect(comp.totalElements$).toBeObservable(cold('(a|)', { @@ -119,12 +119,12 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { }); it(('Should set data properly after the view init'), () => { - spyOn(compAsAny, 'getNotificationsBrokerTopics'); + spyOn(compAsAny, 'getQualityAssuranceTopics'); comp.ngAfterViewInit(); fixture.detectChanges(); - expect(compAsAny.getNotificationsBrokerTopics).toHaveBeenCalled(); + expect(compAsAny.getQualityAssuranceTopics).toHaveBeenCalled(); }); it(('isTopicsLoading should return FALSE'), () => { @@ -139,12 +139,12 @@ describe('NotificationsBrokerTopicsComponent test suite', () => { })); }); - it(('getNotificationsBrokerTopics should call the service to dispatch a STATE change'), () => { + it(('getQualityAssuranceTopics should call the service to dispatch a STATE change'), () => { comp.ngOnInit(); fixture.detectChanges(); - compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerTopics(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); - expect(compAsAny.notificationsStateService.dispatchRetrieveNotificationsBrokerTopics).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); + compAsAny.notificationsStateService.dispatchRetrieveQualityAssuranceTopics(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage).and.callThrough(); + expect(compAsAny.notificationsStateService.dispatchRetrieveQualityAssuranceTopics).toHaveBeenCalledWith(comp.paginationConfig.pageSize, comp.paginationConfig.currentPage); }); }); }); diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts b/src/app/notifications/qa/topics/quality-assurance-topics.component.ts similarity index 63% rename from src/app/notifications/broker/topics/notifications-broker-topics.component.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.component.ts index a740ca5c1e..f825358f3b 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.component.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.component.ts @@ -4,24 +4,24 @@ import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, map, take } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; -import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; +import { QualityAssuranceTopicObject } from '../../../core/notifications/qa/models/quality-assurance-topic.model'; import { hasValue } from '../../../shared/empty.util'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { NotificationsStateService } from '../../notifications-state.service'; -import { AdminNotificationsBrokerTopicsPageParams } from '../../../admin/admin-notifications/admin-notifications-broker-topics-page/admin-notifications-broker-topics-page-resolver.service'; +import { AdminQualityAssuranceTopicsPageParams } from '../../../admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { ActivatedRoute } from '@angular/router'; -import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; +import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; /** - * Component to display the Notifications Broker topic list. + * Component to display the Quality Assurance topic list. */ @Component({ - selector: 'ds-notifications-broker-topic', - templateUrl: './notifications-broker-topics.component.html', - styleUrls: ['./notifications-broker-topics.component.scss'], + selector: 'ds-quality-assurance-topic', + templateUrl: './quality-assurance-topics.component.html', + styleUrls: ['./quality-assurance-topics.component.scss'], }) -export class NotificationsBrokerTopicsComponent implements OnInit { +export class QualityAssuranceTopicsComponent implements OnInit { /** * The pagination system configuration for HTML listing. * @type {PaginationComponentOptions} @@ -32,16 +32,16 @@ export class NotificationsBrokerTopicsComponent implements OnInit { pageSizeOptions: [5, 10, 20, 40, 60] }); /** - * The Notifications Broker topic list sort options. + * The Quality Assurance topic list sort options. * @type {SortOptions} */ public paginationSortConfig: SortOptions; /** - * The Notifications Broker topic list. + * The Quality Assurance topic list. */ - public topics$: Observable; + public topics$: Observable; /** - * The total number of Notifications Broker topics. + * The total number of Quality Assurance topics. */ public totalElements$: Observable; /** @@ -65,7 +65,7 @@ export class NotificationsBrokerTopicsComponent implements OnInit { private paginationService: PaginationService, private activatedRoute: ActivatedRoute, private notificationsStateService: NotificationsStateService, - private notificationsBrokerTopicsService: NotificationsBrokerTopicsService + private qualityAssuranceTopicsService: QualityAssuranceTopicsService ) { } @@ -74,52 +74,52 @@ export class NotificationsBrokerTopicsComponent implements OnInit { */ ngOnInit(): void { this.sourceId = this.activatedRoute.snapshot.paramMap.get('sourceId'); - this.notificationsBrokerTopicsService.setSourceId(this.sourceId); - this.topics$ = this.notificationsStateService.getNotificationsBrokerTopics(); - this.totalElements$ = this.notificationsStateService.getNotificationsBrokerTopicsTotals(); + this.qualityAssuranceTopicsService.setSourceId(this.sourceId); + this.topics$ = this.notificationsStateService.getQualityAssuranceTopics(); + this.totalElements$ = this.notificationsStateService.getQualityAssuranceTopicsTotals(); } /** - * First Notifications Broker topics loading after view initialization. + * First Quality Assurance topics loading after view initialization. */ ngAfterViewInit(): void { this.subs.push( - this.notificationsStateService.isNotificationsBrokerTopicsLoaded().pipe( + this.notificationsStateService.isQualityAssuranceTopicsLoaded().pipe( take(1) ).subscribe(() => { - this.getNotificationsBrokerTopics(); + this.getQualityAssuranceTopics(); }) ); } /** - * Returns the information about the loading status of the Notifications Broker topics (if it's running or not). + * Returns the information about the loading status of the Quality Assurance topics (if it's running or not). * * @return Observable * 'true' if the topics are loading, 'false' otherwise. */ public isTopicsLoading(): Observable { - return this.notificationsStateService.isNotificationsBrokerTopicsLoading(); + return this.notificationsStateService.isQualityAssuranceTopicsLoading(); } /** - * Returns the information about the processing status of the Notifications Broker topics (if it's running or not). + * Returns the information about the processing status of the Quality Assurance topics (if it's running or not). * * @return Observable * 'true' if there are operations running on the topics (ex.: a REST call), 'false' otherwise. */ public isTopicsProcessing(): Observable { - return this.notificationsStateService.isNotificationsBrokerTopicsProcessing(); + return this.notificationsStateService.isQualityAssuranceTopicsProcessing(); } /** - * Dispatch the Notifications Broker topics retrival. + * Dispatch the Quality Assurance topics retrival. */ - public getNotificationsBrokerTopics(): void { + public getQualityAssuranceTopics(): void { this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( distinctUntilChanged(), ).subscribe((options: PaginationComponentOptions) => { - this.notificationsStateService.dispatchRetrieveNotificationsBrokerTopics( + this.notificationsStateService.dispatchRetrieveQualityAssuranceTopics( options.pageSize, options.currentPage ); @@ -131,7 +131,7 @@ export class NotificationsBrokerTopicsComponent implements OnInit { * * @param eventsRouteParams */ - protected updatePaginationFromRouteParams(eventsRouteParams: AdminNotificationsBrokerTopicsPageParams) { + protected updatePaginationFromRouteParams(eventsRouteParams: AdminQualityAssuranceTopicsPageParams) { if (eventsRouteParams.currentPage) { this.paginationConfig.currentPage = eventsRouteParams.currentPage; } diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.effects.ts b/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts similarity index 59% rename from src/app/notifications/broker/topics/notifications-broker-topics.effects.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.effects.ts index e3e1e16098..14c0dacc23 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.effects.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts @@ -6,35 +6,35 @@ import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators' import { of as observableOf } from 'rxjs'; import { AddTopicsAction, - NotificationsBrokerTopicActionTypes, + QualityAssuranceTopicActionTypes, RetrieveAllTopicsAction, RetrieveAllTopicsErrorAction, -} from './notifications-broker-topics.actions'; +} from './quality-assurance-topics.actions'; -import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; +import { QualityAssuranceTopicObject } from '../../../core/notifications/qa/models/quality-assurance-topic.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; +import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { NotificationsBrokerTopicRestService } from '../../../core/notifications/broker/topics/notifications-broker-topic-rest.service'; +import { QualityAssuranceTopicRestService } from '../../../core/notifications/qa/topics/quality-assurance-topic-rest.service'; /** - * Provides effect methods for the Notifications Broker topics actions. + * Provides effect methods for the Quality Assurance topics actions. */ @Injectable() -export class NotificationsBrokerTopicsEffects { +export class QualityAssuranceTopicsEffects { /** - * Retrieve all Notifications Broker topics managing pagination and errors. + * Retrieve all Quality Assurance topics managing pagination and errors. */ @Effect() retrieveAllTopics$ = this.actions$.pipe( - ofType(NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS), + ofType(QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS), withLatestFrom(this.store$), switchMap(([action, currentState]: [RetrieveAllTopicsAction, any]) => { - return this.notificationsBrokerTopicService.getTopics( + return this.qualityAssuranceTopicService.getTopics( action.payload.elementsPerPage, action.payload.currentPage ).pipe( - map((topics: PaginatedList) => + map((topics: PaginatedList) => new AddTopicsAction(topics.page, topics.totalPages, topics.currentPage, topics.totalElements) ), catchError((error: Error) => { @@ -51,7 +51,7 @@ export class NotificationsBrokerTopicsEffects { * Show a notification on error. */ @Effect({ dispatch: false }) retrieveAllTopicsErrorAction$ = this.actions$.pipe( - ofType(NotificationsBrokerTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR), + ofType(QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR), tap(() => { this.notificationsService.error(null, this.translate.get('notifications.broker.topic.error.service.retrieve')); }) @@ -61,9 +61,9 @@ export class NotificationsBrokerTopicsEffects { * Clear find all topics requests from cache. */ @Effect({ dispatch: false }) addTopicsAction$ = this.actions$.pipe( - ofType(NotificationsBrokerTopicActionTypes.ADD_TOPICS), + ofType(QualityAssuranceTopicActionTypes.ADD_TOPICS), tap(() => { - this.notificationsBrokerTopicDataService.clearFindAllTopicsRequests(); + this.qualityAssuranceTopicDataService.clearFindAllTopicsRequests(); }) ); @@ -73,15 +73,15 @@ export class NotificationsBrokerTopicsEffects { * @param {Store} store$ * @param {TranslateService} translate * @param {NotificationsService} notificationsService - * @param {NotificationsBrokerTopicsService} notificationsBrokerTopicService - * @param {NotificationsBrokerTopicRestService} notificationsBrokerTopicDataService + * @param {QualityAssuranceTopicsService} qualityAssuranceTopicService + * @param {QualityAssuranceTopicRestService} qualityAssuranceTopicDataService */ constructor( private actions$: Actions, private store$: Store, private translate: TranslateService, private notificationsService: NotificationsService, - private notificationsBrokerTopicService: NotificationsBrokerTopicsService, - private notificationsBrokerTopicDataService: NotificationsBrokerTopicRestService + private qualityAssuranceTopicService: QualityAssuranceTopicsService, + private qualityAssuranceTopicDataService: QualityAssuranceTopicRestService ) { } } diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.reducer.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts similarity index 51% rename from src/app/notifications/broker/topics/notifications-broker-topics.reducer.spec.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts index 523fac9550..a1c002d3f2 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.reducer.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts @@ -2,20 +2,20 @@ import { AddTopicsAction, RetrieveAllTopicsAction, RetrieveAllTopicsErrorAction -} from './notifications-broker-topics.actions'; -import { notificationsBrokerTopicsReducer, NotificationsBrokerTopicState } from './notifications-broker-topics.reducer'; +} from './quality-assurance-topics.actions'; +import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState } from './quality-assurance-topics.reducer'; import { - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMorePid + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMorePid } from '../../../shared/mocks/notifications.mock'; -describe('notificationsBrokerTopicsReducer test suite', () => { - let notificationsBrokerTopicInitialState: NotificationsBrokerTopicState; +describe('qualityAssuranceTopicsReducer test suite', () => { + let qualityAssuranceTopicInitialState: QualityAssuranceTopicState; const elementPerPage = 3; const currentPage = 0; beforeEach(() => { - notificationsBrokerTopicInitialState = { + qualityAssuranceTopicInitialState = { topics: [], processing: false, loaded: false, @@ -26,30 +26,30 @@ describe('notificationsBrokerTopicsReducer test suite', () => { }); it('Action RETRIEVE_ALL_TOPICS should set the State property "processing" to TRUE', () => { - const expectedState = notificationsBrokerTopicInitialState; + const expectedState = qualityAssuranceTopicInitialState; expectedState.processing = true; const action = new RetrieveAllTopicsAction(elementPerPage, currentPage); - const newState = notificationsBrokerTopicsReducer(notificationsBrokerTopicInitialState, action); + const newState = qualityAssuranceTopicsReducer(qualityAssuranceTopicInitialState, action); expect(newState).toEqual(expectedState); }); it('Action RETRIEVE_ALL_TOPICS_ERROR should change the State to initial State but processing, loaded, and currentPage', () => { - const expectedState = notificationsBrokerTopicInitialState; + const expectedState = qualityAssuranceTopicInitialState; expectedState.processing = false; expectedState.loaded = true; expectedState.currentPage = 0; const action = new RetrieveAllTopicsErrorAction(); - const newState = notificationsBrokerTopicsReducer(notificationsBrokerTopicInitialState, action); + const newState = qualityAssuranceTopicsReducer(qualityAssuranceTopicInitialState, action); expect(newState).toEqual(expectedState); }); - it('Action ADD_TOPICS should populate the State with Notifications Broker topics', () => { + it('Action ADD_TOPICS should populate the State with Quality Assurance topics', () => { const expectedState = { - topics: [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract ], + topics: [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ], processing: false, loaded: true, totalPages: 1, @@ -58,10 +58,10 @@ describe('notificationsBrokerTopicsReducer test suite', () => { }; const action = new AddTopicsAction( - [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract ], + [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ], 1, 0, 2 ); - const newState = notificationsBrokerTopicsReducer(notificationsBrokerTopicInitialState, action); + const newState = qualityAssuranceTopicsReducer(qualityAssuranceTopicInitialState, action); expect(newState).toEqual(expectedState); }); diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.reducer.ts b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.ts new file mode 100644 index 0000000000..ff94f1b8bb --- /dev/null +++ b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.ts @@ -0,0 +1,72 @@ +import { QualityAssuranceTopicObject } from '../../../core/notifications/qa/models/quality-assurance-topic.model'; +import { QualityAssuranceTopicActionTypes, QualityAssuranceTopicsActions } from './quality-assurance-topics.actions'; + +/** + * The interface representing the Quality Assurance topic state. + */ +export interface QualityAssuranceTopicState { + topics: QualityAssuranceTopicObject[]; + processing: boolean; + loaded: boolean; + totalPages: number; + currentPage: number; + totalElements: number; +} + +/** + * Used for the Quality Assurance topic state initialization. + */ +const qualityAssuranceTopicInitialState: QualityAssuranceTopicState = { + topics: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0 +}; + +/** + * The Quality Assurance Topic Reducer + * + * @param state + * the current state initialized with qualityAssuranceTopicInitialState + * @param action + * the action to perform on the state + * @return QualityAssuranceTopicState + * the new state + */ +export function qualityAssuranceTopicsReducer(state = qualityAssuranceTopicInitialState, action: QualityAssuranceTopicsActions): QualityAssuranceTopicState { + switch (action.type) { + case QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS: { + return Object.assign({}, state, { + topics: [], + processing: true + }); + } + + case QualityAssuranceTopicActionTypes.ADD_TOPICS: { + return Object.assign({}, state, { + topics: action.payload.topics, + processing: false, + loaded: true, + totalPages: action.payload.totalPages, + currentPage: state.currentPage, + totalElements: action.payload.totalElements + }); + } + + case QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR: { + return Object.assign({}, state, { + processing: false, + loaded: true, + totalPages: 0, + currentPage: 0, + totalElements: 0 + }); + } + + default: { + return state; + } + } +} diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts similarity index 58% rename from src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts index e5616df320..6d945446b2 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.service.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts @@ -1,28 +1,28 @@ import { TestBed } from '@angular/core/testing'; import { of as observableOf } from 'rxjs'; -import { NotificationsBrokerTopicsService } from './notifications-broker-topics.service'; +import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { NotificationsBrokerTopicRestService } from '../../../core/notifications/broker/topics/notifications-broker-topic-rest.service'; +import { QualityAssuranceTopicRestService } from '../../../core/notifications/qa/topics/quality-assurance-topic-rest.service'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { FindListOptions } from '../../../core/data/request.models'; import { - getMockNotificationsBrokerTopicRestService, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMorePid + getMockQualityAssuranceTopicRestService, + qualityAssuranceTopicObjectMoreAbstract, + qualityAssuranceTopicObjectMorePid } from '../../../shared/mocks/notifications.mock'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { RequestParam } from '../../../core/cache/models/request-param.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; -describe('NotificationsBrokerTopicsService', () => { - let service: NotificationsBrokerTopicsService; - let restService: NotificationsBrokerTopicRestService; +describe('QualityAssuranceTopicsService', () => { + let service: QualityAssuranceTopicsService; + let restService: QualityAssuranceTopicRestService; let serviceAsAny: any; let restServiceAsAny: any; const pageInfo = new PageInfo(); - const array = [ notificationsBrokerTopicObjectMorePid, notificationsBrokerTopicObjectMoreAbstract ]; + const array = [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); const elementsPerPage = 3; @@ -31,22 +31,22 @@ describe('NotificationsBrokerTopicsService', () => { beforeEach(async () => { TestBed.configureTestingModule({ providers: [ - { provide: NotificationsBrokerTopicRestService, useClass: getMockNotificationsBrokerTopicRestService }, - { provide: NotificationsBrokerTopicsService, useValue: service } + { provide: QualityAssuranceTopicRestService, useClass: getMockQualityAssuranceTopicRestService }, + { provide: QualityAssuranceTopicsService, useValue: service } ] }).compileComponents(); }); beforeEach(() => { - restService = TestBed.get(NotificationsBrokerTopicRestService); + restService = TestBed.get(QualityAssuranceTopicRestService); restServiceAsAny = restService; restServiceAsAny.getTopics.and.returnValue(observableOf(paginatedListRD)); - service = new NotificationsBrokerTopicsService(restService); + service = new QualityAssuranceTopicsService(restService); serviceAsAny = service; }); describe('getTopics', () => { - it('Should proxy the call to notificationsBrokerTopicRestService.getTopics', () => { + it('Should proxy the call to qualityAssuranceTopicRestService.getTopics', () => { const sortOptions = new SortOptions('name', SortDirection.ASC); const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, @@ -56,10 +56,10 @@ describe('NotificationsBrokerTopicsService', () => { }; service.setSourceId('ENRICH!MORE!ABSTRACT'); const result = service.getTopics(elementsPerPage, currentPage); - expect((service as any).notificationsBrokerTopicRestService.getTopics).toHaveBeenCalledWith(findListOptions); + expect((service as any).qualityAssuranceTopicRestService.getTopics).toHaveBeenCalledWith(findListOptions); }); - it('Should return a paginated list of Notifications Broker topics', () => { + it('Should return a paginated list of Quality Assurance topics', () => { const expected = cold('(a|)', { a: paginatedList }); diff --git a/src/app/notifications/broker/topics/notifications-broker-topics.service.ts b/src/app/notifications/qa/topics/quality-assurance-topics.service.ts similarity index 51% rename from src/app/notifications/broker/topics/notifications-broker-topics.service.ts rename to src/app/notifications/qa/topics/quality-assurance-topics.service.ts index 80c52a70a9..c09a0750e0 100644 --- a/src/app/notifications/broker/topics/notifications-broker-topics.service.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.service.ts @@ -1,26 +1,26 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { find, map } from 'rxjs/operators'; -import { NotificationsBrokerTopicRestService } from '../../../core/notifications/broker/topics/notifications-broker-topic-rest.service'; +import { QualityAssuranceTopicRestService } from '../../../core/notifications/qa/topics/quality-assurance-topic-rest.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../core/data/request.models'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { NotificationsBrokerTopicObject } from '../../../core/notifications/broker/models/notifications-broker-topic.model'; +import { QualityAssuranceTopicObject } from '../../../core/notifications/qa/models/quality-assurance-topic.model'; import { RequestParam } from '../../../core/cache/models/request-param.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; /** - * The service handling all Notifications Broker topic requests to the REST service. + * The service handling all Quality Assurance topic requests to the REST service. */ @Injectable() -export class NotificationsBrokerTopicsService { +export class QualityAssuranceTopicsService { /** * Initialize the service variables. - * @param {NotificationsBrokerTopicRestService} notificationsBrokerTopicRestService + * @param {QualityAssuranceTopicRestService} qualityAssuranceTopicRestService */ constructor( - private notificationsBrokerTopicRestService: NotificationsBrokerTopicRestService + private qualityAssuranceTopicRestService: QualityAssuranceTopicRestService ) { } /** @@ -29,16 +29,16 @@ export class NotificationsBrokerTopicsService { sourceId: string; /** - * Return the list of Notifications Broker topics managing pagination and errors. + * Return the list of Quality Assurance topics managing pagination and errors. * * @param elementsPerPage * The number of the topics per page * @param currentPage * The page number to retrieve - * @return Observable> - * The list of Notifications Broker topics. + * @return Observable> + * The list of Quality Assurance topics. */ - public getTopics(elementsPerPage, currentPage): Observable> { + public getTopics(elementsPerPage, currentPage): Observable> { const sortOptions = new SortOptions('name', SortDirection.ASC); const findListOptions: FindListOptions = { @@ -48,13 +48,13 @@ export class NotificationsBrokerTopicsService { searchParams: [new RequestParam('source', this.sourceId)] }; - return this.notificationsBrokerTopicRestService.getTopics(findListOptions).pipe( - find((rd: RemoteData>) => !rd.isResponsePending), - map((rd: RemoteData>) => { + return this.qualityAssuranceTopicRestService.getTopics(findListOptions).pipe( + find((rd: RemoteData>) => !rd.isResponsePending), + map((rd: RemoteData>) => { if (rd.hasSucceeded) { return rd.payload; } else { - throw new Error('Can\'t retrieve Notifications Broker topics from the Broker topics REST service'); + throw new Error('Can\'t retrieve Quality Assurance topics from the Broker topics REST service'); } }) ); diff --git a/src/app/notifications/selectors.ts b/src/app/notifications/selectors.ts index 0436a35eb3..3ab769aa95 100644 --- a/src/app/notifications/selectors.ts +++ b/src/app/notifications/selectors.ts @@ -1,10 +1,10 @@ import { createSelector, MemoizedSelector } from '@ngrx/store'; import { subStateSelector } from '../shared/selector.util'; import { notificationsSelector, NotificationsState } from './notifications.reducer'; -import { NotificationsBrokerTopicObject } from '../core/notifications/broker/models/notifications-broker-topic.model'; -import { NotificationsBrokerTopicState } from './broker/topics/notifications-broker-topics.reducer'; -import { NotificationsBrokerSourceState } from './broker/source/notifications-broker-source.reducer'; -import { NotificationsBrokerSourceObject } from '../core/notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceTopicObject } from '../core/notifications/qa/models/quality-assurance-topic.model'; +import { QualityAssuranceTopicState } from './qa/topics/quality-assurance-topics.reducer'; +import { QualityAssuranceSourceState } from './qa/source/quality-assurance-source.reducer'; +import { QualityAssuranceSourceObject } from '../core/notifications/qa/models/quality-assurance-source.model'; /** * Returns the Notifications state. @@ -14,33 +14,33 @@ import { NotificationsBrokerSourceObject } from '../core/notifications/broker/mo */ const _getNotificationsState = (state: any) => state.notifications; -// Notifications Broker topics +// Quality Assurance topics // ---------------------------------------------------------------------------- /** - * Returns the Notifications Broker topics State. - * @function notificationsBrokerTopicsStateSelector - * @return {NotificationsBrokerTopicState} + * Returns the Quality Assurance topics State. + * @function qualityAssuranceTopicsStateSelector + * @return {QualityAssuranceTopicState} */ -export function notificationsBrokerTopicsStateSelector(): MemoizedSelector { - return subStateSelector(notificationsSelector, 'brokerTopic'); +export function qualityAssuranceTopicsStateSelector(): MemoizedSelector { + return subStateSelector(notificationsSelector, 'brokerTopic'); } /** - * Returns the Notifications Broker topics list. - * @function notificationsBrokerTopicsObjectSelector - * @return {NotificationsBrokerTopicObject[]} + * Returns the Quality Assurance topics list. + * @function qualityAssuranceTopicsObjectSelector + * @return {QualityAssuranceTopicObject[]} */ -export function notificationsBrokerTopicsObjectSelector(): MemoizedSelector { - return subStateSelector(notificationsBrokerTopicsStateSelector(), 'topics'); +export function qualityAssuranceTopicsObjectSelector(): MemoizedSelector { + return subStateSelector(qualityAssuranceTopicsStateSelector(), 'topics'); } /** - * Returns true if the Notifications Broker topics are loaded. - * @function isNotificationsBrokerTopicsLoadedSelector + * Returns true if the Quality Assurance topics are loaded. + * @function isQualityAssuranceTopicsLoadedSelector * @return {boolean} */ -export const isNotificationsBrokerTopicsLoadedSelector = createSelector(_getNotificationsState, +export const isQualityAssuranceTopicsLoadedSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.loaded ); @@ -49,64 +49,64 @@ export const isNotificationsBrokerTopicsLoadedSelector = createSelector(_getNoti * @function isDeduplicationSetsProcessingSelector * @return {boolean} */ -export const isNotificationsBrokerTopicsProcessingSelector = createSelector(_getNotificationsState, +export const isQualityAssuranceTopicsProcessingSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.processing ); /** - * Returns the total available pages of Notifications Broker topics. - * @function getNotificationsBrokerTopicsTotalPagesSelector + * Returns the total available pages of Quality Assurance topics. + * @function getQualityAssuranceTopicsTotalPagesSelector * @return {number} */ -export const getNotificationsBrokerTopicsTotalPagesSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceTopicsTotalPagesSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.totalPages ); /** - * Returns the current page of Notifications Broker topics. - * @function getNotificationsBrokerTopicsCurrentPageSelector + * Returns the current page of Quality Assurance topics. + * @function getQualityAssuranceTopicsCurrentPageSelector * @return {number} */ -export const getNotificationsBrokerTopicsCurrentPageSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceTopicsCurrentPageSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.currentPage ); /** - * Returns the total number of Notifications Broker topics. - * @function getNotificationsBrokerTopicsTotalsSelector + * Returns the total number of Quality Assurance topics. + * @function getQualityAssuranceTopicsTotalsSelector * @return {number} */ -export const getNotificationsBrokerTopicsTotalsSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceTopicsTotalsSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerTopic.totalElements ); -// Notifications Broker source +// Quality Assurance source // ---------------------------------------------------------------------------- /** - * Returns the Notifications Broker source State. - * @function notificationsBrokerSourceStateSelector - * @return {NotificationsBrokerSourceState} + * Returns the Quality Assurance source State. + * @function qualityAssuranceSourceStateSelector + * @return {QualityAssuranceSourceState} */ - export function notificationsBrokerSourceStateSelector(): MemoizedSelector { - return subStateSelector(notificationsSelector, 'brokerSource'); + export function qualityAssuranceSourceStateSelector(): MemoizedSelector { + return subStateSelector(notificationsSelector, 'brokerSource'); } /** - * Returns the Notifications Broker source list. - * @function notificationsBrokerSourceObjectSelector - * @return {NotificationsBrokerSourceObject[]} + * Returns the Quality Assurance source list. + * @function qualityAssuranceSourceObjectSelector + * @return {QualityAssuranceSourceObject[]} */ -export function notificationsBrokerSourceObjectSelector(): MemoizedSelector { - return subStateSelector(notificationsBrokerSourceStateSelector(), 'source'); +export function qualityAssuranceSourceObjectSelector(): MemoizedSelector { + return subStateSelector(qualityAssuranceSourceStateSelector(), 'source'); } /** - * Returns true if the Notifications Broker source are loaded. - * @function isNotificationsBrokerSourceLoadedSelector + * Returns true if the Quality Assurance source are loaded. + * @function isQualityAssuranceSourceLoadedSelector * @return {boolean} */ -export const isNotificationsBrokerSourceLoadedSelector = createSelector(_getNotificationsState, +export const isQualityAssuranceSourceLoadedSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerSource.loaded ); @@ -115,33 +115,33 @@ export const isNotificationsBrokerSourceLoadedSelector = createSelector(_getNoti * @function isDeduplicationSetsProcessingSelector * @return {boolean} */ -export const isNotificationsBrokerSourceProcessingSelector = createSelector(_getNotificationsState, +export const isQualityAssuranceSourceProcessingSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerSource.processing ); /** - * Returns the total available pages of Notifications Broker source. - * @function getNotificationsBrokerSourceTotalPagesSelector + * Returns the total available pages of Quality Assurance source. + * @function getQualityAssuranceSourceTotalPagesSelector * @return {number} */ -export const getNotificationsBrokerSourceTotalPagesSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceSourceTotalPagesSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerSource.totalPages ); /** - * Returns the current page of Notifications Broker source. - * @function getNotificationsBrokerSourceCurrentPageSelector + * Returns the current page of Quality Assurance source. + * @function getQualityAssuranceSourceCurrentPageSelector * @return {number} */ -export const getNotificationsBrokerSourceCurrentPageSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceSourceCurrentPageSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerSource.currentPage ); /** - * Returns the total number of Notifications Broker source. - * @function getNotificationsBrokerSourceTotalsSelector + * Returns the total number of Quality Assurance source. + * @function getQualityAssuranceSourceTotalsSelector * @return {number} */ -export const getNotificationsBrokerSourceTotalsSelector = createSelector(_getNotificationsState, +export const getQualityAssuranceSourceTotalsSelector = createSelector(_getNotificationsState, (state: NotificationsState) => state.brokerSource.totalElements ); diff --git a/src/app/shared/mocks/notifications.mock.ts b/src/app/shared/mocks/notifications.mock.ts index 8af034ea32..845c13a4ce 100644 --- a/src/app/shared/mocks/notifications.mock.ts +++ b/src/app/shared/mocks/notifications.mock.ts @@ -1,9 +1,9 @@ import { of as observableOf } from 'rxjs'; import { ResourceType } from '../../core/shared/resource-type'; -import { NotificationsBrokerTopicObject } from '../../core/notifications/broker/models/notifications-broker-topic.model'; -import { NotificationsBrokerEventObject } from '../../core/notifications/broker/models/notifications-broker-event.model'; -import { NotificationsBrokerTopicRestService } from '../../core/notifications/broker/topics/notifications-broker-topic-rest.service'; -import { NotificationsBrokerEventRestService } from '../../core/notifications/broker/events/notifications-broker-event-rest.service'; +import { QualityAssuranceTopicObject } from '../../core/notifications/qa/models/quality-assurance-topic.model'; +import { QualityAssuranceEventObject } from '../../core/notifications/qa/models/quality-assurance-event.model'; +import { QualityAssuranceTopicRestService } from '../../core/notifications/qa/topics/quality-assurance-topic-rest.service'; +import { QualityAssuranceEventRestService } from '../../core/notifications/qa/events/quality-assurance-event-rest.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { NotificationsStateService } from '../../notifications/notifications-state.service'; import { Item } from '../../core/shared/item.model'; @@ -13,7 +13,7 @@ import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { SearchResult } from '../search/models/search-result.model'; -import { NotificationsBrokerSourceObject } from '../../core/notifications/broker/models/notifications-broker-source.model'; +import { QualityAssuranceSourceObject } from '../../core/notifications/qa/models/quality-assurance-source.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- @@ -1333,7 +1333,7 @@ export const NotificationsMockDspaceObject: SearchResult = Object. // Sources // ------------------------------------------------------------------------------- -export const notificationsBrokerSourceObjectMorePid: NotificationsBrokerSourceObject = { +export const qualityAssuranceSourceObjectMorePid: QualityAssuranceSourceObject = { type: new ResourceType('nbsource'), id: 'ENRICH!MORE!PID', lastEvent: '2020/10/09 10:11 UTC', @@ -1345,7 +1345,7 @@ export const notificationsBrokerSourceObjectMorePid: NotificationsBrokerSourceOb } }; -export const notificationsBrokerSourceObjectMoreAbstract: NotificationsBrokerSourceObject = { +export const qualityAssuranceSourceObjectMoreAbstract: QualityAssuranceSourceObject = { type: new ResourceType('nbsource'), id: 'ENRICH!MORE!ABSTRACT', lastEvent: '2020/09/08 21:14 UTC', @@ -1357,7 +1357,7 @@ export const notificationsBrokerSourceObjectMoreAbstract: NotificationsBrokerSou } }; -export const notificationsBrokerSourceObjectMissingPid: NotificationsBrokerSourceObject = { +export const qualityAssuranceSourceObjectMissingPid: QualityAssuranceSourceObject = { type: new ResourceType('nbsource'), id: 'ENRICH!MISSING!PID', lastEvent: '2020/10/01 07:36 UTC', @@ -1372,7 +1372,7 @@ export const notificationsBrokerSourceObjectMissingPid: NotificationsBrokerSourc // Topics // ------------------------------------------------------------------------------- -export const notificationsBrokerTopicObjectMorePid: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMorePid: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MORE!PID', name: 'ENRICH/MORE/PID', @@ -1385,7 +1385,7 @@ export const notificationsBrokerTopicObjectMorePid: NotificationsBrokerTopicObje } }; -export const notificationsBrokerTopicObjectMoreAbstract: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMoreAbstract: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MORE!ABSTRACT', name: 'ENRICH/MORE/ABSTRACT', @@ -1398,7 +1398,7 @@ export const notificationsBrokerTopicObjectMoreAbstract: NotificationsBrokerTopi } }; -export const notificationsBrokerTopicObjectMissingPid: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMissingPid: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MISSING!PID', name: 'ENRICH/MISSING/PID', @@ -1411,7 +1411,7 @@ export const notificationsBrokerTopicObjectMissingPid: NotificationsBrokerTopicO } }; -export const notificationsBrokerTopicObjectMissingAbstract: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMissingAbstract: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MISSING!ABSTRACT', name: 'ENRICH/MISSING/ABSTRACT', @@ -1424,7 +1424,7 @@ export const notificationsBrokerTopicObjectMissingAbstract: NotificationsBrokerT } }; -export const notificationsBrokerTopicObjectMissingAcm: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMissingAcm: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MISSING!SUBJECT!ACM', name: 'ENRICH/MISSING/SUBJECT/ACM', @@ -1437,7 +1437,7 @@ export const notificationsBrokerTopicObjectMissingAcm: NotificationsBrokerTopicO } }; -export const notificationsBrokerTopicObjectMissingProject: NotificationsBrokerTopicObject = { +export const qualityAssuranceTopicObjectMissingProject: QualityAssuranceTopicObject = { type: new ResourceType('nbtopic'), id: 'ENRICH!MISSING!PROJECT', name: 'ENRICH/MISSING/PROJECT', @@ -1453,7 +1453,7 @@ export const notificationsBrokerTopicObjectMissingProject: NotificationsBrokerTo // Events // ------------------------------------------------------------------------------- -export const notificationsBrokerEventObjectMissingPid: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174001', uuid: '123e4567-e89b-12d3-a456-426614174001', type: new ResourceType('nbevent'), @@ -1489,10 +1489,10 @@ export const notificationsBrokerEventObjectMissingPid: NotificationsBrokerEventO related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingPid2: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid2: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174004', uuid: '123e4567-e89b-12d3-a456-426614174004', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/21486', title: 'UNA NUOVA RILETTURA DELL\u0027 ARISTOTELE DI FRANZ BRENTANO ALLA LUCE DI ALCUNI INEDITI', trust: 1.0, @@ -1525,10 +1525,10 @@ export const notificationsBrokerEventObjectMissingPid2: NotificationsBrokerEvent related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingPid3: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid3: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174005', uuid: '123e4567-e89b-12d3-a456-426614174005', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/554', title: 'Sustainable development', trust: 0.375, @@ -1561,10 +1561,10 @@ export const notificationsBrokerEventObjectMissingPid3: NotificationsBrokerEvent related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingPid4: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid4: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174006', uuid: '123e4567-e89b-12d3-a456-426614174006', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/10787', title: 'Reply to Critics', trust: 1.0, @@ -1597,10 +1597,10 @@ export const notificationsBrokerEventObjectMissingPid4: NotificationsBrokerEvent related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingPid5: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid5: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174007', uuid: '123e4567-e89b-12d3-a456-426614174007', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/11339', title: 'PROGETTAZIONE, SINTESI E VALUTAZIONE DELL\u0027ATTIVITA\u0027 ANTIMICOBATTERICA ED ANTIFUNGINA DI NUOVI DERIVATI ETEROCICLICI', trust: 0.375, @@ -1633,10 +1633,10 @@ export const notificationsBrokerEventObjectMissingPid5: NotificationsBrokerEvent related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingPid6: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingPid6: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174008', uuid: '123e4567-e89b-12d3-a456-426614174008', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/29860', title: 'Donald Davidson', trust: 0.375, @@ -1669,10 +1669,10 @@ export const notificationsBrokerEventObjectMissingPid6: NotificationsBrokerEvent related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingAbstract: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingAbstract: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174009', uuid: '123e4567-e89b-12d3-a456-426614174009', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/21110', title: 'Missing abstract article', trust: 0.751, @@ -1705,10 +1705,10 @@ export const notificationsBrokerEventObjectMissingAbstract: NotificationsBrokerE related: observableOf(createSuccessfulRemoteDataObject(ItemMockPid10)) }; -export const notificationsBrokerEventObjectMissingProjectFound: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingProjectFound: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174002', uuid: '123e4567-e89b-12d3-a456-426614174002', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/21838', title: 'Egypt, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature', trust: 1.0, @@ -1741,10 +1741,10 @@ export const notificationsBrokerEventObjectMissingProjectFound: NotificationsBro related: createSuccessfulRemoteDataObject$(ItemMockPid10) }; -export const notificationsBrokerEventObjectMissingProjectNotFound: NotificationsBrokerEventObject = { +export const qualityAssuranceEventObjectMissingProjectNotFound: QualityAssuranceEventObject = { id: '123e4567-e89b-12d3-a456-426614174003', uuid: '123e4567-e89b-12d3-a456-426614174003', - type: new ResourceType('notificationsBrokerEvent'), + type: new ResourceType('qualityAssuranceEvent'), originalId: 'oai:www.openstarts.units.it:10077/21838', title: 'Morocco, crossroad of translations and literary interweavings (3rd-6th centuries). A reconsideration of earlier Coptic literature', trust: 1.0, @@ -1785,51 +1785,51 @@ export const notificationsBrokerEventObjectMissingProjectNotFound: Notifications */ export function getMockNotificationsStateService(): any { return jasmine.createSpyObj('NotificationsStateService', { - getNotificationsBrokerTopics: jasmine.createSpy('getNotificationsBrokerTopics'), - isNotificationsBrokerTopicsLoading: jasmine.createSpy('isNotificationsBrokerTopicsLoading'), - isNotificationsBrokerTopicsLoaded: jasmine.createSpy('isNotificationsBrokerTopicsLoaded'), - isNotificationsBrokerTopicsProcessing: jasmine.createSpy('isNotificationsBrokerTopicsProcessing'), - getNotificationsBrokerTopicsTotalPages: jasmine.createSpy('getNotificationsBrokerTopicsTotalPages'), - getNotificationsBrokerTopicsCurrentPage: jasmine.createSpy('getNotificationsBrokerTopicsCurrentPage'), - getNotificationsBrokerTopicsTotals: jasmine.createSpy('getNotificationsBrokerTopicsTotals'), - dispatchRetrieveNotificationsBrokerTopics: jasmine.createSpy('dispatchRetrieveNotificationsBrokerTopics'), - getNotificationsBrokerSource: jasmine.createSpy('getNotificationsBrokerSource'), - isNotificationsBrokerSourceLoading: jasmine.createSpy('isNotificationsBrokerSourceLoading'), - isNotificationsBrokerSourceLoaded: jasmine.createSpy('isNotificationsBrokerSourceLoaded'), - isNotificationsBrokerSourceProcessing: jasmine.createSpy('isNotificationsBrokerSourceProcessing'), - getNotificationsBrokerSourceTotalPages: jasmine.createSpy('getNotificationsBrokerSourceTotalPages'), - getNotificationsBrokerSourceCurrentPage: jasmine.createSpy('getNotificationsBrokerSourceCurrentPage'), - getNotificationsBrokerSourceTotals: jasmine.createSpy('getNotificationsBrokerSourceTotals'), - dispatchRetrieveNotificationsBrokerSource: jasmine.createSpy('dispatchRetrieveNotificationsBrokerSource'), + getQualityAssuranceTopics: jasmine.createSpy('getQualityAssuranceTopics'), + isQualityAssuranceTopicsLoading: jasmine.createSpy('isQualityAssuranceTopicsLoading'), + isQualityAssuranceTopicsLoaded: jasmine.createSpy('isQualityAssuranceTopicsLoaded'), + isQualityAssuranceTopicsProcessing: jasmine.createSpy('isQualityAssuranceTopicsProcessing'), + getQualityAssuranceTopicsTotalPages: jasmine.createSpy('getQualityAssuranceTopicsTotalPages'), + getQualityAssuranceTopicsCurrentPage: jasmine.createSpy('getQualityAssuranceTopicsCurrentPage'), + getQualityAssuranceTopicsTotals: jasmine.createSpy('getQualityAssuranceTopicsTotals'), + dispatchRetrieveQualityAssuranceTopics: jasmine.createSpy('dispatchRetrieveQualityAssuranceTopics'), + getQualityAssuranceSource: jasmine.createSpy('getQualityAssuranceSource'), + isQualityAssuranceSourceLoading: jasmine.createSpy('isQualityAssuranceSourceLoading'), + isQualityAssuranceSourceLoaded: jasmine.createSpy('isQualityAssuranceSourceLoaded'), + isQualityAssuranceSourceProcessing: jasmine.createSpy('isQualityAssuranceSourceProcessing'), + getQualityAssuranceSourceTotalPages: jasmine.createSpy('getQualityAssuranceSourceTotalPages'), + getQualityAssuranceSourceCurrentPage: jasmine.createSpy('getQualityAssuranceSourceCurrentPage'), + getQualityAssuranceSourceTotals: jasmine.createSpy('getQualityAssuranceSourceTotals'), + dispatchRetrieveQualityAssuranceSource: jasmine.createSpy('dispatchRetrieveQualityAssuranceSource'), dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') }); } /** - * Mock for [[NotificationsBrokerSourceRestService]] + * Mock for [[QualityAssuranceSourceRestService]] */ - export function getMockNotificationsBrokerSourceRestService(): NotificationsBrokerTopicRestService { - return jasmine.createSpyObj('NotificationsBrokerSourceRestService', { + export function getMockQualityAssuranceSourceRestService(): QualityAssuranceTopicRestService { + return jasmine.createSpyObj('QualityAssuranceSourceRestService', { getSources: jasmine.createSpy('getSources'), getSource: jasmine.createSpy('getSource'), }); } /** - * Mock for [[NotificationsBrokerTopicRestService]] + * Mock for [[QualityAssuranceTopicRestService]] */ -export function getMockNotificationsBrokerTopicRestService(): NotificationsBrokerTopicRestService { - return jasmine.createSpyObj('NotificationsBrokerTopicRestService', { +export function getMockQualityAssuranceTopicRestService(): QualityAssuranceTopicRestService { + return jasmine.createSpyObj('QualityAssuranceTopicRestService', { getTopics: jasmine.createSpy('getTopics'), getTopic: jasmine.createSpy('getTopic'), }); } /** - * Mock for [[NotificationsBrokerEventRestService]] + * Mock for [[QualityAssuranceEventRestService]] */ -export function getMockNotificationsBrokerEventRestService(): NotificationsBrokerEventRestService { - return jasmine.createSpyObj('NotificationsBrokerEventRestService', { +export function getMockQualityAssuranceEventRestService(): QualityAssuranceEventRestService { + return jasmine.createSpyObj('QualityAssuranceEventRestService', { getEventsByTopic: jasmine.createSpy('getEventsByTopic'), getEvent: jasmine.createSpy('getEvent'), patchEvent: jasmine.createSpy('patchEvent'), @@ -1840,7 +1840,7 @@ export function getMockNotificationsBrokerEventRestService(): NotificationsBroke } /** - * Mock for [[NotificationsBrokerEventRestService]] + * Mock for [[QualityAssuranceEventRestService]] */ export function getMockSuggestionsService(): any { return jasmine.createSpyObj('SuggestionsService', { diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d092e4f2c8..0f5db4eb5b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -499,13 +499,13 @@ "admin.access-control.groups.form.return": "Back", - "admin.notifications.broker.breadcrumbs": "Notifications Broker", + "admin.notifications.broker.breadcrumbs": "Quality Assurance", "admin.notifications.event.breadcrumbs": "Broker Suggestions", "admin.notifications.event.page.title": "Broker Suggestions", - "admin.notifications.broker.page.title": "Notifications Broker", + "admin.notifications.broker.page.title": "Quality Assurance", "admin.notifications.source.breadcrumbs": "Notifications Source", @@ -2687,7 +2687,7 @@ "menu.section.notifications": "Notifications", - "menu.section.notifications_broker": "Notifications Broker", + "menu.section.notifications_broker": "Quality Assurance", "menu.section.notifications_reciter": "Publication Claim", @@ -2889,9 +2889,9 @@ "notifications.events.title": "Broker Suggestions", - "notifications.broker.topic.error.service.retrieve": "An error occurred while loading the Notifications Broker topics", + "notifications.broker.topic.error.service.retrieve": "An error occurred while loading the Quality Assurance topics", - "notifications.broker.source.error.service.retrieve": "An error occurred while loading the Notifications Broker source", + "notifications.broker.source.error.service.retrieve": "An error occurred while loading the Quality Assurance source", "notifications.broker.events.description": "Below the list of all the suggestions for the selected topic.", From a355a154599a1b7b1860197626301bbb40006a31 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 5 Jul 2022 17:28:14 +0200 Subject: [PATCH 008/153] [CST-5249] Fix deprecated selector creation --- src/app/notifications/selectors.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/notifications/selectors.ts b/src/app/notifications/selectors.ts index 3ab769aa95..2b78b947f8 100644 --- a/src/app/notifications/selectors.ts +++ b/src/app/notifications/selectors.ts @@ -1,4 +1,4 @@ -import { createSelector, MemoizedSelector } from '@ngrx/store'; +import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/store'; import { subStateSelector } from '../shared/selector.util'; import { notificationsSelector, NotificationsState } from './notifications.reducer'; import { QualityAssuranceTopicObject } from '../core/notifications/qa/models/quality-assurance-topic.model'; @@ -12,7 +12,7 @@ import { QualityAssuranceSourceObject } from '../core/notifications/qa/models/qu * @param {AppState} state Top level state. * @return {NotificationsState} */ -const _getNotificationsState = (state: any) => state.notifications; +const _getNotificationsState = createFeatureSelector('notifications'); // Quality Assurance topics // ---------------------------------------------------------------------------- From a7d2278d993212d60cb8c43fdfe1da000d6f3e5c Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Wed, 6 Jul 2022 17:14:12 +0200 Subject: [PATCH 009/153] [CST-5249] Renamed nbevent and nbtopics --- .../admin-notifications-routing.module.ts | 10 +- ...quality-assurance-topics-page.component.ts | 2 +- ...ality-assurance-event-rest.service.spec.ts | 18 +-- .../quality-assurance-event-rest.service.ts | 2 +- ...ty-assurance-event-object.resource-type.ts | 2 +- .../models/quality-assurance-event.model.ts | 20 +-- ...y-assurance-source-object.resource-type.ts | 2 +- ...ty-assurance-topic-object.resource-type.ts | 2 +- ...lity-assurance-source-rest.service.spec.ts | 8 +- .../quality-assurance-source-rest.service.ts | 8 +- ...ality-assurance-topic-rest.service.spec.ts | 8 +- .../quality-assurance-topic-rest.service.ts | 8 +- src/app/menu.resolver.ts | 23 +++ .../notifications-state.service.spec.ts | 8 +- .../notifications/notifications.reducer.ts | 8 +- .../quality-assurance-events.component.html | 86 +++++------ .../quality-assurance-events.component.ts | 20 +-- .../project-entry-import-modal.component.ts | 6 +- .../quality-assurance-source.component.html | 20 +-- .../quality-assurance-source.effects.ts | 2 +- .../quality-assurance-topics.component.html | 20 +-- .../quality-assurance-topics.effects.ts | 2 +- src/app/notifications/selectors.ts | 24 +-- src/app/shared/mocks/notifications.mock.ts | 92 ++++++------ src/app/shared/selector.util.ts | 4 +- src/assets/i18n/en.json5 | 142 +++++++++--------- 26 files changed, 285 insertions(+), 262 deletions(-) diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index c9cca6d8d8..dc0d82c1d9 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -23,11 +23,11 @@ import { SourceDataResolver } from './admin-quality-assurance-source-page-compon pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerTopicsParams: AdminQualityAssuranceTopicsPageResolver + openaireQualityAssuranceTopicsParams: AdminQualityAssuranceTopicsPageResolver }, data: { - title: 'admin.notifications.broker.page.title', - breadcrumbKey: 'admin.notifications.broker', + title: 'admin.quality-assurance.page.title', + breadcrumbKey: 'admin.quality-assurance', showBreadcrumbsFluid: false } }, @@ -38,7 +38,7 @@ import { SourceDataResolver } from './admin-quality-assurance-source-page-compon pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerSourceParams: AdminQualityAssuranceSourcePageResolver, + openaireQualityAssuranceSourceParams: AdminQualityAssuranceSourcePageResolver, sourceData: SourceDataResolver }, data: { @@ -54,7 +54,7 @@ import { SourceDataResolver } from './admin-quality-assurance-source-page-compon pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireBrokerEventsParams: AdminQualityAssuranceEventsPageResolver + openaireQualityAssuranceEventsParams: AdminQualityAssuranceEventsPageResolver }, data: { title: 'admin.notifications.event.page.title', diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts index 53f951ba54..1b4f1d70aa 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; @Component({ - selector: 'ds-notification-broker-page', + selector: 'ds-notification-qa-page', templateUrl: './admin-quality-assurance-topics-page.component.html' }) export class AdminQualityAssuranceTopicsPageComponent { diff --git a/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts index 556665adbd..3734ae0dd2 100644 --- a/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts +++ b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.spec.ts @@ -38,15 +38,15 @@ describe('QualityAssuranceEventRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/nbtopics'; + const endpointURL = 'https://rest.api/rest/api/integration/qatopics'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const topic = 'ENRICH!MORE!PID'; const pageInfo = new PageInfo(); const array = [ qualityAssuranceEventObjectMissingPid, qualityAssuranceEventObjectMissingPid2 ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerEventObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingPid); - const brokerEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingProjectFound); + const qaEventObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingPid); + const qaEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingProjectFound); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); const status = 'ACCEPTED'; @@ -82,7 +82,7 @@ describe('QualityAssuranceEventRestService', () => { rdbService = jasmine.createSpyObj('rdbService', { buildSingle: cold('(a)', { - a: brokerEventObjectRD + a: qaEventObjectRD }), buildList: cold('(a)', { a: paginatedListRD @@ -122,7 +122,7 @@ describe('QualityAssuranceEventRestService', () => { beforeEach(() => { serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); - serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); }); it('should proxy the call to dataservice.searchBy', () => { @@ -151,7 +151,7 @@ describe('QualityAssuranceEventRestService', () => { beforeEach(() => { serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); - serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); }); it('should proxy the call to dataservice.findById', () => { @@ -165,7 +165,7 @@ describe('QualityAssuranceEventRestService', () => { it('should return a RemoteData for the object with the given URL', () => { const result = service.getEvent(qualityAssuranceEventObjectMissingPid.id); const expected = cold('(a)', { - a: brokerEventObjectRD + a: qaEventObjectRD }); expect(result).toBeObservable(expected); }); @@ -175,7 +175,7 @@ describe('QualityAssuranceEventRestService', () => { beforeEach(() => { serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); - serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectRD)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); }); it('should proxy the call to dataservice.patch', () => { @@ -199,7 +199,7 @@ describe('QualityAssuranceEventRestService', () => { beforeEach(() => { serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntryB)); serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntryB)); - serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(brokerEventObjectMissingProjectRD)); + serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectMissingProjectRD)); }); it('should proxy the call to dataservice.postOnRelated', () => { diff --git a/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts index 59f6c31e05..67863cad74 100644 --- a/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts +++ b/src/app/core/notifications/qa/events/quality-assurance-event-rest.service.ts @@ -33,7 +33,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'nbevents'; + protected linkPath = 'qaevents'; /** * Initialize service variables diff --git a/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts index 33c7b338ed..2dedc84d08 100644 --- a/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-event-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_EVENT_OBJECT = new ResourceType('nbevent'); +export const QUALITY_ASSURANCE_EVENT_OBJECT = new ResourceType('qaevent'); diff --git a/src/app/core/notifications/qa/models/quality-assurance-event.model.ts b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts index 15fbae7821..f070e7303a 100644 --- a/src/app/core/notifications/qa/models/quality-assurance-event.model.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts @@ -11,16 +11,16 @@ import { RemoteData } from '../../../data/remote-data'; import {CacheableObject} from '../../../cache/cacheable-object.model'; /** - * The interface representing the Notifications Broker event message + * The interface representing the Quality Assurance event message */ export interface QualityAssuranceEventMessageObject { } /** - * The interface representing the Notifications Broker event message + * The interface representing the Quality Assurance event message */ -export interface OpenaireBrokerEventMessageObject { +export interface OpenaireQualityAssuranceEventMessageObject { /** * The type of 'value' */ @@ -74,7 +74,7 @@ export interface OpenaireBrokerEventMessageObject { } /** - * The interface representing the Notifications Broker event model + * The interface representing the Quality Assurance event model */ @typedObject export class QualityAssuranceEventObject implements CacheableObject { @@ -84,19 +84,19 @@ export class QualityAssuranceEventObject implements CacheableObject { static type = QUALITY_ASSURANCE_EVENT_OBJECT; /** - * The Notifications Broker event uuid inside DSpace + * The Quality Assurance event uuid inside DSpace */ @autoserialize id: string; /** - * The universally unique identifier of this Notifications Broker event + * The universally unique identifier of this Quality Assurance event */ @autoserializeAs(String, 'id') uuid: string; /** - * The Notifications Broker event original id (ex.: the source archive OAI-PMH identifier) + * The Quality Assurance event original id (ex.: the source archive OAI-PMH identifier) */ @autoserialize originalId: string; @@ -114,13 +114,13 @@ export class QualityAssuranceEventObject implements CacheableObject { trust: number; /** - * The timestamp Notifications Broker event was saved in DSpace + * The timestamp Quality Assurance event was saved in DSpace */ @autoserialize eventDate: string; /** - * The Notifications Broker event status (ACCEPTED, REJECTED, DISCARDED, PENDING) + * The Quality Assurance event status (ACCEPTED, REJECTED, DISCARDED, PENDING) */ @autoserialize status: string; @@ -129,7 +129,7 @@ export class QualityAssuranceEventObject implements CacheableObject { * The suggestion data. Data may vary depending on the source */ @autoserialize - message: OpenaireBrokerEventMessageObject; + message: OpenaireQualityAssuranceEventMessageObject; /** * The type of this ConfigObject diff --git a/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts index 585216c34f..5f4c8dd954 100644 --- a/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-source-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_SOURCE_OBJECT = new ResourceType('nbsource'); +export const QUALITY_ASSURANCE_SOURCE_OBJECT = new ResourceType('qasource'); diff --git a/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts b/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts index 8cd5bec61b..7e12dd9ca8 100644 --- a/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-topic-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_TOPIC_OBJECT = new ResourceType('nbtopic'); +export const QUALITY_ASSURANCE_TOPIC_OBJECT = new ResourceType('qatopic'); diff --git a/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts index dff604b0c4..d574b36802 100644 --- a/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts +++ b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.spec.ts @@ -32,13 +32,13 @@ describe('QualityAssuranceSourceRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/nbsources'; + const endpointURL = 'https://rest.api/rest/api/integration/qasources'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); const array = [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerSourceObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceSourceObjectMorePid); + const qaSourceObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceSourceObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); beforeEach(() => { @@ -56,7 +56,7 @@ describe('QualityAssuranceSourceRestService', () => { rdbService = jasmine.createSpyObj('rdbService', { buildSingle: cold('(a)', { - a: brokerSourceObjectRD + a: qaSourceObjectRD }), buildList: cold('(a)', { a: paginatedListRD @@ -118,7 +118,7 @@ describe('QualityAssuranceSourceRestService', () => { it('should return a RemoteData for the object with the given URL', () => { const result = service.getSource(qualityAssuranceSourceObjectMorePid.id); const expected = cold('(a)', { - a: brokerSourceObjectRD + a: qaSourceObjectRD }); expect(result).toBeObservable(expected); }); diff --git a/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts index 85045aebcd..10bcfbe896 100644 --- a/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts +++ b/src/app/core/notifications/qa/source/quality-assurance-source-rest.service.ts @@ -31,7 +31,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'nbsources'; + protected linkPath = 'qasources'; /** * Initialize service variables @@ -100,7 +100,7 @@ export class QualityAssuranceSourceRestService { * The list of Quality Assurance source. */ public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'nbsources').pipe( + return this.dataService.getBrowseEndpoint(options, 'qasources').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), ); @@ -110,7 +110,7 @@ export class QualityAssuranceSourceRestService { * Clear FindAll source requests from cache */ public clearFindAllSourceRequests() { - this.requestService.setStaleByHrefSubstring('nbsources'); + this.requestService.setStaleByHrefSubstring('qasources'); } /** @@ -125,7 +125,7 @@ export class QualityAssuranceSourceRestService { */ public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'nbsources').pipe( + return this.dataService.getBrowseEndpoint(options, 'qasources').pipe( take(1), mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); diff --git a/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts index cb828141a6..458bc4957d 100644 --- a/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts @@ -32,13 +32,13 @@ describe('QualityAssuranceTopicRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/nbtopics'; + const endpointURL = 'https://rest.api/rest/api/integration/qatopics'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); const array = [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ]; const paginatedList = buildPaginatedList(pageInfo, array); - const brokerTopicObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceTopicObjectMorePid); + const qaTopicObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceTopicObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); beforeEach(() => { @@ -56,7 +56,7 @@ describe('QualityAssuranceTopicRestService', () => { rdbService = jasmine.createSpyObj('rdbService', { buildSingle: cold('(a)', { - a: brokerTopicObjectRD + a: qaTopicObjectRD }), buildList: cold('(a)', { a: paginatedListRD @@ -118,7 +118,7 @@ describe('QualityAssuranceTopicRestService', () => { it('should return a RemoteData for the object with the given URL', () => { const result = service.getTopic(qualityAssuranceTopicObjectMorePid.id); const expected = cold('(a)', { - a: brokerTopicObjectRD + a: qaTopicObjectRD }); expect(result).toBeObservable(expected); }); diff --git a/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts index da90126709..da9d95d290 100644 --- a/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-rest.service.ts @@ -31,7 +31,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'nbtopics'; + protected linkPath = 'qatopics'; /** * Initialize service variables @@ -100,7 +100,7 @@ export class QualityAssuranceTopicRestService { * The list of Quality Assurance topics. */ public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( + return this.dataService.getBrowseEndpoint(options, 'qatopics').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), ); @@ -110,7 +110,7 @@ export class QualityAssuranceTopicRestService { * Clear FindAll topics requests from cache */ public clearFindAllTopicsRequests() { - this.requestService.setStaleByHrefSubstring('nbtopics'); + this.requestService.setStaleByHrefSubstring('qatopics'); } /** @@ -125,7 +125,7 @@ export class QualityAssuranceTopicRestService { */ public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'nbtopics').pipe( + return this.dataService.getBrowseEndpoint(options, 'qatopics').pipe( take(1), mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 4c97d3d1b3..e4eba11622 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -507,6 +507,29 @@ export class MenuResolver implements Resolve { createSiteAdministratorMenuSections() { this.authorizationService.isAuthorized(FeatureID.AdministratorOf).subscribe((authorized) => { const menuList = [ + /* Notifications */ + { + id: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications' + } as TextMenuItemModel, + icon: 'bell', + index: 4 + }, + { + id: 'notifications_quality-assurance', + parentID: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.quality-assurance', + link: '/admin/notifications/quality-assurance' + } as LinkMenuItemModel, + }, /* Admin Search */ { id: 'admin_search', diff --git a/src/app/notifications/notifications-state.service.spec.ts b/src/app/notifications/notifications-state.service.spec.ts index cabda48ec5..8c191415b7 100644 --- a/src/app/notifications/notifications-state.service.spec.ts +++ b/src/app/notifications/notifications-state.service.spec.ts @@ -26,7 +26,7 @@ describe('NotificationsStateService', () => { if (mode === 'empty') { initialState = { notifications: { - brokerTopic: { + qaTopic: { topics: [], processing: false, loaded: false, @@ -40,7 +40,7 @@ describe('NotificationsStateService', () => { } else { initialState = { notifications: { - brokerTopic: { + qaTopic: { topics: [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract, @@ -284,7 +284,7 @@ describe('NotificationsStateService', () => { if (mode === 'empty') { initialState = { notifications: { - brokerSource: { + qaSource: { source: [], processing: false, loaded: false, @@ -298,7 +298,7 @@ describe('NotificationsStateService', () => { } else { initialState = { notifications: { - brokerSource: { + qaSource: { source: [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract, diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index 5800788c42..4cce554f95 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -6,13 +6,13 @@ import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState, } from './qa * The OpenAIRE State */ export interface NotificationsState { - 'brokerTopic': QualityAssuranceTopicState; - 'brokerSource': QualityAssuranceSourceState; + 'qaTopic': QualityAssuranceTopicState; + 'qaSource': QualityAssuranceSourceState; } export const notificationsReducers: ActionReducerMap = { - brokerTopic: qualityAssuranceTopicsReducer, - brokerSource: qualityAssuranceSourceReducer + qaTopic: qualityAssuranceTopicsReducer, + qaSource: qualityAssuranceSourceReducer }; export const notificationsSelector = createFeatureSelector('notifications'); diff --git a/src/app/notifications/qa/events/quality-assurance-events.component.html b/src/app/notifications/qa/events/quality-assurance-events.component.html index 40fa75943f..d7f6129b3b 100644 --- a/src/app/notifications/qa/events/quality-assurance-events.component.html +++ b/src/app/notifications/qa/events/quality-assurance-events.component.html @@ -2,11 +2,11 @@

{{'notifications.events.title'| translate}}

-

{{'notifications.broker.events.description'| translate}}

+

{{'quality-assurance.events.description'| translate}}

- {{'notifications.broker.events.back' | translate}} + {{'quality-assurance.events.back' | translate}}

@@ -14,10 +14,10 @@

- {{'notifications.broker.events.topic' | translate}} {{this.showTopic}} + {{'quality-assurance.events.topic' | translate}} {{this.showTopic}}

- + - +
- - - - - + + + + + @@ -51,8 +51,8 @@ {{eventElement.title}} @@ -142,7 +142,7 @@ @@ -150,58 +150,58 @@ diff --git a/src/app/notifications/qa/events/quality-assurance-events.component.ts b/src/app/notifications/qa/events/quality-assurance-events.component.ts index aa47bfc590..6e3dd8d010 100644 --- a/src/app/notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/notifications/qa/events/quality-assurance-events.component.ts @@ -11,7 +11,7 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; import { QualityAssuranceEventObject, - OpenaireBrokerEventMessageObject + OpenaireQualityAssuranceEventMessageObject } from '../../../core/notifications/qa/models/quality-assurance-event.model'; import { QualityAssuranceEventRestService } from '../../../core/notifications/qa/events/quality-assurance-event-rest.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; @@ -242,12 +242,12 @@ export class QualityAssuranceEventsComponent implements OnInit { .subscribe((rd: RemoteData) => { if (rd.isSuccess && rd.statusCode === 200) { this.notificationsService.success( - this.translateService.instant('notifications.broker.event.action.saved') + this.translateService.instant('quality-assurance.event.action.saved') ); this.getQualityAssuranceEvents(); } else { this.notificationsService.error( - this.translateService.instant('notifications.broker.event.action.error') + this.translateService.instant('quality-assurance.event.action.error') ); } eventData.isRunning = false; @@ -274,7 +274,7 @@ export class QualityAssuranceEventsComponent implements OnInit { .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( - this.translateService.instant('notifications.broker.event.project.bounded') + this.translateService.instant('quality-assurance.event.project.bounded') ); eventData.hasProject = true; eventData.projectTitle = projectTitle; @@ -282,7 +282,7 @@ export class QualityAssuranceEventsComponent implements OnInit { eventData.projectId = projectId; } else { this.notificationsService.error( - this.translateService.instant('notifications.broker.event.project.error') + this.translateService.instant('quality-assurance.event.project.error') ); } eventData.isRunning = false; @@ -303,7 +303,7 @@ export class QualityAssuranceEventsComponent implements OnInit { .subscribe((rd: RemoteData) => { if (rd.isSuccess) { this.notificationsService.success( - this.translateService.instant('notifications.broker.event.project.removed') + this.translateService.instant('quality-assurance.event.project.removed') ); eventData.hasProject = false; eventData.projectTitle = null; @@ -311,7 +311,7 @@ export class QualityAssuranceEventsComponent implements OnInit { eventData.projectId = null; } else { this.notificationsService.error( - this.translateService.instant('notifications.broker.event.project.error') + this.translateService.instant('quality-assurance.event.project.error') ); } eventData.isRunning = false; @@ -323,7 +323,7 @@ export class QualityAssuranceEventsComponent implements OnInit { * Check if the event has a valid href. * @param event */ - public hasPIDHref(event: OpenaireBrokerEventMessageObject): boolean { + public hasPIDHref(event: OpenaireQualityAssuranceEventMessageObject): boolean { return this.getPIDHref(event) !== null; } @@ -331,7 +331,7 @@ export class QualityAssuranceEventsComponent implements OnInit { * Get the event pid href. * @param event */ - public getPIDHref(event: OpenaireBrokerEventMessageObject): string { + public getPIDHref(event: OpenaireQualityAssuranceEventMessageObject): string { return this.computePIDHref(event); } @@ -419,7 +419,7 @@ export class QualityAssuranceEventsComponent implements OnInit { ); } - protected computePIDHref(event: OpenaireBrokerEventMessageObject) { + protected computePIDHref(event: OpenaireQualityAssuranceEventMessageObject) { const type = event.type.toLowerCase(); const pid = event.value; let prefix = null; diff --git a/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts index 64a5f6908f..64a2df30ba 100644 --- a/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts +++ b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts @@ -15,7 +15,7 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { QualityAssuranceEventObject, QualityAssuranceEventMessageObject, - OpenaireBrokerEventMessageObject, + OpenaireQualityAssuranceEventMessageObject, } from '../../../core/notifications/qa/models/quality-assurance-event.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { Item } from '../../../core/shared/item.model'; @@ -98,7 +98,7 @@ export class ProjectEntryImportModalComponent implements OnInit { /** * The prefix for every i18n key within this modal */ - labelPrefix = 'notifications.broker.event.modal.'; + labelPrefix = 'quality-assurance.event.modal.'; /** * The search configuration to retrieve project */ @@ -181,7 +181,7 @@ export class ProjectEntryImportModalComponent implements OnInit { public ngOnInit(): void { this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'notifications-project-bound', pageSize: this.pageSize }); this.projectTitle = (this.externalSourceEntry.projectTitle !== null) ? this.externalSourceEntry.projectTitle - : (this.externalSourceEntry.event.message as OpenaireBrokerEventMessageObject).title; + : (this.externalSourceEntry.event.message as OpenaireQualityAssuranceEventMessageObject).title; this.searchOptions = Object.assign(new PaginatedSearchOptions( { configuration: this.configuration, diff --git a/src/app/notifications/qa/source/quality-assurance-source.component.html b/src/app/notifications/qa/source/quality-assurance-source.component.html index 5309098c55..20f4d4394a 100644 --- a/src/app/notifications/qa/source/quality-assurance-source.component.html +++ b/src/app/notifications/qa/source/quality-assurance-source.component.html @@ -1,15 +1,15 @@
-

{{'notifications.broker.title'| translate}}

-

{{'notifications.broker.source.description'| translate}}

+

{{'quality-assurance.title'| translate}}

+

{{'quality-assurance.source.description'| translate}}

-

{{'notifications.broker.source'| translate}}

+

{{'quality-assurance.source'| translate}}

- + - +
{{'notifications.broker.event.table.trust' | translate}}{{'notifications.broker.event.table.publication' | translate}}{{'notifications.broker.event.table.details' | translate}}{{'notifications.broker.event.table.project-details' | translate}}{{'notifications.broker.event.table.actions' | translate}}{{'quality-assurance.event.table.trust' | translate}}{{'quality-assurance.event.table.publication' | translate}}{{'quality-assurance.event.table.details' | translate}}{{'quality-assurance.event.table.project-details' | translate}}{{'quality-assurance.event.table.actions' | translate}}
-

{{'notifications.broker.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

-

{{'notifications.broker.event.table.pidvalue' | translate}}
+

{{'quality-assurance.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

+

{{'quality-assurance.event.table.pidvalue' | translate}}
{{eventElement.event.message.value}} @@ -60,37 +60,37 @@

-

{{'notifications.broker.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

+

{{'quality-assurance.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

- {{'notifications.broker.event.table.abstract' | translate}}
+ {{'quality-assurance.event.table.abstract' | translate}}
{{eventElement.event.message.abstract}}

- {{'notifications.broker.event.table.suggestedProject' | translate}} + {{'quality-assurance.event.table.suggestedProject' | translate}}

- {{'notifications.broker.event.table.project' | translate}}
+ {{'quality-assurance.event.table.project' | translate}}
{{eventElement.event.message.title}}

- {{'notifications.broker.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
- {{'notifications.broker.event.table.code' | translate}} {{eventElement.event.message.code}}
- {{'notifications.broker.event.table.funder' | translate}} {{eventElement.event.message.funder}}
- {{'notifications.broker.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
- {{'notifications.broker.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}} + {{'quality-assurance.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
+ {{'quality-assurance.event.table.code' | translate}} {{eventElement.event.message.code}}
+ {{'quality-assurance.event.table.funder' | translate}} {{eventElement.event.message.funder}}
+ {{'quality-assurance.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
+ {{'quality-assurance.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}}


- {{(eventElement.hasProject ? 'notifications.broker.event.project.found' : 'notifications.broker.event.project.notFound') | translate}} + {{(eventElement.hasProject ? 'quality-assurance.event.project.found' : 'quality-assurance.event.project.notFound') | translate}} {{eventElement.handle}}
- - - + + + @@ -39,7 +39,7 @@
{{'notifications.broker.table.source' | translate}}{{'notifications.broker.table.last-event' | translate}}{{'notifications.broker.table.actions' | translate}}{{'quality-assurance.table.source' | translate}}{{'quality-assurance.table.last-event' | translate}}{{'quality-assurance.table.actions' | translate}}
- - - + + + @@ -39,7 +39,7 @@
@@ -155,13 +166,13 @@ @@ -172,16 +183,13 @@ @@ -192,16 +200,13 @@ From bb357df738ce12c35064434f5663de2932f53546 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 8 Jul 2022 18:04:42 +0200 Subject: [PATCH 016/153] [CST-5337] Added missing typedocs --- .../admin-quality-assurance-events-page.component.ts | 3 +++ .../admin-quality-assurance-source-page.component.ts | 3 +++ .../admin-quality-assurance-topics-page.component.ts | 3 +++ ...scomponent.scss => quality-assurance-events.component.scss} | 0 .../qa/source/quality-assurance-source.component.ts | 3 +++ 5 files changed, 12 insertions(+) rename src/app/suggestion-notifications/qa/events/{quality-assurance-events.scomponent.scss => quality-assurance-events.component.scss} (100%) diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts index a1e15d5bdb..bd3470f301 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for the page that show the QA events related to a specific topic. + */ @Component({ selector: 'ds-quality-assurance-events-page', templateUrl: './admin-quality-assurance-events-page.component.html' diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts index 624e71f281..20d0356d5f 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts @@ -1,5 +1,8 @@ import { Component, OnInit } from '@angular/core'; +/** + * Component for the page that show the QA sources. + */ @Component({ selector: 'ds-admin-quality-assurance-source-page-component', templateUrl: './admin-quality-assurance-source-page.component.html', diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts index 1b4f1d70aa..f17d3448d5 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for the page that show the QA topics related to a specific source. + */ @Component({ selector: 'ds-notification-qa-page', templateUrl: './admin-quality-assurance-topics-page.component.html' diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.scomponent.scss b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss similarity index 100% rename from src/app/suggestion-notifications/qa/events/quality-assurance-events.scomponent.scss rename to src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.ts index 372dc654ff..f6f02d9ab9 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.ts @@ -9,6 +9,9 @@ import { SuggestionNotificationsStateService } from '../../suggestion-notificati import { AdminQualityAssuranceSourcePageParams } from '../../../admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service'; import { hasValue } from '../../../shared/empty.util'; +/** + * Component to display the Quality Assurance source list. + */ @Component({ selector: 'ds-quality-assurance-source', templateUrl: './quality-assurance-source.component.html', From 7808f85a2dea85b347c6bf64531577c5fdce0851 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 8 Jul 2022 18:20:38 +0200 Subject: [PATCH 017/153] [CST-5337] Moved compute PID href on rest side --- .../models/quality-assurance-event.model.ts | 5 ++ src/app/shared/mocks/notifications.mock.ts | 9 ++++ .../quality-assurance-events.component.ts | 47 +------------------ 3 files changed, 16 insertions(+), 45 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model.ts b/src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model.ts index c9395bd528..7517148def 100644 --- a/src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model.ts +++ b/src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model.ts @@ -73,6 +73,11 @@ export interface OpenaireQualityAssuranceEventMessageObject { */ openaireId: string; + /** + * The PID href. + */ + pidHref: string; + } /** diff --git a/src/app/shared/mocks/notifications.mock.ts b/src/app/shared/mocks/notifications.mock.ts index ef6d99e9ea..bbdf60c083 100644 --- a/src/app/shared/mocks/notifications.mock.ts +++ b/src/app/shared/mocks/notifications.mock.ts @@ -1464,6 +1464,7 @@ export const qualityAssuranceEventObjectMissingPid: QualityAssuranceEventObject message: { type: 'doi', value: '10.18848/1447-9494/cgp/v15i09/45934', + pidHref: 'https://doi.org/10.18848/1447-9494/cgp/v15i09/45934', abstract: null, openaireId: null, acronym: null, @@ -1500,6 +1501,7 @@ export const qualityAssuranceEventObjectMissingPid2: QualityAssuranceEventObject message: { type: 'urn', value: 'http://thesis2.sba.units.it/store/handle/item/12238', + pidHref:'http://thesis2.sba.units.it/store/handle/item/12238', abstract: null, openaireId: null, acronym: null, @@ -1536,6 +1538,7 @@ export const qualityAssuranceEventObjectMissingPid3: QualityAssuranceEventObject message: { type: 'doi', value: '10.4324/9780203408889', + pidHref: 'https://doi.org/10.4324/9780203408889', abstract: null, openaireId: null, acronym: null, @@ -1572,6 +1575,7 @@ export const qualityAssuranceEventObjectMissingPid4: QualityAssuranceEventObject message: { type: 'doi', value: '10.1080/13698230.2018.1430104', + pidHref: 'https://doi.org/10.1080/13698230.2018.1430104', abstract: null, openaireId: null, acronym: null, @@ -1608,6 +1612,7 @@ export const qualityAssuranceEventObjectMissingPid5: QualityAssuranceEventObject message: { type: 'urn', value: 'http://thesis2.sba.units.it/store/handle/item/12477', + pidHref:'http://thesis2.sba.units.it/store/handle/item/12477', abstract: null, openaireId: null, acronym: null, @@ -1644,6 +1649,7 @@ export const qualityAssuranceEventObjectMissingPid6: QualityAssuranceEventObject message: { type: 'doi', value: '10.1111/j.1475-4975.2004.00098.x', + pidHref: 'https://doi.org/10.1111/j.1475-4975.2004.00098.x', abstract: null, openaireId: null, acronym: null, @@ -1680,6 +1686,7 @@ export const qualityAssuranceEventObjectMissingAbstract: QualityAssuranceEventOb message: { type: null, value: null, + pidHref: null, abstract: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque vestibulum tellus sed lacinia. Aenean vitae sapien a quam congue ultrices. Sed vehicula sollicitudin ligula, vitae lacinia velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque vestibulum tellus sed lacinia. Aenean vitae sapien a quam congue ultrices. Sed vehicula sollicitudin ligula, vitae lacinia velit.', openaireId: null, acronym: null, @@ -1716,6 +1723,7 @@ export const qualityAssuranceEventObjectMissingProjectFound: QualityAssuranceEve message: { type: null, value: null, + pidHref: null, abstract: null, openaireId: null, acronym: 'PAThs', @@ -1752,6 +1760,7 @@ export const qualityAssuranceEventObjectMissingProjectNotFound: QualityAssurance message: { type: null, value: null, + pidHref: null, abstract: null, openaireId: null, acronym: 'PAThs', diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts index 0f71123d22..9f33a02225 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts @@ -38,7 +38,7 @@ import { FindListOptions } from '../../../core/data/find-list-options.model'; @Component({ selector: 'ds-quality-assurance-events', templateUrl: './quality-assurance-events.component.html', - styleUrls: ['./quality-assurance-events.scomponent.scss'], + styleUrls: ['./quality-assurance-events.component.scss'], }) export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { /** @@ -334,7 +334,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @param event */ public getPIDHref(event: OpenaireQualityAssuranceEventMessageObject): string { - return this.computePIDHref(event); + return event.pidHref; } @@ -423,47 +423,4 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { ); } } - - protected computePIDHref(event: OpenaireQualityAssuranceEventMessageObject) { - const type = event.type.toLowerCase(); - const pid = event.value; - let prefix = null; - switch (type) { - case 'arxiv': { - prefix = 'https://arxiv.org/abs/'; - break; - } - case 'handle': { - prefix = 'https://hdl.handle.net/'; - break; - } - case 'urn': { - prefix = ''; - break; - } - case 'doi': { - prefix = 'https://doi.org/'; - break; - } - case 'pmc': { - prefix = 'https://www.ncbi.nlm.nih.gov/pmc/articles/'; - break; - } - case 'pmid': { - prefix = 'https://pubmed.ncbi.nlm.nih.gov/'; - break; - } - case 'ncid': { - prefix = 'https://ci.nii.ac.jp/ncid/'; - break; - } - default: { - break; - } - } - if (prefix === null) { - return null; - } - return prefix + pid; - } } From 3a70b880cbc41b32521d4251e7e912e9bb27b6d8 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Wed, 9 Nov 2022 15:13:09 +0100 Subject: [PATCH 018/153] [CST-5337] Renamed qa endpoints --- .../events/quality-assurance-event-rest.service.spec.ts | 2 +- .../qa/events/quality-assurance-event-rest.service.ts | 3 +-- .../quality-assurance-source-object.resource-type.ts | 2 +- .../quality-assurance-topic-object.resource-type.ts | 2 +- .../source/quality-assurance-source-rest.service.spec.ts | 2 +- .../qa/source/quality-assurance-source-rest.service.ts | 8 ++++---- .../topics/quality-assurance-topic-rest.service.spec.ts | 2 +- .../qa/topics/quality-assurance-topic-rest.service.ts | 8 ++++---- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts index 3734ae0dd2..55b2788c8b 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts @@ -38,7 +38,7 @@ describe('QualityAssuranceEventRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/qatopics'; + const endpointURL = 'https://rest.api/rest/api/integration/qualityassurancetopics'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const topic = 'ENRICH!MORE!PID'; diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts index a7cdd9e786..e4d13670a1 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts @@ -12,7 +12,6 @@ import { RestResponse } from '../../../cache/response.models'; import { ObjectCacheService } from '../../../cache/object-cache.service'; import { dataService } from '../../../cache/builders/build-decorators'; import { RequestService } from '../../../data/request.service'; -import { DataService } from '../../../data/data.service'; import { ChangeAnalyzer } from '../../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; @@ -33,7 +32,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'qaevents'; + protected linkPath = 'qualityassuranceevents'; /** * Initialize service variables diff --git a/src/app/core/suggestion-notifications/qa/models/quality-assurance-source-object.resource-type.ts b/src/app/core/suggestion-notifications/qa/models/quality-assurance-source-object.resource-type.ts index 5f4c8dd954..b4f64b24d1 100644 --- a/src/app/core/suggestion-notifications/qa/models/quality-assurance-source-object.resource-type.ts +++ b/src/app/core/suggestion-notifications/qa/models/quality-assurance-source-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_SOURCE_OBJECT = new ResourceType('qasource'); +export const QUALITY_ASSURANCE_SOURCE_OBJECT = new ResourceType('qualityassurancesource'); diff --git a/src/app/core/suggestion-notifications/qa/models/quality-assurance-topic-object.resource-type.ts b/src/app/core/suggestion-notifications/qa/models/quality-assurance-topic-object.resource-type.ts index 7e12dd9ca8..e9fc57a307 100644 --- a/src/app/core/suggestion-notifications/qa/models/quality-assurance-topic-object.resource-type.ts +++ b/src/app/core/suggestion-notifications/qa/models/quality-assurance-topic-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_TOPIC_OBJECT = new ResourceType('qatopic'); +export const QUALITY_ASSURANCE_TOPIC_OBJECT = new ResourceType('qualityassurancetopic'); diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts index d574b36802..dc90b581cb 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts @@ -32,7 +32,7 @@ describe('QualityAssuranceSourceRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/qasources'; + const endpointURL = 'https://rest.api/rest/api/integration/qualityassurancesources'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts index 6b5ca806ff..05d2ba4ae6 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts @@ -30,7 +30,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'qasources'; + protected linkPath = 'qualityassurancesources'; /** * Initialize service variables @@ -99,7 +99,7 @@ export class QualityAssuranceSourceRestService { * The list of Quality Assurance source. */ public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'qasources').pipe( + return this.dataService.getBrowseEndpoint(options, 'qualityassurancesources').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), ); @@ -109,7 +109,7 @@ export class QualityAssuranceSourceRestService { * Clear FindAll source requests from cache */ public clearFindAllSourceRequests() { - this.requestService.setStaleByHrefSubstring('qasources'); + this.requestService.setStaleByHrefSubstring('qualityassurancesources'); } /** @@ -124,7 +124,7 @@ export class QualityAssuranceSourceRestService { */ public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'qasources').pipe( + return this.dataService.getBrowseEndpoint(options, 'qualityassurancesources').pipe( take(1), mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts index 458bc4957d..babc9d83b3 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts @@ -32,7 +32,7 @@ describe('QualityAssuranceTopicRestService', () => { let http: HttpClient; let comparator: any; - const endpointURL = 'https://rest.api/rest/api/integration/qatopics'; + const endpointURL = 'https://rest.api/rest/api/integration/qualityassurancetopics'; const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts index a2f2498fca..86942a7b5b 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts @@ -30,7 +30,7 @@ class DataServiceImpl extends DataService { /** * The REST endpoint. */ - protected linkPath = 'qatopics'; + protected linkPath = 'qualityassurancetopics'; /** * Initialize service variables @@ -99,7 +99,7 @@ export class QualityAssuranceTopicRestService { * The list of Quality Assurance topics. */ public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'qatopics').pipe( + return this.dataService.getBrowseEndpoint(options, 'qualityassurancetopics').pipe( take(1), mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), ); @@ -109,7 +109,7 @@ export class QualityAssuranceTopicRestService { * Clear FindAll topics requests from cache */ public clearFindAllTopicsRequests() { - this.requestService.setStaleByHrefSubstring('qatopics'); + this.requestService.setStaleByHrefSubstring('qualityassurancetopics'); } /** @@ -124,7 +124,7 @@ export class QualityAssuranceTopicRestService { */ public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'qatopics').pipe( + return this.dataService.getBrowseEndpoint(options, 'qualityassurancetopics').pipe( take(1), mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); From 5efe3296c613be48d25251bfbfdd24e3d448556c Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 9 Nov 2022 19:05:20 +0100 Subject: [PATCH 019/153] [CST-5337] Refactoring in order to comply with new data service --- ...ality-assurance-event-rest.service.spec.ts | 47 +++--- .../quality-assurance-event-rest.service.ts | 137 ++++++++++-------- ...lity-assurance-source-rest.service.spec.ts | 24 ++- .../quality-assurance-source-rest.service.ts | 67 ++------- ...ality-assurance-topic-rest.service.spec.ts | 22 ++- .../quality-assurance-topic-rest.service.ts | 70 ++------- 6 files changed, 146 insertions(+), 221 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts index 55b2788c8b..731c70d624 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts @@ -20,8 +20,8 @@ import { qualityAssuranceEventObjectMissingProjectFound } from '../../../../shared/mocks/notifications.mock'; import { ReplaceOperation } from 'fast-json-patch'; -import {RequestEntry} from '../../../data/request-entry.model'; -import {FindListOptions} from '../../../data/find-list-options.model'; +import { RequestEntry } from '../../../data/request-entry.model'; +import { FindListOptions } from '../../../data/find-list-options.model'; describe('QualityAssuranceEventRestService', () => { let scheduler: TestScheduler; @@ -43,7 +43,7 @@ describe('QualityAssuranceEventRestService', () => { const topic = 'ENRICH!MORE!PID'; const pageInfo = new PageInfo(); - const array = [ qualityAssuranceEventObjectMissingPid, qualityAssuranceEventObjectMissingPid2 ]; + const array = [qualityAssuranceEventObjectMissingPid, qualityAssuranceEventObjectMissingPid2]; const paginatedList = buildPaginatedList(pageInfo, array); const qaEventObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingPid); const qaEventObjectMissingProjectRD = createSuccessfulRemoteDataObject(qualityAssuranceEventObjectMissingProjectFound); @@ -87,12 +87,13 @@ describe('QualityAssuranceEventRestService', () => { buildList: cold('(a)', { a: paginatedListRD }), - buildFromRequestUUID: jasmine.createSpy('buildFromRequestUUID') + buildFromRequestUUID: jasmine.createSpy('buildFromRequestUUID'), + buildFromRequestUUIDAndAwait: jasmine.createSpy('buildFromRequestUUIDAndAwait') }); objectCache = {} as ObjectCacheService; halService = jasmine.createSpyObj('halService', { - getEndpoint: cold('a|', { a: endpointURL }) + getEndpoint: cold('a|', { a: endpointURL }) }); notificationsService = {} as NotificationsService; @@ -105,17 +106,16 @@ describe('QualityAssuranceEventRestService', () => { objectCache, halService, notificationsService, - http, comparator ); serviceASAny = service; - spyOn(serviceASAny.dataService, 'searchBy').and.callThrough(); - spyOn(serviceASAny.dataService, 'findById').and.callThrough(); - spyOn(serviceASAny.dataService, 'patch').and.callThrough(); - spyOn(serviceASAny.dataService, 'postOnRelated').and.callThrough(); - spyOn(serviceASAny.dataService, 'deleteOnRelated').and.callThrough(); + spyOn(serviceASAny.searchData, 'searchBy').and.callThrough(); + spyOn(serviceASAny, 'findById').and.callThrough(); + spyOn(serviceASAny.patchData, 'patch').and.callThrough(); + spyOn(serviceASAny, 'postOnRelated').and.callThrough(); + spyOn(serviceASAny, 'deleteOnRelated').and.callThrough(); }); describe('getEventsByTopic', () => { @@ -125,7 +125,7 @@ describe('QualityAssuranceEventRestService', () => { serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); }); - it('should proxy the call to dataservice.searchBy', () => { + it('should proxy the call to searchData.searchBy', () => { const options: FindListOptions = { searchParams: [ { @@ -135,13 +135,13 @@ describe('QualityAssuranceEventRestService', () => { ] }; service.getEventsByTopic(topic); - expect(serviceASAny.dataService.searchBy).toHaveBeenCalledWith('findByTopic', options, true, true); + expect(serviceASAny.searchData.searchBy).toHaveBeenCalledWith('findByTopic', options, true, true); }); it('should return a RemoteData> for the object with the given Topic', () => { const result = service.getEventsByTopic(topic); const expected = cold('(a)', { - a: paginatedListRD + a: paginatedListRD }); expect(result).toBeObservable(expected); }); @@ -154,15 +154,15 @@ describe('QualityAssuranceEventRestService', () => { serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); }); - it('should proxy the call to dataservice.findById', () => { + it('should call findById', () => { service.getEvent(qualityAssuranceEventObjectMissingPid.id).subscribe( (res) => { - expect(serviceASAny.dataService.findById).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid.id, true, true); + expect(serviceASAny.findById).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid.id, true, true); } ); }); - it('should return a RemoteData for the object with the given URL', () => { + it('should return a RemoteData for the object with the given URL', () => { const result = service.getEvent(qualityAssuranceEventObjectMissingPid.id); const expected = cold('(a)', { a: qaEventObjectRD @@ -176,12 +176,13 @@ describe('QualityAssuranceEventRestService', () => { serviceASAny.requestService.getByHref.and.returnValue(observableOf(responseCacheEntry)); serviceASAny.requestService.getByUUID.and.returnValue(observableOf(responseCacheEntry)); serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectRD)); + serviceASAny.rdbService.buildFromRequestUUIDAndAwait.and.returnValue(observableOf(qaEventObjectRD)); }); - it('should proxy the call to dataservice.patch', () => { + it('should proxy the call to patchData.patch', () => { service.patchEvent(status, qualityAssuranceEventObjectMissingPid).subscribe( (res) => { - expect(serviceASAny.dataService.patch).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid, operation); + expect(serviceASAny.patchData.patch).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingPid, operation); } ); }); @@ -202,10 +203,10 @@ describe('QualityAssuranceEventRestService', () => { serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(qaEventObjectMissingProjectRD)); }); - it('should proxy the call to dataservice.postOnRelated', () => { + it('should call postOnRelated', () => { service.boundProject(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID).subscribe( (res) => { - expect(serviceASAny.dataService.postOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID); + expect(serviceASAny.postOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id, requestUUID); } ); }); @@ -226,10 +227,10 @@ describe('QualityAssuranceEventRestService', () => { serviceASAny.rdbService.buildFromRequestUUID.and.returnValue(observableOf(createSuccessfulRemoteDataObject({}))); }); - it('should proxy the call to dataservice.deleteOnRelated', () => { + it('should call deleteOnRelated', () => { service.removeProject(qualityAssuranceEventObjectMissingProjectFound.id).subscribe( (res) => { - expect(serviceASAny.dataService.deleteOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id); + expect(serviceASAny.deleteOnRelated).toHaveBeenCalledWith(qualityAssuranceEventObjectMissingProjectFound.id); } ); }); diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts index e4d13670a1..e83c9a8b43 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts @@ -1,73 +1,42 @@ -/* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; +import { find, take } from 'rxjs/operators'; +import { ReplaceOperation } from 'fast-json-patch'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; -import { RestResponse } from '../../../cache/response.models'; import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { dataService } from '../../../cache/builders/build-decorators'; +import { dataService } from '../../../data/base/data-service.decorator'; import { RequestService } from '../../../data/request.service'; -import { ChangeAnalyzer } from '../../../data/change-analyzer'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; import { QualityAssuranceEventObject } from '../models/quality-assurance-event.model'; import { QUALITY_ASSURANCE_EVENT_OBJECT } from '../models/quality-assurance-event-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; -import { ReplaceOperation } from 'fast-json-patch'; import { NoContent } from '../../../shared/NoContent.model'; -import {CoreState} from '../../../core-state.model'; -import {FindListOptions} from '../../../data/find-list-options.model'; - - -/** - * A private DataService implementation to delegate specific methods to. - */ -class DataServiceImpl extends DataService { - /** - * The REST endpoint. - */ - protected linkPath = 'qualityassuranceevents'; - - /** - * Initialize service variables - * @param {RequestService} requestService - * @param {RemoteDataBuildService} rdbService - * @param {Store} store - * @param {ObjectCacheService} objectCache - * @param {HALEndpointService} halService - * @param {NotificationsService} notificationsService - * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator - */ - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected store: Store, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: ChangeAnalyzer) { - super(); - } -} +import { FindListOptions } from '../../../data/find-list-options.model'; +import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; +import { CreateData, CreateDataImpl } from '../../../data/base/create-data'; +import { PatchData, PatchDataImpl } from '../../../data/base/patch-data'; +import { DeleteData, DeleteDataImpl } from '../../../data/base/delete-data'; +import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; +import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { hasValue } from '../../../../shared/empty.util'; +import { DeleteByIDRequest, PostRequest } from '../../../data/request.models'; /** * The service handling all Quality Assurance topic REST requests. */ @Injectable() @dataService(QUALITY_ASSURANCE_EVENT_OBJECT) -export class QualityAssuranceEventRestService { - /** - * A private DataService implementation to delegate specific methods to. - */ - private dataService: DataServiceImpl; +export class QualityAssuranceEventRestService extends IdentifiableDataService { + + private createData: CreateData; + private searchData: SearchData; + private patchData: PatchData; + private deleteData: DeleteData; /** * Initialize service variables @@ -76,7 +45,6 @@ export class QualityAssuranceEventRestService { * @param {ObjectCacheService} objectCache * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService - * @param {HttpClient} http * @param {DefaultChangeAnalyzer} comparator */ constructor( @@ -85,9 +53,13 @@ export class QualityAssuranceEventRestService { protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + protected comparator: DefaultChangeAnalyzer + ) { + super('qualityassuranceevents', requestService, rdbService, objectCache, halService); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, comparator, this.responseMsToLive, this.constructIdEndpoint); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } /** @@ -109,14 +81,14 @@ export class QualityAssuranceEventRestService { fieldValue: topic } ]; - return this.dataService.searchBy('findByTopic', options, true, true, ...linksToFollow); + return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow); } /** * Clear findByTopic requests from cache */ public clearFindByTopicRequests() { - this.requestService.removeByHrefSubstring('findByTopic'); + this.requestService.setStaleByHrefSubstring('findByTopic'); } /** @@ -130,7 +102,7 @@ export class QualityAssuranceEventRestService { * The Quality Assurance event. */ public getEvent(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { - return this.dataService.findById(id, true, true, ...linksToFollow); + return this.findById(id, true, true, ...linksToFollow); } /** @@ -153,7 +125,7 @@ export class QualityAssuranceEventRestService { value: status } ]; - return this.dataService.patch(dso, operation); + return this.patchData.patch(dso, operation); } /** @@ -167,7 +139,7 @@ export class QualityAssuranceEventRestService { * The REST response. */ public boundProject(itemId: string, projectId: string): Observable> { - return this.dataService.postOnRelated(itemId, projectId); + return this.postOnRelated(itemId, projectId); } /** @@ -179,6 +151,53 @@ export class QualityAssuranceEventRestService { * The REST response. */ public removeProject(itemId: string): Observable> { - return this.dataService.deleteOnRelated(itemId); + return this.deleteOnRelated(itemId); + } + + /** + * Perform a delete operation on an endpoint related item. Ex.: endpoint//related + * @param objectId The item id + * @return the RestResponse as an Observable + */ + private deleteOnRelated(objectId: string): Observable> { + const requestId = this.requestService.generateRequestId(); + + const hrefObs = this.getIDHrefObs(objectId); + + hrefObs.pipe( + find((href: string) => hasValue(href)), + ).subscribe((href: string) => { + const request = new DeleteByIDRequest(requestId, href + '/related', objectId); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + }); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + /** + * Perform a post on an endpoint related item with ID. Ex.: endpoint//related?item= + * @param objectId The item id + * @param relatedItemId The related item Id + * @param body The optional POST body + * @return the RestResponse as an Observable + */ + private postOnRelated(objectId: string, relatedItemId: string, body?: any) { + const requestId = this.requestService.generateRequestId(); + const hrefObs = this.getIDHrefObs(objectId); + + hrefObs.pipe( + take(1) + ).subscribe((href: string) => { + const request = new PostRequest(requestId, href + '/related?item=' + relatedItemId, body); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + }); + + return this.rdbService.buildFromRequestUUID(requestId); } } diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts index dc90b581cb..f4a2d81b36 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts @@ -17,8 +17,8 @@ import { qualityAssuranceSourceObjectMoreAbstract, qualityAssuranceSourceObjectMorePid } from '../../../../shared/mocks/notifications.mock'; -import {RequestEntry} from '../../../data/request-entry.model'; -import {QualityAssuranceSourceRestService} from './quality-assurance-source-rest.service'; +import { RequestEntry } from '../../../data/request-entry.model'; +import { QualityAssuranceSourceRestService } from './quality-assurance-source-rest.service'; describe('QualityAssuranceSourceRestService', () => { let scheduler: TestScheduler; @@ -36,7 +36,7 @@ describe('QualityAssuranceSourceRestService', () => { const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); - const array = [ qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract ]; + const array = [qualityAssuranceSourceObjectMorePid, qualityAssuranceSourceObjectMoreAbstract]; const paginatedList = buildPaginatedList(pageInfo, array); const qaSourceObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceSourceObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); @@ -65,7 +65,7 @@ describe('QualityAssuranceSourceRestService', () => { objectCache = {} as ObjectCacheService; halService = jasmine.createSpyObj('halService', { - getEndpoint: cold('a|', { a: endpointURL }) + getEndpoint: cold('a|', { a: endpointURL }) }); notificationsService = {} as NotificationsService; @@ -77,20 +77,18 @@ describe('QualityAssuranceSourceRestService', () => { rdbService, objectCache, halService, - notificationsService, - http, - comparator + notificationsService ); - spyOn((service as any).dataService, 'findAllByHref').and.callThrough(); - spyOn((service as any).dataService, 'findByHref').and.callThrough(); + spyOn((service as any), 'findListByHref').and.callThrough(); + spyOn((service as any), 'findByHref').and.callThrough(); }); describe('getSources', () => { - it('should proxy the call to dataservice.findAllByHref', (done) => { + it('should call findListByHref', (done) => { service.getSources().subscribe( (res) => { - expect((service as any).dataService.findAllByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + expect((service as any).findListByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); } ); done(); @@ -106,10 +104,10 @@ describe('QualityAssuranceSourceRestService', () => { }); describe('getSource', () => { - it('should proxy the call to dataservice.findByHref', (done) => { + it('should call findByHref', (done) => { service.getSource(qualityAssuranceSourceObjectMorePid.id).subscribe( (res) => { - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceSourceObjectMorePid.id, true, true); + expect((service as any).findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceSourceObjectMorePid.id, true, true); } ); done(); diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts index 05d2ba4ae6..8f16347b25 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts @@ -1,7 +1,5 @@ /* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; @@ -10,62 +8,22 @@ import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { dataService } from '../../../cache/builders/build-decorators'; +import { dataService } from '../../../data/base/data-service.decorator'; import { RequestService } from '../../../data/request.service'; -import { DataService } from '../../../data/data.service'; -import { ChangeAnalyzer } from '../../../data/change-analyzer'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; import { QualityAssuranceSourceObject } from '../models/quality-assurance-source.model'; import { QUALITY_ASSURANCE_SOURCE_OBJECT } from '../models/quality-assurance-source-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; -import {CoreState} from '../../../core-state.model'; -import {FindListOptions} from '../../../data/find-list-options.model'; - -/** - * A private DataService implementation to delegate specific methods to. - */ -class DataServiceImpl extends DataService { - /** - * The REST endpoint. - */ - protected linkPath = 'qualityassurancesources'; - - /** - * Initialize service variables - * @param {RequestService} requestService - * @param {RemoteDataBuildService} rdbService - * @param {Store} store - * @param {ObjectCacheService} objectCache - * @param {HALEndpointService} halService - * @param {NotificationsService} notificationsService - * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator - */ - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected store: Store, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: ChangeAnalyzer) { - super(); - } -} +import { FindListOptions } from '../../../data/find-list-options.model'; +import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; /** * The service handling all Quality Assurance source REST requests. */ @Injectable() @dataService(QUALITY_ASSURANCE_SOURCE_OBJECT) -export class QualityAssuranceSourceRestService { - /** - * A private DataService implementation to delegate specific methods to. - */ - private dataService: DataServiceImpl; +export class QualityAssuranceSourceRestService extends IdentifiableDataService { /** * Initialize service variables @@ -74,18 +32,15 @@ export class QualityAssuranceSourceRestService { * @param {ObjectCacheService} objectCache * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService - * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + protected notificationsService: NotificationsService + ) { + super('qualityassurancesources', requestService, rdbService, objectCache, halService); } /** @@ -99,9 +54,9 @@ export class QualityAssuranceSourceRestService { * The list of Quality Assurance source. */ public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'qualityassurancesources').pipe( + return this.getBrowseEndpoint(options).pipe( take(1), - mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), + mergeMap((href: string) => this.findListByHref(href, options, true, true, ...linksToFollow)), ); } @@ -124,9 +79,9 @@ export class QualityAssuranceSourceRestService { */ public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'qualityassurancesources').pipe( + return this.getBrowseEndpoint(options, 'qualityassurancesources').pipe( take(1), - mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) + mergeMap((href: string) => this.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); } } diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts index babc9d83b3..d16ccbdb00 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts @@ -18,7 +18,7 @@ import { qualityAssuranceTopicObjectMoreAbstract, qualityAssuranceTopicObjectMorePid } from '../../../../shared/mocks/notifications.mock'; -import {RequestEntry} from '../../../data/request-entry.model'; +import { RequestEntry } from '../../../data/request-entry.model'; describe('QualityAssuranceTopicRestService', () => { let scheduler: TestScheduler; @@ -36,7 +36,7 @@ describe('QualityAssuranceTopicRestService', () => { const requestUUID = '8b3c913a-5a4b-438b-9181-be1a5b4a1c8a'; const pageInfo = new PageInfo(); - const array = [ qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract ]; + const array = [qualityAssuranceTopicObjectMorePid, qualityAssuranceTopicObjectMoreAbstract]; const paginatedList = buildPaginatedList(pageInfo, array); const qaTopicObjectRD = createSuccessfulRemoteDataObject(qualityAssuranceTopicObjectMorePid); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); @@ -65,7 +65,7 @@ describe('QualityAssuranceTopicRestService', () => { objectCache = {} as ObjectCacheService; halService = jasmine.createSpyObj('halService', { - getEndpoint: cold('a|', { a: endpointURL }) + getEndpoint: cold('a|', { a: endpointURL }) }); notificationsService = {} as NotificationsService; @@ -77,20 +77,18 @@ describe('QualityAssuranceTopicRestService', () => { rdbService, objectCache, halService, - notificationsService, - http, - comparator + notificationsService ); - spyOn((service as any).dataService, 'findAllByHref').and.callThrough(); - spyOn((service as any).dataService, 'findByHref').and.callThrough(); + spyOn((service as any), 'findListByHref').and.callThrough(); + spyOn((service as any), 'findByHref').and.callThrough(); }); describe('getTopics', () => { - it('should proxy the call to dataservice.findAllByHref', (done) => { + it('should call findListByHref', (done) => { service.getTopics().subscribe( (res) => { - expect((service as any).dataService.findAllByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + expect((service as any).findListByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); } ); done(); @@ -106,10 +104,10 @@ describe('QualityAssuranceTopicRestService', () => { }); describe('getTopic', () => { - it('should proxy the call to dataservice.findByHref', (done) => { + it('should call findByHref', (done) => { service.getTopic(qualityAssuranceTopicObjectMorePid.id).subscribe( (res) => { - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceTopicObjectMorePid.id, true, true); + expect((service as any).findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceTopicObjectMorePid.id, true, true); } ); done(); diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts index 86942a7b5b..2ab715bbbe 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts @@ -1,7 +1,4 @@ -/* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; @@ -10,62 +7,22 @@ import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { dataService } from '../../../cache/builders/build-decorators'; import { RequestService } from '../../../data/request.service'; -import { DataService } from '../../../data/data.service'; -import { ChangeAnalyzer } from '../../../data/change-analyzer'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { RemoteData } from '../../../data/remote-data'; import { QualityAssuranceTopicObject } from '../models/quality-assurance-topic.model'; -import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../data/paginated-list.model'; -import {CoreState} from '../../../core-state.model'; -import {FindListOptions} from '../../../data/find-list-options.model'; - -/** - * A private DataService implementation to delegate specific methods to. - */ -class DataServiceImpl extends DataService { - /** - * The REST endpoint. - */ - protected linkPath = 'qualityassurancetopics'; - - /** - * Initialize service variables - * @param {RequestService} requestService - * @param {RemoteDataBuildService} rdbService - * @param {Store} store - * @param {ObjectCacheService} objectCache - * @param {HALEndpointService} halService - * @param {NotificationsService} notificationsService - * @param {HttpClient} http - * @param {ChangeAnalyzer} comparator - */ - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected store: Store, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: ChangeAnalyzer) { - super(); - } -} +import { FindListOptions } from '../../../data/find-list-options.model'; +import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; +import { dataService } from '../../../data/base/data-service.decorator'; +import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; /** * The service handling all Quality Assurance topic REST requests. */ @Injectable() @dataService(QUALITY_ASSURANCE_TOPIC_OBJECT) -export class QualityAssuranceTopicRestService { - /** - * A private DataService implementation to delegate specific methods to. - */ - private dataService: DataServiceImpl; +export class QualityAssuranceTopicRestService extends IdentifiableDataService { /** * Initialize service variables @@ -74,18 +31,15 @@ export class QualityAssuranceTopicRestService { * @param {ObjectCacheService} objectCache * @param {HALEndpointService} halService * @param {NotificationsService} notificationsService - * @param {HttpClient} http - * @param {DefaultChangeAnalyzer} comparator */ constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + protected notificationsService: NotificationsService + ) { + super('qualityassurancetopics', requestService, rdbService, objectCache, halService); } /** @@ -99,9 +53,9 @@ export class QualityAssuranceTopicRestService { * The list of Quality Assurance topics. */ public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.dataService.getBrowseEndpoint(options, 'qualityassurancetopics').pipe( + return this.getBrowseEndpoint(options).pipe( take(1), - mergeMap((href: string) => this.dataService.findAllByHref(href, options, true, true, ...linksToFollow)), + mergeMap((href: string) => this.findListByHref(href, options, true, true, ...linksToFollow)), ); } @@ -124,9 +78,9 @@ export class QualityAssuranceTopicRestService { */ public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { const options = {}; - return this.dataService.getBrowseEndpoint(options, 'qualityassurancetopics').pipe( + return this.getBrowseEndpoint(options).pipe( take(1), - mergeMap((href: string) => this.dataService.findByHref(href + '/' + id, true, true, ...linksToFollow)) + mergeMap((href: string) => this.findByHref(href + '/' + id, true, true, ...linksToFollow)) ); } } From 58db3c7b0efed5aee9e1ec5940a2c306927d71cd Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 10 Nov 2022 18:28:10 +0100 Subject: [PATCH 020/153] [CST-5337] remove deprecated @Effect decorators --- .../quality-assurance-source.effects.ts | 38 +++++++++++-------- .../quality-assurance-topics.effects.ts | 25 +++++++----- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts index 2d758d2625..b1514171aa 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts @@ -1,21 +1,26 @@ import { Injectable } from '@angular/core'; + import { Store } from '@ngrx/store'; -import { Actions, Effect, ofType } from '@ngrx/effects'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; import { TranslateService } from '@ngx-translate/core'; import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; import { of as observableOf } from 'rxjs'; -import { - AddSourceAction, - QualityAssuranceSourceActionTypes, - RetrieveAllSourceAction, - RetrieveAllSourceErrorAction, -} from './quality-assurance-source.actions'; -import { QualityAssuranceSourceObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; +import { + AddSourceAction, + QualityAssuranceSourceActionTypes, + RetrieveAllSourceAction, + RetrieveAllSourceErrorAction, +} from './quality-assurance-source.actions'; +import { + QualityAssuranceSourceObject +} from '../../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { QualityAssuranceSourceService } from './quality-assurance-source.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { QualityAssuranceSourceRestService } from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; +import { + QualityAssuranceSourceRestService +} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; /** * Provides effect methods for the Quality Assurance source actions. @@ -26,7 +31,7 @@ export class QualityAssuranceSourceEffects { /** * Retrieve all Quality Assurance source managing pagination and errors. */ - @Effect() retrieveAllSource$ = this.actions$.pipe( + retrieveAllSource$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE), withLatestFrom(this.store$), switchMap(([action, currentState]: [RetrieveAllSourceAction, any]) => { @@ -45,27 +50,27 @@ export class QualityAssuranceSourceEffects { }) ); }) - ); + )); /** * Show a notification on error. */ - @Effect({ dispatch: false }) retrieveAllSourceErrorAction$ = this.actions$.pipe( + retrieveAllSourceErrorAction$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceSourceActionTypes.RETRIEVE_ALL_SOURCE_ERROR), tap(() => { this.notificationsService.error(null, this.translate.get('quality-assurance.source.error.service.retrieve')); }) - ); + ), { dispatch: false }); /** * Clear find all source requests from cache. */ - @Effect({ dispatch: false }) addSourceAction$ = this.actions$.pipe( + addSourceAction$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceSourceActionTypes.ADD_SOURCE), tap(() => { this.qualityAssuranceSourceDataService.clearFindAllSourceRequests(); }) - ); + ), { dispatch: false }); /** * Initialize the effect class variables. @@ -83,5 +88,6 @@ export class QualityAssuranceSourceEffects { private notificationsService: NotificationsService, private qualityAssuranceSourceService: QualityAssuranceSourceService, private qualityAssuranceSourceDataService: QualityAssuranceSourceRestService - ) { } + ) { + } } diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts index 880a2d2318..11d7e11555 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts @@ -1,21 +1,26 @@ import { Injectable } from '@angular/core'; + import { Store } from '@ngrx/store'; -import { Actions, Effect, ofType } from '@ngrx/effects'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; import { TranslateService } from '@ngx-translate/core'; import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; import { of as observableOf } from 'rxjs'; + import { AddTopicsAction, QualityAssuranceTopicActionTypes, RetrieveAllTopicsAction, RetrieveAllTopicsErrorAction, } from './quality-assurance-topics.actions'; - -import { QualityAssuranceTopicObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-topic.model'; +import { + QualityAssuranceTopicObject +} from '../../../core/suggestion-notifications/qa/models/quality-assurance-topic.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { QualityAssuranceTopicRestService } from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; +import { + QualityAssuranceTopicRestService +} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; /** * Provides effect methods for the Quality Assurance topics actions. @@ -26,7 +31,7 @@ export class QualityAssuranceTopicsEffects { /** * Retrieve all Quality Assurance topics managing pagination and errors. */ - @Effect() retrieveAllTopics$ = this.actions$.pipe( + retrieveAllTopics$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS), withLatestFrom(this.store$), switchMap(([action, currentState]: [RetrieveAllTopicsAction, any]) => { @@ -45,27 +50,27 @@ export class QualityAssuranceTopicsEffects { }) ); }) - ); + )); /** * Show a notification on error. */ - @Effect({ dispatch: false }) retrieveAllTopicsErrorAction$ = this.actions$.pipe( + retrieveAllTopicsErrorAction$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceTopicActionTypes.RETRIEVE_ALL_TOPICS_ERROR), tap(() => { this.notificationsService.error(null, this.translate.get('quality-assurance.topic.error.service.retrieve')); }) - ); + ), { dispatch: false }); /** * Clear find all topics requests from cache. */ - @Effect({ dispatch: false }) addTopicsAction$ = this.actions$.pipe( + addTopicsAction$ = createEffect(() => this.actions$.pipe( ofType(QualityAssuranceTopicActionTypes.ADD_TOPICS), tap(() => { this.qualityAssuranceTopicDataService.clearFindAllTopicsRequests(); }) - ); + ), { dispatch: false }); /** * Initialize the effect class variables. From 3188374800c46978f530cf2c5aa141c33e393475 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Nov 2022 12:56:57 +0100 Subject: [PATCH 021/153] [CST-5537] Fix issues and refactoring in order to remove nested subscriptions --- ...ty-assurance-event-object.resource-type.ts | 2 +- .../quality-assurance-events.component.html | 56 +++--- .../quality-assurance-events.component.scss | 11 +- ...quality-assurance-events.component.spec.ts | 54 +++--- .../quality-assurance-events.component.ts | 168 +++++++++--------- .../quality-assurance-source.component.html | 4 +- .../quality-assurance-source.service.ts | 20 ++- .../quality-assurance-topics.component.html | 4 +- .../quality-assurance-topics.component.ts | 12 +- .../quality-assurance-topics.service.ts | 15 +- .../suggestion-notifications.module.ts | 4 +- 11 files changed, 196 insertions(+), 154 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/models/quality-assurance-event-object.resource-type.ts b/src/app/core/suggestion-notifications/qa/models/quality-assurance-event-object.resource-type.ts index 2dedc84d08..84aff6ba2c 100644 --- a/src/app/core/suggestion-notifications/qa/models/quality-assurance-event-object.resource-type.ts +++ b/src/app/core/suggestion-notifications/qa/models/quality-assurance-event-object.resource-type.ts @@ -6,4 +6,4 @@ import { ResourceType } from '../../../shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const QUALITY_ASSURANCE_EVENT_OBJECT = new ResourceType('qaevent'); +export const QUALITY_ASSURANCE_EVENT_OBJECT = new ResourceType('qualityassuranceevent'); diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html index 209b2cde27..7f1b166d24 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html @@ -1,21 +1,23 @@
-

{{'notifications.events.title'| translate}}

-

{{'quality-assurance.events.description'| translate}}

-

- - - {{'quality-assurance.events.back' | translate}} - -

+

+
+ {{'notifications.events.title'| translate}} + + + {{'quality-assurance.events.back' | translate}} + +
+

+
-

+

{{'quality-assurance.events.topic' | translate}} {{this.showTopic}} -

+ @@ -25,8 +27,7 @@ [sortOptions]="paginationSortConfig" (paginationChange)="getQualityAssuranceEvents()"> - - + @@ -34,11 +35,15 @@
{{'notifications.broker.table.topic' | translate}}{{'notifications.broker.table.last-event' | translate}}{{'notifications.broker.table.actions' | translate}}{{'quality-assurance.table.topic' | translate}}{{'quality-assurance.table.last-event' | translate}}{{'quality-assurance.table.actions' | translate}}
-
+
- - -
- - - - - + + + + + @@ -51,7 +56,7 @@ {{eventElement.title}} diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index b3e686c012..704a92d0f9 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -7,10 +7,9 @@ import { of as observableOf, Subscription, BehaviorSubject, - combineLatest as observableCombineLatest, - ObservedValueOf, + combineLatest as observableCombineLatest } from 'rxjs'; -import { defaultIfEmpty, map, mergeMap, switchMap, take } from 'rxjs/operators'; +import { defaultIfEmpty, map, switchMap, take } from 'rxjs/operators'; import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; @@ -18,10 +17,8 @@ import { GroupDataService } from '../../../../core/eperson/group-data.service'; import { EPerson } from '../../../../core/eperson/models/eperson.model'; import { Group } from '../../../../core/eperson/models/group.model'; import { - getFirstSucceededRemoteData, getFirstCompletedRemoteData, - getAllCompletedRemoteData, - getRemoteDataPayload + getAllCompletedRemoteData } from '../../../../core/shared/operators'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; @@ -191,14 +188,9 @@ export class MembersListComponent implements OnInit, OnDestroy { }), switchMap((epersonListRD: RemoteData>) => { const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => { - const dto$: Observable = observableCombineLatest( - this.isMemberOfGroup(member), (isMember: ObservedValueOf>) => { - const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); - epersonDtoModel.eperson = member; - epersonDtoModel.memberOfGroup = isMember; - return epersonDtoModel; - }); - return dto$; + const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); + epersonDtoModel.eperson = member; + return observableOf(epersonDtoModel); })]); return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => { return buildPaginatedList(epersonListRD.payload.pageInfo, dtos); @@ -209,29 +201,6 @@ export class MembersListComponent implements OnInit, OnDestroy { })); } - /** - * Whether the given ePerson is a member of the group currently being edited - * @param possibleMember EPerson that is a possible member (being tested) of the group currently being edited - */ - isMemberOfGroup(possibleMember: EPerson): Observable { - return this.groupDataService.getActiveGroup().pipe(take(1), - mergeMap((group: Group) => { - if (group != null) { - return this.ePersonDataService.findListByHref(group._links.epersons.href, { - currentPage: 1, - elementsPerPage: 9999 - }) - .pipe( - getFirstSucceededRemoteData(), - getRemoteDataPayload(), - map((listEPeopleInGroup: PaginatedList) => listEPeopleInGroup.page.filter((ePersonInList: EPerson) => ePersonInList.id === possibleMember.id)), - map((epeople: EPerson[]) => epeople.length > 0)); - } else { - return observableOf(false); - } - })); - } - /** * Unsubscribe from a subscription if it's still subscribed, and remove it from the map of * active subscriptions @@ -251,7 +220,6 @@ export class MembersListComponent implements OnInit, OnDestroy { * @param ePerson EPerson we want to delete as member from group that is currently being edited */ deleteMemberFromGroup(ePerson: EpersonDtoModel) { - ePerson.memberOfGroup = false; this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { const response = this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson.eperson); @@ -267,7 +235,6 @@ export class MembersListComponent implements OnInit, OnDestroy { * @param ePerson EPerson we want to add as member to group that is currently being edited */ addMemberToGroup(ePerson: EpersonDtoModel) { - ePerson.memberOfGroup = true; this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { const response = this.groupDataService.addMemberToGroup(activeGroup, ePerson.eperson); @@ -321,14 +288,9 @@ export class MembersListComponent implements OnInit, OnDestroy { }), switchMap((epersonListRD: RemoteData>) => { const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => { - const dto$: Observable = observableCombineLatest( - this.isMemberOfGroup(member), (isMember: ObservedValueOf>) => { - const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); - epersonDtoModel.eperson = member; - epersonDtoModel.memberOfGroup = isMember; - return epersonDtoModel; - }); - return dto$; + const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); + epersonDtoModel.eperson = member; + return observableOf(epersonDtoModel); })]); return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => { return buildPaginatedList(epersonListRD.payload.pageInfo, dtos); From bffae54b10ea7a4c883cb25512f9c9ac4949f97a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 25 Sep 2023 16:34:04 -0500 Subject: [PATCH 040/153] Remove unnecessary EpersonDtoModel. Rework code and tests to use EPerson instead. --- .../members-list/members-list.component.html | 48 +++--- .../members-list.component.spec.ts | 156 ++++++++---------- .../members-list/members-list.component.ts | 62 +++---- 3 files changed, 116 insertions(+), 150 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html index b90a3e405b..0f5010e08e 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html @@ -37,10 +37,10 @@ - @@ -55,24 +55,24 @@ - - + + - - + + @@ -106,8 +105,7 @@ diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 5d97dcade8..99ee9827e8 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -68,9 +68,6 @@ describe('MembersListComponent', () => { clearLinkRequests() { // empty }, - getEPeoplePageRouterLink(): string { - return '/access-control/epeople'; - } }; groupsDataServiceStub = { activeGroup: activeGroup, diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index feb90b52b3..6129d4d02d 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -23,6 +23,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { getEPersonEditRoute } from '../../../access-control-routing-paths'; /** * Keys to keep track of specific subscriptions @@ -131,6 +132,8 @@ export class MembersListComponent implements OnInit, OnDestroy { // current active group being edited groupBeingEdited: Group; + readonly getEPersonEditRoute = getEPersonEditRoute; + constructor( protected groupDataService: GroupDataService, public ePersonDataService: EPersonDataService, diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index fb8b8bc9b0..a85d471e7d 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -34,7 +34,7 @@ import { PatchData, PatchDataImpl } from '../data/base/patch-data'; import { DeleteData, DeleteDataImpl } from '../data/base/delete-data'; import { RestRequestMethod } from '../data/rest-request-method'; import { dataService } from '../data/base/data-service.decorator'; -import { getEPersonEditRoute, getEPersonsRoute } from '../../access-control/access-control-routing-paths'; +import { getEPersonEditRoute } from '../../access-control/access-control-routing-paths'; const ePeopleRegistryStateSelector = (state: AppState) => state.epeopleRegistry; const editEPersonSelector = createSelector(ePeopleRegistryStateSelector, (ePeopleRegistryState: EPeopleRegistryState) => ePeopleRegistryState.editEPerson); @@ -313,13 +313,6 @@ export class EPersonDataService extends IdentifiableDataService impleme return getEPersonEditRoute(ePerson.id); } - /** - * Get EPeople admin page - */ - public getEPeoplePageRouterLink(): string { - return getEPersonsRoute(); - } - /** * Create a new EPerson using a token * @param eperson diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts index bcbeef5683..91e200e85d 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts @@ -72,9 +72,6 @@ describe('ReviewersListComponent', () => { clearLinkRequests() { // empty }, - getEPeoplePageRouterLink(): string { - return '/access-control/epeople'; - } }; groupsDataServiceStub = { activeGroup: activeGroup, From e229be44d6450f9c50ed2d53f4b5d9cb7939fcd1 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 25 Nov 2023 14:21:57 +0100 Subject: [PATCH 072/153] Added missing aria labels to edit bitstream tab --- .../item-bitstreams/item-bitstreams.component.html | 7 +++++++ .../item-edit-bitstream-bundle.component.html | 1 + 2 files changed, 8 insertions(+) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 4cb9577fcb..bd4c9334ad 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -1,21 +1,25 @@
diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts index 88efd2a711..9522be29ce 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -143,7 +143,7 @@ describe('AdminSidebarComponent', () => { describe('when the collapse link is clicked', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); - const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle > a')); + const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle > button')); sidebarToggler.triggerEventHandler('click', { preventDefault: () => {/**/ } diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 13d84e6e2e..d4c0cd1a37 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -62,10 +62,11 @@ {{ 'footer.link.lyrasis' | translate}}

-
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7392b3da7a..f6630d594d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3242,6 +3242,8 @@ "process.overview.delete": "Delete {{count}} processes", + "process.overview.delete-process": "Delete process", + "process.overview.delete.clear": "Clear delete selection", "process.overview.delete.processing": "{{count}} process(es) are being deleted. Please wait for the deletion to fully complete. Note that this can take a while.", From 52c0977489063689dba99caf004e4120a85e9fc9 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Tue, 28 Nov 2023 00:20:35 +0100 Subject: [PATCH 083/153] Fix Create a new process page accessibility issues - Added missing aria-label to delete buttons - Moved hardcoded translation to translation files - Fix color contrast issues on buttons - Fix minor alignment issues - Added missing aria labels to input and select elements --- .../process-page/form/process-form.component.html | 6 +++--- .../parameter-select/parameter-select.component.html | 12 ++++++++---- .../parameter-select.component.spec.ts | 7 +++++-- .../boolean-value-input.component.html | 2 +- .../boolean-value-input.component.spec.ts | 5 ++++- .../date-value-input/date-value-input.component.html | 4 ++-- .../date-value-input/date-value-input.component.scss | 5 +++++ .../file-value-input/file-value-input.component.html | 2 +- .../string-value-input.component.html | 4 ++-- .../string-value-input.component.scss | 5 +++++ src/assets/i18n/en.json5 | 8 ++++++++ 11 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/app/process-page/form/process-form.component.html b/src/app/process-page/form/process-form.component.html index ce6d62efec..c55592f3e7 100644 --- a/src/app/process-page/form/process-form.component.html +++ b/src/app/process-page/form/process-form.component.html @@ -3,12 +3,12 @@

{{headerKey | translate}}

-
+
- - + {{ 'process.new.cancel' | translate }} +
diff --git a/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.html b/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.html index 4bf06bbade..1f1559b50b 100644 --- a/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.html +++ b/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.html @@ -1,16 +1,20 @@ -
+
- - + +
diff --git a/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.spec.ts b/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.spec.ts index 56fece56b4..818a292e33 100644 --- a/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.spec.ts +++ b/src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.spec.ts @@ -1,5 +1,5 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; - +import { TranslateModule } from '@ngx-translate/core'; import { ParameterSelectComponent } from './parameter-select.component'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { FormsModule } from '@angular/forms'; @@ -33,7 +33,10 @@ describe('ParameterSelectComponent', () => { beforeEach(waitForAsync(() => { init(); TestBed.configureTestingModule({ - imports: [FormsModule], + imports: [ + FormsModule, + TranslateModule.forRoot(), + ], declarations: [ParameterSelectComponent], schemas: [NO_ERRORS_SCHEMA] }) diff --git a/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.html b/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.html index 914b331413..68171a23b2 100644 --- a/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.html +++ b/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.html @@ -1 +1 @@ - + diff --git a/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.spec.ts b/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.spec.ts index 38f119ad5b..76b01b8709 100644 --- a/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.spec.ts +++ b/src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.spec.ts @@ -1,5 +1,5 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - +import { TranslateModule } from '@ngx-translate/core'; import { BooleanValueInputComponent } from './boolean-value-input.component'; describe('BooleanValueInputComponent', () => { @@ -8,6 +8,9 @@ describe('BooleanValueInputComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + ], declarations: [BooleanValueInputComponent] }) .compileComponents(); diff --git a/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.html b/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.html index f367d3779f..4e77f4ed1b 100644 --- a/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.html +++ b/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.html @@ -1,6 +1,6 @@ - +
+ class="alert alert-danger validation-error mb-0">
{{'process.new.parameter.string.required' | translate}}
diff --git a/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.scss b/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.scss index e69de29bb2..8c6325f95a 100644 --- a/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.scss +++ b/src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.scss @@ -0,0 +1,5 @@ +:host { + display: flex; + flex-direction: column; + gap: calc(var(--bs-spacer) / 2); +} diff --git a/src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.html b/src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.html index cac3fbd82d..a741eacc86 100644 --- a/src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.html +++ b/src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.html @@ -1,5 +1,5 @@
diff --git a/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.html b/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.html index 0a2e9f0f92..45d8ed5d11 100644 --- a/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.html +++ b/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.html @@ -2,7 +2,7 @@
- +

{{'admin.registries.bitstream-formats.description' | translate}}

{{'admin.registries.bitstream-formats.create.new' | translate}}

@@ -19,7 +19,7 @@
{{'quality-assurance.event.table.trust' | translate}}{{'quality-assurance.event.table.publication' | translate}}{{'quality-assurance.event.table.details' | translate}}{{'quality-assurance.event.table.project-details' | translate}}{{'quality-assurance.event.table.actions' | translate}}{{'quality-assurance.event.table.trust' | translate}}{{'quality-assurance.event.table.publication' | translate}} + {{'quality-assurance.event.table.details' | translate}} + + {{'quality-assurance.event.table.project-details' | translate}} + {{'quality-assurance.event.table.actions' | translate}}
-

{{'quality-assurance.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

+

{{'quality-assurance.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

{{'quality-assurance.event.table.pidvalue' | translate}}
{{eventElement.event.message.value}} @@ -82,18 +87,19 @@ {{eventElement.event.message.title}}

- {{'quality-assurance.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
- {{'quality-assurance.event.table.code' | translate}} {{eventElement.event.message.code}}
- {{'quality-assurance.event.table.funder' | translate}} {{eventElement.event.message.funder}}
- {{'quality-assurance.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
- {{'quality-assurance.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}} + {{'quality-assurance.event.table.acronym' | translate}} {{eventElement.event.message.acronym}}
+ {{'quality-assurance.event.table.code' | translate}} {{eventElement.event.message.code}}
+ {{'quality-assurance.event.table.funder' | translate}} {{eventElement.event.message.funder}}
+ {{'quality-assurance.event.table.fundingProgram' | translate}} {{eventElement.event.message.fundingProgram}}
+ {{'quality-assurance.event.table.jurisdiction' | translate}} {{eventElement.event.message.jurisdiction}}


{{(eventElement.hasProject ? 'quality-assurance.event.project.found' : 'quality-assurance.event.project.notFound') | translate}} {{eventElement.handle}}
-
-
+
diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss index b38da70f37..29c16328c3 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.scss @@ -1,5 +1,12 @@ -.button-rows { - min-width: 200px; +.button-col, .trust-col { + width: 15%; +} + +.title-col { + width: 30%; +} +.content-col { + width: 40%; } .button-width { diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts index 41358b20a5..f0109f5f66 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts @@ -5,16 +5,18 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/t import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { of as observableOf } from 'rxjs'; -import { QualityAssuranceEventRestService } from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; +import { + QualityAssuranceEventRestService +} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; import { QualityAssuranceEventsComponent } from './quality-assurance-events.component'; import { getMockQualityAssuranceEventRestService, ItemMockPid10, ItemMockPid8, ItemMockPid9, + NotificationsMockDspaceObject, qualityAssuranceEventObjectMissingProjectFound, - qualityAssuranceEventObjectMissingProjectNotFound, - NotificationsMockDspaceObject + qualityAssuranceEventObjectMissingProjectNotFound } from '../../../shared/mocks/notifications.mock'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -22,10 +24,12 @@ import { getMockTranslateService } from '../../../shared/mocks/translate.service import { createTestComponent } from '../../../shared/testing/utils.test'; import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { QualityAssuranceEventObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; +import { + QualityAssuranceEventObject +} from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; import { QualityAssuranceEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; import { TestScheduler } from 'rxjs/testing'; -import { getTestScheduler } from 'jasmine-marbles'; +import { cold, getTestScheduler } from 'jasmine-marbles'; import { followLink } from '../../../shared/utils/follow-link-config.model'; import { PageInfo } from '../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; @@ -37,7 +41,7 @@ import { import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; -import {FindListOptions} from '../../../core/data/find-list-options.model'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; describe('QualityAssuranceEventsComponent test suite', () => { let fixture: ComponentFixture; @@ -156,18 +160,16 @@ describe('QualityAssuranceEventsComponent test suite', () => { compAsAny = null; }); - describe('setEventUpdated', () => { - it('should update events', () => { - const expected = [ - getQualityAssuranceEventData1(), - getQualityAssuranceEventData2() - ]; - scheduler.schedule(() => { - compAsAny.setEventUpdated(events); + describe('fetchEvents', () => { + it('should fetch events', () => { + const result = compAsAny.fetchEvents(events); + const expected = cold('(a|)', { + a: [ + getQualityAssuranceEventData1(), + getQualityAssuranceEventData2() + ] }); - scheduler.flush(); - - expect(comp.eventsUpdated$.value).toEqual(expected); + expect(result).toBeObservable(expected); }); }); @@ -229,7 +231,10 @@ describe('QualityAssuranceEventsComponent test suite', () => { describe('executeAction', () => { it('should call getQualityAssuranceEvents on 200 response from REST', () => { const action = 'ACCEPTED'; - spyOn(compAsAny, 'getQualityAssuranceEvents'); + spyOn(compAsAny, 'getQualityAssuranceEvents').and.returnValue(observableOf([ + getQualityAssuranceEventData1(), + getQualityAssuranceEventData2() + ])); qualityAssuranceEventRestServiceStub.patchEvent.and.returnValue(createSuccessfulRemoteDataObject$({})); scheduler.schedule(() => { @@ -279,7 +284,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { }); describe('getQualityAssuranceEvents', () => { - it('should call the "qualityAssuranceEventRestService.getEventsByTopic" to take data and "setEventUpdated" to populate eventData', () => { + it('should call the "qualityAssuranceEventRestService.getEventsByTopic" to take data and "fetchEvents" to populate eventData', () => { comp.paginationConfig = new PaginationComponentOptions(); comp.paginationConfig.currentPage = 1; comp.paginationConfig.pageSize = 20; @@ -292,7 +297,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { const pageInfo = new PageInfo({ elementsPerPage: comp.paginationConfig.pageSize, - totalElements: 0, + totalElements: 2, totalPages: 1, currentPage: comp.paginationConfig.currentPage }); @@ -303,10 +308,13 @@ describe('QualityAssuranceEventsComponent test suite', () => { const paginatedList = buildPaginatedList(pageInfo, array); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); qualityAssuranceEventRestServiceStub.getEventsByTopic.and.returnValue(observableOf(paginatedListRD)); - spyOn(compAsAny, 'setEventUpdated'); + spyOn(compAsAny, 'fetchEvents').and.returnValue(observableOf([ + getQualityAssuranceEventData1(), + getQualityAssuranceEventData2() + ])); scheduler.schedule(() => { - compAsAny.getQualityAssuranceEvents(); + compAsAny.getQualityAssuranceEvents().subscribe(); }); scheduler.flush(); @@ -315,7 +323,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { options, followLink('target'),followLink('related') ); - expect(compAsAny.setEventUpdated).toHaveBeenCalled(); + expect(compAsAny.fetchEvents).toHaveBeenCalled(); }); }); diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts index 9f33a02225..f78798ac25 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts @@ -3,8 +3,8 @@ import { ActivatedRoute } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; -import { BehaviorSubject, from, Observable, of as observableOf, Subscription } from 'rxjs'; -import { distinctUntilChanged, map, mergeMap, scan, switchMap, take } from 'rxjs/operators'; +import { BehaviorSubject, combineLatest, from, Observable, of, Subscription } from 'rxjs'; +import { distinctUntilChanged, last, map, mergeMap, scan, switchMap, take, tap } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -19,7 +19,7 @@ import { import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { Metadata } from '../../../core/shared/metadata.utils'; import { followLink } from '../../../shared/utils/follow-link-config.model'; -import { hasValue, isEmpty } from '../../../shared/empty.util'; +import { hasValue } from '../../../shared/empty.util'; import { ItemSearchResult } from '../../../shared/object-collection/shared/item-search-result.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { @@ -28,7 +28,6 @@ import { } from '../project-entry-import-modal/project-entry-import-modal.component'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { PaginationService } from '../../../core/pagination/pagination.service'; -import { combineLatest } from 'rxjs/internal/observable/combineLatest'; import { Item } from '../../../core/shared/item.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; @@ -65,7 +64,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * The total number of Quality Assurance events. * @type {Observable} */ - public totalElements$: Observable; + public totalElements$: BehaviorSubject = new BehaviorSubject(null); /** * The topic of the Quality Assurance events; suitable for displaying. * @type {string} @@ -86,11 +85,6 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @type {Observable} */ public isEventPageLoading: BehaviorSubject = new BehaviorSubject(false); - /** - * Contains the information about the loading status of the events inside the pagination component. - * @type {Observable} - */ - public isEventLoading: BehaviorSubject = new BehaviorSubject(false); /** * The modal reference. * @type {any} @@ -104,7 +98,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { /** * The FindListOptions object */ - protected defaultConfig: FindListOptions = Object.assign(new FindListOptions(), {sort: this.paginationSortConfig}); + protected defaultConfig: FindListOptions = Object.assign(new FindListOptions(), { sort: this.paginationSortConfig }); /** * Array to track all the component subscriptions. Useful to unsubscribe them with 'onDestroy'. * @type {Array} @@ -138,13 +132,17 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { this.activatedRoute.paramMap.pipe( map((params) => params.get('topicId')), - take(1) - ).subscribe((id: string) => { - const regEx = /!/g; - this.showTopic = id.replace(regEx, '/'); - this.topic = id; + take(1), + switchMap((id: string) => { + const regEx = /!/g; + this.showTopic = id.replace(regEx, '/'); + this.topic = id; + return this.getQualityAssuranceEvents(); + }) + ).subscribe((events: QualityAssuranceEventData[]) => { + console.log(events); + this.eventsUpdated$.next(events); this.isEventPageLoading.next(false); - this.getQualityAssuranceEvents(); }); } @@ -240,20 +238,25 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { public executeAction(action: string, eventData: QualityAssuranceEventData): void { eventData.isRunning = true; this.subs.push( - this.qualityAssuranceEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe(getFirstCompletedRemoteData()) - .subscribe((rd: RemoteData) => { - if (rd.isSuccess && rd.statusCode === 200) { + this.qualityAssuranceEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe( + getFirstCompletedRemoteData(), + switchMap((rd: RemoteData) => { + if (rd.hasSucceeded) { this.notificationsService.success( this.translateService.instant('quality-assurance.event.action.saved') ); - this.getQualityAssuranceEvents(); + return this.getQualityAssuranceEvents(); } else { this.notificationsService.error( this.translateService.instant('quality-assurance.event.action.error') ); + return of(this.eventsUpdated$.value); } - eventData.isRunning = false; }) + ).subscribe((events: QualityAssuranceEventData[]) => { + this.eventsUpdated$.next(events); + eventData.isRunning = false; + }) ); } @@ -274,7 +277,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { this.subs.push( this.qualityAssuranceEventRestService.boundProject(eventData.id, projectId).pipe(getFirstCompletedRemoteData()) .subscribe((rd: RemoteData) => { - if (rd.isSuccess) { + if (rd.hasSucceeded) { this.notificationsService.success( this.translateService.instant('quality-assurance.event.project.bounded') ); @@ -303,7 +306,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { this.subs.push( this.qualityAssuranceEventRestService.removeProject(eventData.id).pipe(getFirstCompletedRemoteData()) .subscribe((rd: RemoteData) => { - if (rd.isSuccess) { + if (rd.hasSucceeded) { this.notificationsService.success( this.translateService.instant('quality-assurance.event.project.removed') ); @@ -337,12 +340,11 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { return event.pidHref; } - /** * Dispatch the Quality Assurance events retrival. */ - public getQualityAssuranceEvents(): void { - this.paginationService.getFindListOptions(this.paginationConfig.id, this.defaultConfig).pipe( + public getQualityAssuranceEvents(): Observable { + return this.paginationService.getFindListOptions(this.paginationConfig.id, this.defaultConfig).pipe( distinctUntilChanged(), switchMap((options: FindListOptions) => this.qualityAssuranceEventRestService.getEventsByTopic( this.topic, @@ -350,16 +352,24 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { followLink('target'), followLink('related') )), getFirstCompletedRemoteData(), - ).subscribe((rd: RemoteData>) => { - if (rd.hasSucceeded) { - this.isEventLoading.next(false); - this.totalElements$ = observableOf(rd.payload.totalElements); - this.setEventUpdated(rd.payload.page); - } else { - throw new Error('Can\'t retrieve Quality Assurance events from the Broker events REST service'); - } - this.qualityAssuranceEventRestService.clearFindByTopicRequests(); - }); + switchMap((rd: RemoteData>) => { + if (rd.hasSucceeded) { + this.totalElements$.next(rd.payload.totalElements); + if (rd.payload.totalElements > 0) { + console.log(rd.payload.page); + return this.fetchEvents(rd.payload.page); + } else { + return of([]); + } + } else { + throw new Error('Can\'t retrieve Quality Assurance events from the Broker events REST service'); + } + }), + take(1), + tap(() => { + this.qualityAssuranceEventRestService.clearFindByTopicRequests(); + }) + ); } /** @@ -372,55 +382,47 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { } /** - * Set the project status for the Quality Assurance events. + * Fetch Quality Assurance events in order to build proper QualityAssuranceEventData object. * * @param {QualityAssuranceEventObject[]} events * the Quality Assurance event item + * @return array of QualityAssuranceEventData */ - protected setEventUpdated(events: QualityAssuranceEventObject[]): void { - if (isEmpty(events)) { - this.eventsUpdated$.next([]); - } else { - this.subs.push( - from(events).pipe( - mergeMap((event: QualityAssuranceEventObject) => { - const related$ = event.related.pipe( - getFirstCompletedRemoteData(), - ); - const target$ = event.target.pipe( - getFirstCompletedRemoteData() - ); - return combineLatest([related$, target$]).pipe( - map(([relatedItemRD, targetItemRD]: [RemoteData, RemoteData]) => { - const data: QualityAssuranceEventData = { - event: event, - id: event.id, - title: event.title, - hasProject: false, - projectTitle: null, - projectId: null, - handle: null, - reason: null, - isRunning: false, - target: (targetItemRD?.hasSucceeded) ? targetItemRD.payload : null, - }; - if (relatedItemRD?.hasSucceeded && relatedItemRD?.payload?.id) { - data.hasProject = true; - data.projectTitle = event.message.title; - data.projectId = relatedItemRD?.payload?.id; - data.handle = relatedItemRD?.payload?.handle; - } - return data; - }) - ); - }), - scan((acc: any, value: any) => [...acc, value], []), - take(events.length) - ).subscribe((eventsReduced) => { - this.eventsUpdated$.next(eventsReduced); - } - ) - ); - } + protected fetchEvents(events: QualityAssuranceEventObject[]): Observable { + return from(events).pipe( + mergeMap((event: QualityAssuranceEventObject) => { + const related$ = event.related.pipe( + getFirstCompletedRemoteData(), + ); + const target$ = event.target.pipe( + getFirstCompletedRemoteData() + ); + return combineLatest([related$, target$]).pipe( + map(([relatedItemRD, targetItemRD]: [RemoteData, RemoteData]) => { + const data: QualityAssuranceEventData = { + event: event, + id: event.id, + title: event.title, + hasProject: false, + projectTitle: null, + projectId: null, + handle: null, + reason: null, + isRunning: false, + target: (targetItemRD?.hasSucceeded) ? targetItemRD.payload : null, + }; + if (relatedItemRD?.hasSucceeded && relatedItemRD?.payload?.id) { + data.hasProject = true; + data.projectTitle = event.message.title; + data.projectId = relatedItemRD?.payload?.id; + data.handle = relatedItemRD?.payload?.handle; + } + return data; + }) + ); + }), + scan((acc: any, value: any) => [...acc, value], []), + last() + ); } } diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.html b/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.html index 20f4d4394a..0f6cf18402 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.html +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.component.html @@ -2,12 +2,12 @@

{{'quality-assurance.title'| translate}}

-

{{'quality-assurance.source.description'| translate}}

+
-

{{'quality-assurance.source'| translate}}

+

{{'quality-assurance.source'| translate}}

>) => !rd.isResponsePending), + getFirstCompletedRemoteData(), map((rd: RemoteData>) => { if (rd.hasSucceeded) { return rd.payload; diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html index fdc7d554a2..db8586f264 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html @@ -2,12 +2,12 @@

{{'quality-assurance.title'| translate}}

-

{{'quality-assurance.topics.description'| translate:{source: sourceId} }}

+ {{'quality-assurance.topics.description'| translate:{source: sourceId} }}
-

{{'quality-assurance.topics'| translate}}

+

{{'quality-assurance.topics'| translate}}

>) => !rd.isResponsePending), + getFirstCompletedRemoteData(), map((rd: RemoteData>) => { if (rd.hasSucceeded) { return rd.payload; diff --git a/src/app/suggestion-notifications/suggestion-notifications.module.ts b/src/app/suggestion-notifications/suggestion-notifications.module.ts index 90e73eb0be..e7e2272fff 100644 --- a/src/app/suggestion-notifications/suggestion-notifications.module.ts +++ b/src/app/suggestion-notifications/suggestion-notifications.module.ts @@ -30,6 +30,7 @@ import { const MODULES = [ CommonModule, SharedModule, + SearchModule, CoreModule.forRoot(), StoreModule.forFeature('suggestionNotifications', suggestionNotificationsReducers, storeModuleConfig as StoreConfig), EffectsModule.forFeature(suggestionNotificationsEffects), @@ -59,8 +60,7 @@ const PROVIDERS = [ @NgModule({ imports: [ - ...MODULES, - SearchModule + ...MODULES ], declarations: [ ...COMPONENTS, From 9fd4a1feee5a13fbe1c2909445c8cc61548f9b3e Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Nov 2022 13:07:21 +0100 Subject: [PATCH 022/153] [CST-5537] Add flag to hide the export button from search results when needed --- .../search-results.component.html | 2 +- .../search-results.component.ts | 5 +++++ .../themed-search-results.component.ts | 4 +++- src/app/shared/search/search.component.html | 21 ++++++++++--------- src/app/shared/search/search.component.ts | 5 +++++ .../shared/search/themed-search.component.ts | 4 +++- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/app/shared/search/search-results/search-results.component.html b/src/app/shared/search/search-results/search-results.component.html index 44498c3cab..dcb3465be4 100644 --- a/src/app/shared/search/search-results/search-results.component.html +++ b/src/app/shared/search/search-results/search-results.component.html @@ -1,6 +1,6 @@

{{ (configuration ? configuration + '.search.results.head' : 'search.results.head') | translate }}

- +
{ - protected inAndOutputNames: (keyof SearchResultsComponent & keyof this)[] = ['linkType', 'searchResults', 'searchConfig', 'sortConfig', 'viewMode', 'configuration', 'disableHeader', 'selectable', 'context', 'hidePaginationDetail', 'selectionConfig', 'contentChange', 'deselectObject', 'selectObject']; + protected inAndOutputNames: (keyof SearchResultsComponent & keyof this)[] = ['linkType', 'searchResults', 'searchConfig', 'showExport', 'sortConfig', 'viewMode', 'configuration', 'disableHeader', 'selectable', 'context', 'hidePaginationDetail', 'selectionConfig', 'contentChange', 'deselectObject', 'selectObject']; @Input() linkType: CollectionElementLinkType; @@ -29,6 +29,8 @@ export class ThemedSearchResultsComponent extends ThemedComponent
+ [searchConfig]="searchOptions$ | async" + [configuration]="(currentConfiguration$ | async)" + [disableHeader]="!searchEnabled" + [linkType]="linkType" + [context]="(currentContext$ | async)" + [selectable]="selectable" + [selectionConfig]="selectionConfig" + [showExport]="showExport" + (contentChange)="onContentChange($event)" + (deselectObject)="deselectObject.emit($event)" + (selectObject)="selectObject.emit($event)">
diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index c094e37ef2..b08b9a4b2a 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -117,6 +117,11 @@ export class SearchComponent implements OnInit { */ @Input() selectionConfig: SelectionConfig; + /** + * A boolean representing if show export button + */ + @Input() showExport = true; + /** * A boolean representing if show search sidebar button */ diff --git a/src/app/shared/search/themed-search.component.ts b/src/app/shared/search/themed-search.component.ts index 64a2befeb2..095357d74b 100644 --- a/src/app/shared/search/themed-search.component.ts +++ b/src/app/shared/search/themed-search.component.ts @@ -19,7 +19,7 @@ import { ListableObject } from '../object-collection/shared/listable-object.mode templateUrl: '../theme-support/themed.component.html', }) export class ThemedSearchComponent extends ThemedComponent { - protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = ['configurationList', 'context', 'configuration', 'fixedFilterQuery', 'useCachedVersionIfAvailable', 'inPlaceSearch', 'linkType', 'paginationId', 'searchEnabled', 'sideBarWidth', 'searchFormPlaceholder', 'selectable', 'selectionConfig', 'showSidebar', 'showViewModes', 'useUniquePageId', 'viewModeList', 'showScopeSelector', 'resultFound', 'deselectObject', 'selectObject', 'trackStatistics']; + protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = ['configurationList', 'context', 'configuration', 'fixedFilterQuery', 'useCachedVersionIfAvailable', 'inPlaceSearch', 'linkType', 'paginationId', 'searchEnabled', 'sideBarWidth', 'searchFormPlaceholder', 'selectable', 'selectionConfig', 'showExport', 'showSidebar', 'showViewModes', 'useUniquePageId', 'viewModeList', 'showScopeSelector', 'resultFound', 'deselectObject', 'selectObject', 'trackStatistics']; @Input() configurationList: SearchConfigurationOption[] = []; @@ -47,6 +47,8 @@ export class ThemedSearchComponent extends ThemedComponent { @Input() selectionConfig: SelectionConfig; + @Input() showExport = true; + @Input() showSidebar = true; @Input() showViewModes = true; From 79cd69fb9421d818b9e33731fc8eb2e47f49f3c7 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Nov 2022 13:07:52 +0100 Subject: [PATCH 023/153] [CST-5537] hide the export button from project search --- .../project-entry-import-modal.component.html | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html index 1090fd22fc..35b4b396a7 100644 --- a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html +++ b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html @@ -38,19 +38,20 @@
- - + +
From b8880091e6da2f5168255b8de8a55723cbcb0f94 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Nov 2022 14:41:50 +0100 Subject: [PATCH 024/153] [CST-5537] Fix lint --- .../admin-quality-assurance-source-page.component.ts | 2 +- src/app/shared/selector.util.ts | 2 +- .../project-entry-import-modal.component.ts | 3 +-- .../qa/source/quality-assurance-source.service.spec.ts | 7 ++++--- .../qa/topics/quality-assurance-topics.component.spec.ts | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts index 20d0356d5f..447e5a2e55 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts +++ b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; /** * Component for the page that show the QA sources. diff --git a/src/app/shared/selector.util.ts b/src/app/shared/selector.util.ts index 97ddb9af7d..7ea73347b7 100644 --- a/src/app/shared/selector.util.ts +++ b/src/app/shared/selector.util.ts @@ -1,4 +1,4 @@ -import { createSelector, MemoizedSelector, Selector } from '@ngrx/store'; +import { createSelector, MemoizedSelector } from '@ngrx/store'; import { hasValue } from './empty.util'; /** diff --git a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts index bde97f364c..1a43f59a1f 100644 --- a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts +++ b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts @@ -13,9 +13,8 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SearchService } from '../../../core/shared/search/search.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { - QualityAssuranceEventObject, - QualityAssuranceEventMessageObject, OpenaireQualityAssuranceEventMessageObject, + QualityAssuranceEventObject, } from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { Item } from '../../../core/shared/item.model'; diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts index 208e45e387..355de6e616 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts @@ -11,9 +11,10 @@ import { import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { QualityAssuranceSourceRestService } from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; -import { RequestParam } from '../../../core/cache/models/request-param.model'; -import {FindListOptions} from '../../../core/data/find-list-options.model'; +import { + QualityAssuranceSourceRestService +} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; describe('QualityAssuranceSourceService', () => { let service: QualityAssuranceSourceService; diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.spec.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.spec.ts index 6e933a0e80..c80d2bce20 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.spec.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.spec.ts @@ -1,9 +1,9 @@ /* eslint-disable no-empty, @typescript-eslint/no-empty-function */ import { CommonModule } from '@angular/common'; import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; -import { of as observableOf, of } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; import { createTestComponent } from '../../../shared/testing/utils.test'; import { From 625409cbb016c16d894826a915ee337ccdeabb29 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 17 Nov 2022 11:45:59 +0100 Subject: [PATCH 025/153] [CST-5537] Rename rest services to data services --- ...lity-assurance-event-data.service.spec.ts} | 8 ++-- ...> quality-assurance-event-data.service.ts} | 2 +- ...ity-assurance-source-data.service.spec.ts} | 20 ++++---- ... quality-assurance-source-data.service.ts} | 48 +++++++++---------- ...lity-assurance-topic-data.service.spec.ts} | 16 +++---- ...> quality-assurance-topic-data.service.ts} | 44 +++++++++-------- src/app/shared/mocks/notifications.mock.ts | 40 ++++++++++------ ...quality-assurance-events.component.spec.ts | 6 +-- .../quality-assurance-events.component.ts | 8 ++-- .../quality-assurance-source.effects.ts | 8 ++-- .../quality-assurance-source.service.spec.ts | 10 ++-- .../quality-assurance-source.service.ts | 8 ++-- .../quality-assurance-topics.effects.ts | 8 ++-- .../quality-assurance-topics.service.spec.ts | 12 +++-- .../quality-assurance-topics.service.ts | 8 ++-- .../suggestion-notifications.module.ts | 18 +++---- 16 files changed, 139 insertions(+), 125 deletions(-) rename src/app/core/suggestion-notifications/qa/events/{quality-assurance-event-rest.service.spec.ts => quality-assurance-event-data.service.spec.ts} (97%) rename src/app/core/suggestion-notifications/qa/events/{quality-assurance-event-rest.service.ts => quality-assurance-event-data.service.ts} (99%) rename src/app/core/suggestion-notifications/qa/source/{quality-assurance-source-rest.service.spec.ts => quality-assurance-source-data.service.spec.ts} (84%) rename src/app/core/suggestion-notifications/qa/source/{quality-assurance-source-rest.service.ts => quality-assurance-source-data.service.ts} (52%) rename src/app/core/suggestion-notifications/qa/topics/{quality-assurance-topic-rest.service.spec.ts => quality-assurance-topic-data.service.spec.ts} (86%) rename src/app/core/suggestion-notifications/qa/topics/{quality-assurance-topic-rest.service.ts => quality-assurance-topic-data.service.ts} (53%) diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.spec.ts similarity index 97% rename from src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts rename to src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.spec.ts index 731c70d624..50d0e43a99 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.spec.ts @@ -13,7 +13,7 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { QualityAssuranceEventRestService } from './quality-assurance-event-rest.service'; +import { QualityAssuranceEventDataService } from './quality-assurance-event-data.service'; import { qualityAssuranceEventObjectMissingPid, qualityAssuranceEventObjectMissingPid2, @@ -23,9 +23,9 @@ import { ReplaceOperation } from 'fast-json-patch'; import { RequestEntry } from '../../../data/request-entry.model'; import { FindListOptions } from '../../../data/find-list-options.model'; -describe('QualityAssuranceEventRestService', () => { +describe('QualityAssuranceEventDataService', () => { let scheduler: TestScheduler; - let service: QualityAssuranceEventRestService; + let service: QualityAssuranceEventDataService; let serviceASAny: any; let responseCacheEntry: RequestEntry; let responseCacheEntryB: RequestEntry; @@ -100,7 +100,7 @@ describe('QualityAssuranceEventRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new QualityAssuranceEventRestService( + service = new QualityAssuranceEventDataService( requestService, rdbService, objectCache, diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts similarity index 99% rename from src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts rename to src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts index e83c9a8b43..7f7e68afaa 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts @@ -31,7 +31,7 @@ import { DeleteByIDRequest, PostRequest } from '../../../data/request.models'; */ @Injectable() @dataService(QUALITY_ASSURANCE_EVENT_OBJECT) -export class QualityAssuranceEventRestService extends IdentifiableDataService { +export class QualityAssuranceEventDataService extends IdentifiableDataService { private createData: CreateData; private searchData: SearchData; diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.spec.ts similarity index 84% rename from src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts rename to src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.spec.ts index f4a2d81b36..50d9251bb8 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.spec.ts @@ -18,11 +18,11 @@ import { qualityAssuranceSourceObjectMorePid } from '../../../../shared/mocks/notifications.mock'; import { RequestEntry } from '../../../data/request-entry.model'; -import { QualityAssuranceSourceRestService } from './quality-assurance-source-rest.service'; +import { QualityAssuranceSourceDataService } from './quality-assurance-source-data.service'; -describe('QualityAssuranceSourceRestService', () => { +describe('QualityAssuranceSourceDataService', () => { let scheduler: TestScheduler; - let service: QualityAssuranceSourceRestService; + let service: QualityAssuranceSourceDataService; let responseCacheEntry: RequestEntry; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -72,7 +72,7 @@ describe('QualityAssuranceSourceRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new QualityAssuranceSourceRestService( + service = new QualityAssuranceSourceDataService( requestService, rdbService, objectCache, @@ -80,15 +80,15 @@ describe('QualityAssuranceSourceRestService', () => { notificationsService ); - spyOn((service as any), 'findListByHref').and.callThrough(); - spyOn((service as any), 'findByHref').and.callThrough(); + spyOn((service as any).findAllData, 'findAll').and.callThrough(); + spyOn((service as any), 'findById').and.callThrough(); }); describe('getSources', () => { - it('should call findListByHref', (done) => { + it('should call findAll', (done) => { service.getSources().subscribe( (res) => { - expect((service as any).findListByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + expect((service as any).findAllData.findAll).toHaveBeenCalledWith({}, true, true); } ); done(); @@ -104,10 +104,10 @@ describe('QualityAssuranceSourceRestService', () => { }); describe('getSource', () => { - it('should call findByHref', (done) => { + it('should call findById', (done) => { service.getSource(qualityAssuranceSourceObjectMorePid.id).subscribe( (res) => { - expect((service as any).findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceSourceObjectMorePid.id, true, true); + expect((service as any).findById).toHaveBeenCalledWith(qualityAssuranceSourceObjectMorePid.id, true, true); } ); done(); diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts similarity index 52% rename from src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts rename to src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts index 8f16347b25..03a5da2e8c 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts @@ -1,8 +1,6 @@ -/* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { mergeMap, take } from 'rxjs/operators'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; @@ -17,13 +15,16 @@ import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.mo import { PaginatedList } from '../../../data/paginated-list.model'; import { FindListOptions } from '../../../data/find-list-options.model'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; /** * The service handling all Quality Assurance source REST requests. */ @Injectable() @dataService(QUALITY_ASSURANCE_SOURCE_OBJECT) -export class QualityAssuranceSourceRestService extends IdentifiableDataService { +export class QualityAssuranceSourceDataService extends IdentifiableDataService { + + private findAllData: FindAllData; /** * Initialize service variables @@ -41,23 +42,24 @@ export class QualityAssuranceSourceRestService extends IdentifiableDataService>> * The list of Quality Assurance source. */ - public getSources(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.getBrowseEndpoint(options).pipe( - take(1), - mergeMap((href: string) => this.findListByHref(href, options, true, true, ...linksToFollow)), - ); + public getSources(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** @@ -70,18 +72,16 @@ export class QualityAssuranceSourceRestService extends IdentifiableDataService> - * The Quality Assurance source. + * @param id The Quality Assurance source id + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * + * @return Observable> The Quality Assurance source. */ - public getSource(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { - const options = {}; - return this.getBrowseEndpoint(options, 'qualityassurancesources').pipe( - take(1), - mergeMap((href: string) => this.findByHref(href + '/' + id, true, true, ...linksToFollow)) - ); + public getSource(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } } diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts similarity index 86% rename from src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts rename to src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts index d16ccbdb00..638ee3fa62 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts @@ -13,16 +13,16 @@ import { PageInfo } from '../../../shared/page-info.model'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject } from '../../../../shared/remote-data.utils'; -import { QualityAssuranceTopicRestService } from './quality-assurance-topic-rest.service'; +import { QualityAssuranceTopicDataService } from './quality-assurance-topic-data.service'; import { qualityAssuranceTopicObjectMoreAbstract, qualityAssuranceTopicObjectMorePid } from '../../../../shared/mocks/notifications.mock'; import { RequestEntry } from '../../../data/request-entry.model'; -describe('QualityAssuranceTopicRestService', () => { +describe('QualityAssuranceTopicDataService', () => { let scheduler: TestScheduler; - let service: QualityAssuranceTopicRestService; + let service: QualityAssuranceTopicDataService; let responseCacheEntry: RequestEntry; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -72,7 +72,7 @@ describe('QualityAssuranceTopicRestService', () => { http = {} as HttpClient; comparator = {} as any; - service = new QualityAssuranceTopicRestService( + service = new QualityAssuranceTopicDataService( requestService, rdbService, objectCache, @@ -80,15 +80,15 @@ describe('QualityAssuranceTopicRestService', () => { notificationsService ); - spyOn((service as any), 'findListByHref').and.callThrough(); - spyOn((service as any), 'findByHref').and.callThrough(); + spyOn((service as any).findAllData, 'findAll').and.callThrough(); + spyOn((service as any), 'findById').and.callThrough(); }); describe('getTopics', () => { it('should call findListByHref', (done) => { service.getTopics().subscribe( (res) => { - expect((service as any).findListByHref).toHaveBeenCalledWith(endpointURL, {}, true, true); + expect((service as any).findAllData.findAll).toHaveBeenCalledWith({}, true, true); } ); done(); @@ -107,7 +107,7 @@ describe('QualityAssuranceTopicRestService', () => { it('should call findByHref', (done) => { service.getTopic(qualityAssuranceTopicObjectMorePid.id).subscribe( (res) => { - expect((service as any).findByHref).toHaveBeenCalledWith(endpointURL + '/' + qualityAssuranceTopicObjectMorePid.id, true, true); + expect((service as any).findById).toHaveBeenCalledWith(qualityAssuranceTopicObjectMorePid.id, true, true); } ); done(); diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts similarity index 53% rename from src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts rename to src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts index 2ab715bbbe..2bf5195bf1 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { mergeMap, take } from 'rxjs/operators'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; @@ -16,13 +15,16 @@ import { FindListOptions } from '../../../data/find-list-options.model'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { dataService } from '../../../data/base/data-service.decorator'; import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; +import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; /** * The service handling all Quality Assurance topic REST requests. */ @Injectable() @dataService(QUALITY_ASSURANCE_TOPIC_OBJECT) -export class QualityAssuranceTopicRestService extends IdentifiableDataService { +export class QualityAssuranceTopicDataService extends IdentifiableDataService { + + private findAllData: FindAllData; /** * Initialize service variables @@ -40,23 +42,24 @@ export class QualityAssuranceTopicRestService extends IdentifiableDataService>> * The list of Quality Assurance topics. */ - public getTopics(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.getBrowseEndpoint(options).pipe( - take(1), - mergeMap((href: string) => this.findListByHref(href, options, true, true, ...linksToFollow)), - ); + public getTopics(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** @@ -69,18 +72,17 @@ export class QualityAssuranceTopicRestService extends IdentifiableDataService> * The Quality Assurance topic. */ - public getTopic(id: string, ...linksToFollow: FollowLinkConfig[]): Observable> { - const options = {}; - return this.getBrowseEndpoint(options).pipe( - take(1), - mergeMap((href: string) => this.findByHref(href + '/' + id, true, true, ...linksToFollow)) - ); + public getTopic(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } } diff --git a/src/app/shared/mocks/notifications.mock.ts b/src/app/shared/mocks/notifications.mock.ts index bbdf60c083..dc1c98c7b9 100644 --- a/src/app/shared/mocks/notifications.mock.ts +++ b/src/app/shared/mocks/notifications.mock.ts @@ -1,9 +1,17 @@ import { of as observableOf } from 'rxjs'; import { ResourceType } from '../../core/shared/resource-type'; -import { QualityAssuranceTopicObject } from '../../core/suggestion-notifications/qa/models/quality-assurance-topic.model'; -import { QualityAssuranceEventObject } from '../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; -import { QualityAssuranceTopicRestService } from '../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; -import { QualityAssuranceEventRestService } from '../../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; +import { + QualityAssuranceTopicObject +} from '../../core/suggestion-notifications/qa/models/quality-assurance-topic.model'; +import { + QualityAssuranceEventObject +} from '../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; +import { + QualityAssuranceTopicDataService +} from '../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; +import { + QualityAssuranceEventDataService +} from '../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Item } from '../../core/shared/item.model'; import { @@ -12,7 +20,9 @@ import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { SearchResult } from '../search/models/search-result.model'; -import { QualityAssuranceSourceObject } from '../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; +import { + QualityAssuranceSourceObject +} from '../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- @@ -1814,30 +1824,30 @@ export function getMockNotificationsStateService(): any { } /** - * Mock for [[QualityAssuranceSourceRestService]] + * Mock for [[QualityAssuranceSourceDataService]] */ - export function getMockQualityAssuranceSourceRestService(): QualityAssuranceTopicRestService { - return jasmine.createSpyObj('QualityAssuranceSourceRestService', { + export function getMockQualityAssuranceSourceRestService(): QualityAssuranceTopicDataService { + return jasmine.createSpyObj('QualityAssuranceSourceDataService', { getSources: jasmine.createSpy('getSources'), getSource: jasmine.createSpy('getSource'), }); } /** - * Mock for [[QualityAssuranceTopicRestService]] + * Mock for [[QualityAssuranceTopicDataService]] */ -export function getMockQualityAssuranceTopicRestService(): QualityAssuranceTopicRestService { - return jasmine.createSpyObj('QualityAssuranceTopicRestService', { +export function getMockQualityAssuranceTopicRestService(): QualityAssuranceTopicDataService { + return jasmine.createSpyObj('QualityAssuranceTopicDataService', { getTopics: jasmine.createSpy('getTopics'), getTopic: jasmine.createSpy('getTopic'), }); } /** - * Mock for [[QualityAssuranceEventRestService]] + * Mock for [[QualityAssuranceEventDataService]] */ -export function getMockQualityAssuranceEventRestService(): QualityAssuranceEventRestService { - return jasmine.createSpyObj('QualityAssuranceEventRestService', { +export function getMockQualityAssuranceEventRestService(): QualityAssuranceEventDataService { + return jasmine.createSpyObj('QualityAssuranceEventDataService', { getEventsByTopic: jasmine.createSpy('getEventsByTopic'), getEvent: jasmine.createSpy('getEvent'), patchEvent: jasmine.createSpy('patchEvent'), @@ -1848,7 +1858,7 @@ export function getMockQualityAssuranceEventRestService(): QualityAssuranceEvent } /** - * Mock for [[QualityAssuranceEventRestService]] + * Mock for [[QualityAssuranceEventDataService]] */ export function getMockSuggestionsService(): any { return jasmine.createSpyObj('SuggestionsService', { diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts index f0109f5f66..04ece87fbb 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts @@ -6,8 +6,8 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { of as observableOf } from 'rxjs'; import { - QualityAssuranceEventRestService -} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; + QualityAssuranceEventDataService +} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { QualityAssuranceEventsComponent } from './quality-assurance-events.component'; import { getMockQualityAssuranceEventRestService, @@ -113,7 +113,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { ], providers: [ { provide: ActivatedRoute, useValue: new ActivatedRouteStub(activatedRouteParamsMap, activatedRouteParams) }, - { provide: QualityAssuranceEventRestService, useValue: qualityAssuranceEventRestServiceStub }, + { provide: QualityAssuranceEventDataService, useValue: qualityAssuranceEventRestServiceStub }, { provide: NgbModal, useValue: modalStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts index f78798ac25..e34c121f35 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts @@ -14,8 +14,8 @@ import { QualityAssuranceEventObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; import { - QualityAssuranceEventRestService -} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; + QualityAssuranceEventDataService +} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { Metadata } from '../../../core/shared/metadata.utils'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -110,7 +110,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @param {ActivatedRoute} activatedRoute * @param {NgbModal} modalService * @param {NotificationsService} notificationsService - * @param {QualityAssuranceEventRestService} qualityAssuranceEventRestService + * @param {QualityAssuranceEventDataService} qualityAssuranceEventRestService * @param {PaginationService} paginationService * @param {TranslateService} translateService */ @@ -118,7 +118,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { private activatedRoute: ActivatedRoute, private modalService: NgbModal, private notificationsService: NotificationsService, - private qualityAssuranceEventRestService: QualityAssuranceEventRestService, + private qualityAssuranceEventRestService: QualityAssuranceEventDataService, private paginationService: PaginationService, private translateService: TranslateService ) { diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts index b1514171aa..fd78911ab4 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.effects.ts @@ -19,8 +19,8 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { QualityAssuranceSourceService } from './quality-assurance-source.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { - QualityAssuranceSourceRestService -} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; + QualityAssuranceSourceDataService +} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; /** * Provides effect methods for the Quality Assurance source actions. @@ -79,7 +79,7 @@ export class QualityAssuranceSourceEffects { * @param {TranslateService} translate * @param {NotificationsService} notificationsService * @param {QualityAssuranceSourceService} qualityAssuranceSourceService - * @param {QualityAssuranceSourceRestService} qualityAssuranceSourceDataService + * @param {QualityAssuranceSourceDataService} qualityAssuranceSourceDataService */ constructor( private actions$: Actions, @@ -87,7 +87,7 @@ export class QualityAssuranceSourceEffects { private translate: TranslateService, private notificationsService: NotificationsService, private qualityAssuranceSourceService: QualityAssuranceSourceService, - private qualityAssuranceSourceDataService: QualityAssuranceSourceRestService + private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService ) { } } diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts index 355de6e616..745a2baef7 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.spec.ts @@ -12,13 +12,13 @@ import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.ut import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { - QualityAssuranceSourceRestService -} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; + QualityAssuranceSourceDataService +} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; import { FindListOptions } from '../../../core/data/find-list-options.model'; describe('QualityAssuranceSourceService', () => { let service: QualityAssuranceSourceService; - let restService: QualityAssuranceSourceRestService; + let restService: QualityAssuranceSourceDataService; let serviceAsAny: any; let restServiceAsAny: any; @@ -32,14 +32,14 @@ describe('QualityAssuranceSourceService', () => { beforeEach(async () => { TestBed.configureTestingModule({ providers: [ - { provide: QualityAssuranceSourceRestService, useClass: getMockQualityAssuranceSourceRestService }, + { provide: QualityAssuranceSourceDataService, useClass: getMockQualityAssuranceSourceRestService }, { provide: QualityAssuranceSourceService, useValue: service } ] }).compileComponents(); }); beforeEach(() => { - restService = TestBed.get(QualityAssuranceSourceRestService); + restService = TestBed.inject(QualityAssuranceSourceDataService); restServiceAsAny = restService; restServiceAsAny.getSources.and.returnValue(observableOf(paginatedListRD)); service = new QualityAssuranceSourceService(restService); diff --git a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.ts b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.ts index a0556ece8c..5c16fb1a03 100644 --- a/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.ts +++ b/src/app/suggestion-notifications/qa/source/quality-assurance-source.service.ts @@ -4,8 +4,8 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { - QualityAssuranceSourceRestService -} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; + QualityAssuranceSourceDataService +} from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -23,10 +23,10 @@ export class QualityAssuranceSourceService { /** * Initialize the service variables. - * @param {QualityAssuranceSourceRestService} qualityAssuranceSourceRestService + * @param {QualityAssuranceSourceDataService} qualityAssuranceSourceRestService */ constructor( - private qualityAssuranceSourceRestService: QualityAssuranceSourceRestService + private qualityAssuranceSourceRestService: QualityAssuranceSourceDataService ) { } diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts index 11d7e11555..13e3670000 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.effects.ts @@ -19,8 +19,8 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { - QualityAssuranceTopicRestService -} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; + QualityAssuranceTopicDataService +} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; /** * Provides effect methods for the Quality Assurance topics actions. @@ -79,7 +79,7 @@ export class QualityAssuranceTopicsEffects { * @param {TranslateService} translate * @param {NotificationsService} notificationsService * @param {QualityAssuranceTopicsService} qualityAssuranceTopicService - * @param {QualityAssuranceTopicRestService} qualityAssuranceTopicDataService + * @param {QualityAssuranceTopicDataService} qualityAssuranceTopicDataService */ constructor( private actions$: Actions, @@ -87,6 +87,6 @@ export class QualityAssuranceTopicsEffects { private translate: TranslateService, private notificationsService: NotificationsService, private qualityAssuranceTopicService: QualityAssuranceTopicsService, - private qualityAssuranceTopicDataService: QualityAssuranceTopicRestService + private qualityAssuranceTopicDataService: QualityAssuranceTopicDataService ) { } } diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.spec.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.spec.ts index ba1399fcd4..1e4e3fcffd 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.spec.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.spec.ts @@ -2,7 +2,9 @@ import { TestBed } from '@angular/core/testing'; import { of as observableOf } from 'rxjs'; import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { QualityAssuranceTopicRestService } from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; +import { + QualityAssuranceTopicDataService +} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; import { PageInfo } from '../../../core/shared/page-info.model'; import { getMockQualityAssuranceTopicRestService, @@ -13,11 +15,11 @@ import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.ut import { cold } from 'jasmine-marbles'; import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { RequestParam } from '../../../core/cache/models/request-param.model'; -import {FindListOptions} from '../../../core/data/find-list-options.model'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; describe('QualityAssuranceTopicsService', () => { let service: QualityAssuranceTopicsService; - let restService: QualityAssuranceTopicRestService; + let restService: QualityAssuranceTopicDataService; let serviceAsAny: any; let restServiceAsAny: any; @@ -31,14 +33,14 @@ describe('QualityAssuranceTopicsService', () => { beforeEach(async () => { TestBed.configureTestingModule({ providers: [ - { provide: QualityAssuranceTopicRestService, useClass: getMockQualityAssuranceTopicRestService }, + { provide: QualityAssuranceTopicDataService, useClass: getMockQualityAssuranceTopicRestService }, { provide: QualityAssuranceTopicsService, useValue: service } ] }).compileComponents(); }); beforeEach(() => { - restService = TestBed.get(QualityAssuranceTopicRestService); + restService = TestBed.inject(QualityAssuranceTopicDataService); restServiceAsAny = restService; restServiceAsAny.getTopics.and.returnValue(observableOf(paginatedListRD)); service = new QualityAssuranceTopicsService(restService); diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.ts index 968e21fb95..6820791dff 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { - QualityAssuranceTopicRestService -} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; + QualityAssuranceTopicDataService +} from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -22,10 +22,10 @@ export class QualityAssuranceTopicsService { /** * Initialize the service variables. - * @param {QualityAssuranceTopicRestService} qualityAssuranceTopicRestService + * @param {QualityAssuranceTopicDataService} qualityAssuranceTopicRestService */ constructor( - private qualityAssuranceTopicRestService: QualityAssuranceTopicRestService + private qualityAssuranceTopicRestService: QualityAssuranceTopicDataService ) { } /** diff --git a/src/app/suggestion-notifications/suggestion-notifications.module.ts b/src/app/suggestion-notifications/suggestion-notifications.module.ts index e7e2272fff..eac527d672 100644 --- a/src/app/suggestion-notifications/suggestion-notifications.module.ts +++ b/src/app/suggestion-notifications/suggestion-notifications.module.ts @@ -13,19 +13,19 @@ import { suggestionNotificationsReducers, SuggestionNotificationsState } from '. import { suggestionNotificationsEffects } from './suggestion-notifications-effects'; import { QualityAssuranceTopicsService } from './qa/topics/quality-assurance-topics.service'; import { - QualityAssuranceTopicRestService -} from '../core/suggestion-notifications/qa/topics/quality-assurance-topic-rest.service'; + QualityAssuranceTopicDataService +} from '../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; import { - QualityAssuranceEventRestService -} from '../core/suggestion-notifications/qa/events/quality-assurance-event-rest.service'; + QualityAssuranceEventDataService +} from '../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { ProjectEntryImportModalComponent } from './qa/project-entry-import-modal/project-entry-import-modal.component'; import { TranslateModule } from '@ngx-translate/core'; import { SearchModule } from '../shared/search/search.module'; import { QualityAssuranceSourceComponent } from './qa/source/quality-assurance-source.component'; import { QualityAssuranceSourceService } from './qa/source/quality-assurance-source.service'; import { - QualityAssuranceSourceRestService -} from '../core/suggestion-notifications/qa/source/quality-assurance-source-rest.service'; + QualityAssuranceSourceDataService +} from '../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; const MODULES = [ CommonModule, @@ -53,9 +53,9 @@ const PROVIDERS = [ SuggestionNotificationsStateService, QualityAssuranceTopicsService, QualityAssuranceSourceService, - QualityAssuranceTopicRestService, - QualityAssuranceSourceRestService, - QualityAssuranceEventRestService + QualityAssuranceTopicDataService, + QualityAssuranceSourceDataService, + QualityAssuranceEventDataService ]; @NgModule({ From 822db5120ad2d1d663c2c6ff39232e9efad715fe Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Mon, 22 May 2023 16:56:13 +0200 Subject: [PATCH 026/153] 101731: Make ConfirmationModalComponent not dependent on DSpaceObject --- .../epeople-registry/epeople-registry.component.ts | 2 +- .../eperson-form/eperson-form.component.ts | 2 +- .../group-registry/group-form/group-form.component.ts | 2 +- .../confirmation-modal/confirmation-modal.component.html | 8 ++++---- .../confirmation-modal/confirmation-modal.component.ts | 5 +---- .../export-batch-selector.component.ts | 4 +++- .../export-metadata-selector.component.ts | 4 +++- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.ts b/src/app/access-control/epeople-registry/epeople-registry.component.ts index c7b9907b82..c51070183a 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/access-control/epeople-registry/epeople-registry.component.ts @@ -228,7 +228,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { deleteEPerson(ePerson: EPerson) { if (hasValue(ePerson.id)) { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = ePerson; + modalRef.componentInstance.name = this.dsoNameService.getName(ePerson); modalRef.componentInstance.headerLabel = 'confirmation-modal.delete-eperson.header'; modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel'; diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index ce30062a69..41408c9e8f 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -454,7 +454,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy { delete() { this.epersonService.getActiveEPerson().pipe(take(1)).subscribe((eperson: EPerson) => { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = eperson; + modalRef.componentInstance.name = this.dsoNameService.getName(eperson); modalRef.componentInstance.headerLabel = 'confirmation-modal.delete-eperson.header'; modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel'; diff --git a/src/app/access-control/group-registry/group-form/group-form.component.ts b/src/app/access-control/group-registry/group-form/group-form.component.ts index b837d80479..37d30c218c 100644 --- a/src/app/access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/access-control/group-registry/group-form/group-form.component.ts @@ -416,7 +416,7 @@ export class GroupFormComponent implements OnInit, OnDestroy { delete() { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((group: Group) => { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = group; + modalRef.componentInstance.name = this.dsoNameService.getName(group); modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-group.modal.header'; modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-group.modal.info'; modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-group.modal.cancel'; diff --git a/src/app/shared/confirmation-modal/confirmation-modal.component.html b/src/app/shared/confirmation-modal/confirmation-modal.component.html index 02434b1fa1..ff82f5bc83 100644 --- a/src/app/shared/confirmation-modal/confirmation-modal.component.html +++ b/src/app/shared/confirmation-modal/confirmation-modal.component.html @@ -1,18 +1,18 @@
- diff --git a/src/app/shared/confirmation-modal/confirmation-modal.component.ts b/src/app/shared/confirmation-modal/confirmation-modal.component.ts index 46eb4cedc5..e48986d880 100644 --- a/src/app/shared/confirmation-modal/confirmation-modal.component.ts +++ b/src/app/shared/confirmation-modal/confirmation-modal.component.ts @@ -1,7 +1,5 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; @Component({ selector: 'ds-confirmation-modal', @@ -18,7 +16,7 @@ export class ConfirmationModalComponent { */ @Input() brandColor = 'primary'; - @Input() dso: DSpaceObject; + @Input() name: string; /** * An event fired when the cancel or confirm button is clicked, with respectively false or true @@ -28,7 +26,6 @@ export class ConfirmationModalComponent { constructor( protected activeModal: NgbActiveModal, - public dsoNameService: DSONameService, ) { } diff --git a/src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.ts index 0645e09029..e5f5eca350 100644 --- a/src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.ts @@ -20,6 +20,7 @@ import { RemoteData } from '../../../../core/data/remote-data'; import { getProcessDetailRoute } from '../../../../process-page/process-page-routing.paths'; import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; /** * Component to wrap a list of existing dso's inside a modal @@ -38,6 +39,7 @@ export class ExportBatchSelectorComponent extends DSOSelectorModalWrapperCompone protected notificationsService: NotificationsService, protected translationService: TranslateService, protected scriptDataService: ScriptDataService, protected authorizationDataService: AuthorizationDataService, + protected dsoNameService: DSONameService, private modalService: NgbModal) { super(activeModal, route); } @@ -49,7 +51,7 @@ export class ExportBatchSelectorComponent extends DSOSelectorModalWrapperCompone navigate(dso: DSpaceObject): Observable { if (dso instanceof Collection) { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = dso; + modalRef.componentInstance.name = this.dsoNameService.getName(dso); modalRef.componentInstance.headerLabel = 'confirmation-modal.export-batch.header'; modalRef.componentInstance.infoLabel = 'confirmation-modal.export-batch.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.export-batch.cancel'; diff --git a/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts index d4b4314a99..d1252bf485 100644 --- a/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts @@ -21,6 +21,7 @@ import { RemoteData } from '../../../../core/data/remote-data'; import { getProcessDetailRoute } from '../../../../process-page/process-page-routing.paths'; import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; /** * Component to wrap a list of existing dso's inside a modal @@ -39,6 +40,7 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp protected notificationsService: NotificationsService, protected translationService: TranslateService, protected scriptDataService: ScriptDataService, protected authorizationDataService: AuthorizationDataService, + protected dsoNameService: DSONameService, private modalService: NgbModal) { super(activeModal, route); } @@ -50,7 +52,7 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp navigate(dso: DSpaceObject): Observable { if (dso instanceof Collection || dso instanceof Community) { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = dso; + modalRef.componentInstance.name = this.dsoNameService.getName(dso); modalRef.componentInstance.headerLabel = 'confirmation-modal.export-metadata.header'; modalRef.componentInstance.infoLabel = 'confirmation-modal.export-metadata.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.export-metadata.cancel'; From 7998ef489cc4e30dc0f058d481329e2f39096caa Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 23 Jun 2023 23:38:06 +0200 Subject: [PATCH 027/153] 101731: Make ConfirmationModalComponent not dependent on DSpaceObject --- .../workspace-item-admin-workflow-actions.component.ts | 2 +- .../subscription-view/subscription-view.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts index 36678460da..8db862dd5a 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts @@ -124,7 +124,7 @@ export class WorkspaceItemAdminWorkflowActionsComponent implements OnInit { */ deleteSupervisionOrder(supervisionOrderEntry: SupervisionOrderListEntry) { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = supervisionOrderEntry.group; + modalRef.componentInstance.name = this.dsoNameService.getName(supervisionOrderEntry.group); modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; diff --git a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts index 072b8d7828..0362ae6695 100644 --- a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts +++ b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts @@ -82,7 +82,7 @@ export class SubscriptionViewComponent { deleteSubscriptionPopup(subscription: Subscription) { if (hasValue(subscription.id)) { const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = this.dso; + modalRef.componentInstance.name = this.dsoNameService.getName(this.dso); modalRef.componentInstance.headerLabel = 'confirmation-modal.delete-subscription.header'; modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-subscription.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-subscription.cancel'; From ec821392565737f768b0cd95917eade7e5ae6589 Mon Sep 17 00:00:00 2001 From: Francesco Bacchelli Date: Mon, 7 Aug 2023 14:26:42 +0200 Subject: [PATCH 028/153] CST-11298 COAR: Update the first community PRs for DSpace target 8.0-SNAPSHOT --- .../project-entry-import-modal.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html index 35b4b396a7..42eb7e4b16 100644 --- a/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html +++ b/src/app/suggestion-notifications/qa/project-entry-import-modal/project-entry-import-modal.component.html @@ -46,7 +46,7 @@ [disableHeader]="true" [hidePaginationDetail]="false" [selectionConfig]="{ repeatable: false, listId: entityListId }" - [showExport]="false" + [showCsvExport]="false" [linkType]="linkTypes.ExternalLink" [context]="context" (deselectObject)="deselectEntity()" From 2f26e686cc472a0929e27b6c70cda823dab55fc5 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 25 Oct 2023 11:20:39 +0200 Subject: [PATCH 029/153] 107685: menu-component re-render section on store update --- src/app/shared/menu/menu.component.ts | 3 +-- src/app/shared/menu/menu.service.ts | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/shared/menu/menu.component.ts b/src/app/shared/menu/menu.component.ts index 35e180b476..805f5888ea 100644 --- a/src/app/shared/menu/menu.component.ts +++ b/src/app/shared/menu/menu.component.ts @@ -6,7 +6,6 @@ import { GenericConstructor } from '../../core/shared/generic-constructor'; import { hasValue, isNotEmptyOperator } from '../empty.util'; import { MenuSectionComponent } from './menu-section/menu-section.component'; import { getComponentForMenu } from './menu-section.decorator'; -import { compareArraysUsingIds } from '../../item-page/simple/item-types/shared/item-relationships-utils'; import { MenuSection } from './menu-section.model'; import { MenuID } from './menu-id.model'; import { ActivatedRoute } from '@angular/router'; @@ -86,7 +85,7 @@ export class MenuComponent implements OnInit, OnDestroy { this.menuCollapsed = this.menuService.isMenuCollapsed(this.menuID); this.menuPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID); this.menuVisible = this.menuService.isMenuVisible(this.menuID); - this.sections = this.menuService.getMenuTopSections(this.menuID).pipe(distinctUntilChanged(compareArraysUsingIds())); + this.sections = this.menuService.getMenuTopSections(this.menuID); this.subs.push( this.sections.pipe( diff --git a/src/app/shared/menu/menu.service.ts b/src/app/shared/menu/menu.service.ts index f44ddea649..1412acf09b 100644 --- a/src/app/shared/menu/menu.service.ts +++ b/src/app/shared/menu/menu.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { AppState, keySelector } from '../../app.reducer'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { ActivateMenuSectionAction, AddMenuSectionAction, @@ -22,6 +22,7 @@ import { MenuState } from './menu-state.model'; import { MenuSections } from './menu-sections.model'; import { MenuSection } from './menu-section.model'; import { MenuID } from './menu-id.model'; +import { compareArraysUsingIds } from '../../item-page/simple/item-types/shared/item-relationships-utils'; export function menuKeySelector(key: string, selector): MemoizedSelector { return createSelector(selector, (state) => { @@ -76,8 +77,10 @@ export class MenuService { return this.store.pipe( select(menuByIDSelector(menuID)), select(menuSectionStateSelector), - map((sections: MenuSections) => { - return Object.values(sections) + map((sections: MenuSections) => Object.values(sections)), + distinctUntilChanged(compareArraysUsingIds()), + map((sections: MenuSection[]) => { + return sections .filter((section: MenuSection) => hasNoValue(section.parentID)) .filter((section: MenuSection) => !mustBeVisible || section.visible); } From e847e4ef51aab604d1d07b79860003551eafe467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 26 Oct 2023 14:14:22 +0100 Subject: [PATCH 030/153] adding new access-status-list-element-badge css classes --- .../access-status-badge/access-status-badge.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html b/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html index a0180a761a..264bd3621c 100644 --- a/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html +++ b/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html @@ -1,5 +1,5 @@ - {{ accessStatus | translate }} + {{ accessStatus | translate }} From 1bbc053c0038de7ca37c43e92af6bf6fb3234b78 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Wed, 8 Nov 2023 14:57:54 +0100 Subject: [PATCH 031/153] 107902: Created test case for 2f26e686cc --- src/app/shared/menu/menu.component.spec.ts | 134 +++++++++++++++++++-- src/app/shared/menu/menu.component.ts | 2 +- 2 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/app/shared/menu/menu.component.spec.ts b/src/app/shared/menu/menu.component.spec.ts index f0660fab4a..e6566d97c3 100644 --- a/src/app/shared/menu/menu.component.spec.ts +++ b/src/app/shared/menu/menu.component.spec.ts @@ -1,12 +1,12 @@ +// eslint-disable-next-line max-classes-per-file import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; -import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA, Component } from '@angular/core'; import { MenuService } from './menu.service'; import { MenuComponent } from './menu.component'; -import { MenuServiceStub } from '../testing/menu-service.stub'; -import { of as observableOf } from 'rxjs'; -import { Router, ActivatedRoute } from '@angular/router'; +import { of as observableOf, BehaviorSubject } from 'rxjs'; +import { ActivatedRoute } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { MenuSection } from './menu-section.model'; import { MenuID } from './menu-id.model'; @@ -15,14 +15,39 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/ import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; import { ThemeService } from '../theme-support/theme.service'; import { getMockThemeService } from '../mocks/theme-service.mock'; +import { MenuItemType } from './menu-item-type.model'; +import { LinkMenuItemModel } from './menu-item/models/link.model'; +import { provideMockStore, MockStore } from '@ngrx/store/testing'; +import { StoreModule, Store } from '@ngrx/store'; +import { authReducer } from '../../core/auth/auth.reducer'; +import { storeModuleConfig, AppState } from '../../app.reducer'; +import { rendersSectionForMenu } from './menu-section.decorator'; + +const mockMenuID = 'mock-menuID' as MenuID; + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: '', + template: '', +}) +@rendersSectionForMenu(mockMenuID, true) +class TestExpandableMenuComponent { +} + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: '', + template: '', +}) +@rendersSectionForMenu(mockMenuID, false) +class TestMenuComponent { +} describe('MenuComponent', () => { let comp: MenuComponent; let fixture: ComponentFixture; let menuService: MenuService; - let router: any; - - const mockMenuID = 'mock-menuID' as MenuID; + let store: MockStore; const mockStatisticSection = { 'id': 'statistics_site', 'active': true, 'visible': true, 'index': 2, 'type': 'statistics', 'model': { 'type': 1, 'text': 'menu.section.statistics', 'link': 'statistics' } }; @@ -48,21 +73,55 @@ describe('MenuComponent', () => { children: [] }; + const initialState = { + menus: { + [mockMenuID]: { + collapsed: true, + id: mockMenuID, + previewCollapsed: true, + sectionToSubsectionIndex: { + section1: [], + }, + sections: { + section1: { + id: 'section1', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'test', + link: '/test', + } as LinkMenuItemModel, + }, + }, + visible: true, + }, + }, + }; + beforeEach(waitForAsync(() => { authorizationService = jasmine.createSpyObj('authorizationService', { isAuthorized: observableOf(false) }); - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], + void TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + NoopAnimationsModule, + RouterTestingModule, + StoreModule.forRoot(authReducer, storeModuleConfig), + ], declarations: [MenuComponent], providers: [ Injector, { provide: ThemeService, useValue: getMockThemeService() }, - { provide: MenuService, useClass: MenuServiceStub }, + MenuService, + provideMockStore({ initialState }), { provide: AuthorizationDataService, useValue: authorizationService }, { provide: ActivatedRoute, useValue: routeStub }, + TestExpandableMenuComponent, + TestMenuComponent, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(MenuComponent, { @@ -74,13 +133,62 @@ describe('MenuComponent', () => { fixture = TestBed.createComponent(MenuComponent); comp = fixture.componentInstance; // SearchPageComponent test instance comp.menuID = mockMenuID; - menuService = (comp as any).menuService; - router = TestBed.inject(Router); + menuService = TestBed.inject(MenuService); + store = TestBed.inject(Store) as MockStore; spyOn(comp as any, 'getSectionDataInjector').and.returnValue(MenuSection); - spyOn(comp as any, 'getSectionComponent').and.returnValue(observableOf({})); fixture.detectChanges(); }); + describe('ngOnInit', () => { + it('should trigger the section observable again when a new sub section has been added', () => { + spyOn(comp.sectionMap$, 'next').and.callThrough(); + const hasSubSections = new BehaviorSubject(false); + spyOn(menuService, 'hasSubSections').and.returnValue(hasSubSections.asObservable()); + spyOn(store, 'dispatch').and.callThrough(); + + store.setState({ + menus: { + [mockMenuID]: { + collapsed: true, + id: mockMenuID, + previewCollapsed: true, + sectionToSubsectionIndex: { + section1: ['test'], + }, + sections: { + section1: { + id: 'section1', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'test', + link: '/test', + } as LinkMenuItemModel, + }, + test: { + id: 'test', + parentID: 'section1', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'test', + link: '/test', + } as LinkMenuItemModel, + } + }, + visible: true, + }, + }, + }); + expect(menuService.hasSubSections).toHaveBeenCalled(); + hasSubSections.next(true); + + expect(comp.sectionMap$.next).toHaveBeenCalled(); + }); + }); + describe('toggle', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); diff --git a/src/app/shared/menu/menu.component.ts b/src/app/shared/menu/menu.component.ts index 805f5888ea..7b1394ddd2 100644 --- a/src/app/shared/menu/menu.component.ts +++ b/src/app/shared/menu/menu.component.ts @@ -102,7 +102,7 @@ export class MenuComponent implements OnInit, OnDestroy { switchMap((section: MenuSection) => this.getSectionComponent(section).pipe( map((component: GenericConstructor) => ({ section, component })) )), - distinctUntilChanged((x, y) => x.section.id === y.section.id) + distinctUntilChanged((x, y) => x.section.id === y.section.id && x.component.prototype === y.component.prototype), ).subscribe(({ section, component }) => { const nextMap = this.sectionMap$.getValue(); nextMap.set(section.id, { From c4205163f9c8a7ca97466f6f78d2de51bf259e5d Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Wed, 8 Nov 2023 23:43:17 +0100 Subject: [PATCH 032/153] Added skip to main content button --- .../feedback-form/feedback-form.component.html | 2 +- src/app/root/root.component.html | 6 +++++- src/app/root/root.component.scss | 16 ++++++++++++++++ src/app/root/root.component.ts | 8 ++++++++ src/assets/i18n/en.json5 | 2 ++ src/styles/_global-styles.scss | 2 +- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.html b/src/app/info/feedback/feedback-form/feedback-form.component.html index 02745f2580..a3bab3a6a3 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.html +++ b/src/app/info/feedback/feedback-form/feedback-form.component.html @@ -1,5 +1,5 @@
-
+

{{ 'info.feedback.head' | translate }}

{{ 'info.feedback.info' | translate }}

diff --git a/src/app/root/root.component.html b/src/app/root/root.component.html index bf49e507c0..39640ffbd4 100644 --- a/src/app/root/root.component.html +++ b/src/app/root/root.component.html @@ -1,3 +1,7 @@ + +
-
+
diff --git a/src/app/root/root.component.scss b/src/app/root/root.component.scss index e69de29bb2..9eb198417a 100644 --- a/src/app/root/root.component.scss +++ b/src/app/root/root.component.scss @@ -0,0 +1,16 @@ +#skip-to-main-content { + position: absolute; + top: -40px; + left: 0; + opacity: 0; + transition: opacity 0.3s; + z-index: calc(var(--ds-nav-z-index) + 1); + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 0; + + &:focus { + opacity: 1; + top: 0; + } +} diff --git a/src/app/root/root.component.ts b/src/app/root/root.component.ts index 3c2d65fc1f..aef43b510a 100644 --- a/src/app/root/root.component.ts +++ b/src/app/root/root.component.ts @@ -78,4 +78,12 @@ export class RootComponent implements OnInit { this.shouldShowRouteLoader = false; } } + + skipToMainContent() { + const mainContent = document.getElementById('main-content'); + if (mainContent) { + mainContent.tabIndex = -1; + mainContent.focus(); + } + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6c91bae4c1..60a4c21a49 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3610,6 +3610,8 @@ "resource-policies.table.headers.title.for.collection": "Policies for Collection", + "root.skip-to-content": "Skip to main content", + "search.description": "", "search.switch-configuration.title": "Show", diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index b714d399a0..a2642b1fdd 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -23,7 +23,7 @@ body { position: relative; } -.main-content { +#main-content { z-index: var(--ds-main-z-index); flex: 1 1 100%; margin-top: var(--ds-content-spacing); From 4e2d6d109e13f8e16ca08b825a367fafad7ae991 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 9 Nov 2023 15:46:57 +0100 Subject: [PATCH 033/153] 108045: Fix for repeatable date field labels --- .../models/date-picker/date-picker.component.html | 2 +- .../ds-dynamic-form-ui/models/date-picker/date-picker.model.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html index 1046dd6b2d..26803f3c67 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html @@ -1,6 +1,6 @@
- + {{model.placeholder}} * (this.hidden); - + this.repeatable = config.repeatable; // This was a subscription, then an async setTimeout, but it seems unnecessary const parentModel = this.getRootParent(this); if (parentModel && isNotUndefined(parentModel.hidden)) { From 11d3771e72e3f54f73bb60a23abd970eff5d66a3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 3 Nov 2023 08:21:11 -0500 Subject: [PATCH 034/153] Update condition to render show more node `loadingNode` ends up being the current `node` after clicking it preventing it from rendering when more pages available. Update community list component spec Make the show more flat node id unique The nodes with same id are conflicting when added to the tree. Clicking on the second with same id places the show more button under the wrong branch and expands the wrong page. --- src/app/community-list-page/community-list-service.ts | 5 +++-- .../community-list/community-list.component.html | 2 +- .../community-list/community-list.component.spec.ts | 9 +++++---- .../community-list/community-list.component.ts | 7 +++---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/app/community-list-page/community-list-service.ts b/src/app/community-list-page/community-list-service.ts index 67715716da..bbf1c7cdb5 100644 --- a/src/app/community-list-page/community-list-service.ts +++ b/src/app/community-list-page/community-list-service.ts @@ -24,6 +24,7 @@ import { FlatNode } from './flat-node.model'; import { ShowMoreFlatNode } from './show-more-flat-node.model'; import { FindListOptions } from '../core/data/find-list-options.model'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; +import { v4 as uuidv4 } from 'uuid'; // Helper method to combine and flatten an array of observables of flatNode arrays export const combineAndFlatten = (obsList: Observable[]): Observable => @@ -186,7 +187,7 @@ export class CommunityListService { return this.transformCommunity(community, level, parent, expandedNodes); }); if (currentPage < listOfPaginatedCommunities.totalPages && currentPage === listOfPaginatedCommunities.currentPage) { - obsList = [...obsList, observableOf([showMoreFlatNode('community', level, parent)])]; + obsList = [...obsList, observableOf([showMoreFlatNode(`community-${uuidv4()}`, level, parent)])]; } return combineAndFlatten(obsList); @@ -257,7 +258,7 @@ export class CommunityListService { let nodes = rd.payload.page .map((collection: Collection) => toFlatNode(collection, observableOf(false), level + 1, false, communityFlatNode)); if (currentCollectionPage < rd.payload.totalPages && currentCollectionPage === rd.payload.currentPage) { - nodes = [...nodes, showMoreFlatNode('collection', level + 1, communityFlatNode)]; + nodes = [...nodes, showMoreFlatNode(`collection-${uuidv4()}`, level + 1, communityFlatNode)]; } return nodes; } else { diff --git a/src/app/community-list-page/community-list/community-list.component.html b/src/app/community-list-page/community-list/community-list.component.html index 18e9e84577..de67607bb4 100644 --- a/src/app/community-list-page/community-list/community-list.component.html +++ b/src/app/community-list-page/community-list/community-list.component.html @@ -8,7 +8,7 @@
- diff --git a/src/app/community-list-page/community-list/community-list.component.spec.ts b/src/app/community-list-page/community-list/community-list.component.spec.ts index ce6b27dbeb..fb47f4994d 100644 --- a/src/app/community-list-page/community-list/community-list.component.spec.ts +++ b/src/app/community-list-page/community-list/community-list.component.spec.ts @@ -17,6 +17,7 @@ import { By } from '@angular/platform-browser'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { FlatNode } from '../flat-node.model'; import { RouterLinkWithHref } from '@angular/router'; +import { v4 as uuidv4 } from 'uuid'; describe('CommunityListComponent', () => { let component: CommunityListComponent; @@ -138,7 +139,7 @@ describe('CommunityListComponent', () => { } if (expandedNodes === null || isEmpty(expandedNodes)) { if (showMoreTopComNode) { - return observableOf([...mockTopFlatnodesUnexpanded.slice(0, endPageIndex), showMoreFlatNode('community', 0, null)]); + return observableOf([...mockTopFlatnodesUnexpanded.slice(0, endPageIndex), showMoreFlatNode(`community-${uuidv4()}`, 0, null)]); } else { return observableOf(mockTopFlatnodesUnexpanded.slice(0, endPageIndex)); } @@ -165,21 +166,21 @@ describe('CommunityListComponent', () => { const endSubComIndex = this.pageSize * expandedParent.currentCommunityPage; flatnodes = [...flatnodes, ...subComFlatnodes.slice(0, endSubComIndex)]; if (subComFlatnodes.length > endSubComIndex) { - flatnodes = [...flatnodes, showMoreFlatNode('community', topNode.level + 1, expandedParent)]; + flatnodes = [...flatnodes, showMoreFlatNode(`community-${uuidv4()}`, topNode.level + 1, expandedParent)]; } } if (isNotEmpty(collFlatnodes)) { const endColIndex = this.pageSize * expandedParent.currentCollectionPage; flatnodes = [...flatnodes, ...collFlatnodes.slice(0, endColIndex)]; if (collFlatnodes.length > endColIndex) { - flatnodes = [...flatnodes, showMoreFlatNode('collection', topNode.level + 1, expandedParent)]; + flatnodes = [...flatnodes, showMoreFlatNode(`collection-${uuidv4()}`, topNode.level + 1, expandedParent)]; } } } } }); if (showMoreTopComNode) { - flatnodes = [...flatnodes, showMoreFlatNode('community', 0, null)]; + flatnodes = [...flatnodes, showMoreFlatNode(`community-${uuidv4()}`, 0, null)]; } return observableOf(flatnodes); } diff --git a/src/app/community-list-page/community-list/community-list.component.ts b/src/app/community-list-page/community-list/community-list.component.ts index 90dd6b3c05..10ffb5e0b4 100644 --- a/src/app/community-list-page/community-list/community-list.component.ts +++ b/src/app/community-list-page/community-list/community-list.component.ts @@ -111,19 +111,18 @@ export class CommunityListComponent implements OnInit, OnDestroy { getNextPage(node: FlatNode): void { this.loadingNode = node; if (node.parent != null) { - if (node.id === 'collection') { + if (node.id.startsWith('collection')) { const parentNodeInExpandedNodes = this.expandedNodes.find((node2: FlatNode) => node.parent.id === node2.id); parentNodeInExpandedNodes.currentCollectionPage++; } - if (node.id === 'community') { + if (node.id.startsWith('community')) { const parentNodeInExpandedNodes = this.expandedNodes.find((node2: FlatNode) => node.parent.id === node2.id); parentNodeInExpandedNodes.currentCommunityPage++; } - this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes); } else { this.paginationConfig.currentPage++; - this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes); } + this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes); } } From dc2ef989e612c305ae98932be491db15a1fc74a4 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 9 Nov 2023 11:24:31 -0600 Subject: [PATCH 035/153] Filter expanded nodes by id Co-Authored-By: Art Lowel <1567693+artlowel@users.noreply.github.com> --- .../community-list/community-list.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/community-list-page/community-list/community-list.component.ts b/src/app/community-list-page/community-list/community-list.component.ts index 10ffb5e0b4..6b5c6578e1 100644 --- a/src/app/community-list-page/community-list/community-list.component.ts +++ b/src/app/community-list-page/community-list/community-list.component.ts @@ -84,7 +84,7 @@ export class CommunityListComponent implements OnInit, OnDestroy { toggleExpanded(node: FlatNode) { this.loadingNode = node; if (node.isExpanded) { - this.expandedNodes = this.expandedNodes.filter((node2) => node2.name !== node.name); + this.expandedNodes = this.expandedNodes.filter((node2) => node2.id !== node.id); node.isExpanded = false; } else { this.expandedNodes.push(node); From 0da7c15f2eff6229caafccae1be8dd7b10ebc629 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 20 Sep 2023 14:28:08 -0500 Subject: [PATCH 036/153] Limit getMembers() and getSubgroups() to only fetching one object. These lists are only used to find the size of each --- .../group-registry/groups-registry.component.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/app/access-control/group-registry/groups-registry.component.ts b/src/app/access-control/group-registry/groups-registry.component.ts index ccfd155e39..06a048ad72 100644 --- a/src/app/access-control/group-registry/groups-registry.component.ts +++ b/src/app/access-control/group-registry/groups-registry.component.ts @@ -216,18 +216,28 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { /** * Get the members (epersons embedded value of a group) + * NOTE: At this time we only grab the *first* member in order to receive the `totalElements` value + * needed for our HTML template. * @param group */ getMembers(group: Group): Observable>> { - return this.ePersonDataService.findListByHref(group._links.epersons.href).pipe(getFirstSucceededRemoteData()); + return this.ePersonDataService.findListByHref(group._links.epersons.href, { + currentPage: 1, + elementsPerPage: 1, + }).pipe(getFirstSucceededRemoteData()); } /** * Get the subgroups (groups embedded value of a group) + * NOTE: At this time we only grab the *first* subgroup in order to receive the `totalElements` value + * needed for our HTML template. * @param group */ getSubgroups(group: Group): Observable>> { - return this.groupService.findListByHref(group._links.subgroups.href).pipe(getFirstSucceededRemoteData()); + return this.groupService.findListByHref(group._links.subgroups.href, { + currentPage: 1, + elementsPerPage: 1, + }).pipe(getFirstSucceededRemoteData()); } /** From 97479a29453eaf18031e095b612c1c054f9bb31f Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 20 Sep 2023 14:30:54 -0500 Subject: [PATCH 037/153] Remove isSubgroupOfGroup() functionality as it loads every subgroup at once. Bad peformance for large groups --- .../subgroups-list.component.html | 9 +---- .../subgroup-list/subgroups-list.component.ts | 33 ++----------------- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html index d009f0283e..8268eb5eb4 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html @@ -62,16 +62,9 @@
{{ dsoNameService.getName((group.object | async)?.payload) }}
- - {{ messagePrefix + '.table.edit.currentGroup' | translate }} -
- - -
- -
{{ePerson.eperson.id}}
{{eperson.id}} - - {{ dsoNameService.getName(ePerson.eperson) }} + {{ dsoNameService.getName(eperson) }} - {{messagePrefix + '.table.email' | translate}}: {{ ePerson.eperson.email ? ePerson.eperson.email : '-' }}
- {{messagePrefix + '.table.netid' | translate}}: {{ ePerson.eperson.netid ? ePerson.eperson.netid : '-' }} + {{messagePrefix + '.table.email' | translate}}: {{ eperson.email ? eperson.email : '-' }}
+ {{messagePrefix + '.table.netid' | translate}}: {{ eperson.netid ? eperson.netid : '-' }}
-
@@ -84,7 +84,7 @@ -
{{ePerson.eperson.id}}
{{eperson.id}} - - {{ dsoNameService.getName(ePerson.eperson) }} + {{ dsoNameService.getName(eperson) }} - {{messagePrefix + '.table.email' | translate}}: {{ ePerson.eperson.email ? ePerson.eperson.email : '-' }}
- {{messagePrefix + '.table.netid' | translate}}: {{ ePerson.eperson.netid ? ePerson.eperson.netid : '-' }} + {{messagePrefix + '.table.email' | translate}}: {{ eperson.email ? eperson.email : '-' }}
+ {{messagePrefix + '.table.netid' | translate}}: {{ eperson.netid ? eperson.netid : '-' }}
-
@@ -139,7 +139,7 @@ - diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 7c8db399bc..76e38067bc 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -17,7 +17,7 @@ import { Group } from '../../../../core/eperson/models/group.model'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; +import { GroupMock } from '../../../../shared/testing/group-mock'; import { MembersListComponent } from './members-list.component'; import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson.mock'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; @@ -39,28 +39,26 @@ describe('MembersListComponent', () => { let ePersonDataServiceStub: any; let groupsDataServiceStub: any; let activeGroup; - let allEPersons: EPerson[]; - let allGroups: Group[]; let epersonMembers: EPerson[]; - let subgroupMembers: Group[]; + let epersonNonMembers: EPerson[]; let paginationService; beforeEach(waitForAsync(() => { activeGroup = GroupMock; epersonMembers = [EPersonMock2]; - subgroupMembers = [GroupMock2]; - allEPersons = [EPersonMock, EPersonMock2]; - allGroups = [GroupMock, GroupMock2]; + epersonNonMembers = [EPersonMock]; ePersonDataServiceStub = { activeGroup: activeGroup, epersonMembers: epersonMembers, - subgroupMembers: subgroupMembers, + epersonNonMembers: epersonNonMembers, + // This method is used to get all the current members findListByHref(_href: string): Observable>> { return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), groupsDataServiceStub.getEPersonMembers())); }, + // This method is used to search across *non-members* searchByScope(scope: string, query: string): Observable>> { if (query === '') { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allEPersons)); + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), epersonNonMembers)); } return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); }, @@ -77,22 +75,22 @@ describe('MembersListComponent', () => { groupsDataServiceStub = { activeGroup: activeGroup, epersonMembers: epersonMembers, - subgroupMembers: subgroupMembers, - allGroups: allGroups, + epersonNonMembers: epersonNonMembers, getActiveGroup(): Observable { return observableOf(activeGroup); }, getEPersonMembers() { return this.epersonMembers; }, - searchGroups(query: string): Observable>> { - if (query === '') { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), this.allGroups)); - } - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); - }, - addMemberToGroup(parentGroup, eperson: EPerson): Observable { - this.epersonMembers = [...this.epersonMembers, eperson]; + addMemberToGroup(parentGroup, epersonToAdd: EPerson): Observable { + // Add eperson to list of members + this.epersonMembers = [...this.epersonMembers, epersonToAdd]; + // Remove eperson from list of non-members + this.epersonNonMembers.forEach( (eperson: EPerson, index: number) => { + if (eperson.id === epersonToAdd.id) { + this.epersonNonMembers.splice(index, 1); + } + }); return observableOf(new RestResponse(true, 200, 'Success')); }, clearGroupsRequests() { @@ -105,14 +103,14 @@ describe('MembersListComponent', () => { return '/access-control/groups/' + group.id; }, deleteMemberFromGroup(parentGroup, epersonToDelete: EPerson): Observable { - this.epersonMembers = this.epersonMembers.find((eperson: EPerson) => { - if (eperson.id !== epersonToDelete.id) { - return eperson; + // Remove eperson from list of members + this.epersonMembers.forEach( (eperson: EPerson, index: number) => { + if (eperson.id === epersonToDelete.id) { + this.epersonMembers.splice(index, 1); } }); - if (this.epersonMembers === undefined) { - this.epersonMembers = []; - } + // Add eperson to list of non-members + this.epersonNonMembers = [...this.epersonNonMembers, epersonToDelete]; return observableOf(new RestResponse(true, 200, 'Success')); } }; @@ -160,13 +158,37 @@ describe('MembersListComponent', () => { expect(comp).toBeDefined(); })); - it('should show list of eperson members of current active group', () => { - const epersonIdsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tr td:first-child')); - expect(epersonIdsFound.length).toEqual(1); - epersonMembers.map((eperson: EPerson) => { - expect(epersonIdsFound.find((foundEl) => { - return (foundEl.nativeElement.textContent.trim() === eperson.uuid); - })).toBeTruthy(); + describe('current members list', () => { + it('should show list of eperson members of current active group', () => { + const epersonIdsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tr td:first-child')); + expect(epersonIdsFound.length).toEqual(1); + epersonMembers.map((eperson: EPerson) => { + expect(epersonIdsFound.find((foundEl) => { + return (foundEl.nativeElement.textContent.trim() === eperson.uuid); + })).toBeTruthy(); + }); + }); + + it('should show a delete button next to each member', () => { + const epersonsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tbody tr')); + epersonsFound.map((foundEPersonRowElement: DebugElement) => { + const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus')); + const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt')); + expect(addButton).toBeNull(); + expect(deleteButton).not.toBeNull(); + }); + }); + + describe('if first delete button is pressed', () => { + beforeEach(() => { + const deleteButton: DebugElement = fixture.debugElement.query(By.css('#ePeopleMembersOfGroup tbody .fa-trash-alt')); + deleteButton.nativeElement.click(); + fixture.detectChanges(); + }); + it('then no ePerson remains as a member of the active group.', () => { + const epersonsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tbody tr')); + expect(epersonsFound.length).toEqual(0); + }); }); }); @@ -174,76 +196,40 @@ describe('MembersListComponent', () => { describe('when searching without query', () => { let epersonsFound: DebugElement[]; beforeEach(fakeAsync(() => { - spyOn(component, 'isMemberOfGroup').and.callFake((ePerson: EPerson) => { - return observableOf(activeGroup.epersons.includes(ePerson)); - }); component.search({ scope: 'metadata', query: '' }); tick(); fixture.detectChanges(); epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr')); - // Stop using the fake spy function (because otherwise the clicking on the buttons will not change anything - // because they don't change the value of activeGroup.epersons) - jasmine.getEnv().allowRespy(true); - spyOn(component, 'isMemberOfGroup').and.callThrough(); })); - it('should display all epersons', () => { - expect(epersonsFound.length).toEqual(2); + it('should display only non-members of the group', () => { + const epersonIdsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr td:first-child')); + expect(epersonIdsFound.length).toEqual(1); + epersonNonMembers.map((eperson: EPerson) => { + expect(epersonIdsFound.find((foundEl) => { + return (foundEl.nativeElement.textContent.trim() === eperson.uuid); + })).toBeTruthy(); + }); }); - describe('if eperson is already a eperson', () => { - it('should have delete button, else it should have add button', () => { - const memberIds: string[] = activeGroup.epersons.map((ePerson: EPerson) => ePerson.id); - epersonsFound.map((foundEPersonRowElement: DebugElement) => { - const epersonId: DebugElement = foundEPersonRowElement.query(By.css('td:first-child')); - const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus')); - const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt')); - if (memberIds.includes(epersonId.nativeElement.textContent)) { - expect(addButton).toBeNull(); - expect(deleteButton).not.toBeNull(); - } else { - expect(deleteButton).toBeNull(); - expect(addButton).not.toBeNull(); - } - }); + it('should display an add button next to non-members, not a delete button', () => { + epersonsFound.map((foundEPersonRowElement: DebugElement) => { + const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus')); + const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt')); + expect(addButton).not.toBeNull(); + expect(deleteButton).toBeNull(); }); }); describe('if first add button is pressed', () => { - beforeEach(fakeAsync(() => { + beforeEach(() => { const addButton: DebugElement = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-plus')); addButton.nativeElement.click(); - tick(); fixture.detectChanges(); - })); - it('then all the ePersons are member of the active group', () => { - epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr')); - expect(epersonsFound.length).toEqual(2); - epersonsFound.map((foundEPersonRowElement: DebugElement) => { - const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus')); - const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt')); - expect(addButton).toBeNull(); - expect(deleteButton).not.toBeNull(); - }); }); - }); - - describe('if first delete button is pressed', () => { - beforeEach(fakeAsync(() => { - const deleteButton: DebugElement = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-trash-alt')); - deleteButton.nativeElement.click(); - tick(); - fixture.detectChanges(); - })); - it('then no ePerson is member of the active group', () => { + it('then all (two) ePersons are member of the active group. No non-members left', () => { epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr')); - expect(epersonsFound.length).toEqual(2); - epersonsFound.map((foundEPersonRowElement: DebugElement) => { - const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus')); - const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt')); - expect(deleteButton).toBeNull(); - expect(addButton).not.toBeNull(); - }); + expect(epersonsFound.length).toEqual(0); }); }); }); diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index 704a92d0f9..f49690f674 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -4,13 +4,11 @@ import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Observable, - of as observableOf, Subscription, - BehaviorSubject, - combineLatest as observableCombineLatest + BehaviorSubject } from 'rxjs'; -import { defaultIfEmpty, map, switchMap, take } from 'rxjs/operators'; -import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; +import { map, switchMap, take } from 'rxjs/operators'; +import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; import { GroupDataService } from '../../../../core/eperson/group-data.service'; @@ -18,11 +16,11 @@ import { EPerson } from '../../../../core/eperson/models/eperson.model'; import { Group } from '../../../../core/eperson/models/group.model'; import { getFirstCompletedRemoteData, - getAllCompletedRemoteData + getAllCompletedRemoteData, + getRemoteDataPayload } from '../../../../core/shared/operators'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; -import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; @@ -93,11 +91,11 @@ export class MembersListComponent implements OnInit, OnDestroy { /** * EPeople being displayed in search result, initially all members, after search result of search */ - ePeopleSearchDtos: BehaviorSubject> = new BehaviorSubject>(undefined); + ePeopleSearch: BehaviorSubject> = new BehaviorSubject>(undefined); /** * List of EPeople members of currently active group being edited */ - ePeopleMembersOfGroupDtos: BehaviorSubject> = new BehaviorSubject>(undefined); + ePeopleMembersOfGroup: BehaviorSubject> = new BehaviorSubject>(undefined); /** * Pagination config used to display the list of EPeople that are result of EPeople search @@ -186,18 +184,9 @@ export class MembersListComponent implements OnInit, OnDestroy { return rd; } }), - switchMap((epersonListRD: RemoteData>) => { - const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => { - const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); - epersonDtoModel.eperson = member; - return observableOf(epersonDtoModel); - })]); - return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => { - return buildPaginatedList(epersonListRD.payload.pageInfo, dtos); - })); - })) - .subscribe((paginatedListOfDTOs: PaginatedList) => { - this.ePeopleMembersOfGroupDtos.next(paginatedListOfDTOs); + getRemoteDataPayload()) + .subscribe((paginatedListOfEPersons: PaginatedList) => { + this.ePeopleMembersOfGroup.next(paginatedListOfEPersons); })); } @@ -217,13 +206,13 @@ export class MembersListComponent implements OnInit, OnDestroy { /** * Deletes a given EPerson from the members list of the group currently being edited - * @param ePerson EPerson we want to delete as member from group that is currently being edited + * @param eperson EPerson we want to delete as member from group that is currently being edited */ - deleteMemberFromGroup(ePerson: EpersonDtoModel) { + deleteMemberFromGroup(eperson: EPerson) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - const response = this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson.eperson); - this.showNotifications('deleteMember', response, this.dsoNameService.getName(ePerson.eperson), activeGroup); + const response = this.groupDataService.deleteMemberFromGroup(activeGroup, eperson); + this.showNotifications('deleteMember', response, this.dsoNameService.getName(eperson), activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); } @@ -232,13 +221,13 @@ export class MembersListComponent implements OnInit, OnDestroy { /** * Adds a given EPerson to the members list of the group currently being edited - * @param ePerson EPerson we want to add as member to group that is currently being edited + * @param eperson EPerson we want to add as member to group that is currently being edited */ - addMemberToGroup(ePerson: EpersonDtoModel) { + addMemberToGroup(eperson: EPerson) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - const response = this.groupDataService.addMemberToGroup(activeGroup, ePerson.eperson); - this.showNotifications('addMember', response, this.dsoNameService.getName(ePerson.eperson), activeGroup); + const response = this.groupDataService.addMemberToGroup(activeGroup, eperson); + this.showNotifications('addMember', response, this.dsoNameService.getName(eperson), activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); } @@ -286,18 +275,9 @@ export class MembersListComponent implements OnInit, OnDestroy { return rd; } }), - switchMap((epersonListRD: RemoteData>) => { - const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => { - const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); - epersonDtoModel.eperson = member; - return observableOf(epersonDtoModel); - })]); - return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => { - return buildPaginatedList(epersonListRD.payload.pageInfo, dtos); - })); - })) - .subscribe((paginatedListOfDTOs: PaginatedList) => { - this.ePeopleSearchDtos.next(paginatedListOfDTOs); + getRemoteDataPayload()) + .subscribe((paginatedListOfEPersons: PaginatedList) => { + this.ePeopleSearch.next(paginatedListOfEPersons); })); } From b598f1b5ca9b54c4b5fe23daa3d7b502ee0dc6b2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 26 Sep 2023 12:07:30 -0500 Subject: [PATCH 041/153] Also remove unnecessary EpersonDtoModel from extending ReviewersListComponent. Remove "memberOfGroup" from EpersonDtoModel as it is no longer used --- .../members-list/members-list.component.ts | 12 +-- .../core/eperson/models/eperson-dto.model.ts | 5 - .../reviewers-list.component.spec.ts | 95 ++++++++----------- .../reviewers-list.component.ts | 51 ++++------ 4 files changed, 65 insertions(+), 98 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index f49690f674..e828555a80 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -29,8 +29,8 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; */ enum SubKey { ActiveGroup, - MembersDTO, - SearchResultsDTO, + Members, + SearchResults, } /** @@ -166,8 +166,8 @@ export class MembersListComponent implements OnInit, OnDestroy { * @private */ retrieveMembers(page: number): void { - this.unsubFrom(SubKey.MembersDTO); - this.subs.set(SubKey.MembersDTO, + this.unsubFrom(SubKey.Members); + this.subs.set(SubKey.Members, this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( switchMap((currentPagination) => { return this.ePersonDataService.findListByHref(this.groupBeingEdited._links.epersons.href, { @@ -239,8 +239,8 @@ export class MembersListComponent implements OnInit, OnDestroy { * @param data Contains scope and query param */ search(data: any) { - this.unsubFrom(SubKey.SearchResultsDTO); - this.subs.set(SubKey.SearchResultsDTO, + this.unsubFrom(SubKey.SearchResults); + this.subs.set(SubKey.SearchResults, this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( switchMap((paginationOptions) => { diff --git a/src/app/core/eperson/models/eperson-dto.model.ts b/src/app/core/eperson/models/eperson-dto.model.ts index 0e79902196..5fa6c7ed68 100644 --- a/src/app/core/eperson/models/eperson-dto.model.ts +++ b/src/app/core/eperson/models/eperson-dto.model.ts @@ -13,9 +13,4 @@ export class EpersonDtoModel { * Whether or not the linked EPerson is able to be deleted */ public ableToDelete: boolean; - /** - * Whether or not this EPerson is member of group on page it is being used on - */ - public memberOfGroup: boolean; - } diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts index 7c8db782ce..bcbeef5683 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts @@ -17,7 +17,7 @@ import { Group } from '../../../../core/eperson/models/group.model'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; +import { GroupMock } from '../../../../shared/testing/group-mock'; import { ReviewersListComponent } from './reviewers-list.component'; import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson.mock'; import { @@ -31,8 +31,10 @@ import { NotificationsServiceStub } from '../../../../shared/testing/notificatio import { RouterMock } from '../../../../shared/mocks/router.mock'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; -import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.model'; +// NOTE: Because ReviewersListComponent extends MembersListComponent, the below tests ONLY validate +// features which are *unique* to ReviewersListComponent. All other features are tested in the +// members-list.component.spec.ts file. describe('ReviewersListComponent', () => { let component: ReviewersListComponent; let fixture: ComponentFixture; @@ -40,31 +42,27 @@ describe('ReviewersListComponent', () => { let builderService: FormBuilderService; let ePersonDataServiceStub: any; let groupsDataServiceStub: any; - let activeGroup; - let allEPersons; - let allGroups; - let epersonMembers; - let subgroupMembers; + let activeGroup: Group; + let epersonMembers: EPerson[]; + let epersonNonMembers: EPerson[]; let paginationService; - let ePersonDtoModel1: EpersonDtoModel; - let ePersonDtoModel2: EpersonDtoModel; beforeEach(waitForAsync(() => { activeGroup = GroupMock; epersonMembers = [EPersonMock2]; - subgroupMembers = [GroupMock2]; - allEPersons = [EPersonMock, EPersonMock2]; - allGroups = [GroupMock, GroupMock2]; + epersonNonMembers = [EPersonMock]; ePersonDataServiceStub = { activeGroup: activeGroup, epersonMembers: epersonMembers, - subgroupMembers: subgroupMembers, + epersonNonMembers: epersonNonMembers, + // This method is used to get all the current members findListByHref(_href: string): Observable>> { return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), groupsDataServiceStub.getEPersonMembers())); }, + // This method is used to search across *non-members* searchByScope(scope: string, query: string): Observable>> { if (query === '') { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allEPersons)); + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), epersonNonMembers)); } return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); }, @@ -81,22 +79,22 @@ describe('ReviewersListComponent', () => { groupsDataServiceStub = { activeGroup: activeGroup, epersonMembers: epersonMembers, - subgroupMembers: subgroupMembers, - allGroups: allGroups, + epersonNonMembers: epersonNonMembers, getActiveGroup(): Observable { return observableOf(activeGroup); }, getEPersonMembers() { return this.epersonMembers; }, - searchGroups(query: string): Observable>> { - if (query === '') { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), this.allGroups)); - } - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); - }, - addMemberToGroup(parentGroup, eperson: EPerson): Observable { - this.epersonMembers = [...this.epersonMembers, eperson]; + addMemberToGroup(parentGroup, epersonToAdd: EPerson): Observable { + // Add eperson to list of members + this.epersonMembers = [...this.epersonMembers, epersonToAdd]; + // Remove eperson from list of non-members + this.epersonNonMembers.forEach( (eperson: EPerson, index: number) => { + if (eperson.id === epersonToAdd.id) { + this.epersonNonMembers.splice(index, 1); + } + }); return observableOf(new RestResponse(true, 200, 'Success')); }, clearGroupsRequests() { @@ -109,21 +107,20 @@ describe('ReviewersListComponent', () => { return '/access-control/groups/' + group.id; }, deleteMemberFromGroup(parentGroup, epersonToDelete: EPerson): Observable { - this.epersonMembers = this.epersonMembers.find((eperson: EPerson) => { - if (eperson.id !== epersonToDelete.id) { - return eperson; + // Remove eperson from list of members + this.epersonMembers.forEach( (eperson: EPerson, index: number) => { + if (eperson.id === epersonToDelete.id) { + this.epersonMembers.splice(index, 1); } }); - if (this.epersonMembers === undefined) { - this.epersonMembers = []; - } + // Add eperson to list of non-members + this.epersonNonMembers = [...this.epersonNonMembers, epersonToDelete]; return observableOf(new RestResponse(true, 200, 'Success')); }, + // Used to find the currently active group findById(id: string) { - for (const group of allGroups) { - if (group.id === id) { - return createSuccessfulRemoteDataObject$(group); - } + if (activeGroup.id === id) { + return createSuccessfulRemoteDataObject$(activeGroup); } return createNoContentRemoteDataObject$(); }, @@ -135,7 +132,7 @@ describe('ReviewersListComponent', () => { translateService = getMockTranslateService(); paginationService = new PaginationServiceStub(); - TestBed.configureTestingModule({ + return TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ loader: { @@ -169,12 +166,6 @@ describe('ReviewersListComponent', () => { fixture.debugElement.nativeElement.remove(); })); - beforeEach(() => { - ePersonDtoModel1 = new EpersonDtoModel(); - ePersonDtoModel1.eperson = EPersonMock; - ePersonDtoModel2 = new EpersonDtoModel(); - ePersonDtoModel2.eperson = EPersonMock2; - }); describe('when no group is selected', () => { beforeEach(() => { @@ -218,34 +209,32 @@ describe('ReviewersListComponent', () => { it('should replace the value when a new member is added when multipleReviewers is false', () => { spyOn(component.selectedReviewersUpdated, 'emit'); component.multipleReviewers = false; - component.selectedReviewers = [ePersonDtoModel1]; + component.selectedReviewers = [EPersonMock]; - component.addMemberToGroup(ePersonDtoModel2); + component.addMemberToGroup(EPersonMock2); - expect(component.selectedReviewers).toEqual([ePersonDtoModel2]); - expect(component.selectedReviewersUpdated.emit).toHaveBeenCalledWith([ePersonDtoModel2.eperson]); + expect(component.selectedReviewers).toEqual([EPersonMock2]); + expect(component.selectedReviewersUpdated.emit).toHaveBeenCalledWith([EPersonMock2]); }); it('should add the value when a new member is added when multipleReviewers is true', () => { spyOn(component.selectedReviewersUpdated, 'emit'); component.multipleReviewers = true; - component.selectedReviewers = [ePersonDtoModel1]; + component.selectedReviewers = [EPersonMock]; - component.addMemberToGroup(ePersonDtoModel2); + component.addMemberToGroup(EPersonMock2); - expect(component.selectedReviewers).toEqual([ePersonDtoModel1, ePersonDtoModel2]); - expect(component.selectedReviewersUpdated.emit).toHaveBeenCalledWith([ePersonDtoModel1.eperson, ePersonDtoModel2.eperson]); + expect(component.selectedReviewers).toEqual([EPersonMock, EPersonMock2]); + expect(component.selectedReviewersUpdated.emit).toHaveBeenCalledWith([EPersonMock, EPersonMock2]); }); it('should delete the member when present', () => { spyOn(component.selectedReviewersUpdated, 'emit'); - ePersonDtoModel1.memberOfGroup = true; - component.selectedReviewers = [ePersonDtoModel1]; + component.selectedReviewers = [EPersonMock]; - component.deleteMemberFromGroup(ePersonDtoModel1); + component.deleteMemberFromGroup(EPersonMock); expect(component.selectedReviewers).toEqual([]); - expect(ePersonDtoModel1.memberOfGroup).toBeFalse(); expect(component.selectedReviewersUpdated.emit).toHaveBeenCalledWith([]); }); diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts index 6984a1d86d..65a106e2e8 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts @@ -8,10 +8,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat import { PaginationService } from '../../../../core/pagination/pagination.service'; import { Group } from '../../../../core/eperson/models/group.model'; import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; -import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.model'; import { EPerson } from '../../../../core/eperson/models/eperson.model'; -import { Observable, of as observableOf } from 'rxjs'; -import { hasValue } from '../../../../shared/empty.util'; import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { MembersListComponent, @@ -24,8 +21,8 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; */ enum SubKey { ActiveGroup, - MembersDTO, - SearchResultsDTO, + Members, + SearchResults, } /** @@ -50,7 +47,7 @@ export class ReviewersListComponent extends MembersListComponent implements OnIn @Output() selectedReviewersUpdated: EventEmitter = new EventEmitter(); - selectedReviewers: EpersonDtoModel[] = []; + selectedReviewers: EPerson[] = []; constructor( protected groupService: GroupDataService, @@ -100,54 +97,40 @@ export class ReviewersListComponent extends MembersListComponent implements OnIn retrieveMembers(page: number): void { this.config.currentPage = page; if (this.groupId === null) { - this.unsubFrom(SubKey.MembersDTO); - const paginatedListOfDTOs: PaginatedList = new PaginatedList(); - paginatedListOfDTOs.page = this.selectedReviewers; - this.ePeopleMembersOfGroupDtos.next(paginatedListOfDTOs); + this.unsubFrom(SubKey.Members); + const paginatedListOfEPersons: PaginatedList = new PaginatedList(); + paginatedListOfEPersons.page = this.selectedReviewers; + this.ePeopleMembersOfGroup.next(paginatedListOfEPersons); } else { super.retrieveMembers(page); } } /** - * Checks whether the given {@link possibleMember} is part of the {@link selectedReviewers}. + * Removes the {@link eperson} from the {@link selectedReviewers} * - * @param possibleMember The {@link EPerson} that needs to be checked + * @param eperson The {@link EPerson} to remove */ - isMemberOfGroup(possibleMember: EPerson): Observable { - return observableOf(hasValue(this.selectedReviewers.find((reviewer: EpersonDtoModel) => reviewer.eperson.id === possibleMember.id))); - } - - /** - * Removes the {@link ePerson} from the {@link selectedReviewers} - * - * @param ePerson The {@link EpersonDtoModel} containg the {@link EPerson} to remove - */ - deleteMemberFromGroup(ePerson: EpersonDtoModel) { - ePerson.memberOfGroup = false; - const index = this.selectedReviewers.indexOf(ePerson); + deleteMemberFromGroup(eperson: EPerson) { + const index = this.selectedReviewers.indexOf(eperson); if (index !== -1) { this.selectedReviewers.splice(index, 1); } - this.selectedReviewersUpdated.emit(this.selectedReviewers.map((ePersonDtoModel: EpersonDtoModel) => ePersonDtoModel.eperson)); + this.selectedReviewersUpdated.emit(this.selectedReviewers); } /** - * Adds the {@link ePerson} to the {@link selectedReviewers} (or replaces it when {@link multipleReviewers} is + * Adds the {@link eperson} to the {@link selectedReviewers} (or replaces it when {@link multipleReviewers} is * `false`). Afterwards it will emit the list. * - * @param ePerson The {@link EPerson} to add to the list + * @param eperson The {@link EPerson} to add to the list */ - addMemberToGroup(ePerson: EpersonDtoModel) { - ePerson.memberOfGroup = true; + addMemberToGroup(eperson: EPerson) { if (!this.multipleReviewers) { - for (const selectedReviewer of this.selectedReviewers) { - selectedReviewer.memberOfGroup = false; - } this.selectedReviewers = []; } - this.selectedReviewers.push(ePerson); - this.selectedReviewersUpdated.emit(this.selectedReviewers.map((epersonDtoModel: EpersonDtoModel) => epersonDtoModel.eperson)); + this.selectedReviewers.push(eperson); + this.selectedReviewersUpdated.emit(this.selectedReviewers); } } From 64f968b246774140b2e3d4f134be7608ab7a6207 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 2 Oct 2023 16:35:26 -0500 Subject: [PATCH 042/153] Fix subgroups-list specs so they align with new members-list specs --- .../subgroups-list.component.spec.ts | 188 ++++++++++-------- 1 file changed, 104 insertions(+), 84 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index ac5750dcac..7bbbb24f30 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -1,12 +1,12 @@ import { CommonModule } from '@angular/common'; import { NO_ERRORS_SCHEMA, DebugElement } from '@angular/core'; -import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, inject, TestBed, waitForAsync } from '@angular/core/testing'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule, By } from '@angular/platform-browser'; import { Router } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { Observable, of as observableOf, BehaviorSubject } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { RestResponse } from '../../../../core/cache/response.models'; import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; @@ -18,19 +18,18 @@ import { NotificationsService } from '../../../../shared/notifications/notificat import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; import { SubgroupsListComponent } from './subgroups-list.component'; import { - createSuccessfulRemoteDataObject$, - createSuccessfulRemoteDataObject + createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; import { RouterMock } from '../../../../shared/mocks/router.mock'; import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock'; import { getMockTranslateService } from '../../../../shared/mocks/translate.service.mock'; import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; -import { map } from 'rxjs/operators'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../shared/mocks/dso-name.service.mock'; +import { EPersonMock2 } from 'src/app/shared/testing/eperson.mock'; describe('SubgroupsListComponent', () => { let component: SubgroupsListComponent; @@ -39,44 +38,70 @@ describe('SubgroupsListComponent', () => { let builderService: FormBuilderService; let ePersonDataServiceStub: any; let groupsDataServiceStub: any; - let activeGroup; + let activeGroup: Group; let subgroups: Group[]; - let allGroups: Group[]; + let groupNonMembers: Group[]; let routerStub; let paginationService; + // Define a new mock activegroup for all tests below + let mockActiveGroup: Group = Object.assign(new Group(), { + handle: null, + subgroups: [GroupMock2], + epersons: [EPersonMock2], + selfRegistered: false, + permanent: false, + _links: { + self: { + href: 'https://rest.api/server/api/eperson/groups/activegroupid', + }, + subgroups: { href: 'https://rest.api/server/api/eperson/groups/activegroupid/subgroups' }, + object: { href: 'https://rest.api/server/api/eperson/groups/activegroupid/object' }, + epersons: { href: 'https://rest.api/server/api/eperson/groups/activegroupid/epersons' } + }, + _name: 'activegroupname', + id: 'activegroupid', + uuid: 'activegroupid', + type: 'group', + }); beforeEach(waitForAsync(() => { - activeGroup = GroupMock; + activeGroup = mockActiveGroup; subgroups = [GroupMock2]; - allGroups = [GroupMock, GroupMock2]; + groupNonMembers = [GroupMock]; ePersonDataServiceStub = {}; groupsDataServiceStub = { activeGroup: activeGroup, - subgroups$: new BehaviorSubject(subgroups), + subgroups: subgroups, + groupNonMembers: groupNonMembers, getActiveGroup(): Observable { return observableOf(this.activeGroup); }, getSubgroups(): Group { - return this.activeGroup; + return this.subgroups; }, + // This method is used to get all the current subgroups findListByHref(_href: string): Observable>> { - return this.subgroups$.pipe( - map((currentGroups: Group[]) => { - return createSuccessfulRemoteDataObject(buildPaginatedList(new PageInfo(), currentGroups)); - }) - ); + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), groupsDataServiceStub.getSubgroups())); }, getGroupEditPageRouterLink(group: Group): string { return '/access-control/groups/' + group.id; }, + // This method is used to get all groups which are NOT currently a subgroup member searchGroups(query: string): Observable>> { if (query === '') { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allGroups)); + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), groupNonMembers)); } return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); }, - addSubGroupToGroup(parentGroup, subgroup: Group): Observable { - this.subgroups$.next([...this.subgroups$.getValue(), subgroup]); + addSubGroupToGroup(parentGroup, subgroupToAdd: Group): Observable { + // Add group to list of subgroups + this.subgroups = [...this.subgroups, subgroupToAdd]; + // Remove group from list of non-members + this.groupNonMembers.forEach( (group: Group, index: number) => { + if (group.id === subgroupToAdd.id) { + this.groupNonMembers.splice(index, 1); + } + }); return observableOf(new RestResponse(true, 200, 'Success')); }, clearGroupsRequests() { @@ -85,12 +110,15 @@ describe('SubgroupsListComponent', () => { clearGroupLinkRequests() { // empty }, - deleteSubGroupFromGroup(parentGroup, subgroup: Group): Observable { - this.subgroups$.next(this.subgroups$.getValue().filter((group: Group) => { - if (group.id !== subgroup.id) { - return group; + deleteSubGroupFromGroup(parentGroup, subgroupToDelete: Group): Observable { + // Remove group from list of subgroups + this.subgroups.forEach( (group: Group, index: number) => { + if (group.id === subgroupToDelete.id) { + this.subgroups.splice(index, 1); } - })); + }); + // Add group to list of non-members + this.groupNonMembers = [...this.groupNonMembers, subgroupToDelete]; return observableOf(new RestResponse(true, 200, 'Success')); } }; @@ -99,7 +127,7 @@ describe('SubgroupsListComponent', () => { translateService = getMockTranslateService(); paginationService = new PaginationServiceStub(); - TestBed.configureTestingModule({ + return TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ loader: { @@ -137,30 +165,38 @@ describe('SubgroupsListComponent', () => { expect(comp).toBeDefined(); })); - it('should show list of subgroups of current active group', () => { - const groupIdsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tr td:first-child')); - expect(groupIdsFound.length).toEqual(1); - activeGroup.subgroups.map((group: Group) => { - expect(groupIdsFound.find((foundEl) => { - return (foundEl.nativeElement.textContent.trim() === group.uuid); - })).toBeTruthy(); - }); - }); - - describe('if first group delete button is pressed', () => { - let groupsFound: DebugElement[]; - beforeEach(fakeAsync(() => { - const addButton = fixture.debugElement.query(By.css('#subgroupsOfGroup tbody .deleteButton')); - addButton.triggerEventHandler('click', { - preventDefault: () => {/**/ - } + describe('current subgroup list', () => { + it('should show list of subgroups of current active group', () => { + const groupIdsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tr td:first-child')); + expect(groupIdsFound.length).toEqual(1); + subgroups.map((group: Group) => { + expect(groupIdsFound.find((foundEl) => { + return (foundEl.nativeElement.textContent.trim() === group.uuid); + })).toBeTruthy(); + }); + }); + + it('should show a delete button next to each subgroup', () => { + const subgroupsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tbody tr')); + subgroupsFound.map((foundGroupRowElement: DebugElement) => { + const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus')); + const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt')); + expect(addButton).toBeNull(); + expect(deleteButton).not.toBeNull(); + }); + }); + + describe('if first group delete button is pressed', () => { + let groupsFound: DebugElement[]; + beforeEach(() => { + const deleteButton = fixture.debugElement.query(By.css('#subgroupsOfGroup tbody .deleteButton')); + deleteButton.nativeElement.click(); + fixture.detectChanges(); + }); + it('then no subgroup remains as a member of the active group', () => { + groupsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tbody tr')); + expect(groupsFound.length).toEqual(0); }); - tick(); - fixture.detectChanges(); - })); - it('one less subgroup in list from 1 to 0 (of 2 total groups)', () => { - groupsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tbody tr')); - expect(groupsFound.length).toEqual(0); }); }); @@ -169,54 +205,38 @@ describe('SubgroupsListComponent', () => { let groupsFound: DebugElement[]; beforeEach(fakeAsync(() => { component.search({ query: '' }); + fixture.detectChanges(); groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr')); })); - it('should display all groups', () => { - fixture.detectChanges(); - groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr')); - expect(groupsFound.length).toEqual(2); - groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr')); + it('should display only non-member groups (i.e. groups that are not a subgroup)', () => { const groupIdsFound: DebugElement[] = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr td:first-child')); - allGroups.map((group: Group) => { + expect(groupIdsFound.length).toEqual(1); + groupNonMembers.map((group: Group) => { expect(groupIdsFound.find((foundEl: DebugElement) => { return (foundEl.nativeElement.textContent.trim() === group.uuid); })).toBeTruthy(); }); }); - describe('if group is already a subgroup', () => { - it('should have delete button, else it should have add button', () => { + it('should display an add button next to non-member groups, not a delete button', () => { + groupsFound.map((foundGroupRowElement: DebugElement) => { + const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus')); + const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt')); + expect(addButton).not.toBeNull(); + expect(deleteButton).toBeNull(); + }); + }); + + describe('if first add button is pressed', () => { + beforeEach(() => { + const addButton: DebugElement = fixture.debugElement.query(By.css('#groupsSearch tbody .fa-plus')); + addButton.nativeElement.click(); fixture.detectChanges(); + }); + it('then all (two) Groups are subgroups of the active group. No non-members left', () => { groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr')); - const getSubgroups = groupsDataServiceStub.getSubgroups().subgroups; - if (getSubgroups !== undefined && getSubgroups.length > 0) { - groupsFound.map((foundGroupRowElement: DebugElement) => { - const groupId: DebugElement = foundGroupRowElement.query(By.css('td:first-child')); - const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus')); - const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt')); - expect(addButton).toBeNull(); - if (activeGroup.id === groupId.nativeElement.textContent) { - expect(deleteButton).toBeNull(); - } else { - expect(deleteButton).not.toBeNull(); - } - }); - } else { - const subgroupIds: string[] = activeGroup.subgroups.map((group: Group) => group.id); - groupsFound.map((foundGroupRowElement: DebugElement) => { - const groupId: DebugElement = foundGroupRowElement.query(By.css('td:first-child')); - const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus')); - const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt')); - if (subgroupIds.includes(groupId.nativeElement.textContent)) { - expect(addButton).toBeNull(); - expect(deleteButton).not.toBeNull(); - } else { - expect(deleteButton).toBeNull(); - expect(addButton).not.toBeNull(); - } - }); - } + expect(groupsFound.length).toEqual(0); }); }); }); From 8a10888d2ad7916570472173070370da61320a72 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 13 Oct 2023 14:43:28 -0500 Subject: [PATCH 043/153] Refactor members-list and subgroups-list components to use new isNotMemberOf endpoints (via services) --- .../members-list/members-list.component.html | 10 +---- .../members-list.component.spec.ts | 2 +- .../members-list/members-list.component.ts | 30 +++++++------ .../subgroups-list.component.html | 5 +-- .../subgroups-list.component.spec.ts | 2 +- .../subgroup-list/subgroups-list.component.ts | 35 +++++++--------- .../core/eperson/eperson-data.service.spec.ts | 25 +++++++++++ src/app/core/eperson/eperson-data.service.ts | 28 +++++++++++++ .../core/eperson/group-data.service.spec.ts | 28 ++++++++++++- src/app/core/eperson/group-data.service.ts | 42 +++++++++++-------- src/assets/i18n/en.json5 | 10 ----- 11 files changed, 139 insertions(+), 78 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html index 0f5010e08e..e185d37e28 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html @@ -15,14 +15,8 @@
-
- -
-
-
+
+
diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 76e38067bc..5d97dcade8 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -56,7 +56,7 @@ describe('MembersListComponent', () => { return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), groupsDataServiceStub.getEPersonMembers())); }, // This method is used to search across *non-members* - searchByScope(scope: string, query: string): Observable>> { + searchNonMembers(query: string, group: string): Observable>> { if (query === '') { return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), epersonNonMembers)); } diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index e828555a80..4924f3168b 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -124,7 +124,6 @@ export class MembersListComponent implements OnInit, OnDestroy { // Current search in edit group - epeople search form currentSearchQuery: string; - currentSearchScope: string; // Whether or not user has done a EPeople search yet searchDone: boolean; @@ -143,12 +142,10 @@ export class MembersListComponent implements OnInit, OnDestroy { public dsoNameService: DSONameService, ) { this.currentSearchQuery = ''; - this.currentSearchScope = 'metadata'; } ngOnInit(): void { this.searchForm = this.formBuilder.group(({ - scope: 'metadata', query: '', })); this.subs.set(SubKey.ActiveGroup, this.groupDataService.getActiveGroup().subscribe((activeGroup: Group) => { @@ -213,6 +210,11 @@ export class MembersListComponent implements OnInit, OnDestroy { if (activeGroup != null) { const response = this.groupDataService.deleteMemberFromGroup(activeGroup, eperson); this.showNotifications('deleteMember', response, this.dsoNameService.getName(eperson), activeGroup); + // Reload search results (if there is an active query). + // This will potentially add this deleted subgroup into the list of search results. + if (this.currentSearchQuery != null) { + this.search({query: this.currentSearchQuery}); + } } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); } @@ -228,6 +230,11 @@ export class MembersListComponent implements OnInit, OnDestroy { if (activeGroup != null) { const response = this.groupDataService.addMemberToGroup(activeGroup, eperson); this.showNotifications('addMember', response, this.dsoNameService.getName(eperson), activeGroup); + // Reload search results (if there is an active query). + // This will potentially add this deleted subgroup into the list of search results. + if (this.currentSearchQuery != null) { + this.search({query: this.currentSearchQuery}); + } } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); } @@ -235,17 +242,15 @@ export class MembersListComponent implements OnInit, OnDestroy { } /** - * Search in the EPeople by name, email or metadata - * @param data Contains scope and query param + * Search all EPeople who are NOT a member of the current group by name, email or metadata + * @param data Contains query param */ search(data: any) { this.unsubFrom(SubKey.SearchResults); this.subs.set(SubKey.SearchResults, this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( switchMap((paginationOptions) => { - const query: string = data.query; - const scope: string = data.scope; if (query != null && this.currentSearchQuery !== query && this.groupBeingEdited) { this.router.navigate([], { queryParamsHandling: 'merge' @@ -253,19 +258,12 @@ export class MembersListComponent implements OnInit, OnDestroy { this.currentSearchQuery = query; this.paginationService.resetPage(this.configSearch.id); } - if (scope != null && this.currentSearchScope !== scope && this.groupBeingEdited) { - this.router.navigate([], { - queryParamsHandling: 'merge' - }); - this.currentSearchScope = scope; - this.paginationService.resetPage(this.configSearch.id); - } this.searchDone = true; - return this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + return this.ePersonDataService.searchNonMembers(this.currentSearchQuery, this.groupBeingEdited.id, { currentPage: paginationOptions.currentPage, elementsPerPage: paginationOptions.pageSize - }); + }, false, true); }), getAllCompletedRemoteData(), map((rd: RemoteData) => { diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html index 8268eb5eb4..d97272ec6f 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html @@ -62,10 +62,7 @@
{{ dsoNameService.getName((group.object | async)?.payload) }}
- {{ messagePrefix + '.table.edit.currentGroup' | translate }} - -
diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.ts b/src/app/item-page/edit-item-page/item-status/item-status.component.ts index 828f8d7439..8e04985c18 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.ts @@ -3,21 +3,20 @@ import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; import { Item } from '../../../core/shared/item.model'; import { ActivatedRoute } from '@angular/router'; import { ItemOperation } from '../item-operation/itemOperation.model'; -import { distinctUntilChanged, map, mergeMap, switchMap, toArray } from 'rxjs/operators'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { concatMap, distinctUntilChanged, first, map, mergeMap, switchMap, toArray } from 'rxjs/operators'; +import { BehaviorSubject, combineLatest, Observable, of, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { getItemEditRoute, getItemPageRoute } from '../../item-page-routing-paths'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { hasValue, isNotEmpty } from '../../../shared/empty.util'; -import { - getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData, getRemoteDataPayload, -} from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; +import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, } from '../../../core/shared/operators'; import { IdentifierDataService } from '../../../core/data/identifier-data.service'; import { Identifier } from '../../../shared/object-list/identifier-data/identifier.model'; import { ConfigurationProperty } from '../../../core/shared/configuration-property.model'; import { ConfigurationDataService } from '../../../core/data/configuration-data.service'; import { IdentifierData } from '../../../shared/object-list/identifier-data/identifier-data.model'; +import { OrcidAuthService } from '../../../core/orcid/orcid-auth.service'; @Component({ selector: 'ds-item-status', @@ -73,6 +72,7 @@ export class ItemStatusComponent implements OnInit { private authorizationService: AuthorizationDataService, private identifierDataService: IdentifierDataService, private configurationService: ConfigurationDataService, + private orcidAuthService: OrcidAuthService ) { } @@ -82,14 +82,16 @@ export class ItemStatusComponent implements OnInit { ngOnInit(): void { this.itemRD$ = this.route.parent.data.pipe(map((data) => data.dso)); this.itemRD$.pipe( + first(), map((data: RemoteData) => data.payload) - ).subscribe((item: Item) => { - this.statusData = Object.assign({ - id: item.id, - handle: item.handle, - lastModified: item.lastModified - }); - this.statusDataKeys = Object.keys(this.statusData); + ).pipe( + switchMap((item: Item) => { + this.statusData = Object.assign({ + id: item.id, + handle: item.handle, + lastModified: item.lastModified + }); + this.statusDataKeys = Object.keys(this.statusData); // Observable for item identifiers (retrieved from embedded link) this.identifiers$ = this.identifierDataService.getIdentifierDataFor(item).pipe( @@ -105,99 +107,108 @@ export class ItemStatusComponent implements OnInit { // Observable for configuration determining whether the Register DOI feature is enabled let registerConfigEnabled$: Observable = this.configurationService.findByPropertyName('identifiers.item-status.register-doi').pipe( getFirstCompletedRemoteData(), - map((rd: RemoteData) => { - // If the config property is exposed via rest and has a value set, return it - if (rd.hasSucceeded && hasValue(rd.payload) && isNotEmpty(rd.payload.values)) { - return rd.payload.values[0] === 'true'; - } - // Otherwise, return false - return false; - }) + map((enabledRD: RemoteData) => enabledRD.hasSucceeded && enabledRD.payload.values.length > 0) ); - /* - Construct a base list of operations. - The key is used to build messages - i18n example: 'item.edit.tabs.status.buttons..label' - The value is supposed to be a href for the button - */ - const operations: ItemOperation[] = []; - operations.push(new ItemOperation('authorizations', this.getCurrentUrl(item) + '/authorizations', FeatureID.CanManagePolicies, true)); - operations.push(new ItemOperation('mappedCollections', this.getCurrentUrl(item) + '/mapper', FeatureID.CanManageMappings, true)); - if (item.isWithdrawn) { - operations.push(new ItemOperation('reinstate', this.getCurrentUrl(item) + '/reinstate', FeatureID.ReinstateItem, true)); - } else { - operations.push(new ItemOperation('withdraw', this.getCurrentUrl(item) + '/withdraw', FeatureID.WithdrawItem, true)); - } - if (item.isDiscoverable) { - operations.push(new ItemOperation('private', this.getCurrentUrl(item) + '/private', FeatureID.CanMakePrivate, true)); - } else { - operations.push(new ItemOperation('public', this.getCurrentUrl(item) + '/public', FeatureID.CanMakePrivate, true)); - } - operations.push(new ItemOperation('delete', this.getCurrentUrl(item) + '/delete', FeatureID.CanDelete, true)); - operations.push(new ItemOperation('move', this.getCurrentUrl(item) + '/move', FeatureID.CanMove, true)); - this.operations$.next(operations); - - /* - When the identifier data stream changes, determine whether the register DOI button should be shown or not. - This is based on whether the DOI is in the right state (minted or pending, not already queued for registration - or registered) and whether the configuration property identifiers.item-status.register-doi is true + /** + * Construct a base list of operations. + * The key is used to build messages + * i18n example: 'item.edit.tabs.status.buttons..label' + * The value is supposed to be a href for the button */ - this.identifierDataService.getIdentifierDataFor(item).pipe( - getFirstSucceededRemoteData(), - getRemoteDataPayload(), - mergeMap((data: IdentifierData) => { - let identifiers = data.identifiers; - let no_doi = true; - let pending = false; - if (identifiers !== undefined && identifiers !== null) { - identifiers.forEach((identifier: Identifier) => { - if (hasValue(identifier) && identifier.identifierType === 'doi') { - // The item has some kind of DOI - no_doi = false; - if (identifier.identifierStatus === 'PENDING' || identifier.identifierStatus === 'MINTED' - || identifier.identifierStatus == null) { - // The item's DOI is pending, minted or null. - // It isn't registered, reserved, queued for registration or reservation or update, deleted - // or queued for deletion. - pending = true; - } + const currentUrl = this.getCurrentUrl(item); + const inititalOperations: ItemOperation[] = [ + new ItemOperation('authorizations', `${currentUrl}/authorizations`, FeatureID.CanManagePolicies, true), + new ItemOperation('mappedCollections', `${currentUrl}/mapper`, FeatureID.CanManageMappings, true), + item.isWithdrawn + ? new ItemOperation('reinstate', `${currentUrl}/reinstate`, FeatureID.ReinstateItem, true) + : new ItemOperation('withdraw', `${currentUrl}/withdraw`, FeatureID.WithdrawItem, true), + item.isDiscoverable + ? new ItemOperation('private', `${currentUrl}/private`, FeatureID.CanMakePrivate, true) + : new ItemOperation('public', `${currentUrl}/public`, FeatureID.CanMakePrivate, true), + new ItemOperation('move', `${currentUrl}/move`, FeatureID.CanMove, true), + new ItemOperation('delete', `${currentUrl}/delete`, FeatureID.CanDelete, true) + ]; + + this.operations$.next(inititalOperations); + + /** + * When the identifier data stream changes, determine whether the register DOI button should be shown or not. + * This is based on whether the DOI is in the right state (minted or pending, not already queued for registration + * or registered) and whether the configuration property identifiers.item-status.register-doi is true + */ + const ops$ = this.identifierDataService.getIdentifierDataFor(item).pipe( + getFirstCompletedRemoteData(), + mergeMap((dataRD: RemoteData) => { + if (dataRD.hasSucceeded) { + let identifiers = dataRD.payload.identifiers; + let no_doi = true; + let pending = false; + if (identifiers !== undefined && identifiers !== null) { + identifiers.forEach((identifier: Identifier) => { + if (hasValue(identifier) && identifier.identifierType === 'doi') { + // The item has some kind of DOI + no_doi = false; + if (['PENDING', 'MINTED', null].includes(identifier.identifierStatus)) { + // The item's DOI is pending, minted or null. + // It isn't registered, reserved, queued for registration or reservation or update, deleted + // or queued for deletion. + pending = true; + } + } + }); } - }); - } - // If there is no DOI, or a pending/minted/null DOI, and the config is enabled, return true - return registerConfigEnabled$.pipe( - map((enabled: boolean) => { - return enabled && (pending || no_doi); + // If there is no DOI, or a pending/minted/null DOI, and the config is enabled, return true + return registerConfigEnabled$.pipe( + map((enabled: boolean) => { + return enabled && (pending || no_doi); + } + )); + } else { + return of(false); + } + }), + // Switch map pushes the register DOI operation onto a copy of the base array then returns to the pipe + switchMap((showDoi: boolean) => { + const ops = [...inititalOperations]; + if (showDoi) { + const op = new ItemOperation('register-doi', `${currentUrl}/register-doi`, FeatureID.CanRegisterDOI, true); + ops.splice(ops.length - 1, 0, op); // Add item before last + } + return inititalOperations; + }), + concatMap((op: ItemOperation) => { + if (hasValue(op.featureID)) { + return this.authorizationService.isAuthorized(op.featureID, item.self).pipe( + distinctUntilChanged(), + map((authorized) => { + op.setDisabled(!authorized); + op.setAuthorized(authorized); + return op; + }) + ); } - )); - }), - // Switch map pushes the register DOI operation onto a copy of the base array then returns to the pipe - switchMap((showDoi: boolean) => { - let ops = [...operations]; - if (showDoi) { - ops.push(new ItemOperation('register-doi', this.getCurrentUrl(item) + '/register-doi', FeatureID.CanRegisterDOI, true)); - } - return ops; - }), - // Merge map checks and transforms each operation in the array based on whether it is authorized or not (disabled) - mergeMap((op: ItemOperation) => { - if (hasValue(op.featureID)) { - return this.authorizationService.isAuthorized(op.featureID, item.self).pipe( - distinctUntilChanged(), - map((authorized) => new ItemOperation(op.operationKey, op.operationUrl, op.featureID, !authorized, authorized)) - ); - } else { return [op]; - } - }), - // Wait for all operations to be emitted and return as an array - toArray(), - ).subscribe((data) => { - // Update the operations$ subject that draws the administrative buttons on the status page - this.operations$.next(data); - }); - }); + }), + toArray() + ); + + let orcidOps$ = of([]); + if (this.orcidAuthService.isLinkedToOrcid(item)) { + orcidOps$ = this.orcidAuthService.onlyAdminCanDisconnectProfileFromOrcid().pipe( + map((canDisconnect) => { + if (canDisconnect) { + return [new ItemOperation('unlinkOrcid', `${currentUrl}/unlink-orcid`)]; + } + return []; + }) + ); + } + + return combineLatest([ops$, orcidOps$]); + }), + map(([ops, orcidOps]: [ItemOperation[], ItemOperation[]]) => [...ops, ...orcidOps]) + ).subscribe((ops) => this.operations$.next(ops)); this.itemPageRoute$ = this.itemRD$.pipe( getAllSucceededRemoteDataPayload(), @@ -206,6 +217,7 @@ export class ItemStatusComponent implements OnInit { } + /** * Get the current url without query params * @returns {string} url From fbbbc18844b44f6f56b7c5f1f5e07e4886877d20 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Mon, 13 Nov 2023 15:02:27 +0100 Subject: [PATCH 063/153] refactor: code --- .../item-status/item-status.component.spec.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.spec.ts b/src/app/item-page/edit-item-page/item-status/item-status.component.spec.ts index a67de2f435..17ac3efa09 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.spec.ts @@ -16,6 +16,7 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { IdentifierDataService } from '../../../core/data/identifier-data.service'; import { ConfigurationDataService } from '../../../core/data/configuration-data.service'; import { ConfigurationProperty } from '../../../core/shared/configuration-property.model'; +import { OrcidAuthService } from '../../../core/orcid/orcid-auth.service'; let mockIdentifierDataService: IdentifierDataService; let mockConfigurationDataService: ConfigurationDataService; @@ -57,12 +58,18 @@ describe('ItemStatusComponent', () => { }; let authorizationService: AuthorizationDataService; + let orcidAuthService: any; beforeEach(waitForAsync(() => { authorizationService = jasmine.createSpyObj('authorizationService', { isAuthorized: observableOf(true) }); + orcidAuthService = jasmine.createSpyObj('OrcidAuthService', { + onlyAdminCanDisconnectProfileFromOrcid: observableOf ( true ), + isLinkedToOrcid: true + }); + TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [ItemStatusComponent], @@ -71,7 +78,8 @@ describe('ItemStatusComponent', () => { { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, { provide: AuthorizationDataService, useValue: authorizationService }, { provide: IdentifierDataService, useValue: mockIdentifierDataService }, - { provide: ConfigurationDataService, useValue: mockConfigurationDataService } + { provide: ConfigurationDataService, useValue: mockConfigurationDataService }, + { provide: OrcidAuthService, useValue: orcidAuthService }, ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); })); From 394dc677471231d5b09bb25c2c976b8ceab70422 Mon Sep 17 00:00:00 2001 From: Thomas Misilo Date: Thu, 16 Nov 2023 11:36:06 -0600 Subject: [PATCH 064/153] Setup the Docker GH Action for Matrix Building This change enables building of the amd64 and arm64 images simultaneously. Once both images finish, the manifest is sent to Docker Hub, allowing for a single image that has both the amd64/arm64 images. --- .github/workflows/docker.yml | 173 +++++++++++++++++++++++++++++++---- 1 file changed, 153 insertions(+), 20 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0c36d5af98..18bdef78be 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,6 +17,7 @@ permissions: env: + REGISTRY_IMAGE: dspace/dspace-angular # Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action) # For a new commit on default branch (main), use the literal tag 'latest' on Docker image. # For a new commit on other branches, use the branch name as the tag for Docker image. @@ -30,21 +31,30 @@ env: # We manage the 'latest' tag ourselves to the 'main' branch (see settings above) TAGS_FLAVOR: | latest=false - # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. - PLATFORMS: linux/amd64${{ github.event_name != 'pull_request' && ', linux/arm64' || '' }} - jobs: - ############################################### - # Build/Push the 'dspace/dspace-angular' image - ############################################### + ############################################################# + # Build/Push the '${{ env.REGISTRY_IMAGE }}' image + ############################################################# dspace-angular: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - runs-on: ubuntu-latest + strategy: + matrix: + isPr: + - ${{ github.event_name == 'pull_request' }} + # Architectures / Platforms for which we will build Docker images + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. + arch: ['linux/amd64', 'linux/arm64'] + os: [ubuntu-latest] + exclude: + - isPr: true + os: ubuntu-latest + arch: linux/arm64 + + runs-on: ${{ matrix.os }} steps: # https://github.com/actions/checkout - name: Checkout codebase @@ -61,7 +71,7 @@ jobs: # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: github.event_name != 'pull_request' + if: ${{ ! matrix.isPr }} uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} @@ -73,7 +83,7 @@ jobs: id: meta_build uses: docker/metadata-action@v4 with: - images: dspace/dspace-angular + images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} @@ -84,22 +94,89 @@ jobs: with: context: . file: ./Dockerfile - platforms: ${{ env.PLATFORMS }} + platforms: ${{ matrix.arch }} # For pull requests, we run the Docker build (to ensure no PR changes break the build), # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ github.event_name != 'pull_request' }} + push: ${{ ! matrix.isPr }} # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} + - name: Export digest + if: ${{ ! matrix.isPr }} + run: | + mkdir -p /tmp/digests + digest="${{ steps.docker_build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + if: ${{ ! matrix.isPr }} + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - dspace-angular + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: ${{ env.IMAGE_TAGS }} + flavor: ${{ env.TAGS_FLAVOR }} + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} + ############################################################# - # Build/Push the 'dspace/dspace-angular' image ('-dist' tag) + # Build/Push the '${{ env.REGISTRY_IMAGE }}' image ('-dist' tag) ############################################################# dspace-angular-dist: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - runs-on: ubuntu-latest + strategy: + matrix: + isPr: + - ${{ github.event_name == 'pull_request' }} + # Architectures / Platforms for which we will build Docker images + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. + arch: ['linux/amd64', 'linux/arm64'] + os: [ubuntu-latest] + exclude: + - isPr: true + os: ubuntu-latest + arch: linux/arm64 + + runs-on: ${{ matrix.os }} steps: # https://github.com/actions/checkout - name: Checkout codebase @@ -116,7 +193,7 @@ jobs: # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: github.event_name != 'pull_request' + if: ${{ ! matrix.isPr }} uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} @@ -128,10 +205,10 @@ jobs: id: meta_build_dist uses: docker/metadata-action@v4 with: - images: dspace/dspace-angular + images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same - # tagging logic as the primary 'dspace/dspace-angular' image above. + # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. flavor: ${{ env.TAGS_FLAVOR }} suffix=-dist @@ -141,10 +218,66 @@ jobs: with: context: . file: ./Dockerfile.dist - platforms: ${{ env.PLATFORMS }} + platforms: ${{ matrix.arch }} # For pull requests, we run the Docker build (to ensure no PR changes break the build), # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ github.event_name != 'pull_request' }} + push: ${{ ! matrix.isPr }} # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build_dist.outputs.tags }} labels: ${{ steps.meta_build_dist.outputs.labels }} + + - name: Export digest + if: ${{ ! matrix.isPr }} + run: | + mkdir -p /tmp/digests/dist + digest="${{ steps.docker_build_dist.outputs.digest }}" + touch "/tmp/digests/dist/${digest#sha256:}" + + - name: Upload digest + if: ${{ ! matrix.isPr }} + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/dist/* + if-no-files-found: error + retention-days: 1 + + merge-dist: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - dspace-angular-dist + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Docker meta + id: meta_dist + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: ${{ env.IMAGE_TAGS }} + # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same + # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. + flavor: ${{ env.TAGS_FLAVOR }} + suffix=-dist + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests/dist + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} From 41eba0dc2fac4c20d8d9cf5511eb1e7e50a51b44 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 09:31:09 -0600 Subject: [PATCH 065/153] Fix bug in Docker manifest. Each build must use a separate artifact to store digests. Other minor cleanup & comments added. --- .github/workflows/docker.yml | 81 ++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 18bdef78be..23919d573c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -42,13 +42,13 @@ jobs: strategy: matrix: - isPr: - - ${{ github.event_name == 'pull_request' }} # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. arch: ['linux/amd64', 'linux/arm64'] os: [ubuntu-latest] + isPr: + - ${{ github.event_name == 'pull_request' }} + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # The below exclude therefore ensures we do NOT build ARM64 for PRs. exclude: - isPr: true os: ubuntu-latest @@ -58,21 +58,21 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} @@ -81,7 +81,7 @@ jobs: # Get Metadata for docker_build step below - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular' image id: meta_build - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} @@ -90,7 +90,7 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push 'dspace-angular' image id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile @@ -102,6 +102,7 @@ jobs: tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} + # Export the digest of Docker build locally (for non PRs only) - name: Export digest if: ${{ ! matrix.isPr }} run: | @@ -109,6 +110,7 @@ jobs: digest="${{ steps.docker_build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" + # Upload digest to an artifact, so that it can be used in manifest below - name: Upload digest if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v3 @@ -118,7 +120,12 @@ jobs: if-no-files-found: error retention-days: 1 - merge: + # Merge digests into a manifest. + # This runs after all Docker builds complete above, and it tells hub.docker.com + # that these builds should be all included in the manifest for this tag. + # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + # Borrowed from https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners + dspace-angular_manifest: if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: @@ -129,9 +136,11 @@ jobs: with: name: digests path: /tmp/digests + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Docker meta + + - name: Add Docker metadata for image id: meta uses: docker/metadata-action@v5 with: @@ -145,7 +154,7 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Create manifest list and push + - name: Create manifest list from digests and push working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ @@ -164,13 +173,13 @@ jobs: strategy: matrix: - isPr: - - ${{ github.event_name == 'pull_request' }} # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. arch: ['linux/amd64', 'linux/arm64'] os: [ubuntu-latest] + isPr: + - ${{ github.event_name == 'pull_request' }} + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # The below exclude therefore ensures we do NOT build ARM64 for PRs. exclude: - isPr: true os: ubuntu-latest @@ -180,21 +189,21 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} @@ -203,7 +212,7 @@ jobs: # Get Metadata for docker_build_dist step below - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular-dist' image id: meta_build_dist - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} @@ -214,7 +223,7 @@ jobs: - name: Build and push 'dspace-angular-dist' image id: docker_build_dist - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile.dist @@ -226,6 +235,7 @@ jobs: tags: ${{ steps.meta_build_dist.outputs.tags }} labels: ${{ steps.meta_build_dist.outputs.labels }} + # Export the digest of Docker build locally (for non PRs only) - name: Export digest if: ${{ ! matrix.isPr }} run: | @@ -233,29 +243,38 @@ jobs: digest="${{ steps.docker_build_dist.outputs.digest }}" touch "/tmp/digests/dist/${digest#sha256:}" + # Upload Digest to an artifact, so that it can be used in manifest below - name: Upload digest if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v3 with: - name: digests - path: /tmp/digests/dist/* + # NOTE: It's important that this artifact has a unique name so that two + # image builds don't upload digests to the same artifact. + name: digests-dist + path: /tmp/digests/* if-no-files-found: error retention-days: 1 - merge-dist: + # Merge *-dist digests into a manifest. + # This runs after all Docker builds complete above, and it tells hub.docker.com + # that these builds should be all included in the manifest for this tag. + # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + dspace-angular-dist_manifest: if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: - dspace-angular-dist steps: - - name: Download digests + - name: Download digests for -dist builds uses: actions/download-artifact@v3 with: - name: digests + name: digests-dist path: /tmp/digests + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Docker meta + + - name: Add Docker metadata for image id: meta_dist uses: docker/metadata-action@v5 with: @@ -272,8 +291,8 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Create manifest list and push - working-directory: /tmp/digests/dist + - name: Create manifest list from digests and push + working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) From 9f12ca3265299160dd93ecc6e0cadfd5aeec9117 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 11:05:46 -0600 Subject: [PATCH 066/153] Update GH actions to latest versions. Fix bug in codecov to ensure it retries on error. --- .github/workflows/build.yml | 16 ++++++++++------ .github/workflows/codescan.yml | 2 +- .github/workflows/port_merged_pull_request.yml | 4 ++-- .github/workflows/pull_request_opened.yml | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 219074780e..e2680420a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,11 +43,11 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/actions/setup-node - name: Install Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} @@ -118,7 +118,7 @@ jobs: # https://github.com/cypress-io/github-action # (NOTE: to run these e2e tests locally, just use 'ng e2e') - name: Run e2e tests (integration tests) - uses: cypress-io/github-action@v5 + uses: cypress-io/github-action@v6 with: # Run tests in Chrome, headless mode (default) browser: chrome @@ -191,7 +191,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Download artifacts from previous 'tests' job - name: Download coverage artifacts @@ -203,10 +203,14 @@ jobs: # Retry action: https://github.com/marketplace/actions/retry-action # Codecov action: https://github.com/codecov/codecov-action - name: Upload coverage to Codecov.io - uses: Wandalen/wretry.action@v1.0.36 + uses: Wandalen/wretry.action@v1.3.0 with: action: codecov/codecov-action@v3 - # Try upload 5 times max + # Ensure codecov-action throws an error when it fails to upload + # This allows us to auto-restart the action if an error is thrown + with: | + fail_ci_if_error: true + # Try re-running action 5 times max attempt_limit: 5 # Run again in 30 seconds attempt_delay: 30000 diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml index 8b415296c7..d96e786cc3 100644 --- a/.github/workflows/codescan.yml +++ b/.github/workflows/codescan.yml @@ -35,7 +35,7 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. # https://github.com/github/codeql-action diff --git a/.github/workflows/port_merged_pull_request.yml b/.github/workflows/port_merged_pull_request.yml index 109835d14d..857f22755e 100644 --- a/.github/workflows/port_merged_pull_request.yml +++ b/.github/workflows/port_merged_pull_request.yml @@ -23,11 +23,11 @@ jobs: if: github.event.pull_request.merged steps: # Checkout code - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Port PR to other branch (ONLY if labeled with "port to") # See https://github.com/korthout/backport-action - name: Create backport pull requests - uses: korthout/backport-action@v1 + uses: korthout/backport-action@v2 with: # Trigger based on a "port to [branch]" label on PR # (This label must specify the branch name to port to) diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml index 9b61af72d1..f16e81c9fd 100644 --- a/.github/workflows/pull_request_opened.yml +++ b/.github/workflows/pull_request_opened.yml @@ -21,4 +21,4 @@ jobs: # Assign the PR to whomever created it. This is useful for visualizing assignments on project boards # See https://github.com/toshimaru/auto-author-assign - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v1.6.2 + uses: toshimaru/auto-author-assign@v2.0.1 From c99fe3a6c1d1a69126ef83d0aadf9489db1edb9e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 11:56:48 -0600 Subject: [PATCH 067/153] Fix directory structure for -dist digests --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 23919d573c..04112f7b70 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -239,9 +239,9 @@ jobs: - name: Export digest if: ${{ ! matrix.isPr }} run: | - mkdir -p /tmp/digests/dist + mkdir -p /tmp/digests digest="${{ steps.docker_build_dist.outputs.digest }}" - touch "/tmp/digests/dist/${digest#sha256:}" + touch "/tmp/digests/${digest#sha256:}" # Upload Digest to an artifact, so that it can be used in manifest below - name: Upload digest From ecca8286b5e8c4d90d9d04e9ea71238dd5046f8e Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 18 Nov 2023 15:24:56 +0100 Subject: [PATCH 068/153] 108587: Deselect all fields on component destruction --- .../metadata-schema/metadata-schema.component.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts index d0827e6e4d..4dec129ead 100644 --- a/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { RegistryService } from '../../../core/registry/registry.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { BehaviorSubject, combineLatest as observableCombineLatest, @@ -32,7 +32,7 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; * A component used for managing all existing metadata fields within the current metadata schema. * The admin can create, edit or delete metadata fields here. */ -export class MetadataSchemaComponent implements OnInit { +export class MetadataSchemaComponent implements OnInit, OnDestroy { /** * The metadata schema */ @@ -60,7 +60,6 @@ export class MetadataSchemaComponent implements OnInit { constructor(private registryService: RegistryService, private route: ActivatedRoute, private notificationsService: NotificationsService, - private router: Router, private paginationService: PaginationService, private translateService: TranslateService) { @@ -86,7 +85,7 @@ export class MetadataSchemaComponent implements OnInit { */ private updateFields() { this.metadataFields$ = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( - switchMap((currentPagination) => combineLatest(this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination))), + switchMap((currentPagination) => combineLatest([this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination)])), switchMap(([schema, update, currentPagination]: [MetadataSchema, boolean, PaginationComponentOptions]) => { if (update) { this.needsUpdate$.next(false); @@ -193,10 +192,10 @@ export class MetadataSchemaComponent implements OnInit { showNotification(success: boolean, amount: number) { const prefix = 'admin.registries.schema.notification'; const suffix = success ? 'success' : 'failure'; - const messages = observableCombineLatest( + const messages = observableCombineLatest([ this.translateService.get(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`), this.translateService.get(`${prefix}.field.deleted.${suffix}`, { amount: amount }) - ); + ]); messages.subscribe(([head, content]) => { if (success) { this.notificationsService.success(head, content); @@ -207,6 +206,7 @@ export class MetadataSchemaComponent implements OnInit { } ngOnDestroy(): void { this.paginationService.clearPagination(this.config.id); + this.registryService.deselectAllMetadataField(); } } From fd645452a54748c8f91c4803279ad3585055a7ed Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 21 Nov 2023 12:15:42 -0600 Subject: [PATCH 069/153] Trigger redeploy of demo/sandbox from GitHub Actions after DockerHub image updated. --- .github/workflows/docker.yml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 23919d573c..7e322caf8b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -23,8 +23,8 @@ env: # For a new commit on other branches, use the branch name as the tag for Docker image. # For a new tag, copy that tag name as the tag for Docker image. IMAGE_TAGS: | - type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} - type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }} + type=raw,value=latest,enable=${{ github.ref_name == github.event.repository.default_branch }} + type=ref,event=branch,enable=${{ github.ref_name != github.event.repository.default_branch }} type=ref,event=tag # Define default tag "flavor" for docker/metadata-action per # https://github.com/docker/metadata-action#flavor-input @@ -300,3 +300,25 @@ jobs: - name: Inspect image run: | docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} + + # Deploy latest -dist image to Demo or Sandbox site, based on the branch updated + dspace-angular-dist_deploy: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + # Requires manifest to be fully updated on DockerHub + - dspace-angular-dist_manifest + steps: + - name: Redeploy sandbox.dspace.org (based on main branch) + if: ${{ github.ref_name == github.event.repository.default_branch }} + run: | + curl -X POST -d '{}' $REDEPLOY_SANDBOX_URL + env: + REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} + + - name: Redeploy demo.dspace.org (based on maintenace branch) + if: ${{ github.ref_name == 'dspace-7_x' }} + run: | + curl -X POST -d '{}' $REDEPLOY_DEMO_URL + env: + REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} From ff677a83d663393cb529c4abc0ba45b96019055c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 22 Nov 2023 10:51:28 -0600 Subject: [PATCH 070/153] Redeploy demo/sandbox more quickly by only waiting for AMD64 image --- .github/workflows/docker.yml | 40 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c482d8f29a..a581b63e7b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -255,6 +255,24 @@ jobs: if-no-files-found: error retention-days: 1 + # If the 'linux/amd64' -dist image was just updated for the 'main' branch, + # Then redeploy https://sandbox.dspace.org using that updated image. + - name: Redeploy sandbox.dspace.org (based on main branch) + if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == github.event.repository.default_branch }} + run: | + curl -X POST $REDEPLOY_SANDBOX_URL + env: + REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} + + # If the 'linux/amd64' -dist image was just updated for the maintenance branch, + # Then redeploy https://demo.dspace.org using that updated image. + - name: Redeploy demo.dspace.org (based on maintenace branch) + if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == 'dspace-7_x' }} + run: | + curl -X POST $REDEPLOY_DEMO_URL + env: + REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} + # Merge *-dist digests into a manifest. # This runs after all Docker builds complete above, and it tells hub.docker.com # that these builds should be all included in the manifest for this tag. @@ -300,25 +318,3 @@ jobs: - name: Inspect image run: | docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} - - # Deploy latest -dist image to Demo or Sandbox site, based on the branch updated - dspace-angular-dist_deploy: - if: ${{ github.event_name != 'pull_request' }} - runs-on: ubuntu-latest - needs: - # Requires manifest to be fully updated on DockerHub - - dspace-angular-dist_manifest - steps: - - name: Redeploy sandbox.dspace.org (based on main branch) - if: ${{ github.ref_name == github.event.repository.default_branch }} - run: | - curl -X POST -d '{}' $REDEPLOY_SANDBOX_URL - env: - REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} - - - name: Redeploy demo.dspace.org (based on maintenace branch) - if: ${{ github.ref_name == 'dspace-7_x' }} - run: | - curl -X POST -d '{}' $REDEPLOY_DEMO_URL - env: - REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} From 430ee3846a2446e16914764e71c1d0c5e739ae2c Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 23 Nov 2023 21:04:02 +0100 Subject: [PATCH 071/153] Fixed ePerson link on edit group page --- .../group-form/members-list/members-list.component.html | 6 ++---- .../members-list/members-list.component.spec.ts | 3 --- .../group-form/members-list/members-list.component.ts | 3 +++ src/app/core/eperson/eperson-data.service.ts | 9 +-------- .../reviewers-list/reviewers-list.component.spec.ts | 3 --- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html index c0c77f44eb..1e61f2cdb2 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html @@ -24,8 +24,7 @@
{{eperson.id}} - + {{ dsoNameService.getName(eperson) }}
{{eperson.id}} - + {{ dsoNameService.getName(eperson) }} {{process.endTime | date:dateFormat:'UTC'}} {{process.processStatus}} - +
- + @@ -31,6 +31,7 @@ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index dbf32bb707..1522723bdd 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3610,6 +3610,14 @@ "resource-policies.table.headers.group": "Group", + "resource-policies.table.headers.select-all": "Select all", + + "resource-policies.table.headers.deselect-all": "Deselect all", + + "resource-policies.table.headers.select": "Select", + + "resource-policies.table.headers.deselect": "Deselect", + "resource-policies.table.headers.id": "ID", "resource-policies.table.headers.name": "Name", From 5b21d14583f8b1ca22f889ee4c24fc7e54579fa7 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sun, 3 Dec 2023 15:15:52 +0100 Subject: [PATCH 087/153] Fix item mapper accessibility issues - Added missing aria-labels to input checkboxes - Fixed role="tablist" not having direct role="tab" by adding role="presentation" on the li elements --- .../collection-item-mapper.component.html | 4 ++-- .../object-select/item-select/item-select.component.html | 4 ++-- src/assets/i18n/en.json5 | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.html b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.html index a48c4d15bf..649aa9b43d 100644 --- a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.html +++ b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.html @@ -6,7 +6,7 @@

{{'collection.edit.item-mapper.description' | translate}}

{{'admin.registries.bitstream-formats.table.id' | translate}} {{'admin.registries.bitstream-formats.table.name' | translate}} {{'admin.registries.bitstream-formats.table.mimetype' | translate}} diff --git a/src/app/shared/resource-policies/resource-policies.component.html b/src/app/shared/resource-policies/resource-policies.component.html index 277f6e4998..b3dda9091d 100644 --- a/src/app/shared/resource-policies/resource-policies.component.html +++ b/src/app/shared/resource-policies/resource-policies.component.html @@ -38,11 +38,13 @@
- - +
{{'resource-policies.table.headers.id' | translate}}
- + @@ -19,7 +19,7 @@ - +
{{'item.select.table.collection' | translate}} {{'item.select.table.author' | translate}} {{'item.select.table.title' | translate}}
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 1522723bdd..3fa71678b8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2508,6 +2508,10 @@ "item.select.empty": "No items to show", + "item.select.table.select": "Select item", + + "item.select.table.deselect": "Deselect item", + "item.select.table.author": "Author", "item.select.table.collection": "Collection", From 1db83ba3c5529fdf8dadddf8431b2dac029cfa0e Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sun, 3 Dec 2023 15:42:13 +0100 Subject: [PATCH 088/153] Fix collection mapper accessibility issues - Added missing aria-labels to input checkboxes - Fixed multiple tab related accessibility issues --- .../item-page/edit-item-page/edit-item-page.component.html | 6 ++++-- .../item-collection-mapper.component.html | 4 ++-- .../collection-select/collection-select.component.html | 4 ++-- src/assets/i18n/en.json5 | 4 ++++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/item-page/edit-item-page/edit-item-page.component.html b/src/app/item-page/edit-item-page/edit-item-page.component.html index c370fe4f20..4aa4c9af16 100644 --- a/src/app/item-page/edit-item-page/edit-item-page.component.html +++ b/src/app/item-page/edit-item-page/edit-item-page.component.html @@ -4,11 +4,13 @@

{{'item.edit.head' | translate}}