From b8e9f620b6da41b4bcdd31f565096b58f1779675 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 18 Feb 2022 16:40:45 +0100 Subject: [PATCH 001/592] [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 00000000000..5c8f8820a00 --- /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 00000000000..ab7a08a695e --- /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 00000000000..df7b21dbdab --- /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 00000000000..b215013e11c --- /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 00000000000..f8e02cabbfe --- /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 00000000000..b1616cfe781 --- /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 00000000000..712c7ba2c3d --- /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 00000000000..5bf1832c595 --- /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 00000000000..ea7242adcb8 --- /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 00000000000..2dfa938c4f7 --- /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 00000000000..9894dac2335 --- /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 3168ea93c92..30f801cecb7 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 ee5cb8737bc..782a7faa380 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 c81b2e6e93b..a2a7eb30b56 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 8d8a614a899..928d34c48e4 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 6bad02e7761..0b4f3af4b45 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 00000000000..2d0d236330e --- /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 00000000000..6e944c8038c --- /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 00000000000..c0be0071ebc --- /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 00000000000..40c65412f52 --- /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 00000000000..58ceb4e671e --- /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 00000000000..3f286e5fead --- /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 00000000000..87aa0b42f0c --- /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 00000000000..3fe39174858 --- /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 00000000000..05d77222911 --- /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 00000000000..267f6a82423 --- /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 00000000000..14ad175e809 --- /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 00000000000..b38da70f376 --- /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 00000000000..1090fd22fcf --- /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 00000000000..7db9839e384 --- /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 00000000000..e19d0a7c867 --- /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 00000000000..5d8cb20c6d2 --- /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 00000000000..fd98c6acb8b --- /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 00000000000..d8321bc932b --- /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 00000000000..e69de29bb2d 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 00000000000..00ea772ff9a --- /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 00000000000..408e21d946f --- /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 00000000000..b590b122f52 --- /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 00000000000..b4ee60558bc --- /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 00000000000..6ae596117f7 --- /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 00000000000..3daed2c3bf4 --- /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 00000000000..17f189922f1 --- /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 00000000000..874d4b4e1a7 --- /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 00000000000..10dd739ae5c --- /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 00000000000..9861c1a921c --- /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 00000000000..ac5d4e72872 --- /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 00000000000..9ead098329e --- /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 00000000000..fc3508eef4a --- /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 00000000000..908aae1f679 --- /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 2a9aa1a0624..e980e733136 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 8f1c6bf26fe..50210c4794d 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 00000000000..2343e12f1aa --- /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 f742273edbe..360e50790a3 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/592] [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 00000000000..89ef1bfc885 --- /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 00000000000..57a79e017bf --- /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 00000000000..f014b4d133e --- /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 b215013e11c..dcf530858cc 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 f8e02cabbfe..d4fd354d92b 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 00000000000..dbdae2e6b9a --- /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 00000000000..c21e0ce73ba --- /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 00000000000..4f60ffd3fdd --- /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 5c8f8820a00..00000000000 --- 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 ab7a08a695e..00000000000 --- 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 df7b21dbdab..00000000000 --- 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 b1616cfe781..00000000000 --- 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 712c7ba2c3d..00000000000 --- 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 5bf1832c595..00000000000 --- 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 ea7242adcb8..469cbb980ff 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 2dfa938c4f7..f1f46ca4f1e 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 9894dac2335..350e9de800b 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 a2a7eb30b56..3e989f16f31 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 928d34c48e4..f5a959592f3 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 2d0d236330e..16d55479ae0 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 6e944c8038c..7f4761009d9 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 c0be0071ebc..2493ae02d1e 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 40c65412f52..ed73168e6d9 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 58ceb4e671e..e7012eee4fe 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 3f286e5fead..d1f2e6ff502 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 87aa0b42f0c..06931e2032c 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 3fe39174858..9f0b93cfb39 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 05d77222911..a9f51cefd09 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.events.title'| translate}}

- {{'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 267f6a82423..40be083567d 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 14ad175e809..b416664fca5 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 e19d0a7c867..7cac576844c 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 5d8cb20c6d2..64672fa1fac 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 fd98c6acb8b..622ecc81414 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 d8321bc932b..02371a8a6b9 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.topics'| translate}}

{{'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 00000000000..e69de29bb2d 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 00000000000..7d18c726c51 --- /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 00000000000..070e03f396f --- /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 00000000000..bd8b3f00cd9 --- /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 00000000000..5395796380c --- /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 00000000000..e80643049c2 --- /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 02371a8a6b9..8b27778ee94 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 3bedf6b9d02..f33d3c2fb10 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 b04229e0d9d..80c52a70a96 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 c81c924465e..cbee503acd1 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 cbc76a5b3eb..39ecded7970 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 4b0ba3cfd18..63224fdd81b 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 b3dc54d5249..27bebbea205 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 7474aa3adc8..0436a35eb30 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 674254e6057..e04792273b8 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/592] [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 | 656 ++++++++++++------ src/app/shared/mocks/notifications.mock.ts | 58 ++ 11 files changed, 948 insertions(+), 227 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 b5eecd112f0..3866797f5d3 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 c4a3611c584..f6d3eb20fe5 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 00000000000..984f44bd15d --- /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 7d18c726c51..6c0ad42ce8a 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(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); - component = fixture.componentInstance; - fixture.detectChanges(); + it('should create NotificationsBrokerSourceComponent', inject([NotificationsBrokerSourceComponent], (app: NotificationsBrokerSourceComponent) => { + expect(app).toBeDefined(); + })); }); - it('should create', () => { - expect(component).toBeTruthy(); + describe('Main tests running with two Source', () => { + beforeEach(() => { + fixture = TestBed.createComponent(NotificationsBrokerSourceComponent); + comp = fixture.componentInstance; + compAsAny = comp; + + }); + + 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 00000000000..74bc77d3ec4 --- /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 00000000000..e94804cbf68 --- /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 5bbe3b29079..dbb81373211 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 f33d3c2fb10..a740ca5c1ee 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 3b780fc173d..e5616df3208 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 97d958e2435..91048a93ef3 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: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMissingPid - ], - processing: false, - loaded: true, - totalPages: 1, - currentPage: 1, - totalElements: 3, - totalLoadedPages: 1 + }; + } 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('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(); + }); - describe('getNotificationsBrokerTopics', () => { - it('Should return an empty array', () => { - const result = service.getNotificationsBrokerTopics(); - const expected = cold('(a)', { - a: [] + 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); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsTotalPages', () => { - it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); - const expected = cold('(a)', { - a: 0 + describe('getNotificationsBrokerTopicsTotalPages', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerTopicsTotalPages(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsCurrentPage', () => { - it('Should return minus one (0)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); - const expected = cold('(a)', { - a: 0 + describe('getNotificationsBrokerTopicsCurrentPage', () => { + it('Should return minus one (0)', () => { + const result = service.getNotificationsBrokerTopicsCurrentPage(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsTotals', () => { - it('Should return zero (0)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); - const expected = cold('(a)', { - a: 0 + describe('getNotificationsBrokerTopicsTotals', () => { + it('Should return zero (0)', () => { + const result = service.getNotificationsBrokerTopicsTotals(); + const expected = cold('(a)', { + a: 0 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('isNotificationsBrokerTopicsLoading', () => { - it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); - const expected = cold('(a)', { - a: true + 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); }); - expect(result).toBeObservable(expected); }); }); - describe('isNotificationsBrokerTopicsLoaded', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); - const expected = cold('(a)', { - a: false + 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 + ] + }); + 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('isNotificationsBrokerTopicsProcessing', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); - const expected = cold('(a)', { - a: false + 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(); + }); + + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); + + 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('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(); - }); + 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 + } + } + }; + } + } + + 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(); + }); - beforeEach(() => { - store = TestBed.get(Store); - service = new NotificationsStateService(store); - serviceAsAny = service; - spyOn(store, 'dispatch'); + 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('getNotificationsBrokerTopics', () => { - it('Should return an array of topics', () => { - const result = service.getNotificationsBrokerTopics(); - const expected = cold('(a)', { - a: [ - notificationsBrokerTopicObjectMorePid, - notificationsBrokerTopicObjectMoreAbstract, - notificationsBrokerTopicObjectMissingPid + 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); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsTotalPages', () => { - it('Should return one (1)', () => { - const result = service.getNotificationsBrokerTopicsTotalPages(); - const expected = cold('(a)', { - a: 1 + describe('getNotificationsBrokerSourceTotalPages', () => { + it('Should return one (1)', () => { + const result = service.getNotificationsBrokerSourceTotalPages(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsCurrentPage', () => { - it('Should return minus zero (1)', () => { - const result = service.getNotificationsBrokerTopicsCurrentPage(); - const expected = cold('(a)', { - a: 1 + describe('getNotificationsBrokerSourceCurrentPage', () => { + it('Should return minus zero (1)', () => { + const result = service.getNotificationsBrokerSourceCurrentPage(); + const expected = cold('(a)', { + a: 1 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('getNotificationsBrokerTopicsTotals', () => { - it('Should return three (3)', () => { - const result = service.getNotificationsBrokerTopicsTotals(); - const expected = cold('(a)', { - a: 3 + describe('getNotificationsBrokerSourceTotals', () => { + it('Should return three (3)', () => { + const result = service.getNotificationsBrokerSourceTotals(); + const expected = cold('(a)', { + a: 3 + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('isNotificationsBrokerTopicsLoading', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsLoading(); - const expected = cold('(a)', { - a: false + describe('isNotificationsBrokerSourceLoading', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceLoading(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('isNotificationsBrokerTopicsLoaded', () => { - it('Should return TRUE', () => { - const result = service.isNotificationsBrokerTopicsLoaded(); - const expected = cold('(a)', { - a: true + describe('isNotificationsBrokerSourceLoaded', () => { + it('Should return TRUE', () => { + const result = service.isNotificationsBrokerSourceLoaded(); + const expected = cold('(a)', { + a: true + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); - }); - describe('isNotificationsBrokerTopicsProcessing', () => { - it('Should return FALSE', () => { - const result = service.isNotificationsBrokerTopicsProcessing(); - const expected = cold('(a)', { - a: false + describe('isNotificationsBrokerSourceProcessing', () => { + it('Should return FALSE', () => { + const result = service.isNotificationsBrokerSourceProcessing(); + const expected = cold('(a)', { + a: false + }); + expect(result).toBeObservable(expected); }); - 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('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'); - }); + beforeEach(() => { + store = TestBed.get(Store); + service = new NotificationsStateService(store); + serviceAsAny = service; + spyOn(store, 'dispatch'); + }); - 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); + 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 2e9303c3a35..8af034ea323 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/592] [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 3866797f5d3..b5eecd112f0 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/592] [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 72d22fb5028..873fad622c6 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 5d8d3e35d58f2151e37faff9191159b44c5a33c9 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Tue, 29 Mar 2022 16:16:22 +0200 Subject: [PATCH 007/592] [CST-5249] Added suggestions from openaire --- .../admin-notifications-routing-paths.ts | 9 + .../admin-notifications-routing.module.ts | 42 + ...uggestion-targets-page-resolver.service.ts | 32 + ...ons-suggestion-targets-page.component.html | 1 + ...ons-suggestion-targets-page.component.scss | 0 ...-suggestion-targets-page.component.spec.ts | 38 + ...tions-suggestion-targets-page.component.ts | 10 + .../admin-notifications.module.ts | 27 + src/app/admin/admin-routing-paths.ts | 5 + src/app/admin/admin-routing.module.ts | 7 +- .../admin-sidebar/admin-sidebar.component.ts | 38 +- src/app/app-routing.module.ts | 6 + src/app/core/core.module.ts | 6 + ...enaire-suggestion-objects.resource-type.ts | 25 + .../openaire-suggestion-source.model.ts | 47 + .../openaire-suggestion-target.model.ts | 60 + .../models/openaire-suggestion.model.ts | 85 + .../openaire-suggestions-data.service.ts | 301 +++ src/app/openaire/openaire.module.ts | 72 + src/app/openaire/openaire.reducer.ts | 19 + .../openaire/reciter-suggestions/selectors.ts | 97 + .../suggestion-actions.component.html | 28 + .../suggestion-actions.component.scss | 1 + .../suggestion-actions.component.ts | 92 + .../suggestion-evidences.component.html | 20 + .../suggestion-evidences.component.scss | 0 .../suggestion-evidences.component.ts | 15 + .../suggestion-list-element.component.html | 44 + .../suggestion-list-element.component.scss | 16 + .../suggestion-list-element.component.ts | 98 + .../suggestion-targets.actions.ts | 154 ++ .../suggestion-targets.component.html | 51 + .../suggestion-targets.component.scss | 0 .../suggestion-targets.component.ts | 150 ++ .../suggestion-targets.effects.ts | 110 + .../suggestion-targets.reducer.ts | 100 + .../suggestion-targets.state.service.ts | 164 ++ .../suggestions-notification.component.html | 8 + .../suggestions-notification.component.scss | 0 .../suggestions-notification.component.ts | 42 + .../suggestions-popup.component.html | 1 + .../suggestions-popup.component.scss | 0 .../suggestions-popup.component.spec.ts | 79 + .../suggestions-popup.component.ts | 67 + .../suggestions.service.ts | 296 +++ src/app/shared/mocks/openaire.mock.ts | 1797 +++++++++++++++++ .../mocks/reciter-suggestion-targets.mock.ts | 42 + .../shared/mocks/reciter-suggestion.mock.ts | 210 ++ .../suggestions-page-routing-paths.ts | 11 + .../suggestions-page-routing.module.ts | 36 + .../suggestions-page.component.html | 48 + .../suggestions-page.component.scss | 0 .../suggestions-page.component.spec.ts | 107 + .../suggestions-page.component.ts | 285 +++ .../suggestions-page.module.ts | 24 + .../suggestions-page.resolver.ts | 32 + src/assets/i18n/en.json5 | 65 + 57 files changed, 5112 insertions(+), 8 deletions(-) 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-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html create mode 100644 src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss create mode 100644 src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts create mode 100644 src/app/admin/admin-notifications/admin-notifications.module.ts create mode 100644 src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-objects.resource-type.ts create mode 100644 src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts create mode 100644 src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts create mode 100644 src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts create mode 100644 src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.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/reciter-suggestions/selectors.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.html create mode 100644 src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss create mode 100644 src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts create mode 100644 src/app/openaire/reciter-suggestions/suggestions.service.ts create mode 100644 src/app/shared/mocks/openaire.mock.ts create mode 100644 src/app/shared/mocks/reciter-suggestion-targets.mock.ts create mode 100644 src/app/shared/mocks/reciter-suggestion.mock.ts create mode 100644 src/app/suggestions-page/suggestions-page-routing-paths.ts create mode 100644 src/app/suggestions-page/suggestions-page-routing.module.ts create mode 100644 src/app/suggestions-page/suggestions-page.component.html create mode 100644 src/app/suggestions-page/suggestions-page.component.scss create mode 100644 src/app/suggestions-page/suggestions-page.component.spec.ts create mode 100644 src/app/suggestions-page/suggestions-page.component.ts create mode 100644 src/app/suggestions-page/suggestions-page.module.ts create mode 100644 src/app/suggestions-page/suggestions-page.resolver.ts 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 00000000000..614b2ef49b2 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -0,0 +1,9 @@ +import { URLCombiner } from '../../core/url-combiner/url-combiner'; +import { getNotificationsModuleRoute } from '../admin-routing-paths'; + +export const NOTIFICATIONS_EDIT_PATH = 'openaire-broker'; +export const NOTIFICATIONS_RECITER_SUGGESTION_PATH = 'suggestion-targets'; + +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 00000000000..12bc7b9ec73 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -0,0 +1,42 @@ +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, NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './admin-notifications-routing-paths'; +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component'; +import { AdminNotificationsSuggestionTargetsPageResolver } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + canActivate: [ AuthenticatedGuard ], + path: `${NOTIFICATIONS_RECITER_SUGGESTION_PATH}`, + component: AdminNotificationsSuggestionTargetsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + reciterSuggestionTargetParams: AdminNotificationsSuggestionTargetsPageResolver + }, + data: { + title: 'admin.notifications.recitersuggestion.page.title', + breadcrumbKey: 'admin.notifications.recitersuggestion', + showBreadcrumbsFluid: false + } + }, + ]) + ], + providers: [ + I18nBreadcrumbResolver, + I18nBreadcrumbsService, + AdminNotificationsSuggestionTargetsPageResolver + ] +}) +/** + * Routing module for the Notifications section of the admin sidebar + */ +export class AdminNotificationsRoutingModule { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts new file mode 100644 index 00000000000..df1f4b81e69 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-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 AdminNotificationsSuggestionTargetsPageParams { + pageId?: string; + pageSize?: number; + currentPage?: number; +} + +/** + * This class represents a resolver that retrieve the route data before the route is activated. + */ +@Injectable() +export class AdminNotificationsSuggestionTargetsPageResolver implements Resolve { + + /** + * Method for resolving the parameters in the current route. + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns AdminNotificationsSuggestionTargetsPageParams Emits the route parameters + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsSuggestionTargetsPageParams { + 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-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html new file mode 100644 index 00000000000..5d06a1a6bdd --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts new file mode 100644 index 00000000000..f9e407f4021 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts @@ -0,0 +1,38 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; + +describe('AdminNotificationsSuggestionTargetsPageComponent', () => { + let component: AdminNotificationsSuggestionTargetsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot() + ], + declarations: [ + AdminNotificationsSuggestionTargetsPageComponent + ], + providers: [ + AdminNotificationsSuggestionTargetsPageComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminNotificationsSuggestionTargetsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts new file mode 100644 index 00000000000..a9a77f50890 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-admin-notifications-reciter-page', + templateUrl: './admin-notifications-suggestion-targets-page.component.html', + styleUrls: ['./admin-notifications-suggestion-targets-page.component.scss'] +}) +export class AdminNotificationsSuggestionTargetsPageComponent { + +} 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 00000000000..47125daad64 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -0,0 +1,27 @@ +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 { OpenaireModule } from '../../openaire/openaire.module'; +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + AdminNotificationsRoutingModule, + OpenaireModule + ], + declarations: [ + AdminNotificationsSuggestionTargetsPageComponent + ], + 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 3168ea93c92..30f801cecb7 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 ee5cb8737bc..782a7faa380 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 dc9d2a817ff..dd5d7e507a0 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -22,6 +22,7 @@ import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { Router, ActivatedRoute } from '@angular/router'; +import {NOTIFICATIONS_RECITER_SUGGESTION_PATH} from "../admin-notifications/admin-notifications-routing-paths"; /** * Component representing the admin sidebar @@ -277,7 +278,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { // link: '' // } as LinkMenuItemModel, // icon: 'chart-bar', - // index: 8 + // index: 9 // }, /* Control Panel */ @@ -292,7 +293,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { // link: '' // } as LinkMenuItemModel, // icon: 'cogs', - // index: 9 + // index: 10 // }, /* Processes */ @@ -306,7 +307,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '/processes' } as LinkMenuItemModel, icon: 'terminal', - index: 10 + index: 12 }, ]; menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { @@ -465,6 +466,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_reciter', + parentID: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_reciter', + link: '/admin/notifications/' + NOTIFICATIONS_RECITER_SUGGESTION_PATH + } as LinkMenuItemModel, + }, /* Admin Search */ { id: 'admin_search', @@ -476,7 +500,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '/admin/search' } as LinkMenuItemModel, icon: 'search', - index: 5 + index: 6 }, /* Registries */ { @@ -488,7 +512,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { text: 'menu.section.registries' } as TextMenuItemModel, icon: 'list', - index: 6 + index: 7 }, { id: 'registries_metadata', @@ -524,7 +548,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: 'admin/curation-tasks' } as LinkMenuItemModel, icon: 'filter', - index: 7 + index: 8 }, /* Workflow */ @@ -601,7 +625,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/app-routing.module.ts b/src/app/app-routing.module.ts index 88f7791b1b2..9bf55185584 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -30,6 +30,7 @@ import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component import { GroupAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/group-administrator.guard'; import { ThemedPageInternalServerErrorComponent } from './page-internal-server-error/themed-page-internal-server-error.component'; import { ServerCheckGuard } from './core/server-check/server-check.guard'; +import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths'; @NgModule({ imports: [ @@ -190,6 +191,11 @@ import { ServerCheckGuard } from './core/server-check/server-check.guard'; .then((m) => m.ProcessPageModule), canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard] }, + { path: SUGGESTION_MODULE_PATH, + loadChildren: () => import('./suggestions-page/suggestions-page.module') + .then((m) => m.SuggestionsPageModule), + canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard] + }, { path: INFO_MODULE_PATH, loadChildren: () => import('./info/info.module').then((m) => m.InfoModule) diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 8d8a614a899..6293fbd1092 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -162,6 +162,9 @@ 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 { OpenaireSuggestionTarget } from './openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { OpenaireSuggestion } from './openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { OpenaireSuggestionSource } from './openaire/reciter-suggestions/models/openaire-suggestion-source.model'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -343,6 +346,9 @@ export const models = ShortLivedToken, Registration, UsageReport, + OpenaireSuggestion, + OpenaireSuggestionTarget, + OpenaireSuggestionSource, Root, SearchConfig, SubmissionAccessesModel diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-objects.resource-type.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-objects.resource-type.ts new file mode 100644 index 00000000000..e31006959ff --- /dev/null +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-objects.resource-type.ts @@ -0,0 +1,25 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for the Suggestion Target object + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUGGESTION_TARGET = new ResourceType('suggestiontarget'); + +/** + * The resource type for the Suggestion Source object + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUGGESTION_SOURCE = new ResourceType('suggestionsource'); + +/** + * The resource type for the Suggestion object + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUGGESTION = new ResourceType('suggestion'); diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts new file mode 100644 index 00000000000..6da9fd47b9b --- /dev/null +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts @@ -0,0 +1,47 @@ +import { autoserialize, deserialize } from 'cerialize'; + +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { SUGGESTION_SOURCE } from './openaire-suggestion-objects.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 Suggestion Source model + */ +@typedObject +export class OpenaireSuggestionSource implements CacheableObject { + /** + * A string representing the kind of object, e.g. community, item, … + */ + static type = SUGGESTION_SOURCE; + + /** + * The Suggestion Target id + */ + @autoserialize + id: string; + + /** + * The total number of suggestions provided by Suggestion Target for + */ + @autoserialize + total: 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, + suggestiontargets: HALLink + }; +} diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts new file mode 100644 index 00000000000..e35972bc798 --- /dev/null +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts @@ -0,0 +1,60 @@ +import { autoserialize, deserialize } from 'cerialize'; + +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { SUGGESTION_TARGET } from './openaire-suggestion-objects.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 Suggestion Target model + */ +@typedObject +export class OpenaireSuggestionTarget implements CacheableObject { + /** + * A string representing the kind of object, e.g. community, item, … + */ + static type = SUGGESTION_TARGET; + + /** + * The Suggestion Target id + */ + @autoserialize + id: string; + + /** + * The Suggestion Target name to display + */ + @autoserialize + display: string; + + /** + * The Suggestion Target source to display + */ + @autoserialize + source: string; + + /** + * The total number of suggestions provided by Suggestion Target for + */ + @autoserialize + total: 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, + suggestions: HALLink, + target: HALLink + }; +} diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts new file mode 100644 index 00000000000..3ff5d7b630c --- /dev/null +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts @@ -0,0 +1,85 @@ +import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; + +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { SUGGESTION } from './openaire-suggestion-objects.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 { MetadataMap, MetadataMapSerializer } from '../../../shared/metadata.models'; + +export interface SuggestionEvidences { + [sectionId: string]: { + score: string; + notes: string + }; +} +/** + * The interface representing the Suggestion Source model + */ +@typedObject +export class OpenaireSuggestion implements CacheableObject { + /** + * A string representing the kind of object, e.g. community, item, … + */ + static type = SUGGESTION; + + /** + * The Suggestion id + */ + @autoserialize + id: string; + + /** + * The Suggestion name to display + */ + @autoserialize + display: string; + + /** + * The Suggestion source to display + */ + @autoserialize + source: string; + + /** + * The Suggestion external source uri + */ + @autoserialize + externalSourceUri: string; + + /** + * The Total Score of the suggestion + */ + @autoserialize + score: string; + + /** + * The total number of suggestions provided by Suggestion Target for + */ + @autoserialize + evidences: SuggestionEvidences; + + /** + * All metadata of this suggestion object + */ + @excludeFromEquals + @autoserializeAs(MetadataMapSerializer) + metadata: MetadataMap; + + /** + * 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 + }; +} diff --git a/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts new file mode 100644 index 00000000000..d961eaf9b52 --- /dev/null +++ b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts @@ -0,0 +1,301 @@ +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 { 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 { SUGGESTION_TARGET } from './models/openaire-suggestion-objects.resource-type'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../../data/paginated-list.model'; +import { OpenaireSuggestionSource } from './models/openaire-suggestion-source.model'; +import { OpenaireSuggestionTarget } from './models/openaire-suggestion-target.model'; +import { OpenaireSuggestion } from './models/openaire-suggestion.model'; +import { RequestParam } from '../../cache/models/request-param.model'; +import { NoContent } from '../../shared/NoContent.model'; + +/* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ +class SuggestionDataServiceImpl extends DataService { + /** + * The REST endpoint. + */ + protected linkPath = 'suggestions'; + + /** + * 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(); + } +} + +/** + * A private DataService implementation to delegate specific methods to. + */ +class SuggestionTargetsDataServiceImpl extends DataService { + /** + * The REST endpoint. + */ + protected linkPath = 'suggestiontargets'; + + /** + * 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(); + } +} + +/** + * A private DataService implementation to delegate specific methods to. + */ +class SuggestionSourcesDataServiceImpl extends DataService { + /** + * The REST endpoint. + */ + protected linkPath = 'suggestionsources'; + + /** + * 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 Suggestion Target REST requests. + */ +@Injectable() +@dataService(SUGGESTION_TARGET) +export class OpenaireSuggestionsDataService { + protected searchFindBySourceMethod = 'findBySource'; + protected searchFindByTargetMethod = 'findByTarget'; + protected searchFindByTargetAndSourceMethod = 'findByTargetAndSource'; + + /** + * A private DataService implementation to delegate specific methods to. + */ + private suggestionsDataService: SuggestionDataServiceImpl; + + /** + * A private DataService implementation to delegate specific methods to. + */ + private suggestionSourcesDataService: SuggestionSourcesDataServiceImpl; + + /** + * A private DataService implementation to delegate specific methods to. + */ + private suggestionTargetsDataService: SuggestionTargetsDataServiceImpl; + + /** + * Initialize service variables + * @param {RequestService} requestService + * @param {RemoteDataBuildService} rdbService + * @param {ObjectCacheService} objectCache + * @param {HALEndpointService} halService + * @param {NotificationsService} notificationsService + * @param {HttpClient} http + * @param {DefaultChangeAnalyzer} comparatorSuggestions + * @param {DefaultChangeAnalyzer} comparatorSources + * @param {DefaultChangeAnalyzer} comparatorTargets + */ + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparatorSuggestions: DefaultChangeAnalyzer, + protected comparatorSources: DefaultChangeAnalyzer, + protected comparatorTargets: DefaultChangeAnalyzer, + ) { + this.suggestionsDataService = new SuggestionDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorSuggestions); + this.suggestionSourcesDataService = new SuggestionSourcesDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorSources); + this.suggestionTargetsDataService = new SuggestionTargetsDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorTargets); + } + + /** + * Return the list of Suggestion Target + * + * @param options + * Find list options object. + * @return Observable>> + * The list of Suggestion Sources. + */ + public getSources(options: FindListOptions = {}): Observable>> { + return this.suggestionSourcesDataService.findAll(options); + } + + /** + * Return the list of Suggestion Target for a given source + * + * @param source + * The source for which to find targets. + * @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 Suggestion Target. + */ + public getTargets( + source: string, + options: FindListOptions = {}, + ...linksToFollow: FollowLinkConfig[] + ): Observable>> { + options.searchParams = [new RequestParam('source', source)]; + + return this.suggestionTargetsDataService.searchBy(this.searchFindBySourceMethod, options, true, true, ...linksToFollow); + } + + /** + * Return the list of Suggestion Target for a given user + * + * @param userId + * The user Id for which to find targets. + * @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 Suggestion Target. + */ + public getTargetsByUser( + userId: string, + options: FindListOptions = {}, + ...linksToFollow: FollowLinkConfig[] + ): Observable>> { + options.searchParams = [new RequestParam('target', userId)]; + + return this.suggestionTargetsDataService.searchBy(this.searchFindByTargetMethod, options, true, true, ...linksToFollow); + } + + /** + * Return a Suggestion Target for a given id + * + * @param targetId + * The target id to retrieve. + * + * @return Observable> + * The list of Suggestion Target. + */ + public getTargetById(targetId: string): Observable> { + return this.suggestionTargetsDataService.findById(targetId); + } + + /** + * Used to delete Suggestion + * @suggestionId + */ + public deleteSuggestion(suggestionId: string): Observable> { + return this.suggestionsDataService.delete(suggestionId); + } + + /** + * Used to fetch Suggestion notification for user + * @suggestionId + */ + public getSuggestion(suggestionId: string, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.suggestionsDataService.findById(suggestionId, true, true, ...linksToFollow); + } + + /** + * Return the list of Suggestion for a given target and source + * + * @param target + * The target for which to find suggestions. + * @param source + * The source for which to find suggestions. + * @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 Suggestion. + */ + public getSuggestionsByTargetAndSource( + target: string, + source: string, + options: FindListOptions = {}, + ...linksToFollow: FollowLinkConfig[] + ): Observable>> { + options.searchParams = [ + new RequestParam('target', target), + new RequestParam('source', source) + ]; + + return this.suggestionsDataService.searchBy(this.searchFindByTargetAndSourceMethod, options, true, true, ...linksToFollow); + } + + /** + * Clear findByTargetAndSource suggestions requests from cache + */ + public clearSuggestionRequests() { + this.requestService.setStaleByHrefSubstring(this.searchFindByTargetAndSourceMethod); + } +} diff --git a/src/app/openaire/openaire.module.ts b/src/app/openaire/openaire.module.ts new file mode 100644 index 00000000000..22d04f3002b --- /dev/null +++ b/src/app/openaire/openaire.module.ts @@ -0,0 +1,72 @@ +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 { openaireReducers, OpenaireState } from './openaire.reducer'; +import { SuggestionTargetsStateService } from './reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +import { SuggestionsService } from './reciter-suggestions/suggestions.service'; +import { OpenaireSuggestionsDataService } from '../core/openaire/reciter-suggestions/openaire-suggestions-data.service'; +import { SuggestionTargetsComponent } from './reciter-suggestions/suggestion-targets/suggestion-targets.component'; +import { SuggestionListElementComponent } from './reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionEvidencesComponent } from './reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { SuggestionActionsComponent } from './reciter-suggestions/suggestion-actions/suggestion-actions.component'; +import { SuggestionsPopupComponent } from './reciter-suggestions/suggestions-popup/suggestions-popup.component'; +import { SuggestionsNotificationComponent } from './reciter-suggestions/suggestions-notification/suggestions-notification.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), + TranslateModule +]; + +const COMPONENTS = [ + SuggestionTargetsComponent, + SuggestionActionsComponent, + SuggestionListElementComponent, + SuggestionEvidencesComponent, + SuggestionsPopupComponent, + SuggestionsNotificationComponent +]; + +const DIRECTIVES = [ ]; + + +const PROVIDERS = [ + SuggestionTargetsStateService, + SuggestionsService, + OpenaireSuggestionsDataService +]; + +@NgModule({ + imports: [ + ...MODULES, + SearchModule + ], + declarations: [ + ...COMPONENTS, + ...DIRECTIVES, + ], + providers: [ + ...PROVIDERS + ], + entryComponents: [ + ], + 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 00000000000..cacf3c72834 --- /dev/null +++ b/src/app/openaire/openaire.reducer.ts @@ -0,0 +1,19 @@ +import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; + +import { + SuggestionTargetsReducer, + SuggestionTargetState +} from './reciter-suggestions/suggestion-targets/suggestion-targets.reducer'; + +/** + * The OpenAIRE State + */ +export interface OpenaireState { + 'suggestionTarget': SuggestionTargetState; +} + +export const openaireReducers: ActionReducerMap = { + suggestionTarget: SuggestionTargetsReducer, +}; + +export const openaireSelector = createFeatureSelector('openaire'); diff --git a/src/app/openaire/reciter-suggestions/selectors.ts b/src/app/openaire/reciter-suggestions/selectors.ts new file mode 100644 index 00000000000..e699b27dbae --- /dev/null +++ b/src/app/openaire/reciter-suggestions/selectors.ts @@ -0,0 +1,97 @@ +import { createSelector, MemoizedSelector } from '@ngrx/store'; +import { subStateSelector } from '../../shared/selector.util'; +import { openaireSelector, OpenaireState } from '../openaire.reducer'; +import { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; + +/** + * Returns the Reciter Suggestion Target state. + * @function _getReciterSuggestionTargetState + * @param {AppState} state Top level state. + * @return {OpenaireState} + */ +const _getReciterSuggestionTargetState = (state: any) => state.openaire; + +// Reciter Suggestion Targets +// ---------------------------------------------------------------------------- + +/** + * Returns the Reciter Suggestion Targets State. + * @function reciterSuggestionTargetStateSelector + * @return {OpenaireState} + */ +export function reciterSuggestionTargetStateSelector(): MemoizedSelector { + return subStateSelector(openaireSelector, 'suggestionTarget'); +} + +/** + * Returns the Reciter Suggestion Targets list. + * @function reciterSuggestionTargetObjectSelector + * @return {OpenaireReciterSuggestionTarget[]} + */ +export function reciterSuggestionTargetObjectSelector(): MemoizedSelector { + return subStateSelector(reciterSuggestionTargetStateSelector(), 'targets'); +} + +/** + * Returns true if the Reciter Suggestion Targets are loaded. + * @function isReciterSuggestionTargetLoadedSelector + * @return {boolean} + */ +export const isReciterSuggestionTargetLoadedSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.loaded +); + +/** + * Returns true if the deduplication sets are processing. + * @function isDeduplicationSetsProcessingSelector + * @return {boolean} + */ +export const isreciterSuggestionTargetProcessingSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.processing +); + +/** + * Returns the total available pages of Reciter Suggestion Targets. + * @function getreciterSuggestionTargetTotalPagesSelector + * @return {number} + */ +export const getreciterSuggestionTargetTotalPagesSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.totalPages +); + +/** + * Returns the current page of Reciter Suggestion Targets. + * @function getreciterSuggestionTargetCurrentPageSelector + * @return {number} + */ +export const getreciterSuggestionTargetCurrentPageSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.currentPage +); + +/** + * Returns the total number of Reciter Suggestion Targets. + * @function getreciterSuggestionTargetTotalsSelector + * @return {number} + */ +export const getreciterSuggestionTargetTotalsSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.totalElements +); + +/** + * Returns Suggestion Targets for the current user. + * @function getCurrentUserReciterSuggestionTargetSelector + * @return {OpenaireSuggestionTarget[]} + */ +export const getCurrentUserSuggestionTargetsSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.currentUserTargets +); + +/** + * Returns whether or not the user has consulted their suggestions + * @function getCurrentUserReciterSuggestionTargetSelector + * @return {boolean} + */ +export const getCurrentUserSuggestionTargetsVisitedSelector = createSelector(_getReciterSuggestionTargetState, + (state: OpenaireState) => state.suggestionTarget.currentUserTargetsVisited +); diff --git a/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.html b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.html new file mode 100644 index 00000000000..7ec3e61395e --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.html @@ -0,0 +1,28 @@ +
+
+ + + + + + + +
+ + +
diff --git a/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.scss b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.scss new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts new file mode 100644 index 00000000000..cf219011237 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts @@ -0,0 +1,92 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { ItemType } from '../../../core/shared/item-relationships/item-type.model'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { OpenaireSuggestion } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { SuggestionApproveAndImport } from '../suggestion-list-element/suggestion-list-element.component'; +import { Collection } from '../../../core/shared/collection.model'; +import { take } from 'rxjs/operators'; +import { CreateItemParentSelectorComponent } from '../../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; + +@Component({ + selector: 'ds-suggestion-actions', + styleUrls: [ './suggestion-actions.component.scss' ], + templateUrl: './suggestion-actions.component.html' +}) +export class SuggestionActionsComponent { + + @Input() object: OpenaireSuggestion; + + @Input() isBulk = false; + + @Input() hasEvidence = false; + + @Input() seeEvidence = false; + + @Input() isCollectionFixed = false; + + /** + * The component is used to Delete suggestion + */ + @Output() notMineClicked = new EventEmitter(); + + /** + * The component is used to approve & import + */ + @Output() approveAndImport = new EventEmitter(); + + /** + * The component is used to approve & import + */ + @Output() seeEvidences = new EventEmitter(); + + constructor(private modalService: NgbModal) { } + + /** + * Method called on clicking the button "approve & import", It opens a dialog for + * select a collection and it emits an approveAndImport event. + */ + openDialog(entity: ItemType) { + + const modalRef = this.modalService.open(CreateItemParentSelectorComponent); + modalRef.componentInstance.emitOnly = true; + modalRef.componentInstance.entityType = entity.label; + + modalRef.componentInstance.select.pipe(take(1)) + .subscribe((collection: Collection) => { + this.approveAndImport.emit({ + suggestion: this.isBulk ? undefined : this.object, + collectionId: collection.id + }); + }); + } + + approveAndImportCollectionFixed() { + this.approveAndImport.emit({ + suggestion: this.isBulk ? undefined : this.object, + collectionId: null + }); + } + + + /** + * Delete the suggestion + */ + notMine() { + this.notMineClicked.emit(this.isBulk ? undefined : this.object.id); + } + + /** + * Toggle See Evidence + */ + toggleSeeEvidences() { + this.seeEvidences.emit(!this.seeEvidence); + } + + notMineLabel(): string { + return this.isBulk ? 'reciter.suggestion.notMine.bulk' : 'reciter.suggestion.notMine' ; + } + + approveAndImportLabel(): string { + return this.isBulk ? 'reciter.suggestion.approveAndImport.bulk' : 'reciter.suggestion.approveAndImport'; + } +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html new file mode 100644 index 00000000000..5ad4f0a9783 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html @@ -0,0 +1,20 @@ +
+
+ + + + + + + + + + + + + + + +
{{'reciter.suggestion.evidence.score' | translate}}{{'reciter.suggestion.evidence.type' | translate}}{{'reciter.suggestion.evidence.notes' | translate}}
{{evidences[evidence].score}}{{evidence | translate}}{{evidences[evidence].notes}}
+
+
diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts new file mode 100644 index 00000000000..e0536ae7234 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts @@ -0,0 +1,15 @@ +import { Component, Input } from '@angular/core'; +import { fadeIn } from '../../../../shared/animations/fade'; +import { SuggestionEvidences } from '../../../../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; + +@Component({ + selector: 'ds-suggestion-evidences', + styleUrls: [ './suggestion-evidences.component.scss' ], + templateUrl: './suggestion-evidences.component.html', + animations: [fadeIn] +}) +export class SuggestionEvidencesComponent { + + @Input() evidences: SuggestionEvidences; + +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html new file mode 100644 index 00000000000..05f9c0ac771 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html @@ -0,0 +1,44 @@ +
+
+ +
+
+ +
+
+ +
+
+
{{'reciter.suggestion.totalScore' | translate}}
+ {{ object.score }} +
+
+ +
+ + + + +
+
+ +
+
+ +
+
+
+
diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss new file mode 100644 index 00000000000..1c522095189 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss @@ -0,0 +1,16 @@ +.issue-date { + color: #c8c8c8; +} + +.parent { + display: flex; + gap:10px; +} + +.import { + flex: initial; +} + +.suggestion-score { + font-size: 1.5rem; +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts new file mode 100644 index 00000000000..8227dc3213b --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts @@ -0,0 +1,98 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; + +import { fadeIn } from '../../../shared/animations/fade'; +import { OpenaireSuggestion } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { Item } from '../../../core/shared/item.model'; +import { isNotEmpty } from '../../../shared/empty.util'; + +export interface SuggestionApproveAndImport { + suggestion: OpenaireSuggestion; + collectionId: string; +} + +@Component({ + selector: 'ds-suggestion-list-item', + styleUrls: ['./suggestion-list-element.component.scss'], + templateUrl: './suggestion-list-element.component.html', + animations: [fadeIn] +}) +export class SuggestionListElementComponent implements OnInit { + + @Input() object: OpenaireSuggestion; + + @Input() isSelected = false; + + @Input() isCollectionFixed = false; + + public listableObject: any; + + public seeEvidence = false; + + /** + * The component is used to Delete suggestion + */ + @Output() notMineClicked = new EventEmitter(); + + /** + * The component is used to approve & import + */ + @Output() approveAndImport = new EventEmitter(); + + /** + * New value whether the element is selected + */ + @Output() selected = new EventEmitter(); + + /** + * Initialize instance variables + * + * @param {NgbModal} modalService + */ + constructor(private modalService: NgbModal) { } + + ngOnInit() { + this.listableObject = { + indexableObject: Object.assign(new Item(), {id: this.object.id, metadata: this.object.metadata}), + hitHighlights: {} + }; + } + + /** + * Approve and import the suggestion + */ + onApproveAndImport(event: SuggestionApproveAndImport) { + this.approveAndImport.emit(event); + } + + /** + * Delete the suggestion + */ + onNotMine(suggestionId: string) { + this.notMineClicked.emit(suggestionId); + } + + /** + * Change is selected value. + */ + changeSelected(event) { + this.isSelected = event.target.checked; + this.selected.next(this.isSelected); + } + + /** + * See the Evidence + */ + hasEvidences() { + return isNotEmpty(this.object.evidences); + } + + /** + * Set the see evidence variable. + */ + onSeeEvidences(seeEvidence: boolean) { + this.seeEvidence = seeEvidence; + } + +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts new file mode 100644 index 00000000000..6c44d40b915 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts @@ -0,0 +1,154 @@ +import { Action } from '@ngrx/store'; +import { type } from '../../../shared/ngrx/type'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.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 SuggestionTargetActionTypes = { + ADD_TARGETS: type('dspace/integration/openaire/suggestions/target/ADD_TARGETS'), + CLEAR_TARGETS: type('dspace/integration/openaire/suggestions/target/CLEAR_TARGETS'), + RETRIEVE_TARGETS_BY_SOURCE: type('dspace/integration/openaire/suggestions/target/RETRIEVE_TARGETS_BY_SOURCE'), + RETRIEVE_TARGETS_BY_SOURCE_ERROR: type('dspace/integration/openaire/suggestions/target/RETRIEVE_TARGETS_BY_SOURCE_ERROR'), + ADD_USER_SUGGESTIONS: type('dspace/integration/openaire/suggestions/target/ADD_USER_SUGGESTIONS'), + REFRESH_USER_SUGGESTIONS: type('dspace/integration/openaire/suggestions/target/REFRESH_USER_SUGGESTIONS'), + MARK_USER_SUGGESTIONS_AS_VISITED: type('dspace/integration/openaire/suggestions/target/MARK_USER_SUGGESTIONS_AS_VISITED') +}; + +/* tslint:disable:max-classes-per-file */ + +/** + * An ngrx action to retrieve all the Suggestion Targets. + */ +export class RetrieveTargetsBySourceAction implements Action { + type = SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE; + payload: { + source: string; + elementsPerPage: number; + currentPage: number; + }; + + /** + * Create a new RetrieveTargetsBySourceAction. + * + * @param source + * the source for which to retrieve suggestion targets + * @param elementsPerPage + * the number of targets per page + * @param currentPage + * The page number to retrieve + */ + constructor(source: string, elementsPerPage: number, currentPage: number) { + this.payload = { + source, + elementsPerPage, + currentPage + }; + } +} + +/** + * An ngrx action for retrieving 'all Suggestion Targets' error. + */ +export class RetrieveAllTargetsErrorAction implements Action { + type = SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR; +} + +/** + * An ngrx action to load the Suggestion Target objects. + */ +export class AddTargetAction implements Action { + type = SuggestionTargetActionTypes.ADD_TARGETS; + payload: { + targets: OpenaireSuggestionTarget[]; + totalPages: number; + currentPage: number; + totalElements: number; + }; + + /** + * Create a new AddTargetAction. + * + * @param targets + * the list of targets + * @param totalPages + * the total available pages of targets + * @param currentPage + * the current page + * @param totalElements + * the total available Suggestion Targets + */ + constructor(targets: OpenaireSuggestionTarget[], totalPages: number, currentPage: number, totalElements: number) { + this.payload = { + targets, + totalPages, + currentPage, + totalElements + }; + } + +} + +/** + * An ngrx action to load the user Suggestion Target object. + * Called by the ??? effect. + */ +export class AddUserSuggestionsAction implements Action { + type = SuggestionTargetActionTypes.ADD_USER_SUGGESTIONS; + payload: { + suggestionTargets: OpenaireSuggestionTarget[]; + }; + + /** + * Create a new AddUserSuggestionsAction. + * + * @param suggestionTargets + * the user suggestions target + */ + constructor(suggestionTargets: OpenaireSuggestionTarget[]) { + this.payload = { suggestionTargets }; + } + +} + +/** + * An ngrx action to reload the user Suggestion Target object. + * Called by the ??? effect. + */ +export class RefreshUserSuggestionsAction implements Action { + type = SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS; +} + +/** + * An ngrx action to Mark User Suggestions As Visited. + * Called by the ??? effect. + */ +export class MarkUserSuggestionsAsVisitedAction implements Action { + type = SuggestionTargetActionTypes.MARK_USER_SUGGESTIONS_AS_VISITED; +} + +/** + * An ngrx action to clear targets state. + */ +export class ClearSuggestionTargetsAction implements Action { + type = SuggestionTargetActionTypes.CLEAR_TARGETS; +} + +/* 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 SuggestionTargetsActions + = AddTargetAction + | AddUserSuggestionsAction + | ClearSuggestionTargetsAction + | MarkUserSuggestionsAsVisitedAction + | RetrieveTargetsBySourceAction + | RetrieveAllTargetsErrorAction; diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.html b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.html new file mode 100644 index 00000000000..791e694ba90 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.html @@ -0,0 +1,51 @@ +
+
+
+ + + + + + + + +
+ + + + + + + + + + + + + +
{{'reciter.suggestion.table.name' | translate}}{{'reciter.suggestion.table.actions' | translate}}
+ {{targetElement.display}} + +
+ +
+
+
+
+
+
+
+
diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts new file mode 100644 index 00000000000..b9ed6c4e87b --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts @@ -0,0 +1,150 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { Observable, Subscription } from 'rxjs'; +import { distinctUntilChanged, take } from 'rxjs/operators'; + +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { hasValue } from '../../../shared/empty.util'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SuggestionTargetsStateService } from './suggestion-targets.state.service'; +import { getSuggestionPageRoute } from '../../../suggestions-page/suggestions-page-routing-paths'; +import { SuggestionsService } from '../suggestions.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; + +/** + * Component to display the Suggestion Target list. + */ +@Component({ + selector: 'ds-suggestion-target', + templateUrl: './suggestion-targets.component.html', + styleUrls: ['./suggestion-targets.component.scss'], +}) +export class SuggestionTargetsComponent implements OnInit { + + /** + * The source for which to list targets + */ + @Input() source: string; + + /** + * The pagination system configuration for HTML listing. + * @type {PaginationComponentOptions} + */ + public paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'stp', + pageSizeOptions: [5, 10, 20, 40, 60] + }); + + /** + * The Suggestion Target list. + */ + public targets$: Observable; + /** + * The total number of Suggestion Targets. + */ + 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 {SuggestionTargetsStateService} suggestionTargetsStateService + * @param {SuggestionsService} suggestionService + * @param {Router} router + */ + constructor( + private paginationService: PaginationService, + private suggestionTargetsStateService: SuggestionTargetsStateService, + private suggestionService: SuggestionsService, + private router: Router + ) { + } + + /** + * Component initialization. + */ + ngOnInit(): void { + this.targets$ = this.suggestionTargetsStateService.getReciterSuggestionTargets(); + this.totalElements$ = this.suggestionTargetsStateService.getReciterSuggestionTargetsTotals(); + } + + /** + * First Suggestion Targets loading after view initialization. + */ + ngAfterViewInit(): void { + this.subs.push( + this.suggestionTargetsStateService.isReciterSuggestionTargetsLoaded().pipe( + take(1) + ).subscribe(() => { + this.getSuggestionTargets(); + }) + ); + } + + /** + * Returns the information about the loading status of the Suggestion Targets (if it's running or not). + * + * @return Observable + * 'true' if the targets are loading, 'false' otherwise. + */ + public isTargetsLoading(): Observable { + return this.suggestionTargetsStateService.isReciterSuggestionTargetsLoading(); + } + + /** + * Returns the information about the processing status of the Suggestion Targets (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the targets (ex.: a REST call), 'false' otherwise. + */ + public isTargetsProcessing(): Observable { + return this.suggestionTargetsStateService.isReciterSuggestionTargetsProcessing(); + } + + /** + * Redirect to suggestion page. + * + * @param {string} id + * the id of suggestion target + * @param {string} name + * the name of suggestion target + */ + public redirectToSuggestions(id: string, name: string) { + this.router.navigate([getSuggestionPageRoute(id)]); + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.suggestionTargetsStateService.dispatchClearSuggestionTargetsAction(); + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + + /** + * Dispatch the Suggestion Targets retrival. + */ + public getSuggestionTargets(): void { + this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( + distinctUntilChanged(), + take(1) + ).subscribe((options: PaginationComponentOptions) => { + this.suggestionTargetsStateService.dispatchRetrieveReciterSuggestionTargets( + this.source, + options.pageSize, + options.currentPage + ); + }); + } + + public getTargetUuid(target: OpenaireSuggestionTarget) { + return this.suggestionService.getTargetUuid(target); + } +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts new file mode 100644 index 00000000000..85e871403c4 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts @@ -0,0 +1,110 @@ +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 } from 'rxjs/operators'; +import { of } from 'rxjs'; + +import { + AddTargetAction, + AddUserSuggestionsAction, + RefreshUserSuggestionsAction, + RetrieveAllTargetsErrorAction, + RetrieveTargetsBySourceAction, + SuggestionTargetActionTypes, +} from './suggestion-targets.actions'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { SuggestionsService } from '../suggestions.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { AuthActionTypes, RetrieveAuthenticatedEpersonSuccessAction } from '../../../core/auth/auth.actions'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { EPerson } from '../../../core/eperson/models/eperson.model'; + +/** + * Provides effect methods for the Suggestion Targets actions. + */ +@Injectable() +export class SuggestionTargetsEffects { + + /** + * Retrieve all Suggestion Targets managing pagination and errors. + */ + @Effect() retrieveTargetsBySource$ = this.actions$.pipe( + ofType(SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE), + switchMap((action: RetrieveTargetsBySourceAction) => { + return this.suggestionsService.getTargets( + action.payload.source, + action.payload.elementsPerPage, + action.payload.currentPage + ).pipe( + map((targets: PaginatedList) => + new AddTargetAction(targets.page, targets.totalPages, targets.currentPage, targets.totalElements) + ), + catchError((error: Error) => { + if (error) { + console.error(error.message); + } + return of(new RetrieveAllTargetsErrorAction()); + }) + ); + }) + ); + + /** + * Show a notification on error. + */ + @Effect({ dispatch: false }) retrieveAllTargetsErrorAction$ = this.actions$.pipe( + ofType(SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR), + tap(() => { + this.notificationsService.error(null, this.translate.get('reciter.suggestion.target.error.service.retrieve')); + }) + ); + + /** + * Show a notification on error. + */ + @Effect() retrieveUserTargets$ = this.actions$.pipe( + ofType(AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS), + switchMap((action: RetrieveAuthenticatedEpersonSuccessAction) => { + return this.suggestionsService.retrieveCurrentUserSuggestions(action.payload).pipe( + map((suggestionTargets: OpenaireSuggestionTarget[]) => new AddUserSuggestionsAction(suggestionTargets)) + ); + })); + + /** + * Fetch the current user suggestion + */ + @Effect() refreshUserTargets$ = this.actions$.pipe( + ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS), + switchMap((action: RefreshUserSuggestionsAction) => { + return this.store$.select((state: any) => state.core.auth.user) + .pipe( + switchMap((user: EPerson) => { + return this.suggestionsService.retrieveCurrentUserSuggestions(user) + .pipe( + map((suggestionTargets: OpenaireSuggestionTarget[]) => new AddUserSuggestionsAction(suggestionTargets)), + catchError((errors) => of(errors)) + ); + }), + catchError((errors) => of(errors)) + ); + })); + + /** + * Initialize the effect class variables. + * @param {Actions} actions$ + * @param {Store} store$ + * @param {TranslateService} translate + * @param {NotificationsService} notificationsService + * @param {SuggestionsService} suggestionsService + */ + constructor( + private actions$: Actions, + private store$: Store, + private translate: TranslateService, + private notificationsService: NotificationsService, + private suggestionsService: SuggestionsService + ) { + } +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts new file mode 100644 index 00000000000..f8bd53ec050 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts @@ -0,0 +1,100 @@ +import { SuggestionTargetActionTypes, SuggestionTargetsActions } from './suggestion-targets.actions'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; + +/** + * The interface representing the OpenAIRE suggestion targets state. + */ +export interface SuggestionTargetState { + targets: OpenaireSuggestionTarget[]; + processing: boolean; + loaded: boolean; + totalPages: number; + currentPage: number; + totalElements: number; + currentUserTargets: OpenaireSuggestionTarget[]; + currentUserTargetsVisited: boolean; +} + +/** + * Used for the OpenAIRE Suggestion Target state initialization. + */ +const SuggestionTargetInitialState: SuggestionTargetState = { + targets: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0, + currentUserTargets: null, + currentUserTargetsVisited: false +}; + +/** + * The OpenAIRE Broker Topic Reducer + * + * @param state + * the current state initialized with SuggestionTargetInitialState + * @param action + * the action to perform on the state + * @return SuggestionTargetState + * the new state + */ +export function SuggestionTargetsReducer(state = SuggestionTargetInitialState, action: SuggestionTargetsActions): SuggestionTargetState { + switch (action.type) { + case SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE: { + return Object.assign({}, state, { + targets: [], + processing: true + }); + } + + case SuggestionTargetActionTypes.ADD_TARGETS: { + return Object.assign({}, state, { + targets: state.targets.concat(action.payload.targets), + processing: false, + loaded: true, + totalPages: action.payload.totalPages, + currentPage: state.currentPage, + totalElements: action.payload.totalElements + }); + } + + case SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR: { + return Object.assign({}, state, { + targets: [], + processing: false, + loaded: true, + totalPages: 0, + currentPage: 0, + totalElements: 0, + }); + } + + case SuggestionTargetActionTypes.ADD_USER_SUGGESTIONS: { + return Object.assign({}, state, { + currentUserTargets: action.payload.suggestionTargets + }); + } + + case SuggestionTargetActionTypes.MARK_USER_SUGGESTIONS_AS_VISITED: { + return Object.assign({}, state, { + currentUserTargetsVisited: true + }); + } + + case SuggestionTargetActionTypes.CLEAR_TARGETS: { + return Object.assign({}, state, { + targets: [], + processing: false, + loaded: false, + totalPages: 0, + currentPage: 0, + totalElements: 0, + }); + } + + default: { + return state; + } + } +} diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts new file mode 100644 index 00000000000..2e05bce0a9b --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts @@ -0,0 +1,164 @@ +import { Injectable } from '@angular/core'; + +import { select, Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { + getCurrentUserSuggestionTargetsSelector, + getCurrentUserSuggestionTargetsVisitedSelector, + getreciterSuggestionTargetCurrentPageSelector, + getreciterSuggestionTargetTotalsSelector, + isReciterSuggestionTargetLoadedSelector, + isreciterSuggestionTargetProcessingSelector, + reciterSuggestionTargetObjectSelector +} from '../selectors'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { + ClearSuggestionTargetsAction, + MarkUserSuggestionsAsVisitedAction, + RefreshUserSuggestionsAction, + RetrieveTargetsBySourceAction +} from './suggestion-targets.actions'; +import { OpenaireState } from '../../openaire.reducer'; + +/** + * The service handling the Suggestion targets State. + */ +@Injectable() +export class SuggestionTargetsStateService { + + /** + * Initialize the service variables. + * @param {Store} store + */ + constructor(private store: Store) { } + + /** + * Returns the list of Reciter Suggestion Targets from the state. + * + * @return Observable + * The list of Reciter Suggestion Targets. + */ + public getReciterSuggestionTargets(): Observable { + return this.store.pipe(select(reciterSuggestionTargetObjectSelector())); + } + + /** + * Returns the information about the loading status of the Reciter Suggestion Targets (if it's running or not). + * + * @return Observable + * 'true' if the targets are loading, 'false' otherwise. + */ + public isReciterSuggestionTargetsLoading(): Observable { + return this.store.pipe( + select(isReciterSuggestionTargetLoadedSelector), + map((loaded: boolean) => !loaded) + ); + } + + /** + * Returns the information about the loading status of the Reciter Suggestion Targets (whether or not they were loaded). + * + * @return Observable + * 'true' if the targets are loaded, 'false' otherwise. + */ + public isReciterSuggestionTargetsLoaded(): Observable { + return this.store.pipe(select(isReciterSuggestionTargetLoadedSelector)); + } + + /** + * Returns the information about the processing status of the Reciter Suggestion Targets (if it's running or not). + * + * @return Observable + * 'true' if there are operations running on the targets (ex.: a REST call), 'false' otherwise. + */ + public isReciterSuggestionTargetsProcessing(): Observable { + return this.store.pipe(select(isreciterSuggestionTargetProcessingSelector)); + } + + /** + * Returns, from the state, the total available pages of the Reciter Suggestion Targets. + * + * @return Observable + * The number of the Reciter Suggestion Targets pages. + */ + public getReciterSuggestionTargetsTotalPages(): Observable { + return this.store.pipe(select(getreciterSuggestionTargetTotalsSelector)); + } + + /** + * Returns the current page of the Reciter Suggestion Targets, from the state. + * + * @return Observable + * The number of the current Reciter Suggestion Targets page. + */ + public getReciterSuggestionTargetsCurrentPage(): Observable { + return this.store.pipe(select(getreciterSuggestionTargetCurrentPageSelector)); + } + + /** + * Returns the total number of the Reciter Suggestion Targets. + * + * @return Observable + * The number of the Reciter Suggestion Targets. + */ + public getReciterSuggestionTargetsTotals(): Observable { + return this.store.pipe(select(getreciterSuggestionTargetTotalsSelector)); + } + + /** + * Dispatch a request to change the Reciter Suggestion Targets state, retrieving the targets from the server. + * + * @param source + * the source for which to retrieve suggestion targets + * @param elementsPerPage + * The number of the targets per page. + * @param currentPage + * The number of the current page. + */ + public dispatchRetrieveReciterSuggestionTargets(source: string, elementsPerPage: number, currentPage: number): void { + this.store.dispatch(new RetrieveTargetsBySourceAction(source, elementsPerPage, currentPage)); + } + + /** + * Returns, from the state, the reciter suggestion targets for the current user. + * + * @return Observable + * The Reciter Suggestion Targets object. + */ + public getCurrentUserSuggestionTargets(): Observable { + return this.store.pipe(select(getCurrentUserSuggestionTargetsSelector)); + } + + /** + * Returns, from the state, whether or not the user has consulted their suggestion targets. + * + * @return Observable + * True if user already visited, false otherwise. + */ + public hasUserVisitedSuggestions(): Observable { + return this.store.pipe(select(getCurrentUserSuggestionTargetsVisitedSelector)); + } + + /** + * Dispatch a new MarkUserSuggestionsAsVisitedAction + */ + public dispatchMarkUserSuggestionsAsVisitedAction(): void { + this.store.dispatch(new MarkUserSuggestionsAsVisitedAction()); + } + + /** + * Dispatch an action to clear the Reciter Suggestion Targets state. + */ + public dispatchClearSuggestionTargetsAction(): void { + this.store.dispatch(new ClearSuggestionTargetsAction()); + } + + /** + * Dispatch an action to refresh the user suggestions. + */ + public dispatchRefreshUserSuggestionsAction(): void { + this.store.dispatch(new RefreshUserSuggestionsAction()); + } +} diff --git a/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.html b/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.html new file mode 100644 index 00000000000..577aa496b38 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.html @@ -0,0 +1,8 @@ + + +
+
+
+
+
+
diff --git a/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss b/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts b/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts new file mode 100644 index 00000000000..094dfab0174 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit } from '@angular/core'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { TranslateService } from '@ngx-translate/core'; +import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SuggestionsService } from '../suggestions.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'ds-suggestions-notification', + templateUrl: './suggestions-notification.component.html', + styleUrls: ['./suggestions-notification.component.scss'] +}) +export class SuggestionsNotificationComponent implements OnInit { + + labelPrefix = 'mydspace.'; + + /** + * The user suggestion targets. + */ + suggestionsRD$: Observable; + + constructor( + private translateService: TranslateService, + private reciterSuggestionStateService: SuggestionTargetsStateService, + private notificationsService: NotificationsService, + private suggestionsService: SuggestionsService + ) { } + + ngOnInit() { + this.suggestionsRD$ = this.reciterSuggestionStateService.getCurrentUserSuggestionTargets(); + } + + /** + * Interpolated params to build the notification suggestions notification. + * @param suggestionTarget + */ + public getNotificationSuggestionInterpolation(suggestionTarget: OpenaireSuggestionTarget): any { + return this.suggestionsService.getNotificationSuggestionInterpolation(suggestionTarget); + } + +} diff --git a/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.html b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.html new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.html @@ -0,0 +1 @@ + diff --git a/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts new file mode 100644 index 00000000000..67678354caf --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts @@ -0,0 +1,79 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SuggestionsPopupComponent } from './suggestions-popup.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { mockSuggestionTargetsObjectOne } from '../../../shared/mocks/reciter-suggestion-targets.mock'; +import { SuggestionsService } from '../suggestions.service'; + +describe('SuggestionsPopupComponent', () => { + let component: SuggestionsPopupComponent; + let fixture: ComponentFixture; + + const suggestionStateService = jasmine.createSpyObj('SuggestionTargetsStateService', { + hasUserVisitedSuggestions: jasmine.createSpy('hasUserVisitedSuggestions'), + getCurrentUserSuggestionTargets: jasmine.createSpy('getCurrentUserSuggestionTargets'), + dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') + }); + + const mockNotificationInterpolation = { count: 12, source: 'source', suggestionId: 'id', displayName: 'displayName' }; + const suggestionService = jasmine.createSpyObj('SuggestionService', { + getNotificationSuggestionInterpolation: + jasmine.createSpy('getNotificationSuggestionInterpolation').and.returnValue(mockNotificationInterpolation) + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [ SuggestionsPopupComponent ], + providers: [ + { provide: SuggestionTargetsStateService, useValue: suggestionStateService }, + { provide: SuggestionsService, useValue: suggestionService }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + ], + schemas: [NO_ERRORS_SCHEMA] + + }) + .compileComponents(); + })); + + describe('should create', () => { + + beforeEach(() => { + fixture = TestBed.createComponent(SuggestionsPopupComponent); + component = fixture.componentInstance; + spyOn(component, 'initializePopup').and.returnValue(null); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + expect(component.initializePopup).toHaveBeenCalled(); + }); + + }); + + describe('when there are publication suggestions', () => { + + beforeEach(() => { + + suggestionStateService.hasUserVisitedSuggestions.and.returnValue(observableOf(false)); + suggestionStateService.getCurrentUserSuggestionTargets.and.returnValue(observableOf([mockSuggestionTargetsObjectOne])); + suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction.and.returnValue(observableOf(null)); + + fixture = TestBed.createComponent(SuggestionsPopupComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should show a notification when new publication suggestions are available', () => { + expect((component as any).notificationsService.success).toHaveBeenCalled(); + expect(suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction).toHaveBeenCalled(); + }); + + }); +}); diff --git a/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts new file mode 100644 index 00000000000..6135cd99eab --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts @@ -0,0 +1,67 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SuggestionsService } from '../suggestions.service'; +import { takeUntil } from 'rxjs/operators'; +import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { isNotEmpty } from '../../../shared/empty.util'; +import { combineLatest, Subject } from 'rxjs'; + +@Component({ + selector: 'ds-suggestions-popup', + templateUrl: './suggestions-popup.component.html', + styleUrls: ['./suggestions-popup.component.scss'] +}) +export class SuggestionsPopupComponent implements OnInit, OnDestroy { + + labelPrefix = 'mydspace.'; + + subscription; + + constructor( + private translateService: TranslateService, + private reciterSuggestionStateService: SuggestionTargetsStateService, + private notificationsService: NotificationsService, + private suggestionsService: SuggestionsService + ) { } + + ngOnInit() { + this.initializePopup(); + } + + public initializePopup() { + const notifier = new Subject(); + this.subscription = combineLatest([ + this.reciterSuggestionStateService.getCurrentUserSuggestionTargets(), + this.reciterSuggestionStateService.hasUserVisitedSuggestions() + ]).pipe(takeUntil(notifier)).subscribe(([suggestions, visited]) => { + if (isNotEmpty(suggestions)) { + if (!visited) { + suggestions.forEach((suggestionTarget: OpenaireSuggestionTarget) => this.showNotificationForNewSuggestions(suggestionTarget)); + this.reciterSuggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction(); + notifier.next(); + notifier.complete(); + } + } + }); + } + + /** + * Show a notification to user for a new suggestions detected + * @param suggestionTarget + * @private + */ + private showNotificationForNewSuggestions(suggestionTarget: OpenaireSuggestionTarget): void { + const content = this.translateService.instant(this.labelPrefix + 'notification.suggestion', + this.suggestionsService.getNotificationSuggestionInterpolation(suggestionTarget)); + this.notificationsService.success('', content, {timeOut:0}, true); + } + + ngOnDestroy() { + if (this.subscription) { + this.subscription.unsubscribe(); + } + } + +} diff --git a/src/app/openaire/reciter-suggestions/suggestions.service.ts b/src/app/openaire/reciter-suggestions/suggestions.service.ts new file mode 100644 index 00000000000..de743d95e34 --- /dev/null +++ b/src/app/openaire/reciter-suggestions/suggestions.service.ts @@ -0,0 +1,296 @@ +import { Injectable } from '@angular/core'; + +import { of, forkJoin, Observable } from 'rxjs'; +import { catchError, map, mergeMap, take } from 'rxjs/operators'; + +import { OpenaireSuggestionsDataService } from '../../core/openaire/reciter-suggestions/openaire-suggestions-data.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 { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { ResearcherProfileService } from '../../core/profile/researcher-profile.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; +import { + getAllSucceededRemoteDataPayload, + getFinishedRemoteData, + getFirstSucceededRemoteDataPayload, + getFirstSucceededRemoteListPayload +} from '../../core/shared/operators'; +import { OpenaireSuggestion } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { TranslateService } from '@ngx-translate/core'; +import { NoContent } from '../../core/shared/NoContent.model'; +import { environment } from '../../../environments/environment'; +import { SuggestionConfig } from '../../../config/layout-config.interfaces'; +import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; + +export interface SuggestionBulkResult { + success: number; + fails: number; +} + +/** + * The service handling all Suggestion Target requests to the REST service. + */ +@Injectable() +export class SuggestionsService { + + /** + * Initialize the service variables. + * @param {AuthService} authService + * @param {ResearcherProfileService} researcherProfileService + * @param {OpenaireSuggestionsDataService} suggestionsDataService + */ + constructor( + private authService: AuthService, + private researcherProfileService: ResearcherProfileService, + private suggestionsDataService: OpenaireSuggestionsDataService, + private translateService: TranslateService + ) { + } + + /** + * Return the list of Suggestion Target managing pagination and errors. + * + * @param source + * The source for which to retrieve targets + * @param elementsPerPage + * The number of the target per page + * @param currentPage + * The page number to retrieve + * @return Observable> + * The list of Suggestion Targets. + */ + public getTargets(source, elementsPerPage, currentPage): Observable> { + const sortOptions = new SortOptions('display', SortDirection.ASC); + + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + + return this.suggestionsDataService.getTargets(source, findListOptions).pipe( + getFinishedRemoteData(), + take(1), + map((rd: RemoteData>) => { + if (rd.hasSucceeded) { + return rd.payload; + } else { + throw new Error('Can\'t retrieve Suggestion Target from the Search Target REST service'); + } + }) + ); + } + + /** + * Return the list of review suggestions Target managing pagination and errors. + * + * @param targetId + * The target id for which to find suggestions. + * @param elementsPerPage + * The number of the target per page + * @param currentPage + * The page number to retrieve + * @param sortOptions + * The sort options + * @return Observable>> + * The list of Suggestion. + */ + public getSuggestions(targetId: string, elementsPerPage, currentPage, sortOptions: SortOptions): Observable> { + const [source, target] = targetId.split(':'); + + const findListOptions: FindListOptions = { + elementsPerPage: elementsPerPage, + currentPage: currentPage, + sort: sortOptions + }; + + return this.suggestionsDataService.getSuggestionsByTargetAndSource(target, source, findListOptions).pipe( + getAllSucceededRemoteDataPayload() + ); + } + + /** + * Clear suggestions requests from cache + */ + public clearSuggestionRequests() { + this.suggestionsDataService.clearSuggestionRequests(); + } + + /** + * Used to delete Suggestion + * @suggestionId + */ + public deleteReviewedSuggestion(suggestionId: string): Observable> { + return this.suggestionsDataService.deleteSuggestion(suggestionId).pipe( + map((response: RemoteData) => { + if (response.isSuccess) { + return response; + } else { + throw new Error('Can\'t delete Suggestion from the Search Target REST service'); + } + }), + take(1) + ); + } + + /** + * Retrieve suggestion targets for the given user + * + * @param user + * The EPerson object for which to retrieve suggestion targets + */ + public retrieveCurrentUserSuggestions(user: EPerson): Observable { + return this.researcherProfileService.findById(user.uuid).pipe( + mergeMap((profile: ResearcherProfile) => { + if (isNotEmpty(profile)) { + return this.researcherProfileService.findRelatedItemId(profile).pipe( + mergeMap((itemId: string) => { + return this.suggestionsDataService.getTargetsByUser(itemId).pipe( + getFirstSucceededRemoteListPayload() + ); + }) + ); + } else { + return of([]); + } + }), + take(1) + ); + } + + /** + * Perform the approve and import operation over a single suggestion + * @param suggestion target suggestion + * @param collectionId the collectionId + * @param workspaceitemService injected dependency + * @private + */ + public approveAndImport(workspaceitemService: WorkspaceitemDataService, + suggestion: OpenaireSuggestion, + collectionId: string): Observable { + + const resolvedCollectionId = this.resolveCollectionId(suggestion, collectionId); + return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, resolvedCollectionId) + .pipe( + getFirstSucceededRemoteDataPayload(), + catchError((error) => of(null)) + ); + } + + /** + * Perform the delete operation over a single suggestion. + * @param suggestionId + */ + public notMine(suggestionId): Observable> { + return this.deleteReviewedSuggestion(suggestionId).pipe( + catchError((error) => of(null)) + ); + } + + /** + * Perform a bulk approve and import operation. + * @param workspaceitemService injected dependency + * @param suggestions the array containing the suggestions + * @param collectionId the collectionId + */ + public approveAndImportMultiple(workspaceitemService: WorkspaceitemDataService, + suggestions: OpenaireSuggestion[], + collectionId: string): Observable { + + return forkJoin(suggestions.map((suggestion: OpenaireSuggestion) => + this.approveAndImport(workspaceitemService, suggestion, collectionId))) + .pipe(map((results: WorkspaceItem[]) => { + return { + success: results.filter((result) => result != null).length, + fails: results.filter((result) => result == null).length + }; + }), take(1)); + } + + /** + * Perform a bulk notMine operation. + * @param suggestions the array containing the suggestions + */ + public notMineMultiple(suggestions: OpenaireSuggestion[]): Observable { + return forkJoin(suggestions.map((suggestion: OpenaireSuggestion) => this.notMine(suggestion.id))) + .pipe(map((results: RemoteData[]) => { + return { + success: results.filter((result) => result != null).length, + fails: results.filter((result) => result == null).length + }; + }), take(1)); + } + + /** + * Get the researcher uuid (for navigation purpose) from a target instance. + * TODO Find a better way + * @param target + * @return the researchUuid + */ + public getTargetUuid(target: OpenaireSuggestionTarget): string { + const tokens = target.id.split(':'); + return tokens.length === 2 ? tokens[1] : null; + } + + /** + * Interpolated params to build the notification suggestions notification. + * @param suggestionTarget + */ + public getNotificationSuggestionInterpolation(suggestionTarget: OpenaireSuggestionTarget): any { + return { + count: suggestionTarget.total, + source: this.translateService.instant(this.translateSuggestionSource(suggestionTarget.source)), + type: this.translateService.instant(this.translateSuggestionType(suggestionTarget.source)), + suggestionId: suggestionTarget.id, + displayName: suggestionTarget.display + }; + } + + public translateSuggestionType(source: string): string { + return 'reciter.suggestion.type.' + source; + } + + public translateSuggestionSource(source: string): string { + return 'reciter.suggestion.source.' + source; + } + + /** + * If the provided collectionId ha no value, tries to resolve it by suggestion source. + * @param suggestion + * @param collectionId + */ + public resolveCollectionId(suggestion: OpenaireSuggestion, collectionId): string { + if (hasValue(collectionId)) { + return collectionId; + } + return environment.suggestion + .find((suggestionConf: SuggestionConfig) => suggestionConf.source === suggestion.source) + .collectionId; + } + + /** + * Return true if all the suggestion are configured with the same fixed collection + * in the configuration. + * @param suggestions + */ + public isCollectionFixed(suggestions: OpenaireSuggestion[]): boolean { + return this.getFixedCollectionIds(suggestions).length === 1; + } + + private getFixedCollectionIds(suggestions: OpenaireSuggestion[]): string[] { + const collectionIds = {}; + suggestions.forEach((suggestion: OpenaireSuggestion) => { + const conf = environment.suggestion.find((suggestionConf: SuggestionConfig) => suggestionConf.source === suggestion.source); + if (hasValue(conf)) { + collectionIds[conf.collectionId] = true; + } + }); + return Object.keys(collectionIds); + } +} diff --git a/src/app/shared/mocks/openaire.mock.ts b/src/app/shared/mocks/openaire.mock.ts new file mode 100644 index 00000000000..95ea8717274 --- /dev/null +++ b/src/app/shared/mocks/openaire.mock.ts @@ -0,0 +1,1797 @@ +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'; +import { SuggestionsService } from '../../openaire/reciter-suggestions/suggestions.service'; + +// 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/mocks/reciter-suggestion-targets.mock.ts b/src/app/shared/mocks/reciter-suggestion-targets.mock.ts new file mode 100644 index 00000000000..42e293e6031 --- /dev/null +++ b/src/app/shared/mocks/reciter-suggestion-targets.mock.ts @@ -0,0 +1,42 @@ +import { ResourceType } from '../../core/shared/resource-type'; +import { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; + +// REST Mock --------------------------------------------------------------------- +// ------------------------------------------------------------------------------- +export const mockSuggestionTargetsObjectOne: OpenaireSuggestionTarget = { + type: new ResourceType('suggestiontarget'), + id: 'reciter:gf3d657-9d6d-4a87-b905-fef0f8cae26', + display: 'Bollini, Andrea', + source: 'reciter', + total: 31, + _links: { + target: { + href: 'https://rest.api/rest/api/core/items/gf3d657-9d6d-4a87-b905-fef0f8cae26' + }, + suggestions: { + href: 'https://rest.api/rest/api/integration/suggestions/search/findByTargetAndSource?target=gf3d657-9d6d-4a87-b905-fef0f8cae26c&source=reciter' + }, + self: { + href: 'https://rest.api/rest/api/integration/suggestiontargets/reciter:gf3d657-9d6d-4a87-b905-fef0f8cae26' + } + } +}; + +export const mockSuggestionTargetsObjectTwo: OpenaireSuggestionTarget = { + type: new ResourceType('suggestiontarget'), + id: 'reciter:nhy567-9d6d-ty67-b905-fef0f8cae26', + display: 'Digilio, Andrea', + source: 'reciter', + total: 12, + _links: { + target: { + href: 'https://rest.api/rest/api/core/items/nhy567-9d6d-ty67-b905-fef0f8cae26' + }, + suggestions: { + href: 'https://rest.api/rest/api/integration/suggestions/search/findByTargetAndSource?target=nhy567-9d6d-ty67-b905-fef0f8cae26&source=reciter' + }, + self: { + href: 'https://rest.api/rest/api/integration/suggestiontargets/reciter:nhy567-9d6d-ty67-b905-fef0f8cae26' + } + } +}; diff --git a/src/app/shared/mocks/reciter-suggestion.mock.ts b/src/app/shared/mocks/reciter-suggestion.mock.ts new file mode 100644 index 00000000000..2ddb49868f1 --- /dev/null +++ b/src/app/shared/mocks/reciter-suggestion.mock.ts @@ -0,0 +1,210 @@ + +// REST Mock --------------------------------------------------------------------- +// ------------------------------------------------------------------------------- + +import { OpenaireSuggestion } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { SUGGESTION } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-objects.resource-type'; + +export const mockSuggestionPublicationOne: OpenaireSuggestion = { + id: '24694772', + display: 'publication one', + source: 'reciter', + externalSourceUri: 'https://dspace7.4science.cloud/server/api/integration/reciterSourcesEntry/pubmed/entryValues/24694772', + score: '48', + evidences: { + acceptedRejectedEvidence: { + score: '2.7', + notes: 'some notes, eventually empty or null' + }, + authorNameEvidence: { + score: '0', + notes: 'some notes, eventually empty or null' + }, + journalCategoryEvidence: { + score: '6', + notes: 'some notes, eventually empty or null' + }, + affiliationEvidence: { + score: 'xxx', + notes: 'some notes, eventually empty or null' + }, + relationshipEvidence: { + score: '9', + notes: 'some notes, eventually empty or null' + }, + educationYearEvidence: { + score: '3.6', + notes: 'some notes, eventually empty or null' + }, + personTypeEvidence: { + score: '4', + notes: 'some notes, eventually empty or null' + }, + articleCountEvidence: { + score: '6.7', + notes: 'some notes, eventually empty or null' + }, + averageClusteringEvidence: { + score: '7', + notes: 'some notes, eventually empty or null' + } + }, + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://publication/0000-0003-3681-2038', + language: null, + authority: null, + confidence: -1, + place: -1 + } as any + ], + 'dc.title': [ + { + value: 'publication one', + language: null, + authority: null, + confidence: -1 + } as any + ], + 'dc.date.issued': [ + { + value: '2010-11-03', + language: null, + authority: null, + confidence: -1 + } as any + ], + 'dspace.entity.type': [ + { + uuid: '95f21fe6-ce38-43d6-96d4-60ae66385a06', + language: null, + value: 'OrgUnit', + place: 0, + authority: null, + confidence: -1 + } as any + ], + 'dc.description': [ + { + uuid: '95f21fe6-ce38-43d6-96d4-60ae66385a06', + language: null, + value: "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).", + place: 0, + authority: null, + confidence: -1 + } as any + ] + }, + type: SUGGESTION, + _links: { + target: { + href: 'https://dspace7.4science.cloud/server/api/core/items/gf3d657-9d6d-4a87-b905-fef0f8cae26' + }, + self: { + href: 'https://dspace7.4science.cloud/server/api/integration/suggestions/reciter:gf3d657-9d6d-4a87-b905-fef0f8cae26c:24694772' + } + } +}; + +export const mockSuggestionPublicationTwo: OpenaireSuggestion = { + id: '24694772', + display: 'publication two', + source: 'reciter', + externalSourceUri: 'https://dspace7.4science.cloud/server/api/integration/reciterSourcesEntry/pubmed/entryValues/24694772', + score: '48', + evidences: { + acceptedRejectedEvidence: { + score: '2.7', + notes: 'some notes, eventually empty or null' + }, + authorNameEvidence: { + score: '0', + notes: 'some notes, eventually empty or null' + }, + journalCategoryEvidence: { + score: '6', + notes: 'some notes, eventually empty or null' + }, + affiliationEvidence: { + score: 'xxx', + notes: 'some notes, eventually empty or null' + }, + relationshipEvidence: { + score: '9', + notes: 'some notes, eventually empty or null' + }, + educationYearEvidence: { + score: '3.6', + notes: 'some notes, eventually empty or null' + }, + personTypeEvidence: { + score: '4', + notes: 'some notes, eventually empty or null' + }, + articleCountEvidence: { + score: '6.7', + notes: 'some notes, eventually empty or null' + }, + averageClusteringEvidence: { + score: '7', + notes: 'some notes, eventually empty or null' + } + }, + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://publication/0000-0003-3681-2038', + language: null, + authority: null, + confidence: -1, + place: -1 + } as any + ], + 'dc.title': [ + { + value: 'publication one', + language: null, + authority: null, + confidence: -1 + } as any + ], + 'dc.date.issued': [ + { + value: '2010-11-03', + language: null, + authority: null, + confidence: -1 + } as any + ], + 'dspace.entity.type': [ + { + uuid: '95f21fe6-ce38-43d6-96d4-60ae66385a06', + language: null, + value: 'OrgUnit', + place: 0, + authority: null, + confidence: -1 + } as any + ], + 'dc.description': [ + { + uuid: '95f21fe6-ce38-43d6-96d4-60ae66385a06', + language: null, + value: "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).", + place: 0, + authority: null, + confidence: -1 + } as any + ] + }, + type: SUGGESTION, + _links: { + target: { + href: 'https://dspace7.4science.cloud/server/api/core/items/gf3d657-9d6d-4a87-b905-fef0f8cae26' + }, + self: { + href: 'https://dspace7.4science.cloud/server/api/integration/suggestions/reciter:gf3d657-9d6d-4a87-b905-fef0f8cae26c:24694772' + } + } +}; diff --git a/src/app/suggestions-page/suggestions-page-routing-paths.ts b/src/app/suggestions-page/suggestions-page-routing-paths.ts new file mode 100644 index 00000000000..0f3aa782d21 --- /dev/null +++ b/src/app/suggestions-page/suggestions-page-routing-paths.ts @@ -0,0 +1,11 @@ +import { URLCombiner } from '../core/url-combiner/url-combiner'; + +export const SUGGESTION_MODULE_PATH = 'suggestions'; + +export function getSuggestionModuleRoute() { + return `/${SUGGESTION_MODULE_PATH}`; +} + +export function getSuggestionPageRoute(SuggestionId: string) { + return new URLCombiner(getSuggestionModuleRoute(), SuggestionId).toString(); +} diff --git a/src/app/suggestions-page/suggestions-page-routing.module.ts b/src/app/suggestions-page/suggestions-page-routing.module.ts new file mode 100644 index 00000000000..20ed658707e --- /dev/null +++ b/src/app/suggestions-page/suggestions-page-routing.module.ts @@ -0,0 +1,36 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { SuggestionsPageResolver } from './suggestions-page.resolver'; +import { SuggestionsPageComponent } from './suggestions-page.component'; +import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; +import { SiteAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: ':targetId', + resolve: { + suggestionTargets: SuggestionsPageResolver, + breadcrumb: I18nBreadcrumbResolver + }, + data: { + title: 'admin.notifications.recitersuggestion.page.title', + breadcrumbKey: 'admin.notifications.recitersuggestion', + showBreadcrumbsFluid: false + }, + canActivate: [AuthenticatedGuard], + runGuardsAndResolvers: 'always', + component: SuggestionsPageComponent, + }, + ]) + ], + providers: [ + SuggestionsPageResolver + ] +}) +export class SuggestionsPageRoutingModule { + +} diff --git a/src/app/suggestions-page/suggestions-page.component.html b/src/app/suggestions-page/suggestions-page.component.html new file mode 100644 index 00000000000..fb5f08b6a4c --- /dev/null +++ b/src/app/suggestions-page/suggestions-page.component.html @@ -0,0 +1,48 @@ +
+
+
+ +
+ +

+ {{ translateSuggestionType() | translate }} + {{'reciter.suggestion.suggestionFor' | translate}} + {{researcherName}} + {{'reciter.suggestion.from.source' | translate}} {{ translateSuggestionSource() | translate }} +

+ +
+ + ({{ getSelectedSuggestionsCount() }}) + + +
+ + +
    +
  • + +
  • +
+
+
+
+
+
+
diff --git a/src/app/suggestions-page/suggestions-page.component.scss b/src/app/suggestions-page/suggestions-page.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts new file mode 100644 index 00000000000..ad518930d98 --- /dev/null +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -0,0 +1,107 @@ +import { CommonModule } from '@angular/common'; +import { BrowserModule } from '@angular/platform-browser'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; + +import { SuggestionsPageComponent } from './suggestions-page.component'; +import { SuggestionListElementComponent } from '../openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionsService } from '../openaire/reciter-suggestions/suggestions.service'; +import { getMockOpenaireStateService, getMockSuggestionsService } from '../shared/mocks/openaire.mock'; +import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; +import { OpenaireSuggestion } from '../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/reciter-suggestion.mock'; +import { SuggestionEvidencesComponent } from '../openaire/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; +import { VarDirective } from '../shared/utils/var.directive'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RouterStub } from '../shared/testing/router.stub'; +import { mockSuggestionTargetsObjectOne } from '../shared/mocks/reciter-suggestion-targets.mock'; +import { AuthService } from '../core/auth/auth.service'; +import { NotificationsService } from '../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; +import { getMockTranslateService } from '../shared/mocks/translate.service.mock'; +import { SuggestionTargetsStateService } from '../openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; +import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; +import { PageInfo } from '../core/shared/page-info.model'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; +import { PaginationService } from '../core/pagination/pagination.service'; + +describe('SuggestionPageComponent', () => { + let component: SuggestionsPageComponent; + let fixture: ComponentFixture; + let scheduler: TestScheduler; + const mockSuggestionsService = getMockSuggestionsService(); + const mockSuggestionsTargetStateService = getMockOpenaireStateService(); + const suggestionTargetsList: PaginatedList = buildPaginatedList(new PageInfo(), [mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + const router = new RouterStub(); + const routeStub = { + data: observableOf({ + suggestionTargets: createSuccessfulRemoteDataObject(mockSuggestionTargetsObjectOne) + }), + queryParams: observableOf({}) + }; + const workspaceitemServiceMock = jasmine.createSpyObj('WorkspaceitemDataService', { + importExternalSourceEntry: jasmine.createSpy('importExternalSourceEntry') + }); + + const authService = jasmine.createSpyObj('authService', { + isAuthenticated: observableOf(true), + setRedirectUrl: {} + }); + const paginationService = new PaginationServiceStub(); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + BrowserModule, + CommonModule, + TranslateModule.forRoot() + ], + declarations: [ + SuggestionEvidencesComponent, + SuggestionListElementComponent, + SuggestionsPageComponent, + ObjectKeysPipe, + VarDirective + ], + providers: [ + { provide: AuthService, useValue: authService }, + { provide: ActivatedRoute, useValue: routeStub }, + { provide: WorkspaceitemDataService, useValue: workspaceitemServiceMock }, + { provide: Router, useValue: router }, + { provide: SuggestionsService, useValue: mockSuggestionsService }, + { provide: SuggestionTargetsStateService, useValue: mockSuggestionsTargetStateService }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: TranslateService, useValue: getMockTranslateService() }, + { provide: PaginationService, useValue: paginationService }, + SuggestionsPageComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents().then(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SuggestionsPageComponent); + component = fixture.componentInstance; + scheduler = getTestScheduler(); + }); + + it('should create', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + + expect(component).toBeTruthy(); + expect(component.suggestionId).toBe(mockSuggestionTargetsObjectOne.id); + expect(component.researcherName).toBe(mockSuggestionTargetsObjectOne.display); + expect(component.updatePage).toHaveBeenCalled(); + }); +}); diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts new file mode 100644 index 00000000000..911f6167de5 --- /dev/null +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -0,0 +1,285 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Data, Router } from '@angular/router'; + +import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; +import { distinctUntilChanged, map, switchMap, take } from 'rxjs/operators'; +import { TranslateService } from '@ngx-translate/core'; + +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 { getFirstSucceededRemoteDataPayload, redirectOn4xx } from '../core/shared/operators'; +import { SuggestionBulkResult, SuggestionsService } from '../openaire/reciter-suggestions/suggestions.service'; +import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; +import { OpenaireSuggestion } from '../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; +import { OpenaireSuggestionTarget } from '../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; +import { AuthService } from '../core/auth/auth.service'; +import { SuggestionApproveAndImport } from '../openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { NotificationsService } from '../shared/notifications/notifications.service'; +import { SuggestionTargetsStateService } from '../openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; +import { PaginationService } from '../core/pagination/pagination.service'; +import { FindListOptions } from '../core/data/request.models'; +import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; + +@Component({ + selector: 'ds-suggestion-page', + templateUrl: './suggestions-page.component.html', + styleUrls: ['./suggestions-page.component.scss'], +}) +export class SuggestionsPageComponent implements OnInit { + + /** + * The pagination configuration + */ + paginationOptions: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'sp', + pageSizeOptions: [5, 10, 20, 40, 60] + }); + + /** + * The sorting configuration + */ + paginationSortConfig: SortOptions = new SortOptions('trust', SortDirection.DESC); + + /** + * The FindListOptions object + */ + defaultConfig: FindListOptions = Object.assign(new FindListOptions(), {sort: this.paginationSortConfig}); + + /** + * A boolean representing if results are loading + */ + public processing$ = new BehaviorSubject(false); + + /** + * A list of remote data objects of suggestions + */ + suggestionsRD$: BehaviorSubject> = new BehaviorSubject>({} as any); + + targetRD$: Observable>; + targetId$: Observable; + + suggestionTarget: OpenaireSuggestionTarget; + suggestionId: any; + suggestionSource: any; + researcherName: any; + researcherUuid: any; + + selectedSuggestions: { [id: string]: OpenaireSuggestion } = {}; + isBulkOperationPending = false; + + constructor( + private authService: AuthService, + private notificationService: NotificationsService, + private paginationService: PaginationService, + private route: ActivatedRoute, + private router: Router, + private suggestionService: SuggestionsService, + private suggestionTargetsStateService: SuggestionTargetsStateService, + private translateService: TranslateService, + private workspaceItemService: WorkspaceitemDataService + ) { + } + + ngOnInit(): void { + this.targetRD$ = this.route.data.pipe( + map((data: Data) => data.suggestionTargets as RemoteData), + redirectOn4xx(this.router, this.authService) + ); + + this.targetId$ = this.targetRD$.pipe( + getFirstSucceededRemoteDataPayload(), + map((target: OpenaireSuggestionTarget) => target.id) + ); + this.targetRD$.pipe( + getFirstSucceededRemoteDataPayload() + ).subscribe((suggestionTarget: OpenaireSuggestionTarget) => { + this.suggestionTarget = suggestionTarget; + this.suggestionId = suggestionTarget.id; + this.researcherName = suggestionTarget.display; + this.suggestionSource = suggestionTarget.source; + this.researcherUuid = this.suggestionService.getTargetUuid(suggestionTarget); + this.updatePage(); + }); + + this.suggestionTargetsStateService.dispatchMarkUserSuggestionsAsVisitedAction(); + } + + /** + * Called when one of the pagination settings is changed + */ + onPaginationChange() { + this.updatePage(); + } + + /** + * Update the list of suggestions + */ + updatePage() { + this.processing$.next(true); + const pageConfig$: Observable = this.paginationService.getFindListOptions( + this.paginationOptions.id, + this.defaultConfig, + ).pipe( + distinctUntilChanged() + ); + combineLatest([this.targetId$, pageConfig$]).pipe( + switchMap(([targetId, config]: [string, FindListOptions]) => { + return this.suggestionService.getSuggestions( + targetId, + config.elementsPerPage, + config.currentPage, + config.sort + ); + }), + take(1) + ).subscribe((results: PaginatedList) => { + this.processing$.next(false); + this.suggestionsRD$.next(results); + this.suggestionService.clearSuggestionRequests(); + // navigate to the mydspace if no suggestions remains + + // if (results.totalElements === 0) { + // const content = this.translateService.instant('reciter.suggestion.empty', + // this.suggestionService.getNotificationSuggestionInterpolation(this.suggestionTarget)); + // this.notificationService.success('', content, {timeOut:0}, true); + // TODO if the target is not the current use route to the suggestion target page + // this.router.navigate(['/mydspace']); + // } + }); + } + + /** + * Used to delete a suggestion. + * @suggestionId + */ + notMine(suggestionId) { + this.suggestionService.notMine(suggestionId).subscribe((res) => { + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); + this.updatePage(); + }); + } + + /** + * Used to delete all selected suggestions. + */ + notMineAllSelected() { + this.isBulkOperationPending = true; + this.suggestionService + .notMineMultiple(Object.values(this.selectedSuggestions)) + .subscribe((results: SuggestionBulkResult) => { + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); + this.updatePage(); + this.isBulkOperationPending = false; + this.selectedSuggestions = {}; + if (results.success > 0) { + this.notificationService.success( + this.translateService.get('reciter.suggestion.notMine.bulk.success', + {count: results.success})); + } + if (results.fails > 0) { + this.notificationService.error( + this.translateService.get('reciter.suggestion.notMine.bulk.error', + {count: results.fails})); + } + }); + } + + /** + * Used to approve & import. + * @param event contains the suggestion and the target collection + */ + approveAndImport(event: SuggestionApproveAndImport) { + this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId) + .subscribe((workspaceitem: WorkspaceItem) => { + const content = this.translateService.instant('reciter.suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id }); + this.notificationService.success('', content, {timeOut:0}, true); + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); + this.updatePage(); + }); + } + + /** + * Used to approve & import all selected suggestions. + * @param event contains the target collection + */ + approveAndImportAllSelected(event: SuggestionApproveAndImport) { + this.isBulkOperationPending = true; + this.suggestionService + .approveAndImportMultiple(this.workspaceItemService, Object.values(this.selectedSuggestions), event.collectionId) + .subscribe((results: SuggestionBulkResult) => { + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); + this.updatePage(); + this.isBulkOperationPending = false; + this.selectedSuggestions = {}; + if (results.success > 0) { + this.notificationService.success( + this.translateService.get('reciter.suggestion.approveAndImport.bulk.success', + {count: results.success})); + } + if (results.fails > 0) { + this.notificationService.error( + this.translateService.get('reciter.suggestion.approveAndImport.bulk.error', + {count: results.fails})); + } + }); + } + + /** + * When a specific suggestion is selected. + * @param object the suggestions + * @param selected the new selected value for the suggestion + */ + onSelected(object: OpenaireSuggestion, selected: boolean) { + if (selected) { + this.selectedSuggestions[object.id] = object; + } else { + delete this.selectedSuggestions[object.id]; + } + } + + /** + * When Toggle Select All occurs. + * @param suggestions all the visible suggestions inside the page + */ + onToggleSelectAll(suggestions: OpenaireSuggestion[]) { + if ( this.getSelectedSuggestionsCount() > 0) { + this.selectedSuggestions = {}; + } else { + suggestions.forEach((suggestion) => { + this.selectedSuggestions[suggestion.id] = suggestion; + }); + } + } + + /** + * The current number of selected suggestions. + */ + getSelectedSuggestionsCount(): number { + return Object.keys(this.selectedSuggestions).length; + } + + /** + * Return true if all the suggestion are configured with the same fixed collection in the configuration. + * @param suggestions + */ + isCollectionFixed(suggestions: OpenaireSuggestion[]): boolean { + return this.suggestionService.isCollectionFixed(suggestions); + } + + /** + * Label to be used to translate the suggestion source. + */ + translateSuggestionSource() { + return this.suggestionService.translateSuggestionSource(this.suggestionSource); + } + + /** + * Label to be used to translate the suggestion type. + */ + translateSuggestionType() { + return this.suggestionService.translateSuggestionType(this.suggestionSource); + } + +} diff --git a/src/app/suggestions-page/suggestions-page.module.ts b/src/app/suggestions-page/suggestions-page.module.ts new file mode 100644 index 00000000000..3fad2d0c19e --- /dev/null +++ b/src/app/suggestions-page/suggestions-page.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { SuggestionsPageComponent } from './suggestions-page.component'; +import { SharedModule } from '../shared/shared.module'; +import { SuggestionsPageRoutingModule } from './suggestions-page-routing.module'; +import { SuggestionsService } from '../openaire/reciter-suggestions/suggestions.service'; +import { OpenaireSuggestionsDataService } from '../core/openaire/reciter-suggestions/openaire-suggestions-data.service'; +import { OpenaireModule } from '../openaire/openaire.module'; + +@NgModule({ + declarations: [SuggestionsPageComponent], + imports: [ + CommonModule, + SharedModule, + OpenaireModule, + SuggestionsPageRoutingModule + ], + providers: [ + OpenaireSuggestionsDataService, + SuggestionsService + ] +}) +export class SuggestionsPageModule { } diff --git a/src/app/suggestions-page/suggestions-page.resolver.ts b/src/app/suggestions-page/suggestions-page.resolver.ts new file mode 100644 index 00000000000..0027ae2e779 --- /dev/null +++ b/src/app/suggestions-page/suggestions-page.resolver.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; + +import { Observable } from 'rxjs'; +import { find } from 'rxjs/operators'; + +import { RemoteData } from '../core/data/remote-data'; +import { hasValue } from '../shared/empty.util'; +import { OpenaireSuggestionsDataService } from '../core/openaire/reciter-suggestions/openaire-suggestions-data.service'; +import { OpenaireSuggestionTarget } from '../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; + +/** + * This class represents a resolver that requests a specific collection before the route is activated + */ +@Injectable() +export class SuggestionsPageResolver implements Resolve> { + constructor(private suggestionsDataService: OpenaireSuggestionsDataService) { + } + + /** + * Method for resolving a suggestion target based on the parameters in the current route + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns Observable<> Emits the found collection based on the parameters in the current route, + * or an error if something went wrong + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { + return this.suggestionsDataService.getTargetById(route.params.targetId).pipe( + find((RD) => hasValue(RD.hasFailed) || RD.hasSucceeded), + ); + } +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 2af9d16b0c3..e2919097d6c 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -27,6 +27,10 @@ "404.page-not-found": "page not found", + "admin.notifications.recitersuggestion.breadcrumbs": "Suggestions", + + "admin.notifications.recitersuggestion.page.title": "Suggestions", + "admin.curation-tasks.breadcrumbs": "System curation tasks", "admin.curation-tasks.title": "System curation tasks", @@ -2511,6 +2515,7 @@ "menu.section.icon.unpin": "Unpin sidebar", + "menu.section.icon.notifications": "Notifictions menu section", "menu.section.import": "Import", @@ -2533,6 +2538,10 @@ "menu.section.new_process": "Process", + "menu.section.notifications": "Notifications", + + "menu.section.notifications_reciter": "Publication Claim", + "menu.section.pin": "Pin sidebar", @@ -2960,6 +2969,62 @@ "media-viewer.playlist": "Playlist", + "reciter.suggestion.loading": "Loading ...", + + "reciter.suggestion.title": "Suggestions", + + "reciter.suggestion.targets.description": "Below you can see all the suggestions ", + + "reciter.suggestion.targets": "Current Suggestions", + + "reciter.suggestion.table.name": "Researcher Name", + + "reciter.suggestion.table.actions": "Actions", + + "reciter.suggestion.button.review": "Review {{ total }} suggestion(s)", + + "reciter.suggestion.noTargets": "No target found.", + + "reciter.suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + + "reciter.suggestion.evidence.type": "Type", + + "reciter.suggestion.evidence.score": "Score", + + "reciter.suggestion.evidence.notes": "Notes", + + "reciter.suggestion.approveAndImport": "Approve & import", + + "reciter.suggestion.approveAndImport.success": "The suggestion has been imported successfully", + + "reciter.suggestion.approveAndImport.bulk": "Approve & import Selected", + + "reciter.suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + + "reciter.suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + + "reciter.suggestion.notMine": "Not mine", + + "reciter.suggestion.notMine.success": "The suggestion has been discarded", + + "reciter.suggestion.notMine.bulk": "Not mine Selected", + + "reciter.suggestion.notMine.bulk.success": "{{ count }} suggestions have been discarded ", + + "reciter.suggestion.notMine.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + + "reciter.suggestion.seeEvidence": "See evidence", + + "reciter.suggestion.hideEvidence": "Hide evidence", + + "reciter.suggestion.suggestionFor": "Suggestion for", + + "reciter.suggestion.source.oaire": "OpenAIRE Graph", + + "reciter.suggestion.from.source": "from the ", + + "reciter.suggestion.totalScore": "Total Score", + "register-email.title": "New user registration", From b4d6fbc390282a381e1f7cc340615c40f39e936a Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Mon, 2 May 2022 17:40:51 +0200 Subject: [PATCH 008/592] [CST-5249] Fixed compilation issues --- .../admin-sidebar/admin-sidebar.component.ts | 1 - .../openaire-suggestion-source.model.ts | 2 +- .../openaire-suggestion-target.model.ts | 2 +- .../models/openaire-suggestion.model.ts | 2 +- .../openaire-suggestions-data.service.ts | 4 +- .../submission/workspaceitem-data.service.ts | 31 ++++++++++++- src/app/openaire/openaire.effects.ts | 5 ++ src/app/openaire/openaire.module.ts | 2 + .../openaire/reciter-suggestions/selectors.ts | 6 +-- .../suggestion-list-element.component.html | 1 - .../suggestion-targets.component.html | 1 - .../suggestion-targets.effects.ts | 2 +- .../suggestions.service.ts | 12 ++--- .../suggestions-page.component.ts | 5 +- src/config/app-config.interface.ts | 2 + src/config/default-app-config.ts | 9 ++++ src/config/layout-config.interfaces.ts | 46 +++++++++++++++++++ 17 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 src/app/openaire/openaire.effects.ts create mode 100644 src/config/layout-config.interfaces.ts diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.ts index a8c5ef800c7..b770e3d6753 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -42,7 +42,6 @@ import { Router, ActivatedRoute } from '@angular/router'; import {NOTIFICATIONS_RECITER_SUGGESTION_PATH} from "../admin-notifications/admin-notifications-routing-paths"; import { MenuID } from '../../shared/menu/menu-id.model'; import { MenuItemType } from '../../shared/menu/menu-item-type.model'; -import { ActivatedRoute } from '@angular/router'; /** * Component representing the admin sidebar diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts index 6da9fd47b9b..d71b49b913f 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts @@ -1,11 +1,11 @@ import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; import { SUGGESTION_SOURCE } from './openaire-suggestion-objects.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 Suggestion Source model diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts index e35972bc798..06f85ea5b3c 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts @@ -1,11 +1,11 @@ import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; import { SUGGESTION_TARGET } from './openaire-suggestion-objects.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 Suggestion Target model diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts index 3ff5d7b630c..2d28ccf9bc3 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts @@ -1,12 +1,12 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/object-cache.reducer'; import { SUGGESTION } from './openaire-suggestion-objects.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 { MetadataMap, MetadataMapSerializer } from '../../../shared/metadata.models'; +import {CacheableObject} from "../../../cache/cacheable-object.model"; export interface SuggestionEvidences { [sectionId: string]: { diff --git a/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts index d961eaf9b52..7454caa1d93 100644 --- a/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts +++ b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts @@ -4,14 +4,12 @@ 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 { 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'; @@ -24,6 +22,8 @@ import { OpenaireSuggestionTarget } from './models/openaire-suggestion-target.mo import { OpenaireSuggestion } from './models/openaire-suggestion.model'; import { RequestParam } from '../../cache/models/request-param.model'; 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 */ diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 1b9782834c0..a4dbaab6ca5 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import {HttpClient, HttpHeaders} from '@angular/common/http'; import { Store } from '@ngrx/store'; import { dataService } from '../cache/builders/build-decorators'; @@ -17,6 +17,10 @@ import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core-state.model'; import { FindListOptions } from '../data/find-list-options.model'; +import {HttpOptions} from "../dspace-rest/dspace-rest.service"; +import {find, map} from "rxjs/operators"; +import {PostRequest} from "../data/request.models"; +import {hasValue} from "../../shared/empty.util"; /** * A service that provides methods to make REST requests with workspaceitems endpoint. @@ -57,4 +61,29 @@ export class WorkspaceitemDataService extends DataService { return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + /** + * Import an external source entry into a collection + * @param externalSourceEntryHref + * @param collectionId + */ + public importExternalSourceEntry(externalSourceEntryHref: string, collectionId: string): Observable> { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + + const requestId = this.requestService.generateRequestId(); + const href$ = this.halService.getEndpoint(this.linkPath).pipe(map((href) => `${href}?owningCollection=${collectionId}`)); + + href$.pipe( + find((href: string) => hasValue(href)), + map((href: string) => { + const request = new PostRequest(requestId, href, externalSourceEntryHref, options); + this.requestService.send(request); + }) + ).subscribe(); + + return this.rdbService.buildFromRequestUUID(requestId); + } + } diff --git a/src/app/openaire/openaire.effects.ts b/src/app/openaire/openaire.effects.ts new file mode 100644 index 00000000000..d771089f92b --- /dev/null +++ b/src/app/openaire/openaire.effects.ts @@ -0,0 +1,5 @@ +import { SuggestionTargetsEffects } from './reciter-suggestions/suggestion-targets/suggestion-targets.effects'; + +export const openaireEffects = [ + SuggestionTargetsEffects +]; diff --git a/src/app/openaire/openaire.module.ts b/src/app/openaire/openaire.module.ts index 22d04f3002b..ace4622190f 100644 --- a/src/app/openaire/openaire.module.ts +++ b/src/app/openaire/openaire.module.ts @@ -18,12 +18,14 @@ import { SuggestionsPopupComponent } from './reciter-suggestions/suggestions-pop import { SuggestionsNotificationComponent } from './reciter-suggestions/suggestions-notification/suggestions-notification.component'; import { TranslateModule } from '@ngx-translate/core'; import { SearchModule } from '../shared/search/search.module'; +import {openaireEffects} from "./openaire.effects"; const MODULES = [ CommonModule, SharedModule, CoreModule.forRoot(), StoreModule.forFeature('openaire', openaireReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(openaireEffects), TranslateModule ]; diff --git a/src/app/openaire/reciter-suggestions/selectors.ts b/src/app/openaire/reciter-suggestions/selectors.ts index e699b27dbae..292e63472a7 100644 --- a/src/app/openaire/reciter-suggestions/selectors.ts +++ b/src/app/openaire/reciter-suggestions/selectors.ts @@ -1,8 +1,8 @@ -import { createSelector, MemoizedSelector } from '@ngrx/store'; -import { subStateSelector } from '../../shared/selector.util'; +import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/store'; import { openaireSelector, OpenaireState } from '../openaire.reducer'; import { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; +import {subStateSelector} from "../../submission/selectors"; /** * Returns the Reciter Suggestion Target state. @@ -10,7 +10,7 @@ import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.r * @param {AppState} state Top level state. * @return {OpenaireState} */ -const _getReciterSuggestionTargetState = (state: any) => state.openaire; +const _getReciterSuggestionTargetState = createFeatureSelector('openaire'); // Reciter Suggestion Targets // ---------------------------------------------------------------------------- diff --git a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html index 05f9c0ac771..f37d595c45b 100644 --- a/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html +++ b/src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html @@ -21,7 +21,6 @@ [showLabel]="false" [object]="listableObject" [linkType]="0" - [hideMetrics]="true" > {{'reciter.suggestion.title'| transla [paginationOptions]="paginationConfig" [collectionSize]="(totalElements$ | async)" [hideGear]="false" - [hideSortOptions]="true" [retainScrollPosition]="false" (paginationChange)="getSuggestionTargets()"> diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts index 85e871403c4..9a007fab214 100644 --- a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts @@ -81,7 +81,7 @@ export class SuggestionTargetsEffects { return this.store$.select((state: any) => state.core.auth.user) .pipe( switchMap((user: EPerson) => { - return this.suggestionsService.retrieveCurrentUserSuggestions(user) + return this.suggestionsService.retrieveCurrentUserSuggestions(user.uuid) .pipe( map((suggestionTargets: OpenaireSuggestionTarget[]) => new AddUserSuggestionsAction(suggestionTargets)), catchError((errors) => of(errors)) diff --git a/src/app/openaire/reciter-suggestions/suggestions.service.ts b/src/app/openaire/reciter-suggestions/suggestions.service.ts index de743d95e34..5908c8c6bff 100644 --- a/src/app/openaire/reciter-suggestions/suggestions.service.ts +++ b/src/app/openaire/reciter-suggestions/suggestions.service.ts @@ -5,7 +5,6 @@ import { catchError, map, mergeMap, take } from 'rxjs/operators'; import { OpenaireSuggestionsDataService } from '../../core/openaire/reciter-suggestions/openaire-suggestions-data.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 { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; @@ -25,8 +24,9 @@ import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-da import { TranslateService } from '@ngx-translate/core'; import { NoContent } from '../../core/shared/NoContent.model'; import { environment } from '../../../environments/environment'; -import { SuggestionConfig } from '../../../config/layout-config.interfaces'; import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; +import {FindListOptions} from "../../core/data/find-list-options.model"; +import {SuggestionConfig} from "../../../config/layout-config.interfaces"; export interface SuggestionBulkResult { success: number; @@ -142,11 +142,11 @@ export class SuggestionsService { /** * Retrieve suggestion targets for the given user * - * @param user - * The EPerson object for which to retrieve suggestion targets + * @param userUuid + * The EPerson id for which to retrieve suggestion targets */ - public retrieveCurrentUserSuggestions(user: EPerson): Observable { - return this.researcherProfileService.findById(user.uuid).pipe( + public retrieveCurrentUserSuggestions(userUuid: string): Observable { + return this.researcherProfileService.findById(userUuid).pipe( mergeMap((profile: ResearcherProfile) => { if (isNotEmpty(profile)) { return this.researcherProfileService.findRelatedItemId(profile).pipe( diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 911f6167de5..850a30da221 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -8,7 +8,7 @@ import { TranslateService } from '@ngx-translate/core'; 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 { getFirstSucceededRemoteDataPayload, redirectOn4xx } from '../core/shared/operators'; +import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; import { SuggestionBulkResult, SuggestionsService } from '../openaire/reciter-suggestions/suggestions.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { OpenaireSuggestion } from '../core/openaire/reciter-suggestions/models/openaire-suggestion.model'; @@ -19,8 +19,9 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { SuggestionTargetsStateService } from '../openaire/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { PaginationService } from '../core/pagination/pagination.service'; -import { FindListOptions } from '../core/data/request.models'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; +import {FindListOptions} from "../core/data/find-list-options.model"; +import {redirectOn4xx} from "../core/shared/authorized.operators"; @Component({ selector: 'ds-suggestion-page', diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 121e80cd74b..6446e7f127f 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -14,6 +14,7 @@ import { AuthConfig } from './auth-config.interfaces'; import { UIServerConfig } from './ui-server-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { BrowseByConfig } from './browse-by-config.interface'; +import {SuggestionConfig} from "./layout-config.interfaces"; interface AppConfig extends Config { ui: UIServerConfig; @@ -32,6 +33,7 @@ interface AppConfig extends Config { collection: CollectionPageConfig; themes: ThemeConfig[]; mediaViewer: MediaViewerConfig; + suggestion: SuggestionConfig[]; } const APP_CONFIG = new InjectionToken('APP_CONFIG'); diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index dc54c2fcb0f..aea29fc819e 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -14,6 +14,7 @@ import { ServerConfig } from './server-config.interface'; import { SubmissionConfig } from './submission-config.interface'; import { ThemeConfig } from './theme.model'; import { UIServerConfig } from './ui-server-config.interface'; +import {SuggestionConfig} from "./layout-config.interfaces"; export class DefaultAppConfig implements AppConfig { production = false; @@ -210,6 +211,14 @@ export class DefaultAppConfig implements AppConfig { } }; + suggestion: SuggestionConfig[] = [ + // { + // // Use this configuration to map a suggestion import to a specific collection based on the suggestion type. + // source: 'suggestionSource', + // collectionId: 'collectionUUID' + // } + ]; + // Theme Config themes: ThemeConfig[] = [ // Add additional themes here. In the case where multiple themes match a route, the first one diff --git a/src/config/layout-config.interfaces.ts b/src/config/layout-config.interfaces.ts new file mode 100644 index 00000000000..0b15a06aa92 --- /dev/null +++ b/src/config/layout-config.interfaces.ts @@ -0,0 +1,46 @@ +import { Config } from './config.interface'; + +export interface UrnConfig extends Config { + name: string; + baseUrl: string; +} + +export interface CrisRefConfig extends Config { + entityType: string; + icon: string; +} + +export interface CrisLayoutMetadataBoxConfig extends Config { + defaultMetadataLabelColStyle: string; + defaultMetadataValueColStyle: string; +} + +export interface CrisLayoutTypeConfig { + orientation: string; +} + +export interface NavbarConfig extends Config { + showCommunityCollection: boolean; +} + +export interface CrisItemPageConfig extends Config { + [entity: string]: CrisLayoutTypeConfig; + default: CrisLayoutTypeConfig; +} + + +export interface CrisLayoutConfig extends Config { + urn: UrnConfig[]; + crisRef: CrisRefConfig[]; + itemPage: CrisItemPageConfig; + metadataBox: CrisLayoutMetadataBoxConfig; +} + +export interface LayoutConfig extends Config { + navbar: NavbarConfig; +} + +export interface SuggestionConfig extends Config { + source: string; + collectionId: string; +} From 11d25e66997d99bd1cb932c057feff3f8dc30e70 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Wed, 4 May 2022 13:16:13 +0200 Subject: [PATCH 009/592] [CST-5249] Fixed suggestion page --- .../admin-sidebar/admin-sidebar.component.ts | 2 +- src/app/core/core.module.ts | 2 +- .../openaire-suggestion-source.model.ts | 2 +- .../openaire-suggestion-target.model.ts | 2 +- .../models/openaire-suggestion.model.ts | 2 +- .../openaire-suggestions-data.service.ts | 5 +- .../submission/workspaceitem-data.service.ts | 8 +- src/app/openaire/openaire.module.ts | 2 +- .../openaire/reciter-suggestions/selectors.ts | 2 +- .../suggestion-targets.actions.ts | 1 + .../suggestion-targets.effects.ts | 6 +- .../suggestions.service.ts | 4 +- .../dso-selector-modal-wrapper.component.ts | 24 +- src/app/shared/mocks/openaire.mock.ts | 445 ------------------ .../suggestions-page.component.ts | 4 +- src/assets/i18n/en.json5 | 1 + src/config/app-config.interface.ts | 2 +- src/config/default-app-config.ts | 2 +- src/environments/environment.test.ts | 8 + 19 files changed, 55 insertions(+), 469 deletions(-) diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.ts index b770e3d6753..c13599be9da 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -39,7 +39,7 @@ import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { Router, ActivatedRoute } from '@angular/router'; -import {NOTIFICATIONS_RECITER_SUGGESTION_PATH} from "../admin-notifications/admin-notifications-routing-paths"; +import {NOTIFICATIONS_RECITER_SUGGESTION_PATH} from '../admin-notifications/admin-notifications-routing-paths'; import { MenuID } from '../../shared/menu/menu-id.model'; import { MenuItemType } from '../../shared/menu/menu-item-type.model'; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 7273996401c..879ba76c7df 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -168,7 +168,7 @@ import { OpenaireSuggestionSource } from './openaire/reciter-suggestions/models/ import { ResearcherProfileService } from './profile/researcher-profile.service'; import { ProfileClaimService } from '../profile-page/profile-claim/profile-claim.service'; import { ResearcherProfile } from './profile/model/researcher-profile.model'; -import {SubmissionAccessesModel} from "./config/models/config-submission-accesses.model"; +import {SubmissionAccessesModel} from './config/models/config-submission-accesses.model'; /** * When not in production, endpoint responses can be mocked for testing purposes diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts index d71b49b913f..00f5f11936b 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-source.model.ts @@ -5,7 +5,7 @@ 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"; +import {CacheableObject} from '../../../cache/cacheable-object.model'; /** * The interface representing the Suggestion Source model diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts index 06f85ea5b3c..96a43c96544 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion-target.model.ts @@ -5,7 +5,7 @@ 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"; +import {CacheableObject} from '../../../cache/cacheable-object.model'; /** * The interface representing the Suggestion Target model diff --git a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts index 2d28ccf9bc3..0f84072c6ba 100644 --- a/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts +++ b/src/app/core/openaire/reciter-suggestions/models/openaire-suggestion.model.ts @@ -6,7 +6,7 @@ import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; import { typedObject } from '../../../cache/builders/build-decorators'; import { MetadataMap, MetadataMapSerializer } from '../../../shared/metadata.models'; -import {CacheableObject} from "../../../cache/cacheable-object.model"; +import {CacheableObject} from '../../../cache/cacheable-object.model'; export interface SuggestionEvidences { [sectionId: string]: { diff --git a/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts index 7454caa1d93..3c1d04c0404 100644 --- a/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts +++ b/src/app/core/openaire/reciter-suggestions/openaire-suggestions-data.service.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; @@ -22,8 +23,8 @@ import { OpenaireSuggestionTarget } from './models/openaire-suggestion-target.mo import { OpenaireSuggestion } from './models/openaire-suggestion.model'; import { RequestParam } from '../../cache/models/request-param.model'; import { NoContent } from '../../shared/NoContent.model'; -import {CoreState} from "../../core-state.model"; -import {FindListOptions} from "../../data/find-list-options.model"; +import {CoreState} from '../../core-state.model'; +import {FindListOptions} from '../../data/find-list-options.model'; /* tslint:disable:max-classes-per-file */ diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index a4dbaab6ca5..6c0e909bb48 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -17,10 +17,10 @@ import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core-state.model'; import { FindListOptions } from '../data/find-list-options.model'; -import {HttpOptions} from "../dspace-rest/dspace-rest.service"; -import {find, map} from "rxjs/operators"; -import {PostRequest} from "../data/request.models"; -import {hasValue} from "../../shared/empty.util"; +import {HttpOptions} from '../dspace-rest/dspace-rest.service'; +import {find, map} from 'rxjs/operators'; +import {PostRequest} from '../data/request.models'; +import {hasValue} from '../../shared/empty.util'; /** * A service that provides methods to make REST requests with workspaceitems endpoint. diff --git a/src/app/openaire/openaire.module.ts b/src/app/openaire/openaire.module.ts index ace4622190f..8ae52b27f4b 100644 --- a/src/app/openaire/openaire.module.ts +++ b/src/app/openaire/openaire.module.ts @@ -18,7 +18,7 @@ import { SuggestionsPopupComponent } from './reciter-suggestions/suggestions-pop import { SuggestionsNotificationComponent } from './reciter-suggestions/suggestions-notification/suggestions-notification.component'; import { TranslateModule } from '@ngx-translate/core'; import { SearchModule } from '../shared/search/search.module'; -import {openaireEffects} from "./openaire.effects"; +import {openaireEffects} from './openaire.effects'; const MODULES = [ CommonModule, diff --git a/src/app/openaire/reciter-suggestions/selectors.ts b/src/app/openaire/reciter-suggestions/selectors.ts index 292e63472a7..cfbb36d4c2a 100644 --- a/src/app/openaire/reciter-suggestions/selectors.ts +++ b/src/app/openaire/reciter-suggestions/selectors.ts @@ -2,7 +2,7 @@ import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/sto import { openaireSelector, OpenaireState } from '../openaire.reducer'; import { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; -import {subStateSelector} from "../../submission/selectors"; +import {subStateSelector} from '../../submission/selectors'; /** * Returns the Reciter Suggestion Target state. diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts index 6c44d40b915..33dfb1474b2 100644 --- a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { Action } from '@ngrx/store'; import { type } from '../../../shared/ngrx/type'; import { OpenaireSuggestionTarget } from '../../../core/openaire/reciter-suggestions/models/openaire-suggestion-target.model'; diff --git a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts index 9a007fab214..29672ad49b8 100644 --- a/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/openaire/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts @@ -78,10 +78,10 @@ export class SuggestionTargetsEffects { @Effect() refreshUserTargets$ = this.actions$.pipe( ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS), switchMap((action: RefreshUserSuggestionsAction) => { - return this.store$.select((state: any) => state.core.auth.user) + return this.store$.select((state: any) => state.core.auth.userId) .pipe( - switchMap((user: EPerson) => { - return this.suggestionsService.retrieveCurrentUserSuggestions(user.uuid) + switchMap((userId: string) => { + return this.suggestionsService.retrieveCurrentUserSuggestions(userId) .pipe( map((suggestionTargets: OpenaireSuggestionTarget[]) => new AddUserSuggestionsAction(suggestionTargets)), catchError((errors) => of(errors)) diff --git a/src/app/openaire/reciter-suggestions/suggestions.service.ts b/src/app/openaire/reciter-suggestions/suggestions.service.ts index 5908c8c6bff..67b496b903a 100644 --- a/src/app/openaire/reciter-suggestions/suggestions.service.ts +++ b/src/app/openaire/reciter-suggestions/suggestions.service.ts @@ -25,8 +25,8 @@ import { TranslateService } from '@ngx-translate/core'; import { NoContent } from '../../core/shared/NoContent.model'; import { environment } from '../../../environments/environment'; import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; -import {FindListOptions} from "../../core/data/find-list-options.model"; -import {SuggestionConfig} from "../../../config/layout-config.interfaces"; +import {FindListOptions} from '../../core/data/find-list-options.model'; +import {SuggestionConfig} from '../../../config/layout-config.interfaces'; export interface SuggestionBulkResult { success: number; diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index ca8343cfad4..3b3ef59ae51 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { RemoteData } from '../../../core/data/remote-data'; @@ -21,11 +21,22 @@ export enum SelectorActionType { template: '' }) export abstract class DSOSelectorModalWrapperComponent implements OnInit { + + /** + * The discovery configuration. + */ + @Input() configuration = 'default'; + /** * The current page's DSO */ @Input() dsoRD: RemoteData; + /** + * Representing if component should emit value of selected entries or navigate + */ + @Input() emitOnly = false; + /** * Optional header to display above the selection list * Supports i18n keys @@ -47,6 +58,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ action: SelectorActionType; + /** + * Event emitted when a DSO entry is selected if emitOnly is set to true + */ + @Output() select: EventEmitter = new EventEmitter(); + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) { } @@ -85,7 +101,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ selectObject(dso: DSpaceObject) { this.close(); - this.navigate(dso); + if (this.emitOnly) { + this.select.emit(dso); + } else { + this.navigate(dso); + } } /** diff --git a/src/app/shared/mocks/openaire.mock.ts b/src/app/shared/mocks/openaire.mock.ts index 95ea8717274..d6c50510cd5 100644 --- a/src/app/shared/mocks/openaire.mock.ts +++ b/src/app/shared/mocks/openaire.mock.ts @@ -1,17 +1,5 @@ -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'; import { SuggestionsService } from '../../openaire/reciter-suggestions/suggestions.service'; @@ -1330,414 +1318,6 @@ export const OpenaireMockDspaceObject: SearchResult = Object.assig } ); -// 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 // ------------------------------------------------------------------------------- @@ -1757,31 +1337,6 @@ export function getMockOpenaireStateService(): any { 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]] */ diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 850a30da221..3d6ced5ef57 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -20,8 +20,8 @@ import { SuggestionTargetsStateService } from '../openaire/reciter-suggestions/s import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { PaginationService } from '../core/pagination/pagination.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; -import {FindListOptions} from "../core/data/find-list-options.model"; -import {redirectOn4xx} from "../core/shared/authorized.operators"; +import {FindListOptions} from '../core/data/find-list-options.model'; +import {redirectOn4xx} from '../core/shared/authorized.operators'; @Component({ selector: 'ds-suggestion-page', diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index fbc04033d61..f79cf799e5d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3033,6 +3033,7 @@ "reciter.suggestion.totalScore": "Total Score", + "reciter.suggestion.type.oaire": "OpenAIRE", "register-email.title": "New user registration", diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 6446e7f127f..fbd84fae844 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -14,7 +14,7 @@ import { AuthConfig } from './auth-config.interfaces'; import { UIServerConfig } from './ui-server-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { BrowseByConfig } from './browse-by-config.interface'; -import {SuggestionConfig} from "./layout-config.interfaces"; +import {SuggestionConfig} from './layout-config.interfaces'; interface AppConfig extends Config { ui: UIServerConfig; diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index aea29fc819e..9def4849f57 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -14,7 +14,7 @@ import { ServerConfig } from './server-config.interface'; import { SubmissionConfig } from './submission-config.interface'; import { ThemeConfig } from './theme.model'; import { UIServerConfig } from './ui-server-config.interface'; -import {SuggestionConfig} from "./layout-config.interfaces"; +import {SuggestionConfig} from './layout-config.interfaces'; export class DefaultAppConfig implements AppConfig { production = false; diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 7c24ef8f05f..6bf3a9ab8f9 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -2,6 +2,7 @@ import { BuildConfig } from 'src/config/build-config.interface'; import { RestRequestMethod } from '../app/core/data/rest-request-method'; import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; +import {SuggestionConfig} from '../config/layout-config.interfaces'; export const environment: BuildConfig = { production: false, @@ -203,6 +204,13 @@ export const environment: BuildConfig = { undoTimeout: 10000 // 10 seconds } }, + suggestion: [ + // { + // // Use this configuration to map a suggestion import to a specific collection based on the suggestion type. + // source: 'suggestionSource', + // collectionId: 'collectionUUID' + // } + ], themes: [ { name: 'full-item-page-theme', From d5c1b11d77a67e29e687f94d529764b2bbb410b5 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Wed, 6 Jul 2022 17:04:11 +0200 Subject: [PATCH 010/592] [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 89ef1bfc885..00000000000 --- 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 57a79e017bf..00000000000 --- 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 f014b4d133e..00000000000 --- 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 57f635d5da3..00000000000 --- 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 f6d3eb20fe5..00000000000 --- 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 1ec08948270..00000000000 --- 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 dbdae2e6b9a..00000000000 --- 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 c21e0ce73ba..00000000000 --- 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 4f60ffd3fdd..00000000000 --- 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 469cbb980ff..2820a9a2c7b 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 4e5997e2035..c9cca6d8d80 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 6351498dc57..ba0c6eee58a 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 00000000000..315209d3429 --- /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 00000000000..b9520782154 --- /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 00000000000..a1e15d5bdb7 --- /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 dcf530858cc..3139355629f 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 114f5f7df12..6201e0a7435 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 d4fd354d92b..ac9bdb48d66 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 00000000000..709103cf3d2 --- /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 00000000000..451c911c4ce --- /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 00000000000..624e71f281e --- /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 8450e20c3ce..47500d18783 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 00000000000..fc905ad7240 --- /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 00000000000..a32f60f017a --- /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 00000000000..53f951ba541 --- /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 a2ee9abc2d8..fcc8160f88b 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 16d55479ae0..556665adbd7 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 7f4761009d9..59f6c31e057 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 e7012eee4fe..33c7b338edb 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 4df326f325b..15fbae7821d 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 2493ae02d1e..585216c34f8 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 3f18c3affb0..f59467384ff 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 e3d10dc5abf..8cd5bec61bc 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 d1f2e6ff502..529980e5f7c 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 984f44bd15d..dff604b0c40 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 ebbbe995d1a..85045aebcd0 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 06931e2032c..cb828141a6d 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 9f0b93cfb39..da901267097 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 5395796380c..00000000000 --- 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 e80643049c2..00000000000 --- 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 2a7be1bf13d..00000000000 --- 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 91048a93ef3..cabda48ec58 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 cbee503acd1..99605a54fa0 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 39ecded7970..bf70a058554 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 63224fdd81b..27e34c8d516 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 27bebbea205..5800788c42c 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 a9f51cefd09..40fa75943f8 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 40be083567d..976d8540e3a 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 7639554c55d..aa47bfc590f 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 7cac576844c..42a57c2ac5e 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 64672fa1fac..64a5f6908fe 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 a3fd9240c81..7a22e7a9ae9 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 a7e1e527483..5309098c555 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.title'| translate}}

{{'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 6c0ad42ce8a..ba3a903cc5e 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 070e03f396f..fde1afec436 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 bd8b3f00cd9..6d8aa275d53 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 74bc77d3ec4..fcb717067d5 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 00000000000..08e26a177ac --- /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 e94804cbf68..06f020be1d2 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 00000000000..30a889d3e2f --- /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 622ecc81414..0506806587d 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 8b27778ee94..b563a355f57 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 @@

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

[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 dbb81373211..8e154eca990 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 a740ca5c1ee..f825358f3bf 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 e3e1e16098f..14c0dacc238 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 523fac95508..a1c002d3f25 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 00000000000..ff94f1b8bb1 --- /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 e5616df3208..6d945446b2f 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 80c52a70a96..c09a0750e01 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 0436a35eb30..3ab769aa95e 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 8af034ea323..845c13a4cee 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 d092e4f2c81..0f5db4eb5be 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 011/592] [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 3ab769aa95e..2b78b947f83 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 012/592] [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 c9cca6d8d80..dc0d82c1d99 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 53f951ba541..1b4f1d70aa8 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 556665adbd7..3734ae0dd2c 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 59f6c31e057..67863cad745 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 33c7b338edb..2dedc84d086 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 15fbae7821d..f070e7303ad 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 585216c34f8..5f4c8dd954a 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 8cd5bec61bc..7e12dd9ca81 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 dff604b0c40..d574b36802a 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 85045aebcd0..10bcfbe896a 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 cb828141a6d..458bc4957d6 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 da901267097..da9d95d290d 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 4c97d3d1b30..e4eba116228 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 cabda48ec58..8c191415b70 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 5800788c42c..4cce554f95c 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 40fa75943f8..d7f6129b3b2 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.events.title'| translate}}

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

- + [sortOptions]="paginationSortConfig" (paginationChange)="getQualityAssuranceEvents()"> - +
- - - - - + + + + + @@ -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 aa47bfc590f..6e3dd8d010a 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 64a5f6908fe..64a2df30ba1 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 5309098c555..20f4d4394a5 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.source'| translate}}

[hideSortOptions]="true" (paginationChange)="getQualityAssuranceSource()"> - +
{{'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.source'| translate}}

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

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

@@ -155,13 +166,13 @@ @@ -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/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 9bc06027875..91904d6bc57 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -11,10 +11,10 @@ import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { Operation } from 'fast-json-patch'; -import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { Router } from '@angular/router'; + @Component({ selector: 'ds-ldn-services-directory', @@ -38,6 +38,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { isProcessingSub: Subscription; private modalRef: any; + constructor( protected ldnServicesService: LdnServicesService, protected paginationService: PaginationService, @@ -45,7 +46,6 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { private cdRef: ChangeDetectorRef, private notificationService: NotificationsService, private translateService: TranslateService, - private router: Router, ) { } @@ -57,18 +57,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( getFirstCompletedRemoteData() - )) ); - - this.ldnServicesRD$.subscribe((rd: RemoteData>) => { - console.log(rd); - if (rd.hasSucceeded) { - this.notificationService.success(this.translateService.get('notification.loaded.success')); - } else { - this.notificationService.error(this.translateService.get('notification.loaded.failure')); - } - }); } ngOnDestroy(): void { @@ -107,9 +97,11 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { ); this.cdRef.detectChanges(); this.closeModal(); - this.notificationService.success(this.translateService.get('notification.created.success')); + this.notificationService.success(this.translateService.get('ldn-service-delete.notification.success.title'), + this.translateService.get('ldn-service-delete.notification.success.content')); } else { - this.notificationService.error(this.translateService.get('notification.created.failure')); + this.notificationService.error(this.translateService.get('ldn-service-delete.notification.error.title'), + this.translateService.get('ldn-service-delete.notification.error.content')); this.cdRef.detectChanges(); } }); @@ -117,24 +109,32 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } + + toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { const newStatus = !ldnService.enabled; - let status = ldnService.enabled; + const originalStatus = ldnService.enabled; + const patchOperation: Operation = { op: 'replace', path: '/enabled', value: newStatus, }; + ldnServicesService.patch(ldnService, [patchOperation]).pipe(getFirstCompletedRemoteData()).subscribe( - () => { - if (status !== newStatus) { + (rd: RemoteData) => { + if (rd.hasSucceeded) { + ldnService.enabled = newStatus; this.notificationService.success(this.translateService.get('ldn-enable-service.notification.success.title'), this.translateService.get('ldn-enable-service.notification.success.content')); } else { + ldnService.enabled = originalStatus; this.notificationService.error(this.translateService.get('ldn-enable-service.notification.error.title'), this.translateService.get('ldn-enable-service.notification.error.content')); } } ); } + + } diff --git a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts index 14d227c131e..7b0c25e832e 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts @@ -67,7 +67,3 @@ export const notifyPatterns = [ ]; -const pattern = notifyPatterns[0]; -console.log(`Pattern Name: ${pattern.name}`); -console.log(`Pattern Description: ${pattern.description}`); -console.log(`Pattern Category: ${pattern.category}`); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7a68fc60c88..7cded8573d4 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -917,9 +917,15 @@ "ldn-service.overview.table.clickToEnable": "Click to enable", "ldn-service.overview.table.clickToDisable": "Click to disable", + "ldn-edit-registered-service.title": "Edit Service", + "ldn-create-service.title": "Create service", + "service.overview.create.modal": "Create Service", + "service.overview.create.body": "Please confirm the creation of this service", "ldn-service-status": "Status", + "service.confirm.create": "Create", + "service.refuse.create": "Discard", "ldn-register-new-service.title": "Register a new service", - "ldn-new-service.form.label.submit": "Submit", + "ldn-new-service.form.label.submit": "Save", "ldn-new-service.form.label.name": "Name", "ldn-new-service.form.label.description": "Description", "ldn-new-service.form.label.url": "Service URL", @@ -939,6 +945,23 @@ "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", "service.overview.delete.body": "Are you sure you want to delete this service?", + "service.overview.edit.body": "Are you sure you want to confirm those service changes?", + "service.overview.edit.modal": "Edit Service", + "service.detail.update": "Edit Service", + "service.detail.return": "Cancel", + "service.overview.reset-form.body": "Are you sure you want to discard those changes and leave?", + "service.overview.reset-form.modal": "Discard Service Changes", + "service.overview.reset-form.reset-confirm":"Discard", + "admin.registries.services-formats.modify.success.head": "Successful Edit", + "admin.registries.services-formats.modify.success.content": "The service has been edited", + "ldn-service-notification.created.success.title": "Successful Create", + "ldn-service-notification.created.success.body": "The service has been created", + "ldn-enable-service.notification.success.title": "Successful status updated", + "ldn-enable-service.notification.success.content": "The service status has been updated", + "ldn-service-delete.notification.success.title": "Successful Deletion", + "ldn-service-delete.notification.success.content": "The service has been deleted", + "ldn-service-delete.notification.error.title": "Failed Deletion", + "ldn-service-delete.notification.error.content": "The service has not been deleted", "service.overview.delete": "Delete service", "ldn-edit-service.title": "Edit service", "ldn-edit-service.form.label.name": "Name", @@ -954,7 +977,7 @@ "ldn-edit-service.form.label.outboundPattern": "Outbound Pattern", "ldn-edit-service.form.label.noOutboundPatternSelected": "No Outbound Pattern", "ldn-edit-service.form.label.addOutboundPattern": "+ Add more", - "ldn-edit-service.form.label.submit": "Submit", + "ldn-edit-service.form.label.submit": "Save", "ldn-edit-service.breadcrumbs": "Edit Service", From 0963a320810bf091938644b144e0d2692ca8c9f0 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 12:59:21 +0200 Subject: [PATCH 093/592] CST-12174 Updated delete services to mark for deletion --- .../admin-ldn-services-routing.module.ts | 48 +- .../admin-ldn-services.module.ts | 30 +- .../ldn-service-form-edit.component.html | 468 ++++++------- .../ldn-service-form-edit.component.scss | 18 +- .../ldn-service-form-edit.component.spec.ts | 28 +- .../ldn-service-form-edit.component.ts | 638 +++++++++--------- .../ldn-service-form.component.html | 445 ++++++------ .../ldn-service-form.component.scss | 20 +- .../ldn-service-form.component.spec.ts | 32 +- .../ldn-service-form.component.ts | 328 +++++---- .../ldn-service-new.component.spec.ts | 32 +- .../ldn-service-new.component.ts | 29 +- .../ldnServicesRD$-mock.ts | 6 +- .../ldn-itemfilters-data.service.ts | 13 +- .../ldn-services-data.service.ts | 171 +++-- .../ldn-services-directory.component.html | 37 +- .../ldn-services-directory.component.spec.ts | 32 +- .../ldn-services-directory.component.ts | 222 +++--- .../ldn-services-guard.service.ts | 40 +- .../ldn-services.guard.spec.ts | 18 +- .../ldn-service-itemfilters.ts | 3 +- .../ldn-service-patterns.model.ts | 12 +- .../ldn-service-status.model.ts | 6 +- .../ldn-service.constrain.model.ts | 2 +- .../ldn-services-model/ldn-services.model.ts | 1 - .../ldn-directory.service.spec.ts | 18 +- .../ldn-directory.service.ts | 24 +- .../ldn-service-bulk-delete.service.spec.ts | 18 +- 28 files changed, 1365 insertions(+), 1374 deletions(-) diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 4f05bca9e34..2d3c68f7cb7 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -7,30 +7,30 @@ import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.compon import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @NgModule({ - imports: [ - RouterModule.forChild([ - { - path: '', - pathMatch: 'full', - component: LdnServicesOverviewComponent, - resolve: { breadcrumb: I18nBreadcrumbResolver }, - data: { title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new' }, - canActivate: [LdnServicesGuard] - }, - { - path: 'new', - resolve: { breadcrumb: I18nBreadcrumbResolver }, - component: LdnServiceNewComponent, - data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' } - }, - { - path: 'edit/:serviceId', - resolve: { breadcrumb: I18nBreadcrumbResolver }, - component: LdnServiceFormEditComponent, - data: { title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service' } - }, - ]), - ] + imports: [ + RouterModule.forChild([ + { + path: '', + pathMatch: 'full', + component: LdnServicesOverviewComponent, + resolve: {breadcrumb: I18nBreadcrumbResolver}, + data: {title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new'}, + canActivate: [LdnServicesGuard] + }, + { + path: 'new', + resolve: {breadcrumb: I18nBreadcrumbResolver}, + component: LdnServiceNewComponent, + data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'} + }, + { + path: 'edit/:serviceId', + resolve: {breadcrumb: I18nBreadcrumbResolver}, + component: LdnServiceFormEditComponent, + data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'} + }, + ]), + ] }) export class AdminLdnServicesRoutingModule { diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index c82250fcec7..9ca3775a9ea 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -10,20 +10,20 @@ import { FormsModule } from '@angular/forms'; import { LdnItemfiltersService } from './ldn-services-data/ldn-itemfilters-data.service'; - @NgModule({ - imports: [ - CommonModule, - SharedModule, - AdminLdnServicesRoutingModule, - FormsModule - ], - declarations: [ - LdnServicesOverviewComponent, - LdnServiceNewComponent, - LdnServiceFormComponent, - LdnServiceFormEditComponent, - ], - providers: [LdnItemfiltersService] + imports: [ + CommonModule, + SharedModule, + AdminLdnServicesRoutingModule, + FormsModule + ], + declarations: [ + LdnServicesOverviewComponent, + LdnServiceNewComponent, + LdnServiceFormComponent, + LdnServiceFormEditComponent, + ], + providers: [LdnItemfiltersService] }) -export class AdminLdnServicesModule { } +export class AdminLdnServicesModule { +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 3781a059ec3..bcd597845d3 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,275 +1,277 @@
-
-
-

{{ 'ldn-edit-registered-service.title' | translate }}

-
- -
- -
- -
-
-
-
-
- -
- - -
- -
-   -
- - -
- - -
- -
-   -
- - -
- - -
- -
-   -
- - -
- - -
- -
-   -
- -
-
- -
-
- -
-
- -
-
-
-
- -
+ +
+

{{ 'ldn-edit-registered-service.title' | translate }}

+
+ +
+ +
+ +
+
+
+
+
- +
+ + +
+
+   +
+ +
+ + +
+
+   +
-
-
- + +
+ +
-
- - - +
+  
-
- -
-
-
+ +
+ +
+
+   +
-
- - +
+
+ +
+
+ +
+
+ +
+
+
-
- -
+
+ + + + +
+
+ +
+ +
+ + + +
+ +
+ +
+
+
+
+ + +
+ + +
+
+
+
- {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
+ {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-
- -
-
- -
-
- -
-
-
-
- -
- - - - -
-
- -
-
- - - +
+  
-
- -
-
-
+
+
+ +
+
+ +
+
+ +
+
+
-
- +
+ + + + +
+
+ +
+
+ + + +
+ +
+ +
+
+
+
+ +
+ +
+
+
-
- -
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
- - +
+   +
+ +
-
+
- + - -
-
+
- + - -
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index df8146330fd..b686e6533bc 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -27,12 +27,13 @@ textarea { resize: none; } -.add-pattern-link{ +.add-pattern-link { color: #0048ff; cursor: pointer; margin-left: 10px; } -.remove-pattern-link{ + +.remove-pattern-link { color: #e34949; cursor: pointer; margin-left: 10px; @@ -75,7 +76,6 @@ textarea { } - .toggle-switch .slider { width: 22px; height: 22px; @@ -101,16 +101,16 @@ textarea { margin-right: 3px } -.label-box{ - margin-left:11px; +.label-box { + margin-left: 11px; } -.label-box-2{ - margin-left:14px; +.label-box-2 { + margin-left: 14px; } -.label-box-3{ - margin-left:5px; +.label-box-3 { + margin-left: 5px; } form button.btn.btn-primary[type="submit"] { diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts index 8320ec90422..332d43cae3b 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts @@ -3,21 +3,21 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LdnServiceFormEditComponent } from './ldn-service-form-edit.component'; describe('LdnServiceFormEditComponent', () => { - let component: LdnServiceFormEditComponent; - let fixture: ComponentFixture; + let component: LdnServiceFormEditComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ LdnServiceFormEditComponent ] - }) - .compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LdnServiceFormEditComponent] + }) + .compileComponents(); - fixture = TestBed.createComponent(LdnServiceFormEditComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(LdnServiceFormEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 39cfb6ac6c6..93622f9df09 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -21,371 +21,365 @@ import { FindListOptions } from '../../../core/data/find-list-options.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; @Component({ - selector: 'ds-ldn-service-form-edit', - templateUrl: './ldn-service-form-edit.component.html', - styleUrls: ['./ldn-service-form-edit.component.scss'], - animations: [ - trigger('toggleAnimation', [ - state('true', style({})), - state('false', style({})), - transition('true <=> false', animate('300ms ease-in')), - ]), - ], + selector: 'ds-ldn-service-form-edit', + templateUrl: './ldn-service-form-edit.component.html', + styleUrls: ['./ldn-service-form-edit.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), + ]), + ], }) export class LdnServiceFormEditComponent implements OnInit { - formModel: FormGroup; - @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; - @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; - - public inboundPatterns: object[] = notifyPatterns; - public outboundPatterns: object[] = notifyPatterns; - itemfiltersRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - @Input() public name: string; - @Input() public description: string; - @Input() public url: string; - @Input() public ldnUrl: string; - @Input() public inboundPattern: string; - @Input() public outboundPattern: string; - @Input() public constraint: string; - @Input() public automatic: boolean; - @Input() public headerKey: string; - private originalInboundPatterns: any[] = []; - private originalOutboundPatterns: any[] = []; - private deletedInboundPatterns: number[] = []; - private deletedOutboundPatterns: number[] = []; - private modalRef: any; - private service: LdnService; - protected serviceId: string; - markedForDeletion: number[] = []; - - - constructor( - protected ldnServicesService: LdnServicesService, - private ldnItemfiltersService: LdnItemfiltersService, - private formBuilder: FormBuilder, - private router: Router, - private route: ActivatedRoute, - private cdRef: ChangeDetectorRef, - protected modalService: NgbModal, - private notificationService: NotificationsService, - private translateService: TranslateService, - protected paginationService: PaginationService - ) { - - this.formModel = this.formBuilder.group({ - id: [''], - name: ['', Validators.required], - description: ['', Validators.required], - url: ['', Validators.required], - ldnUrl: ['', Validators.required], - inboundPattern: [''], - outboundPattern: [''], - constraintPattern: [''], - enabled: [''], - notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), - notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), - type: LDN_SERVICE.value, + formModel: FormGroup; + @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; + @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; + + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + itemfiltersRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 }); - } - - ngOnInit(): void { - this.route.params.subscribe((params) => { - this.serviceId = params.serviceId; - if (this.serviceId) { - this.fetchServiceData(this.serviceId); - } - }); - this.setItemfilters(); - } - - setItemfilters() { - this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( - getFirstCompletedRemoteData()); - } - - - - - fetchServiceData(serviceId: string): void { - this.ldnServicesService.findById(serviceId).pipe( - getFirstCompletedRemoteData() - ).subscribe( - (data: RemoteData) => { - if (data.hasSucceeded) { - this.service = data.payload; - - this.formModel.patchValue({ - id: this.service.id, - name: this.service.name, - description: this.service.description, - url: this.service.url, - ldnUrl: this.service.ldnUrl, - type: this.service.type, - enabled: this.service.enabled - }); - - const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - inboundPatternsArray.clear(); - - this.service.notifyServiceInboundPatterns.forEach((pattern: any) => { - const patternFormGroup = this.initializeInboundPatternFormGroup(); - patternFormGroup.patchValue(pattern); - inboundPatternsArray.push(patternFormGroup); - this.cdRef.detectChanges(); - }); - - const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - outboundPatternsArray.clear(); - - this.service.notifyServiceOutboundPatterns.forEach((pattern: any) => { - const patternFormGroup = this.initializeOutboundPatternFormGroup(); - patternFormGroup.patchValue(pattern); - outboundPatternsArray.push(patternFormGroup); - - this.cdRef.detectChanges(); - }); - this.originalInboundPatterns = [...this.service.notifyServiceInboundPatterns]; - this.originalOutboundPatterns = [...this.service.notifyServiceOutboundPatterns]; - } - }, - ); - } - - generatePatchOperations(): any[] { - const patchOperations: any[] = []; - - this.createReplaceOperation(patchOperations, 'name', '/name'); - this.createReplaceOperation(patchOperations, 'description', '/description'); - this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); - this.createReplaceOperation(patchOperations, 'url', '/url'); - - this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); - - this.deletedInboundPatterns.forEach(index => { - const removeOperation: Operation = { - op: 'remove', - path: `notifyServiceInboundPatterns[${index}]` - }; - patchOperations.push(removeOperation); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 }); + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + @Input() public headerKey: string; + markedForDeletion: number[] = []; + protected serviceId: string; + private originalInboundPatterns: any[] = []; + private originalOutboundPatterns: any[] = []; + private deletedInboundPatterns: number[] = []; + private deletedOutboundPatterns: number[] = []; + private modalRef: any; + private service: LdnService; + + constructor( + protected ldnServicesService: LdnServicesService, + private ldnItemfiltersService: LdnItemfiltersService, + private formBuilder: FormBuilder, + private router: Router, + private route: ActivatedRoute, + private cdRef: ChangeDetectorRef, + protected modalService: NgbModal, + private notificationService: NotificationsService, + private translateService: TranslateService, + protected paginationService: PaginationService + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: ['', Validators.required], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + enabled: [''], + notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), + notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + type: LDN_SERVICE.value, + }); + } - this.deletedOutboundPatterns.forEach(index => { - const removeOperation: Operation = { - op: 'remove', - path: `notifyServiceOutboundPatterns[${index}]` - }; - patchOperations.push(removeOperation); - }); + ngOnInit(): void { + this.route.params.subscribe((params) => { + this.serviceId = params.serviceId; + if (this.serviceId) { + this.fetchServiceData(this.serviceId); + } + }); + this.setItemfilters(); + } - return patchOperations; - } + setItemfilters() { + this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( + getFirstCompletedRemoteData()); + } - onSubmit() { - this.openConfirmModal(this.confirmModal); - } - addInboundPattern() { - const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); - } + fetchServiceData(serviceId: string): void { + this.ldnServicesService.findById(serviceId).pipe( + getFirstCompletedRemoteData() + ).subscribe( + (data: RemoteData) => { + if (data.hasSucceeded) { + this.service = data.payload; + + this.formModel.patchValue({ + id: this.service.id, + name: this.service.name, + description: this.service.description, + url: this.service.url, + ldnUrl: this.service.ldnUrl, + type: this.service.type, + enabled: this.service.enabled + }); + + const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + inboundPatternsArray.clear(); + + this.service.notifyServiceInboundPatterns.forEach((pattern: any) => { + const patternFormGroup = this.initializeInboundPatternFormGroup(); + patternFormGroup.patchValue(pattern); + inboundPatternsArray.push(patternFormGroup); + this.cdRef.detectChanges(); + }); + + const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + outboundPatternsArray.clear(); + + this.service.notifyServiceOutboundPatterns.forEach((pattern: any) => { + const patternFormGroup = this.initializeOutboundPatternFormGroup(); + patternFormGroup.patchValue(pattern); + outboundPatternsArray.push(patternFormGroup); + + this.cdRef.detectChanges(); + }); + this.originalInboundPatterns = [...this.service.notifyServiceInboundPatterns]; + this.originalOutboundPatterns = [...this.service.notifyServiceOutboundPatterns]; + } + }, + ); + } - addOutboundPattern() { - const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); - } + generatePatchOperations(): any[] { + const patchOperations: any[] = []; + + this.createReplaceOperation(patchOperations, 'name', '/name'); + this.createReplaceOperation(patchOperations, 'description', '/description'); + this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); + this.createReplaceOperation(patchOperations, 'url', '/url'); + + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); + this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); + + this.deletedInboundPatterns.forEach(index => { + const removeOperation: Operation = { + op: 'remove', + path: `notifyServiceInboundPatterns[${index}]` + }; + patchOperations.push(removeOperation); + }); + + this.deletedOutboundPatterns.forEach(index => { + const removeOperation: Operation = { + op: 'remove', + path: `notifyServiceOutboundPatterns[${index}]` + }; + patchOperations.push(removeOperation); + }); + + return patchOperations; + } - removeOutboundPattern(index: number): void { - const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - const patternGroup = patternsArray.at(index) as FormGroup; - const patternValue = patternGroup.value; + onSubmit() { + this.openConfirmModal(this.confirmModal); + } + + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } - if (index < 0 || index >= patternsArray.length || patternValue.isNew) { - patternsArray.removeAt(index); - return; + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } + removeOutboundPattern(index: number): void { + const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; - this.deletedOutboundPatterns.push(index); + if (index < 0 || index >= patternsArray.length || patternValue.isNew) { + patternsArray.removeAt(index); + return; + } - patternsArray.removeAt(index); - this.cdRef.detectChanges(); - } + this.deletedOutboundPatterns.push(index); - toggleAutomatic(i: number) { - const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); - if (automaticControl) { - automaticControl.setValue(!automaticControl.value); + patternsArray.removeAt(index); + this.cdRef.detectChanges(); } - } - toggleEnabled() { - const newStatus = !this.formModel.get('enabled').value; - const patchOperation: Operation = { - op: 'replace', - path: '/enabled', - value: newStatus, - }; + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } - this.ldnServicesService.patch(this.service, [patchOperation]).pipe( - getFirstCompletedRemoteData() - ).subscribe( - () => { + toggleEnabled() { + const newStatus = !this.formModel.get('enabled').value; - this.formModel.get('enabled').setValue(newStatus); - this.cdRef.detectChanges(); - } - ); - } + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.ldnServicesService.patch(this.service, [patchOperation]).pipe( + getFirstCompletedRemoteData() + ).subscribe( + () => { + + this.formModel.get('enabled').setValue(newStatus); + this.cdRef.detectChanges(); + } + ); + } - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); - } + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } - openConfirmModal(content) { - this.modalRef = this.modalService.open(content); - } + openConfirmModal(content) { + this.modalRef = this.modalService.open(content); + } + + openResetFormModal(content) { + this.modalRef = this.modalService.open(content); + } - openResetFormModal(content) { - this.modalRef = this.modalService.open(content); - } + patchService() { + this.deleteMarkedPatterns(); + const patchOperations = this.generatePatchOperations(); - patchService() { - this.deleteMarkedPatterns(); - const patchOperations = this.generatePatchOperations(); + this.ldnServicesService.patch(this.service, patchOperations).pipe( + getFirstCompletedRemoteData() + ).subscribe( + () => { - this.ldnServicesService.patch(this.service, patchOperations).pipe( - getFirstCompletedRemoteData() - ).subscribe( - () => { + this.closeModal(); + this.sendBack(); + this.notificationService.success(this.translateService.get('admin.registries.services-formats.modify.success.head'), + this.translateService.get('admin.registries.services-formats.modify.success.content')); + } + ); - this.closeModal(); - this.sendBack(); - this.notificationService.success(this.translateService.get('admin.registries.services-formats.modify.success.head'), - this.translateService.get('admin.registries.services-formats.modify.success.content')); - }, - (error) => { - this.notificationService.error(this.translateService.get('admin.registries.services-formats.modify.failure.head'), - this.translateService.get('admin.registries.services-formats.modify.failure.content')); + } + + resetFormAndLeave() { + this.sendBack(); + this.closeModal(); + } + + markForDeletion(index: number) { + if (!this.markedForDeletion.includes(index)) { + this.markedForDeletion.push(index); } - ); + } - } + unmarkForDeletion(index: number) { + const i = this.markedForDeletion.indexOf(index); + if (i !== -1) { + this.markedForDeletion.splice(i, 1); + } + } + + deleteMarkedPatterns() { + this.markedForDeletion.sort((a, b) => b - a); + const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { - if (this.formModel.get(formControlName).dirty) { - patchOperations.push({ - op: 'replace', - path, - value: this.formModel.get(formControlName).value, - }); + for (const index of this.markedForDeletion) { + if (index >= 0 && index < patternsArray.length) { + this.deletedInboundPatterns.push(index); + patternsArray.removeAt(index); + } + } + + this.markedForDeletion = []; } - } - - private handlePatterns(patchOperations: any[], formArrayName: string): void { - const patternsArray = this.formModel.get(formArrayName) as FormArray; - - for (let i = 0; i < patternsArray.length; i++) { - const patternGroup = patternsArray.at(i) as FormGroup; - const patternValue = patternGroup.value; - - if (patternGroup.dirty) { - if (patternValue.isNew) { - delete patternValue.isNew; - const addOperation = { - op: 'add', - path: `${formArrayName}/-`, - value: patternValue, - }; - patchOperations.push(addOperation); - } else { - const replaceOperation = { - op: 'replace', - path: `${formArrayName}[${i}]`, - value: patternValue, - }; - patchOperations.push(replaceOperation); + + private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { + if (this.formModel.get(formControlName).dirty) { + patchOperations.push({ + op: 'replace', + path, + value: this.formModel.get(formControlName).value, + }); } - } } - } - - private sendBack() { - this.router.navigateByUrl('admin/ldn/services'); - } - - resetFormAndLeave() { - this.sendBack(); - this.closeModal(); - } - - private createOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - constraint: '', - isNew: true, - }); - } - - private createInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - constraint: '', - automatic: false, - isNew: true - }); - } - private initializeOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - constraint: '', - }); - } + private handlePatterns(patchOperations: any[], formArrayName: string): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; + + for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; + const patternValue = patternGroup.value; + + if (patternGroup.dirty) { + if (patternValue.isNew) { + delete patternValue.isNew; + const addOperation = { + op: 'add', + path: `${formArrayName}/-`, + value: patternValue, + }; + patchOperations.push(addOperation); + } else { + const replaceOperation = { + op: 'replace', + path: `${formArrayName}[${i}]`, + value: patternValue, + }; + patchOperations.push(replaceOperation); + } + } + } + } - private initializeInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - constraint: '', - automatic: '', - }); - } - markForDeletion(index: number) { - if (!this.markedForDeletion.includes(index)) { - this.markedForDeletion.push(index); + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); } - } - unmarkForDeletion(index: number) { - const i = this.markedForDeletion.indexOf(index); - if (i !== -1) { - this.markedForDeletion.splice(i, 1); + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + isNew: true, + }); } - } - deleteMarkedPatterns() { - this.markedForDeletion.sort((a, b) => b - a); - const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: false, + isNew: true + }); + } - for (const index of this.markedForDeletion) { - if (index >= 0 && index < patternsArray.length) { - this.deletedInboundPatterns.push(index); - patternsArray.removeAt(index); - } + private initializeOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + }); } - this.markedForDeletion = []; - } + private initializeInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: '', + }); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index b82b05af777..f1afa886f16 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,263 +1,266 @@
-
-
-

{{ 'ldn-create-service.title' | translate }}

-
- -
- - -
- -
-   -
- - -
- - -
- -
-   -
- - -
- - -
- -
-   -
- - -
- - -
- -
-   -
- - -
-
- -
-
- -
-
- -
-
-
-
+ +
+

{{ 'ldn-create-service.title' | translate }}

+
+ +
+ + +
-
+
+   +
- + +
+ + +
+
+   +
-
-
- + +
+ +
+
+   +
-
- - - + +
+ +
-
- -
-
-
+
+  
-
- + +
+
+ +
+
+ +
+
+ +
+
+
-
- -
- {{ 'ldn-new-service.form.label.addPattern' | translate }} +
+ + + + +
+
+ +
+ + +
+ + + +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
- -
-
- -
-
- -
-
-
-
-
-
- -
- - - - -
-
- -
-
- - - +
+  
-
- -
-
-
+ +
+
+ +
+
+ +
+
+
+
+
-
- -
-
- +
+ + + + +
+
+ +
+
+ + + +
+ +
+ +
+
+
+
+ +
+ +
+
+
-
+
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
- - +
+   +
+ - + +
-
+
- + - -
-
+
- + - -
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 523653381b2..f0fdcd81a20 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -27,12 +27,13 @@ textarea { resize: none; } -.add-pattern-link{ +.add-pattern-link { color: #0048ff; cursor: pointer; margin-left: 10px; } -.remove-pattern-link{ + +.remove-pattern-link { color: #e34949; cursor: pointer; margin-left: 10px; @@ -75,7 +76,6 @@ textarea { } - .toggle-switch .slider { width: 22px; height: 22px; @@ -99,21 +99,21 @@ textarea { cursor: pointer; } -.label-box{ - margin-left:11px; +.label-box { + margin-left: 11px; } -.label-box-2{ - margin-left:14px; +.label-box-2 { + margin-left: 14px; } -.label-box-3{ - margin-left:5px; +.label-box-3 { + margin-left: 5px; } form button.btn.btn-primary[type="submit"] { position: absolute; - bottom: 0px; + bottom: 0; right: -10px; } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts index 3ae834d6429..757b6170911 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -3,23 +3,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LdnServiceFormComponent } from './ldn-service-form.component'; describe('LdnServiceFormComponent', () => { - let component: LdnServiceFormComponent; - let fixture: ComponentFixture; + let component: LdnServiceFormComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ LdnServiceFormComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LdnServiceFormComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LdnServiceFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 7e9a1e148fb..ff42ffb4dc9 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -30,203 +30,193 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; @Component({ - selector: 'ds-ldn-service-form', - templateUrl: './ldn-service-form.component.html', - styleUrls: ['./ldn-service-form.component.scss'], - animations: [ - trigger('toggleAnimation', [ - state('true', style({})), - state('false', style({})), - transition('true <=> false', animate('300ms ease-in')), - ]), - ], + selector: 'ds-ldn-service-form', + templateUrl: './ldn-service-form.component.html', + styleUrls: ['./ldn-service-form.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), + ]), + ], }) export class LdnServiceFormComponent implements OnInit { - formModel: FormGroup; - private modalRef: any; - @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; - @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; - - - public inboundPatterns: object[] = notifyPatterns; - public outboundPatterns: object[] = notifyPatterns; - itemfiltersRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - - - - @Input() public name: string; - @Input() public description: string; - @Input() public url: string; - @Input() public ldnUrl: string; - @Input() public inboundPattern: string; - @Input() public outboundPattern: string; - @Input() public constraint: string; - @Input() public automatic: boolean; - - @Input() public headerKey: string; - @Output() submitForm: EventEmitter = new EventEmitter(); - @Output() cancelForm: EventEmitter = new EventEmitter(); - - constructor( - private ldnServicesService: LdnServicesService, - private ldnItemfiltersService: LdnItemfiltersService, - private formBuilder: FormBuilder, - private router: Router, - private notificationsService: NotificationsService, - private translateService: TranslateService, - private cdRef: ChangeDetectorRef, - protected modalService: NgbModal, - - ) { - - this.formModel = this.formBuilder.group({ - enabled: true, - id: [''], - name: ['', Validators.required], - description: [''], - url: ['', Validators.required], - ldnUrl: ['', Validators.required], - inboundPattern: [''], - outboundPattern: [''], - constraintPattern: [''], - notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), - notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), - type: LDN_SERVICE.value, + formModel: FormGroup; + @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; + @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + itemfiltersRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 }); - } - - ngOnInit(): void { - this.setItemfilters(); - - } - setItemfilters() { - this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( - getFirstCompletedRemoteData()); - this.itemfiltersRD$.subscribe((rd: RemoteData>) => { - if (rd.hasSucceeded) { - } + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 }); - } - - onSubmit() { - this.openConfirmModal(this.confirmModal); - } - - openConfirmModal(content) { - this.modalRef = this.modalService.open(content); - } + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + @Input() public headerKey: string; + @Output() submitForm: EventEmitter = new EventEmitter(); + @Output() cancelForm: EventEmitter = new EventEmitter(); + private modalRef: any; + + constructor( + private ldnServicesService: LdnServicesService, + private ldnItemfiltersService: LdnItemfiltersService, + private formBuilder: FormBuilder, + private router: Router, + private notificationsService: NotificationsService, + private translateService: TranslateService, + private cdRef: ChangeDetectorRef, + protected modalService: NgbModal, + ) { + + this.formModel = this.formBuilder.group({ + enabled: true, + id: [''], + name: ['', Validators.required], + description: [''], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), + notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + type: LDN_SERVICE.value, + }); + } - openResetFormModal(content) { - this.modalRef = this.modalService.open(content); - } - createService() { - this.formModel.get('name').markAsTouched(); - this.formModel.get('url').markAsTouched(); - this.formModel.get('ldnUrl').markAsTouched(); + ngOnInit(): void { + this.setItemfilters(); - const name = this.formModel.get('name').value; - const url = this.formModel.get('url').value; - const ldnUrl = this.formModel.get('ldnUrl').value; + } - if (!name || !url || !ldnUrl) { - this.closeModal(); - return; + setItemfilters() { + this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( + getFirstCompletedRemoteData()); } - const values = this.formModel.value; + onSubmit() { + this.openConfirmModal(this.confirmModal); + } - const inboundPatternValue = this.formModel.get('inboundPattern').value; - const outboundPatternValue = this.formModel.get('outboundPattern').value; + openConfirmModal(content) { + this.modalRef = this.modalService.open(content); + } - if (inboundPatternValue === '') { - values.notifyServiceInboundPatterns = []; + openResetFormModal(content) { + this.modalRef = this.modalService.open(content); } - if (outboundPatternValue === '') { - values.notifyServiceOutboundPatterns = []; + + createService() { + this.formModel.get('name').markAsTouched(); + this.formModel.get('url').markAsTouched(); + this.formModel.get('ldnUrl').markAsTouched(); + + const name = this.formModel.get('name').value; + const url = this.formModel.get('url').value; + const ldnUrl = this.formModel.get('ldnUrl').value; + + if (!name || !url || !ldnUrl) { + this.closeModal(); + return; + } + + const values = this.formModel.value; + + const inboundPatternValue = this.formModel.get('inboundPattern').value; + const outboundPatternValue = this.formModel.get('outboundPattern').value; + + if (inboundPatternValue === '') { + values.notifyServiceInboundPatterns = []; + } + if (outboundPatternValue === '') { + values.notifyServiceOutboundPatterns = []; + } + + const ldnServiceData = this.ldnServicesService.create(values); + + ldnServiceData.pipe( + getFirstCompletedRemoteData() + ).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + this.notificationsService.success(this.translateService.get('ldn-service-notification.created.success.title')); + (this.translateService.get('ldn-service-notification.created.success.title'), + this.translateService.get('ldn-service-notification.created.success.body')); + this.sendBack(); + this.closeModal(); + } else { + this.notificationsService.error(this.translateService.get('notification.created.failure')); + } + }); } - const ldnServiceData = this.ldnServicesService.create(values); - ldnServiceData.pipe( - getFirstCompletedRemoteData() - ).subscribe((rd: RemoteData) => { - if (rd.hasSucceeded) { - this.notificationsService.success(this.translateService.get('ldn-service-notification.created.success.title')); - (this.translateService.get('ldn-service-notification.created.success.title'), - this.translateService.get('ldn-service-notification.created.success.body')); + resetFormAndLeave() { this.sendBack(); this.closeModal(); - } else { - this.notificationsService.error(this.translateService.get('notification.created.failure')); - } - }); - } - - - resetFormAndLeave() { - this.sendBack(); - this.closeModal(); - } - - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); - } + } - addInboundPattern() { - const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); - } + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } - removeInboundPattern(index: number) { - const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.removeAt(index); - } + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } - addOutboundPattern() { - const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); - } + removeInboundPattern(index: number) { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.removeAt(index); + } - removeOutboundPattern(index: number) { - const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.removeAt(index); - } + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); + } - toggleAutomatic(i: number) { - const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); - if (automaticControl) { - automaticControl.setValue(!automaticControl.value); + removeOutboundPattern(index: number) { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.removeAt(index); } - } - private sendBack() { - this.router.navigateByUrl('admin/ldn/services'); - } + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } - private createOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: [''], - constraint: [''], - }); - } + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + }); + } - private createInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: [''], - constraint: [''], - automatic: false - }); - } + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + automatic: false + }); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts index 4994823004e..d49d3931958 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts @@ -3,23 +3,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LdnServiceNewComponent } from './ldn-service-new.component'; describe('LdnServiceNewComponent', () => { - let component: LdnServiceNewComponent; - let fixture: ComponentFixture; + let component: LdnServiceNewComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ LdnServiceNewComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LdnServiceNewComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LdnServiceNewComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceNewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts index daf1653cd11..e92c06dc269 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts @@ -4,25 +4,24 @@ import { LdnService } from "../ldn-services-model/ldn-services.model"; import { ActivatedRoute } from "@angular/router"; import { ProcessDataService } from "../../../core/data/processes/process-data.service"; import { LinkService } from "../../../core/cache/builders/link.service"; -import { getFirstSucceededRemoteDataPayload } from "../../../core/shared/operators"; @Component({ - selector: 'ds-ldn-service-new', - templateUrl: './ldn-service-new.component.html', - styleUrls: ['./ldn-service-new.component.scss'] + selector: 'ds-ldn-service-new', + templateUrl: './ldn-service-new.component.html', + styleUrls: ['./ldn-service-new.component.scss'] }) export class LdnServiceNewComponent implements OnInit { - /** - * Emits preselected process if there is one - */ - ldnService$?: Observable; + /** + * Emits preselected process if there is one + */ + ldnService$?: Observable; - constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) { - } + constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) { + } - /** - * If there's an id parameter, use this the process with this identifier as presets for the form - */ - ngOnInit() { - } + /** + * If there's an id parameter, use this the process with this identifier as presets for the form + */ + ngOnInit() { + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index fccb374b5f7..b1a954b9d62 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -37,8 +37,6 @@ export const mockLdnService: LdnService = { }; - - const mockLdnServices = { payload: { elementsPerPage: 20, @@ -52,7 +50,7 @@ const mockLdnServices = { page: [mockLdnService], type: LDN_SERVICE, self: undefined, - getPageLength: function() { + getPageLength: function () { return this.page.length; }, _links: { @@ -67,7 +65,5 @@ const mockLdnServices = { }; - - // Create a mock ldnServicesRD$ observable export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts index 692e1a5db9e..babb00c9594 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts @@ -17,7 +17,6 @@ import { Itemfilter } from '../ldn-services-model/ldn-service-itemfilters'; import { PaginatedList } from '../../../core/data/paginated-list.model'; - /** * A service responsible for fetching/sending data from/to the REST API on the itemfilters endpoint */ @@ -38,11 +37,11 @@ export class LdnItemfiltersService extends IdentifiableDataService i this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } - getEndpoint() { - return this.halService.getEndpoint(this.linkPath); - } + getEndpoint() { + return this.halService.getEndpoint(this.linkPath); + } - findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); - } + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index d2ef16fadae..35f9bee04f2 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -38,90 +38,89 @@ import { hasValue } from 'src/app/shared/empty.util'; @Injectable() @dataService(LDN_SERVICE) export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { - createData: CreateDataImpl; - private findAllData: FindAllDataImpl; - private deleteData: DeleteDataImpl; - private patchData: PatchDataImpl; - private comparator: ChangeAnalyzer; - - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - ) { - super('ldnservices', requestService, rdbService, objectCache, halService); - - this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, 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, this.comparator, this.responseMsToLive, this.constructIdEndpoint); - this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); - } - - - create(object: LdnService): Observable> { - return this.createData.create(object); - } - - patch(object: LdnService, operations: Operation[]): Observable> { - return this.patchData.patch(object, operations); - } - - update(object: LdnService): Observable> { - return this.patchData.update(object); - } - - commitUpdates(method?: RestRequestMethod): void { - return this.patchData.commitUpdates(method); - } - - createPatchFromCache(object: LdnService): Observable { - return this.patchData.createPatchFromCache(object); - } - - findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); - } - - public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { - return this.deleteData.delete(objectId, copyVirtualMetadata); - } - - public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { - return this.deleteData.deleteByHref(href, copyVirtualMetadata); - } - - public invoke(serviceName: string, serviceId: string, parameters: ldnServiceConstrain[], files: File[]): Observable> { - const requestId = this.requestService.generateRequestId(); - this.getBrowseEndpoint().pipe( - take(1), - map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes', serviceId).toString()), - map((endpoint: string) => { - const body = this.getInvocationFormData(parameters, files); - return new MultipartPostRequest(requestId, endpoint, body); - }) - ).subscribe((request: RestRequest) => this.requestService.send(request)); - - return this.rdbService.buildFromRequestUUID(requestId); - } - - - private getInvocationFormData(constrain: ldnServiceConstrain[], files: File[]): FormData { - const form: FormData = new FormData(); - form.set('properties', JSON.stringify(constrain)); - files.forEach((file: File) => { - form.append('file', file); - }); - return form; - } - - public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable { - return this.findById(scriptName).pipe( - getFirstCompletedRemoteData(), - map((rd: RemoteData) => { - return hasValue(rd.payload); - }), - ); - } + createData: CreateDataImpl; + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, 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, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + } + + + create(object: LdnService): Observable> { + return this.createData.create(object); + } + + patch(object: LdnService, operations: Operation[]): Observable> { + return this.patchData.patch(object, operations); + } + + update(object: LdnService): Observable> { + return this.patchData.update(object); + } + + commitUpdates(method?: RestRequestMethod): void { + return this.patchData.commitUpdates(method); + } + + createPatchFromCache(object: LdnService): Observable { + return this.patchData.createPatchFromCache(object); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, serviceId: string, parameters: ldnServiceConstrain[], files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes', serviceId).toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(parameters, files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } + + private getInvocationFormData(constrain: ldnServiceConstrain[], files: File[]): FormData { + const form: FormData = new FormData(); + form.set('properties', JSON.stringify(constrain)); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index 6753c6e90c7..45c2106468d 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -15,34 +15,34 @@

{{ 'ldn-registered-services.title' | 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.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 b38da70f376..29c16328c35 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 41358b20a52..f0109f5f662 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 9f33a022251..f78798ac250 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 20f4d4394a5..0f6cf184024 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 fdc7d554a23..db8586f264d 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 90e73eb0bef..e7e2272fffd 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 026/592] [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 44498c3cab8..dcb3465be4b 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 c094e37ef23..b08b9a4b2a5 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 64a2befeb2d..095357d74b5 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 027/592] [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 1090fd22fcf..35b4b396a7b 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 @@

{{ (labelPrefix + label + '.select' | translate) }}

- - + +
From b8880091e6da2f5168255b8de8a55723cbcb0f94 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Nov 2022 14:41:50 +0100 Subject: [PATCH 028/592] [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 20d0356d5f0..447e5a2e553 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 97ddb9af7dc..7ea73347b7c 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 bde97f364ce..1a43f59a1fc 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 208e45e387f..355de6e6169 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 6e933a0e803..c80d2bce20b 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 029/592] [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 731c70d6243..50d0e43a99c 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 e83c9a8b439..7f7e68afaab 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 f4a2d81b367..50d9251bb88 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 8f16347b252..03a5da2e8c4 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 d16ccbdb005..638ee3fa62e 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 2ab715bbbec..2bf5195bf1e 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 bbdf60c083f..dc1c98c7b95 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 f0109f5f662..04ece87fbb3 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 f78798ac250..e34c121f359 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 b1514171aaf..fd78911ab4d 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 355de6e6169..745a2baef78 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 a0556ece8cc..5c16fb1a03d 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 11d7e115553..13e36700001 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 ba1399fcd43..1e4e3fcffd9 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 968e21fb957..6820791dffd 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 e7e2272fffd..eac527d6726 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 f37122b23cb578407e4dd4055d799736f43c0c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin?= Date: Wed, 30 Nov 2022 15:41:56 -0500 Subject: [PATCH 030/592] Content Reports --- .../admin-reports-routing.module.ts | 37 ++ .../admin-reports/admin-reports.module.ts | 28 ++ .../filtered-collection.model.ts | 36 ++ .../filtered-collections.actions.ts | 0 .../filtered-collections.component.html | 64 +++ .../filtered-collections.component.scss | 15 + .../filtered-collections.component.spec.ts | 83 ++++ .../filtered-collections.component.ts | 58 +++ .../filtered-collections.model.ts | 26 ++ .../filtered-items/filtered-items-model.ts | 23 + .../filtered-items/filtered-items.actions.ts | 0 .../filtered-items.component.html | 156 +++++++ .../filtered-items.component.scss | 19 + .../filtered-items.component.spec.ts | 108 +++++ .../filtered-items.component.ts | 301 ++++++++++++ .../filtered-items/option-vo.model.ts | 46 ++ .../filtered-items/preset-query.model.ts | 17 + .../filtered-items/query-predicate.model.ts | 36 ++ .../filters-section/filter-group.model.ts | 19 + .../filters-section/filter.model.ts | 8 + .../filters-section.component.html | 19 + .../filters-section.component.scss | 0 .../filters-section.component.spec.ts | 101 ++++ .../filters-section.component.ts | 129 ++++++ src/app/admin/admin-routing-paths.ts | 6 + src/app/admin/admin-routing.module.ts | 7 +- src/app/admin/admin.module.ts | 2 + src/app/menu.resolver.ts | 54 +++ src/assets/i18n/ar.json5 | 424 ++++++++++++++++- src/assets/i18n/bn.json5 | 426 ++++++++++++++++- src/assets/i18n/cs.json5 | 424 ++++++++++++++++- src/assets/i18n/de.json5 | 421 ++++++++++++++++- src/assets/i18n/el.json5 | 414 +++++++++++++++++ src/assets/i18n/en.json5 | 211 +++++++++ src/assets/i18n/es.json5 | 425 +++++++++++++++++ src/assets/i18n/fi.json5 | 422 +++++++++++++++++ src/assets/i18n/fr.json5 | 309 +++++++++++++ src/assets/i18n/gd.json5 | 422 +++++++++++++++++ src/assets/i18n/hi.json5 | 425 +++++++++++++++++ src/assets/i18n/hu.json5 | 424 ++++++++++++++++- src/assets/i18n/ja.json5 | 424 ++++++++++++++++- src/assets/i18n/kk.json5 | 424 +++++++++++++++++ src/assets/i18n/lv.json5 | 420 +++++++++++++++++ src/assets/i18n/nl.json5 | 421 ++++++++++++++++- src/assets/i18n/pl.json5 | 424 ++++++++++++++++- src/assets/i18n/pt-BR.json5 | 431 +++++++++++++++++- src/assets/i18n/pt-PT.json5 | 421 ++++++++++++++++- src/assets/i18n/sv.json5 | 423 +++++++++++++++++ src/assets/i18n/sw.json5 | 424 ++++++++++++++++- src/assets/i18n/tr.json5 | 396 +++++++++++++++- 50 files changed, 10313 insertions(+), 40 deletions(-) create mode 100644 src/app/admin/admin-reports/admin-reports-routing.module.ts create mode 100644 src/app/admin/admin-reports/admin-reports.module.ts create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.actions.ts create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts create mode 100644 src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items-model.ts create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.actions.ts create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.component.html create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.component.scss create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.component.ts create mode 100644 src/app/admin/admin-reports/filtered-items/option-vo.model.ts create mode 100644 src/app/admin/admin-reports/filtered-items/preset-query.model.ts create mode 100644 src/app/admin/admin-reports/filtered-items/query-predicate.model.ts create mode 100644 src/app/admin/admin-reports/filters-section/filter-group.model.ts create mode 100644 src/app/admin/admin-reports/filters-section/filter.model.ts create mode 100644 src/app/admin/admin-reports/filters-section/filters-section.component.html create mode 100644 src/app/admin/admin-reports/filters-section/filters-section.component.scss create mode 100644 src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts create mode 100644 src/app/admin/admin-reports/filters-section/filters-section.component.ts diff --git a/src/app/admin/admin-reports/admin-reports-routing.module.ts b/src/app/admin/admin-reports/admin-reports-routing.module.ts new file mode 100644 index 00000000000..9022429502f --- /dev/null +++ b/src/app/admin/admin-reports/admin-reports-routing.module.ts @@ -0,0 +1,37 @@ +import { FilteredCollectionsComponent } from './filtered-collections/filtered-collections.component'; +import { FilteredItemsComponent } from './filtered-items/filtered-items.component'; +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: 'collections', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: {title: 'admin.reports.collections.title', breadcrumbKey: 'admin.reports.collections'}, + children: [ + { + path: '', + component: FilteredCollectionsComponent + } + ] + }, + { + path: 'queries', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: {title: 'admin.reports.items.title', breadcrumbKey: 'admin.reports.items'}, + children: [ + { + path: '', + component: FilteredItemsComponent + } + ] + } + ]) + ] +}) +export class AdminReportsRoutingModule { + +} diff --git a/src/app/admin/admin-reports/admin-reports.module.ts b/src/app/admin/admin-reports/admin-reports.module.ts new file mode 100644 index 00000000000..70dfba8a072 --- /dev/null +++ b/src/app/admin/admin-reports/admin-reports.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FilteredCollectionsComponent } from './filtered-collections/filtered-collections.component'; +import { RouterModule } from '@angular/router'; +import { SharedModule } from '../../shared/shared.module'; +import { FormModule } from '../../shared/form/form.module'; +import { FilteredItemsComponent } from './filtered-items/filtered-items.component'; +import { AdminReportsRoutingModule } from './admin-reports-routing.module'; +import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; +import { FiltersComponent } from './filters-section/filters-section.component'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + RouterModule, + FormModule, + AdminReportsRoutingModule, + NgbAccordionModule + ], + declarations: [ + FilteredCollectionsComponent, + FilteredItemsComponent, + FiltersComponent + ] +}) +export class AdminReportsModule { +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts new file mode 100644 index 00000000000..a48b1e02fa8 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts @@ -0,0 +1,36 @@ +export class FilteredCollection { + + public label: string; + public handle: string; + public communityLabel: string; + public communityHandle: string; + public nbTotalItems: number; + public values = {}; + public allFiltersValue: number; + + public clear() { + this.label = ''; + this.handle = ''; + this.communityLabel = ''; + this.communityHandle = ''; + this.nbTotalItems = 0; + this.values = {}; + this.allFiltersValue = 0; + } + + public deserialize(object: any) { + this.clear(); + this.label = object.label; + this.handle = object.handle; + this.communityLabel = object.community_label; + this.communityHandle = object.community_handle; + this.nbTotalItems = object.nb_total_items; + let valuesPerFilter = object.values; + for (let filter in valuesPerFilter) { + if (valuesPerFilter.hasOwnProperty(filter)) { + this.values[filter] = valuesPerFilter[filter]; + } + } + this.allFiltersValue = object.all_filters_value; + } +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.actions.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.actions.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html new file mode 100644 index 00000000000..514b06719aa --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html @@ -0,0 +1,64 @@ +
+ +
diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss new file mode 100644 index 00000000000..476341a8b94 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss @@ -0,0 +1,15 @@ +.num { + text-align: center; +} + +.stats tbody tr:nth-child(even) { + background: #CCC +} +.stats tbody tr:nth-child(odd) { + background: #FFF +} + +.stats thead tr { + border-bottom-width: 1px; + border-bottom-style: solid; +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts new file mode 100644 index 00000000000..73f3e86a0b3 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts @@ -0,0 +1,83 @@ +import { waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; +import { FormBuilder } from '@angular/forms'; +import { FilteredCollectionsComponent } from './filtered-collections.component'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { NgbAccordion, NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { of as observableOf } from 'rxjs'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; + +describe('FiltersComponent', () => { + let component: FilteredCollectionsComponent; + let fixture: ComponentFixture; + let formBuilder: FormBuilder; + + const expected = { + payload: { + collections: [], + summary: { + label: 'Test' + } + }, + statusCode: 200, + statusText: 'OK' + } as RawRestResponse; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FilteredCollectionsComponent], + imports: [ + NgbAccordionModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }), + HttpClientTestingModule + ], + providers: [ + FormBuilder, + DspaceRestService + ], + schemas: [NO_ERRORS_SCHEMA] + }); + })); + + beforeEach(waitForAsync(() => { + formBuilder = TestBed.inject(FormBuilder); + + fixture = TestBed.createComponent(FilteredCollectionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should be displaying the filters panel initially', () => { + let accordion: NgbAccordion = component.accordionComponent; + expect(accordion.isExpanded('filters')).toBeTrue(); + }); + + describe('toggle', () => { + beforeEach(() => { + spyOn(component, 'postFilteredCollections').and.returnValue(observableOf(expected)); + spyOn(component.results, 'deserialize'); + spyOn(component.accordionComponent, 'expand').and.callThrough(); + component.submit(); + fixture.detectChanges(); + }); + + it('should be displaying the collections panel after submitting', waitForAsync(() => { + fixture.whenStable().then(() => { + expect(component.accordionComponent.expand).toHaveBeenCalledWith('collections'); + expect(component.accordionComponent.isExpanded('collections')).toBeTrue(); + }); + })); + }); +}); diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts new file mode 100644 index 00000000000..4f7e7bb5db8 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts @@ -0,0 +1,58 @@ +import { Component, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'; +import { Observable } from 'rxjs'; +import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; +import { environment } from 'src/environments/environment'; +import { FiltersComponent } from '../filters-section/filters-section.component'; +import { FilteredCollections } from './filtered-collections.model'; + +@Component({ + selector: 'ds-report-filtered-collections', + templateUrl: './filtered-collections.component.html', + styleUrls: ['./filtered-collections.component.scss'] +}) +export class FilteredCollectionsComponent { + + queryForm: FormGroup; + results: FilteredCollections = new FilteredCollections(); + @ViewChild('acc') accordionComponent: NgbAccordion; + + constructor( + private formBuilder: FormBuilder, + private restService: DspaceRestService) {} + + ngOnInit() { + this.queryForm = this.formBuilder.group({ + filters: FiltersComponent.formGroup(this.formBuilder) + }); + } + + filtersFormGroup(): FormGroup { + return this.queryForm.get('filters') as FormGroup; + } + + getGroup(filterId: string): string { + return FiltersComponent.getGroup(filterId).id; + } + + submit() { + this + .postFilteredCollections() + .subscribe( + response => { + this.results.deserialize(response.payload); + this.accordionComponent.expand('collections'); + } + ); + } + + postFilteredCollections(): Observable { + let form = this.queryForm.value; + let scheme = environment.rest.ssl ? 'https' : 'http'; + let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; + return this.restService.request(RestRequestMethod.POST, `${urlRestApp}/api/contentreports/filteredcollections`, form); + } +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts new file mode 100644 index 00000000000..6ea5a2fc80a --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts @@ -0,0 +1,26 @@ +import { FilteredCollection } from './filtered-collection.model'; + +export class FilteredCollections { + + public collections: Array = []; + public summary: FilteredCollection = new FilteredCollection(); + + public clear() { + this.collections.splice(0, this.collections.length); + this.summary.clear(); + } + + public deserialize(object: any) { + this.clear(); + let summary = object.summary; + this.summary.deserialize(summary); + let collections = object.collections; + for (let i = 0; i < collections.length; i++) { + let collection = collections[i]; + let coll = new FilteredCollection(); + coll.deserialize(collection); + this.collections.push(coll); + } + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts new file mode 100644 index 00000000000..5811efe53bd --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts @@ -0,0 +1,23 @@ +import { Item } from "src/app/core/shared/item.model"; + +export class FilteredItems { + + public items: Item[] = []; + public itemCount: number; + + public clear() { + this.items.splice(0, this.items.length); + } + + public deserialize(object: any, offset: number = 0) { + this.clear(); + this.itemCount = object.itemCount; + let items = object.items; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + item.index = this.items.length + offset + 1; + this.items.push(item); + } + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.actions.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.actions.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.html b/src/app/admin/admin-reports/filtered-items/filtered-items.component.html new file mode 100644 index 00000000000..34bad69e852 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.html @@ -0,0 +1,156 @@ +
+ +
diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss b/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss new file mode 100644 index 00000000000..61a7a4516b5 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss @@ -0,0 +1,19 @@ +.predicate { + height: 26px; +} + +.num { + text-align: center; +} + +.stats tbody tr:nth-child(even) { + background: #CCC +} +.stats tbody tr:nth-child(odd) { + background: #FFF +} + +.stats thead tr { + border-bottom-width: 1px; + border-bottom-style: solid; +} diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts new file mode 100644 index 00000000000..70e32d402fc --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts @@ -0,0 +1,108 @@ +import { waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; +import { FormBuilder } from '@angular/forms'; +import { FilteredItemsComponent } from './filtered-items.component'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { NgbAccordion, NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { of as observableOf } from 'rxjs'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; +import { CommunityDataService } from 'src/app/core/data/community-data.service'; +import { ObjectCacheService } from 'src/app/core/cache/object-cache.service'; +import { ActionsSubject, ReducerManager, ReducerManagerDispatcher, StateObservable, Store, StoreModule } from '@ngrx/store'; +import { UUIDService } from 'src/app/core/shared/uuid.service'; +import { RemoteDataBuildService } from 'src/app/core/cache/builders/remote-data-build.service'; +import { HALEndpointService } from 'src/app/core/shared/hal-endpoint.service'; +import { DSOChangeAnalyzer } from 'src/app/core/data/dso-change-analyzer.service'; +import { NotificationsService } from 'src/app/shared/notifications/notifications.service'; +import { BitstreamFormatDataService } from 'src/app/core/data/bitstream-format-data.service'; +import { CollectionDataService } from 'src/app/core/data/collection-data.service'; +import { MetadataSchemaDataService } from 'src/app/core/data/metadata-schema-data.service'; +import { MetadataFieldDataService } from 'src/app/core/data/metadata-field-data.service'; +import { StoreMock } from 'src/app/shared/testing/store.mock'; + +describe('FiltersComponent', () => { + let component: FilteredItemsComponent; + let fixture: ComponentFixture; + let formBuilder: FormBuilder; + + const expected = { + payload: { + items: [], + itemCount: 0 + }, + statusCode: 200, + statusText: 'OK' + } as RawRestResponse; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FilteredItemsComponent], + imports: [ + NgbAccordionModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }), + HttpClientTestingModule, + StoreModule.forRoot({}) + ], + providers: [ + CommunityDataService, + CollectionDataService, + MetadataSchemaDataService, + MetadataFieldDataService, + //TranslateService, + FormBuilder, + DspaceRestService, + // Starting here, these services not referenced directly by the component. + ObjectCacheService, + UUIDService, + RemoteDataBuildService, + HALEndpointService, + DSOChangeAnalyzer, + NotificationsService, + BitstreamFormatDataService + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(waitForAsync(() => { + formBuilder = TestBed.inject(FormBuilder); + + fixture = TestBed.createComponent(FilteredItemsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should be displaying the collectionSelector panel initially', () => { + let accordion: NgbAccordion = component.accordionComponent; + expect(accordion.isExpanded('collectionSelector')).toBeTrue(); + }); + + describe('expand', () => { + beforeEach(() => { + spyOn(component, 'postFilteredItems').and.returnValue(observableOf(expected)); + spyOn(component.results, 'deserialize'); + spyOn(component.accordionComponent, 'expand').and.callThrough(); + component.submit(); + fixture.detectChanges(); + }); + + it('should be displaying the itemResults panel after submitting', waitForAsync(() => { + fixture.whenStable().then(() => { + expect(component.accordionComponent.expand).toHaveBeenCalledWith('itemResults'); + expect(component.accordionComponent.isExpanded('itemResults')).toBeTrue(); + }); + })); + }); +}); diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts new file mode 100644 index 00000000000..21b7f2e12b4 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts @@ -0,0 +1,301 @@ +import { Component, ViewChild } from '@angular/core'; +import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { map, Observable } from 'rxjs'; +import { CollectionDataService } from 'src/app/core/data/collection-data.service'; +import { CommunityDataService } from 'src/app/core/data/community-data.service'; +import { MetadataFieldDataService } from 'src/app/core/data/metadata-field-data.service'; +import { MetadataSchemaDataService } from 'src/app/core/data/metadata-schema-data.service'; +import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; +import { MetadataField } from 'src/app/core/metadata/metadata-field.model'; +import { MetadataSchema } from 'src/app/core/metadata/metadata-schema.model'; +import { Collection } from 'src/app/core/shared/collection.model'; +import { Community } from 'src/app/core/shared/community.model'; +import { Item } from 'src/app/core/shared/item.model'; +import { getFirstSucceededRemoteListPayload } from 'src/app/core/shared/operators'; +import { isEmpty } from 'src/app/shared/empty.util'; +import { environment } from 'src/environments/environment'; +import { FiltersComponent } from '../filters-section/filters-section.component'; +import { FilteredItems } from './filtered-items-model'; +import { OptionVO } from './option-vo.model'; +import { PresetQuery } from './preset-query.model'; +import { QueryPredicate } from './query-predicate.model'; + +@Component({ + selector: 'ds-report-filtered-items', + templateUrl: './filtered-items.component.html', + styleUrls: ['./filtered-items.component.scss'] +}) +export class FilteredItemsComponent { + + collections: OptionVO[]; + presetQueries: PresetQuery[]; + metadataFields: OptionVO[]; + metadataFieldsWithAny: OptionVO[]; + predicates: OptionVO[]; + pageLimits: OptionVO[]; + + queryForm: FormGroup; + currentPage: number = 0; + results: FilteredItems = new FilteredItems(); + results$: Observable; + @ViewChild('acc') accordionComponent: NgbAccordion; + + constructor( + private communityService: CommunityDataService, + private collectionService: CollectionDataService, + private metadataSchemaService: MetadataSchemaDataService, + private metadataFieldService: MetadataFieldDataService, + private translateService: TranslateService, + private formBuilder: FormBuilder, + private restService: DspaceRestService) {} + + ngOnInit() { + this.loadCollections(); + this.loadPresetQueries(); + this.loadMetadataFields(); + this.loadPredicates(); + this.loadPageLimits(); + + let formQueryPredicates: FormGroup[] = [ + new QueryPredicate().toFormGroup(this.formBuilder) + ]; + + this.queryForm = this.formBuilder.group({ + collections: this.formBuilder.control([''], []), + presetQuery: this.formBuilder.control('new', []), + queryPredicates: this.formBuilder.array(formQueryPredicates), + pageLimit: this.formBuilder.control('100', []), + filters: FiltersComponent.formGroup(this.formBuilder), + additionalFields: this.formBuilder.control([], []) + }); + } + + loadCollections(): void { + this.collections = []; + let wholeRepo$ = this.translateService.stream('admin.reports.items.wholeRepo'); + this.collections.push(OptionVO.collectionLoc('', wholeRepo$)); + + this.communityService.findAll({ elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (communitiesRest: Community[]) => { + communitiesRest.forEach(community => { + let commVO = OptionVO.collection(community.uuid, community.name, true); + this.collections.push(commVO); + + this.collectionService.findByParent(community.uuid, { elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (collectionsRest: Collection[]) => { + collectionsRest.filter(collection => collection.firstMetadataValue('dspace.entity.type') === 'Publication') + .forEach(collection => { + let collVO = OptionVO.collection(collection.uuid, '–' + collection.name); + this.collections.push(collVO); + }); + } + ); + }); + } + ); + } + + loadPresetQueries(): void { + this.presetQueries = [ + PresetQuery.of('new', 'admin.reports.items.preset.new', []), + PresetQuery.of('q1', 'admin.reports.items.preset.hasNoTitle', [ + QueryPredicate.of('dc.title', QueryPredicate.DOES_NOT_EXIST) + ]), + PresetQuery.of('q2', 'admin.reports.items.preset.hasNoIdentifierUri', [ + QueryPredicate.of('dc.identifier.uri', QueryPredicate.DOES_NOT_EXIST) + ]), + PresetQuery.of('q3', 'admin.reports.items.preset.hasCompoundSubject', [ + QueryPredicate.of('dc.subject.*', QueryPredicate.LIKE, '%;%') + ]), + PresetQuery.of('q4', 'admin.reports.items.preset.hasCompoundAuthor', [ + QueryPredicate.of('dc.contributor.author', QueryPredicate.LIKE, '% and %') + ]), + PresetQuery.of('q5', 'admin.reports.items.preset.hasCompoundCreator', [ + QueryPredicate.of('dc.creator', QueryPredicate.LIKE, '% and %') + ]), + PresetQuery.of('q6', 'admin.reports.items.preset.hasUrlInDescription', [ + QueryPredicate.of('dc.description', QueryPredicate.MATCHES, '^.*(http://|https://|mailto:).*$') + ]), + PresetQuery.of('q7', 'admin.reports.items.preset.hasFullTextInProvenance', [ + QueryPredicate.of('dc.description.provenance', QueryPredicate.MATCHES, '^.*No\. of bitstreams(.|\r|\n|\r\n)*\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$') + ]), + PresetQuery.of('q8', 'admin.reports.items.preset.hasNonFullTextInProvenance', [ + QueryPredicate.of('dc.description.provenance', QueryPredicate.DOES_NOT_MATCH, '^.*No\. of bitstreams(.|\r|\n|\r\n)*\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$') + ]), + PresetQuery.of('q9', 'admin.reports.items.preset.hasEmptyMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^\s*$') + ]), + PresetQuery.of('q10', 'admin.reports.items.preset.hasUnbreakingDataInDescription', [ + QueryPredicate.of('dc.description.*', QueryPredicate.MATCHES, '^.*[^\s]{50,}.*$') + ]), + PresetQuery.of('q12', 'admin.reports.items.preset.hasXmlEntityInMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^.*&#.*$') + ]), + PresetQuery.of('q13', 'admin.reports.items.preset.hasNonAsciiCharInMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^.*[^[:ascii:]].*$') + ]) + ]; + } + + loadMetadataFields(): void { + this.metadataFields = []; + this.metadataFieldsWithAny = []; + let anyField$ = this.translateService.stream('admin.reports.items.anyField'); + this.metadataFieldsWithAny.push(OptionVO.itemLoc('*', anyField$)); + this.metadataSchemaService.findAll({ elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (schemasRest: MetadataSchema[]) => { + schemasRest.forEach(schema => { + this.metadataFieldService.findBySchema(schema, { elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (fieldsRest: MetadataField[]) => { + fieldsRest.forEach(field => { + let fieldName = schema.prefix + '.' + field.toString(); + let fieldVO = OptionVO.item(fieldName, fieldName); + this.metadataFields.push(fieldVO); + this.metadataFieldsWithAny.push(fieldVO); + if (isEmpty(field.qualifier)) { + fieldName = schema.prefix + '.' + field.element + '.*'; + fieldVO = OptionVO.item(fieldName, fieldName); + this.metadataFieldsWithAny.push(fieldVO); + } + }); + } + ); + }); + } + ); + } + + loadPredicates(): void { + this.predicates = [ + OptionVO.item(QueryPredicate.EXISTS, 'admin.reports.items.predicate.exists'), + OptionVO.item(QueryPredicate.DOES_NOT_EXIST, 'admin.reports.items.predicate.doesNotExist'), + OptionVO.item(QueryPredicate.EQUALS, 'admin.reports.items.predicate.equals'), + OptionVO.item(QueryPredicate.DOES_NOT_EQUAL, 'admin.reports.items.predicate.doesNotEqual'), + OptionVO.item(QueryPredicate.LIKE, 'admin.reports.items.predicate.like'), + OptionVO.item(QueryPredicate.NOT_LIKE, 'admin.reports.items.predicate.notLike'), + OptionVO.item(QueryPredicate.CONTAINS, 'admin.reports.items.predicate.contains'), + OptionVO.item(QueryPredicate.DOES_NOT_CONTAIN, 'admin.reports.items.predicate.doesNotContain'), + OptionVO.item(QueryPredicate.MATCHES, 'admin.reports.items.predicate.matches'), + OptionVO.item(QueryPredicate.DOES_NOT_MATCH, 'admin.reports.items.predicate.doesNotMatch') + ]; + } + + loadPageLimits(): void { + this.pageLimits = [ + OptionVO.item('10', '10'), + OptionVO.item('25', '25'), + OptionVO.item('50', '50'), + OptionVO.item('100', '100'), + OptionVO.item('250', '250'), + OptionVO.item('1000', '1000') + ]; + } + + queryPredicatesArray(): FormArray { + return (this.queryForm.get('queryPredicates') as FormArray); + } + + addQueryPredicate(newItem: FormGroup = new QueryPredicate().toFormGroup(this.formBuilder)) { + this.queryPredicatesArray().push(newItem); + } + + deleteQueryPredicateDisabled(): boolean { + return this.queryPredicatesArray().length < 2; + } + + deleteQueryPredicate(index: number, nbToDelete: number = 1) { + if (index > -1) { + this.queryPredicatesArray().removeAt(index); + } + } + + setPresetQuery() { + let queryField = this.queryForm.controls.presetQuery as FormControl; + let value = queryField.value; + let query = this.presetQueries.find(q => q.id === value); + if (query !== undefined) { + this.queryPredicatesArray().clear(); + query.predicates + .map(qp => qp.toFormGroup(this.formBuilder)) + .forEach(qp => this.addQueryPredicate(qp)); + if (query.predicates.length == 0) { + this.addQueryPredicate(new QueryPredicate().toFormGroup(this.formBuilder)); + } + } + } + + filtersFormGroup(): FormGroup { + return this.queryForm.get('filters') as FormGroup; + } + + private pageSize() { + let form = this.queryForm.value; + return form.pageLimit; + } + + canNavigatePrevious(): boolean { + return this.currentPage > 0; + } + + prevPage() { + if (this.canNavigatePrevious()) { + this.currentPage--; + this.resubmit(); + } + } + + pageCount(): number { + let total = this.results.itemCount || 0; + return Math.ceil(total / this.pageSize()); + } + + canNavigateNext(): boolean { + return this.currentPage + 1 < this.pageCount(); + } + + nextPage() { + if (this.canNavigateNext()) { + this.currentPage++; + this.resubmit(); + } + } + + submit() { + this.accordionComponent.expand('itemResults'); + this.currentPage = 0; + this.resubmit(); + } + + resubmit() { + this.results$ = this + .postFilteredItems() + .pipe( + map(response => { + let offset = this.currentPage * this.pageSize(); + this.results.deserialize(response.payload, offset); + return this.results.items; + }) + ); + } + + postFilteredItems(): Observable { + let form = this.queryForm.value; + let scheme = environment.rest.ssl ? 'https' : 'http'; + let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; + let urlRequest = `${urlRestApp}/api/contentreports/filtereditems?page=${this.currentPage}&size=${this.pageSize()}`; + return this.restService.request(RestRequestMethod.POST, urlRequest, form); + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/option-vo.model.ts b/src/app/admin/admin-reports/filtered-items/option-vo.model.ts new file mode 100644 index 00000000000..206388c2d70 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/option-vo.model.ts @@ -0,0 +1,46 @@ +import { Observable } from 'rxjs'; + +export class OptionVO { + + id: string; + name$: Observable; + disabled = false; + + static collection(id: string, name: string, disabled: boolean = false): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = OptionVO.toObservable(name); + opt.disabled = disabled; + return opt; + } + + static collectionLoc(id: string, name$: Observable, disabled: boolean = false): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = name$; + opt.disabled = disabled; + return opt; + } + + static item(id: string, name: string): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = OptionVO.toObservable(name); + return opt; + } + + static itemLoc(id: string, name$: Observable): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = name$; + return opt; + } + + private static toObservable(value: T): Observable { + return new Observable(subscriber => { + subscriber.next(value); + subscriber.complete(); + }); + + } +} diff --git a/src/app/admin/admin-reports/filtered-items/preset-query.model.ts b/src/app/admin/admin-reports/filtered-items/preset-query.model.ts new file mode 100644 index 00000000000..73522f02cf1 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/preset-query.model.ts @@ -0,0 +1,17 @@ +import { QueryPredicate } from './query-predicate.model'; + +export class PresetQuery { + + id: string; + label: string; + predicates: QueryPredicate[]; + + static of(id: string, label: string, predicates: QueryPredicate[]) { + let query = new PresetQuery(); + query.id = id; + query.label = label; + query.predicates = predicates; + return query; + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts b/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts new file mode 100644 index 00000000000..c5f323ed2c8 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts @@ -0,0 +1,36 @@ +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; + +export class QueryPredicate { + + static EXISTS = 'exists'; + static DOES_NOT_EXIST = 'doesnt_exist'; + static EQUALS = 'equals'; + static DOES_NOT_EQUAL = 'not_equals'; + static LIKE = 'like'; + static NOT_LIKE = 'not_like'; + static CONTAINS = 'contains'; + static DOES_NOT_CONTAIN = 'doesnt_contain'; + static MATCHES = 'matches'; + static DOES_NOT_MATCH = 'doesnt_match'; + + field = '*'; + operator: string; + value: string; + + static of(field: string, operator: string, value: string = '') { + let pred = new QueryPredicate(); + pred.field = field; + pred.operator = operator; + pred.value = value; + return pred; + } + + toFormGroup(formBuilder: FormBuilder): FormGroup { + return formBuilder.group({ + field: new FormControl(this.field), + operator: new FormControl(this.operator), + value: new FormControl(this.value) + }); + } + +} diff --git a/src/app/admin/admin-reports/filters-section/filter-group.model.ts b/src/app/admin/admin-reports/filters-section/filter-group.model.ts new file mode 100644 index 00000000000..975b43a9860 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filter-group.model.ts @@ -0,0 +1,19 @@ +import { Filter } from './filter.model'; + +export class FilterGroup { + + id: string; + key: string; + + constructor(id: string, public filters: Filter[]) { + this.id = id; + this.key = 'admin.reports.commons.filters.' + id; + filters.forEach(filter => { + filter.key = this.key + '.' + filter.id; + if (filter.hasTooltip) { + filter.tooltipKey = filter.key + '.tooltip'; + } + }); + } + +} diff --git a/src/app/admin/admin-reports/filters-section/filter.model.ts b/src/app/admin/admin-reports/filters-section/filter.model.ts new file mode 100644 index 00000000000..63eeb114cde --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filter.model.ts @@ -0,0 +1,8 @@ +export class Filter { + + key: string; + tooltipKey: string; + + constructor(public id: string, public hasTooltip: boolean = false) {} + +} diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.html b/src/app/admin/admin-reports/filters-section/filters-section.component.html new file mode 100644 index 00000000000..b0281e2153b --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.html @@ -0,0 +1,19 @@ +
+ +   +   + +   + +   +   + +
+
+ {{group.key | translate}} + +
+ +
+
+
diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.scss b/src/app/admin/admin-reports/filters-section/filters-section.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts b/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts new file mode 100644 index 00000000000..94f2753ec09 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts @@ -0,0 +1,101 @@ +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { FiltersComponent } from './filters-section.component'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; +import { FormBuilder } from '@angular/forms'; + +describe('FiltersComponent', () => { + let component: FiltersComponent; + let fixture: ComponentFixture; + let formBuilder: FormBuilder; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FiltersComponent], + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }) + ], + providers: [ + FormBuilder + ], + schemas: [NO_ERRORS_SCHEMA] + }); + })); + + beforeEach(waitForAsync(() => { + formBuilder = TestBed.inject(FormBuilder); + + fixture = TestBed.createComponent(FiltersComponent); + component = fixture.componentInstance; + component.filtersForm = FiltersComponent.formGroup(formBuilder); + fixture.detectChanges(); + })); + + const isOneSelected = (values: {}): boolean => { + let oneSelected = false; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; !oneSelected && i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + oneSelected = oneSelected || values[filter.id]; + } + } + return oneSelected; + }; + + const isAllSelected = (values: {}): boolean => { + let allSelected = true; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; allSelected && i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + allSelected = allSelected && values[filter.id]; + } + } + return allSelected; + }; + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should select all checkboxes', () => { + // By default, nothing is selected, so at least one item is not selected. + let values = component.filtersForm.value; + let allSelected: boolean = isAllSelected(values); + expect(allSelected).toBeFalse(); + + // Now we select everything... + component.selectAll(); + + // We must retrieve the form values again since selectAll() injects a new dictionary. + values = component.filtersForm.value; + allSelected = isAllSelected(values); + expect(allSelected).toBeTrue(); + }); + + it('should deselect all checkboxes', () => { + // Since nothing is selected by default, we select at least an item + // so that deselectAll() actually deselects something. + let values = component.filtersForm.value; + values.is_item = true; + let oneSelected: boolean = isOneSelected(values); + expect(oneSelected).toBeTrue(); + + // Now we deselect everything... + component.deselectAll(); + + // We must retrieve the form values again since deselectAll() injects a new dictionary. + values = component.filtersForm.value; + oneSelected = isOneSelected(values); + expect(oneSelected).toBeFalse(); + }); +}); diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.ts b/src/app/admin/admin-reports/filters-section/filters-section.component.ts new file mode 100644 index 00000000000..e6a7f683dd2 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.ts @@ -0,0 +1,129 @@ +import { Component, Input } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { FilterGroup } from './filter-group.model'; +import { Filter } from './filter.model'; + +@Component({ + selector: 'ds-filters', + templateUrl: './filters-section.component.html', + styleUrls: ['./filters-section.component.scss'] +}) +export class FiltersComponent { + + static FILTERS = [ + new FilterGroup('property', [ + new Filter('is_item'), + new Filter('is_withdrawn'), + new Filter('is_not_withdrawn'), + new Filter('is_discoverable'), + new Filter('is_not_discoverable') + ]), + new FilterGroup('bitstream', [ + new Filter('has_multiple_originals'), + new Filter('has_no_originals'), + new Filter('has_one_original') + ]), + new FilterGroup('bitstream_mime', [ + new Filter('has_doc_original'), + new Filter('has_image_original'), + new Filter('has_unsupp_type'), + new Filter('has_mixed_original'), + new Filter('has_pdf_original'), + new Filter('has_jpg_original'), + new Filter('has_small_pdf'), + new Filter('has_large_pdf'), + new Filter('has_doc_without_text') + ]), + new FilterGroup('mime', [ + new Filter('has_only_supp_image_type'), + new Filter('has_unsupp_image_type'), + new Filter('has_only_supp_doc_type'), + new Filter('has_unsupp_doc_type') + ]), + new FilterGroup('bundle', [ + new Filter('has_unsupported_bundle'), + new Filter('has_small_thumbnail'), + new Filter('has_original_without_thumbnail'), + new Filter('has_invalid_thumbnail_name'), + new Filter('has_non_generated_thumb'), + new Filter('no_license'), + new Filter('has_license_documentation') + ]), + new FilterGroup('permission', [ + new Filter('has_restricted_original', true), + new Filter('has_restricted_thumbnail', true), + new Filter('has_restricted_metadata', true) + ]) + ]; + + @Input() filtersForm: FormGroup; + + static formGroup(formBuilder: FormBuilder): FormGroup { + let fields = {}; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + fields[filter.id] = new FormControl(false); + } + } + return formBuilder.group(fields); + } + + static getFilter(filterId: string): Filter { + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + if (filter.id === filterId) { + return filter; + } + } + } + return undefined; + } + + static getGroup(filterId: string): FilterGroup { + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + if (filter.id === filterId) { + return group; + } + } + } + return undefined; + } + + allFilters(): FilterGroup[] { + return FiltersComponent.FILTERS; + } + + private setAllFilters(value: boolean) { + // I don't know why, but patchValue() with individual controls doesn't work. + // I therefore use setValue() with the whole set, which mercifully works... + let fields = {}; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + fields[filter.id] = value; + } + } + this.filtersForm.setValue(fields); + } + + selectAll(): void { + this.setAllFilters(true); + } + + deselectAll(): void { + this.setAllFilters(false); + } + +} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 3168ea93c92..afad47044de 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -6,3 +6,9 @@ export const REGISTRIES_MODULE_PATH = 'registries'; export function getRegistriesModuleRoute() { return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString(); } + +export const REPORTS_MODULE_PATH = 'reports'; + +export function getReportsModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), REPORTS_MODULE_PATH).toString(); +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index 1ea20bc9a0f..190d47a0e47 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,7 +6,7 @@ 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, REPORTS_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ @@ -17,6 +17,11 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import loadChildren: () => import('./admin-registries/admin-registries.module') .then((m) => m.AdminRegistriesModule), }, + { + path: REPORTS_MODULE_PATH, + loadChildren: () => import('./admin-reports/admin-reports.module') + .then((m) => m.AdminReportsModule), + }, { path: 'search', resolve: { breadcrumb: I18nBreadcrumbResolver }, diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 0ddbefd2532..ca3eac36300 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -10,6 +10,7 @@ import { AdminSearchModule } from './admin-search-page/admin-search.module'; import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component'; import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; +import { AdminReportsModule } from './admin-reports/admin-reports.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -22,6 +23,7 @@ const ENTRY_COMPONENTS = [ imports: [ AdminRoutingModule, AdminRegistriesModule, + AdminReportsModule, AccessControlModule, AdminSearchModule.withEntryComponents(), AdminWorkflowModuleModule.withEntryComponents(), diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 8630150c58f..5ebc9f77330 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -155,6 +155,7 @@ export class MenuResolver implements Resolve { this.createExportMenuSections(); this.createImportMenuSections(); this.createAccessControlMenuSections(); + this.createReportMenuSections(); return this.waitForMenu$(MenuID.ADMIN); } @@ -668,4 +669,57 @@ export class MenuResolver implements Resolve { }))); }); } + + /** + * Create menu sections dependent on whether or not the current user is a site administrator + */ + createReportMenuSections() { + observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.AdministratorOf) + ]).subscribe(([isSiteAdmin]) => { + const menuList = [ + { + id: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.reports' + } as TextMenuItemModel, + icon: 'file-alt', + index: 5 + }, + /* Collections Report */ + { + id: 'reports_collections', + parentID: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.reports.collections', + link: '/admin/reports/collections' + } as LinkMenuItemModel, + icon: 'user-check' + }, + /* Queries Report */ + { + id: 'reports_queries', + parentID: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.reports.queries', + link: '/admin/reports/queries' + } as LinkMenuItemModel, + icon: 'user-check' + }, + ]; + + menuList.forEach((menuSection) => this.menuService.addSection(MenuID.ADMIN, Object.assign(menuSection, { + shouldPersistOnRouteChange: true + }))); + }); + } } diff --git a/src/assets/i18n/ar.json5 b/src/assets/i18n/ar.json5 index 58c8c61eb5d..e0cdb41c0b9 100644 --- a/src/assets/i18n/ar.json5 +++ b/src/assets/i18n/ar.json5 @@ -877,9 +877,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3886,6 +4287,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3987,7 +4400,11 @@ // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4121,7 +4538,10 @@ "menu.section.statistics_task": "Statistics Task", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/bn.json5 b/src/assets/i18n/bn.json5 index 8020ee7a965..9f4e66c8d25 100644 --- a/src/assets/i18n/bn.json5 +++ b/src/assets/i18n/bn.json5 @@ -716,9 +716,410 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "পেছনে", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "প্রশাসনিক অনুসন্ধান", @@ -3568,7 +3969,19 @@ "menu.section.access_control_people": "ব্যাক্তি", - + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "অ্যাডমিন অনুসন্ধান", @@ -3647,7 +4060,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "অ্যাক্সেস কন্ট্রোল মেনু বিভাগ", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "অ্যাডমিন অনুসন্ধান মেনু বিভাগ", @@ -3754,7 +4171,10 @@ "menu.section.statistics_task": "পরিসংখ্যান টাস্ক", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "অ্যাক্সেস কন্ট্রোল বিভাগ টগল করুন", diff --git a/src/assets/i18n/cs.json5 b/src/assets/i18n/cs.json5 index 12b67e54e25..25163a76a45 100644 --- a/src/assets/i18n/cs.json5 +++ b/src/assets/i18n/cs.json5 @@ -857,9 +857,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3797,6 +4198,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3898,7 +4311,11 @@ // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4032,7 +4449,10 @@ "menu.section.statistics_task": "Statistics Task", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 80a6b5605a8..da1e10373e0 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -683,9 +683,410 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Zurück zu den Gruppen", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Admin-Suche", @@ -3185,6 +3586,15 @@ + // "menu.section.reports": "Reports", + "menu.section.reports": "Berichte", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Filtrierte Sammlungen", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Metadatenabfrage", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Admin-Suche", @@ -3263,7 +3673,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Menübereich Zugriffskontrolle", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Menüabschnitt (Admin-Suche)", @@ -3367,7 +3781,10 @@ "menu.section.statistics_task": "Statistikaufgaben", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Bereich Zugriffskontrolle umschalten", diff --git a/src/assets/i18n/el.json5 b/src/assets/i18n/el.json5 index e8ae4ab2e9d..952c2244069 100644 --- a/src/assets/i18n/el.json5 +++ b/src/assets/i18n/el.json5 @@ -151,6 +151,410 @@ "admin.access-control.groups.title": "Ομάδες", "admin.access-control.groups.title.addGroup": "Νέα ομάδα", "admin.access-control.groups.title.singleGroup": "Επεξεργασία ομάδας", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.curation-tasks.breadcrumbs": "Εργασίες επιμέλειας συστήματος", "admin.curation-tasks.header": "Εργασίες επιμέλειας συστήματος", "admin.curation-tasks.title": "Εργασίες επιμέλειας συστήματος", @@ -1238,6 +1642,11 @@ "menu.section.export_metadata": "Μεταδεδομένα", "menu.section.health": "Υγεία", "menu.section.icon.access_control": "Ενότητα μενού ελέγχου πρόσβασης", + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "Ενότητα μενού αναζήτησης διαχειριστή", "menu.section.icon.control_panel": "Ενότητα μενού Πίνακας Ελέγχου", "menu.section.icon.curation_tasks": "Ενότητα μενού Εργασίας Επιμέλειας", @@ -1269,6 +1678,11 @@ "menu.section.registries_metadata": "Μεταδεδομένα", "menu.section.statistics": "Στατιστικά", "menu.section.statistics_task": "Εργασία Στατιστικών", + + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.access_control": "Εναλλαγή ενότητας Ελέγχου πρόσβασης", "menu.section.toggle.control_panel": "Εναλλαγή ενότητας Πίνακας Ελέγχου", "menu.section.toggle.curation_task": "Εναλλαγή ενότητας Εργασία Επιμέλειας", diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a806588701f..6b1900708c7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -503,6 +503,207 @@ + "admin.reports.collections.title": "Collection Filter Report", + + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + "admin.reports.collections.head": "Collection Filter Report", + + "admin.reports.button.show-collections": "Show Collections", + + "admin.reports.collections.collections-report": "Collection Report", + + "admin.reports.collections.item-results": "Item Results", + + "admin.reports.collections.community": "Community", + + "admin.reports.collections.collection": "Collection", + + "admin.reports.collections.nb_items": "Nb. Items", + + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + "admin.reports.items.title": "Metadata Query Report", + + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + "admin.reports.items.head": "Metadata Query Report", + + "admin.reports.items.run": "Run Item Query", + + "admin.reports.items.section.collectionSelector": "Collection Selector", + + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + "admin.reports.items.predefinedQueries": "Predefined Queries", + + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + "admin.reports.items.limit": "Limit/", + + "admin.reports.items.wholeRepo": "Whole Repository", + + "admin.reports.items.anyField": "Any field", + + "admin.reports.items.predicate.exists": "exists", + + "admin.reports.items.predicate.doesNotExist": "does not exist", + + "admin.reports.items.predicate.equals": "equals", + + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + "admin.reports.items.predicate.like": "like", + + "admin.reports.items.predicate.notLike": "not like", + + "admin.reports.items.predicate.contains": "contains", + + "admin.reports.items.predicate.doesNotContain": "does not contain", + + "admin.reports.items.predicate.matches": "matches", + + "admin.reports.items.predicate.doesNotMatch": "does not match", + + "admin.reports.items.preset.new": "New Query", + + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + "admin.reports.items.number": "No.", + + "admin.reports.items.id": "UUID", + + "admin.reports.items.collection": "Collection", + + "admin.reports.items.handle": "URI", + + "admin.reports.items.title": "Title", + + + "admin.reports.commons.filters": "Filters", + + "admin.reports.commons.additional-data": "Additional data to return", + + "admin.reports.commons.previous-page": "Prev Page", + + "admin.reports.commons.next-page": "Next Page", + + "admin.reports.commons.page": "Page", + + "admin.reports.commons.of": "of", + + "admin.reports.commons.export": "Export for Metadata Update", + + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + "admin.reports.commons.filters.select_all": "Select all filters", + + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + "admin.reports.commons.filters.property": "Item Property Filters", + + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + "admin.reports.commons.filters.permission": "Permission Filters", + + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.search.breadcrumbs": "Administrative Search", "admin.search.collection.edit": "Edit", @@ -2617,6 +2818,12 @@ + "menu.section.reports": "Reports", + + "menu.section.reports.collections": "Filtered Collections", + + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "Admin Search", @@ -2674,6 +2881,8 @@ "menu.section.icon.access_control": "Access Control menu section", + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.control_panel": "Control Panel menu section", @@ -2756,6 +2965,8 @@ "menu.section.toggle.access_control": "Toggle Access Control section", + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.curation_task": "Toggle Curation Task section", diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index 02169514c45..f13e637c716 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -718,6 +718,412 @@ // "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Current group", "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Grupo actual", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + // "admin.search.breadcrumbs": "Administrative Search", + "admin.search.breadcrumbs": "Búsqueda administrativa", + // "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Subgrupo agregado exitosamente: \"{{ name }} \"", @@ -3247,6 +3653,18 @@ // "item.page.filesection.size": "Size:", "item.page.filesection.size": "Tamaño:", + // "menu.section.reports": "Reports", + "menu.section.reports": "Informes", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Colecciones filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consulta de metadatos", + + // "menu.section.admin_search": "Admin Search", + "menu.section.admin_search": "Búsqueda de administrador", + // "item.page.journal.search.title": "Articles in this journal", "item.page.journal.search.title": "Ítems de esta revista", @@ -3872,6 +4290,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Sección del menú de control de acceso", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Sección del menú de búsqueda de administrador", @@ -3984,6 +4406,9 @@ "menu.section.statistics_task": "Tarea de estadísticas", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar sección de control de acceso", diff --git a/src/assets/i18n/fi.json5 b/src/assets/i18n/fi.json5 index 1ef67e2a484..398433ea445 100644 --- a/src/assets/i18n/fi.json5 +++ b/src/assets/i18n/fi.json5 @@ -665,6 +665,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Ylläpitäjän haku", @@ -2957,6 +3360,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Ylläpitäjän haku", @@ -3036,6 +3451,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Pääsyoikeudet", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Ylläpitäjän haku", @@ -3139,6 +3558,9 @@ "menu.section.statistics_task": "Tilastointitehtävä", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Vaihda Pääsyoikeudet-osion tilaa", diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index c8e992182ae..13644bdc4a2 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -718,6 +718,300 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Retour", + //"admin.reports.collections.title": "Collection Filter Report", + "admin.reports.collections.title": "Rapport de collections filtrées", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + "admin.reports.collections.breadcrumbs": "Collections filtrées", + + //"admin.reports.collections.head": "Collection Filter Report", + "admin.reports.collections.head": "Rapport de collections filtrées", + + //"admin.reports.button.show-collections": "Show Collections", + "admin.reports.button.show-collections": "Afficher les collections", + + //"admin.reports.collections.collections-report": "Collection Report", + "admin.reports.collections.collections-report": "Rapport des collections", + + //"admin.reports.collections.item-results": "Item Results", + "admin.reports.collections.item-results": "Éléments résultants", + + //"admin.reports.collections.community": "Community", + "admin.reports.collections.community": "Communauté", + + //"admin.reports.collections.collection": "Collection", + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + "admin.reports.collections.nb_items": "Nb. d'éléments", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + "admin.reports.collections.match_all_selected_filters": "Correspondant à tous les filtres sélectionnés", + + + //"admin.reports.items.title": "Metadata Query Report", + "admin.reports.items.title": "Rapport de requête de métadonnées", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + "admin.reports.items.breadcrumbs": "Requête de métadonnées", + + //"admin.reports.items.head": "Metadata Query Report", + "admin.reports.items.head": "Rapport de requête de métadonnées", + + //"admin.reports.items.run": "Run Item Query", + "admin.reports.items.run": "Exécuter la requête", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + "admin.reports.items.section.collectionSelector": "Sélecteur de collections", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + "admin.reports.items.section.metadataFieldQueries": "Requêtes sur les champs de métadonnées", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + "admin.reports.items.predefinedQueries": "Requêtes prédéfinies", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + "admin.reports.items.section.limitPaginateQueries": "Limiter/paginer les résultats", + + //"admin.reports.items.limit": "Limit/", + "admin.reports.items.limit": "Limite", + + //"admin.reports.items.wholeRepo": "Whole Repository", + "admin.reports.items.wholeRepo": "Tout le dépôt", + + //"admin.reports.items.anyField": "Any field", + "admin.reports.items.anyField": "Tous les champs", + + //"admin.reports.items.predicate.exists": "exists", + "admin.reports.items.predicate.exists": "existe", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + "admin.reports.items.predicate.doesNotExist": "n'existe pas", + + //"admin.reports.items.predicate.equals": "equals", + "admin.reports.items.predicate.equals": "est égal à", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + "admin.reports.items.predicate.doesNotEqual": "n'est pas égal à", + + //"admin.reports.items.predicate.like": "like", + "admin.reports.items.predicate.like": "est de forme (like)", + + //"admin.reports.items.predicate.notLike": "not like", + "admin.reports.items.predicate.notLike": "n'est pas de forme (not like)", + + //"admin.reports.items.predicate.contains": "contains", + "admin.reports.items.predicate.contains": "contient", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + "admin.reports.items.predicate.doesNotContain": "ne contient pas", + + //"admin.reports.items.predicate.matches": "matches", + "admin.reports.items.predicate.matches": "correspond à (matches)", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + "admin.reports.items.predicate.doesNotMatch": "ne correspond pas à (does not match)", + + //"admin.reports.items.preset.new": "New Query", + "admin.reports.items.preset.new": "Nouvelle requête", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + "admin.reports.items.preset.hasNoTitle": "Sans titre", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + "admin.reports.items.preset.hasNoIdentifierUri": "Sans dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + "admin.reports.items.preset.hasCompoundSubject": "A un sujet composite", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + "admin.reports.items.preset.hasCompoundAuthor": "A un dc.contributor.author composite", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + "admin.reports.items.preset.hasCompoundCreator": "A un dc.creator composite", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + "admin.reports.items.preset.hasUrlInDescription": "A un URL dans dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + "admin.reports.items.preset.hasFullTextInProvenance": "A des documents texte dans dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + "admin.reports.items.preset.hasNonFullTextInProvenance": "N'a pas de document texte dans dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + "admin.reports.items.preset.hasEmptyMetadata": "A des métadonnées vides", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + "admin.reports.items.preset.hasUnbreakingDataInDescription": "A du contenu insécable dans la description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + "admin.reports.items.preset.hasXmlEntityInMetadata": "A des entités XML dans les métadonnées", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ASCII character in metadata", + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "A des caractères non ASCII dans les métadonnées", + + //"admin.reports.items.number": "No.", + "admin.reports.items.number": "Nº", + + //"admin.reports.items.id": "UUID", + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + "admin.reports.items.title": "Titre", + + + //"admin.reports.commons.filters": "Filters", + "admin.reports.commons.filters": "Filtres", + + //"admin.reports.commons.additional-data": "Additional data to return", + "admin.reports.commons.additional-data": "Données additionnelles", + + //"admin.reports.commons.previous-page": "Prev Page", + "admin.reports.commons.previous-page": "Page précédente", + + //"admin.reports.commons.next-page": "Next Page", + "admin.reports.commons.next-page": "Page suivante", + + //"admin.reports.commons.page": "Page", + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + "admin.reports.commons.of": "de", + + //"admin.reports.commons.export": "Export for Metadata Update", + "admin.reports.commons.export": "Exporter les métadonnées", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + "admin.reports.commons.filters.deselect_all": "Désélectionner tous les filtres", + + //"admin.reports.commons.filters.select_all": "Select all filters", + "admin.reports.commons.filters.select_all": "Sélectionner tous les filtres", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + "admin.reports.commons.filters.matches_all": "Tous les filtres spécifiés", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + "admin.reports.commons.filters.property": "Filtres de propriétés d'éléments", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + "admin.reports.commons.filters.property.is_item": "Est un élément - toujours vrai", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + "admin.reports.commons.filters.property.is_withdrawn": "Éléments retirés", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + "admin.reports.commons.filters.property.is_not_withdrawn": "Éléments disponibles - Non retirés", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + "admin.reports.commons.filters.property.is_discoverable": "Éléments découvrables - Non privés", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + "admin.reports.commons.filters.property.is_not_discoverable": "Éléments non découvrables - Privés", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + "admin.reports.commons.filters.bitstream": "Filtres Bitstream de base", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + "admin.reports.commons.filters.bitstream.has_multiple_originals": "L'élément a plusieurs Bitstreams originaux", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + "admin.reports.commons.filters.bitstream.has_no_originals": "L'élément n'a pas de Bitstreams originaux", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + "admin.reports.commons.filters.bitstream.has_one_original": "L'élément a un seul Bitstream original", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + "admin.reports.commons.filters.bitstream_mime": "Filtres Bitstream par type MIME", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "L'élément a un Bitstream original de type document (PDF, Office, Text, HTML, XML, etc.)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_image_original": "L'élément a un Bitstream original de type image", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "L'élément a d'autres types de Bitstream (ni document ni image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "L'élément a des Bitstreams originaux de types multiples (document, image, autres)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "L'élément a un Bitstream original PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "L'élément a un Bitstream original JPG", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "L'élément a un PDF anormalement petit", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "L'élément a un PDF anormalement grand", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "L'élément a un Bitstream sans élément TEXT", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + "admin.reports.commons.filters.mime": "Filtres de types MIME pris en charge", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + "admin.reports.commons.filters.mime.has_only_supp_image_type": "L'élément a des Bitstreams image pris en charge", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + "admin.reports.commons.filters.mime.has_unsupp_image_type": "L'élément a des Bitstreams image non pris en charge", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Les Bitstreams document de l'élément sont pris en charge", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "L'élément a des Bitstreams document non pris en charge", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + "admin.reports.commons.filters.bundle": "Filtres de Bitstreams de type Bundle", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "L'élément a un Bitstream dans un Bundle non pris en charge", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + "admin.reports.commons.filters.bundle.has_small_thumbnail": "L'élément a une vignette anormalement petite", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "L'élément a un Bitstream original sans vignette", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "L'élément a une vignette ayant un nom invalide (une vignette par original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "L'élément a une vignette non générée", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + "admin.reports.commons.filters.bundle.no_license": "L'élément n'a pas de licence", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + "admin.reports.commons.filters.bundle.has_license_documentation": "L'élément a de la documentation dans le Bundle de licence", + + //"admin.reports.commons.filters.permission": "Permission Filters", + "admin.reports.commons.filters.permission": "Filtres de permissions", + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + "admin.reports.commons.filters.permission.has_restricted_original": "L'élément a un Bitstream original à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "L'élément a au moins un Bitstream original non accessible aux utilisateurs anonymes", + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "L'élément a une vignette à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "L'élément a au moins une vignette non accessible aux utilisateurs anonymes", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + "admin.reports.commons.filters.permission.has_restricted_metadata": "L'élément a des métadonnées à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "L'élément a des métadonnées non accessibles aux utilisateurs anonymes", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Recherche Administrateur", @@ -3448,6 +3742,15 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Utilisateurs", + //"menu.section.reports": "Reports", + "menu.section.reports": "Rapports", + + //"menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Collections filtrées", + + //"menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Requête de métadonnées", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Recherche Administrateur", @@ -3517,6 +3820,9 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Section du menu relative au contrôle d'accès", + //"menu.section.icon.reports": "Reports menu section", + "menu.section.icon.reports": "Section du menu d'accès aux rapports", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Section du menu relative à la recherche Administrateur", @@ -3616,6 +3922,9 @@ // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Ouvrir/Fermer section Contrôle d'accès", + //"menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.reports": "Ouvrir/Fermer section Rapports", + // "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.control_panel": "Ouvrir/Fermer section Panneau de configuration", diff --git a/src/assets/i18n/gd.json5 b/src/assets/i18n/gd.json5 index e42bb239f25..17cfae0ec4a 100644 --- a/src/assets/i18n/gd.json5 +++ b/src/assets/i18n/gd.json5 @@ -710,6 +710,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Rannsachadh Rianachd", @@ -3553,6 +3956,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Rannsachadh Rianachd", @@ -3632,6 +4047,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": " Earrann clàr-iùil Riaghladh Cothruim", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Earrann clàr-iùil rannsachadh rianachd", @@ -3738,6 +4157,9 @@ "menu.section.statistics_task": "Obair Staitistigs", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Suids earrann Riaghladh Cothruim", diff --git a/src/assets/i18n/hi.json5 b/src/assets/i18n/hi.json5 index 4a59dc1b1b1..34b4a014a48 100644 --- a/src/assets/i18n/hi.json5 +++ b/src/assets/i18n/hi.json5 @@ -309,6 +309,411 @@ "admin.access-control.groups.title.singleGroup": "समूह संपादित करें", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + "admin.curation-tasks.breadcrumbs": "प्रणाली क्यूरेशन कार्य", "admin.curation-tasks.header": "प्रणाली क्यूरेशन कार्य", @@ -2475,6 +2880,18 @@ "menu.section.access_control_people": "लोग", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "व्यवस्थापक खोज", "menu.section.browse_community": "यह समुदाय", @@ -2523,6 +2940,10 @@ "menu.section.icon.access_control": "अभिगम नियंत्रण मेन्यू अनुभाग", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "व्यवस्थापक खोज मेनू अनुभाग", "menu.section.icon.control_panel": "नियंत्रण कक्ष मेन्यू अनुभाग", @@ -2585,6 +3006,10 @@ "menu.section.statistics_task": "सांख्यिकी कार्य", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.access_control": "अभिगम नियंत्रण अनुभाग टॉगल करें", "menu.section.toggle.control_panel": "नियंत्रण कक्ष अनुभाग टॉगल करें", diff --git a/src/assets/i18n/hu.json5 b/src/assets/i18n/hu.json5 index 8231f796520..98df544128e 100644 --- a/src/assets/i18n/hu.json5 +++ b/src/assets/i18n/hu.json5 @@ -666,9 +666,410 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Vissza a csoportokhoz", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Adminisztratív keresés", @@ -2968,6 +3369,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Admin keresés", @@ -3046,7 +3459,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Hozzáférés kontroll menü felület", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Admin keresés menü felület", @@ -3150,7 +3567,10 @@ "menu.section.statistics_task": "Statisztikai feladatok", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Váltás a Hozzáférés kontrol felületre", diff --git a/src/assets/i18n/ja.json5 b/src/assets/i18n/ja.json5 index 58c8c61eb5d..e0cdb41c0b9 100644 --- a/src/assets/i18n/ja.json5 +++ b/src/assets/i18n/ja.json5 @@ -877,9 +877,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3886,6 +4287,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3987,7 +4400,11 @@ // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4121,7 +4538,10 @@ "menu.section.statistics_task": "Statistics Task", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/kk.json5 b/src/assets/i18n/kk.json5 index 8e46ee73cec..9c2e53f349d 100644 --- a/src/assets/i18n/kk.json5 +++ b/src/assets/i18n/kk.json5 @@ -748,6 +748,411 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Әкімшілік іздеу", @@ -3812,6 +4217,18 @@ "menu.section.access_control_people": "Адамдар", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search":"Әкімші іздеу", @@ -3892,6 +4309,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Қатынасты басқару мәзірі бөлімі", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Әкімші іздеу мәзірі бөлімі", @@ -4004,6 +4425,9 @@ "menu.section.statistics_task": "Статистика тапсырмасы", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Қатынасты басқару бөлімін ауыстырып-қосқыш", diff --git a/src/assets/i18n/lv.json5 b/src/assets/i18n/lv.json5 index 995d8175af5..b9836d65cf8 100644 --- a/src/assets/i18n/lv.json5 +++ b/src/assets/i18n/lv.json5 @@ -703,6 +703,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Administratīvā Meklēšana", @@ -3186,7 +3589,17 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Personas", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Administratora Meklēšana", @@ -3267,6 +3680,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Piekļuves kontroles izvēlnes sadaļa", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Administratoru meklēšanas izvēlnes sadaļa", @@ -3372,6 +3789,9 @@ "menu.section.statistics_task": "Statistikas Uzdevumi", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Pārslēgt Piekļuvas Kontronles sadaļu", diff --git a/src/assets/i18n/nl.json5 b/src/assets/i18n/nl.json5 index fb66f769aeb..7965cf1576f 100644 --- a/src/assets/i18n/nl.json5 +++ b/src/assets/i18n/nl.json5 @@ -797,9 +797,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3457,6 +3858,15 @@ + // "menu.section.reports": "Reports", + "menu.section.reports": "Verslagen", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Gefilterde collecties", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Metagegevensquery", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3536,7 +3946,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Menusectie toegangscontrole", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -3644,7 +4058,10 @@ "menu.section.statistics_task": "Statistiektaken", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Sectie Toegangscontrole aan/uit", diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index 58c8c61eb5d..e0cdb41c0b9 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -877,9 +877,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3886,6 +4287,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3987,7 +4400,11 @@ // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4121,7 +4538,10 @@ "menu.section.statistics_task": "Statistics Task", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/pt-BR.json5 b/src/assets/i18n/pt-BR.json5 index 77b06a6566a..819bf13aeb4 100644 --- a/src/assets/i18n/pt-BR.json5 +++ b/src/assets/i18n/pt-BR.json5 @@ -747,30 +747,412 @@ // "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "Ainda não há subgrupos no grupo.", + + // "admin.access-control.groups.form.return": "Return to groups", + "admin.access-control.groups.form.return": "Retornar aos grupos", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", - // "admin.access-control.groups.form.return": "Back", - "admin.access-control.groups.form.return": "Voltar", + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", - //"admin.batch-import.breadcrumbs": "Import Batch", - "admin.batch-import.breadcrumbs": "Importar um Lote", + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", - //"admin.batch-import.title": "Import Batch", - "admin.batch-import.title": "Importar um Lote", + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", - //"admin.batch-import.page.header": "Import Batch", - "admin.batch-import.page.header": "Importar um Lote", + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", - //"admin.batch-import.page.help": "Select the Collection to import into. Then, drop or browse to a Simple Archive Format (SAF) zip file that includes the Items to import", - "admin.batch-import.page.help": "Selecione a Coleção para o qual deseja importar. Arraste ou selecione um arquivo zip no formato Simple Archive Format (SAF) que inclua os Items para importar", + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", - //"admin.batch-import.page.dropMsg": "Drop a batch ZIP to import", - "admin.batch-import.page.dropMsg": "Arraste e solte um lote ZIP para importar", + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", - //"admin.batch-import.page.dropMsgReplace": "Drop to replace the batch ZIP to import", - "admin.batch-import.page.dropMsgReplace": "Arraste e solte um lote ZIP para substituir o lote para importar", + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", - //"admin.batch-import.page.error.addFile": "Select Zip file first!", - "admin.batch-import.page.error.addFile": "Selecione um arquivo ZIP primeiro!", + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", //"admin.batch-import.page.validateOnly.hint": "When selected, the uploaded ZIP will be validated. You will receive a report of detected changes, but no changes will be saved.", "admin.batch-import.page.validateOnly.hint": "Quando selecionado , o ZIP enviado sera validado. Você receberá um relatório das alterações detectadas, mas nenhuma alteração será salva.", @@ -3682,6 +4064,15 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Pessoas", + + // "menu.section.reports": "Reports", + "menu.section.reports": "Relatórios", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Coleções filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consultas de metadados", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Pesquisa Administrativa", @@ -3752,6 +4143,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Seção do menu Controle de Acesso", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Seção do menu de busca administrativa", @@ -3854,6 +4249,10 @@ // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "Tarefas de Estatísticas", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar Seção Controle de Acesso", diff --git a/src/assets/i18n/pt-PT.json5 b/src/assets/i18n/pt-PT.json5 index c0327c4b54e..8e1ed57cf8e 100644 --- a/src/assets/i18n/pt-PT.json5 +++ b/src/assets/i18n/pt-PT.json5 @@ -870,9 +870,410 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Retornar aos grupos", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Pesquisa administrativa", @@ -3162,6 +3563,15 @@ + // "menu.section.reports": "Reports", + "menu.section.reports": "Relatórios", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Coleções filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consultas de metadados", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Pesquisa Administrativa", @@ -3240,7 +3650,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Secção do menu Controle de Acesso", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Secção do menu de Pesquisa Administrativa", @@ -3344,7 +3758,10 @@ "menu.section.statistics_task": "Tarefas de Estatísticas", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar Secção Controle de Acesso", diff --git a/src/assets/i18n/sv.json5 b/src/assets/i18n/sv.json5 index 86a6b045ccf..80912440f4a 100644 --- a/src/assets/i18n/sv.json5 +++ b/src/assets/i18n/sv.json5 @@ -721,6 +721,410 @@ "admin.access-control.groups.form.return": "Tillbaka", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Admin sökning", @@ -3621,6 +4025,18 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "EPersoner", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", @@ -3702,6 +4118,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Åtkomstkontroll - meny", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Admin sök - meny", @@ -3808,6 +4228,9 @@ "menu.section.statistics_task": "Statistik uppgift", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Växla till åtkomstkontroll", diff --git a/src/assets/i18n/sw.json5 b/src/assets/i18n/sw.json5 index 58c8c61eb5d..e0cdb41c0b9 100644 --- a/src/assets/i18n/sw.json5 +++ b/src/assets/i18n/sw.json5 @@ -877,9 +877,410 @@ // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", @@ -3886,6 +4287,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3987,7 +4400,11 @@ // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4121,7 +4538,10 @@ "menu.section.statistics_task": "Statistics Task", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index 8eb0ce7e199..de7625aacdd 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -662,9 +662,384 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Gruplara dön", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Yönetimsel Arama", @@ -2956,7 +3331,17 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Kişiler", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Yönetici araması", @@ -3036,7 +3421,11 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Erişim Kontrolü menüsü bölümü", - + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Yönetici arama menüsü bölümü", @@ -3140,7 +3529,10 @@ "menu.section.statistics_task": "İstatistiksel Görev", - + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Erişim kontrolü bölümünü aç/kapat", From 9533713a3d2b559c830df59556368c657f9ca601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin?= Date: Thu, 12 Jan 2023 11:37:45 -0500 Subject: [PATCH 031/592] Synchronized API update with REST layer + i18n update in Greek and Ukrainian files --- .../filtered-collections.component.ts | 2 +- .../filtered-items.component.ts | 2 +- src/assets/i18n/el.json5 | 12 + src/assets/i18n/uk.json5 | 421 ++++++++++++++++++ 4 files changed, 435 insertions(+), 2 deletions(-) diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts index 4f7e7bb5db8..3d0c52d47e0 100644 --- a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts @@ -53,6 +53,6 @@ export class FilteredCollectionsComponent { let form = this.queryForm.value; let scheme = environment.rest.ssl ? 'https' : 'http'; let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; - return this.restService.request(RestRequestMethod.POST, `${urlRestApp}/api/contentreports/filteredcollections`, form); + return this.restService.request(RestRequestMethod.POST, `${urlRestApp}/api/contentreport/filteredcollections`, form); } } diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts index 21b7f2e12b4..7b41a93fdc2 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts @@ -294,7 +294,7 @@ export class FilteredItemsComponent { let form = this.queryForm.value; let scheme = environment.rest.ssl ? 'https' : 'http'; let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; - let urlRequest = `${urlRestApp}/api/contentreports/filtereditems?page=${this.currentPage}&size=${this.pageSize()}`; + let urlRequest = `${urlRestApp}/api/contentreport/filtereditems?page=${this.currentPage}&size=${this.pageSize()}`; return this.restService.request(RestRequestMethod.POST, urlRequest, form); } diff --git a/src/assets/i18n/el.json5 b/src/assets/i18n/el.json5 index fc98e92af35..53f449c986f 100644 --- a/src/assets/i18n/el.json5 +++ b/src/assets/i18n/el.json5 @@ -1618,6 +1618,18 @@ "menu.section.access_control_authorizations": "Εξουσιοδοτήσεις", "menu.section.access_control_groups": "Ομάδες", "menu.section.access_control_people": "Ανθρωποι", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "Αναζήτηση διαχειριστή", "menu.section.browse_community": "Αυτή η Κοινότητα", "menu.section.browse_community_by_author": "Από Συγγραφέα", diff --git a/src/assets/i18n/uk.json5 b/src/assets/i18n/uk.json5 index b0413d9353a..da84e37bcc9 100644 --- a/src/assets/i18n/uk.json5 +++ b/src/assets/i18n/uk.json5 @@ -699,6 +699,407 @@ + // "admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + // "admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + // "admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + // "admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + // "admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + // "admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + // "admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + // "admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + // "admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + // "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + // "admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + // "admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + // "admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + // "admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + // "admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + // "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + // "admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + // "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + // "admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + // "admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + // "admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + // "admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + // "admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + // "admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + // "admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + // "admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + // "admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + // "admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + // "admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + // "admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + // "admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + // "admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + // "admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + // "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + // "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + // "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + // "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + // "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + // "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + // "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + // "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + // "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + // "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + // "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + // "admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + // "admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + // "admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + // "admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + // "admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + // "admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + // "admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + // "admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + // "admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + // "admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + // "admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + // "admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + // "admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + // "admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + // "admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + // "admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + // "admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + // "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + // "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + // "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + // "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + // "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + // "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + // "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + // "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + // "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + // "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + // "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + // "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + // "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + // "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + // "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + // "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + // "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + // "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + // "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + // "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + // "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + // "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + // "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + // "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + // "admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + // "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + // "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + // "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Пошук адміністратора", @@ -3078,6 +3479,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Пошук адміністратора", @@ -3157,6 +3570,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Меню контролю доступу", + // "menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Меню пошуку адміна", @@ -3266,6 +3683,10 @@ // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Переключити розділ контролю доступу", + // "menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.control_panel": "Переключити панель контролю доступу", From 9677de735ca85b7886f93d934364638cd9ce038c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin?= Date: Thu, 12 Jan 2023 13:56:47 -0500 Subject: [PATCH 032/592] Fixed code style errors --- .../admin-reports/filtered-items/filtered-items-model.ts | 2 +- .../filtered-items/filtered-items.component.spec.ts | 5 ++--- .../admin-reports/filtered-items/filtered-items.component.ts | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts index 5811efe53bd..2c384fe39cf 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts +++ b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts @@ -1,4 +1,4 @@ -import { Item } from "src/app/core/shared/item.model"; +import { Item } from 'src/app/core/shared/item.model'; export class FilteredItems { diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts index 70e32d402fc..1626b66d341 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts @@ -1,6 +1,6 @@ import { waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; import { FormBuilder } from '@angular/forms'; import { FilteredItemsComponent } from './filtered-items.component'; @@ -11,7 +11,7 @@ import { of as observableOf } from 'rxjs'; import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; import { CommunityDataService } from 'src/app/core/data/community-data.service'; import { ObjectCacheService } from 'src/app/core/cache/object-cache.service'; -import { ActionsSubject, ReducerManager, ReducerManagerDispatcher, StateObservable, Store, StoreModule } from '@ngrx/store'; +import { StoreModule } from '@ngrx/store'; import { UUIDService } from 'src/app/core/shared/uuid.service'; import { RemoteDataBuildService } from 'src/app/core/cache/builders/remote-data-build.service'; import { HALEndpointService } from 'src/app/core/shared/hal-endpoint.service'; @@ -21,7 +21,6 @@ import { BitstreamFormatDataService } from 'src/app/core/data/bitstream-format-d import { CollectionDataService } from 'src/app/core/data/collection-data.service'; import { MetadataSchemaDataService } from 'src/app/core/data/metadata-schema-data.service'; import { MetadataFieldDataService } from 'src/app/core/data/metadata-field-data.service'; -import { StoreMock } from 'src/app/shared/testing/store.mock'; describe('FiltersComponent', () => { let component: FilteredItemsComponent; diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts index 7b41a93fdc2..0aaa56b1a06 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts @@ -39,7 +39,7 @@ export class FilteredItemsComponent { pageLimits: OptionVO[]; queryForm: FormGroup; - currentPage: number = 0; + currentPage = 0; results: FilteredItems = new FilteredItems(); results$: Observable; @ViewChild('acc') accordionComponent: NgbAccordion; @@ -230,7 +230,7 @@ export class FilteredItemsComponent { query.predicates .map(qp => qp.toFormGroup(this.formBuilder)) .forEach(qp => this.addQueryPredicate(qp)); - if (query.predicates.length == 0) { + if (query.predicates.length === 0) { this.addQueryPredicate(new QueryPredicate().toFormGroup(this.formBuilder)); } } From 2c0e0ab991efbfb9c7236c23ac03730e82a67ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin?= Date: Fri, 24 Mar 2023 11:58:45 -0400 Subject: [PATCH 033/592] Fixed conflicts and added strings for Content Reports --- src/assets/i18n/pl.json5 | 427 +++++++++++++++++++++++++++++++++++++++ src/assets/i18n/tr.json5 | 26 +++ 2 files changed, 453 insertions(+) diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index 6bc9974a865..ce1f6dc596f 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -7398,6 +7398,410 @@ "admin.access-control.groups.form.subgroups-list.no-items":"Nie znaleziono grup z tą nazwą lub UUID", "admin.access-control.groups.form.subgroups-list.no-subgroups-yet":"Brak podgrup w grupie.", "admin.access-control.groups.form.return":"Powrót", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.search.breadcrumbs":"Wyszukiwanie administracyjne", "admin.search.collection.edit":"Edytuj", "admin.search.community.edit":"Edytuj", @@ -8282,6 +8686,19 @@ "menu.section.access_control_authorizations":"Dostępy", "menu.section.access_control_groups":"Grupy", "menu.section.access_control_people":"Użytkownicy", + + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search":"Wyszukiwanie administracyjne", "menu.section.browse_community":"Ten zbiór", "menu.section.browse_community_by_author":"Wg autorów", @@ -8305,6 +8722,11 @@ "menu.section.export_item":"Pozycja", "menu.section.export_metadata":"Metadane", "menu.section.icon.access_control":"Sekcja menu Uprawnienia", + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search":"Sekcja menu Wyszukiwanie administracyjne", "menu.section.icon.control_panel":"Sekcja menu Panel sterowania", "menu.section.icon.curation_tasks":"Sekcja menu Zadanie administracyjne", @@ -8336,6 +8758,11 @@ "menu.section.registries_metadata":"Metadane", "menu.section.statistics":"Statystyki", "menu.section.statistics_task":"Zadanie statystyczne", + + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.access_control":"Przełącz sekcję Uprawnienia", "menu.section.toggle.control_panel":"Przełącz sekcję Panel sterowania", "menu.section.toggle.curation_task":"Przełącz sekcję Zadanie kuratora", diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index 331a291e1e2..4ebe8d60f2e 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -1020,6 +1020,32 @@ // TODO New key - Add a translation "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", From 83a41652001bd17b30c68874815e16f5e73129bc Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Wed, 17 May 2023 17:42:31 +0200 Subject: [PATCH 034/592] CST-9779 Provided changes to Title, repository name, added introduction text with links, as well added the small icon for coar-notify inside the navbar. --- src/assets/i18n/en.json5 | 2 +- src/assets/images/notify-coar-icon.png | Bin 0 -> 31117 bytes .../home-news/home-news.component.html | 45 ++++++++++-------- .../dspace/app/navbar/navbar.component.html | 3 ++ 4 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 src/assets/images/notify-coar-icon.png diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 1af7c36e196..3a5ff742df0 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3599,7 +3599,7 @@ "repository.image.logo": "Repository logo", - "repository.title.prefix": "DSpace Angular :: ", + "repository.title.prefix": "Demo of COAR Notify in DSpace 7 :: ", "repository.title.prefixDSpace": "DSpace Angular ::", diff --git a/src/assets/images/notify-coar-icon.png b/src/assets/images/notify-coar-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba021dfd27dcd323bade2c944c87c7d728c34d8 GIT binary patch literal 31117 zcmdqJ^;ecr(>6?8A|c%%EnR{%lG2TImvl;ZcY}0$At?G$<$IU$4KXklI9X;znUoH)h6rp%l=ub%RpYF!oXy5Z< zmSUIT-4%_j#f={=Ew0a)J)WL>Exmu@?)bt?Qu5(h&83mAh%wR9HCdDvjTqCu(Z2~d zzAK9BouBAm!%P?sj#5T^PR|%&{@78?Qf0mMFqnHOD-fpyT^3I!g&pY^&ss+qHGqq9 z&*Vf?ies9YV(<4=d8arim8gL#|2bP462aoHPAY7D(ZSzKgrWBFp0D`P8+bPHI_Udz zW*4>uEsO>#94nJ1bE@Oax0EF97iwnUCz3sP@VANn*sf^SrqYL+JnA+wzBxMkOY*g^ zBcdjrTN(!Bi0#nwLeLgZEmCVMY7x6Bd7ijQ=sEN?isb3Nv#y=ZM&ZBjnC1U^gdo@+ z`YcYRr1KU>9Nzg!wrVeAY&PCC-F(jd&9#8?tmX{;g-7O z|C@lVr%gA-%wE^hsvj;d5IN;5~bcP8%+MIqpy9KjfW7_6Q)o&SF+X&wUs! z-C6!{UZ=GmF^+{@7u!8e)^O}AH~;*q#fhC0M;<|G)U0L~ge{Ah-<`RTQJ?dEV+@Bi z83UVDr;nelhv81yTGKe5F=}xnOrZKl*gcMiV>uqN+0xQ!WzA=h5{O7{flFaQ62cN( zPHw+x{LCk%!-9`RN%M$qfTKq4bl(6-5%L77#eqNFV1# zE2DiZKJ+XZNnpF*YPM2Xl;GCIT4x_*@$k-VXCXdkEe>o$BlipAY30e=^&aVwcB!T3 z=&h3uF3hFwF_LnNdcmL&H^uNsx6Tk}6{X05g zR{deJ^uwg1tJ$w>)+vAZXCP)l)wy;KJz29}KGVB?5{@ z*`F5f8;_dc$evTTKPjA;+Di^vgaff z^`~PND+l68CY~R4?lb2W&ZF*(4GY)a50)}{21x!4|G*segUX7R?E1#*q;$w*km(uG zF0kC^elBA|Fd%4xRc?FVr*w$vc%S)>0r6ju1Tllk6$OvImWmzp*^&MmmcnfyU%)Q8 zpcqs*^!J-b7t@F`X#f40KQbH>MqD`eo3$oHL0mLBnrC!b9M^f~ch*875@dp?r$`pn ze`^Jzeue~uU%(cUQtInrzHMO0N|SpA4oYOuFRb)1A&+lgRJU^lVEuO}kEHFK`~WJq z4phG*X(7imh#MsTFD>Np!P$*`%LF6vQ#_Vr{OVsTZ;liRc;@JInNZp(x9URZvWqrs zV4aT|B>At^VBn@O-RGDt!?oo^S~uYBGOS#ZgW&%AWaLUTu+tNwKbxt|vfH0D->2;K z{zZPqiFOgIa`3>@(sj*jsApS8z1A+c!T%r2(W*w{a`IGq!rJH*;(uX$hPFznj_cAp zsMOV1)nl~i+69W5kwu@C^b1TNUSLWb`aR$jtP@`bai5bD!~O9p_ed}hVT;lqnv#WC zF(AHp#xwHd;8=DMz9N4e>VN5L>-#=+XXIH?tq`luD1cq_HbzZf_E=@SL`MEEjM1g~ zM>U@SVs^Mv*gWc2NPcQZ@R;u^ylvxO@jvE6X68v8-ndkFp&EThX`}_zVx;8UC>YxpribcDU@V8FJ^Ll$1)8v$;JRz zYOo6poqw~tS2>Tln7viu0kzH?^1F$`>q#D6~5lQnb708T< zxwz6h_(c@0m!~(pq`tlOVsdNB-sa<~tRCf$%mU6Nsqu*Q;5EL(3&{Qo8_^4q{BUwe zah|a#;Ot@9>cesH%lBmydeU`%O$u-QEq<)2G zX&qZk*0kOF7j6DE9tABfYlSrPTXn=&p~A|bU^4#_B8tP>6RWx)58REOPYC~UC{>Bh z2(6bQ!ZIsO;|5tBMX`rFU=O^Oo$iq&U&mX=+vX~-!Pi03qp4FbBD8({micneATPH7 zw@pWMHp)^V@~ntB!T6OSLF2Yj{~r|OdBS=0l%2Id-Ro(;`n>jMf(DYtsWd7|)u8)H zIl4MH>T*b}1Q{2C1~+q`Jy5Qj)8#|4A_Aklci+|fWI`HC%FjJ0otO>=lLU(@OeF_$PN@BJm=?f9Fr9MTlgAa%R zVL&jd3!M>Ynu$~YuY^gC+#xM6)xC7J(YGe*Jc2s%HMlmCsR$cKHe!MI`h(w)?zlNE zi@d||imYn5c4jXbtrY@(3KU?3aEs~<>!g}0J?Ir|gRZpeG2i|#XLL{?_hvhO^YF{I zxC&RN7?UV$e{nQwi%aIAqqFX(&n|o8oh2qj+kn!TF)YeK5pjVguarW%m7sY%=ssZAiyxlA4_C!wj-O#hMsXNHwz_#Us?W>T)ar#FD^W0>W^a*dlK~I z7!m&Up<>@)C7JkL#rhr|G+V_Tg%ba-WUf(IID35JqND*o(&?n?x1$+$Jt#Hqq<&F6 zKlWa9Rg;4^KY@-H748Cy=cf)Ctr_`aXGyk7j`^rh8zd?5|FEC`&%Uo&`DW;H2 z;cNZZ@ZWMG-DjCrjD1CY`eIO3ra42v>RfE^3iKNBL8_SXb_5@Y)hiTh5CWHjlnqmf z)sjPh{=X4R1TMpXuci2VwFO6NEw{vmMJPO!j!TM92vP^z-*= z?J%0us4FM!9TL?*cA)>zA3L@~RJo8XUcup`8{}xO_CwaDBU*HJqMWoB)XU+o+O59O zZ?)WgD@A|>Pmk*HUtU%5&bcDTeYO6`E@O&v2oF020=bTbFEyfZ(!3tV?!|4cjoBR% z-TY6S^CyR`mdXNB6Kt4;Vd<;ATPK$8;)f@II?&d-&qX@=lRktgI=sAWll79?=P47X zrX*;-LuwY!JnxcNTW89(Xc=c$WSyw9pr@6P?=ZLD-`F|&n$<`OhtVh^eEgMiX`9mK zf@p>#!AYzBu5Gp38+utG7YZo6;j&J-sx`adu~ugVe)(Q6j$};b1}ys=WzA^S`sQ$c z57VlZy9|9V#Ni0!MCV9|Oei%@)=oFA@y$1F9iiBu8fw)CSDX;f~VR1zFIfkh*6Us4FbF;9N&4~_ogW?P%1^DvALUfAC_{v z@6Eq62?QwgIKoZ43fB=~)%1}%iKbyUXQX2fUjslZCC6~m;GgM0$E3*;ez(?p_3h#t zcogeKvsE7Vi*C}~gc+Lv-+^q0Zbj~EhVE-*_ffx(s?9s=;||jkM+beKt5=F$sb0c) zL~vmU50UW!?i+XHRi3`3FLgPS;{pN9+#)tgm9k(Bi)+W=mcWhav_q72Z!Ho`5QPoj z1gMMMQYOmn1}S1?u$Z0=u|$74#8%6SsPjmOYL1w4b6YQ!W%>{+i3`_%^M~b4he>5N z3sXpxOn?i^AfJ^9uOlg_l-2>!Tzryfrc+}?dRIixhZ+RLMJ2%iGoKl8#R9Avgri#P z{Dz?-aWnuKif~IRkD+(vUxEvDv;^ev_bbIAB>YoH?++~2qPLRz&%Cpq$YgE4XvQ(n z!K|8`@Mu*<{k+a~zF2#$Y5wZ#8=P+ja&^`OE znY#g+`Mu2+Zc$IkMCPGme<5KguP`C6=$)odR{=z987d5u{vRcx69jkyMyC7_p;=j~ zvPyX-{f^j~D3Sq6E!geM;wpbLxtV+BmvgA8EmSXPr;+yZymAzc!0rrj%{#m8N z42ODie-A_2_2IrNW$>Yi8Q{18Be+HI5mFK1ZKST9Hl?*4Dsfys#`p*FzV01`*YPaX z!&|B%!yC*J92w_uixiaoC9EWt+TTp@IK&UhALa35@%+A-Tgr_QgHxP+XnhcisW8@! zJgo+>CDA_{*nhVAJztHJP3?jk_6pz?E+l7u!e*B;M{(nu1-IqHW{U}|BxE=>jBxVH zebJsm)p&Ty&{!Xh6TO>2v2POubg?UI`&cW)MI^&PL+91*U(Vz1!P8)&^2=>=lgFHE znNtc|MB&aaFl$OgpQRYh2jg88H8z}~eCh~l4p}idGTWy5C@*lOjD}1P?4Jk{?IlHJ zCDjvRZ$xL}I5=LYhZX%T{fbx7Y3NCzIBRJCJ=nHKA*HA_clq6=^N?Uv7Fa!gw*N59 z=iMnG+y(}s<^CwK&?7f({0SF0t5ik-2om&gi^j(<6uDaoc`q44LY)D`5W-P(_f~f> z)ARK(TqNt^utw7NpOQRAN?MW(6VbRjoA?tli+X9Bqe;rN<&S@rwRSQm*{iM3sZvaO%8e6_9?7pI{ExEKrVIVGKz5(}#13 zmvn}DrT(IB;)F(2Ew}^lF=LFi1<8vt6u+4mCZ3OBFd$=$G{It_aN10=E4EXLYzg5c zCH~BHZ@z42Unj}&7h;imy6kTpvdq5J%YXc1WsD~Fc6X-S|+oK6P{I2$Y8MVGISWV;$)D$I9{!Uvo1;4Be? z+ojVdd2krEl~O8EvKCEr6dxJU=n)(H01L`bvjXra>NTobhyOLEvca8?Qs4i}4p`xe*3r%ovb%xdWo@nXR2Tgh*|_!fQRv;8`983fNa{ zt}gpdzqk(N+Uj+3adTs^9jr>e8`>6c_OJa?i>(N3Y^r@&?w!v6Jm=f)`sgb+^B}Nv zltNU2>7!}Fx7pRhOX|yWY^c~D7ph}|N;8Jx4-{HPcBkBv)D_RQeaU)*zno)O0MTmV z=+#0KDY-IOg|H^cwwZCI$g_id<`5T7*3tFeY9zy~@Zrj&;GU#ubUF9`%ivG}8 zqz)uZz_)xptveCh*Q5Jzie*K%yl0a7ka2X9tqdo*I&^^Xo7b;pHZx9&ni*|B3vqLk zjZB<%Bv3;shyjn2qx|H;wuH#rsE*<(6 zscsiphFzu|z%Uhxz!LZi$+$AiOX#O=_NrvC@OGY{>)&W83iDbm!zVu3T#mP6ODZ(z z{J)N9m#)^}PPVvEQ4Pa+`%o{QBFb7_fI^%T>)KN$C>BnA@9$ztW{WBsqeJe4^1h=^ zZJ!OuF7Oo(MO`)a%J$-QeApKr&X~o41_4;Rz5-}odx}xaAhSm|%UK4S*gxO52+>*| zY35wg1+7-B(23HzHqpHeuK1kN=Apiwr!TAOW6^O>GcZ64t<0kg*ZMhYg|jYblRv&z zlnTx}Y8yRTd=mQh)98{=NI`UbS0{Q5AE}OV`shiZ5gDt>XQwW}E2kLjGav8GM5-6$ zfho7i+Pssx&gfkl8glohS~`W>I9)Gi9w0+b42ul=7bpk~log`weq~*)RztHAC>5Dn z4R?i`ki{$*H;g6>g`(?RuN{)#4KCo$q`Sg)nolIO{j?Wp^fn?cGa6U;5K)2~1O-rv z{ZZc$n|HB;vh~sKR#Tx8H{z)rL3Ynq(cW z`X%5L;!H0jH<7mmFI`K2UugtY@}~8;DPY?5W{w!|>aGr=MzIUcH-~m>d`_+Yv!+Ja zqU|kKlO<*;txEG7h`>YShT2Lz3Y@LysV)hL{6@rt+hU}{qSNAjUe-nQG+`A-pe)rEQT@_MeGqiM!KHnrtI!s04@Z>%4-VN0TrLB#=fy}dl$9VF<&F!jVnM@b zt=;E6S!HUq*M427!AN!dc+K?gYS&*Xw;@NaDxa*@n(!sIttEBVx8K`WKgOMa-zU4{ zQ&?G@D+I?L8PTY~wUJ+@QR@1ou~_MKG++zo7LK9Kdr1nh8^&zt&Y%*17imsWDC%tC z{AHXR;jC*accH$PXbVsLA_UdB%{P^w{WuZb@ilON6~=)ZxovW+UKK!=#JZ8mn{OLG zc(u)VKIz^br5{y8I;Qbq`#l!b$9^P}-vw^(97Ox5yHsxHKK~M0rXD8zfhVX!Z4&Oo z+rRYH0Yo>V3 zK*8{KQn3lh;Qc$*;1(5}I3p4J*}cTkbxj9TNdh`1Ud2V<@axackLrFR7Ge%S3>+hy zF-YzHLyWRtcqm3dK{;Yza}49?p3s3pTI)Vbf%e6FJ#qZxhx4js)+MHD<@ZbUcrq-N@Wnd zmd>XdKlnD7p|vhvM$yGOWITbV>v+5JIMHY(q~_4vS4C??rgFY_#x@hq%8HX!mFkPm&!_$7uMHeEKM&4!)`a`Vnf2Ce}hw;0?BiU zTlNaM@{=<|}mfpkV{e<^6HYNu#!d-Cf`JXn;WrN6yxNkpO)>sH0tKCtwo^~--Yuf&pU*e3zQJD+Az-&BGmLkmd zbN==5WIEW@WV6~ApM$faEOmdKDr0oz8wN!5#k%s^!ARuClrBNFZ#AbZR8~!qzT#h5 z(EOtui>iU8)rkAM~(;@>FkcM8h%4D);yPpsUi z%iNrg-ub@nZR0IqvL0B=hs}3Qy8ZHKk!RGrFO0a;>*_)vg!$;aGLFnuWd@7CwJeSc zrI!}*>w1}S*;~8Tr|L8umvqrd$0?gzA8q1AyaNP=Wgdr_?3QkhwJ7asM!tG9>qcGE z_g->hRga)gAPw$YQ@BxK_D zj5I+;6ueaDEqR`=JaO(RxFV=<1@CuYV)z4|)y(eRE9If%iPEaKRQECT!8+vdi?x`} z3n8$R$+G6_CEG8TlQ*%7ijTG%!SGJ)P1LvIVKx4_+0!1}=hLA}Z-Qtsn!rQ|mp z$m=hih)u)8_1>Q&>5@z015AF`T=Oe0|3N?VOyX0K%ZcEQ_&lW{`;aX4A=C8#{eHFvp_v{>{Z}tehK20Xtog7Y9 zwlg`un&naDLH=XuK+bP~Cg3umL>u=jOTOcc=Z3JAGNW_-FY!k$M%^6PjZd^qqgENk zQ=yFrd`B1F*$k~pO?$E(-z=DCB+@;GjY|a@HCZnkrimI)7gqn()0>g1#<@|P;!X@f z%sbm0)ly&BHm96pC5(p6k-@d%#RKskubUNV*PMO4c6`0J;V#=R6`8Fdf?LxmCT6t1jC$Dw`q#P%V#|5s zkC+!W$K|3-FUd)u>_&vh@x8xUoY^(AWw&tZE^OQRM~-IwWk!zklv%QOiOBg$%s4N1 zb}0L$Gm5>)a58sYv3Nda?47p>^Bw!crPIA5jSYt}E}o~gJjHCq+_A^5*}YIh z=dI|Bh1;MxV++PL8arzlxSiA)CzJItv`Q_$GTJ*Y z+GE=R4SFra2JPy-i*Sh!ech<#n>)qmeA!zlmK%Zh+VR7($;*H@7K{1g)!CVLJZdY1 zDoa1kt3IZ1A>ke6a2bi}?Go~RrOb*7Br@5`0;dcc6uY}&5r1IBnIU^Qo+{2fv)#Ef zFu1U+jM|qbLA}ZQ(kRNZ0x5U|#l_12yh1q9F9jX0=zIe=C9zQz`zx=5<2$pmHh2Q{ z&X};p9*uAHJSZ$LGrqWxNVMgj+_T(UWV9jfx9^ny4vjwHA?ob-`21c=rc@9HL)}{D z&3Kt>G7@1p(g)uGyELCJ`Yv-W1_H+)1pRZx89*s=rO|UHg5R>I%!!7ur<~4sy889k z?gfI++wPTVenlt>{p5+2w>=(@h0E)%b6Z!<=TGPF&xhzWZ+=GL&uIB@F$H%28r;3! zBf68t<=i@%MmHs^NuD~(d~9W&!gsu-xPq3Sjw6I!q5`RCylXn{inIh&X>4dP%I(Cx zIloL(-Wv0x>Ao4iZ1Ee*3<}30=;HLV4=H=v?A=%QAkcU(XdA4b(ZV)-;XOU-^$|N$x5P! z&B}*<)uqX;#=gjAmi<)ND2>9)mxnK*mjV6&PcY<>VL`ES^}>%Kz`sW-w~Q+1mL9YaZk0o_Uwa`h{GD!f$fc#BAj4B z6_~=4k<>Xr|GCb%S~XLlL1__!oO;85RfUN{C@9Wc3R%Ya8uMcH-5o~*5MXcsazCms z%41%}(UGLto3g{f5I7x@B%dE9_@WAwln`-5VU!u?U=~I)X^;yQjPhASi_^?HoqG^3 za&|&P-uDh5fXMSwglq5Z+==FVHw*uqoTbCGklcnVSC5+Ru9~y{6#`0SM6hDzh(S8R zS?$Ft59Z7&zclY`9T%5dFs!V{;D+D>K7r;e&G)vnOg0;&`$pGdezFjZ*8N~T)E-Hi zC{xyg7oFAaC6YI|5BWE5(1#^Fneo1=T)(x;jpZ&jlU1-DZBsC=xO~|4er;XMe8W}a z&_2Mwjo$nS?`I<9Re7gY1_nkVnJfSOnj#aL5II-K_3XB_n}JOiU}+e*X+&?rI!u>f z%@FjSksjYkS(~FgYn1#u+T`p7q823)+RM_{8#Q7Zj1#H}vks4fEETNuQZWT#wLyT4n|w@Ej%*!?A8 zBtzq0tXAVPG^kVCo|()VYGclld#_7l=;|hmx~6ecF`dzA#+0~ z{c?g_Cgktu8?GV2ENGji6At!;G0YmyS`sdq5`=24{Bk5hq=V}W-_+V3B04>`{N&ZB zCfE+ZJs6SP3Mqgy%ck~TkWuorM|RWwu~Vk7bpwV`s5LxDNx&{fd2%VD|xg0TpI>6rC;9GVIg^<1>Zr-9je5>hHL%g}3+9 zdPmbej+T6wF_7xfk~1L?GBvPau~CxQckD(|pr*D#P7sVpqG02&^Pc?Ei`x&2D(Km1 zZpTz{F`#D4`m5~tW=G5jY`2*6M)SP%rhnIDOlS{u?l{0kP${{}<$D)DvVp=q-;;P% zvv}MQMP4`zIEB)Le#DB=nfb^(=FTNS-LCrP%)ss59W6og7qi~-B59KNzcB%_fkSvi9aGMzzW@&7-x%6g-LXVO z)luZd3UgDRCnA2@cBg?Y+1R5*59=u(NHE^bii36!)Ubrd2UsjHJWLr+tx5$j>q~6{ z=s7?Pz-)oq*I)FGYM?pJLG{p{@2sYO8dNl#h%YJ|T|TvqWK$nPjZcp9KgQ1^Ae*gm zRZTJbcQv9%BDX5|Hqu5OpCjDj`v;$5o37R3sU?>)gt_PNbfTgu*@EbkXWUvW)Up-W z!sB!j<7q^zKV0f5+b$7xX6BjN0jMNl3r~Ku6RtrIAO`JEo#bO^h!1>qR%R>hI zCtUkl__JV@->raR?Y0GO`D^GTMkJ-7edln7wm2_A`k+D{8*#x!d^R&7uo0l`N)QG| zBsNEQYYnak=bxMoE}@)`Y0X$DjVLL=D9bj%4hn)QFt!W3NvJZJ9(}?9~58H^4E*FN{|Px;OcOF2v6bU zh(_u@hEG6)rVNq|Uie2X;o70m(#qrx5}o=FOS#GMe$W^uoW}v^Ld))4f7{}Cx_T$5%C+&irH?Bw=-^;6a!paIvXLRTZf#@3o6BtS<5=6)JU0JhzV-7l? z*6w|U4^Wz_nxs+20|<==z|1;Aq5BjT zQ1I>(V=g3B-}{LJxSEnU%xBPN5ZT)m_ycX7Ck)EU(hKTZjN&9f!vvzth>*bsM1 zizQ2Xzf+r{K@=1{UJ|Fh!_iUc|j1H2o)Rv zhRBbsJR?rz2*(@AzX!9_${z6YmlTExfZvOM|44)Q)2v>s+)eI(rWj-Z5~cu*G3{gc z7~5FzO@t;Bqc{K%09Cy(niK0SwH5QS6$gbWG(XHs1SD_~2|8U}mn2K;c*m@4`cA%( z!Y~S0nc3?j5#np4w9@&#EtBeNlz(Un!8YvldwqO{Z&2L#a*ne>Q>p#9FMVI6lL1x* zet9Z4oe^CK$h*tRQRH=Kb=#C4ql!ah0WZf;`T#?bPec*KS#l5PYSacgg#2%c$BKxF z9XR+ll9lVIRJfaIoZ#mXtLouJ`bIN^VB-|W+gq$AFy@CleCtCH@V>`awn&Qy>o zp}~Bs)_@72xq-ol7HS4WU_|omMBwjCo`4yi)ck|h9AJ?GkQ}NvCWPU_I8s2YQ*}{d zl8BwH9|%Nn-j!)B`90_fx#=|IKIsYg3e4y&dk-5B zI4ZpYq%;sKH@=UI{!43EYDZ0W^d+*Q(t6Ot^B+*ZgF{&hh6+F$Ua;9hcKOzscrmg`7&j1*i++qd( z8ak3E@5C>$REc3R?N)2H_!{(vR`(!S{QEdbr7o#K%RSbHOK**52RrAn_~h@s@W1c* zU{zd*l^L7;;sJa@yO@YXh(y;gg2%w*b-^6LZ+WRs`7>*(s)f2vu2Tk8Lxv4c+Mc#i zBK#>xyR1}_jx_lbM&B zM~ay`9Z`$RXGZ3cy+@=CArC3fOOf*-~w_^`i1BJ=Nbj;=eRiUa)ejorEA(1d=RFcH%34H&mpuE`b6+ zT)Sj3><$X6G`YMc^kU+5X8^R_QHqEz7{TZf|I{O&U}7!Qaqe6jMZJew=2= zxA1`sF34|j2hMl+i+y9JaLoA=hpGK~Z>gWO&&)MQrS;(~D~BV0+J;!zzN*~3+Hee! zy+(EM+8xGp%k~nXRJtmauZ`wQsJg}V_`X@US?apnmmBF^6`d~XE=5CdFWq+wM1X(K zJnrIM$hW|qXmI!{c*$azW;T(H7YV}rZR5=0`u8j$6hR@cXPP-1({kL;Yaf>@zGVKO zS#ZkGBo5FqQl=}U^hSvGpxtnzq^Ta>1)IANHrm*m1t5u7iUz~$q`Ub-RC8t(FJ#uu~i@0sW zgm`a@{aAk0Eo2d1S=ODwjga5?V*|=}Hwen75D5Qt?!neZ?F8w5M5hop%hMQ66wea8 zYrg4XQ!x{B#X^LRoIKMsz7SrVw)dc%;5>b(?DSCNDc-DgXVr%VzDY`c5EK+=V5$&~>4G#|KUN1>gKg|0T)pItr#&Ei zaDsz4xB<< zCOmWfElmOihKHrOzrS4NVl~n;CE7FnpmC21PHE?aEF6Y3%?w8>oBkuk#}xPU>pKrZ zk`n?nbt|H9EhK(H{h%OEss;>*%!PE9H-!}v`tgu^%EyKmd+{@8A>Q}6yu-!B1(%ow zr>3+-cuxtZm+o7j|?eQD9bQg0wO_vXOF`9YEKQB&iIsU)ASgV0!%*SMQghiA24 z)OosK*D)}=tEmCOdkSoX{&*69lFR9X`K@7}W=6oqI6i`gP zK$DCqFT8kJj2-UX?E=%fyfrPpM1 z8*nVcpOELeJA^z;pWbSj>_Um^0GZ7GYiOPKeHIBu|MhmNQ~0RNRP~@wZd+3^FipQ8 zn7sNJuH6kU09B(mBd@pE&Y@-95fShkf>naG#d9 z!Bb>-ikx;AC|L8~zl#{ljtbV%E7yc=I+z}-NA$FzMOYfSqSJqb8y^1{W zCNLnHZe{pl>*#5R6bI?%)QD(pDV26B>;@8*h|OLS^QpxJIn8b$gT76~e=W8td(?i6 z^p$@lxJ`DBI!i1!o45#P9O&>$r5|fz?AUV4<_wxAo24o(5$j!x#Z!w?0I1e>j#)`ItQ02eecB!vmc+0zAJJBvk1bX+%7!MU z4C*VzRf5JS*qIesE+n=0^W|4o-_YoHB~975xF5uTdR4jR_*RU=@gT1Kr89CJ;9On*(s;5i z5bw%-Wvw~p&9+zpWi-EMZmolkReN(J$BlZV@uZ56gY!vfHg_=U0k1lD5@R+>07skC z{ezRb|3X+C4uj&?y;`C_Jr;|qcJh%&vM>qc$x_ERg8Q!9dnL7hjA+FQ>tnO#h}3}$ z5uHCmRqCyCXD?U;GQ9P95(Kz~tO`m-;wCQYol#0HMZNG>X>Y7;O6$OLLnKfej6 z3OF(c+_Udg_$|Rsj)8&~@X%@1+~k4jZ|jgx5+XC-x)G-K*8LD3aKO<6wXP??R|63e zv_H>}Bkz9W46yp>G5daRc%Xk>xR$*}Rl;bD79AMdk$^)4QNTZ0&O8Fwo-qr@sRma} zyX$?9j<#_W(0KhplZhuKy%1G?NuT{*^AAw?EpVc#FE~e&M+C^z0BoM0wznl zMSZ&YX1p_d{G)bhR(QuvcQuYDD~G5IDODSQ>^E+C2t@}|uHYTgJNssuHfs4<%My0K zJ4!cq(aF;BBTPu}OaE|fGx1c0Ts`{v0gdeJ{+~^D>gulBeUIsS(gz2aFaP!iC`S8@ zXm@roOasRlu93`Ez!!>8sv@TOCW^jZS zTllpUZO_Bpy?c%g9m{*nf3G*L%UhRo{AZ54Mq}9uoTUc)4`B6pDK1_4daf63JNVy< z0$>+a#k_=_%l~!o3*X=kVrS9OVwo$Kclsi$&(F~&a}Wkp0aPZmeOaqp%Mrkvuc*ZY zMn6+;cd+HT-gMcKjWa^KGxCm-;*nC3u}0s#g;=@jCCj!TfP({HLd=(w2Z6h<$1KM9 zuJS5Bq*L^d>~?*zE^&dQco%e+)=VAfA5H$Y6H>NAGt_nsJb>AQG2v9X~k5ijtP173dU#NzZ(JLa?Tj)w#f6i%dXqgH?n4px_hTw!$*;Kg60?SItK4Jmt)BN z-^SB?j4BDE%KEjAL)*C0Qqyj&KWR+vH~qD7s_Cy+*Qm)7>|2+w-Oc{R)S9{3LL221 z{f{_M@3r00($nO3Dbpyphtzf{^IAuz80(y_D#92Es}t}Xo9=$?uwH6~TTZ^vn*giV zw&IhHk0)$0w-up(+HZY#d{LJiB4Q%pN9@^*UBW3weg7}Q*nailOEx0YM~W^qw7Q9g zOEG%8OQVL10$tO=8~XN6jaLoaU8C7rc9ek&X^!~-y~$zRg|b}+YjgFDXXcq<_;hWLfFjX25JXdMx7@QH+O#fE2{_T4Xn`j zXeS1|PY_1nYJKYVdz;QANQ7+GOv?a8*}A9GYFt0E^1~#ST@W-qz-d4ihq#$e7R>)h ztTPAdA`ZkU1Adsy6MV6&EfmNDKs&QObdlEj7xXz18Q~dsJ6R?UWZ%XotGHHKwZA@* z-5i4$;KP%0U!Tzx^BK=qazd>V=C^K>2grM_9XUETS@e+}o+Dq{eve`i$+0G1BsG7O zd=<`$ki|w__OV!o!fNogf>$}pGK`Jy>TqP`E_}HyhC93o0TjW1{L0&864lfaNM;(8 zO~q1`8j`1mb;q*Sj)q0o9;#JqJ#p5C=CrO7ML1`0{5efz7(0 zm#;q~M$f~zS~^L=NE!W7|9uix$p+XM`$pA^Y}ZwLX~t%6f>p`UF2E->$%mdllcYe; zn4%!2Q9}?e9L^EkIbqhN^TKGR&u`;?Cbrmgqg?%%c#XZc?2HTU^PY`^k;4cQDB7uV z%g?(z6y31jao=JL@97PXhJi<#oDOC9G6g$v> zjdo&0NXA8B#a2G#0@oleVYXPh?AKfVE`e5aK_zAB^Z<{+WjS*vE!R82+@~0O4f`u- zxRI1U#pq=!3cs>|`It=*t7o6Pe9Ot`PP$W{*wo2G+L|L8s1=DEaR3o6mXV*#vnBuP zg#u4cn5nmBTk%vRrJACt(}eJEX0Ag$FG>Azm%j@*C?na8ovp-~j$NH@-_A6gi3E*) z%+6Lb@n>lHl|0?E+6Z*2;@P`>J9JXIyP?KqKU5)v1;G-ER4G1W0i@A`sb+c^HI|^ zxNY9U)^iZ${?>bjhu0rix9t8zA58#N??mhu(D&j64HkNCVv~ty22&I0dr_O81J(5o zVn$+bnT>|~l0G7|y9gBbC*kE1d?>kh0@mfKsqMV}b5@;bX)|)V6i%nLT=(l#8-AWw z6uP2~mjYqI2k2@La7y~ygJ1Rwu2V?b{hLLCz;dpeue{?(e=bwOdap@|UK#9b7C!9% z=|$3YP1WA^N=Wxrc<~PD)^**<6R49qf`vV;r`;sQn0cS37_G{!=IHJDohDAK9@!>V ziK&ebJmn-1}Mlxau*M4=63vQggZOfcX9=ey-z{_f&=g)B1HV z!Q3|_lm2gwZFXjkS_tdEgj`*HDyT|Fzl%CLIs=C^26qZJS4$m3I}~hB5BVyS>`mmm z@v~~nMA`;cPk#c;Zp=O{Mo@TN#o3O@R2&%~wBOp$WSe-4W;kS=SDO%xsvH_SSt2}) z{jjd*pb}HBdHlnvbDI4gSdU)WaMT&(ag|MBC4F-w`n?!Z`C+!$M){h}R$8rvlA%Ee zewmF_Z-)0e7}d+9-|=8pfC}|8A^Na*ri|3)+#K~_LD%kp#yl1%^d`~y7bk;5p(|C2 zDi3e!4EP3*uGXG7+{K6H&uNMj=o39YBZE#ig(%Q`8@~7BJHZ*#kZFsPc zk14st9&W8t$FZrTMn}e`?)RN|1KRv12DGJd^ka&tH#&&K%ZUnePx|)ET8uXjHm5{F z4tEaB`1WXtG1Gl&jhA>}a~ol$24`lgZ9cfL`qo8h!ryS$8^x0F9}HDs{2j&lCo^#O z5EmDjOguF(1;~-a7=h2aDBx_gXVi_J2qDuxf6Ql{;)P6t*V|*Hj{w@$+A+@Qn0FLOoVWrSRYm-LApJLx{=3#&Q$AXq}V06xWe_YSk+K>@=*!~d= z6xky)0-^HGi7}t4pkE*p&=UoI^_typyb4ihQ^6p-M)R;)>_0{#zU+_X+qW>&Xj6I9 z;>EQaqkrfXlYL>d({On(WbOf=2fA8H>s50M+UC)9RWv%ZMWSf*gYK%T;dsaVq`R#N z=vexXSmFsRD>b7~!W;M*)cd{wn5}zOIgI20k+yB?YXYZa=G3&ro5jIiaM|A6A8A8Awx)lWhFJeZkK6O28tRF-GMErj z7d1FX>rj}rFaP5=iR4hf!2>cL!*AGc$<^ufSn0)kuiC=0T^JDV#a5kB5Zc>GZJxY= z_!(23&%!_F&9$pLHrN-NbVo=`ykiB=w1M}(A}T8aUURPzRcyLBGVQPV)w^o~2i1Q} zU|&IHY9_#ZWpBO7B`ZpCw(6bhq`4%q@sJjo%%9OtSFZP-QyQ=X)r9|x8}&$;e<;)z zE1zl^kz%IOQ7N(j^)2OV3Cx`*Pvur4M)Jl5*s~SV(NJBBu@xc?A-cZmPTg2DTO~r3MAu z1^K?hs#;9sM&8PRer5rQTgO(bQ*wF)X?v0#iuuy2Bk^Q|kWYNh$0*>a99oB;;GULR zuIKVSkN5>|?~jZwwGSz%?gQ7$7le@dosUt>evjdnFZW*5C;PMnkQ1T;%Dw z9I1V*S%OhTTn1zq7iJ4<@S_escObp!gq5{*YOvGIY;9O*cp-@q5uaW_j?=hW{{=sv z4t{~%aD*2Z^)6+INs6d{yr(@^d1u3z?)k4U#1#Y-Sc=o~5 z%8uBon=>mJQHMGWaC%j+xg??a){S>0uRj0RQ-(JDASJ3gciN)pTG zFi_THL}gjYE7$WQZ9^1~*2-k*{AAaCO86b`9YlbFn5yb)J_Lplvs=!rTkS70l^1}QxXw>R?=y}VHaua(y={_ zo+U;F?vDSgz2ai+G3=H)7?T?=6`ELKYLCb_sLaI9qmOZrr`10dEDImLrP4F#U~vaH zPNj2pf%VV7n%SJ*?hBQMm%dYoxN@PQ18}X;a~%CWU%ljPyatt|!;)}T4(*R1~WZK+=BJKJa4HR;}6 z5_S1IQq>GRM+ZBjY z5I4P7d1I>ojVr7bJpCgg zxoM!rW&c%*p@x0i1b8t>_a}T!R$XEc)8-MbxEMx^y%3o7`yDRFKGx}nW%;x>JEN@# zI7sd83nY=Da^(_RNM5O@BzWi>pwt)B^<=yQvMP#{rvxH>I(I<>w7PP#Aut*cO3cCf z0w_;1IPbM38H)Y3a1q^z1syw@m^!8{x>%^E7n$s&t#V*I&iil=@?T zyOjKNrK(@avfN>-DJ}!7O8zXrk&&kxv7>0+4<*o6Zk9Ji+*G+O)89$AeEKq90v^W; zU*0`!S6-}nh&{0UlSb<(A0vcW)L0*&Y{es@P*! zR{#My0HPWW&MCr5tEl#>%{*hL>Q2kQizTOt;VX1XN!N>Tx{;)7NcRI913?pM3UG}& zCU^BAuTDMMDf#aJnM9XlneS49T8{Y$Dw~y#Hx%WaUfE@h}@35i#E3<-^dFaUJb*js9pEikqM-dLYU@ zG2;t}t%2?t=cz3Um^)Fi5ALi4cCk*m;cFzFui$Bt9!j}b>|x9itSZ8Ykp#zz=1W!M zJiH1v3y4Nf1i8at4Q=E5`tRRe?SdL}5s^r_6Uge+T4k{Ro?JR~BJzNM9k_^9X?JN)C))ia4sFnf#8^nG$`OUrZV%iwxw%T-q6} zcc>>8LLi|er3qN6YUlZ%I+tNYZ+8PQU=*((dq+(sc*HGyP1`?&;}K@*D4ad;5c^~w zBKWM8FluM|duO*-a^^1)sT)=%zK5^rj0mChH+>P=g%?JQw?X28iBLqqtFUb97kg;10w?+|>4jstkgUDRo$q=W9%rX76HosHqG)<9LY0 z*0L`W3mVdyY*xfufB~~^@bBwV=+O5nUoMJj`?K#w>;V@Md%)>NNw#Hu#rk{3izTTq z6A6j*=cw)r&UK$73(n)`ab&bN9N@>hy_+ZCwSI>%L2KrOpm%N>6~ESqMjT@Jel%Yv${O>MnpKF%v7sL#>UjX~ z-0a%MuHO-&(SjGL@t*I0&xFd$F4=eFTLg7J2EJw!YVxTvRR^${5}eBg#X4#R9K z@tL%JljKyx3&PztuQ&+mTs_H8Js@4o$WB&P|JnZ}-^aR*XLr#*BrE*T?tZ>fv;@*z0Z zv;#OIU!+GzbjkV?0L&gBEIn6p@L|k9gL9EYcb|A~Sq|JQfo^rTvp$IozYleWA zH4LGTa?G6)tPr{syFxD0`(ie(BFzi>$o~P}(jZ+;l28{&&YnStfO?nEn$+G;y|y@C zJDwq1r>9%Neb5kLJV9a`s;$m=_wFfe&Z!n%<0`N+v5T>7O3W3mrK(=;Qajd+w`|GB zDtZqHi4;$S)@q+_D5|NK$<*vHpw*38ssH{xPp}ogB!efolw#N|MB&Im&T(59IM{ko z8R}q(`xpbrp1z20{SOymRu|j0VCdrA<~0FXc3t^VU0D+r+tr;l?5}RAF^v|;`)i*$ zblIILYn(+q=7?!2r%j|O!I3{QC_gXna}NjjxVVR8L>0bgM=`#N>5WfTRopJvC^zWF z$7)^NysgrF@Yu|(D|A4By0&|N^&L)#akuG=UKn#oJGw9^jQP#OH`tSCs zk8?*DNe>fpEJ2ul$`aq=gz(nlCQ+JSr0A@N?{x^^wY4NX_m-?Oz8erGO7s3wiHKGb z(%2DUy^(Y3uwQZa!26)jjya>ygu6%S8;UulclIikS0*KVeC=KY^1Z(+{JbH^X7Foi zxL#0W(rWy^A!}_em`3y*1@8lN=`JbuKcaWHtp9eG-WuO_n44zFmLz!?()+lt8= z*{coDb`$S;*41hVcMy})!~P3N3>T0To*Hvxfcp-@BtRca9&4uY{gL|et*Wd$Fp9&o zr`C1q%+gfl%LGBXyx{uWfrxv#>sghBN#G?Ej{Y8Y38F1W|9MCyxLTz4L!TF(8DU<6>02=VjVt4{k_1KdZ>W06 zc>(i8rDG6_hnR}lf;{MYfs;XHM9v9&E^K7^>TnScN$_-&@C<+l6*Nt|8jICDuJ+cVkY${ zX0FnFn<|Kww=)F5O)fBVXW5Zqs_GI+0el%|#vp`F_;(97yK(^?I)l1XT7;#JEA$#n z)W-#H;^KJfY1|^N?dKGc6Dbia(Itd6Axrwtt?{VFt96&_b6K};|j zn4oNe21E6%=g;5P=1Px>4%POm?zUKy*AARzP%V&?4v~E(7@MLA_!}0;b@>aOx9ufu zRdV#CtHP0wLgX)zG6bIeJ^LceKn3Nl+N2xMe}w!DGI-JB?%Aiq__@Up#jxbd6HoQ? zJJH|Y=~t%hqg6ZKp)XF;r!0Q&pypiPDIFB@n%zoB7b+0-9OaUkR&P&GlP``W(Euwq z*psrN6qMLpO)E>{*E#^txbN}awfwn`?e)&N`?S=egjTRcz^sQFx71p~WZ0rrd(VxD z^4Rp$+<(`cLhwG$5ne0JtE+=&fdii4bA%%r34v+R^t! z=mcwY?R96buI_1|&uMo0I2~NS+Ulim^)p(_J*&W}9vG-_U3GE7Yg}Y|)XSqq{)}hL zTV^qLLYm}C6(kiePKE9P-3-LsA#2%`nWuT{3dH;=>wLtJIE@|k?{%K*Yp-GD_Iez- zaRI6^MMHTLXygTyFT1-woO-*jJ3;V-VO;JS4}_8Pi`bbL-tSLmkYjFc5^d(aP$Bv| zjO4{I@~Oke8=J_Vy1So0n6|Q48>=ei#Vrw59xX0mA3H++{0UODeOqsx#^Gq#>Q?#k zQrnq`u?(0%q8$kw_NLE+u4}b)glf-d;n$HPHO(4Wtf%#Q^(GQ%Q_1}`(l#N>0uDfhq1-Jb{GZHG9r z&?$FNWKZBq?)R-|y;~gpr!jWS3Qtz4f^^e3iM;W_tWy$_rbXQ^CuPTE14)h zlA)*5T^(uudX4}uo(GnXvtE#=z6xAbl@6URZw`7R5kQFjT8~;2Y9in(tl?*vj|PL8R_*_fr?Sqtcl{7q^si#n)BXVJL436faq;w_|+ah9Ng$baDg!u&_#~|`%uOVXxGyn#SR98A-sOdxOXOz*z*VVU63Ky1|M%MH6_7~= zOiX6bA!3Y8y(&wbr&PSz`K<1vj)Y8~=*dKy&eREa($m*|D>GBs))fUxT5VBKyV9e&{yasP@LX7<5a&fgh zzX(LzKYP)$?<(0S@2qgl501KTE$B%H&U(VVT^RgwoP`-ee5HCJ0)TQa))R&3c0bq2 zbCL@Tv1-Xrc3zOUwcG#Q_t<6kgMv4=((|WSmFg@`l&uj}YZ|(?)zBk__2l7L$BvW! zP8lzn_x@M=tj5n5=SQl5rL(~WdOzr!4M>7BRkhnIrF-**aF@3Nc0p?^^uiKfu312X1}By?62Wv4nl>#7%KFOmQ8oX$G@r@no6QIUU&bB@d>>V%=t<%r0`nIase+3gjJ z{9glj;*Df6?{9)xzhNHl%w(>%TJ>ap^~Ee`uh7f)!bw9RzH&RvtG5vWDxIb0w$T*% zgOwSEL^=MLWy_#cIgNviPMP+s*R*p?cNarRLbQ&_JNP`& z7+P_0uPh&<+BWgYCA}>pVvgGWZ$BRXVt*{+I?Ql9_w@%((Mu00YNKg}J*uYn=@rek z0hGgF?AGU|r5>jb=08gMJFBGjrycdok2Wj{S%LmQQN$H_L60BaB+@ryQ} zdpb32w8PWB*?-Js+}4Dt3NwWjbNVs$LS(<405{BA||^kD-xWRLCR$;^9+@F!C_51h!)G#FWl|e#(T_S zHeezs7162ua&n%3CTI2a{7biH{dbLVbAh-t7P+?s@gb3)y%@%LskrFHP?>2k*0g=_ z!c0GhhV}IB6XBtHX>LfY7ju!M@<;y#&8v&A?d@r^BTutJZtvmv2gQD|Y|1A(-#5e! zo#}_$yH-C~)XScpamD;B$TTTD&2wbCzxH~l>&Sub1~1kTw-vrrx6&hm*rzlsSDx74 z1QA^UrG510>u3{sr#mjExBMDm+u=NH_lF{0lW;Z2>J;{`ef1~BFZ5bazz|$Yw>y}c ztO{Wsuf^Zodp6P#g#|RszC3`(o7geKM}$$KQ0IXob|6JxGZ^xX)YZY50rErMEBTlo zPmjyP?FBhTDn6dL>IhBz$#ZG4f^>o0C*;Ci9jL#t5Cw&Q?g*GyQUB;N>Inx(@7}FW z*(_DXPJ%w2Z+lPaZVbZ`R(htKH#8bOlKUmFj^2u|i@-qnKSO$6Pp*3=Sj;pF-XMG1 zKy(FAMCGCTM1SZ>+V|V~4rmP{ZBt2Pk>^cU^+c4Gqzvo=>B!b!gx}HH2gu9R&3|XzW1=+hpPD%Y1RR>@_6TEZ3 zS7>_k%fIBmD*9M-mPY|HFB%d4qEZuHN(BF!_RJ1J(!tKZj?$r6EH5zK88#bMo64<2CO+M;-c4DQ!jX{b}*wfsNv4+L@~@()M06^F@9EAY(%ByPk@Swi?4+EQZ#vA(fJ6M}3Mu zRSZl{Jkw1{$XpUwHvMmlO;jf|rt%6V?ScvO`rDaz{|oYXrB4j{&Ug32=Z{@Am&x(o zAlun(VR3a#yLZ&Rp_DNh;W#Q?#1;Qhpl0G2NZA@WSCfrWwGY%KX<53hRXiC|t|$=x z>(s`8S^>muJM-@YC!9=%r4cU~RU&C~eOyJW26M~S@dF8TaN6HvIE44rLf3SQ#VP0)EDmj z$7QuZ&n9fEuLAdvx~2Zgdhm~|qZ_@YC(|GaZ3VUjsUvqlI;>~HKYA=5W7xy>n*`3z zg@M|M(Fr6jdWvHxUrPkYJ`zR*^g^{4tDk{QMV}q)$+aH=WyYjetiV3fTf0bq3561k zYxxbp(dN7Ip3YSDe{hB~*3v_GiLABp+oV$TI&9sWljW!n-!An?zNsSy8R3e5(eV4< z7&ggmmX8EE<_okx71D5C9UPPIS5!zN0tevkxFAbPX`TL6<&EqirO6fN(j+F|_e7)3 zIdU7DPSbM4(JqaLRm_%dw~d3s9|Qu&As~5XU67ZP5$!I6Xbv2%|4uoy=R=RfUyHAy zLWB@_rK*Q^U)?KEA&GlCol`!>P=cRtZ;=?xr4H9go5+aazCszRT9D|E&Ok5lB$?HT zdp~r*?{1?7K~`IX9asv>6Ra4@VC@kQQk$GATa?p!rU8$pcs<#nNd7jk`8X7x5y~CG zeMT|uO*ydaeg2eFX68Fx`75jWuW-e$YDA^d$rY0{2K2;qF+nBoS0rz)`?Mb!P~c_D zE(nBZ_ed(R)u2}#Nb1!?IPI3oyM<}MYma%TKjH#OA{&vM^Y;Sx94PoF4a$t#7zO`6M`$$~Z`X zvg%{>ucxRiYPcgk$5^5f7mW*m!d@Ry+nei7xoI;)cfuwISs2|Yy~V#D;`rId8dk^j z(2{@0(AucOYILkdI>4dtm2xu36aU;e@|kKMuB2zTy{=9g6xxBHC2_A;%0UmWG{LT~ z;{Ek6c8PvQv0nE%)MYaLf@p__82oZwmp^f%MXSNkXr}x<19e_{v}?anVe&Q0@Vu8a zzkSDfBSsgh_kry?QZ&*jlNJLCQJRqIj32JI5N)#mJsOg)7zQl3e~d^j&KgnT{IAI% z*2K{JRgi}|YlHc`+AHEmK+}Z~{_`m&{WGi9?;_klYT&(?!&Q`8BKNaP9T-R!T9W~BipHQS#V%6yc?UMEh+rV|Y1CEc@ z9g^3~OtgX3*Q^vS$+NDZ>gU zyWx}n^RrGJGp z_fGP|$5BSutwH_$s>yAP*ZdCyy(zT6>ONK_dcm>|1&9c@c_=>?=;j?`7m!72IMb%9 zi(!de{$Hkv0*@CSf^LIr+MWuWnuQ;Vy0)LB9iB)?hhkrap zf`Gg~#M3c=(IoWsrsS({{=CkXZwR3Pe4w$ch5!FaJnGmiF9>fC@|0HrbcYa)8 z^?oS_KK0kz^j*Zlp7t8sAEwoBlU%34Ux9@^Fc=)`N&3}>bKMX=4ZcVq-HhA1?B4GV zS+4y;G#T+lsIG$G+6hbYbxJHMn2`@Eh8z8C{HT7mzXp~OLNuxTp8zg@E~6wYjsy7@ za_>Vvuvb%lI$=G(Mj9%Qea&3orD!-sjma-k$!%RXU;`4+SRSak&4ZRw7Lf-2cPPL! zEdomq;o?zwfIZxoQ{$$3(V6#OM$V20Fc_H5`;Fs`$Wi`lUM@pIS!EE7(nOh+wH%wP z${yijzV5X&pogJBPK_dS?DDzJq`RXBr1sW9V zty(PiK(uH2mu-kP10RU>=D<#w1+HPQE^s6@nfF0=CdrAhh(S!=%7AYAU+YCMik_}F zFA*bEKKO&8=Jwl^=(fE|>}#kcU;tUTK(m(Ab}F7~d{?0J&VRZ56a7(FIa#CT22C#Rrs~d>Wp+c#Y!UpCS1Y_}Y>*3C(FfuV3#G*)UULLbPAH2GwZrZjk5<<{91#7G%ymAOhnsVtoN?(%CKYUibA( z7}8u!q4xd{_3zx&bAMjb`WMmn;SEOip*-aQBNJksKbDdvNUs}rg08oqveYe!ho#&w z%8u}3=?&Hy{FH(`~7g3d%YfDm~)B0Xc-AG^w{ z!bB~uvwkF$MvSj`2KlhPUJS*2*aBU3M7@cNp3}|IE%JjAMQW$Uq4_+b0c`@73GH-X d42<8@Vre%hevd>S0M9HV$x13o6o@^0^MAC~1TO#p literal 0 HcmV?d00001 diff --git a/src/themes/dspace/app/home-page/home-news/home-news.component.html b/src/themes/dspace/app/home-page/home-news/home-news.component.html index ef576ed99cd..d61f2764c94 100644 --- a/src/themes/dspace/app/home-page/home-news/home-news.component.html +++ b/src/themes/dspace/app/home-page/home-news/home-news.component.html @@ -3,25 +3,29 @@
-
    -
  • easily ingest documents, audio, video, datasets and their corresponding Dublin Core - metadata -
  • -
  • open up this content to local and global audiences, thanks to the OAI-PMH interface and - Google Scholar optimizations -
  • -
  • issue permanent urls and trustworthy identifiers, including optional integrations with - handle.net and DataCite DOI -
  • -
-

Join an international community of leading institutions using DSpace.

+

developing and accelerating community adoption of standard, interoperable, and decentralised approach to + linking research outputs hosted in the distributed network of repositories with resources from external services + such as overlay-journals and open peer review services, using linked data notifications. +

+

As part of this project, COAR is funding the + development of platforms and systems to support the exchange of linked data notifications across partner + organisations and the workflows to manage notifications in those platforms and systems. +

+

4Science has been awarded of the Implementation of the + protocol for the DSpace platform and this site hosts the demo of the resulting implementation. +

+

Join an international community of leading institutions using DSpace. +

The test user accounts below have their password set to the name of this - software in lowercase.

+ software in lowercase. +

  • Demo Site Administrator = dspacedemo+admin@gmail.com
  • Demo Community Administrator = dspacedemo+commadmin@gmail.com
  • @@ -31,9 +35,12 @@

    DSpace 7

- - - + + + + Photo by @inspiredimages
diff --git a/src/themes/dspace/app/navbar/navbar.component.html b/src/themes/dspace/app/navbar/navbar.component.html index 05afac7d7e9..81f13957431 100644 --- a/src/themes/dspace/app/navbar/navbar.component.html +++ b/src/themes/dspace/app/navbar/navbar.component.html @@ -1,6 +1,9 @@
From 7998ef489cc4e30dc0f058d481329e2f39096caa Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 23 Jun 2023 23:38:06 +0200 Subject: [PATCH 038/592] 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 36678460da1..8db862dd5aa 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 072b8d78281..0362ae6695e 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 a9c5c20c5aa810d516eb28d87ee1f217336fe90a Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Fri, 16 Jun 2023 11:45:26 +0200 Subject: [PATCH 039/592] 102415: Provide all external sources of correct entity type in edit relationships ({item-page}/edit/relationship) --- .../dynamic-lookup-relation-modal.component.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index 69c2ac3b7f7..95acd0f41d6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -30,6 +30,10 @@ import { getAllSucceededRemoteDataPayload } from '../../../../../core/shared/ope import { followLink } from '../../../../utils/follow-link-config.model'; import { RelationshipType } from '../../../../../core/shared/item-relationships/relationship-type.model'; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { FindListOptions } from '../../../../../core/data/request.models'; +import { RequestParam } from '../../../../../core/cache/models/request-param.model'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../core/shared/operators'; +import { PaginatedList } from '../../../../../core/data/paginated-list.model'; @Component({ selector: 'ds-dynamic-lookup-relation-modal', @@ -202,6 +206,19 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy ).pipe( getAllSucceededRemoteDataPayload() ); + } else { + const findListOptions = Object.assign({}, new FindListOptions(), { + elementsPerPage: 5, + currentPage: 1, + searchParams: [ + new RequestParam('entityType', this.relationshipOptions.relationshipType) + ] + }); + this.externalSourcesRD$ = this.externalSourceService.searchBy('findByEntityType', findListOptions, + true, true, followLink('entityTypes')) + .pipe(getFirstSucceededRemoteDataPayload(), map((r: PaginatedList) => { + return r.page; + })); } this.setTotals(); From cf9179d800dbaab74fd48b15bde4840cc1155f57 Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 19 Jun 2023 16:29:15 +0200 Subject: [PATCH 040/592] 102415: Fix for import modal i18n labels --- .../dynamic-lookup-relation-modal.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index 95acd0f41d6..38b547d4a98 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -178,6 +178,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy if (!!this.currentItemIsLeftItem$) { this.currentItemIsLeftItem$.subscribe((isLeft) => { this.isLeft = isLeft; + this.label = this.relationshipType.leftwardType; }); } From 969e006e29d7723f36f67d5000489fa30ded3362 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Wed, 26 Jul 2023 18:27:26 +0200 Subject: [PATCH 041/592] CST-11012 Created the footer new icon+text, new json5 texts added, routed the newly created component notify-info.component --- src/app/app-routing-paths.ts | 6 +++++ .../notify-info/notify-info.component.html | 16 +++++++++++ .../notify-info/notify-info.component.scss | 0 .../notify-info/notify-info.component.spec.ts | 25 ++++++++++++++++++ .../notify-info/notify-info.component.ts | 18 +++++++++++++ src/app/footer/footer.component.html | 6 +++++ src/app/footer/footer.component.scss | 13 +++++++++ src/app/info/info-routing.module.ts | 24 ++++++++++++----- src/app/info/info.module.ts | 4 ++- src/assets/i18n/en.json5 | 18 +++++++++++++ src/assets/images/n-coar.png | Bin 0 -> 5564 bytes src/styles/_custom_variables.scss | 1 + 12 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 src/app/core/coar-notify/notify-info/notify-info.component.html create mode 100644 src/app/core/coar-notify/notify-info/notify-info.component.scss create mode 100644 src/app/core/coar-notify/notify-info/notify-info.component.spec.ts create mode 100644 src/app/core/coar-notify/notify-info/notify-info.component.ts create mode 100644 src/assets/images/n-coar.png diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index fe2837c6e3f..518622c8d1e 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -32,6 +32,12 @@ export function getBitstreamRequestACopyRoute(item, bitstream): { routerLink: st }; } +export const COAR_NOTIFY_SUPPORT = 'coar-notify-support'; + +export function getCoarNotifyInfoRoute() { + return `/${COAR_NOTIFY_SUPPORT}`; +} + export const HOME_PAGE_PATH = 'admin'; export function getHomePageRoute() { diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html new file mode 100644 index 00000000000..3596acfc67e --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -0,0 +1,16 @@ + + + + {{ 'coar-notify-support.title' | translate }} + + +

{{ 'coar-notify-support.title' | translate }}

+

+ +

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

+

+ +

{{ 'coar-notify-support.message-moderation.title' | translate }}

+

+ + diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.scss b/src/app/core/coar-notify/notify-info/notify-info.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts new file mode 100644 index 00000000000..eae3a3e3d63 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotifyInfoComponent } from './notify-info.component'; + +describe('NotifyInfoComponent', () => { + let component: NotifyInfoComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotifyInfoComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotifyInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts new file mode 100644 index 00000000000..a144f5d7468 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'ds-notify-info', + templateUrl: './notify-info.component.html', + styleUrls: ['./notify-info.component.scss'] +}) +export class NotifyInfoComponent implements OnInit { + + constructor() { + // + } + + ngOnInit(): void { + // + } + +} diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 97265d7a232..5a77d98269a 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -81,6 +81,12 @@
Footer Content
+ diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 350295b8704..7a1af42bfcf 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -22,6 +22,18 @@ } .bottom-footer { + .notify-enabled { + .coar-notify-support-route{ + padding: 0 calc(var(--bs-spacer) / 2); + color: inherit + } + .n-coar{ + height: var(--ds-footer-n-coar-height); + margin-bottom: 7px; + } + margin-top: 15px; + margin-left: 50px; + } ul { li { display: inline-flex; @@ -45,3 +57,4 @@ } + diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index 4c497461e71..9734fa46273 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -7,6 +7,8 @@ import { ThemedPrivacyComponent } from './privacy/themed-privacy.component'; import { ThemedFeedbackComponent } from './feedback/themed-feedback.component'; import { FeedbackGuard } from '../core/feedback/feedback.guard'; import { environment } from '../../environments/environment'; +import { COAR_NOTIFY_SUPPORT } from '../app-routing-paths'; +import { NotifyInfoComponent } from '../core/coar-notify/notify-info/notify-info.component'; const imports = [ @@ -18,11 +20,21 @@ const imports = [ data: { title: 'info.feedback.title', breadcrumbKey: 'info.feedback' }, canActivate: [FeedbackGuard] } + ]), + RouterModule.forChild([ + { + path: COAR_NOTIFY_SUPPORT, + component: NotifyInfoComponent, + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: { title: 'info.coar-notify-support.title', breadcrumbKey: 'info.coar-notify-support' }, + // TODO: create authGuard for COAR_NOTIFY + // canActivate: [FeedbackGuard] + } ]) ]; - if (environment.info.enableEndUserAgreement) { - imports.push( +if (environment.info.enableEndUserAgreement) { + imports.push( RouterModule.forChild([ { path: END_USER_AGREEMENT_PATH, @@ -31,9 +43,9 @@ const imports = [ data: { title: 'info.end-user-agreement.title', breadcrumbKey: 'info.end-user-agreement' } } ])); - } - if (environment.info.enablePrivacyStatement) { - imports.push( +} +if (environment.info.enablePrivacyStatement) { + imports.push( RouterModule.forChild([ { path: PRIVACY_PATH, @@ -42,7 +54,7 @@ const imports = [ data: { title: 'info.privacy.title', breadcrumbKey: 'info.privacy' } } ])); - } +} @NgModule({ imports: [ diff --git a/src/app/info/info.module.ts b/src/app/info/info.module.ts index ccc4af0a7dd..0cadbf4bfac 100644 --- a/src/app/info/info.module.ts +++ b/src/app/info/info.module.ts @@ -13,6 +13,7 @@ import { FeedbackFormComponent } from './feedback/feedback-form/feedback-form.co import { ThemedFeedbackFormComponent } from './feedback/feedback-form/themed-feedback-form.component'; import { ThemedFeedbackComponent } from './feedback/themed-feedback.component'; import { FeedbackGuard } from '../core/feedback/feedback.guard'; +import { NotifyInfoComponent } from '../core/coar-notify/notify-info/notify-info.component'; const DECLARATIONS = [ @@ -25,7 +26,8 @@ const DECLARATIONS = [ FeedbackComponent, FeedbackFormComponent, ThemedFeedbackFormComponent, - ThemedFeedbackComponent + ThemedFeedbackComponent, + NotifyInfoComponent ]; @NgModule({ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3a5ff742df0..9d72aec64f4 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -867,6 +867,20 @@ "claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow", + "coar-notify-support.title": "COAR Notify Protocol", + + "coar-notify-support-title.content":"Here, we fully support the COAR Notify protocol, which is designed to enhance the communication between repositories. To learn more about the COAR Notify protocol, you can visit their official website here.", + + "coar-notify-support.ldn-inbox.title": "LDN InBox", + + "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at ${restApiUrl}/ldn/inbox. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", + + "coar-notify-support.message-moderation.title": "Message Moderation", + + "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking here.", + + + "collection.create.head": "Create a Collection", "collection.create.notifications.success": "Successfully created the Collection", @@ -1881,6 +1895,10 @@ "info.feedback.breadcrumbs": "Feedback", + "info.coar-notify-support.title":"Notify Support", + + "info.coar-notify-support": "Notify Support", + "info.feedback.head": "Feedback", "info.feedback.title": "Feedback", diff --git a/src/assets/images/n-coar.png b/src/assets/images/n-coar.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4c7415724392bb1c7bca439afbf0c6f5c006e9 GIT binary patch literal 5564 zcmb7o2UJsA(>CafJ#+TnGqY#*JhM;K9b;W)CVnP5Iyz>3 zJuNdjI(o#(%Xk*xEL=7{2M`f%FxVY^7)DZQn(Pwc);Z=3Nd`^X`mk5i(^qS`L5Ef)%C$<%OOq0e&xM4`WQ?O_ z%%*9tG-G&K;||s-q#269B>Z05W4~DXB4@tEhnmDWi-<|d=NL#h`%8na{&}tIXL{Cs zS%n-{r&T)-#X8%C5mhq*fw`jvr2MZ*@=2_7dK;SF=%BjTSt!B1EhKLY){CJXmC8${kQsBrudG@x zYB465!uYtXFnvXdP7tGmbFAq8^%(N2cJs3$-%b_X0Yg!18oT4A_tUUXlD?eFK4`1f zco8}&^P^;Rhg#vOXcF2i_oSfeXyEL%P5q~Y(zdwJM$gIV`qK8G=2@0&YxxE*$a?f| zk2UE7H1gmb^hY%}UB9oCR>k)*2*d0Oyh6iZf7a>^FAJ_x7Jsiy$dw+W=m?vLHYI*Z z6~HfNoeXrffc7Sxziw@>Fwi^qMDIS5j!s78;*q1zqld!&Za%KUy81?UET6IP(9v-u>1*A(7cjCiZs2!m z=uPwbYVJ*wb^#3Gl((0`Sr_HYAusKpO>u?4NkX*uj%_h%mJ4r1<>&D^n(-^vJ-;LA z>isx(X(tqCqrWwII$mOudP&qv5lMfzK2XX40d)BLvAW!Tk**Ji#1F(^7PPixXh~16 z=$6>c(-h`?2K5)EAi3R(m(5T^0=_04+hP8iEZ3Z8r}73&D{zDQfzrC;F?#Oo6{9{S`U zplR5uc-dG(m!jKx^nz9gze^5N=4o+ZrFjdJo1IKZ2HF}355+&18t?Y2WcAk|X0SioIMkAR(SN)E7PD>MYTy*J;z z5Q7-(t4nCfHJpk(N`AcPgl2&+ys7HTO=76T!|nk~Ku~qb2(~i4H?QA#Rr!=?bk$_! z!S~HGUO?1MJH-dkXh7~;;bitB6Hhh#ax`baKlWGNV zkKE5#zqhXc#j|c7XqGmQ_AIMz5dCh6&WlhR*i7nXo z4SAmI4pKG4I&z7y%EI-^HL2u?B#}~$ptWFENaSAHSM6Z>g7*d-(6q1jvpW5OWgytOTthBG4ScLE|>m2oV3=M!mOX5!-c%Xft9?^0$6R{`rm4gj{q+ zgBtLaym4p54twZUCxKc$55?(?uXxy;@p>9AO8y}XHJgxFgI}TTBgIaJ<_1?*a2q2w z=m*Sx@*rHF)%(3liWe+m4hLDU->)kDqB~CO--%9uo&IGpg)GYL<3PA>M9LRtnolMv z3u!n37HAB_d?D$9UT&Dvu$8j?`0qLU2BKNxG26-$%lx9t&Hzd`_OzB0$YrEY0%1x_NTo$T_8|e~sO%JHAcKfo`a{H`|?qh9;aACVzZy_NnTN z5rGTgYW5AOT){MEsLp{1g{nkzAkuP_om{zUmrbz=Ef;)Ms?-o(mkT{0k)q;F!EW)` z^a#Ldv0H-|pRDB7npzTbyv@=&>dH0|N6mvw@?|qJx5y(K3=@)orgI%!W$3j*J|?LA zkH{U>DN%=gfa_N^zvx{(wr>C!#U9xe=*qSGvX3=mffM1{0Y=J%V|#*!3&Y}%fCS0B z_IpZ$rQ}pr?_$3ui!^T?s){kVb+3?eiW}h?t(@MmmyMlCT4e@DzPMT>8;*@HuqNg( zpCs36%iYkLER{$gaPwgc^_6h00Eg%vc-_g?50GcwFo)=T-R;Z-*s|!yhZ6Jg4{#G5 z+mA6^(tVQ*YvGSJI9GB&z_Egz0WjcKS6( zTm^Yj3OOeN=cREqCPH{CE(C>h#aK(W5YG)AgiPBT(B`qa!yNZPU z01X2P8qnlIvDbP}F>51c!u0k}S-@$PhnJM|WIHfQ)W=fIV{D5S^TUSZ(yYbrrvDa!ve;8&6bdb8Trh^W%>f2Uq35z`z)E{aeS!lvKFFp!1O~XWmn`YO6UP z{?!W<#Bg!Kd8MIiMa~+@sQ@@av=;}`YD5}$x67J_CCIU?0q9x4xXjR=-O7~dhK;qK zOC_|pLI=XH%CT9~B^IT1zzcY#w_EX7*jLG<%bD-R$#NUJ0S{Im%Z_o9IzAjyKV8@L zU1nH~Hl4kl@|BhDgT@D;>+BnD=mi$QDT46K+We2(LLE)=Q}r9P_`TxF+@v5UQoo|% zG3r%3jC(`8e(bimvC}d7wkPCHr#T0Y{ zux}hlXFhLm*5G9nu5Oh*e^XqW1Rt5$vhT{E%gERSxrOkv^K9s&vsn%#8@^qF4ZY~8 z3W|@f>CpK)HXtPz6Y#U0;C8H)onUfp+MMddo7h;*k3?;O_98_yb`LkzYEf%tfWeTq za{Gc0P-&fkk^C}az#dd6$)m(hXH5UQwyCemL2R&WnGil`e;@`Gz13PQ?sa_ly3|@omdr`fbnzV_fw1QedYEqkK&BLS)Q$SZ$4oV zuZ_l>_F5_ZSGv@AGk;E(_IiBg`){si>w?ZbPc<7pvy)N3&f@ntGgW|)R83ESwan@*8>RJ^ z&8)9myb+;Inm5dGqAKLm2JCAST3#1cJK=C6IMzem!c8D=rCO3|ZFfYBk@+j{P*8t@ z`Ze}W%hc?$DhN3>wQJiiuI8!uhW#(Ez0LDb1SxY+;BC$9Lovhdql~=oM+!%uPeM~Y zWX(w$ajXs@$sn5V=8Lttx>YT*$A7Fkm84j}AZGN1^7E^(*@%7ixg*bL+ytL5b>x$@ zDEV4xO3ea!KJqsRzHQbqiad0;C`{b6w`qD30ea{2-rffRAL*IotpN_-W8i2Z$hWk{ z+z;GeAwfPd_@SL40E6FNhyP5L%8K1jkFBbYyA{_DH|_61#)Vo{Gr3E4%!rv%ZL=ZX>JsDGZaMCF|Nd#l>mfux0fXbd8{(sVEUk_0 zujBPAj!C+&8hZyAH-C*1Z=pL*c`TO8V_HtuC@*i?X4WfY-?QspEJ^CUpV6mZ^S*ne zaY&jhJcndIU_J65H$L(*6*-}$==}Y@c#H!_wPoXDlan|bf(;oCN(=0o@F=;@6b>2z zZ7N4W0T8XR9dN4+!d?H!$q2FnPR9jz5gf-ZCRbf|vy_Gtv$+A*~g$SvulYSu; zuWGWC3U>E76j9oSyMHQ%6obh((+fB6(L$)(bGLv@KY)-D6;p9UVGH$wGEDt@+V5~c zfAlV@>K^9+V^3{8c5p z14}m$VzHgT&81o26wENPqN+_=eYr#cV*Aakt85VYV{HmDzo~ybF4FrP^oKL_l?p5Z zFy26Hgjq-MrsBdKYOR8L%Y z@8A2AyQjBy|C3S_hHw&|Rrj_;zWM!%b35&T_dFs74R(wLq(fHxb@Glx)fFEA(o=I~ z0LZs5IxEzqZB0Eya6si41IV@tM?do|y%+4xs;#~`=2sprz;m-}%8(7)1IhUDY8L~C zGa;UUTl~mZTiSm*8@I)icOqnAIqXW=UtH+1-spyqnOt!k&X}-r${^$C9Y#Y2#nf2$W#lyj^RXa zODK}h4<@liU@KJOu}$cmwYEPq(J9M|ma;pL`BlPLrQ(ubge{TJr8UNwBHa-`tA0}H zbX{VP$TVj|e4WAZn!9h-CU4ZG73!Jb4=eALTb%~GNU=LCNiVTZAMZ{E@`{LXYd{qVJtQ(1?IK0BLf0=_wMDJy8}}m^HU{fYy5mK&z#L^Z*VyWRK)Q! zq8%!%F{oLA@L)fZOh>$y;k}Fu2Rd-pfbbiw;0w`33W;F}J+2kHB4DAgVxh4oNH)g3 z{tTHV*<(Y^?wxkAT%Cs6|PMTbnrHX-clTlQauM{ z+`Bhy!6!E~9hP9?e@Xb$g5e8}Okr}L>AWUU45HFO56*izI@Iz))${Mh3SQt!c6`pjeWy{rUZxTmKcEZ(f5^ZE2aX^L1o`WmEy@4?>J=viV zS9R*IyOJ<@tfTG|4$ScHHXQVK3$OrwIOyM>{{Qy>Fy$YI{`XS; zams%v^bd;tPg4Maf7|dML;tsC|HqVn+@Ze|3cbJZPR~TDWp@_aQ}RWgTY2a1ZP@wi ns5V!!+J(RWko~{5D~Wdc{@H^+TEKFZCoFw!W34jHKcD{>dwR&= literal 0 HcmV?d00001 diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index ddf490c7a7a..549a3f1d334 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -70,6 +70,7 @@ --ds-footer-padding: 0; --ds-footer-padding-bottom: 0; --ds-footer-logo-height: 50px; + --ds-footer-n-coar-height: 20px; $home-news-link-color: $cyan; --ds-home-news-link-color: #{$home-news-link-color}; From c8a75fa3b1b872e3976d5a7b4a2452c67ee74130 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 28 Jul 2023 15:38:37 +0200 Subject: [PATCH 042/592] CST-11012 Added feature id --- src/app/core/data/feature-authorization/feature-id.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index 8fef45a9532..7119cfd5ad7 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -34,4 +34,5 @@ export enum FeatureID { CanEditItem = 'canEditItem', CanRegisterDOI = 'canRegisterDOI', CanSubscribe = 'canSubscribeDso', + CoarLdnEnabled = 'coarLdnEnabled' } From ec821392565737f768b0cd95917eade7e5ae6589 Mon Sep 17 00:00:00 2001 From: Francesco Bacchelli Date: Mon, 7 Aug 2023 14:26:42 +0200 Subject: [PATCH 043/592] 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 35b4b396a7b..42eb7e4b16a 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 @@

{{ (labelPrefix + label + '.select' | translate) }}

[disableHeader]="true" [hidePaginationDetail]="false" [selectionConfig]="{ repeatable: false, listId: entityListId }" - [showExport]="false" + [showCsvExport]="false" [linkType]="linkTypes.ExternalLink" [context]="context" (deselectObject)="deselectEntity()" From 36dfb69670aad003e35fd1aec889064f0234aca9 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Wed, 9 Aug 2023 10:10:00 +0200 Subject: [PATCH 044/592] CST-11012 notify info component updated --- .../notify-info/notify-info.component.html | 17 ++++++++----- .../notify-info/notify-info.component.ts | 24 ++++++++++++------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html index 3596acfc67e..fcd362562e5 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.html +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -4,13 +4,18 @@ {{ 'coar-notify-support.title' | translate }} -

{{ 'coar-notify-support.title' | translate }}

-

+ +

{{ 'coar-notify-support.title' | translate }}

+

-

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

-

+

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

+

-

{{ 'coar-notify-support.message-moderation.title' | translate }}

-

+

{{ 'coar-notify-support.message-moderation.title' | translate }}

+

+
+ +

Disabled

+
diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index a144f5d7468..1ec6dfedb41 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -1,18 +1,24 @@ import { Component, OnInit } from '@angular/core'; +import { AuthorizationDataService } from '../../data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../data/feature-authorization/feature-id'; @Component({ - selector: 'ds-notify-info', - templateUrl: './notify-info.component.html', - styleUrls: ['./notify-info.component.scss'] + selector: 'ds-notify-info', + templateUrl: './notify-info.component.html', + styleUrls: ['./notify-info.component.scss'] }) export class NotifyInfoComponent implements OnInit { - constructor() { - // - } + coarLdnEnabled: boolean; - ngOnInit(): void { - // - } + constructor( + private authorizationService: AuthorizationDataService, + ) { + } + ngOnInit() { + this.authorizationService.isAuthorized(FeatureID.CoarLdnEnabled).subscribe(enabled => { + this.coarLdnEnabled = enabled; + }); + } } From 2f9089d01328762d244879fe176a1d92986aacfb Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 11 Aug 2023 15:26:20 +0200 Subject: [PATCH 045/592] CST-11012 notify info component updated with guards and services (needs cleanup) --- .../notify-info/notify-info.component.html | 3 ++- .../notify-info/notify-info.component.ts | 18 +++++++------- .../notify-info/notify-info.guard.spec.ts | 16 +++++++++++++ .../notify-info/notify-info.guard.ts | 15 ++++++++++++ .../notify-info/notify-info.service.spec.ts | 16 +++++++++++++ .../notify-info/notify-info.service.ts | 24 +++++++++++++++++++ src/assets/i18n/en.json5 | 2 +- src/modules/app/browser-init.service.ts | 7 ++++++ 8 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts create mode 100644 src/app/core/coar-notify/notify-info/notify-info.guard.ts create mode 100644 src/app/core/coar-notify/notify-info/notify-info.service.spec.ts create mode 100644 src/app/core/coar-notify/notify-info/notify-info.service.ts diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html index fcd362562e5..8552eec83b0 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.html +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -5,6 +5,7 @@ +

{{coarLdnEnabled}}{{coarLdnEnabled | json}}

{{ 'coar-notify-support.title' | translate }}

@@ -15,7 +16,7 @@

{{ 'coar-notify-support.message-moderation.title' | translate }}

-

Disabled

+

Disabled {{coarLdnEnabled}}{{coarLdnEnabled | json}}

diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index 1ec6dfedb41..c8ed8617386 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { AuthorizationDataService } from '../../data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../data/feature-authorization/feature-id'; +import { NotifyInfoService } from './notify-info.service'; + @Component({ selector: 'ds-notify-info', @@ -12,13 +12,13 @@ export class NotifyInfoComponent implements OnInit { coarLdnEnabled: boolean; constructor( - private authorizationService: AuthorizationDataService, - ) { - } + public notifyInfoService: NotifyInfoService, + ) { } ngOnInit() { - this.authorizationService.isAuthorized(FeatureID.CoarLdnEnabled).subscribe(enabled => { - this.coarLdnEnabled = enabled; - }); - } + this.coarLdnEnabled = this.notifyInfoService.isCoarConfigEnabled(); + console.log(this.coarLdnEnabled); + } + } + diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts new file mode 100644 index 00000000000..789140ebe45 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { NotifyInfoGuard } from './notify-info.guard'; + +describe('NotifyInfoGuard', () => { + let guard: NotifyInfoGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(NotifyInfoGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.ts new file mode 100644 index 00000000000..6a920a090bc --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class NotifyInfoGuard implements CanActivate { + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + return true; + } + +} diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts new file mode 100644 index 00000000000..b32d590cd69 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { NotifyInfoService } from './notify-info.service'; + +describe('NotifyInfoService', () => { + let service: NotifyInfoService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(NotifyInfoService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts new file mode 100644 index 00000000000..3651c04e937 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { getFirstSucceededRemoteData } from '../../shared/operators'; +import { ConfigurationDataService } from '../../data/configuration-data.service'; + + +@Injectable({ + providedIn: 'root' +}) +export class NotifyInfoService { + + constructor( + private configService: ConfigurationDataService, + ) { + } + + isCoarConfigEnabled(): boolean { + this.configService.findByPropertyName('coar-notify.enabled').pipe( + getFirstSucceededRemoteData() + ); + if (!getFirstSucceededRemoteData()) { + return true; + } + } +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 9d72aec64f4..9cd1519363d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -877,7 +877,7 @@ "coar-notify-support.message-moderation.title": "Message Moderation", - "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking here.", + "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking here.", diff --git a/src/modules/app/browser-init.service.ts b/src/modules/app/browser-init.service.ts index 61d57f10f98..3d03e015c55 100644 --- a/src/modules/app/browser-init.service.ts +++ b/src/modules/app/browser-init.service.ts @@ -32,6 +32,7 @@ import { logStartupMessage } from '../../../startup-message'; import { MenuService } from '../../app/shared/menu/menu.service'; import { RootDataService } from '../../app/core/data/root-data.service'; import { firstValueFrom, Subscription } from 'rxjs'; +import { NotifyInfoService } from '../../app/core/coar-notify/notify-info/notify-info.service'; /** * Performs client-side initialization. @@ -50,6 +51,7 @@ export class BrowserInitService extends InitService { protected localeService: LocaleService, protected angulartics2DSpace: Angulartics2DSpace, protected googleAnalyticsService: GoogleAnalyticsService, + protected notifyInfoService: NotifyInfoService, protected metadata: MetadataService, protected breadcrumbsService: BreadcrumbsService, protected klaroService: KlaroService, @@ -95,6 +97,7 @@ export class BrowserInitService extends InitService { this.initI18n(); this.initAngulartics(); this.initGoogleAnalytics(); + this.retrieveCoarConfig(); this.initRouteListeners(); this.themeService.listenForThemeChanges(true); this.trackAuthTokenExpiration(); @@ -142,6 +145,10 @@ export class BrowserInitService extends InitService { this.googleAnalyticsService.addTrackingIdToPage(); } + protected retrieveCoarConfig() { + this.notifyInfoService.isCoarConfigEnabled(); + } + /** * During an external authentication flow invalidate the SSR transferState * data in the cache. This allows the app to fetch fresh content. From 8271803f0ab1df953eeb8a7faabb7e3672f84edd Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Thu, 17 Aug 2023 15:57:34 +0200 Subject: [PATCH 046/592] CST-11012 Notify info component has been completed with working guard and service --- .../notify-info/notify-info.component.html | 18 ++++-------- .../notify-info/notify-info.component.ts | 9 +++--- .../notify-info/notify-info.guard.ts | 29 ++++++++++++++----- .../notify-info/notify-info.service.ts | 27 ++++++++--------- src/app/footer/footer.component.html | 6 ++-- src/app/footer/footer.component.ts | 10 ++++++- src/app/info/info-routing.module.ts | 4 +-- src/modules/app/browser-init.service.ts | 8 ----- 8 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html index 8552eec83b0..3596acfc67e 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.html +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -4,19 +4,13 @@ {{ 'coar-notify-support.title' | translate }} - -

{{coarLdnEnabled}}{{coarLdnEnabled | json}}

-

{{ 'coar-notify-support.title' | translate }}

-

+

{{ 'coar-notify-support.title' | translate }}

+

-

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

-

+

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

+

-

{{ 'coar-notify-support.message-moderation.title' | translate }}

-

-
- -

Disabled {{coarLdnEnabled}}{{coarLdnEnabled | json}}

-
+

{{ 'coar-notify-support.message-moderation.title' | translate }}

+

diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index c8ed8617386..9c8f48218dc 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -1,7 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { NotifyInfoService } from './notify-info.service'; - @Component({ selector: 'ds-notify-info', templateUrl: './notify-info.component.html', @@ -16,9 +15,9 @@ export class NotifyInfoComponent implements OnInit { ) { } ngOnInit() { - this.coarLdnEnabled = this.notifyInfoService.isCoarConfigEnabled(); - console.log(this.coarLdnEnabled); - } + this.notifyInfoService.isCoarConfigEnabled().subscribe(value => { + this.coarLdnEnabled = value; + }); + } } - diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.ts index 6a920a090bc..4da9a42f21e 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.guard.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.ts @@ -1,15 +1,30 @@ import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; +import { NotifyInfoService } from './notify-info.service'; +import { map } from 'rxjs/operators'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class NotifyInfoGuard implements CanActivate { - canActivate( - route: ActivatedRouteSnapshot, - state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { - return true; - } + constructor( + private notifyInfoService: NotifyInfoService, + private router: Router + ) {} + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable | Promise | boolean | UrlTree { + return this.notifyInfoService.isCoarConfigEnabled().pipe( + map(coarLdnEnabled => { + if (coarLdnEnabled) { + return true; + } else { + return this.router.parseUrl('/404'); + } + }) + ); + } } diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts index 3651c04e937..6183a1fb309 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -1,24 +1,25 @@ import { Injectable } from '@angular/core'; import { getFirstSucceededRemoteData } from '../../shared/operators'; import { ConfigurationDataService } from '../../data/configuration-data.service'; - +import { map, Observable } from 'rxjs'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class NotifyInfoService { - constructor( - private configService: ConfigurationDataService, - ) { - } + constructor( + private configService: ConfigurationDataService, + ) {} - isCoarConfigEnabled(): boolean { - this.configService.findByPropertyName('coar-notify.enabled').pipe( - getFirstSucceededRemoteData() - ); - if (!getFirstSucceededRemoteData()) { - return true; + isCoarConfigEnabled(): Observable { + return this.configService.findByPropertyName('coar-notify.enabled').pipe( + getFirstSucceededRemoteData(), + map(response => { + const booleanArrayValue = response.payload.values; + const coarConfigEnabled = booleanArrayValue.length > 0 ? booleanArrayValue[0] === 'true' : false; + return coarConfigEnabled; + }) + ); } - } } diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 5a77d98269a..1c4b95c557c 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -81,10 +81,10 @@
Footer Content
- diff --git a/src/app/footer/footer.component.ts b/src/app/footer/footer.component.ts index c4195c8eb3d..4b04a8f5dc2 100644 --- a/src/app/footer/footer.component.ts +++ b/src/app/footer/footer.component.ts @@ -2,6 +2,7 @@ import { Component, Optional } from '@angular/core'; import { hasValue } from '../shared/empty.util'; import { KlaroService } from '../shared/cookies/klaro.service'; import { environment } from '../../environments/environment'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; @Component({ selector: 'ds-footer', @@ -17,8 +18,15 @@ export class FooterComponent { showTopFooter = false; showPrivacyPolicy = environment.info.enablePrivacyStatement; showEndUserAgreement = environment.info.enableEndUserAgreement; + coarLdnEnabled: boolean; // Add this line - constructor(@Optional() private cookies: KlaroService) { + constructor( + @Optional() private cookies: KlaroService, + private notifyInfoService: NotifyInfoService + ) { + this.notifyInfoService.isCoarConfigEnabled().subscribe(coarLdnEnabled => { + this.coarLdnEnabled = coarLdnEnabled; + }); } showCookieSettings() { diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index 9734fa46273..40859245670 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -9,6 +9,7 @@ import { FeedbackGuard } from '../core/feedback/feedback.guard'; import { environment } from '../../environments/environment'; import { COAR_NOTIFY_SUPPORT } from '../app-routing-paths'; import { NotifyInfoComponent } from '../core/coar-notify/notify-info/notify-info.component'; +import { NotifyInfoGuard } from '../core/coar-notify/notify-info/notify-info.guard'; const imports = [ @@ -27,8 +28,7 @@ const imports = [ component: NotifyInfoComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'info.coar-notify-support.title', breadcrumbKey: 'info.coar-notify-support' }, - // TODO: create authGuard for COAR_NOTIFY - // canActivate: [FeedbackGuard] + canActivate: [NotifyInfoGuard] } ]) ]; diff --git a/src/modules/app/browser-init.service.ts b/src/modules/app/browser-init.service.ts index 3d03e015c55..9e8da43557d 100644 --- a/src/modules/app/browser-init.service.ts +++ b/src/modules/app/browser-init.service.ts @@ -32,8 +32,6 @@ import { logStartupMessage } from '../../../startup-message'; import { MenuService } from '../../app/shared/menu/menu.service'; import { RootDataService } from '../../app/core/data/root-data.service'; import { firstValueFrom, Subscription } from 'rxjs'; -import { NotifyInfoService } from '../../app/core/coar-notify/notify-info/notify-info.service'; - /** * Performs client-side initialization. */ @@ -51,7 +49,6 @@ export class BrowserInitService extends InitService { protected localeService: LocaleService, protected angulartics2DSpace: Angulartics2DSpace, protected googleAnalyticsService: GoogleAnalyticsService, - protected notifyInfoService: NotifyInfoService, protected metadata: MetadataService, protected breadcrumbsService: BreadcrumbsService, protected klaroService: KlaroService, @@ -97,7 +94,6 @@ export class BrowserInitService extends InitService { this.initI18n(); this.initAngulartics(); this.initGoogleAnalytics(); - this.retrieveCoarConfig(); this.initRouteListeners(); this.themeService.listenForThemeChanges(true); this.trackAuthTokenExpiration(); @@ -145,10 +141,6 @@ export class BrowserInitService extends InitService { this.googleAnalyticsService.addTrackingIdToPage(); } - protected retrieveCoarConfig() { - this.notifyInfoService.isCoarConfigEnabled(); - } - /** * During an external authentication flow invalidate the SSR transferState * data in the cache. This allows the app to fetch fresh content. From 78d0bdd336f65204bafca66f1c1734f62906a042 Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Fri, 18 Aug 2023 14:18:41 +0200 Subject: [PATCH 047/592] 104938 Implementation and tests (WIP) --- ...llection-source-controls.component.spec.ts | 8 +- .../collection-source-controls.component.ts | 192 +++++++++++------- .../processes/process-data.service.spec.ts | 113 +++++++++++ .../data/processes/process-data.service.ts | 44 +++- .../detail/process-detail.component.spec.ts | 124 +++++------ .../detail/process-detail.component.ts | 139 +++++++------ 6 files changed, 417 insertions(+), 203 deletions(-) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts index 3eb83ebe8ac..37a5d8642de 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts @@ -88,7 +88,7 @@ describe('CollectionSourceControlsComponent', () => { invoke: createSuccessfulRemoteDataObject$(process), }); processDataService = jasmine.createSpyObj('processDataService', { - findById: createSuccessfulRemoteDataObject$(process), + notifyOnCompletion: createSuccessfulRemoteDataObject$(process), }); bitstreamService = jasmine.createSpyObj('bitstreamService', { findByHref: createSuccessfulRemoteDataObject$(bitstream), @@ -137,7 +137,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-i', value: new ContentSourceSetSerializer().Serialize(contentSource.oaiSetId)}, ], []); - expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false); + expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); expect(bitstreamService.findByHref).toHaveBeenCalledWith(process._links.output.href); expect(notificationsService.info).toHaveBeenCalledWith(jasmine.anything() as any, 'Script text'); }); @@ -151,7 +151,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-r', value: null}, {name: '-c', value: collection.uuid}, ], []); - expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false); + expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); expect(notificationsService.success).toHaveBeenCalled(); }); }); @@ -164,7 +164,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-o', value: null}, {name: '-c', value: collection.uuid}, ], []); - expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false); + expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); expect(notificationsService.success).toHaveBeenCalled(); }); }); diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts index 7113c25e9f6..e8c3666da08 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts @@ -95,36 +95,55 @@ export class CollectionSourceControlsComponent implements OnDestroy { }), // filter out responses that aren't successful since the pinging of the process only needs to happen when the invocation was successful. filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)), - getAllCompletedRemoteData(), - filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - map((rd) => rd.payload), - hasValueOperator(), + switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + map((rd) => rd.payload) ).subscribe((process: Process) => { - if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // Ping the current process state every 5s - setTimeout(() => { - this.requestService.setStaleByHrefSubstring(process._links.self.href); - }, 5000); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed')); - this.testConfigRunning$.next(false); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => { - this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => { - const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1') - .replaceAll('The script has started', '') - .replaceAll('The script has completed', ''); - this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output); - }); + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed')); + this.testConfigRunning$.next(false); + } + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => { + this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => { + const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1') + .replaceAll('The script has started', '') + .replaceAll('The script has completed', ''); + this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output); }); - this.testConfigRunning$.next(false); - } + }); + this.testConfigRunning$.next(false); } - )); + })); + + // getAllCompletedRemoteData(), + // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), + // map((rd) => rd.payload), + // hasValueOperator(), + // ).subscribe((process: Process) => { + // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && + // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { + // // Ping the current process state every 5s + // setTimeout(() => { + // this.requestService.setStaleByHrefSubstring(process._links.self.href); + // }, 5000); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + // this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed')); + // this.testConfigRunning$.next(false); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + // this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => { + // this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => { + // const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1') + // .replaceAll('The script has started', '') + // .replaceAll('The script has completed', ''); + // this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output); + // }); + // }); + // this.testConfigRunning$.next(false); + // } + // } + // )); } /** @@ -147,31 +166,44 @@ export class CollectionSourceControlsComponent implements OnDestroy { } }), filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)), - getAllCompletedRemoteData(), - filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - map((rd) => rd.payload), - hasValueOperator(), + switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + map((rd) => rd.payload) ).subscribe((process) => { - if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // Ping the current process state every 5s - setTimeout(() => { - this.requestService.setStaleByHrefSubstring(process._links.self.href); - this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - }, 5000); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed')); - this.importRunning$.next(false); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed')); - this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - this.importRunning$.next(false); - } + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed')); + this.importRunning$.next(false); + } + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed')); + this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + this.importRunning$.next(false); } - )); + })); + + // getAllCompletedRemoteData(), + // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), + // map((rd) => rd.payload), + // hasValueOperator(), + // ).subscribe((process) => { + // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && + // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { + // // Ping the current process state every 5s + // setTimeout(() => { + // this.requestService.setStaleByHrefSubstring(process._links.self.href); + // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + // }, 5000); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + // this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed')); + // this.importRunning$.next(false); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + // this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed')); + // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + // this.importRunning$.next(false); + // } + // } + // )); } /** @@ -194,31 +226,45 @@ export class CollectionSourceControlsComponent implements OnDestroy { } }), filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)), - getAllCompletedRemoteData(), - filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - map((rd) => rd.payload), - hasValueOperator(), + switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + map((rd) => rd.payload) ).subscribe((process) => { - if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // Ping the current process state every 5s - setTimeout(() => { - this.requestService.setStaleByHrefSubstring(process._links.self.href); - this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - }, 5000); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed')); - this.reImportRunning$.next(false); - } - if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed')); - this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - this.reImportRunning$.next(false); - } + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed')); + this.reImportRunning$.next(false); } - )); + if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed')); + this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + this.reImportRunning$.next(false); + } + })); + + // switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)), + // getAllCompletedRemoteData(), + // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), + // map((rd) => rd.payload), + // hasValueOperator(), + // ).subscribe((process) => { + // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && + // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { + // // Ping the current process state every 5s + // setTimeout(() => { + // this.requestService.setStaleByHrefSubstring(process._links.self.href); + // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + // }, 5000); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { + // this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed')); + // this.reImportRunning$.next(false); + // } + // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { + // this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed')); + // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + // this.reImportRunning$.next(false); + // } + // } + // )); } ngOnDestroy(): void { diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index 88e5bd57915..6e7ce515027 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -9,6 +9,21 @@ import { testFindAllDataImplementation } from '../base/find-all-data.spec'; import { ProcessDataService } from './process-data.service'; import { testDeleteDataImplementation } from '../base/delete-data.spec'; +import { cold } from 'jasmine-marbles'; +import { waitForAsync, TestBed } from '@angular/core/testing'; +import { RequestService } from '../request.service'; +import { RemoteData } from '../remote-data'; +import { RequestEntryState } from '../request-entry-state.model'; +import { Process } from '../../../process-page/processes/process.model'; +import { ProcessStatus } from '../../../process-page/processes/process-status.model'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { CoreModule } from '../../core.module'; +import { ReducerManager } from '@ngrx/store'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { DSOChangeAnalyzer } from '../dso-change-analyzer.service'; +import { BitstreamFormatDataService } from '../bitstream-format-data.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; describe('ProcessDataService', () => { describe('composition', () => { @@ -16,4 +31,102 @@ describe('ProcessDataService', () => { testFindAllDataImplementation(initService); testDeleteDataImplementation(initService); }); + + let requestService; + let processDataService; + let remoteDataBuildService; + + describe('notifyOnCompletion', () => { + beforeEach(waitForAsync(() => { + requestService = jasmine.createSpyObj('requestService', ['setStaleByHrefSubstring']); + + TestBed.configureTestingModule({ + imports: [], + providers: [ + ProcessDataService, + { provide: RequestService, useValue: requestService }, + { provide: RemoteDataBuildService, useValue: null }, + { provide: ObjectCacheService, useValue: null }, + { provide: ReducerManager, useValue: null }, + { provide: HALEndpointService, useValue: null }, + { provide: DSOChangeAnalyzer, useValue: null }, + { provide: BitstreamFormatDataService, useValue: null }, + { provide: NotificationsService, useValue: null }, + ] + }); + + processDataService = TestBed.inject(ProcessDataService); + })); + + it('TODO', () => { + let completedProcess = new Process(); + completedProcess.processStatus = ProcessStatus.COMPLETED; + + spyOn(processDataService, 'findById').and.returnValue( + cold('(c|)', { + 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + }) + ); + + let process$ = processDataService.notifyOnCompletion('instantly'); + process$.subscribe((rd) => { + expect(processDataService.findById).toHaveBeenCalledTimes(1); + expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalled(); + }); + expect(process$).toBeObservable(cold('(c|)', { + 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + })); + }); + + // it('TODO2', () => { + // let completedProcess = new Process(); + // completedProcess.processStatus = ProcessStatus.COMPLETED; + + // spyOn(processDataService, 'findById').and.returnValue( + // cold('p 150ms (c|)', { + // 'p': new RemoteData(0, 0, 0, RequestEntryState., null, completedProcess), + // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + // }) + // ); + + // let process$ = processDataService.notifyOnCompletion('foo', 100); + // expect(process$).toBeObservable(cold('---(c|)', { + // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + // })); + // process$.subscribe((rd) => { + // expect(processDataService.findById).toHaveBeenCalledTimes(1); + // expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalled(); + // }); + // }); + }); + }); + +// /** +// * Tests whether calls to `FindAllData` methods are correctly patched through in a concrete data service that implements it +// */ +// export function testFindAllDataImplementation(serviceFactory: () => FindAllData) { +// let service; +// +// describe('FindAllData implementation', () => { +// const OPTIONS = Object.assign(new FindListOptions(), { elementsPerPage: 10, currentPage: 3 }); +// const FOLLOWLINKS = [ +// followLink('test'), +// followLink('something'), +// ]; +// +// beforeAll(() => { +// service = serviceFactory(); +// (service as any).findAllData = jasmine.createSpyObj('findAllData', { +// findAll: 'TEST findAll', +// }); +// }); +// +// it('should handle calls to findAll', () => { +// const out: any = service.findAll(OPTIONS, false, true, ...FOLLOWLINKS); +// +// expect((service as any).findAllData.findAll).toHaveBeenCalledWith(OPTIONS, false, true, ...FOLLOWLINKS); +// expect(out).toBe('TEST findAll'); +// }); +// }); +// } diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index 3bf34eb650d..f550407a59a 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -6,25 +6,28 @@ import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { Process } from '../../../process-page/processes/process.model'; import { PROCESS } from '../../../process-page/processes/process.resource-type'; import { Observable } from 'rxjs'; -import { switchMap } from 'rxjs/operators'; +import { switchMap, filter, take } from 'rxjs/operators'; import { PaginatedList } from '../paginated-list.model'; import { Bitstream } from '../../shared/bitstream.model'; import { RemoteData } from '../remote-data'; import { BitstreamDataService } from '../bitstream-data.service'; import { IdentifiableDataService } from '../base/identifiable-data.service'; -import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { FollowLinkConfig, followLink } from '../../../shared/utils/follow-link-config.model'; import { FindAllData, FindAllDataImpl } from '../base/find-all-data'; import { FindListOptions } from '../find-list-options.model'; import { dataService } from '../base/data-service.decorator'; import { DeleteData, DeleteDataImpl } from '../base/delete-data'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { NoContent } from '../../shared/NoContent.model'; +import { getAllCompletedRemoteData } from '../../shared/operators'; +import { ProcessStatus } from 'src/app/process-page/processes/process-status.model'; @Injectable() @dataService(PROCESS) export class ProcessDataService extends IdentifiableDataService implements FindAllData, DeleteData { private findAllData: FindAllData; private deleteData: DeleteData; + protected activelyBeingPolled: Set = new Set(); constructor( protected requestService: RequestService, @@ -101,4 +104,41 @@ export class ProcessDataService extends IdentifiableDataService impleme public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { return this.deleteData.deleteByHref(href, copyVirtualMetadata); } + + // TODO + public notifyOnCompletion(processId: string, pollingIntervalInMs = 5000): Observable> { + const process$ = this.findById(processId, false, true, followLink('script')) + .pipe( + getAllCompletedRemoteData(), + ); + + // TODO: this is horrible + const statusIs = (process: Process, status: ProcessStatus) => + process.processStatus === status; + + // If we have to wait too long for the result, we should mark the result as stale. + // However, we should make sure this happens only once (in case there are multiple observers waiting + // for the result). + if (!this.activelyBeingPolled.has(processId)) { + this.activelyBeingPolled.add(processId); + + // Create a subscription that marks the data as stale if the polling interval time has been exceeded. + const sub = process$.subscribe((rd) => { + const process = rd.payload; + if (statusIs(process, ProcessStatus.COMPLETED) || statusIs(process, ProcessStatus.FAILED)) { + this.activelyBeingPolled.delete(processId); + sub.unsubscribe(); + } else { + setTimeout(() => { + this.requestService.setStaleByHrefSubstring(process._links.self.href); + }, pollingIntervalInMs); + } + }); + } + + return process$.pipe( + filter(rd => statusIs(rd.payload, ProcessStatus.COMPLETED) || statusIs(rd.payload, ProcessStatus.FAILED)), + take(1) + ); + } } diff --git a/src/app/process-page/detail/process-detail.component.spec.ts b/src/app/process-page/detail/process-detail.component.spec.ts index 9552f9a092a..68b97d0e5cd 100644 --- a/src/app/process-page/detail/process-detail.component.spec.ts +++ b/src/app/process-page/detail/process-detail.component.spec.ts @@ -273,92 +273,92 @@ describe('ProcessDetailComponent', () => { }); }); - describe('refresh counter', () => { - const queryRefreshCounter = () => fixture.debugElement.query(By.css('.refresh-counter')); + // describe('refresh counter', () => { + // const queryRefreshCounter = () => fixture.debugElement.query(By.css('.refresh-counter')); - describe('if process is completed', () => { - beforeEach(() => { - process.processStatus = ProcessStatus.COMPLETED; - route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); - }); + // describe('if process is completed', () => { + // beforeEach(() => { + // process.processStatus = ProcessStatus.COMPLETED; + // route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); + // }); - it('should not show', () => { - spyOn(component, 'startRefreshTimer'); + // it('should not show', () => { + // spyOn(component, 'startRefreshTimer'); - const refreshCounter = queryRefreshCounter(); - expect(refreshCounter).toBeNull(); + // const refreshCounter = queryRefreshCounter(); + // expect(refreshCounter).toBeNull(); - expect(component.startRefreshTimer).not.toHaveBeenCalled(); - }); - }); + // expect(component.startRefreshTimer).not.toHaveBeenCalled(); + // }); + // }); - describe('if process is not finished', () => { - beforeEach(() => { - process.processStatus = ProcessStatus.RUNNING; - route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); - fixture.detectChanges(); - component.stopRefreshTimer(); - }); + // describe('if process is not finished', () => { + // beforeEach(() => { + // process.processStatus = ProcessStatus.RUNNING; + // route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); + // fixture.detectChanges(); + // component.stopRefreshTimer(); + // }); - it('should call startRefreshTimer', () => { - spyOn(component, 'startRefreshTimer'); + // it('should call startRefreshTimer', () => { + // spyOn(component, 'startRefreshTimer'); - component.ngOnInit(); - fixture.detectChanges(); // subscribe to process observable with async pipe + // component.ngOnInit(); + // fixture.detectChanges(); // subscribe to process observable with async pipe - expect(component.startRefreshTimer).toHaveBeenCalled(); - }); + // expect(component.startRefreshTimer).toHaveBeenCalled(); + // }); - it('should call refresh method every 5 seconds, until process is completed', fakeAsync(() => { - spyOn(component, 'refresh'); - spyOn(component, 'stopRefreshTimer'); + // it('should call refresh method every 5 seconds, until process is completed', fakeAsync(() => { + // spyOn(component, 'refresh'); + // spyOn(component, 'stopRefreshTimer'); - process.processStatus = ProcessStatus.COMPLETED; - // set findbyId to return a completed process - (processService.findById as jasmine.Spy).and.returnValue(observableOf(createSuccessfulRemoteDataObject(process))); + // process.processStatus = ProcessStatus.COMPLETED; + // // set findbyId to return a completed process + // (processService.findById as jasmine.Spy).and.returnValue(observableOf(createSuccessfulRemoteDataObject(process))); - component.ngOnInit(); - fixture.detectChanges(); // subscribe to process observable with async pipe + // component.ngOnInit(); + // fixture.detectChanges(); // subscribe to process observable with async pipe - expect(component.refresh).not.toHaveBeenCalled(); + // expect(component.refresh).not.toHaveBeenCalled(); - expect(component.refreshCounter$.value).toBe(0); + // expect(component.refreshCounter$.value).toBe(0); - tick(1001); // 1 second + 1 ms by the setTimeout - expect(component.refreshCounter$.value).toBe(5); // 5 - 0 + // tick(1001); // 1 second + 1 ms by the setTimeout + // expect(component.refreshCounter$.value).toBe(5); // 5 - 0 - tick(2001); // 2 seconds + 1 ms by the setTimeout - expect(component.refreshCounter$.value).toBe(3); // 5 - 2 + // tick(2001); // 2 seconds + 1 ms by the setTimeout + // expect(component.refreshCounter$.value).toBe(3); // 5 - 2 - tick(2001); // 2 seconds + 1 ms by the setTimeout - expect(component.refreshCounter$.value).toBe(1); // 3 - 2 + // tick(2001); // 2 seconds + 1 ms by the setTimeout + // expect(component.refreshCounter$.value).toBe(1); // 3 - 2 - tick(1001); // 1 second + 1 ms by the setTimeout - expect(component.refreshCounter$.value).toBe(0); // 1 - 1 + // tick(1001); // 1 second + 1 ms by the setTimeout + // expect(component.refreshCounter$.value).toBe(0); // 1 - 1 - tick(1000); // 1 second + // tick(1000); // 1 second - expect(component.refresh).toHaveBeenCalledTimes(1); - expect(component.stopRefreshTimer).toHaveBeenCalled(); + // expect(component.refresh).toHaveBeenCalledTimes(1); + // expect(component.stopRefreshTimer).toHaveBeenCalled(); - expect(component.refreshCounter$.value).toBe(0); + // expect(component.refreshCounter$.value).toBe(0); - tick(1001); // 1 second + 1 ms by the setTimeout - // startRefreshTimer not called again - expect(component.refreshCounter$.value).toBe(0); + // tick(1001); // 1 second + 1 ms by the setTimeout + // // startRefreshTimer not called again + // expect(component.refreshCounter$.value).toBe(0); - discardPeriodicTasks(); // discard any periodic tasks that have not yet executed - })); + // discardPeriodicTasks(); // discard any periodic tasks that have not yet executed + // })); - it('should show if refreshCounter is different from 0', () => { - component.refreshCounter$.next(1); - fixture.detectChanges(); + // it('should show if refreshCounter is different from 0', () => { + // component.refreshCounter$.next(1); + // fixture.detectChanges(); - const refreshCounter = queryRefreshCounter(); - expect(refreshCounter).not.toBeNull(); - }); + // const refreshCounter = queryRefreshCounter(); + // expect(refreshCounter).not.toBeNull(); + // }); - }); + // }); - }); + // }); }); diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index a379dfe3376..18992eae2f3 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -1,7 +1,7 @@ import { HttpClient } from '@angular/common/http'; -import { Component, Inject, NgZone, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; +import { Component, Inject, NgZone, OnInit, PLATFORM_ID } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject, interval, Observable, shareReplay, Subscription } from 'rxjs'; +import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { finalize, map, switchMap, take, tap } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; @@ -26,8 +26,6 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { getProcessListRoute } from '../process-page-routing.paths'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { followLink } from '../../shared/utils/follow-link-config.model'; -import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'ds-process-detail', @@ -36,7 +34,7 @@ import { isPlatformBrowser } from '@angular/common'; /** * A component displaying detailed information about a DSpace Process */ -export class ProcessDetailComponent implements OnInit, OnDestroy { +export class ProcessDetailComponent implements OnInit { /** * The AlertType enumeration @@ -107,18 +105,22 @@ export class ProcessDetailComponent implements OnInit, OnDestroy { * Display a 404 if the process doesn't exist */ ngOnInit(): void { - this.processRD$ = this.route.data.pipe( - map((data) => { - if (isPlatformBrowser(this.platformId)) { - if (!this.isProcessFinished(data.process.payload)) { - this.startRefreshTimer(); - } - } + // this.processRD$ = this.route.data.pipe( + // map((data) => { + // if (isPlatformBrowser(this.platformId)) { + // if (!this.isProcessFinished(data.process.payload)) { + // this.startRefreshTimer(); + // } + // } - return data.process as RemoteData; - }), - redirectOn4xx(this.router, this.authService), - shareReplay(1) + // return data.process as RemoteData; + // }), + // redirectOn4xx(this.router, this.authService), + // shareReplay(1) + // ); + + this.processRD$ = this.processService.notifyOnCompletion(this.route.snapshot.params.id).pipe( + redirectOn4xx(this.router, this.authService) ); this.filesRD$ = this.processRD$.pipe( @@ -127,52 +129,69 @@ export class ProcessDetailComponent implements OnInit, OnDestroy { ); } - refresh() { - this.processRD$ = this.processService.findById( - this.route.snapshot.params.id, - false, - true, - followLink('script') - ).pipe( - getFirstSucceededRemoteData(), - redirectOn4xx(this.router, this.authService), - tap((processRemoteData: RemoteData) => { - if (!this.isProcessFinished(processRemoteData.payload)) { - this.startRefreshTimer(); - } - }), - shareReplay(1) - ); + // refresh() { - this.filesRD$ = this.processRD$.pipe( - getFirstSucceededRemoteDataPayload(), - switchMap((process: Process) => this.processService.getFiles(process.processId)) - ); - } + //////////////////////////////////////////////////////////////////////////////// - startRefreshTimer() { - this.refreshCounter$.next(0); + // this.processRD$ = this.processService.findById( + // this.route.snapshot.params.id, + // false, + // true, + // followLink('script') + // ).pipe( + // // First get the process state + // getFirstSucceededRemoteData(), - this.refreshTimerSub = interval(1000).subscribe( - value => { - if (value > 5) { - setTimeout(() => { - this.refresh(); - this.stopRefreshTimer(); - this.refreshCounter$.next(0); - }, 1); - } else { - this.refreshCounter$.next(5 - value); - } - }); - } + // // Error if it goes wrong + // redirectOn4xx(this.router, this.authService), - stopRefreshTimer() { - if (hasValue(this.refreshTimerSub)) { - this.refreshTimerSub.unsubscribe(); - this.refreshTimerSub = undefined; - } - } + // // If process is not finished, start the refresh timer + // tap((processRemoteData: RemoteData) => { + // if (!this.isProcessFinished(processRemoteData.payload)) { + // this.startRefreshTimer(); + // } + // }), + + // // ??? + // shareReplay(1) + // ); + // this.filesRD$ = this.processRD$.pipe( + // getFirstSucceededRemoteDataPayload(), + // switchMap((process: Process) => this.processService.getFiles(process.processId)) + // ); + // } + + // // TODO delete + // // call refresh after 5 sec + // startRefreshTimer() { + // this.refreshCounter$.next(0); + // + // // TODO delete comment + // // This fires every 1000 ms with an incrementing value. + // // So the first time this fires, it adds the value 5 to the refresh counter + // // the second time, it adds the value 4, + // // etc. + // // If the value exceeds 5, the refresh timer is stopped and this.refresh is called. + // this.refreshTimerSub = interval(1000).subscribe( + // value => { + // if (value > 5) { + // setTimeout(() => { + // this.refresh(); + // this.stopRefreshTimer(); + // this.refreshCounter$.next(0); + // }, 1); + // } else { + // this.refreshCounter$.next(5 - value); + // } + // }); + // } + // + // stopRefreshTimer() { + // if (hasValue(this.refreshTimerSub)) { + // this.refreshTimerSub.unsubscribe(); + // this.refreshTimerSub = undefined; + // } + // } /** * Get the name of a bitstream @@ -276,8 +295,4 @@ export class ProcessDetailComponent implements OnInit, OnDestroy { closeModal() { this.modalRef.close(); } - - ngOnDestroy(): void { - this.stopRefreshTimer(); - } } From 9b556fd7039449c9b8a762cb335f0b1b813001da Mon Sep 17 00:00:00 2001 From: Francesco Bacchelli Date: Tue, 22 Aug 2023 11:16:30 +0200 Subject: [PATCH 048/592] Merge branch CST-5249_suggestion of https://github.com/4Science/DSpace into CST-11299 --- .../builders/remote-data-build.service.ts | 1 + src/app/core/core.module.ts | 6 +- .../suggestion-objects.resource-type.ts | 16 ----- .../suggestion-source-object.resource-type.ts | 9 +++ .../models/suggestion-source.model.ts | 2 +- .../suggestion-target-object.resource-type.ts | 9 +++ .../models/suggestion-target.model.ts | 2 +- .../source/suggestion-source-data.service.ts | 2 +- .../suggestions-data.service.ts | 4 +- .../target/suggestion-target-data.service.ts | 3 +- src/app/home-page/home-page.component.html | 1 + src/app/home-page/home-page.module.ts | 18 ++--- src/app/menu.resolver.ts | 12 ++++ .../my-dspace-page.component.html | 1 + .../my-dspace-page/my-dspace-page.module.ts | 18 ++--- .../profile-page/profile-page.component.html | 1 + src/app/profile-page/profile-page.module.ts | 16 +++-- .../dso-selector-modal-wrapper.component.ts | 18 ++++- .../reciter-suggestions/selectors.ts | 10 +-- .../suggestion-targets.component.ts | 1 + .../suggestion-targets.effects.ts | 2 +- .../suggestion-targets.state.service.ts | 14 ++-- .../suggestions-popup.component.ts | 2 + .../suggestions.service.ts | 4 +- .../suggestion-notifications.module.ts | 12 ++++ src/assets/i18n/en.json5 | 68 +++++++++++++++++++ src/themes/custom/lazy-theme.module.ts | 3 + 27 files changed, 193 insertions(+), 62 deletions(-) create mode 100644 src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts create mode 100644 src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 075bf3ca0ca..5b5e362406c 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -161,6 +161,7 @@ export class RemoteDataBuildService { } else { // in case the elements of the paginated list were already filled in, because they're UnCacheableObjects paginatedList.page = paginatedList.page + .filter((obj: any) => obj != null) .map((obj: any) => this.plainObjectToInstance(obj)) .map((obj: any) => this.linkService.resolveLinks(obj, ...pageLink.linksToFollow) diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index e176af7d550..7acf132df9b 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -185,6 +185,8 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model'; import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model'; import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition'; import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; +import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -386,7 +388,9 @@ export const models = IdentifierData, Subscription, ItemRequest, - BulkAccessConditionOptions + BulkAccessConditionOptions, + SuggestionTarget, + SuggestionSource ]; @NgModule({ diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts index e31006959ff..8f87027a8c5 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts @@ -1,21 +1,5 @@ import { ResourceType } from '../../../shared/resource-type'; -/** - * The resource type for the Suggestion Target object - * - * Needs to be in a separate file to prevent circular - * dependencies in webpack. - */ -export const SUGGESTION_TARGET = new ResourceType('suggestiontarget'); - -/** - * The resource type for the Suggestion Source object - * - * Needs to be in a separate file to prevent circular - * dependencies in webpack. - */ -export const SUGGESTION_SOURCE = new ResourceType('suggestionsource'); - /** * The resource type for the Suggestion object * diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts new file mode 100644 index 00000000000..2e26fe4301c --- /dev/null +++ b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for the Suggestion Source object + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUGGESTION_SOURCE = new ResourceType('suggestionsource'); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts index 64ddf9863c8..007520800d3 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize } from 'cerialize'; -import { SUGGESTION_SOURCE } from './suggestion-objects.resource-type'; +import { SUGGESTION_SOURCE } from './suggestion-source-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts new file mode 100644 index 00000000000..71dd41912ac --- /dev/null +++ b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for the Suggestion Target object + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUGGESTION_TARGET = new ResourceType('suggestiontarget'); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts index 970a8e7e285..2afe170e777 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts @@ -2,7 +2,7 @@ import { autoserialize, deserialize } from 'cerialize'; import { CacheableObject } from '../../../cache/cacheable-object.model'; -import { SUGGESTION_TARGET } from './suggestion-objects.resource-type'; +import { SUGGESTION_TARGET } from './suggestion-target-object.resource-type'; import { excludeFromEquals } from '../../../utilities/equals.decorators'; import { ResourceType } from '../../../shared/resource-type'; import { HALLink } from '../../../shared/hal-link.model'; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts index e4286c6b5b8..c3e142044e1 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { dataService } from '../../../data/base/data-service.decorator'; -import { SUGGESTION_SOURCE } from '../models/suggestion-objects.resource-type'; +import { SUGGESTION_SOURCE } from '../models/suggestion-source-object.resource-type'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { SuggestionSource } from '../models/suggestion-source.model'; import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts index abdcbca0c16..944a13e3a3c 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts @@ -168,8 +168,8 @@ export class SuggestionsDataService { ...linksToFollow: FollowLinkConfig[] ): Observable>> { options.searchParams = [new RequestParam('target', userId)]; - - return this.suggestionTargetsDataService.getTargetsByUser(this.searchFindByTargetMethod, options, ...linksToFollow); + //return this.suggestionTargetsDataService.getTargetsByUser(this.searchFindByTargetMethod, options, ...linksToFollow); + return this.suggestionTargetsDataService.getTargetsByUser(userId, options, ...linksToFollow); } /** diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts index 372d1f9917c..ce5f131c1d5 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { dataService } from '../../../data/base/data-service.decorator'; -import { SUGGESTION_TARGET } from '../models/suggestion-objects.resource-type'; + import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { SuggestionTarget } from '../models/suggestion-target.model'; import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; @@ -20,6 +20,7 @@ import { Observable } from 'rxjs/internal/Observable'; import { RequestParam } from '../../../cache/models/request-param.model'; import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { SUGGESTION_TARGET } from '../models/suggestion-target-object.resource-type'; @Injectable() @dataService(SUGGESTION_TARGET) diff --git a/src/app/home-page/home-page.component.html b/src/app/home-page/home-page.component.html index caa86ac290a..49329b3f044 100644 --- a/src/app/home-page/home-page.component.html +++ b/src/app/home-page/home-page.component.html @@ -7,3 +7,4 @@ + diff --git a/src/app/home-page/home-page.module.ts b/src/app/home-page/home-page.module.ts index 1681abd8058..00f9dbd8f9b 100644 --- a/src/app/home-page/home-page.module.ts +++ b/src/app/home-page/home-page.module.ts @@ -13,6 +13,7 @@ import { RecentItemListComponent } from './recent-item-list/recent-item-list.com import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; import { ThemedTopLevelCommunityListComponent } from './top-level-community-list/themed-top-level-community-list.component'; +import { SuggestionNotificationsModule } from '../suggestion-notifications/suggestion-notifications.module'; const DECLARATIONS = [ HomePageComponent, @@ -25,14 +26,15 @@ const DECLARATIONS = [ ]; @NgModule({ - imports: [ - CommonModule, - SharedModule.withEntryComponents(), - JournalEntitiesModule.withEntryComponents(), - ResearchEntitiesModule.withEntryComponents(), - HomePageRoutingModule, - StatisticsModule.forRoot() - ], + imports: [ + CommonModule, + SharedModule.withEntryComponents(), + JournalEntitiesModule.withEntryComponents(), + ResearchEntitiesModule.withEntryComponents(), + HomePageRoutingModule, + StatisticsModule.forRoot(), + SuggestionNotificationsModule + ], declarations: [ ...DECLARATIONS, ], diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 7a3a16d6265..70e2b6462f8 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -47,6 +47,7 @@ import { import { ExportBatchSelectorComponent } from './shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component'; +import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './admin/admin-notifications/admin-notifications-routing-paths'; /** * Creates all of the app's menus @@ -555,6 +556,17 @@ export class MenuResolver implements Resolve { link: '/admin/notifications/quality-assurance' } as LinkMenuItemModel, }, + { + id: 'notifications_reciter', + parentID: 'notifications', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_reciter', + link: '/admin/notifications/' + NOTIFICATIONS_RECITER_SUGGESTION_PATH + } as LinkMenuItemModel, + }, /* Admin Search */ { id: 'admin_search', diff --git a/src/app/my-dspace-page/my-dspace-page.component.html b/src/app/my-dspace-page/my-dspace-page.component.html index ea5784170fb..c5e49b0cece 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.html +++ b/src/app/my-dspace-page/my-dspace-page.component.html @@ -1,5 +1,6 @@
+
{{'profile.head' | translate}}

+ diff --git a/src/app/profile-page/profile-page.module.ts b/src/app/profile-page/profile-page.module.ts index 0e2902de33c..c5bfad17138 100644 --- a/src/app/profile-page/profile-page.module.ts +++ b/src/app/profile-page/profile-page.module.ts @@ -12,16 +12,18 @@ import { ThemedProfilePageComponent } from './themed-profile-page.component'; import { FormModule } from '../shared/form/form.module'; import { UiSwitchModule } from 'ngx-ui-switch'; import { ProfileClaimItemModalComponent } from './profile-claim-item-modal/profile-claim-item-modal.component'; +import { SuggestionNotificationsModule } from '../suggestion-notifications/suggestion-notifications.module'; @NgModule({ - imports: [ - ProfilePageRoutingModule, - CommonModule, - SharedModule, - FormModule, - UiSwitchModule - ], + imports: [ + ProfilePageRoutingModule, + CommonModule, + SharedModule, + FormModule, + UiSwitchModule, + SuggestionNotificationsModule + ], exports: [ ProfilePageComponent, ThemedProfilePageComponent, diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index 3f81687c9f8..6798449094d 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { RemoteData } from '../../../core/data/remote-data'; @@ -29,6 +29,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ @Input() dsoRD: RemoteData; + /** + * Representing if component should emit value of selected entries or navigate + */ + @Input() emitOnly = false; + /** * Optional header to display above the selection list * Supports i18n keys @@ -50,6 +55,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ action: SelectorActionType; + /** + * Event emitted when a DSO entry is selected if emitOnly is set to true + */ + @Output() select: EventEmitter = new EventEmitter(); + /** * Default DSO ordering */ @@ -93,7 +103,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ selectObject(dso: DSpaceObject) { this.close(); - this.navigate(dso); + if (this.emitOnly) { + this.select.emit(dso); + } else { + this.navigate(dso); + } } /** diff --git a/src/app/suggestion-notifications/reciter-suggestions/selectors.ts b/src/app/suggestion-notifications/reciter-suggestions/selectors.ts index cbb99fe8697..ee906132714 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/selectors.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/selectors.ts @@ -27,7 +27,7 @@ export function reciterSuggestionTargetStateSelector(): MemoizedSelector { return subStateSelector(reciterSuggestionTargetStateSelector(), 'targets'); @@ -47,7 +47,7 @@ export const isReciterSuggestionTargetLoadedSelector = createSelector(_getRecite * @function isDeduplicationSetsProcessingSelector * @return {boolean} */ -export const isreciterSuggestionTargetProcessingSelector = createSelector(_getReciterSuggestionTargetState, +export const isReciterSuggestionTargetProcessingSelector = createSelector(_getReciterSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.processing ); @@ -56,7 +56,7 @@ export const isreciterSuggestionTargetProcessingSelector = createSelector(_getRe * @function getreciterSuggestionTargetTotalPagesSelector * @return {number} */ -export const getreciterSuggestionTargetTotalPagesSelector = createSelector(_getReciterSuggestionTargetState, +export const getReciterSuggestionTargetTotalPagesSelector = createSelector(_getReciterSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.totalPages ); @@ -65,7 +65,7 @@ export const getreciterSuggestionTargetTotalPagesSelector = createSelector(_getR * @function getreciterSuggestionTargetCurrentPageSelector * @return {number} */ -export const getreciterSuggestionTargetCurrentPageSelector = createSelector(_getReciterSuggestionTargetState, +export const getReciterSuggestionTargetCurrentPageSelector = createSelector(_getReciterSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.currentPage ); @@ -74,7 +74,7 @@ export const getreciterSuggestionTargetCurrentPageSelector = createSelector(_get * @function getreciterSuggestionTargetTotalsSelector * @return {number} */ -export const getreciterSuggestionTargetTotalsSelector = createSelector(_getReciterSuggestionTargetState, +export const getReciterSuggestionTargetTotalsSelector = createSelector(_getReciterSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.totalElements ); diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts index cfa168e2b83..e5524765da0 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts @@ -136,6 +136,7 @@ export class SuggestionTargetsComponent implements OnInit { distinctUntilChanged(), take(1) ).subscribe((options: PaginationComponentOptions) => { + console.log('HELLO suggestion called!', options); this.suggestionTargetsStateService.dispatchRetrieveReciterSuggestionTargets( this.source, options.pageSize, diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts index 3718e0cfad4..6ab587a6c21 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts @@ -62,7 +62,7 @@ export class SuggestionTargetsEffects { /** * Fetch the current user suggestion */ - refreshUserTargets$ = createEffect(() => this.actions$.pipe( + RefreshUserSuggestionsAction = createEffect(() => this.actions$.pipe( ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS), switchMap((action: RefreshUserSuggestionsAction) => { return this.store$.select((state: any) => state.core.auth.userId) diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts index 97792df6af7..fec9e01f3c7 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts @@ -7,10 +7,10 @@ import { map } from 'rxjs/operators'; import { getCurrentUserSuggestionTargetsSelector, getCurrentUserSuggestionTargetsVisitedSelector, - getreciterSuggestionTargetCurrentPageSelector, - getreciterSuggestionTargetTotalsSelector, + getReciterSuggestionTargetCurrentPageSelector, + getReciterSuggestionTargetTotalsSelector, isReciterSuggestionTargetLoadedSelector, - isreciterSuggestionTargetProcessingSelector, + isReciterSuggestionTargetProcessingSelector, reciterSuggestionTargetObjectSelector } from '../selectors'; import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; @@ -74,7 +74,7 @@ export class SuggestionTargetsStateService { * 'true' if there are operations running on the targets (ex.: a REST call), 'false' otherwise. */ public isReciterSuggestionTargetsProcessing(): Observable { - return this.store.pipe(select(isreciterSuggestionTargetProcessingSelector)); + return this.store.pipe(select(isReciterSuggestionTargetProcessingSelector)); } /** @@ -84,7 +84,7 @@ export class SuggestionTargetsStateService { * The number of the Reciter Suggestion Targets pages. */ public getReciterSuggestionTargetsTotalPages(): Observable { - return this.store.pipe(select(getreciterSuggestionTargetTotalsSelector)); + return this.store.pipe(select(getReciterSuggestionTargetTotalsSelector)); } /** @@ -94,7 +94,7 @@ export class SuggestionTargetsStateService { * The number of the current Reciter Suggestion Targets page. */ public getReciterSuggestionTargetsCurrentPage(): Observable { - return this.store.pipe(select(getreciterSuggestionTargetCurrentPageSelector)); + return this.store.pipe(select(getReciterSuggestionTargetCurrentPageSelector)); } /** @@ -104,7 +104,7 @@ export class SuggestionTargetsStateService { * The number of the Reciter Suggestion Targets. */ public getReciterSuggestionTargetsTotals(): Observable { - return this.store.pipe(select(getreciterSuggestionTargetTotalsSelector)); + return this.store.pipe(select(getReciterSuggestionTargetTotalsSelector)); } /** diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts index 0195f074ae8..c0f94cadce3 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts @@ -31,6 +31,8 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { } public initializePopup() { + console.log('POPUP INIT dispatchRefreshUserSuggestionsAction'); + this.reciterSuggestionStateService.dispatchRefreshUserSuggestionsAction(); const notifier = new Subject(); this.subscription = combineLatest([ this.reciterSuggestionStateService.getCurrentUserSuggestionTargets(), diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts index 662b4c03dec..b760ddf34db 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts @@ -49,7 +49,9 @@ export class SuggestionsService { /** * Initialize the service variables. * @param {AuthService} authService - * @param {ResearcherProfileService} researcherProfileService + * @param {ResearcherProfileDataService} researcherProfileService + * @param {SuggestionSourceDataService} suggestionSourceDataService + * @param {SuggestionTargetDataService} suggestionTargetDataService * @param {SuggestionsDataService} suggestionsDataService */ constructor( diff --git a/src/app/suggestion-notifications/suggestion-notifications.module.ts b/src/app/suggestion-notifications/suggestion-notifications.module.ts index 4369d17375c..fa9d81eb756 100644 --- a/src/app/suggestion-notifications/suggestion-notifications.module.ts +++ b/src/app/suggestion-notifications/suggestion-notifications.module.ts @@ -40,6 +40,15 @@ import { } from './reciter-suggestions/suggestions-notification/suggestions-notification.component'; import { SuggestionsService } from './reciter-suggestions/suggestions.service'; import { SuggestionsDataService } from '../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +import { + SuggestionSourceDataService +} from '../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service'; +import { + SuggestionTargetDataService +} from '../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +import { + SuggestionTargetsStateService +} from './reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; const MODULES = [ CommonModule, @@ -77,6 +86,9 @@ const PROVIDERS = [ QualityAssuranceSourceDataService, QualityAssuranceEventDataService, SuggestionsService, + SuggestionSourceDataService, + SuggestionTargetDataService, + SuggestionTargetsStateService, SuggestionsDataService ]; diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4c13ec73d14..0d90ca693d9 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -24,6 +24,10 @@ "404.page-not-found": "page not found", + "admin.notifications.recitersuggestion.breadcrumbs": "Suggestions", + + "admin.notifications.recitersuggestion.page.title": "Suggestions", + "error-page.description.401": "unauthorized", "error-page.description.403": "forbidden", @@ -3052,6 +3056,12 @@ "mydspace.view-btn": "View", + "mydspace.import": "Import", + + "mydspace.notification.suggestion": "We found {{count}} publications
in the {{source}} that seems to be related to your profile.
Please review the suggestions", + + "mydspace.notification.suggestion.page": "We found {{count}} {{type}} in the {{source}} that seems to be related to your profile. Please review the suggestions.", + "nav.browse.header": "All of DSpace", "nav.community-browse.header": "By Community", @@ -3514,6 +3524,64 @@ "media-viewer.playlist": "Playlist", + "reciter.suggestion.loading": "Loading ...", + + "reciter.suggestion.title": "Suggestions", + + "reciter.suggestion.targets.description": "Below you can see all the suggestions ", + + "reciter.suggestion.targets": "Current Suggestions", + + "reciter.suggestion.table.name": "Researcher Name", + + "reciter.suggestion.table.actions": "Actions", + + "reciter.suggestion.button.review": "Review {{ total }} suggestion(s)", + + "reciter.suggestion.noTargets": "No target found.", + + "reciter.suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + + "reciter.suggestion.evidence.type": "Type", + + "reciter.suggestion.evidence.score": "Score", + + "reciter.suggestion.evidence.notes": "Notes", + + "reciter.suggestion.approveAndImport": "Approve & import", + + "reciter.suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + + "reciter.suggestion.approveAndImport.bulk": "Approve & import Selected", + + "reciter.suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + + "reciter.suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + + "reciter.suggestion.notMine": "Not mine", + + "reciter.suggestion.notMine.success": "The suggestion has been discarded", + + "reciter.suggestion.notMine.bulk": "Not mine Selected", + + "reciter.suggestion.notMine.bulk.success": "{{ count }} suggestions have been discarded ", + + "reciter.suggestion.notMine.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + + "reciter.suggestion.seeEvidence": "See evidence", + + "reciter.suggestion.hideEvidence": "Hide evidence", + + "reciter.suggestion.suggestionFor": "Suggestion for", + + "reciter.suggestion.source.oaire": "OpenAIRE Graph", + + "reciter.suggestion.from.source": "from the ", + + "reciter.suggestion.totalScore": "Total Score", + + "reciter.suggestion.type.oaire": "OpenAIRE", + "register-email.title": "New user registration", "register-page.create-profile.header": "Create Profile", diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index edb3f5478c9..771e9e1b088 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -156,6 +156,8 @@ import { ItemStatusComponent } from './app/item-page/edit-item-page/item-status/ import { EditBitstreamPageComponent } from './app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component'; import { FormModule } from '../../app/shared/form/form.module'; import { RequestCopyModule } from 'src/app/request-copy/request-copy.module'; +import { SuggestionNotificationsModule } from '../../app/suggestion-notifications/suggestion-notifications.module'; + const DECLARATIONS = [ FileSectionComponent, @@ -299,6 +301,7 @@ const DECLARATIONS = [ NgxGalleryModule, FormModule, RequestCopyModule, + SuggestionNotificationsModule ], declarations: DECLARATIONS, exports: [ From c4d57770c74959dbd73ec5fb338692db279942eb Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Thu, 24 Aug 2023 10:00:21 +0200 Subject: [PATCH 049/592] ProcessDataService.notifyOnCompletion tests (WIP) --- .../processes/process-data.service.spec.ts | 48 +++++++++---------- .../data/processes/process-data.service.ts | 11 +++-- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index 6e7ce515027..bf42b6b9cff 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -18,7 +18,6 @@ import { Process } from '../../../process-page/processes/process.model'; import { ProcessStatus } from '../../../process-page/processes/process-status.model'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../cache/object-cache.service'; -import { CoreModule } from '../../core.module'; import { ReducerManager } from '@ngrx/store'; import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { DSOChangeAnalyzer } from '../dso-change-analyzer.service'; @@ -27,7 +26,7 @@ import { NotificationsService } from '../../../shared/notifications/notification describe('ProcessDataService', () => { describe('composition', () => { - const initService = () => new ProcessDataService(null, null, null, null, null, null); + const initService = () => new ProcessDataService(null, null, null, null, null, null, null); testFindAllDataImplementation(initService); testDeleteDataImplementation(initService); }); @@ -38,13 +37,11 @@ describe('ProcessDataService', () => { describe('notifyOnCompletion', () => { beforeEach(waitForAsync(() => { - requestService = jasmine.createSpyObj('requestService', ['setStaleByHrefSubstring']); - TestBed.configureTestingModule({ imports: [], providers: [ ProcessDataService, - { provide: RequestService, useValue: requestService }, + { provide: RequestService, useValue: null }, { provide: RemoteDataBuildService, useValue: null }, { provide: ObjectCacheService, useValue: null }, { provide: ReducerManager, useValue: null }, @@ -56,6 +53,7 @@ describe('ProcessDataService', () => { }); processDataService = TestBed.inject(ProcessDataService); + spyOn(processDataService, 'invalidateByHref'); })); it('TODO', () => { @@ -71,33 +69,35 @@ describe('ProcessDataService', () => { let process$ = processDataService.notifyOnCompletion('instantly'); process$.subscribe((rd) => { expect(processDataService.findById).toHaveBeenCalledTimes(1); - expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalled(); + expect(processDataService.invalidateByHref).not.toHaveBeenCalled(); }); expect(process$).toBeObservable(cold('(c|)', { 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) })); }); - // it('TODO2', () => { - // let completedProcess = new Process(); - // completedProcess.processStatus = ProcessStatus.COMPLETED; + it('TODO2', () => { + let runningProcess = new Process(); + runningProcess.processStatus = ProcessStatus.RUNNING; + let completedProcess = new Process(); + completedProcess.processStatus = ProcessStatus.COMPLETED; - // spyOn(processDataService, 'findById').and.returnValue( - // cold('p 150ms (c|)', { - // 'p': new RemoteData(0, 0, 0, RequestEntryState., null, completedProcess), - // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - // }) - // ); + spyOn(processDataService, 'findById').and.returnValue( + cold('p 150ms (c|)', { + 'p': new RemoteData(0, 0, 0, RequestEntryState.Success, null, runningProcess), + 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + }) + ); - // let process$ = processDataService.notifyOnCompletion('foo', 100); - // expect(process$).toBeObservable(cold('---(c|)', { - // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - // })); - // process$.subscribe((rd) => { - // expect(processDataService.findById).toHaveBeenCalledTimes(1); - // expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalled(); - // }); - // }); + let process$ = processDataService.notifyOnCompletion('foo', 100); + // expect(process$).toBeObservable(cold('- 800ms (c|)', { + // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + // })); + process$.subscribe((rd) => { + expect(processDataService.findById).toHaveBeenCalledTimes(1); + expect(processDataService.invalidateByHref).toHaveBeenCalledTimes(1); + }); + }); }); }); diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index f550407a59a..f0c0829e855 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, NgZone } from '@angular/core'; import { RequestService } from '../request.service'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../cache/object-cache.service'; @@ -36,6 +36,7 @@ export class ProcessDataService extends IdentifiableDataService impleme protected halService: HALEndpointService, protected bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, + protected zone: NgZone, ) { super('processes', requestService, rdbService, objectCache, halService); @@ -129,9 +130,11 @@ export class ProcessDataService extends IdentifiableDataService impleme this.activelyBeingPolled.delete(processId); sub.unsubscribe(); } else { - setTimeout(() => { - this.requestService.setStaleByHrefSubstring(process._links.self.href); - }, pollingIntervalInMs); + this.zone.runOutsideAngular(() => + setTimeout(() => { + this.invalidateByHref(process._links.self.href); + }, pollingIntervalInMs) + ); } }); } From bd6648703c2c73ec552adf3bec13e7bf771fcfe6 Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Fri, 25 Aug 2023 11:17:36 +0200 Subject: [PATCH 050/592] 104938 Add flush to process polling tests --- .../processes/process-data.service.spec.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index bf42b6b9cff..ccdb65c4172 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -9,7 +9,7 @@ import { testFindAllDataImplementation } from '../base/find-all-data.spec'; import { ProcessDataService } from './process-data.service'; import { testDeleteDataImplementation } from '../base/delete-data.spec'; -import { cold } from 'jasmine-marbles'; +import { cold, getTestScheduler } from 'jasmine-marbles'; import { waitForAsync, TestBed } from '@angular/core/testing'; import { RequestService } from '../request.service'; import { RemoteData } from '../remote-data'; @@ -23,6 +23,7 @@ import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { DSOChangeAnalyzer } from '../dso-change-analyzer.service'; import { BitstreamFormatDataService } from '../bitstream-format-data.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TestScheduler } from 'rxjs/testing'; describe('ProcessDataService', () => { describe('composition', () => { @@ -34,9 +35,11 @@ describe('ProcessDataService', () => { let requestService; let processDataService; let remoteDataBuildService; + let scheduler: TestScheduler; describe('notifyOnCompletion', () => { beforeEach(waitForAsync(() => { + scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [], providers: [ @@ -90,13 +93,12 @@ describe('ProcessDataService', () => { ); let process$ = processDataService.notifyOnCompletion('foo', 100); - // expect(process$).toBeObservable(cold('- 800ms (c|)', { - // 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - // })); - process$.subscribe((rd) => { - expect(processDataService.findById).toHaveBeenCalledTimes(1); - expect(processDataService.invalidateByHref).toHaveBeenCalledTimes(1); - }); + expect(process$).toBeObservable(cold('- 150ms (c|)', { + 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) + })); + scheduler.flush(); + expect(processDataService.findById).toHaveBeenCalledTimes(1); + expect(processDataService.invalidateByHref).toHaveBeenCalledTimes(1); }); }); From 44e28c9033e4d18cc833445808898af529ce5955 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 12:32:54 +0200 Subject: [PATCH 051/592] CST-11012 Fixed breadcrumb text and COAR Notify text in footer --- src/app/footer/footer.component.scss | 15 ++++++++++----- src/assets/i18n/en.json5 | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 7a1af42bfcf..745966c825f 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -23,16 +23,21 @@ .bottom-footer { .notify-enabled { - .coar-notify-support-route{ + position: absolute; + bottom: 7px; + right: 0; + + .coar-notify-support-route { padding: 0 calc(var(--bs-spacer) / 2); - color: inherit + color: inherit; } - .n-coar{ + + .n-coar { height: var(--ds-footer-n-coar-height); - margin-bottom: 7px; + margin-bottom: 8.5px; } + margin-top: 15px; - margin-left: 50px; } ul { li { diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 9cd1519363d..096e91bb121 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1897,7 +1897,7 @@ "info.coar-notify-support.title":"Notify Support", - "info.coar-notify-support": "Notify Support", + "info.coar-notify.breadcrumbs": "Notify Support", "info.feedback.head": "Feedback", From eebaa0a213e0a8643e46fc83652bea3059af77f7 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 12:36:05 +0200 Subject: [PATCH 052/592] CST-11012 Fixed breadcrumb text and COAR Notify text in footer (2) --- src/app/footer/footer.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 1c4b95c557c..c5bc2c13a64 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -84,7 +84,7 @@
Footer Content
From fc4a44cc83ac2c3863ac7ce51fd2bf82f5256872 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 12:49:22 +0200 Subject: [PATCH 053/592] CST-11012 Fixed breadcrumb text and COAR Notify text in footer (3) --- src/app/info/info-routing.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index 40859245670..c91c534fe44 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -27,7 +27,7 @@ const imports = [ path: COAR_NOTIFY_SUPPORT, component: NotifyInfoComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, - data: { title: 'info.coar-notify-support.title', breadcrumbKey: 'info.coar-notify-support' }, + data: { title: 'info.coar-notify-support.title', breadcrumbKey: 'info.coar-notify' }, canActivate: [NotifyInfoGuard] } ]) From d3fb5bf686704dbd14cb58122e6a9bd11dcf67c2 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 13:32:03 +0200 Subject: [PATCH 054/592] CST-11012 Dynamically retrieving rest URL for the coar-notify-page --- .../notify-info/notify-info.component.html | 2 +- .../notify-info/notify-info.component.ts | 9 ++++++--- .../coar-notify/notify-info/notify-info.service.ts | 13 +++++++++++++ src/assets/i18n/en.json5 | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html index 3596acfc67e..101cf867cc4 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.html +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -8,7 +8,7 @@

{{ 'coar-notify-support.title' | translate }}

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

-

+

{{ 'coar-notify-support.message-moderation.title' | translate }}

diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index 9c8f48218dc..1abb54c11ea 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -1,23 +1,26 @@ import { Component, OnInit } from '@angular/core'; import { NotifyInfoService } from './notify-info.service'; + @Component({ selector: 'ds-notify-info', templateUrl: './notify-info.component.html', styleUrls: ['./notify-info.component.scss'] }) export class NotifyInfoComponent implements OnInit { - coarLdnEnabled: boolean; + coarRestApiUrl: string; constructor( public notifyInfoService: NotifyInfoService, - ) { } + ) { + } ngOnInit() { + this.coarRestApiUrl = this.notifyInfoService.getCoarLdnRestApiUrl(); + this.notifyInfoService.isCoarConfigEnabled().subscribe(value => { this.coarLdnEnabled = value; }); } - } diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts index 6183a1fb309..a88181a9abd 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { getFirstSucceededRemoteData } from '../../shared/operators'; import { ConfigurationDataService } from '../../data/configuration-data.service'; import { map, Observable } from 'rxjs'; +import { DefaultAppConfig } from '../../../../config/default-app-config'; @Injectable({ providedIn: 'root' @@ -22,4 +23,16 @@ export class NotifyInfoService { }) ); } + + getCoarLdnRestApiUrl(): string { + const appConfig = new DefaultAppConfig(); + const restConfig = appConfig.rest; + + const ssl = restConfig.ssl; + const host = restConfig.host; + const port = restConfig.port; + const namespace = restConfig.nameSpace; + + return `${ssl ? 'https' : 'http'}://${host}:${port}${namespace}`; + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 096e91bb121..65bf1ebaaa8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -873,7 +873,7 @@ "coar-notify-support.ldn-inbox.title": "LDN InBox", - "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at ${restApiUrl}/ldn/inbox. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", + "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at {restApiUrl}ldn/inbox. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", "coar-notify-support.message-moderation.title": "Message Moderation", From 2ba86ed6d942a3346f3a0dbdb6b09eb06815938e Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 13:42:26 +0200 Subject: [PATCH 055/592] CST-11012 Finalized Coar text +logo --- src/app/footer/footer.component.html | 2 +- src/app/footer/footer.component.scss | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index c5bc2c13a64..64ddfc1910b 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -81,7 +81,7 @@
Footer Content
-
+
COAR Notify diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 745966c825f..0faf5ac85eb 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -24,7 +24,7 @@ .bottom-footer { .notify-enabled { position: absolute; - bottom: 7px; + bottom: 4px; right: 0; .coar-notify-support-route { @@ -34,10 +34,10 @@ .n-coar { height: var(--ds-footer-n-coar-height); - margin-bottom: 8.5px; + margin-bottom: 6px; } - margin-top: 15px; + margin-top: 20px; } ul { li { From 76764786002922a7be9a970e3772ad8437847635 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 29 Aug 2023 13:54:21 +0200 Subject: [PATCH 056/592] CST-11012 Finalized Coar text +logo (centered with itself) --- src/app/footer/footer.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 0faf5ac85eb..87896a5e530 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -34,7 +34,7 @@ .n-coar { height: var(--ds-footer-n-coar-height); - margin-bottom: 6px; + margin-bottom: 8.5px; } margin-top: 20px; From 3be90ebe460b9910ab2c86bbc15d27918a7c22a4 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 29 Aug 2023 18:39:39 +0200 Subject: [PATCH 057/592] rewrite notifyOnCompletion as autoRefreshUntilCompletion, fix ProcessDetailComponent, and the ProcessDataService tests --- ...llection-source-controls.component.spec.ts | 8 +- .../collection-source-controls.component.ts | 6 +- .../processes/process-data.service.spec.ts | 111 +++++++++------- .../data/processes/process-data.service.ts | 118 +++++++++++++----- .../detail/process-detail.component.html | 4 +- .../detail/process-detail.component.ts | 104 +++------------ .../processes/process-status.model.ts | 8 +- src/assets/i18n/en.json5 | 2 + 8 files changed, 187 insertions(+), 174 deletions(-) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts index 37a5d8642de..f717943e8eb 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts @@ -88,7 +88,7 @@ describe('CollectionSourceControlsComponent', () => { invoke: createSuccessfulRemoteDataObject$(process), }); processDataService = jasmine.createSpyObj('processDataService', { - notifyOnCompletion: createSuccessfulRemoteDataObject$(process), + autoRefreshUntilCompletion: createSuccessfulRemoteDataObject$(process), }); bitstreamService = jasmine.createSpyObj('bitstreamService', { findByHref: createSuccessfulRemoteDataObject$(bitstream), @@ -137,7 +137,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-i', value: new ContentSourceSetSerializer().Serialize(contentSource.oaiSetId)}, ], []); - expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); + expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId); expect(bitstreamService.findByHref).toHaveBeenCalledWith(process._links.output.href); expect(notificationsService.info).toHaveBeenCalledWith(jasmine.anything() as any, 'Script text'); }); @@ -151,7 +151,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-r', value: null}, {name: '-c', value: collection.uuid}, ], []); - expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); + expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId); expect(notificationsService.success).toHaveBeenCalled(); }); }); @@ -164,7 +164,7 @@ describe('CollectionSourceControlsComponent', () => { {name: '-o', value: null}, {name: '-c', value: collection.uuid}, ], []); - expect(processDataService.notifyOnCompletion).toHaveBeenCalledWith(process.processId); + expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId); expect(notificationsService.success).toHaveBeenCalled(); }); }); diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts index e8c3666da08..ea2cb3e2f49 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts @@ -95,7 +95,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { }), // filter out responses that aren't successful since the pinging of the process only needs to happen when the invocation was successful. filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)), map((rd) => rd.payload) ).subscribe((process: Process) => { if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { @@ -166,7 +166,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { } }), filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)), map((rd) => rd.payload) ).subscribe((process) => { if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { @@ -226,7 +226,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { } }), filter((rd) => rd.hasSucceeded && hasValue(rd.payload)), - switchMap((rd) => this.processDataService.notifyOnCompletion(rd.payload.processId)), + switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)), map((rd) => rd.payload) ).subscribe((process) => { if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index ccdb65c4172..f58752ee973 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -7,10 +7,9 @@ */ import { testFindAllDataImplementation } from '../base/find-all-data.spec'; -import { ProcessDataService } from './process-data.service'; +import { ProcessDataService, TIMER_FACTORY } from './process-data.service'; import { testDeleteDataImplementation } from '../base/delete-data.spec'; -import { cold, getTestScheduler } from 'jasmine-marbles'; -import { waitForAsync, TestBed } from '@angular/core/testing'; +import { waitForAsync, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { RequestService } from '../request.service'; import { RemoteData } from '../remote-data'; import { RequestEntryState } from '../request-entry-state.model'; @@ -23,11 +22,20 @@ import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { DSOChangeAnalyzer } from '../dso-change-analyzer.service'; import { BitstreamFormatDataService } from '../bitstream-format-data.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { TestScheduler } from 'rxjs/testing'; +import { TestScheduler, RunHelpers } from 'rxjs/testing'; +import { cold } from 'jasmine-marbles'; +import { of } from 'rxjs'; describe('ProcessDataService', () => { + let testScheduler; + + const mockTimer = (fn: () => {}, interval: number) => { + fn(); + return 555; + }; + describe('composition', () => { - const initService = () => new ProcessDataService(null, null, null, null, null, null, null); + const initService = () => new ProcessDataService(null, null, null, null, null, null, null, null); testFindAllDataImplementation(initService); testDeleteDataImplementation(initService); }); @@ -35,11 +43,12 @@ describe('ProcessDataService', () => { let requestService; let processDataService; let remoteDataBuildService; - let scheduler: TestScheduler; - describe('notifyOnCompletion', () => { + describe('autoRefreshUntilCompletion', () => { beforeEach(waitForAsync(() => { - scheduler = getTestScheduler(); + testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); TestBed.configureTestingModule({ imports: [], providers: [ @@ -52,6 +61,7 @@ describe('ProcessDataService', () => { { provide: DSOChangeAnalyzer, useValue: null }, { provide: BitstreamFormatDataService, useValue: null }, { provide: NotificationsService, useValue: null }, + { provide: TIMER_FACTORY, useValue: mockTimer }, ] }); @@ -59,50 +69,63 @@ describe('ProcessDataService', () => { spyOn(processDataService, 'invalidateByHref'); })); - it('TODO', () => { - let completedProcess = new Process(); - completedProcess.processStatus = ProcessStatus.COMPLETED; + it('should not do any polling when the process is already completed', () => { + testScheduler.run(({ cold, expectObservable }) => { + let completedProcess = new Process(); + completedProcess.processStatus = ProcessStatus.COMPLETED; + + const completedProcessRD = new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess); - spyOn(processDataService, 'findById').and.returnValue( - cold('(c|)', { - 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - }) - ); + spyOn(processDataService, 'findById').and.returnValue( + cold('c', { + 'c': completedProcessRD + }) + ); - let process$ = processDataService.notifyOnCompletion('instantly'); - process$.subscribe((rd) => { - expect(processDataService.findById).toHaveBeenCalledTimes(1); - expect(processDataService.invalidateByHref).not.toHaveBeenCalled(); + let process$ = processDataService.autoRefreshUntilCompletion('instantly'); + expectObservable(process$).toBe('c', { + c: completedProcessRD + }); }); - expect(process$).toBeObservable(cold('(c|)', { - 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - })); + + expect(processDataService.findById).toHaveBeenCalledTimes(1); + expect(processDataService.invalidateByHref).not.toHaveBeenCalled(); }); - it('TODO2', () => { - let runningProcess = new Process(); - runningProcess.processStatus = ProcessStatus.RUNNING; - let completedProcess = new Process(); - completedProcess.processStatus = ProcessStatus.COMPLETED; - - spyOn(processDataService, 'findById').and.returnValue( - cold('p 150ms (c|)', { - 'p': new RemoteData(0, 0, 0, RequestEntryState.Success, null, runningProcess), - 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - }) - ); - - let process$ = processDataService.notifyOnCompletion('foo', 100); - expect(process$).toBeObservable(cold('- 150ms (c|)', { - 'c': new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess) - })); - scheduler.flush(); + it('should poll until a process completes', () => { + testScheduler.run(({ cold, expectObservable }) => { + const runningProcess = Object.assign(new Process(), { + _links: { + self: { + href: 'https://rest.api/processes/123' + } + } + }); + runningProcess.processStatus = ProcessStatus.RUNNING; + const completedProcess = new Process(); + completedProcess.processStatus = ProcessStatus.COMPLETED; + const runningProcessRD = new RemoteData(0, 0, 0, RequestEntryState.Success, null, runningProcess); + const completedProcessRD = new RemoteData(0, 0, 0, RequestEntryState.Success, null, completedProcess); + + spyOn(processDataService, 'findById').and.returnValue( + cold('r 150ms c', { + 'r': runningProcessRD, + 'c': completedProcessRD + }) + ); + + let process$ = processDataService.autoRefreshUntilCompletion('foo', 100); + expectObservable(process$).toBe('r 150ms c', { + 'r': runningProcessRD, + 'c': completedProcessRD + }); + }); + expect(processDataService.findById).toHaveBeenCalledTimes(1); expect(processDataService.invalidateByHref).toHaveBeenCalledTimes(1); }); - }); -}); + }); // /** // * Tests whether calls to `FindAllData` methods are correctly patched through in a concrete data service that implements it @@ -131,4 +154,4 @@ describe('ProcessDataService', () => { // expect(out).toBe('TEST findAll'); // }); // }); -// } +}); diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index f0c0829e855..a639ef24eae 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NgZone } from '@angular/core'; +import { Injectable, NgZone, Inject, InjectionToken } from '@angular/core'; import { RequestService } from '../request.service'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../cache/object-cache.service'; @@ -6,7 +6,7 @@ import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { Process } from '../../../process-page/processes/process.model'; import { PROCESS } from '../../../process-page/processes/process.resource-type'; import { Observable } from 'rxjs'; -import { switchMap, filter, take } from 'rxjs/operators'; +import { switchMap, filter, distinctUntilChanged, find } from 'rxjs/operators'; import { PaginatedList } from '../paginated-list.model'; import { Bitstream } from '../../shared/bitstream.model'; import { RemoteData } from '../remote-data'; @@ -21,13 +21,23 @@ import { NotificationsService } from '../../../shared/notifications/notification import { NoContent } from '../../shared/NoContent.model'; import { getAllCompletedRemoteData } from '../../shared/operators'; import { ProcessStatus } from 'src/app/process-page/processes/process-status.model'; +import { hasValue } from '../../../shared/empty.util'; + +/** + * Create an InjectionToken for the default JS setTimeout function, purely so we can mock it during + * testing. (fakeAsync isn't working for this case) + */ +export const TIMER_FACTORY = new InjectionToken<(callback: (...args: any[]) => void, ms?: number, ...args: any[]) => NodeJS.Timeout>('timer', { + providedIn: 'root', + factory: () => setTimeout +}); @Injectable() @dataService(PROCESS) export class ProcessDataService extends IdentifiableDataService implements FindAllData, DeleteData { private findAllData: FindAllData; private deleteData: DeleteData; - protected activelyBeingPolled: Set = new Set(); + protected activelyBeingPolled: Map = new Map(); constructor( protected requestService: RequestService, @@ -37,6 +47,7 @@ export class ProcessDataService extends IdentifiableDataService impleme protected bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, protected zone: NgZone, + @Inject(TIMER_FACTORY) protected timer: (callback: (...args: any[]) => void, ms?: number, ...args: any[]) => NodeJS.Timeout ) { super('processes', requestService, rdbService, objectCache, halService); @@ -106,42 +117,83 @@ export class ProcessDataService extends IdentifiableDataService impleme return this.deleteData.deleteByHref(href, copyVirtualMetadata); } - // TODO - public notifyOnCompletion(processId: string, pollingIntervalInMs = 5000): Observable> { - const process$ = this.findById(processId, false, true, followLink('script')) + /** + * Return true if the given process has the given status + * @protected + */ + protected statusIs(process: Process, status: ProcessStatus): boolean { + return hasValue(process) && process.processStatus === status; + } + + /** + * Return true if the given process has the status COMPLETED or FAILED + */ + public hasCompletedOrFailed(process: Process): boolean { + return this.statusIs(process, ProcessStatus.COMPLETED) || + this.statusIs(process, ProcessStatus.FAILED); + } + + /** + * Clear the timeout for the given process, if that timeout exists + * @protected + */ + protected clearCurrentTimeout(processId: string): void { + const timeout = this.activelyBeingPolled.get(processId); + if (hasValue(timeout)) { + clearTimeout(timeout); + } + }; + + /** + * Poll the process with the given ID, using the given interval, until that process either + * completes successfully or fails + * + * Return an Observable for the Process. Note that this will also emit while the + * process is still running. It will only emit again when the process (not the RemoteData!) changes + * status. That makes it more convenient to retrieve that process for a component: you can replace + * a findByID call with this method, rather than having to do a separate findById, and then call + * this method + * @param processId + * @param pollingIntervalInMs + */ + public autoRefreshUntilCompletion(processId: string, pollingIntervalInMs = 5000): Observable> { + const process$ = this.findById(processId, true, true, followLink('script')) .pipe( getAllCompletedRemoteData(), ); - // TODO: this is horrible - const statusIs = (process: Process, status: ProcessStatus) => - process.processStatus === status; - - // If we have to wait too long for the result, we should mark the result as stale. - // However, we should make sure this happens only once (in case there are multiple observers waiting - // for the result). - if (!this.activelyBeingPolled.has(processId)) { - this.activelyBeingPolled.add(processId); - - // Create a subscription that marks the data as stale if the polling interval time has been exceeded. - const sub = process$.subscribe((rd) => { - const process = rd.payload; - if (statusIs(process, ProcessStatus.COMPLETED) || statusIs(process, ProcessStatus.FAILED)) { - this.activelyBeingPolled.delete(processId); - sub.unsubscribe(); - } else { - this.zone.runOutsideAngular(() => - setTimeout(() => { - this.invalidateByHref(process._links.self.href); - }, pollingIntervalInMs) - ); - } - }); - } + // Create a subscription that marks the data as stale if the process hasn't been completed and + // the polling interval time has been exceeded. + const sub = process$.pipe( + filter((processRD: RemoteData) => + !this.hasCompletedOrFailed(processRD.payload) && + !this.activelyBeingPolled.has(processId) + ) + ).subscribe((processRD: RemoteData) => { + this.clearCurrentTimeout(processId); + const nextTimeout = this.timer(() => { + this.activelyBeingPolled.delete(processId); + this.invalidateByHref(processRD.payload._links.self.href); + }, pollingIntervalInMs); + + this.activelyBeingPolled.set(processId, nextTimeout); + }); + + // When the process completes create a one off subscription (the `find` completes the + // observable) that unsubscribes the previous one, removes the processId from the list of + // processes being polled and clears any running timeouts + process$.pipe( + find((processRD: RemoteData) => this.hasCompletedOrFailed(processRD.payload)) + ).subscribe(() => { + this.clearCurrentTimeout(processId); + this.activelyBeingPolled.delete(processId); + sub.unsubscribe(); + }); return process$.pipe( - filter(rd => statusIs(rd.payload, ProcessStatus.COMPLETED) || statusIs(rd.payload, ProcessStatus.FAILED)), - take(1) + distinctUntilChanged((previous: RemoteData, current: RemoteData) => + previous.payload.processStatus === current.payload.processStatus + ) ); } } diff --git a/src/app/process-page/detail/process-detail.component.html b/src/app/process-page/detail/process-detail.component.html index 5f905cbfff3..c25a6ad50a9 100644 --- a/src/app/process-page/detail/process-detail.component.html +++ b/src/app/process-page/detail/process-detail.component.html @@ -5,8 +5,8 @@

{{ 'process.detail.title' | translate:{ id: process?.processId, name: process?.scriptName } }}

-
- Refreshing in {{ seconds }}s +
+ {{ 'process.detail.refreshing' | translate }}
diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index 18992eae2f3..b1d3241422e 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -1,8 +1,8 @@ import { HttpClient } from '@angular/common/http'; import { Component, Inject, NgZone, OnInit, PLATFORM_ID } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { finalize, map, switchMap, take, tap } from 'rxjs/operators'; +import { BehaviorSubject, Observable, Subscription, interval } from 'rxjs'; +import { finalize, map, switchMap, take, tap, filter, find, startWith } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; @@ -14,7 +14,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteData, - getFirstSucceededRemoteDataPayload + getFirstSucceededRemoteDataPayload, getAllSucceededRemoteDataPayload } from '../../core/shared/operators'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { AlertType } from '../../shared/alert/aletr-type'; @@ -26,6 +26,7 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { getProcessListRoute } from '../process-page-routing.paths'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'ds-process-detail', @@ -76,7 +77,7 @@ export class ProcessDetailComponent implements OnInit { */ dateFormat = 'yyyy-MM-dd HH:mm:ss ZZZZ'; - refreshCounter$ = new BehaviorSubject(0); + isRefreshing$: Observable; /** * Reference to NgbModal @@ -105,94 +106,29 @@ export class ProcessDetailComponent implements OnInit { * Display a 404 if the process doesn't exist */ ngOnInit(): void { - // this.processRD$ = this.route.data.pipe( - // map((data) => { - // if (isPlatformBrowser(this.platformId)) { - // if (!this.isProcessFinished(data.process.payload)) { - // this.startRefreshTimer(); - // } - // } - - // return data.process as RemoteData; - // }), - // redirectOn4xx(this.router, this.authService), - // shareReplay(1) - // ); + this.processRD$ = this.route.data.pipe( + switchMap((data) => { + if (isPlatformBrowser(this.platformId)) { + return this.processService.autoRefreshUntilCompletion(this.route.snapshot.params.id, 5000); + } else { + return [data.process as RemoteData]; + } + }), + redirectOn4xx(this.router, this.authService), + ); - this.processRD$ = this.processService.notifyOnCompletion(this.route.snapshot.params.id).pipe( - redirectOn4xx(this.router, this.authService) + this.isRefreshing$ = this.processRD$.pipe( + find((processRD: RemoteData) => this.processService.hasCompletedOrFailed(processRD.payload)), + map(() => false), + startWith(true) ); this.filesRD$ = this.processRD$.pipe( - getFirstSucceededRemoteDataPayload(), + getAllSucceededRemoteDataPayload(), switchMap((process: Process) => this.processService.getFiles(process.processId)) ); } - // refresh() { - - //////////////////////////////////////////////////////////////////////////////// - - // this.processRD$ = this.processService.findById( - // this.route.snapshot.params.id, - // false, - // true, - // followLink('script') - // ).pipe( - // // First get the process state - // getFirstSucceededRemoteData(), - - // // Error if it goes wrong - // redirectOn4xx(this.router, this.authService), - - // // If process is not finished, start the refresh timer - // tap((processRemoteData: RemoteData) => { - // if (!this.isProcessFinished(processRemoteData.payload)) { - // this.startRefreshTimer(); - // } - // }), - - // // ??? - // shareReplay(1) - // ); - // this.filesRD$ = this.processRD$.pipe( - // getFirstSucceededRemoteDataPayload(), - // switchMap((process: Process) => this.processService.getFiles(process.processId)) - // ); - // } - - // // TODO delete - // // call refresh after 5 sec - // startRefreshTimer() { - // this.refreshCounter$.next(0); - // - // // TODO delete comment - // // This fires every 1000 ms with an incrementing value. - // // So the first time this fires, it adds the value 5 to the refresh counter - // // the second time, it adds the value 4, - // // etc. - // // If the value exceeds 5, the refresh timer is stopped and this.refresh is called. - // this.refreshTimerSub = interval(1000).subscribe( - // value => { - // if (value > 5) { - // setTimeout(() => { - // this.refresh(); - // this.stopRefreshTimer(); - // this.refreshCounter$.next(0); - // }, 1); - // } else { - // this.refreshCounter$.next(5 - value); - // } - // }); - // } - // - // stopRefreshTimer() { - // if (hasValue(this.refreshTimerSub)) { - // this.refreshTimerSub.unsubscribe(); - // this.refreshTimerSub = undefined; - // } - // } - /** * Get the name of a bitstream * @param bitstream diff --git a/src/app/process-page/processes/process-status.model.ts b/src/app/process-page/processes/process-status.model.ts index b43340bffb7..1ff42789d81 100644 --- a/src/app/process-page/processes/process-status.model.ts +++ b/src/app/process-page/processes/process-status.model.ts @@ -2,8 +2,8 @@ * List of process statuses */ export enum ProcessStatus { - SCHEDULED, - RUNNING, - COMPLETED, - FAILED + SCHEDULED = 'SCHEDULED', + RUNNING = 'RUNNING', + COMPLETED = 'COMPLETED', + FAILED = 'FAILED' } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6c91bae4c16..aa327c79341 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3216,6 +3216,8 @@ "process.detail.delete.error": "Something went wrong when deleting the process", + "process.detail.refreshing": "Auto-refreshing…", + "process.overview.table.finish": "Finish time (UTC)", "process.overview.table.id": "Process ID", From a59776d5a00b50497e987b372c91b28b17bf5152 Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Fri, 1 Sep 2023 15:10:39 +0200 Subject: [PATCH 058/592] Failed attempt at fixing process-detail.component.spec.ts tests --- .../processes/process-data.service.spec.ts | 29 ------------------- .../detail/process-detail.component.spec.ts | 9 ++++-- .../detail/process-detail.component.ts | 6 +++- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index f58752ee973..fe632096f5d 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -124,34 +124,5 @@ describe('ProcessDataService', () => { expect(processDataService.findById).toHaveBeenCalledTimes(1); expect(processDataService.invalidateByHref).toHaveBeenCalledTimes(1); }); - }); - -// /** -// * Tests whether calls to `FindAllData` methods are correctly patched through in a concrete data service that implements it -// */ -// export function testFindAllDataImplementation(serviceFactory: () => FindAllData) { -// let service; -// -// describe('FindAllData implementation', () => { -// const OPTIONS = Object.assign(new FindListOptions(), { elementsPerPage: 10, currentPage: 3 }); -// const FOLLOWLINKS = [ -// followLink('test'), -// followLink('something'), -// ]; -// -// beforeAll(() => { -// service = serviceFactory(); -// (service as any).findAllData = jasmine.createSpyObj('findAllData', { -// findAll: 'TEST findAll', -// }); -// }); -// -// it('should handle calls to findAll', () => { -// const out: any = service.findAll(OPTIONS, false, true, ...FOLLOWLINKS); -// -// expect((service as any).findAllData.findAll).toHaveBeenCalledWith(OPTIONS, false, true, ...FOLLOWLINKS); -// expect(out).toBe('TEST findAll'); -// }); -// }); }); diff --git a/src/app/process-page/detail/process-detail.component.spec.ts b/src/app/process-page/detail/process-detail.component.spec.ts index 68b97d0e5cd..ba99342191a 100644 --- a/src/app/process-page/detail/process-detail.component.spec.ts +++ b/src/app/process-page/detail/process-detail.component.spec.ts @@ -106,10 +106,12 @@ describe('ProcessDetailComponent', () => { content: { href: 'log-selflink' } } }); + const processRD$ = createSuccessfulRemoteDataObject$(process); processService = jasmine.createSpyObj('processService', { getFiles: createSuccessfulRemoteDataObject$(createPaginatedList(files)), delete: createSuccessfulRemoteDataObject$(null), - findById: createSuccessfulRemoteDataObject$(process), + findById: processRD$, + autoRefreshUntilCompletion: processRD$ }); bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', { findByHref: createSuccessfulRemoteDataObject$(logBitstream) @@ -132,7 +134,7 @@ describe('ProcessDetailComponent', () => { }); route = jasmine.createSpyObj('route', { - data: observableOf({ process: createSuccessfulRemoteDataObject(process) }), + data: observableOf({ process: processRD$ }), snapshot: { params: { id: process.processId } } @@ -158,7 +160,8 @@ describe('ProcessDetailComponent', () => { { provide: NotificationsService, useValue: notificationsService }, { provide: Router, useValue: router }, ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + // schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [] }).compileComponents(); })); diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index b1d3241422e..d96c47b3713 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -109,7 +109,10 @@ export class ProcessDetailComponent implements OnInit { this.processRD$ = this.route.data.pipe( switchMap((data) => { if (isPlatformBrowser(this.platformId)) { - return this.processService.autoRefreshUntilCompletion(this.route.snapshot.params.id, 5000); + const x = this.processService.autoRefreshUntilCompletion(this.route.snapshot.params.id, 5000); + //[data.process as RemoteData]; + console.log("ASDF", x); + return x; } else { return [data.process as RemoteData]; } @@ -117,6 +120,7 @@ export class ProcessDetailComponent implements OnInit { redirectOn4xx(this.router, this.authService), ); + this.processRD$.subscribe(x => console.log("QWER", x)); this.isRefreshing$ = this.processRD$.pipe( find((processRD: RemoteData) => this.processService.hasCompletedOrFailed(processRD.payload)), map(() => false), From 53b0af100d5dcbd07d5ac2f8c8744da7ed7240be Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Fri, 1 Sep 2023 16:11:32 +0200 Subject: [PATCH 059/592] 104938 Fix ProcessDetailComponent tests --- .../collection-source-controls.component.ts | 3 +- .../processes/process-data.service.spec.ts | 6 +-- .../data/processes/process-data.service.ts | 38 +++++++++---------- .../detail/process-detail.component.spec.ts | 18 +++++---- .../detail/process-detail.component.ts | 12 ++---- 5 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts index ea2cb3e2f49..58f41acf344 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts @@ -3,13 +3,12 @@ import { ScriptDataService } from '../../../../core/data/processes/script-data.s import { ContentSource } from '../../../../core/shared/content-source.model'; import { ProcessDataService } from '../../../../core/data/processes/process-data.service'; import { - getAllCompletedRemoteData, getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; import { filter, map, switchMap, tap } from 'rxjs/operators'; -import { hasValue, hasValueOperator } from '../../../../shared/empty.util'; +import { hasValue } from '../../../../shared/empty.util'; import { ProcessStatus } from '../../../../process-page/processes/process-status.model'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { RequestService } from '../../../../core/data/request.service'; diff --git a/src/app/core/data/processes/process-data.service.spec.ts b/src/app/core/data/processes/process-data.service.spec.ts index fe632096f5d..d66560b0834 100644 --- a/src/app/core/data/processes/process-data.service.spec.ts +++ b/src/app/core/data/processes/process-data.service.spec.ts @@ -9,7 +9,7 @@ import { testFindAllDataImplementation } from '../base/find-all-data.spec'; import { ProcessDataService, TIMER_FACTORY } from './process-data.service'; import { testDeleteDataImplementation } from '../base/delete-data.spec'; -import { waitForAsync, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { waitForAsync, TestBed } from '@angular/core/testing'; import { RequestService } from '../request.service'; import { RemoteData } from '../remote-data'; import { RequestEntryState } from '../request-entry-state.model'; @@ -22,9 +22,7 @@ import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { DSOChangeAnalyzer } from '../dso-change-analyzer.service'; import { BitstreamFormatDataService } from '../bitstream-format-data.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { TestScheduler, RunHelpers } from 'rxjs/testing'; -import { cold } from 'jasmine-marbles'; -import { of } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; describe('ProcessDataService', () => { let testScheduler; diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index a639ef24eae..e17b0b1f196 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -35,6 +35,22 @@ export const TIMER_FACTORY = new InjectionToken<(callback: (...args: any[]) => v @Injectable() @dataService(PROCESS) export class ProcessDataService extends IdentifiableDataService implements FindAllData, DeleteData { + /** + * Return true if the given process has the given status + * @protected + */ + protected static statusIs(process: Process, status: ProcessStatus): boolean { + return hasValue(process) && process.processStatus === status; + } + + /** + * Return true if the given process has the status COMPLETED or FAILED + */ + public static hasCompletedOrFailed(process: Process): boolean { + return ProcessDataService.statusIs(process, ProcessStatus.COMPLETED) || + ProcessDataService.statusIs(process, ProcessStatus.FAILED); + } + private findAllData: FindAllData; private deleteData: DeleteData; protected activelyBeingPolled: Map = new Map(); @@ -117,22 +133,6 @@ export class ProcessDataService extends IdentifiableDataService impleme return this.deleteData.deleteByHref(href, copyVirtualMetadata); } - /** - * Return true if the given process has the given status - * @protected - */ - protected statusIs(process: Process, status: ProcessStatus): boolean { - return hasValue(process) && process.processStatus === status; - } - - /** - * Return true if the given process has the status COMPLETED or FAILED - */ - public hasCompletedOrFailed(process: Process): boolean { - return this.statusIs(process, ProcessStatus.COMPLETED) || - this.statusIs(process, ProcessStatus.FAILED); - } - /** * Clear the timeout for the given process, if that timeout exists * @protected @@ -142,7 +142,7 @@ export class ProcessDataService extends IdentifiableDataService impleme if (hasValue(timeout)) { clearTimeout(timeout); } - }; + } /** * Poll the process with the given ID, using the given interval, until that process either @@ -166,7 +166,7 @@ export class ProcessDataService extends IdentifiableDataService impleme // the polling interval time has been exceeded. const sub = process$.pipe( filter((processRD: RemoteData) => - !this.hasCompletedOrFailed(processRD.payload) && + !ProcessDataService.hasCompletedOrFailed(processRD.payload) && !this.activelyBeingPolled.has(processId) ) ).subscribe((processRD: RemoteData) => { @@ -183,7 +183,7 @@ export class ProcessDataService extends IdentifiableDataService impleme // observable) that unsubscribes the previous one, removes the processId from the list of // processes being polled and clears any running timeouts process$.pipe( - find((processRD: RemoteData) => this.hasCompletedOrFailed(processRD.payload)) + find((processRD: RemoteData) => ProcessDataService.hasCompletedOrFailed(processRD.payload)) ).subscribe(() => { this.clearCurrentTimeout(processId); this.activelyBeingPolled.delete(processId); diff --git a/src/app/process-page/detail/process-detail.component.spec.ts b/src/app/process-page/detail/process-detail.component.spec.ts index ba99342191a..1af1edca995 100644 --- a/src/app/process-page/detail/process-detail.component.spec.ts +++ b/src/app/process-page/detail/process-detail.component.spec.ts @@ -35,7 +35,6 @@ import { NotificationsServiceStub } from '../../shared/testing/notifications-ser import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { getProcessListRoute } from '../process-page-routing.paths'; -import {ProcessStatus} from '../processes/process-status.model'; describe('ProcessDetailComponent', () => { let component: ProcessDetailComponent; @@ -106,12 +105,11 @@ describe('ProcessDetailComponent', () => { content: { href: 'log-selflink' } } }); - const processRD$ = createSuccessfulRemoteDataObject$(process); processService = jasmine.createSpyObj('processService', { getFiles: createSuccessfulRemoteDataObject$(createPaginatedList(files)), delete: createSuccessfulRemoteDataObject$(null), - findById: processRD$, - autoRefreshUntilCompletion: processRD$ + findById: createSuccessfulRemoteDataObject$(process), + autoRefreshUntilCompletion: createSuccessfulRemoteDataObject$(process) }); bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', { findByHref: createSuccessfulRemoteDataObject$(logBitstream) @@ -134,7 +132,7 @@ describe('ProcessDetailComponent', () => { }); route = jasmine.createSpyObj('route', { - data: observableOf({ process: processRD$ }), + data: observableOf({ process: createSuccessfulRemoteDataObject$(process) }), snapshot: { params: { id: process.processId } } @@ -149,7 +147,12 @@ describe('ProcessDetailComponent', () => { providers: [ { provide: ActivatedRoute, - useValue: { data: observableOf({ process: createSuccessfulRemoteDataObject(process) }) } + useValue: { + data: observableOf({ process: createSuccessfulRemoteDataObject(process) }), + snapshot: { + params: { id: process.processId } + } + } }, { provide: ProcessDataService, useValue: processService }, { provide: BitstreamDataService, useValue: bitstreamDataService }, @@ -160,8 +163,7 @@ describe('ProcessDetailComponent', () => { { provide: NotificationsService, useValue: notificationsService }, { provide: Router, useValue: router }, ], - // schemas: [CUSTOM_ELEMENTS_SCHEMA] - schemas: [] + schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); })); diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index d96c47b3713..c8e4507fd29 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -1,8 +1,8 @@ import { HttpClient } from '@angular/common/http'; import { Component, Inject, NgZone, OnInit, PLATFORM_ID } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject, Observable, Subscription, interval } from 'rxjs'; -import { finalize, map, switchMap, take, tap, filter, find, startWith } from 'rxjs/operators'; +import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { finalize, map, switchMap, take, tap, find, startWith } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; @@ -109,10 +109,7 @@ export class ProcessDetailComponent implements OnInit { this.processRD$ = this.route.data.pipe( switchMap((data) => { if (isPlatformBrowser(this.platformId)) { - const x = this.processService.autoRefreshUntilCompletion(this.route.snapshot.params.id, 5000); - //[data.process as RemoteData]; - console.log("ASDF", x); - return x; + return this.processService.autoRefreshUntilCompletion(this.route.snapshot.params.id, 5000); } else { return [data.process as RemoteData]; } @@ -120,9 +117,8 @@ export class ProcessDetailComponent implements OnInit { redirectOn4xx(this.router, this.authService), ); - this.processRD$.subscribe(x => console.log("QWER", x)); this.isRefreshing$ = this.processRD$.pipe( - find((processRD: RemoteData) => this.processService.hasCompletedOrFailed(processRD.payload)), + find((processRD: RemoteData) => ProcessDataService.hasCompletedOrFailed(processRD.payload)), map(() => false), startWith(true) ); From 07527e11700f0f4c0b59cc60faf6519af8fd0166 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Sun, 3 Sep 2023 13:44:47 +0200 Subject: [PATCH 060/592] CST-11012 removed extra comment --- src/app/footer/footer.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/footer/footer.component.ts b/src/app/footer/footer.component.ts index 4b04a8f5dc2..c9b8c42bfcd 100644 --- a/src/app/footer/footer.component.ts +++ b/src/app/footer/footer.component.ts @@ -18,7 +18,7 @@ export class FooterComponent { showTopFooter = false; showPrivacyPolicy = environment.info.enablePrivacyStatement; showEndUserAgreement = environment.info.enableEndUserAgreement; - coarLdnEnabled: boolean; // Add this line + coarLdnEnabled: boolean; constructor( @Optional() private cookies: KlaroService, From 1f5f0555ddff091b39a52d09af43f3e549e46946 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Sun, 3 Sep 2023 14:02:47 +0200 Subject: [PATCH 061/592] CST-11012 removed not needed path in app-routing-paths.ts --- src/app/app-routing-paths.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index 518622c8d1e..efc60bb5e48 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -34,10 +34,6 @@ export function getBitstreamRequestACopyRoute(item, bitstream): { routerLink: st export const COAR_NOTIFY_SUPPORT = 'coar-notify-support'; -export function getCoarNotifyInfoRoute() { - return `/${COAR_NOTIFY_SUPPORT}`; -} - export const HOME_PAGE_PATH = 'admin'; export function getHomePageRoute() { From 18aa0bbd96ddb0c9014833302cdb71a15e901358 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Sun, 3 Sep 2023 14:03:25 +0200 Subject: [PATCH 062/592] CST-11012 removed not needed path in app-routing-paths.ts --- src/app/app-routing-paths.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index efc60bb5e48..fe2837c6e3f 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -32,8 +32,6 @@ export function getBitstreamRequestACopyRoute(item, bitstream): { routerLink: st }; } -export const COAR_NOTIFY_SUPPORT = 'coar-notify-support'; - export const HOME_PAGE_PATH = 'admin'; export function getHomePageRoute() { From eb82628164f070f96f27b4200756388e52797068 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Sun, 3 Sep 2023 17:42:26 +0200 Subject: [PATCH 063/592] CST-11012 needed path in app-routing-paths.ts --- src/app/app-routing-paths.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index fe2837c6e3f..3722383745f 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -31,6 +31,7 @@ export function getBitstreamRequestACopyRoute(item, bitstream): { routerLink: st } }; } +export const COAR_NOTIFY_SUPPORT = 'coar-notify-support'; export const HOME_PAGE_PATH = 'admin'; From 9b5001e1d987bde1dd57248c35a69ae60bb8ea48 Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Thu, 7 Sep 2023 10:19:33 +0200 Subject: [PATCH 064/592] 104938 Cleanup --- .../collection-source-controls.component.ts | 81 ----------------- .../detail/process-detail.component.spec.ts | 89 ------------------- 2 files changed, 170 deletions(-) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts index 58f41acf344..185a1f938ef 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts @@ -113,36 +113,6 @@ export class CollectionSourceControlsComponent implements OnDestroy { this.testConfigRunning$.next(false); } })); - - // getAllCompletedRemoteData(), - // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - // map((rd) => rd.payload), - // hasValueOperator(), - // ).subscribe((process: Process) => { - // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // // Ping the current process state every 5s - // setTimeout(() => { - // this.requestService.setStaleByHrefSubstring(process._links.self.href); - // }, 5000); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - // this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed')); - // this.testConfigRunning$.next(false); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - // this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => { - // this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => { - // const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1') - // .replaceAll('The script has started', '') - // .replaceAll('The script has completed', ''); - // this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output); - // }); - // }); - // this.testConfigRunning$.next(false); - // } - // } - // )); } /** @@ -178,31 +148,6 @@ export class CollectionSourceControlsComponent implements OnDestroy { this.importRunning$.next(false); } })); - - // getAllCompletedRemoteData(), - // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - // map((rd) => rd.payload), - // hasValueOperator(), - // ).subscribe((process) => { - // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // // Ping the current process state every 5s - // setTimeout(() => { - // this.requestService.setStaleByHrefSubstring(process._links.self.href); - // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - // }, 5000); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - // this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed')); - // this.importRunning$.next(false); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - // this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed')); - // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - // this.importRunning$.next(false); - // } - // } - // )); } /** @@ -238,32 +183,6 @@ export class CollectionSourceControlsComponent implements OnDestroy { this.reImportRunning$.next(false); } })); - - // switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)), - // getAllCompletedRemoteData(), - // filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)), - // map((rd) => rd.payload), - // hasValueOperator(), - // ).subscribe((process) => { - // if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() && - // process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) { - // // Ping the current process state every 5s - // setTimeout(() => { - // this.requestService.setStaleByHrefSubstring(process._links.self.href); - // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - // }, 5000); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { - // this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed')); - // this.reImportRunning$.next(false); - // } - // if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { - // this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed')); - // this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); - // this.reImportRunning$.next(false); - // } - // } - // )); } ngOnDestroy(): void { diff --git a/src/app/process-page/detail/process-detail.component.spec.ts b/src/app/process-page/detail/process-detail.component.spec.ts index 1af1edca995..241af9fd100 100644 --- a/src/app/process-page/detail/process-detail.component.spec.ts +++ b/src/app/process-page/detail/process-detail.component.spec.ts @@ -277,93 +277,4 @@ describe('ProcessDetailComponent', () => { expect(router.navigateByUrl).not.toHaveBeenCalled(); }); }); - - // describe('refresh counter', () => { - // const queryRefreshCounter = () => fixture.debugElement.query(By.css('.refresh-counter')); - - // describe('if process is completed', () => { - // beforeEach(() => { - // process.processStatus = ProcessStatus.COMPLETED; - // route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); - // }); - - // it('should not show', () => { - // spyOn(component, 'startRefreshTimer'); - - // const refreshCounter = queryRefreshCounter(); - // expect(refreshCounter).toBeNull(); - - // expect(component.startRefreshTimer).not.toHaveBeenCalled(); - // }); - // }); - - // describe('if process is not finished', () => { - // beforeEach(() => { - // process.processStatus = ProcessStatus.RUNNING; - // route.data = observableOf({process: createSuccessfulRemoteDataObject(process)}); - // fixture.detectChanges(); - // component.stopRefreshTimer(); - // }); - - // it('should call startRefreshTimer', () => { - // spyOn(component, 'startRefreshTimer'); - - // component.ngOnInit(); - // fixture.detectChanges(); // subscribe to process observable with async pipe - - // expect(component.startRefreshTimer).toHaveBeenCalled(); - // }); - - // it('should call refresh method every 5 seconds, until process is completed', fakeAsync(() => { - // spyOn(component, 'refresh'); - // spyOn(component, 'stopRefreshTimer'); - - // process.processStatus = ProcessStatus.COMPLETED; - // // set findbyId to return a completed process - // (processService.findById as jasmine.Spy).and.returnValue(observableOf(createSuccessfulRemoteDataObject(process))); - - // component.ngOnInit(); - // fixture.detectChanges(); // subscribe to process observable with async pipe - - // expect(component.refresh).not.toHaveBeenCalled(); - - // expect(component.refreshCounter$.value).toBe(0); - - // tick(1001); // 1 second + 1 ms by the setTimeout - // expect(component.refreshCounter$.value).toBe(5); // 5 - 0 - - // tick(2001); // 2 seconds + 1 ms by the setTimeout - // expect(component.refreshCounter$.value).toBe(3); // 5 - 2 - - // tick(2001); // 2 seconds + 1 ms by the setTimeout - // expect(component.refreshCounter$.value).toBe(1); // 3 - 2 - - // tick(1001); // 1 second + 1 ms by the setTimeout - // expect(component.refreshCounter$.value).toBe(0); // 1 - 1 - - // tick(1000); // 1 second - - // expect(component.refresh).toHaveBeenCalledTimes(1); - // expect(component.stopRefreshTimer).toHaveBeenCalled(); - - // expect(component.refreshCounter$.value).toBe(0); - - // tick(1001); // 1 second + 1 ms by the setTimeout - // // startRefreshTimer not called again - // expect(component.refreshCounter$.value).toBe(0); - - // discardPeriodicTasks(); // discard any periodic tasks that have not yet executed - // })); - - // it('should show if refreshCounter is different from 0', () => { - // component.refreshCounter$.next(1); - // fixture.detectChanges(); - - // const refreshCounter = queryRefreshCounter(); - // expect(refreshCounter).not.toBeNull(); - // }); - - // }); - - // }); }); From 11e98f7e20894e4badb6d2ed3a78d155f56e6a2c Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Thu, 7 Sep 2023 11:36:52 +0200 Subject: [PATCH 065/592] Fix lint issue. --- src/app/core/data/processes/process-data.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index e17b0b1f196..3af755561c1 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -35,6 +35,10 @@ export const TIMER_FACTORY = new InjectionToken<(callback: (...args: any[]) => v @Injectable() @dataService(PROCESS) export class ProcessDataService extends IdentifiableDataService implements FindAllData, DeleteData { + private findAllData: FindAllData; + private deleteData: DeleteData; + protected activelyBeingPolled: Map = new Map(); + /** * Return true if the given process has the given status * @protected @@ -51,10 +55,6 @@ export class ProcessDataService extends IdentifiableDataService impleme ProcessDataService.statusIs(process, ProcessStatus.FAILED); } - private findAllData: FindAllData; - private deleteData: DeleteData; - protected activelyBeingPolled: Map = new Map(); - constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, From f9e4044e8141c290584a93fda9a0b334f2a66965 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Thu, 14 Sep 2023 17:06:14 +0200 Subject: [PATCH 066/592] CST-11012 fixed conflicts --- src/app/footer/footer.component.ts | 6 +++--- src/assets/i18n/en.json5 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/footer/footer.component.ts b/src/app/footer/footer.component.ts index c9b8c42bfcd..1759dd16234 100644 --- a/src/app/footer/footer.component.ts +++ b/src/app/footer/footer.component.ts @@ -20,9 +20,9 @@ export class FooterComponent { showEndUserAgreement = environment.info.enableEndUserAgreement; coarLdnEnabled: boolean; - constructor( - @Optional() private cookies: KlaroService, - private notifyInfoService: NotifyInfoService + constructor(@Optional() + private cookies: KlaroService, + private notifyInfoService: NotifyInfoService ) { this.notifyInfoService.isCoarConfigEnabled().subscribe(coarLdnEnabled => { this.coarLdnEnabled = coarLdnEnabled; diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 65bf1ebaaa8..32e2549518f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3617,7 +3617,7 @@ "repository.image.logo": "Repository logo", - "repository.title.prefix": "Demo of COAR Notify in DSpace 7 :: ", + "repository.title.prefix": "DSpace Angular :: ", "repository.title.prefixDSpace": "DSpace Angular ::", From ed5267820e6619d0723bbbd4e0859a069b9a26e5 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Thu, 6 Jul 2023 16:17:53 -0400 Subject: [PATCH 067/592] Update dependencies for Node v20. --- package.json | 4 +- yarn.lock | 257 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 172 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index 977a4bdc5ec..7135b2d1116 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,7 @@ "@angular-eslint/eslint-plugin-template": "15.2.1", "@angular-eslint/schematics": "15.2.1", "@angular-eslint/template-parser": "15.2.1", - "@angular/cli": "^15.2.6", + "@angular/cli": "^16.0.4", "@angular/compiler-cli": "^15.2.8", "@angular/language-service": "^15.2.8", "@cypress/schematic": "^1.5.0", @@ -169,7 +169,7 @@ "eslint": "^8.39.0", "eslint-plugin-deprecation": "^1.4.1", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jsdoc": "^39.6.4", + "eslint-plugin-jsdoc": "^45.0.0", "eslint-plugin-jsonc": "^2.6.0", "eslint-plugin-lodash": "^7.4.0", "eslint-plugin-unused-imports": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index e53a070d167..771b2e326bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47,6 +47,14 @@ "@angular-devkit/core" "15.2.6" rxjs "6.6.7" +"@angular-devkit/architect@0.1601.4": + version "0.1601.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1601.4.tgz#9fc88461cb65e28508067d93acc1aba69ca7a9ec" + integrity sha512-OOSbNlDy+Q3jY0oFHaq8kkna9HYI1zaS8IHeCIDP6T/ZIAVad4+HqXAL4SKQrKJikkoBQv1Z/eaDBL5XPFK9Bw== + dependencies: + "@angular-devkit/core" "16.1.4" + rxjs "7.8.1" + "@angular-devkit/architect@^0.1202.10": version "0.1202.18" resolved "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.18.tgz" @@ -241,6 +249,17 @@ rxjs "6.6.7" source-map "0.7.4" +"@angular-devkit/core@16.1.4": + version "16.1.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-16.1.4.tgz#033ff3ab4d024ee3d8f4c6f809eed10d716ad0ab" + integrity sha512-WCAzNi9LxpFIi2WVPaJQd2kHPqCnCexWzUZN05ltJuBGCQL1O+LgRHGwnQ4WZoqmrF5tcWt2a3GFtJ3DgMc1hw== + dependencies: + ajv "8.12.0" + ajv-formats "2.1.1" + jsonc-parser "3.2.0" + rxjs "7.8.1" + source-map "0.7.4" + "@angular-devkit/schematics@12.2.18", "@angular-devkit/schematics@^12.2.17": version "12.2.18" resolved "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.18.tgz" @@ -250,16 +269,16 @@ ora "5.4.1" rxjs "6.6.7" -"@angular-devkit/schematics@15.2.6": - version "15.2.6" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.2.6.tgz#fb5b7530f21586dbdec45cac56f8a418bcfd053d" - integrity sha512-f7VgnAcok7AwR/DhX0ZWskB0rFBo/KsvtIUA2qZSrpKMf8eFiwu03dv/b2mI0vnf+1FBfIQzJvO0ww45zRp6dA== +"@angular-devkit/schematics@16.1.4": + version "16.1.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-16.1.4.tgz#91d4d82ee273dd7f24c17b9c7fbbfff11d7cab63" + integrity sha512-yjRgwHAfFaeuimgbQtjwSUyXzEHpMSdTRb2zg+TOp6skoGvHOG8xXFJ7DjBkSMeAQdFF0fkxhPS9YmlxqNc+7A== dependencies: - "@angular-devkit/core" "15.2.6" + "@angular-devkit/core" "16.1.4" jsonc-parser "3.2.0" - magic-string "0.29.0" + magic-string "0.30.0" ora "5.4.1" - rxjs "6.6.7" + rxjs "7.8.1" "@angular-eslint/builder@15.2.1": version "15.2.1" @@ -334,29 +353,29 @@ optionalDependencies: parse5 "^7.1.2" -"@angular/cli@^15.2.6": - version "15.2.6" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-15.2.6.tgz#d5994fbd4d02e71017d4dd28ba06dc1c3cb7a976" - integrity sha512-wNkQ/qCVbd4pERaGVagKJPifEvjRNY5otwsd4iRVubY/XOcIHcYChUThZwgQdVfNAImfJPMZNrhbGxejuWLA9w== +"@angular/cli@^16.0.4": + version "16.1.4" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-16.1.4.tgz#b32de345b6fdb4e975f957b0f9cbcafdcf184f8a" + integrity sha512-coSOLVLpOCOD5q9K9EAFFMrTES+HtdJiLy/iI9kdKNCKWUJpm8/svZ3JZOej3vPxYEp0AokXNOwORQnX21/qZQ== dependencies: - "@angular-devkit/architect" "0.1502.6" - "@angular-devkit/core" "15.2.6" - "@angular-devkit/schematics" "15.2.6" - "@schematics/angular" "15.2.6" + "@angular-devkit/architect" "0.1601.4" + "@angular-devkit/core" "16.1.4" + "@angular-devkit/schematics" "16.1.4" + "@schematics/angular" "16.1.4" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.3" - ini "3.0.1" + ini "4.1.1" inquirer "8.2.4" jsonc-parser "3.2.0" npm-package-arg "10.1.0" npm-pick-manifest "8.0.1" - open "8.4.1" + open "8.4.2" ora "5.4.1" - pacote "15.1.0" - resolve "1.22.1" - semver "7.3.8" + pacote "15.2.0" + resolve "1.22.2" + semver "7.5.3" symbol-observable "4.0.0" - yargs "17.6.2" + yargs "17.7.2" "@angular/common@^15.2.8": version "15.2.8" @@ -1610,14 +1629,14 @@ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@es-joy/jsdoccomment@~0.36.1": - version "0.36.1" - resolved "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz" - integrity sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg== +"@es-joy/jsdoccomment@~0.39.4": + version "0.39.4" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz#6b8a62e9b3077027837728818d3c4389a898b392" + integrity sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg== dependencies: comment-parser "1.3.1" - esquery "^1.4.0" - jsdoc-type-pratt-parser "~3.1.0" + esquery "^1.5.0" + jsdoc-type-pratt-parser "~4.0.0" "@esbuild/android-arm64@0.17.8": version "0.17.8" @@ -2239,13 +2258,13 @@ resolved "https://registry.npmjs.org/@researchgate/react-intersection-observer/-/react-intersection-observer-1.3.5.tgz" integrity sha512-aYlsex5Dd6BAHMJvJrUoFp8gzgMSL27xFvrxkVYW0bV1RMAapVsO+QeYLtTaSF/QCflktODodvv+wJm49oMnnQ== -"@schematics/angular@15.2.6": - version "15.2.6" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-15.2.6.tgz#5a0face51806f6b2adf67eef73b08c31744b07bc" - integrity sha512-OcBUvVAxZEMBX+fi0ytybeAdmStra+GwtlvipS70yOxcAgJ84ZrnZGN7a072cCVQcq7AgqUfssnyqCx1wu+yCg== +"@schematics/angular@16.1.4": + version "16.1.4" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-16.1.4.tgz#e99a8b7e1b1b9db107727d0e26a05dc190eefeea" + integrity sha512-XfoeL+aBVIR/DzgVKGVhHW/TGQnqWvngyJVuCwXEVWzNfjxHYFkchXa78OItpAvTEr6/Y0Me9FQVAGVA4mMUyg== dependencies: - "@angular-devkit/core" "15.2.6" - "@angular-devkit/schematics" "15.2.6" + "@angular-devkit/core" "16.1.4" + "@angular-devkit/schematics" "16.1.4" jsonc-parser "3.2.0" "@schematics/angular@^12.2.17": @@ -2262,6 +2281,14 @@ resolved "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz" integrity sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ== +"@sigstore/tuf@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-1.0.2.tgz#acbb2c8399fb03aca0c90fa1dc1934bda4160623" + integrity sha512-vjwcYePJzM01Ha6oWWZ9gNcdIgnzyFxfqfWzph483DPJTH8Tb7f7bQRRll3CYVkyH56j0AgcPAcl6Vg95DPF+Q== + dependencies: + "@sigstore/protobuf-specs" "^0.1.0" + tuf-js "^1.1.7" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" @@ -2302,13 +2329,13 @@ resolved "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz" integrity sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ== -"@tufjs/models@1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@tufjs/models/-/models-1.0.2.tgz" - integrity sha512-uxarDtxTIK3f8hJS4yFhW/lvTa3tsiQU5iDCRut+NCnOXvNtEul0Ct58NIIcIx9Rkt7OFEK31Ndpqsd663nsew== +"@tufjs/models@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-1.0.4.tgz#5a689630f6b9dbda338d4b208019336562f176ef" + integrity sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A== dependencies: "@tufjs/canonical-json" "1.0.0" - minimatch "^8.0.3" + minimatch "^9.0.0" "@types/body-parser@*": version "1.19.2" @@ -3172,6 +3199,11 @@ arch@^2.2.0: resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== +are-docs-informative@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" + integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== + are-we-there-yet@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" @@ -5236,17 +5268,18 @@ eslint-plugin-import@^2.27.5: semver "^6.3.0" tsconfig-paths "^3.14.1" -eslint-plugin-jsdoc@^39.6.4: - version "39.9.1" - resolved "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.9.1.tgz" - integrity sha512-Rq2QY6BZP2meNIs48aZ3GlIlJgBqFCmR55+UBvaDkA3ZNQ0SvQXOs2QKkubakEijV8UbIVbVZKsOVN8G3MuqZw== +eslint-plugin-jsdoc@^45.0.0: + version "45.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-45.0.0.tgz#6be84e4842a7138cc571a907ea9c31c42eaac5c0" + integrity sha512-l2+Jcs/Ps7oFA+SWY+0sweU/e5LgricnEl6EsDlyRTF5y0+NWL1y9Qwz9PHwHAxtdJq6lxPjEQWmYLMkvhzD4g== dependencies: - "@es-joy/jsdoccomment" "~0.36.1" + "@es-joy/jsdoccomment" "~0.39.4" + are-docs-informative "^0.0.2" comment-parser "1.3.1" debug "^4.3.4" escape-string-regexp "^4.0.0" - esquery "^1.4.0" - semver "^7.3.8" + esquery "^1.5.0" + semver "^7.5.1" spdx-expression-parse "^3.0.1" eslint-plugin-jsonc@^2.6.0: @@ -5383,7 +5416,7 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0, esquery@^1.4.2: +esquery@^1.4.2, esquery@^1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -6531,10 +6564,10 @@ ini@2.0.0: resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz" - integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ== +ini@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" + integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== ini@^1.3.4: version "1.3.8" @@ -6664,7 +6697,7 @@ is-ci@^3.0.0: dependencies: ci-info "^3.2.0" -is-core-module@^2.11.0, is-core-module@^2.8.1, is-core-module@^2.9.0: +is-core-module@^2.11.0, is-core-module@^2.8.1: version "2.12.0" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz" integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== @@ -7053,10 +7086,10 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdoc-type-pratt-parser@~3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz" - integrity sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw== +jsdoc-type-pratt-parser@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" + integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== jsdom@21.1.0: version "21.1.0" @@ -7682,6 +7715,13 @@ magic-string@0.29.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" +magic-string@0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.0.tgz#fd58a4748c5c4547338a424e90fa5dd17f4de529" + integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + magic-string@^0.27.0: version "0.27.0" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz" @@ -7752,6 +7792,27 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: socks-proxy-agent "^7.0.0" ssri "^10.0.0" +make-fetch-happen@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" + integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== + dependencies: + agentkeepalive "^4.2.1" + cacache "^17.0.0" + http-cache-semantics "^4.1.1" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.7.1" + minipass "^5.0.0" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^7.0.0" + ssri "^10.0.0" + manifesto.js@^4.2.0: version "4.2.17" resolved "https://registry.npmjs.org/manifesto.js/-/manifesto.js-4.2.17.tgz" @@ -7925,13 +7986,20 @@ minimatch@^7.4.2: dependencies: brace-expansion "^2.0.1" -minimatch@^8.0.2, minimatch@^8.0.3: +minimatch@^8.0.2: version "8.0.4" resolved "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz" integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.0: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -8529,6 +8597,15 @@ open@8.4.1: is-docker "^2.1.1" is-wsl "^2.2.0" +open@8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + open@^8.0.9: version "8.4.0" resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz" @@ -8657,10 +8734,10 @@ p-try@^2.0.0: resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@15.1.0: - version "15.1.0" - resolved "https://registry.npmjs.org/pacote/-/pacote-15.1.0.tgz" - integrity sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg== +pacote@15.2.0: + version "15.2.0" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-15.2.0.tgz#0f0dfcc3e60c7b39121b2ac612bf8596e95344d3" + integrity sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA== dependencies: "@npmcli/git" "^4.0.0" "@npmcli/installed-package-contents" "^2.0.1" @@ -8668,7 +8745,7 @@ pacote@15.1.0: "@npmcli/run-script" "^6.0.0" cacache "^17.0.0" fs-minipass "^3.0.0" - minipass "^4.0.0" + minipass "^5.0.0" npm-package-arg "^10.0.0" npm-packlist "^7.0.0" npm-pick-manifest "^8.0.0" @@ -8677,7 +8754,7 @@ pacote@15.1.0: promise-retry "^2.0.1" read-package-json "^6.0.0" read-package-json-fast "^3.0.0" - sigstore "^1.0.0" + sigstore "^1.3.0" ssri "^10.0.0" tar "^6.1.11" @@ -9845,16 +9922,7 @@ resolve-url-loader@5.0.0: postcss "^8.2.14" source-map "0.6.1" -resolve@1.22.1: - version "1.22.1" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.9.0: +resolve@1.22.2, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.9.0: version "1.22.2" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -9969,6 +10037,13 @@ rxjs@6.6.7, rxjs@^6.5.5, rxjs@~6.6.0: dependencies: tslib "^1.9.0" +rxjs@7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + rxjs@^7.5.1, rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" @@ -10121,6 +10196,13 @@ semver@7.3.8: dependencies: lru-cache "^6.0.0" +semver@7.5.3, semver@^7.5.1: + version "7.5.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== + dependencies: + lru-cache "^6.0.0" + semver@^5.3.0, semver@^5.6.0, semver@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -10291,14 +10373,14 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -sigstore@^1.0.0: - version "1.2.0" - resolved "https://registry.npmjs.org/sigstore/-/sigstore-1.2.0.tgz" - integrity sha512-Fr9+W1nkBSIZCkJQR7jDn/zI0UXNsVpp+7mDQkCnZOIxG9p6yNXBx9xntHsfUyYHE55XDkkVV3+rYbrkzAeesA== +sigstore@^1.3.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.7.0.tgz#9186e6c8ce1ab0cba5d97b414212d40f0a01564e" + integrity sha512-KP7QULhWdlu3hlp+jw2EvgWKlOGOY9McLj/jrchLjHNlNPK0KWIwF919cbmOp6QiKXLmPijR2qH/5KYWlbtG9Q== dependencies: "@sigstore/protobuf-specs" "^0.1.0" + "@sigstore/tuf" "^1.0.1" make-fetch-happen "^11.0.1" - tuf-js "^1.0.0" simple-update-notifier@^1.0.7: version "1.1.0" @@ -11014,13 +11096,14 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tuf-js@^1.0.0: - version "1.1.3" - resolved "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.3.tgz" - integrity sha512-jGYi5nG/kqgfTFQSdoN6PW9eIn+XRZqdXku+fSwNk6UpWIsWaV7pzAqPgFr85edOPhoyJDyBqCS+DCnHroMvrw== +tuf-js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-1.1.7.tgz#21b7ae92a9373015be77dfe0cb282a80ec3bbe43" + integrity sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg== dependencies: - "@tufjs/models" "1.0.2" - make-fetch-happen "^11.0.1" + "@tufjs/models" "1.0.4" + debug "^4.3.4" + make-fetch-happen "^11.1.1" tunnel-agent@^0.6.0: version "0.6.0" @@ -11871,10 +11954,10 @@ yargs@17.1.1: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@17.6.2: - version "17.6.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== +yargs@17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" escalade "^3.1.1" From faa2089d5cda4ff76e9588fbb87eeae3eb37d84f Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Thu, 14 Sep 2023 15:19:58 -0400 Subject: [PATCH 068/592] restore stock yarn.lock --- yarn.lock | 439 +++++++++++++++++++++++++++++------------------------- 1 file changed, 237 insertions(+), 202 deletions(-) diff --git a/yarn.lock b/yarn.lock index 771b2e326bb..c5a82d9e75d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47,14 +47,6 @@ "@angular-devkit/core" "15.2.6" rxjs "6.6.7" -"@angular-devkit/architect@0.1601.4": - version "0.1601.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1601.4.tgz#9fc88461cb65e28508067d93acc1aba69ca7a9ec" - integrity sha512-OOSbNlDy+Q3jY0oFHaq8kkna9HYI1zaS8IHeCIDP6T/ZIAVad4+HqXAL4SKQrKJikkoBQv1Z/eaDBL5XPFK9Bw== - dependencies: - "@angular-devkit/core" "16.1.4" - rxjs "7.8.1" - "@angular-devkit/architect@^0.1202.10": version "0.1202.18" resolved "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.18.tgz" @@ -249,17 +241,6 @@ rxjs "6.6.7" source-map "0.7.4" -"@angular-devkit/core@16.1.4": - version "16.1.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-16.1.4.tgz#033ff3ab4d024ee3d8f4c6f809eed10d716ad0ab" - integrity sha512-WCAzNi9LxpFIi2WVPaJQd2kHPqCnCexWzUZN05ltJuBGCQL1O+LgRHGwnQ4WZoqmrF5tcWt2a3GFtJ3DgMc1hw== - dependencies: - ajv "8.12.0" - ajv-formats "2.1.1" - jsonc-parser "3.2.0" - rxjs "7.8.1" - source-map "0.7.4" - "@angular-devkit/schematics@12.2.18", "@angular-devkit/schematics@^12.2.17": version "12.2.18" resolved "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.18.tgz" @@ -269,16 +250,16 @@ ora "5.4.1" rxjs "6.6.7" -"@angular-devkit/schematics@16.1.4": - version "16.1.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-16.1.4.tgz#91d4d82ee273dd7f24c17b9c7fbbfff11d7cab63" - integrity sha512-yjRgwHAfFaeuimgbQtjwSUyXzEHpMSdTRb2zg+TOp6skoGvHOG8xXFJ7DjBkSMeAQdFF0fkxhPS9YmlxqNc+7A== +"@angular-devkit/schematics@15.2.6": + version "15.2.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.2.6.tgz#fb5b7530f21586dbdec45cac56f8a418bcfd053d" + integrity sha512-f7VgnAcok7AwR/DhX0ZWskB0rFBo/KsvtIUA2qZSrpKMf8eFiwu03dv/b2mI0vnf+1FBfIQzJvO0ww45zRp6dA== dependencies: - "@angular-devkit/core" "16.1.4" + "@angular-devkit/core" "15.2.6" jsonc-parser "3.2.0" - magic-string "0.30.0" + magic-string "0.29.0" ora "5.4.1" - rxjs "7.8.1" + rxjs "6.6.7" "@angular-eslint/builder@15.2.1": version "15.2.1" @@ -353,29 +334,29 @@ optionalDependencies: parse5 "^7.1.2" -"@angular/cli@^16.0.4": - version "16.1.4" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-16.1.4.tgz#b32de345b6fdb4e975f957b0f9cbcafdcf184f8a" - integrity sha512-coSOLVLpOCOD5q9K9EAFFMrTES+HtdJiLy/iI9kdKNCKWUJpm8/svZ3JZOej3vPxYEp0AokXNOwORQnX21/qZQ== +"@angular/cli@^15.2.6": + version "15.2.6" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-15.2.6.tgz#d5994fbd4d02e71017d4dd28ba06dc1c3cb7a976" + integrity sha512-wNkQ/qCVbd4pERaGVagKJPifEvjRNY5otwsd4iRVubY/XOcIHcYChUThZwgQdVfNAImfJPMZNrhbGxejuWLA9w== dependencies: - "@angular-devkit/architect" "0.1601.4" - "@angular-devkit/core" "16.1.4" - "@angular-devkit/schematics" "16.1.4" - "@schematics/angular" "16.1.4" + "@angular-devkit/architect" "0.1502.6" + "@angular-devkit/core" "15.2.6" + "@angular-devkit/schematics" "15.2.6" + "@schematics/angular" "15.2.6" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.3" - ini "4.1.1" + ini "3.0.1" inquirer "8.2.4" jsonc-parser "3.2.0" npm-package-arg "10.1.0" npm-pick-manifest "8.0.1" - open "8.4.2" + open "8.4.1" ora "5.4.1" - pacote "15.2.0" - resolve "1.22.2" - semver "7.5.3" + pacote "15.1.0" + resolve "1.22.1" + semver "7.3.8" symbol-observable "4.0.0" - yargs "17.7.2" + yargs "17.6.2" "@angular/common@^15.2.8": version "15.2.8" @@ -1570,10 +1551,10 @@ resolved "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz" integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw== -"@cypress/request@^2.88.10": - version "2.88.11" - resolved "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz" - integrity sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w== +"@cypress/request@2.88.12": + version "2.88.12" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.12.tgz#ba4911431738494a85e93fb04498cb38bc55d590" + integrity sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -1590,7 +1571,7 @@ performance-now "^2.1.0" qs "~6.10.3" safe-buffer "^5.1.2" - tough-cookie "~2.5.0" + tough-cookie "^4.1.3" tunnel-agent "^0.6.0" uuid "^8.3.2" @@ -1629,14 +1610,14 @@ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@es-joy/jsdoccomment@~0.39.4": - version "0.39.4" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz#6b8a62e9b3077027837728818d3c4389a898b392" - integrity sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg== +"@es-joy/jsdoccomment@~0.36.1": + version "0.36.1" + resolved "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz" + integrity sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg== dependencies: comment-parser "1.3.1" - esquery "^1.5.0" - jsdoc-type-pratt-parser "~4.0.0" + esquery "^1.4.0" + jsdoc-type-pratt-parser "~3.1.0" "@esbuild/android-arm64@0.17.8": version "0.17.8" @@ -1780,6 +1761,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b" integrity sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng== +"@fastify/deepmerge@^1.0.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a" + integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A== + "@fortawesome/fontawesome-free@^6.4.0": version "6.4.0" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz#1ee0c174e472c84b23cb46c995154dc383e3b4fe" @@ -2258,13 +2244,13 @@ resolved "https://registry.npmjs.org/@researchgate/react-intersection-observer/-/react-intersection-observer-1.3.5.tgz" integrity sha512-aYlsex5Dd6BAHMJvJrUoFp8gzgMSL27xFvrxkVYW0bV1RMAapVsO+QeYLtTaSF/QCflktODodvv+wJm49oMnnQ== -"@schematics/angular@16.1.4": - version "16.1.4" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-16.1.4.tgz#e99a8b7e1b1b9db107727d0e26a05dc190eefeea" - integrity sha512-XfoeL+aBVIR/DzgVKGVhHW/TGQnqWvngyJVuCwXEVWzNfjxHYFkchXa78OItpAvTEr6/Y0Me9FQVAGVA4mMUyg== +"@schematics/angular@15.2.6": + version "15.2.6" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-15.2.6.tgz#5a0face51806f6b2adf67eef73b08c31744b07bc" + integrity sha512-OcBUvVAxZEMBX+fi0ytybeAdmStra+GwtlvipS70yOxcAgJ84ZrnZGN7a072cCVQcq7AgqUfssnyqCx1wu+yCg== dependencies: - "@angular-devkit/core" "16.1.4" - "@angular-devkit/schematics" "16.1.4" + "@angular-devkit/core" "15.2.6" + "@angular-devkit/schematics" "15.2.6" jsonc-parser "3.2.0" "@schematics/angular@^12.2.17": @@ -2281,14 +2267,6 @@ resolved "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz" integrity sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ== -"@sigstore/tuf@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-1.0.2.tgz#acbb2c8399fb03aca0c90fa1dc1934bda4160623" - integrity sha512-vjwcYePJzM01Ha6oWWZ9gNcdIgnzyFxfqfWzph483DPJTH8Tb7f7bQRRll3CYVkyH56j0AgcPAcl6Vg95DPF+Q== - dependencies: - "@sigstore/protobuf-specs" "^0.1.0" - tuf-js "^1.1.7" - "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" @@ -2329,13 +2307,13 @@ resolved "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz" integrity sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ== -"@tufjs/models@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-1.0.4.tgz#5a689630f6b9dbda338d4b208019336562f176ef" - integrity sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A== +"@tufjs/models@1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@tufjs/models/-/models-1.0.2.tgz" + integrity sha512-uxarDtxTIK3f8hJS4yFhW/lvTa3tsiQU5iDCRut+NCnOXvNtEul0Ct58NIIcIx9Rkt7OFEK31Ndpqsd663nsew== dependencies: "@tufjs/canonical-json" "1.0.0" - minimatch "^9.0.0" + minimatch "^8.0.3" "@types/body-parser@*": version "1.19.2" @@ -2484,11 +2462,16 @@ resolved "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== -"@types/node@*", "@types/node@>=10.0.0", "@types/node@^14.14.31", "@types/node@^14.14.9": +"@types/node@*", "@types/node@>=10.0.0", "@types/node@^14.14.9": version "14.18.42" resolved "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz" integrity sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg== +"@types/node@^16.18.39": + version "16.18.46" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.46.tgz#9f2102d0ba74a318fcbe170cbff5463f119eab59" + integrity sha512-Mnq3O9Xz52exs3mlxMcQuA7/9VFe/dXcrgAyfjLkABIqxXKOgBRjyazTxUbjsxDa4BP7hhPliyjVTP9RDP14xg== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" @@ -3088,9 +3071,9 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" -ajv@8.12.0, ajv@^8.8.0: +ajv@8.12.0, ajv@^8.10.0, ajv@^8.8.0: version "8.12.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" @@ -3199,11 +3182,6 @@ arch@^2.2.0: resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== -are-docs-informative@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" - integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== - are-we-there-yet@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" @@ -3390,10 +3368,10 @@ aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== -axe-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== +axe-core@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" + integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== axios@0.21.4: version "0.21.4" @@ -3570,6 +3548,11 @@ boolbase@^1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +boolean@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" + integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== + bootstrap@^4.6.1: version "4.6.2" resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz" @@ -4469,14 +4452,14 @@ cypress-axe@^1.4.0: resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-1.4.0.tgz#e67482bfe9e740796bf77c7823f19781a8a2faff" integrity sha512-Ut7NKfzjyKm0BEbt2WxuKtLkIXmx6FD2j0RwdvO/Ykl7GmB/qRQkwbKLk3VP35+83hiIr8GKD04PDdrTK5BnyA== -cypress@12.10.0: - version "12.10.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.10.0.tgz#b6264f77c214d63530ebac2b33c4d099bd40b715" - integrity sha512-Y0wPc221xKKW1/4iAFCphkrG2jNR4MjOne3iGn4mcuCaE7Y5EtXL83N8BzRsAht7GYfWVjJ/UeTqEdDKHz39HQ== +cypress@12.17.4: + version "12.17.4" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.17.4.tgz#b4dadf41673058493fa0d2362faa3da1f6ae2e6c" + integrity sha512-gAN8Pmns9MA5eCDFSDJXWKUpaL3IDd89N9TtIupjYnzLSmlpVr+ZR+vb4U/qaMp+lB6tBvAmt7504c3Z4RU5KQ== dependencies: - "@cypress/request" "^2.88.10" + "@cypress/request" "2.88.12" "@cypress/xvfb" "^1.2.4" - "@types/node" "^14.14.31" + "@types/node" "^16.18.39" "@types/sinonjs__fake-timers" "8.1.1" "@types/sizzle" "^2.3.2" arch "^2.2.0" @@ -4509,9 +4492,10 @@ cypress@12.10.0: minimist "^1.2.8" ospath "^1.2.2" pretty-bytes "^5.6.0" + process "^0.11.10" proxy-from-env "1.0.0" request-progress "^3.0.0" - semver "^7.3.2" + semver "^7.5.3" supports-color "^8.1.1" tmp "~0.2.1" untildify "^4.0.0" @@ -4673,6 +4657,11 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" @@ -5268,18 +5257,17 @@ eslint-plugin-import@^2.27.5: semver "^6.3.0" tsconfig-paths "^3.14.1" -eslint-plugin-jsdoc@^45.0.0: - version "45.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-45.0.0.tgz#6be84e4842a7138cc571a907ea9c31c42eaac5c0" - integrity sha512-l2+Jcs/Ps7oFA+SWY+0sweU/e5LgricnEl6EsDlyRTF5y0+NWL1y9Qwz9PHwHAxtdJq6lxPjEQWmYLMkvhzD4g== +eslint-plugin-jsdoc@^39.6.4: + version "39.9.1" + resolved "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.9.1.tgz" + integrity sha512-Rq2QY6BZP2meNIs48aZ3GlIlJgBqFCmR55+UBvaDkA3ZNQ0SvQXOs2QKkubakEijV8UbIVbVZKsOVN8G3MuqZw== dependencies: - "@es-joy/jsdoccomment" "~0.39.4" - are-docs-informative "^0.0.2" + "@es-joy/jsdoccomment" "~0.36.1" comment-parser "1.3.1" debug "^4.3.4" escape-string-regexp "^4.0.0" - esquery "^1.5.0" - semver "^7.5.1" + esquery "^1.4.0" + semver "^7.3.8" spdx-expression-parse "^3.0.1" eslint-plugin-jsonc@^2.6.0: @@ -5416,7 +5404,7 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2, esquery@^1.5.0: +esquery@^1.4.0, esquery@^1.4.2: version "1.5.0" resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -5612,6 +5600,18 @@ fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@^2.0.0: resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-json-stringify@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.8.0.tgz#b229ed01ac5f92f3b82001a916c31324652f46d7" + integrity sha512-VVwK8CFMSALIvt14U8AvrSzQAwN/0vaVRiFFUVlpnXSnDGrSkOAO5MtzyN8oQNjLd5AqTW5OZRgyjoNuAuR3jQ== + dependencies: + "@fastify/deepmerge" "^1.0.0" + ajv "^8.10.0" + ajv-formats "^2.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^2.1.0" + rfdc "^1.2.0" + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" @@ -5622,6 +5622,18 @@ fast-memoize@^2.5.1: resolved "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz" integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== +fast-printf@^1.6.9: + version "1.6.9" + resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676" + integrity sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg== + dependencies: + boolean "^3.1.4" + +fast-uri@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.2.0.tgz#519a0f849bef714aad10e9753d69d8f758f7445a" + integrity sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg== + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz" @@ -6054,9 +6066,9 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globalthis@^1.0.3: +globalthis@^1.0.2, globalthis@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== dependencies: define-properties "^1.1.3" @@ -6405,6 +6417,16 @@ http-signature@~1.3.6: jsprim "^2.0.2" sshpk "^1.14.1" +http-terminator@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/http-terminator/-/http-terminator-3.2.0.tgz#bc158d2694b733ca4fbf22a35065a81a609fb3e9" + integrity sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g== + dependencies: + delay "^5.0.0" + p-wait-for "^3.2.0" + roarr "^7.0.4" + type-fest "^2.3.3" + https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" @@ -6564,10 +6586,10 @@ ini@2.0.0: resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" - integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== +ini@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz" + integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ== ini@^1.3.4: version "1.3.8" @@ -6697,7 +6719,7 @@ is-ci@^3.0.0: dependencies: ci-info "^3.2.0" -is-core-module@^2.11.0, is-core-module@^2.8.1: +is-core-module@^2.11.0, is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.12.0" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz" integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== @@ -7086,10 +7108,10 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdoc-type-pratt-parser@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" - integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== +jsdoc-type-pratt-parser@~3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz" + integrity sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw== jsdom@21.1.0: version "21.1.0" @@ -7715,13 +7737,6 @@ magic-string@0.29.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" -magic-string@0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.0.tgz#fd58a4748c5c4547338a424e90fa5dd17f4de529" - integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - magic-string@^0.27.0: version "0.27.0" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz" @@ -7792,27 +7807,6 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: socks-proxy-agent "^7.0.0" ssri "^10.0.0" -make-fetch-happen@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" - integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== - dependencies: - agentkeepalive "^4.2.1" - cacache "^17.0.0" - http-cache-semantics "^4.1.1" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^7.7.1" - minipass "^5.0.0" - minipass-fetch "^3.0.0" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.3" - promise-retry "^2.0.1" - socks-proxy-agent "^7.0.0" - ssri "^10.0.0" - manifesto.js@^4.2.0: version "4.2.17" resolved "https://registry.npmjs.org/manifesto.js/-/manifesto.js-4.2.17.tgz" @@ -7986,20 +7980,13 @@ minimatch@^7.4.2: dependencies: brace-expansion "^2.0.1" -minimatch@^8.0.2: +minimatch@^8.0.2, minimatch@^8.0.3: version "8.0.4" resolved "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz" integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -8259,10 +8246,12 @@ ng2-file-upload@1.4.0: dependencies: tslib "^1.9.0" -ng2-nouislider@^1.8.3: - version "1.8.3" - resolved "https://registry.npmjs.org/ng2-nouislider/-/ng2-nouislider-1.8.3.tgz" - integrity sha512-Vl8tHCcJ/ioJLAs2t6FBC35sZq1P/O5ZdqdFwYxOCOMVbILGWNg+2gWZIjFstvv9pqb/mVvVUYe6qGG/mA/RBQ== +ng2-nouislider@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ng2-nouislider/-/ng2-nouislider-2.0.0.tgz#a62fd6cf3f1561be19a2691c2f68d21a46dc6006" + integrity sha512-NGbF/0w0+bZqclpSPFOlWIeVJaVwRRYFJzD1x8PClbw9GIeo7fCHoBzZ81y7K7FTJg6to+cgjSTFETPZG/Dizg== + dependencies: + tslib "^2.3.0" ngx-infinite-scroll@^15.0.0: version "15.0.0" @@ -8405,10 +8394,10 @@ normalize-url@^4.5.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== -nouislider@^14.6.3: - version "14.7.0" - resolved "https://registry.npmjs.org/nouislider/-/nouislider-14.7.0.tgz" - integrity sha512-4RtQ1+LHJKesDCNJrXkQcwXAWCrC2aggdLYMstS/G5fEWL+fXZbUA9pwVNHFghMGuFGRATlDLNInRaPeRKzpFQ== +nouislider@^15.7.1: + version "15.7.1" + resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-15.7.1.tgz#77d55e47d9b4cd771728515713df43b489db9705" + integrity sha512-5N7C1ru/i8y3dg9+Z6ilj6+m1EfabvOoaRa7ztpxBSKKRZso4vA52DGSbBJjw5XLtFr/LZ9SgGAXqyVtlVHO5w== npm-bundled@^3.0.0: version "3.0.0" @@ -8597,15 +8586,6 @@ open@8.4.1: is-docker "^2.1.1" is-wsl "^2.2.0" -open@8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - open@^8.0.9: version "8.4.0" resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz" @@ -8686,6 +8666,11 @@ ospath@^1.2.2: resolved "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz" integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA== +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" @@ -8729,15 +8714,29 @@ p-retry@^4.5.0: "@types/retry" "0.12.0" retry "^0.13.1" +p-timeout@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@15.2.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-15.2.0.tgz#0f0dfcc3e60c7b39121b2ac612bf8596e95344d3" - integrity sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA== +p-wait-for@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-wait-for/-/p-wait-for-3.2.0.tgz#640429bcabf3b0dd9f492c31539c5718cb6a3f1f" + integrity sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA== + dependencies: + p-timeout "^3.0.0" + +pacote@15.1.0: + version "15.1.0" + resolved "https://registry.npmjs.org/pacote/-/pacote-15.1.0.tgz" + integrity sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg== dependencies: "@npmcli/git" "^4.0.0" "@npmcli/installed-package-contents" "^2.0.1" @@ -8745,7 +8744,7 @@ pacote@15.2.0: "@npmcli/run-script" "^6.0.0" cacache "^17.0.0" fs-minipass "^3.0.0" - minipass "^5.0.0" + minipass "^4.0.0" npm-package-arg "^10.0.0" npm-packlist "^7.0.0" npm-pick-manifest "^8.0.0" @@ -8754,7 +8753,7 @@ pacote@15.2.0: promise-retry "^2.0.1" read-package-json "^6.0.0" read-package-json-fast "^3.0.0" - sigstore "^1.3.0" + sigstore "^1.0.0" ssri "^10.0.0" tar "^6.1.11" @@ -9344,6 +9343,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" @@ -9922,7 +9926,16 @@ resolve-url-loader@5.0.0: postcss "^8.2.14" source-map "0.6.1" -resolve@1.22.2, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.9.0: +resolve@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.9.0: version "1.22.2" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -9962,9 +9975,9 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: +rfdc@^1.2.0, rfdc@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.6.3: @@ -9981,6 +9994,18 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +roarr@^7.0.4: + version "7.15.1" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.15.1.tgz#e4d93105c37b5ea7dd1200d96a3500f757ddc39f" + integrity sha512-0ExL9rjOXeQPvQvQo8IcV8SR2GTXmDr1FQFlY2HiAV+gdVQjaVZNOx9d4FI2RqFFsd0sNsiw2TRS/8RU9g0ZfA== + dependencies: + boolean "^3.1.4" + fast-json-stringify "^5.8.0" + fast-printf "^1.6.9" + globalthis "^1.0.2" + safe-stable-stringify "^2.4.3" + semver-compare "^1.0.0" + rtl-css-js@^1.13.1: version "1.16.1" resolved "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz" @@ -10037,13 +10062,6 @@ rxjs@6.6.7, rxjs@^6.5.5, rxjs@~6.6.0: dependencies: tslib "^1.9.0" -rxjs@7.8.1: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - rxjs@^7.5.1, rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" @@ -10070,6 +10088,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-stable-stringify@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" @@ -10189,6 +10212,11 @@ selfsigned@^2.1.1: dependencies: node-forge "^1" +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== + semver@7.3.8: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -10196,13 +10224,6 @@ semver@7.3.8: dependencies: lru-cache "^6.0.0" -semver@7.5.3, semver@^7.5.1: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== - dependencies: - lru-cache "^6.0.0" - semver@^5.3.0, semver@^5.6.0, semver@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -10213,7 +10234,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: +semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -10373,14 +10394,14 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -sigstore@^1.3.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.7.0.tgz#9186e6c8ce1ab0cba5d97b414212d40f0a01564e" - integrity sha512-KP7QULhWdlu3hlp+jw2EvgWKlOGOY9McLj/jrchLjHNlNPK0KWIwF919cbmOp6QiKXLmPijR2qH/5KYWlbtG9Q== +sigstore@^1.0.0: + version "1.2.0" + resolved "https://registry.npmjs.org/sigstore/-/sigstore-1.2.0.tgz" + integrity sha512-Fr9+W1nkBSIZCkJQR7jDn/zI0UXNsVpp+7mDQkCnZOIxG9p6yNXBx9xntHsfUyYHE55XDkkVV3+rYbrkzAeesA== dependencies: "@sigstore/protobuf-specs" "^0.1.0" - "@sigstore/tuf" "^1.0.1" make-fetch-happen "^11.0.1" + tuf-js "^1.0.0" simple-update-notifier@^1.0.7: version "1.1.0" @@ -10994,6 +11015,16 @@ tough-cookie@^4.0.0, tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" @@ -11096,14 +11127,13 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tuf-js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-1.1.7.tgz#21b7ae92a9373015be77dfe0cb282a80ec3bbe43" - integrity sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg== +tuf-js@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.3.tgz" + integrity sha512-jGYi5nG/kqgfTFQSdoN6PW9eIn+XRZqdXku+fSwNk6UpWIsWaV7pzAqPgFr85edOPhoyJDyBqCS+DCnHroMvrw== dependencies: - "@tufjs/models" "1.0.4" - debug "^4.3.4" - make-fetch-happen "^11.1.1" + "@tufjs/models" "1.0.2" + make-fetch-happen "^11.0.1" tunnel-agent@^0.6.0: version "0.6.0" @@ -11141,6 +11171,11 @@ type-fest@^0.21.3: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^2.3.3: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" @@ -11954,10 +11989,10 @@ yargs@17.1.1: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== +yargs@17.6.2: + version "17.6.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz" + integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== dependencies: cliui "^8.0.1" escalade "^3.1.1" From 24a0af1e9a32002a2d7c7a1c667a401a41f0a321 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Mon, 18 Sep 2023 13:26:10 +0200 Subject: [PATCH 069/592] CST-11048 First commit --- .../admin-ldn-services-routing.module.ts | 30 ++++ .../admin-ldn-services.module.ts | 23 +++ .../ldn-service-form.component.html | 96 ++++++++++++ .../ldn-service-form.component.scss | 51 +++++++ .../ldn-service-form.component.spec.ts | 25 +++ .../ldn-service-form.component.ts | 142 ++++++++++++++++++ .../ldn-service-new.component.html | 1 + .../ldn-service-new.component.scss | 0 .../ldn-service-new.component.spec.ts | 25 +++ .../ldn-service-new.component.ts | 28 ++++ .../ldnServicesRD$-mock.ts | 73 +++++++++ .../ldn-services-data.service.ts | 90 +++++++++++ .../ldn-services-directory.component.html | 85 +++++++++++ .../ldn-services-directory.component.scss | 0 .../ldn-services-directory.component.spec.ts | 25 +++ .../ldn-services-directory.component.ts | 105 +++++++++++++ .../ldn-services-guard.service.ts | 29 ++++ .../ldn-services.guard.spec.ts | 17 +++ .../ldn-service-constraint.model.ts | 26 ++++ .../ldn-service-status.model.ts | 8 + .../ldn-service.resource-type.ts | 9 ++ .../ldn-services-model/ldn-services.model.ts | 58 +++++++ .../service-constrain-type.model.ts | 10 ++ .../ldn-service-coar-patterns.ts | 73 +++++++++ .../ldn-directory.service.spec.ts | 17 +++ .../ldn-directory.service.ts | 54 +++++++ .../ldn-service-bulk-delete.service.spec.ts | 17 +++ .../ldn-service-bulk-delete.service.ts | 117 +++++++++++++++ src/app/admin/admin-routing-paths.ts | 2 + src/app/admin/admin-routing.module.ts | 14 +- src/app/core/core.module.ts | 4 +- src/assets/i18n/en.json5 | 45 ++++++ 32 files changed, 1297 insertions(+), 2 deletions(-) create mode 100644 src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts create mode 100644 src/app/admin/admin-ldn-services/admin-ldn-services.module.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts new file mode 100644 index 00000000000..740cd39621e --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -0,0 +1,30 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service'; +import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + pathMatch: 'full', + component: LdnServicesOverviewComponent, + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: { title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new' }, + canActivate: [LdnServicesGuard] + }, + { + path: 'new', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + component: LdnServiceNewComponent, + data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' } + }, + ]), + ] +}) +export class AdminLdnServicesRoutingModule { + +} diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts new file mode 100644 index 00000000000..c03c16109ed --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { AdminLdnServicesRoutingModule } from './admin-ldn-services-routing.module'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { SharedModule } from '../../shared/shared.module'; +import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; +import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; + + + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + AdminLdnServicesRoutingModule, + ], + declarations: [ + LdnServicesOverviewComponent, + LdnServiceNewComponent, + LdnServiceFormComponent, + ] +}) +export class AdminLdnServicesModule { } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html new file mode 100644 index 00000000000..64146b31a14 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -0,0 +1,96 @@ +
+ +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + +
+ + + + + +
+ + - Remove + +
+ +
+ + + Add more + + +
+ + + + + + + + - Remove + + + +
+ + + Add more + + + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss new file mode 100644 index 00000000000..53bc21d1b3f --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -0,0 +1,51 @@ + +form { + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 0 auto; + max-width: 600px; + font-size: 14px; +} + + +.form-group input[type="text"], +.form-group select { + max-width: 100%; + width: 100%; + padding: 8px; + margin-bottom: 5px; + box-sizing: border-box; + font-size: 14px; +} + + +.description { + height: 9em; + width: 100%; +} + + +.form-group select { + position: relative; + z-index: 1; +} + + +.form-group select option { + font-weight: bold; +} + +.add-pattern-link{ + color: #0048ff; + cursor: pointer; + margin-left: 10px; +} +.remove-pattern-link{ + color: #e34949; + cursor: pointer; + margin-left: 10px; +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts new file mode 100644 index 00000000000..3ae834d6429 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceFormComponent } from './ldn-service-form.component'; + +describe('LdnServiceFormComponent', () => { + let component: LdnServiceFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts new file mode 100644 index 00000000000..b17cc6902dc --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -0,0 +1,142 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Router } from '@angular/router'; + +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; +import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; + +@Component({ + selector: 'ds-ldn-service-form', + templateUrl: './ldn-service-form.component.html', + styleUrls: ['./ldn-service-form.component.scss'], +}) +export class LdnServiceFormComponent implements OnInit { + formModel: FormGroup; + + showItemFilterDropdown = false; + + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + public itemFilterList: LdnServiceConstraint[]; + additionalOutboundPatterns: FormGroup[] = []; + additionalInboundPatterns: FormGroup[] = []; + + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + + @Input() public headerKey: string; + + constructor( + private ldnServicesService: LdnServicesService, + private ldnDirectoryService: LdnDirectoryService, + private formBuilder: FormBuilder, + private http: HttpClient, + private router: Router + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: ['', Validators.required], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), + notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + type: LDN_SERVICE.value, + }); + } + + ngOnInit(): void { + this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { + console.log(itemFilters); + this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ + name: filter.id + })); + console.log(this.itemFilterList); + }); + + } + + submitForm() { + this.formModel.removeControl('inboundPattern'); + this.formModel.removeControl('outboundPattern'); + this.formModel.removeControl('constraintPattern'); + console.log('JSON Data:', this.formModel.value); + + const apiUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; + + this.http.post(apiUrl, this.formModel.value ).subscribe( + (response) => { + console.log('Service created successfully:', response); + this.formModel.reset(); + this.sendBack(); + }, + (error) => { + console.error('Error creating service:', error); + } + ); + } + + private validateForm(form: FormGroup): boolean { + let valid = true; + Object.keys(form.controls).forEach((key) => { + if (form.controls[key].invalid) { + form.controls[key].markAsDirty(); + valid = false; + } + }); + return valid; + } + + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } + + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } + + removeInboundPattern(patternGroup: FormGroup) { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + } + + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); + } + + removeOutboundPattern(patternGroup: FormGroup) { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + } + + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + }); + } + + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + automatic: [true] + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html new file mode 100644 index 00000000000..9567cb1abef --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts new file mode 100644 index 00000000000..4994823004e --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceNewComponent } from './ldn-service-new.component'; + +describe('LdnServiceNewComponent', () => { + let component: LdnServiceNewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceNewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceNewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts new file mode 100644 index 00000000000..daf1653cd11 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { LdnService } from "../ldn-services-model/ldn-services.model"; +import { ActivatedRoute } from "@angular/router"; +import { ProcessDataService } from "../../../core/data/processes/process-data.service"; +import { LinkService } from "../../../core/cache/builders/link.service"; +import { getFirstSucceededRemoteDataPayload } from "../../../core/shared/operators"; + +@Component({ + selector: 'ds-ldn-service-new', + templateUrl: './ldn-service-new.component.html', + styleUrls: ['./ldn-service-new.component.scss'] +}) +export class LdnServiceNewComponent implements OnInit { + /** + * Emits preselected process if there is one + */ + ldnService$?: Observable; + + constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) { + } + + /** + * If there's an id parameter, use this the process with this identifier as presets for the form + */ + ngOnInit() { + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts new file mode 100644 index 00000000000..fccb374b5f7 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -0,0 +1,73 @@ +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { Observable, of } from 'rxjs'; +// Create a mock data object for a single LDN notify service +export const mockLdnService: LdnService = { + id: 1, + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: false, + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: true, + }, + ], + notifyServiceOutboundPatterns: [ + { + pattern: 'patternC', + constraint: 'itemFilterC', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1', + }, + }, +}; + + + + +const mockLdnServices = { + payload: { + elementsPerPage: 20, + totalPages: 1, + totalElements: 1, + currentPage: 1, + first: undefined, + prev: undefined, + next: undefined, + last: undefined, + page: [mockLdnService], + type: LDN_SERVICE, + self: undefined, + getPageLength: function() { + return this.page.length; + }, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1', + }, + page: [], + }, + }, + hasSucceeded: true, + msToLive: 0, +}; + + + + +// Create a mock ldnServicesRD$ observable +export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts new file mode 100644 index 00000000000..43755adb3c0 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -0,0 +1,90 @@ + import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; +import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { map, take } from 'rxjs/operators'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { MultipartPostRequest } from '../../../core/data/request.models'; +import { RestRequest } from '../../../core/data/rest-request.model'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; + +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; + +@Injectable() +@dataService(LDN_SERVICE) +export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData { + private findAllData: FindAllDataImpl; // Corrected the type + private deleteData: DeleteDataImpl; // Corrected the type + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, parameters: LdnServiceConstraint[], files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes').toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(parameters, files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + private getInvocationFormData(constrain: LdnServiceConstraint[], files: File[]): FormData { + const form: FormData = new FormData(); + form.set('properties', JSON.stringify(constrain)); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } + + public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html new file mode 100644 index 00000000000..bd2ec0d418b --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -0,0 +1,85 @@ +
+ {{ldnServicesRD$ | async | json }} +
+

{{'ldn-registered-services.title' | translate}}

+
+
+ + + + +
+ +
+ + + + + + + + + + + + + + + + +
{{'service.overview.table.name' | translate}}{{'service.overview.table.description' | translate}}{{'service.overview.table.status' | translate}}{{'service.overview.table.actions' | translate}}
{{ldnService.id}}{{ldnService.description}} + +
+
+
+
+ + + +
+ + + + +
+ + +
+ diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts new file mode 100644 index 00000000000..bedcabb2713 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesDirectoryComponent } from './services-directory.component'; + +describe('ServicesDirectoryComponent', () => { + let component: ServicesDirectoryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ServicesDirectoryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesDirectoryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts new file mode 100644 index 00000000000..e8c81ea8731 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -0,0 +1,105 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { Observable, Subscription } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { switchMap } from 'rxjs/operators'; +import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { PaginationService } from 'src/app/core/pagination/pagination.service'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LdnServicesBulkDeleteService } from 'src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service'; +import { hasValue } from '../../../shared/empty.util'; +import { HttpClient } from '@angular/common/http'; + +@Component({ + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], +}) +export class LdnServicesOverviewComponent implements OnInit, OnDestroy { + + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + private modalRef: any; + isProcessingSub: Subscription; + + constructor( + protected processLdnService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public ldnServicesBulkDeleteService: LdnServicesBulkDeleteService, + public ldnDirectoryService: LdnDirectoryService, + private http: HttpClient + ) {} + + ngOnInit(): void { + this.setLdnServices(); + this.ldnDirectoryService.listLdnServices(); + this.searchByLdnUrl(); + } + + setLdnServices() { + debugger; + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.processLdnService.findAll(config, true, false)) + ); + console.log() + } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + } + + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } + + closeModal() { + this.modalRef.close(); + } + + + findByLdnUrl(): Observable { + const url = 'http://localhost:8080/server/api/ldn/ldnservices'; + + return this.http.get(url); + } + + searchByLdnUrl(): void { + this.findByLdnUrl().subscribe( + (response) => { + console.log('Search results:', response); + }, + (error) => { + console.error('Error:', error); + } + ); + } + + deleteSelected() { + this.ldnServicesBulkDeleteService.deleteSelectedLdnServices(); + + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + this.isProcessingSub = this.ldnServicesBulkDeleteService.isProcessing$() + .subscribe((isProcessing) => { + if (!isProcessing) { + this.closeModal(); + this.setLdnServices(); + } + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts new file mode 100644 index 00000000000..85235b4370f --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class LdnServicesGuard implements CanActivate { + + constructor( + //private notifyInfoService: NotifyInfoService, + private router: Router + ) {} + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + return true; + /*return this.notifyInfoService.isCoarConfigEnabled().pipe( + map(coarLdnEnabled => { + if (coarLdnEnabled) { + return true; + } else { + return this.router.parseUrl('/404'); + } + }) + );*/ + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts new file mode 100644 index 00000000000..30af31cab82 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnServicesGuard } from './ldn-services-guard.service'; + +describe('LdnServicesGuard', () => { + let guard: LdnServicesGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(LdnServicesGuard); + }); + + it('should be created', () => { + // @ts-ignore + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts new file mode 100644 index 00000000000..704a3e7d8c4 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts @@ -0,0 +1,26 @@ + +/** + * A cosntrain that can be used when running a service + */ +export class LdnServiceConstraint { + /** + * The name of the constrain + */ + name: string; + + /** + * The value of the constrain + */ + value: string; +} + +export const EndorsmentConstrain = [ + { + name: 'Type 1 Item', + value: 'Type1' + }, + { + name: 'Type 2 Item', + value: 'Type2' + }, +]; diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts new file mode 100644 index 00000000000..040e4d37b8a --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts @@ -0,0 +1,8 @@ +/** + * List of services statuses + */ +export enum LdnServiceStatus { + UNKOWN, + DISABLED, + ENABLED, +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts new file mode 100644 index 00000000000..c00d241ee86 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -0,0 +1,9 @@ +/** + * The resource type for Ldn-Services + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +import { ResourceType } from '../../../core/shared/resource-type'; + +export const LDN_SERVICE = new ResourceType('notifyservice'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts new file mode 100644 index 00000000000..bdb8bc51232 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -0,0 +1,58 @@ +import { ResourceType } from '../../../core/shared/resource-type'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize } from 'cerialize'; +import { LDN_SERVICE } from './ldn-service.resource-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; + + +@typedObject +export class LdnService extends CacheableObject { + static type = LDN_SERVICE; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id?: number; + + @autoserialize + name: string; + + @autoserialize + description: string; + + @autoserialize + url: string; + + @autoserialize + ldnUrl: string; + + @autoserialize + notifyServiceInboundPatterns?: NotifyServicePattern[]; + + @autoserialize + notifyServiceOutboundPatterns?: NotifyServicePattern[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} + + +class NotifyServicePattern { + @autoserialize + pattern: string; + @autoserialize + constraint?: string; + @autoserialize + automatic?: boolean; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts new file mode 100644 index 00000000000..d3f55c815ef --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts @@ -0,0 +1,10 @@ +/** + * List of parameter types used for scripts + */ +export enum LdnServiceConstrainType { + STRING = 'String', + DATE = 'date', + BOOLEAN = 'boolean', + FILE = 'InputStream', + OUTPUT = 'OutputStream' +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts new file mode 100644 index 00000000000..14d227c131e --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts @@ -0,0 +1,73 @@ +export const notifyPatterns = [ + { + name: 'Acknowledge and Accept', + description: 'This pattern is used to acknowledge and accept a request (offer). It implies an intention to act on the request.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Reject', + description: 'This pattern is used to acknowledge and reject a request (offer). It signifies no further action regarding the request.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Tentatively Accept', + description: 'This pattern is used to acknowledge and tentatively accept a request (offer). It implies an intention to act, which may change.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Tentatively Reject', + description: 'This pattern is used to acknowledge and tentatively reject a request (offer). It signifies no further action, subject to change.', + category: 'Acknowledgements' + }, + { + name: 'Announce Endorsement', + description: 'This pattern is used to announce the existence of an endorsement, referencing the endorsed resource.', + category: 'Announcements' + }, + { + name: 'Announce Ingest', + description: 'This pattern is used to announce that a resource has been ingested.', + category: 'Announcements' + }, + { + name: 'Announce Relationship', + description: 'This pattern is used to announce a relationship between two resources.', + category: 'Announcements' + }, + { + name: 'Announce Review', + description: 'This pattern is used to announce the existence of a review, referencing the reviewed resource.', + category: 'Announcements' + }, + { + name: 'Announce Service Result', + description: 'This pattern is used to announce the existence of a "service result", referencing the relevant resource.', + category: 'Announcements' + }, + { + name: 'Request Endorsement', + description: 'This pattern is used to request endorsement of a resource owned by the origin system.', + category: 'Requests' + }, + { + name: 'Request Ingest', + description: 'This pattern is used to request that the target system ingest a resource.', + category: 'Requests' + }, + { + name: 'Request Review', + description: 'This pattern is used to request a review of a resource owned by the origin system.', + category: 'Requests' + }, + { + name: 'Undo Offer', + description: 'This pattern is used to undo (retract) an offer previously made.', + category: 'Undo' + } +]; + + +const pattern = notifyPatterns[0]; +console.log(`Pattern Name: ${pattern.name}`); +console.log(`Pattern Description: ${pattern.description}`); +console.log(`Pattern Category: ${pattern.category}`); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts new file mode 100644 index 00000000000..e24508e942d --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnDirectoryService } from './ldn-directory.service'; + +describe('LdnDirectoryService', () => { + let service: LdnDirectoryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnDirectoryService); + }); + + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts new file mode 100644 index 00000000000..d06057800bf --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; + +@Injectable({ + providedIn: 'root', +}) +export class LdnDirectoryService { + private baseUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; + private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; + + + constructor(private http: HttpClient) {} + + + public listLdnServices(): Observable { + const endpoint = `${this.baseUrl}`; + return this.http.get(endpoint); + } + + public getLdnServiceById(id: string): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.get(endpoint); + } + + public createLdnService(ldnService: LdnService): Observable { + return this.http.post(this.baseUrl, ldnService); + } + + public updateLdnService(id: string, ldnService: LdnService): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.put(endpoint, ldnService); + } + + public deleteLdnService(id: string): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.delete(endpoint); + } + + public searchLdnServicesByLdnUrl(ldnUrl: string): Observable { + const endpoint = `${this.baseUrl}/search/byLdnUrl?ldnUrl=${ldnUrl}`; + return this.http.get(endpoint); + } + + public getItemFilters(): Observable { + const endpoint = `${this.itemFilterEndpoint}`; + return this.http.get(endpoint); + } + +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts new file mode 100644 index 00000000000..38e1a4de2b9 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnServicesBulkDeleteService } from './ldn-service-bulk-delete.service'; + +describe('LdnServiceBulkDeleteService', () => { + let service: LdnServicesBulkDeleteService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnServicesBulkDeleteService); + }); + + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts new file mode 100644 index 00000000000..6805cd7f932 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts @@ -0,0 +1,117 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, count, from } from 'rxjs'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { isNotEmpty } from '../../../shared/empty.util'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { RemoteData } from '../../../core/data/remote-data'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; +@Injectable({ + providedIn: 'root' +}) +/** + * Service to facilitate removing ldn services in bulk. + */ +export class LdnServicesBulkDeleteService { + + /** + * Array to track the services to be deleted + */ + ldnServicesToDelete: string[] = []; + + /** + * Behavior subject to track whether the delete is processing + * @protected + */ + protected isProcessingBehaviorSubject: BehaviorSubject = new BehaviorSubject(false); + + constructor( + protected processLdnService: LdnServicesService, + protected notificationsService: NotificationsService, + protected translateService: TranslateService + ) { + } + + /** + * Add or remove a process id to/from the list + * If the id is already present it will be removed, otherwise it will be added. + * + * @param notifyServiceName - The process id to add or remove + */ + toggleDelete(notifyServiceName: string) { + if (this.isToBeDeleted(notifyServiceName)) { + this.ldnServicesToDelete.splice(this.ldnServicesToDelete.indexOf(notifyServiceName), 1); + } else { + this.ldnServicesToDelete.push(notifyServiceName); + } + } + + /** + * Checks if the provided service id is present in the to be deleted list + * @param notifyServiceName + */ + isToBeDeleted(notifyServiceName: string) { + return this.ldnServicesToDelete.includes(notifyServiceName); + } + + /** + * Clear the list of services to be deleted + */ + clearAllServices() { + this.ldnServicesToDelete.splice(0); + } + + /** + * Get the amount of processes selected for deletion + */ + getAmountOfSelectedServices() { + return this.ldnServicesToDelete.length; + } + + /** + * Returns a behavior subject to indicate whether the bulk delete is processing + */ + isProcessing$() { + return this.isProcessingBehaviorSubject; + } + + /** + * Returns whether there currently are values selected for deletion + */ + hasSelected(): boolean { + return isNotEmpty(this.ldnServicesToDelete); + } + + /** + * Delete all selected processes one by one + * When the deletion for a process fails, an error notification will be shown with the process id, + * but it will continue deleting the other processes. + * At the end it will show a notification stating the amount of successful deletes + * The successfully deleted processes will be removed from the list of selected values, the failed ones will be retained. + */ + deleteSelectedLdnServices() { + this.isProcessingBehaviorSubject.next(true); + + from([...this.ldnServicesToDelete]).pipe( + concatMap((notifyServiceName) => { + return this.processLdnService.delete(notifyServiceName).pipe( + getFirstCompletedRemoteData(), + tap((rd: RemoteData) => { + if (rd.hasFailed) { + this.notificationsService.error(this.translateService.get('process.bulk.delete.error.head'), this.translateService.get('process.bulk.delete.error.body', {processId: notifyServiceName})); + } else { + this.toggleDelete(notifyServiceName); + } + }) + ); + }), + filter((rd: RemoteData) => rd.hasSucceeded), + count(), + ).subscribe((value) => { + this.notificationsService.success(this.translateService.get('process.bulk.delete.success', {count: value})); + this.isProcessingBehaviorSubject.next(false); + }); + } +} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 30f801cecb7..df0459ff534 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -11,3 +11,5 @@ export function getRegistriesModuleRoute() { export function getNotificationsModuleRoute() { return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); } + +export const LDN_PATH = 'ldn'; diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index a7d19a69357..5cca6d3e22a 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -7,6 +7,7 @@ import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; +import { LDN_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ @@ -52,13 +53,24 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import component: BatchImportPageComponent, data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' } }, + { + path: LDN_PATH, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'services' }, + { + path: 'services', + loadChildren: () => import('./admin-ldn-services/admin-ldn-services.module') + .then((m) => m.AdminLdnServicesModule), + } + ] + }, { path: 'system-wide-alert', resolve: { breadcrumb: I18nBreadcrumbResolver }, loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule), data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'} }, - ]) + ]), ], providers: [ I18nBreadcrumbResolver, diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 7acf132df9b..e1b1fc88110 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -187,6 +187,7 @@ import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-brows import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model'; +import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -309,7 +310,8 @@ const PROVIDERS = [ OrcidAuthService, OrcidQueueDataService, OrcidHistoryDataService, - SupervisionOrderDataService + SupervisionOrderDataService, + LdnServicesService, ]; /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0d90ca693d9..9f5249e92fe 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -890,6 +890,28 @@ "claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow", + "ldn-registered-services.title": "Registered Services", + "ldn-registered-services.table.name":"Name", + "ldn-registered-services.table.description": "Description", + "ldn-registered-services.table.status": "Status", + "ldn-registered-services.table.action": "Action", + "ldn-registered-services.new": "NEW", + "ldn-registered-services.new.breadcrumbs": "Registered Services", + + "ldn-register-new-service.title": "Register a new service", + "ldn-register-new-service.name": "Name", + "ldn-register-new-service.url": "Service URL", + "ldn-register-new-service.ldn.inbox.url": "LDN InBox URL", + "ldn-register-new-service.inbound": "Inbound- Patterns supported by the service (i.e. messages that the service is able to receive and understand)", + "ldn-register-new-service.outbound": "Outbound- Patterns supported by the service (i.e. messages that the service is likely to generate and that should be processed by DSpace)", + "ldn-register-new-service.addmore": "+ Add more", + "ldn-register-new-service.breadcrumbs": "New Service", + + "ldn-register-new-service.notification.error.title": "Error", + "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", + "ldn-register-new-service.notification.success.title": "Success", + "ldn-register-new-service.notification.success.content": "The process was successfully created", + "collection.create.head": "Create a Collection", "collection.create.notifications.success": "Successfully created the Collection", @@ -3328,6 +3350,10 @@ "process.new.breadcrumbs": "Create a new process", + + + + "process.detail.arguments": "Arguments", "process.detail.arguments.empty": "This process doesn't contain any arguments", @@ -3410,6 +3436,25 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", + "service.overview.table.id": "Services ID", + + "service.overview.table.name": "Name", + + "service.overview.table.start": "Start time (UTC)", + + "service.overview.table.status": "Status", + + "service.overview.table.user": "User", + + "service.overview.title": "Services Overview", + + "service.overview.breadcrumbs": "Services Overview", + + "service.overview.table.actions": "Actions", + + "service.overview.table.description": "Description", + + "profile.breadcrumbs": "Update Profile", "profile.card.identify": "Identify", From 4805b5061a7af9884040fafae50056fd1913b552 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Mon, 18 Sep 2023 13:36:57 +0200 Subject: [PATCH 070/592] CST-11048 First commit +fix for admin routing --- src/app/admin/admin-routing.module.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index 5cca6d3e22a..3acc219bce7 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,8 +6,7 @@ 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, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; -import { LDN_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { LDN_PATH, REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ From 1c9fbd46297a5aaa2ae3bcd67cdc5eccf7b486e5 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 26 Sep 2023 11:12:19 +0200 Subject: [PATCH 071/592] CST-11048 FInished the angular implementation for the ldn inbox, needs cleanup --- .../admin-ldn-services-routing.module.ts | 7 + .../admin-ldn-services.module.ts | 2 + .../ldn-service-form-edit.component.html | 117 ++++++++ .../ldn-service-form-edit.component.scss | 51 ++++ .../ldn-service-form-edit.component.spec.ts | 23 ++ .../ldn-service-form-edit.component.ts | 250 ++++++++++++++++++ .../ldn-service-form.component.html | 132 +++++---- .../ldn-service-form.component.scss | 43 +-- .../ldn-service-form.component.ts | 48 ++-- .../ldn-services-directory.component.html | 144 +++++----- .../ldn-services-directory.component.scss | 29 ++ .../ldn-services-directory.component.ts | 206 +++++++++------ .../ldn-service.resource-type.ts | 2 +- .../ldn-directory.service.ts | 12 +- src/app/menu.resolver.ts | 25 ++ src/assets/i18n/en.json5 | 69 ++++- 16 files changed, 916 insertions(+), 244 deletions(-) create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 740cd39621e..4f05bca9e34 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -4,6 +4,7 @@ import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; +import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @NgModule({ imports: [ @@ -22,6 +23,12 @@ import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.compon component: LdnServiceNewComponent, data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' } }, + { + path: 'edit/:serviceId', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + component: LdnServiceFormEditComponent, + data: { title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service' } + }, ]), ] }) diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index c03c16109ed..1fd67d53b9a 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -5,6 +5,7 @@ import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-servi import { SharedModule } from '../../shared/shared.module'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; +import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @@ -18,6 +19,7 @@ import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.com LdnServicesOverviewComponent, LdnServiceNewComponent, LdnServiceFormComponent, + LdnServiceFormEditComponent, ] }) export class AdminLdnServicesModule { } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html new file mode 100644 index 00000000000..263725e8add --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -0,0 +1,117 @@ +
+ +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ +
+ + {{ 'ldn-edit-service.form.label.addInboundPattern' | translate }} + + +
+ + + + + + + +
+ + + + + +
+ + + +
+ +
+ + {{ 'ldn-edit-service.form.label.addOutboundPattern' | translate }} + + + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss new file mode 100644 index 00000000000..53bc21d1b3f --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -0,0 +1,51 @@ + +form { + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 0 auto; + max-width: 600px; + font-size: 14px; +} + + +.form-group input[type="text"], +.form-group select { + max-width: 100%; + width: 100%; + padding: 8px; + margin-bottom: 5px; + box-sizing: border-box; + font-size: 14px; +} + + +.description { + height: 9em; + width: 100%; +} + + +.form-group select { + position: relative; + z-index: 1; +} + + +.form-group select option { + font-weight: bold; +} + +.add-pattern-link{ + color: #0048ff; + cursor: pointer; + margin-left: 10px; +} +.remove-pattern-link{ + color: #e34949; + cursor: pointer; + margin-left: 10px; +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts new file mode 100644 index 00000000000..8320ec90422 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceFormEditComponent } from './ldn-service-form-edit.component'; + +describe('LdnServiceFormEditComponent', () => { + let component: LdnServiceFormEditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceFormEditComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LdnServiceFormEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts new file mode 100644 index 00000000000..82f7b212d13 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -0,0 +1,250 @@ +import { Component, Input } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { Router } from '@angular/router'; +import { HttpClient } from '@angular/common/http'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; +import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; +import { ActivatedRoute } from '@angular/router'; // Import ActivatedRoute and Params + +@Component({ + selector: 'ds-ldn-service-form-edit', + templateUrl: './ldn-service-form-edit.component.html', + styleUrls: ['./ldn-service-form-edit.component.scss'] +}) +export class LdnServiceFormEditComponent { + formModel: FormGroup; + + showItemFilterDropdown = false; + + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + public itemFilterList: LdnServiceConstraint[]; + + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + + @Input() public headerKey: string; + private serviceId: string; + + constructor( + private ldnServicesService: LdnServicesService, + private ldnDirectoryService: LdnDirectoryService, + private formBuilder: FormBuilder, + private http: HttpClient, + private router: Router, + private route: ActivatedRoute + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: ['', Validators.required], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), + notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + type: LDN_SERVICE.value, + }); + } + + ngOnInit(): void { + this.route.params.subscribe((params) => { + this.serviceId = params.serviceId; + if (this.serviceId) { + this.fetchServiceData(this.serviceId); + } + }); + this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { + console.log(itemFilters); + this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ + name: filter.id + })); + console.log(this.itemFilterList); + }); + } + + fetchServiceData(serviceId: string): void { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.get(apiUrl).subscribe( + (data: any) => { + console.log(data); + + this.formModel.patchValue({ + id: data.id, + name: data.name, + description: data.description, + url: data.url, + ldnUrl: data.ldnUrl, + notifyServiceInboundPatterns: data.notifyServiceInboundPatterns, + notifyServiceOutboundPatterns: data.notifyServiceOutboundPatterns + }); + }, + (error) => { + console.error('Error fetching service data:', error); + } + ); + } + + generatePatchOperations(): any[] { + const patchOperations: any[] = []; + + if (this.formModel.get('name').dirty) { + patchOperations.push({ + op: 'replace', + path: '/name', + value: this.formModel.get('name').value, + }); + } + + if (this.formModel.get('description').dirty) { + patchOperations.push({ + op: 'replace', + path: '/description', + value: this.formModel.get('description').value, + }); + } + + if (this.formModel.get('ldnUrl').dirty) { + patchOperations.push({ + op: 'replace', + path: '/ldnUrl', + value: this.formModel.get('ldnUrl').value, + }); + } + + if (this.formModel.get('url').dirty) { + patchOperations.push({ + op: 'replace', + path: '/url', + value: this.formModel.get('url').value, + }); + } + + const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + const inboundPatternsControls = inboundPatternsArray.controls; + + if (inboundPatternsArray.dirty) { + const inboundPatternsValue = []; + + for (let i = 0; i < inboundPatternsControls.length; i++) { + const patternGroup = inboundPatternsControls[i] as FormGroup; + const patternValue = patternGroup.value; + + if (patternGroup.dirty) { + inboundPatternsValue.push(patternValue); + } + } + + if (inboundPatternsValue.length > 0) { + patchOperations.push({ + op: 'replace', + path: '/notifyServiceInboundPatterns', + value: inboundPatternsValue, + }); + } else { + patchOperations.push({ + op: 'remove', + path: '/notifyServiceInboundPatterns', + }); + } + } + + + const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + const outboundPatternsControls = outboundPatternsArray.controls; + + if (outboundPatternsArray.dirty) { + const outboundPatternsValue = []; + + for (let i = 0; i < outboundPatternsControls.length; i++) { + const patternGroup = outboundPatternsControls[i] as FormGroup; + const patternValue = patternGroup.value; + + if (patternGroup.dirty) { + outboundPatternsValue.push(patternValue); + } + } + + if (outboundPatternsValue.length > 0) { + patchOperations.push({ + op: 'replace', + path: '/notifyServiceOutboundPatterns', + value: outboundPatternsValue, + }); + } else { + patchOperations.push({ + op: 'remove', + path: '/notifyServiceOutboundPatterns', + }); + } + } + + return patchOperations; + } + + submitForm() { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.serviceId}`; + const patchOperations = this.generatePatchOperations(); + + this.http.patch(apiUrl, patchOperations).subscribe( + (response) => { + console.log('Service updated successfully:', response); + }, + (error) => { + console.error('Error updating service:', error); + } + ); + } + + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } + + removeInboundPattern(patternGroup: FormGroup) { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + } + + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); + } + + removeOutboundPattern(patternGroup: FormGroup) { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + } + + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } + + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '' + }); + } + + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: '' + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 64146b31a14..a3272ffc443 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,96 +1,136 @@
-
- - - - +
+ +
-
- - +
+ +
-
- - +
+ +
-
- - +
+ +
-
+
- +
+ - - - + + - + +
-
+ - +
+ - + + + +
- - +
+ +
+ +
+
- +
+
+
- - Remove -
- + Add more + {{ 'ldn-new-service.form.label.addPattern' | translate }} -
+
- +
+ - - - + + - + +
- - Remove +
+ + + + + +
+ +
+ +
- + Add more + {{ 'ldn-new-service.form.label.addPattern' | translate }} + - diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 53bc21d1b3f..d98ebb3deea 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -1,39 +1,36 @@ - form { display: flex; flex-direction: column; align-items: flex-start; - margin: 0 auto; - max-width: 600px; + max-width: 800px; font-size: 14px; -} + margin-left: 300px; + & > * { + width: 100%; + } +} -.form-group input[type="text"], -.form-group select { +input[type="text"], +select { max-width: 100%; width: 100%; padding: 8px; - margin-bottom: 5px; - box-sizing: border-box; font-size: 14px; } - -.description { - height: 9em; - width: 100%; +option:not(:first-child) { + font-weight: bold; } - -.form-group select { - position: relative; - z-index: 1; +.trash-button { + width: 40px; + height: 40px; } - -.form-group select option { - font-weight: bold; +textarea { + height: 200px; + resize: none; } .add-pattern-link{ @@ -47,5 +44,13 @@ form { margin-left: 10px; } +.status-checkbox { + margin-top: 5px; +} +.invalid-field { + border: 1px solid red; + background-color: #e89f9f; + color: #000000; +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index b17cc6902dc..54934913c7f 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Router } from '@angular/router'; import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; @@ -17,14 +17,17 @@ import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; export class LdnServiceFormComponent implements OnInit { formModel: FormGroup; - showItemFilterDropdown = false; + + + //showItemFilterDropdown = false; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; public itemFilterList: LdnServiceConstraint[]; - additionalOutboundPatterns: FormGroup[] = []; - additionalInboundPatterns: FormGroup[] = []; + //additionalOutboundPatterns: FormGroup[] = []; + //additionalInboundPatterns: FormGroup[] = []; + //@Input() public status: boolean; @Input() public name: string; @Input() public description: string; @Input() public url: string; @@ -36,6 +39,12 @@ export class LdnServiceFormComponent implements OnInit { @Input() public headerKey: string; + /* + get notifyServiceInboundPatternsFormArray(): FormArray { + return this.formModel.get('notifyServiceInboundPatterns') as FormArray; + } + */ + constructor( private ldnServicesService: LdnServicesService, private ldnDirectoryService: LdnDirectoryService, @@ -45,9 +54,10 @@ export class LdnServiceFormComponent implements OnInit { ) { this.formModel = this.formBuilder.group({ + //enabled: true, id: [''], name: ['', Validators.required], - description: ['', Validators.required], + description: [''], url: ['', Validators.required], ldnUrl: ['', Validators.required], inboundPattern: [''], @@ -65,12 +75,23 @@ export class LdnServiceFormComponent implements OnInit { this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ name: filter.id })); - console.log(this.itemFilterList); }); } submitForm() { + this.formModel.get('name').markAsTouched(); + this.formModel.get('url').markAsTouched(); + this.formModel.get('ldnUrl').markAsTouched(); + + const name = this.formModel.get('name').value; + const url = this.formModel.get('url').value; + const ldnUrl = this.formModel.get('ldnUrl').value; + + if (!name || !url || !ldnUrl) { + return; + } + this.formModel.removeControl('inboundPattern'); this.formModel.removeControl('outboundPattern'); this.formModel.removeControl('constraintPattern'); @@ -78,7 +99,7 @@ export class LdnServiceFormComponent implements OnInit { const apiUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; - this.http.post(apiUrl, this.formModel.value ).subscribe( + this.http.post(apiUrl, this.formModel.value).subscribe( (response) => { console.log('Service created successfully:', response); this.formModel.reset(); @@ -90,16 +111,6 @@ export class LdnServiceFormComponent implements OnInit { ); } - private validateForm(form: FormGroup): boolean { - let valid = true; - Object.keys(form.controls).forEach((key) => { - if (form.controls[key].invalid) { - form.controls[key].markAsDirty(); - valid = false; - } - }); - return valid; - } private sendBack() { this.router.navigateByUrl('admin/ldn/services'); @@ -136,7 +147,8 @@ export class LdnServiceFormComponent implements OnInit { return this.formBuilder.group({ pattern: [''], constraint: [''], - automatic: [true] + automatic: false }); } + } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index bd2ec0d418b..7d02ffe513e 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -1,85 +1,81 @@
- {{ldnServicesRD$ | async | json }} -
-

{{'ldn-registered-services.title' | translate}}

-
-
- - - - -
- -
- - - - - - - - - - - - - - - - -
{{'service.overview.table.name' | translate}}{{'service.overview.table.description' | translate}}{{'service.overview.table.status' | translate}}{{'service.overview.table.actions' | translate}}
{{ldnService.id}}{{ldnService.description}} - -
+ {{ ldnServicesRD$ | async | json }} +
+

{{ 'ldn-registered-services.title' | translate }}

+
+
+
- + +
+ + + + + + + + + + + + + + + + + +
{{ 'service.overview.table.name' | translate }}{{ 'service.overview.table.description' | translate }}{{ 'service.overview.table.status' | translate }}{{ 'service.overview.table.actions' | translate }}
{{ ldnService.name }}{{ ldnService.description }} + + {{ ldnService.status ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} + + + + +
+
+
-
+
- + - -
- - diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss index e69de29bb2d..07377d63d5a 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss @@ -0,0 +1,29 @@ +.status-indicator { + padding: 2.5px 25px 2.5px 25px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.5s; +} + +.status-enabled { + background-color: #daf7a6; + color: #4f5359; + font-size: 85%; + font-weight: bold; + +} + +.status-enabled:hover { + background-color: #faa0a0; +} + +.status-disabled { + background-color: #faa0a0; + color: #4f5359; + font-size: 85%; + font-weight: bold; +} + +.status-disabled:hover { + background-color: #daf7a6; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index e8c81ea8731..ceaaebdd4f5 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; @@ -10,96 +10,152 @@ import { switchMap } from 'rxjs/operators'; import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { LdnServicesBulkDeleteService } from 'src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service'; import { hasValue } from '../../../shared/empty.util'; import { HttpClient } from '@angular/common/http'; @Component({ - selector: 'ds-ldn-services-directory', - templateUrl: './ldn-services-directory.component.html', - styleUrls: ['./ldn-services-directory.component.scss'], + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], }) export class LdnServicesOverviewComponent implements OnInit, OnDestroy { - ldnServicesRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - private modalRef: any; - isProcessingSub: Subscription; - - constructor( - protected processLdnService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - public ldnServicesBulkDeleteService: LdnServicesBulkDeleteService, - public ldnDirectoryService: LdnDirectoryService, - private http: HttpClient - ) {} - - ngOnInit(): void { - this.setLdnServices(); - this.ldnDirectoryService.listLdnServices(); - this.searchByLdnUrl(); - } - - setLdnServices() { - debugger; - this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.processLdnService.findAll(config, true, false)) - ); - console.log() - } - - ngOnDestroy(): void { - this.paginationService.clearPagination(this.pageConfig.id); - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); + selectedServiceId: number | null = null; + servicesData: any[] = []; + @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + isProcessingSub: Subscription; + private modalRef: any; + + constructor( + protected processLdnService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public ldnDirectoryService: LdnDirectoryService, + private http: HttpClient + ) { + } + + ngOnInit(): void { + /*this.ldnDirectoryService.listLdnServices();*/ + this.findAllServices(); + this.setLdnServices(); + /*this.ldnServicesRD$.subscribe(data => { + console.log('searchByLdnUrl()', data); + });*/ + + /*this.ldnServicesRD$.pipe( + tap(data => { + console.log('ldnServicesRD$ data:', data); + }) + ).subscribe(() => { + this.searchByLdnUrl(); + });*/ + + } + + setLdnServices() { + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.processLdnService.findAll(config, true, false)) + ); + console.log(); + } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + } + + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); } - } - openDeleteModal(content) { - this.modalRef = this.modalService.open(content); - } + closeModal() { + this.modalRef.close(); + } + + + findAllServices(): void { + this.retrieveAll().subscribe( + (response) => { + this.servicesData = response._embedded.ldnservices; + console.log('ServicesData =', this.servicesData); + }, + (error) => { + console.error('Error:', error); + } + ); + } - closeModal() { - this.modalRef.close(); - } + retrieveAll(): Observable { + const url = 'http://localhost:8080/server/api/ldn/ldnservices'; + return this.http.get(url); + } - findByLdnUrl(): Observable { - const url = 'http://localhost:8080/server/api/ldn/ldnservices'; - return this.http.get(url); - } - searchByLdnUrl(): void { - this.findByLdnUrl().subscribe( - (response) => { - console.log('Search results:', response); - }, - (error) => { - console.error('Error:', error); + deleteSelected() { + if (this.selectedServiceId !== null) { + const deleteUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.selectedServiceId}`; + this.http.delete(deleteUrl).subscribe( + () => { + this.closeModal(); + this.findAllServices(); + }, + (error) => { + console.error('Error deleting service:', error); + } + ); } - ); - } + } + + selectServiceToDelete(serviceId: number) { + this.selectedServiceId = serviceId; + this.openDeleteModal(this.deleteModal); + } + + toggleStatus(ldnService: any): void { + const newStatus = !ldnService.status; + + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`; + const patchOperation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.http.patch(apiUrl, [patchOperation]).subscribe( + () => { + console.log('Status updated successfully.'); + // After a successful update, fetch the data to refresh the view + this.fetchServiceData(ldnService.id); + }, + (error) => { + console.error('Error updating status:', error); + } + ); + } - deleteSelected() { - this.ldnServicesBulkDeleteService.deleteSelectedLdnServices(); + fetchServiceData(serviceId: string): void { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); + this.http.get(apiUrl).subscribe( + (data: any) => { + console.log(data); + }, + (error) => { + console.error('Error fetching service data:', error); + } + ); } - this.isProcessingSub = this.ldnServicesBulkDeleteService.isProcessing$() - .subscribe((isProcessing) => { - if (!isProcessing) { - this.closeModal(); - this.setLdnServices(); - } - }); - } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts index c00d241ee86..937fac255d6 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -6,4 +6,4 @@ */ import { ResourceType } from '../../../core/shared/resource-type'; -export const LDN_SERVICE = new ResourceType('notifyservice'); +export const LDN_SERVICE = new ResourceType('ldnservices'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts index d06057800bf..5ed32f5bb77 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { Observable, tap } from 'rxjs'; import { LdnService } from '../ldn-services-model/ldn-services.model'; @Injectable({ @@ -16,7 +16,11 @@ export class LdnDirectoryService { public listLdnServices(): Observable { const endpoint = `${this.baseUrl}`; - return this.http.get(endpoint); + return this.http.get(endpoint).pipe( + tap(data => { + console.log('listLdnServices() Data:', data); + }) + ); } public getLdnServiceById(id: string): Observable { @@ -44,8 +48,8 @@ export class LdnDirectoryService { } public getItemFilters(): Observable { - const endpoint = `${this.itemFilterEndpoint}`; - return this.http.get(endpoint); + const itemFiltersEndpoint = `${this.itemFilterEndpoint}`; + return this.http.get(itemFiltersEndpoint); } } diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 70e2b6462f8..23ba31b1033 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -222,6 +222,18 @@ export class MenuResolver implements Resolve { text: 'menu.section.new_process', link: '/processes/new' } as LinkMenuItemModel, + },/* ldn_services */ + { + id: 'ldn_services_new', + parentID: 'new', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services_new', + link: '/admin/ldn/services/new' + } as LinkMenuItemModel, + icon: '', }, ]; const editSubMenuList = [ @@ -350,6 +362,19 @@ export class MenuResolver implements Resolve { icon: 'terminal', index: 10 }, + /* LDN Services */ + { + id: 'ldn_services', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services', + link: '/admin/ldn/services' + } as LinkMenuItemModel, + icon: 'inbox', + index: 14 + }, { id: 'health', active: false, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 78d4c1b3e16..b5307414e3a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -902,7 +902,7 @@ "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking here.", - + "service.overview.delete.header": "Delete Service", "ldn-registered-services.title": "Registered Services", "ldn-registered-services.table.name":"Name", @@ -912,14 +912,49 @@ "ldn-registered-services.new": "NEW", "ldn-registered-services.new.breadcrumbs": "Registered Services", + "ldn-service.overview.table.enabled": "Enabled", + "ldn-service.overview.table.disabled": "Disabled", + "ldn-service.overview.table.clickToEnable": "Click to enable", + "ldn-service.overview.table.clickToDisable": "Click to disable", + "ldn-register-new-service.title": "Register a new service", - "ldn-register-new-service.name": "Name", - "ldn-register-new-service.url": "Service URL", - "ldn-register-new-service.ldn.inbox.url": "LDN InBox URL", - "ldn-register-new-service.inbound": "Inbound- Patterns supported by the service (i.e. messages that the service is able to receive and understand)", - "ldn-register-new-service.outbound": "Outbound- Patterns supported by the service (i.e. messages that the service is likely to generate and that should be processed by DSpace)", - "ldn-register-new-service.addmore": "+ Add more", + "ldn-new-service.form.label.name": "Name", + "ldn-new-service.form.label.description": "Description", + "ldn-new-service.form.label.url": "Service URL", + "ldn-new-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-new-service.form.placeholder.name": "Please provide service name", + "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", + "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", + "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", + "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-new-service.form.label.placeholder.inboundPattern": "No Inbound Pattern", + "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", + "ldn-new-service.form.label.ItemFilter": "Item Filter", + "ldn-new-service.form.label.automatic": "Automatic", + "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-new-service.form.label.placeholder.outboundPattern": "No Outbound Pattern", + "ldn-new-service.form.label.addPattern": "+ Add more", + "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", + "service.overview.delete.body": "Are you sure you want to delete this service?", + "service.overview.delete": "Delete service", + "ldn-edit-service.title": "Edit service", + "ldn-edit-service.form.label.name": "Name", + "ldn-edit-service.form.label.description": "Description", + "ldn-edit-service.form.label.url": "Service URL", + "ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-edit-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern", + "ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter", + "ldn-edit-service.form.label.selectItemFilter": "No Item Filter", + "ldn-edit-service.form.label.automatic": "Automatic", + "ldn-edit-service.form.label.addInboundPattern": "+ Add more", + "ldn-edit-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-edit-service.form.label.noOutboundPatternSelected": "No Outbound Pattern", + "ldn-edit-service.form.label.addOutboundPattern": "+ Add more", + "ldn-edit-service.form.label.submit": "Submit", + "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-register-new-service.notification.error.title": "Error", "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", @@ -2942,6 +2977,8 @@ "menu.section.icon.notifications": "Notifications menu section", + "menu.section.icon.ldn_services": "LDN Services overview", + "menu.section.import": "Import", "menu.section.import_batch": "Batch Import (ZIP)", @@ -2980,6 +3017,10 @@ "menu.section.registries_metadata": "Metadata", + "menu.section.services": "LDN Services", + + "menu.section.services_new": "LDN Service", + "menu.section.statistics": "Statistics", "menu.section.statistics_task": "Statistics Task", @@ -3454,6 +3495,20 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", + "service.detail.delete.cancel": "Cancel", + + "service.detail.delete.button": "Delete service", + + "service.detail.delete.header": "Delete service", + + "service.detail.delete.body": "Are you sure you want to delete the current service?", + + "service.detail.delete.confirm": "Delete service", + + "service.detail.delete.success": "The service was successfully deleted.", + + "service.detail.delete.error": "Something went wrong when deleting the service", + "service.overview.table.id": "Services ID", "service.overview.table.name": "Name", From 11f9258d40daf99a1b80dd9539c821462270c2b9 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 6 Oct 2023 01:02:49 +0200 Subject: [PATCH 072/592] CST-11048 Form Styling --- .../ldn-service-form-edit.component.html | 214 +++++++------ .../ldn-service-form-edit.component.scss | 86 ++++-- .../ldn-service-form-edit.component.ts | 288 ++++++++++++------ .../ldn-service-form.component.html | 11 +- .../ldn-service-form.component.scss | 46 ++- .../ldn-service-form.component.ts | 19 +- .../ldn-services-directory.component.html | 6 +- .../ldn-services-directory.component.ts | 14 +- src/assets/i18n/en.json5 | 6 +- 9 files changed, 469 insertions(+), 221 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 263725e8add..8640b922e30 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,117 +1,139 @@
-
- - - - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - - - - - - -
- - - - - -
- - -
+
+ + +
+ +
+   +
+ +
+ + +
+ +
+   +
+ +
+ + +
+ +
+   +
+ +
+ + +
+ +
+   +
+ +
+ + + +
+ + +
+ + + +
+ + +
+ +
+ +
+ +
+
+
+
- -
- -
+ - {{ 'ldn-edit-service.form.label.addInboundPattern' | translate }} +
+ +
- -
+ - +
- + {{ 'ldn-new-service.form.label.addPattern' | translate }} - + -
+
+ + +
- - - - -
+
+ + +
- +
+ +
-
+ -
+
- {{ 'ldn-edit-service.form.label.addOutboundPattern' | translate }} - + {{ 'ldn-new-service.form.label.addPattern' | translate }} +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index 53bc21d1b3f..ef38297649c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -1,39 +1,36 @@ - form { display: flex; flex-direction: column; align-items: flex-start; - margin: 0 auto; - max-width: 600px; + max-width: 800px; font-size: 14px; -} + margin-left: 300px; + & > * { + width: 100%; + } +} -.form-group input[type="text"], -.form-group select { +input[type="text"], +select { max-width: 100%; width: 100%; padding: 8px; - margin-bottom: 5px; - box-sizing: border-box; font-size: 14px; } - -.description { - height: 9em; - width: 100%; +option:not(:first-child) { + font-weight: bold; } - -.form-group select { - position: relative; - z-index: 1; +.trash-button { + width: 40px; + height: 40px; } - -.form-group select option { - font-weight: bold; +textarea { + height: 200px; + resize: none; } .add-pattern-link{ @@ -47,5 +44,56 @@ form { margin-left: 10px; } +.status-checkbox { + margin-top: 5px; +} + + +.invalid-field { + border: 1px solid red; + background-color: #e89f9f; + color: #000000; +} + +.toggle-switch { + display: flex; + align-items: center; + opacity: 0.8; + position: relative; + width: 60px; + height: 30px; + background-color: #ccc; + border-radius: 15px; + cursor: pointer; + transition: background-color 0.3s; +} + +.toggle-switch.checked { + background-color: #24cc9a; +} + +.slider { + position: absolute; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: #fff; + transition: transform 0.3s; +} + + + +.toggle-switch .slider { + width: 22px; + height: 22px; + border-radius: 50%; + margin: 0 auto; +} + +.toggle-switch.checked .slider { + transform: translateX(30px); +} + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 82f7b212d13..d86371d441b 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { ChangeDetectorRef, Component, Input } from '@angular/core'; import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; import { Router } from '@angular/router'; @@ -7,18 +7,28 @@ import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.serv import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; -import { ActivatedRoute } from '@angular/router'; // Import ActivatedRoute and Params +import { ActivatedRoute } from '@angular/router'; +import { animate, state, style, transition, trigger } from '@angular/animations'; @Component({ selector: 'ds-ldn-service-form-edit', templateUrl: './ldn-service-form-edit.component.html', - styleUrls: ['./ldn-service-form-edit.component.scss'] + styleUrls: ['./ldn-service-form-edit.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), + ]), + ], }) export class LdnServiceFormEditComponent { formModel: FormGroup; showItemFilterDropdown = false; + private originalInboundPatterns: any[] = []; + private originalOutboundPatterns: any[] = []; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; public itemFilterList: LdnServiceConstraint[]; @@ -41,7 +51,8 @@ export class LdnServiceFormEditComponent { private formBuilder: FormBuilder, private http: HttpClient, private router: Router, - private route: ActivatedRoute + private route: ActivatedRoute, + private cdRef: ChangeDetectorRef ) { this.formModel = this.formBuilder.group({ @@ -67,14 +78,34 @@ export class LdnServiceFormEditComponent { } }); this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { - console.log(itemFilters); this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ name: filter.id })); - console.log(this.itemFilterList); + this.cdRef.detectChanges(); + }); } + private getOriginalPattern(formArrayName: string, patternId: number): any { + let originalPatterns: any[] = []; + + if (formArrayName === 'notifyServiceInboundPatterns') { + originalPatterns = this.originalInboundPatterns; + } else if (formArrayName === 'notifyServiceOutboundPatterns') { + originalPatterns = this.originalOutboundPatterns; + } + + return originalPatterns.find((pattern) => pattern.id === patternId); + } + + private patternsAreEqual(patternA: any, patternB: any): boolean { + return ( + patternA.pattern === patternB.pattern && + patternA.constraint === patternB.constraint && + patternA.automatic === patternB.automatic + ); + } + fetchServiceData(serviceId: string): void { const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; @@ -88,9 +119,35 @@ export class LdnServiceFormEditComponent { description: data.description, url: data.url, ldnUrl: data.ldnUrl, - notifyServiceInboundPatterns: data.notifyServiceInboundPatterns, - notifyServiceOutboundPatterns: data.notifyServiceOutboundPatterns + type: data.type + }); + + const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + inboundPatternsArray.clear(); // Clear existing rows + + data.notifyServiceInboundPatterns.forEach((pattern: any) => { + console.log(pattern); + const patternFormGroup = this.initializeInboundPatternFormGroup(); + console.log(); + patternFormGroup.patchValue(pattern); + inboundPatternsArray.push(patternFormGroup); + this.cdRef.detectChanges(); }); + + // Initialize rows for notifyServiceOutboundPatterns + const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + outboundPatternsArray.clear(); + + data.notifyServiceOutboundPatterns.forEach((pattern: any) => { + const patternFormGroup = this.initializeOutboundPatternFormGroup(); + patternFormGroup.patchValue(pattern); + outboundPatternsArray.push(patternFormGroup); + + this.cdRef.detectChanges(); + }); + this.originalInboundPatterns = [...data.notifyServiceInboundPatterns]; + + this.originalOutboundPatterns = [...data.notifyServiceOutboundPatterns]; }, (error) => { console.error('Error fetching service data:', error); @@ -98,101 +155,74 @@ export class LdnServiceFormEditComponent { ); } + generatePatchOperations(): any[] { const patchOperations: any[] = []; - if (this.formModel.get('name').dirty) { - patchOperations.push({ - op: 'replace', - path: '/name', - value: this.formModel.get('name').value, - }); - } + this.addReplaceOperation(patchOperations, 'name', '/name'); + this.addReplaceOperation(patchOperations, 'description', '/description'); + this.addReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); + this.addReplaceOperation(patchOperations, 'url', '/url'); - if (this.formModel.get('description').dirty) { - patchOperations.push({ - op: 'replace', - path: '/description', - value: this.formModel.get('description').value, - }); - } + // Handle notifyServiceInboundPatterns + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - if (this.formModel.get('ldnUrl').dirty) { - patchOperations.push({ - op: 'replace', - path: '/ldnUrl', - value: this.formModel.get('ldnUrl').value, - }); - } + // Handle notifyServiceOutboundPatterns + this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); - if (this.formModel.get('url').dirty) { + return patchOperations; + } + + private addReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { + if (this.formModel.get(formControlName).dirty) { patchOperations.push({ op: 'replace', - path: '/url', - value: this.formModel.get('url').value, + path, + value: this.formModel.get(formControlName).value, }); } + } - const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - const inboundPatternsControls = inboundPatternsArray.controls; - - if (inboundPatternsArray.dirty) { - const inboundPatternsValue = []; + private handlePatterns(patchOperations: any[], formArrayName: string): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; - for (let i = 0; i < inboundPatternsControls.length; i++) { - const patternGroup = inboundPatternsControls[i] as FormGroup; + if (patternsArray.dirty) { + for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; const patternValue = patternGroup.value; - if (patternGroup.dirty) { - inboundPatternsValue.push(patternValue); + // patternValue.automatic = patternValue.automatic ? 'true' : 'false'; + + if (patternValue.isNew) { + console.log(this.getOriginalPatternsForFormArray(formArrayName)); + console.log(patternGroup); + delete patternValue.isNew; + const addOperation = { + op: 'add', + path: `${formArrayName}/-`, + value: patternValue, + }; + patchOperations.push(addOperation); + } else if (patternGroup.dirty) { + const replaceOperation = { + op: 'replace', + path: `${formArrayName}[${i}]`, + value: patternValue, + }; + patchOperations.push(replaceOperation); + console.log(patternValue.id); } } - - if (inboundPatternsValue.length > 0) { - patchOperations.push({ - op: 'replace', - path: '/notifyServiceInboundPatterns', - value: inboundPatternsValue, - }); - } else { - patchOperations.push({ - op: 'remove', - path: '/notifyServiceInboundPatterns', - }); - } } + } - - const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - const outboundPatternsControls = outboundPatternsArray.controls; - - if (outboundPatternsArray.dirty) { - const outboundPatternsValue = []; - - for (let i = 0; i < outboundPatternsControls.length; i++) { - const patternGroup = outboundPatternsControls[i] as FormGroup; - const patternValue = patternGroup.value; - - if (patternGroup.dirty) { - outboundPatternsValue.push(patternValue); - } - } - - if (outboundPatternsValue.length > 0) { - patchOperations.push({ - op: 'replace', - path: '/notifyServiceOutboundPatterns', - value: outboundPatternsValue, - }); - } else { - patchOperations.push({ - op: 'remove', - path: '/notifyServiceOutboundPatterns', - }); - } + private getOriginalPatternsForFormArray(formArrayName: string): any[] { + if (formArrayName === 'notifyServiceInboundPatterns') { + return this.originalInboundPatterns; + } else if (formArrayName === 'notifyServiceOutboundPatterns') { + return this.originalOutboundPatterns; } - - return patchOperations; + return []; } submitForm() { @@ -202,21 +232,50 @@ export class LdnServiceFormEditComponent { this.http.patch(apiUrl, patchOperations).subscribe( (response) => { console.log('Service updated successfully:', response); + this.sendBack(); }, (error) => { console.error('Error updating service:', error); } ); + } + addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } - removeInboundPattern(patternGroup: FormGroup) { + removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + if (index >= 0 && index < notifyServiceInboundPatternsArray.length) { + // Get the service ID + const serviceId = this.formModel.get('id').value; + + // Construct the patch operation + const patchOperation = [ + { + op: 'remove', + path: `notifyServiceInboundPatterns[${index}]` + } + ]; + + // Make an HTTP PATCH request to apply the patch operation + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.patch(apiUrl, patchOperation).subscribe( + (response) => { + console.log('Pattern removed successfully:', response); + + // After successful removal from the server, also remove it from the form array + notifyServiceInboundPatternsArray.removeAt(index); + }, + (error) => { + console.error('Error removing pattern:', error); + } + ); + } } addOutboundPattern() { @@ -224,9 +283,34 @@ export class LdnServiceFormEditComponent { notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } - removeOutboundPattern(patternGroup: FormGroup) { + removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + if (index >= 0 && index < notifyServiceOutboundPatternsArray.length) { + // Get the service ID + const serviceId = this.formModel.get('id').value; + + // Construct the patch operation + const patchOperation = [ + { + op: 'remove', + path: `notifyServiceOutboundPatterns[${index}]` + } + ]; + + // Make an HTTP PATCH request to apply the patch operation + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.patch(apiUrl, patchOperation).subscribe( + (response) => { + console.log('Pattern removed successfully:', response); + + notifyServiceOutboundPatternsArray.removeAt(index); + }, + (error) => { + console.error('Error removing pattern:', error); + } + ); + } } private sendBack() { @@ -236,7 +320,8 @@ export class LdnServiceFormEditComponent { private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', - constraint: '' + constraint: '', + isNew: true, }); } @@ -244,7 +329,30 @@ export class LdnServiceFormEditComponent { return this.formBuilder.group({ pattern: '', constraint: '', - automatic: '' + automatic: '', + isNew: true + }); + } + + private initializeOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', }); } + + private initializeInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: '', + }); + } + + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index a3272ffc443..db55ec285a9 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -67,14 +67,19 @@
- + +
+
+
+ +
-
@@ -119,7 +124,7 @@
-
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index d98ebb3deea..ade0744d4ce 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -23,6 +23,10 @@ option:not(:first-child) { font-weight: bold; } +select { + width: 90%; +} + .trash-button { width: 40px; height: 40px; @@ -51,6 +55,46 @@ textarea { .invalid-field { border: 1px solid red; - background-color: #e89f9f; color: #000000; } + + +.toggle-switch { + display: flex; + align-items: center; + opacity: 0.8; + position: relative; + width: 60px; + height: 30px; + background-color: #ccc; + border-radius: 15px; + cursor: pointer; + transition: background-color 0.3s; +} + +.toggle-switch.checked { + background-color: #24cc9a; +} + +.slider { + position: absolute; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: #fff; + transition: transform 0.3s; +} + + + +.toggle-switch .slider { + width: 22px; + height: 22px; + border-radius: 50%; + margin: 0 auto; +} + +.toggle-switch.checked .slider { + transform: translateX(30px); +} + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 54934913c7f..608a7ada23b 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -8,11 +8,19 @@ import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constrai import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { animate, state, style, transition, trigger } from '@angular/animations'; @Component({ selector: 'ds-ldn-service-form', templateUrl: './ldn-service-form.component.html', styleUrls: ['./ldn-service-form.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), // Define animation states (empty style) + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), // Define animation transition with duration + ]), + ], }) export class LdnServiceFormComponent implements OnInit { formModel: FormGroup; @@ -27,6 +35,7 @@ export class LdnServiceFormComponent implements OnInit { //additionalOutboundPatterns: FormGroup[] = []; //additionalInboundPatterns: FormGroup[] = []; + //@Input() public status: boolean; @Input() public name: string; @Input() public description: string; @@ -54,7 +63,7 @@ export class LdnServiceFormComponent implements OnInit { ) { this.formModel = this.formBuilder.group({ - //enabled: true, + enabled: true, id: [''], name: ['', Validators.required], description: [''], @@ -151,4 +160,12 @@ export class LdnServiceFormComponent implements OnInit { }); } + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } + + } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index 7d02ffe513e..481989092e9 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -28,10 +28,10 @@

{{ 'ldn-registered-services.title' | translate }}

{{ ldnService.name }} {{ ldnService.description }} - - {{ ldnService.status ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} + [title]="ldnService.enabled ? ('ldn-service.overview.table.clickToDisable' | translate) : ('ldn-service.overview.table.clickToEnable' | translate)"> + {{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index ceaaebdd4f5..9d19ad56c75 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; @@ -12,7 +12,6 @@ import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { HttpClient } from '@angular/common/http'; - @Component({ selector: 'ds-ldn-services-directory', templateUrl: './ldn-services-directory.component.html', @@ -39,7 +38,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { protected paginationService: PaginationService, protected modalService: NgbModal, public ldnDirectoryService: LdnDirectoryService, - private http: HttpClient + private http: HttpClient, + private cdRef: ChangeDetectorRef ) { } @@ -81,6 +81,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { closeModal() { this.modalRef.close(); + this.cdRef.detectChanges(); } @@ -89,6 +90,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { (response) => { this.servicesData = response._embedded.ldnservices; console.log('ServicesData =', this.servicesData); + this.cdRef.detectChanges(); }, (error) => { console.error('Error:', error); @@ -125,7 +127,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } toggleStatus(ldnService: any): void { - const newStatus = !ldnService.status; + const newStatus = !ldnService.enabled; const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`; const patchOperation = { @@ -137,8 +139,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { this.http.patch(apiUrl, [patchOperation]).subscribe( () => { console.log('Status updated successfully.'); - // After a successful update, fetch the data to refresh the view - this.fetchServiceData(ldnService.id); + ldnService.enabled = newStatus; + this.cdRef.detectChanges(); }, (error) => { console.error('Error updating status:', error); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index b5307414e3a..60b7e3cf5d0 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -918,6 +918,7 @@ "ldn-service.overview.table.clickToDisable": "Click to disable", "ldn-register-new-service.title": "Register a new service", + "ldn-new-service.form.label.submit": "Submit", "ldn-new-service.form.label.name": "Name", "ldn-new-service.form.label.description": "Description", "ldn-new-service.form.label.url": "Service URL", @@ -927,12 +928,12 @@ "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", - "ldn-new-service.form.label.placeholder.inboundPattern": "No Inbound Pattern", + "ldn-new-service.form.label.placeholder.inboundPattern": "Select an Inbound Pattern", "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", "ldn-new-service.form.label.ItemFilter": "Item Filter", "ldn-new-service.form.label.automatic": "Automatic", "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", - "ldn-new-service.form.label.placeholder.outboundPattern": "No Outbound Pattern", + "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", @@ -956,6 +957,7 @@ "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-register-new-service.notification.error.title": "Error", "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", "ldn-register-new-service.notification.success.title": "Success", From f893c6f2f37de2ce4a411904ea1fc44938ba3b2f Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 6 Oct 2023 12:25:23 +0200 Subject: [PATCH 073/592] CST-11048 Implemented enabled slider in edit --- .../ldn-service-form-edit.component.html | 10 +++++ .../ldn-service-form-edit.component.scss | 16 +++++++ .../ldn-service-form-edit.component.ts | 42 +++++++++++++------ .../ldn-services-directory.component.html | 1 - src/assets/i18n/en.json5 | 1 + 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 8640b922e30..f887eb2a2a9 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,5 +1,15 @@ +
+
+ +
+ +
+
+
+
+
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index ef38297649c..9a35ee9ad26 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -94,6 +94,22 @@ textarea { transform: translateX(30px); } +.toggle-switch-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-end; + margin-top: 10px; +} + +.toggle-switch { + cursor: pointer; +} + + + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index d86371d441b..90a0546671a 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -64,6 +64,7 @@ export class LdnServiceFormEditComponent { inboundPattern: [''], outboundPattern: [''], constraintPattern: [''], + enabled: [''], notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), type: LDN_SERVICE.value, @@ -119,7 +120,8 @@ export class LdnServiceFormEditComponent { description: data.description, url: data.url, ldnUrl: data.ldnUrl, - type: data.type + type: data.type, + enabled: data.enabled }); const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; @@ -134,7 +136,6 @@ export class LdnServiceFormEditComponent { this.cdRef.detectChanges(); }); - // Initialize rows for notifyServiceOutboundPatterns const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; outboundPatternsArray.clear(); @@ -164,10 +165,8 @@ export class LdnServiceFormEditComponent { this.addReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); this.addReplaceOperation(patchOperations, 'url', '/url'); - // Handle notifyServiceInboundPatterns this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - // Handle notifyServiceOutboundPatterns this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); return patchOperations; @@ -191,8 +190,6 @@ export class LdnServiceFormEditComponent { const patternGroup = patternsArray.at(i) as FormGroup; const patternValue = patternGroup.value; - // patternValue.automatic = patternValue.automatic ? 'true' : 'false'; - if (patternValue.isNew) { console.log(this.getOriginalPatternsForFormArray(formArrayName)); console.log(patternGroup); @@ -250,10 +247,8 @@ export class LdnServiceFormEditComponent { removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; if (index >= 0 && index < notifyServiceInboundPatternsArray.length) { - // Get the service ID const serviceId = this.formModel.get('id').value; - // Construct the patch operation const patchOperation = [ { op: 'remove', @@ -261,14 +256,12 @@ export class LdnServiceFormEditComponent { } ]; - // Make an HTTP PATCH request to apply the patch operation const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; this.http.patch(apiUrl, patchOperation).subscribe( (response) => { console.log('Pattern removed successfully:', response); - // After successful removal from the server, also remove it from the form array notifyServiceInboundPatternsArray.removeAt(index); }, (error) => { @@ -286,10 +279,9 @@ export class LdnServiceFormEditComponent { removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; if (index >= 0 && index < notifyServiceOutboundPatternsArray.length) { - // Get the service ID const serviceId = this.formModel.get('id').value; - // Construct the patch operation + const patchOperation = [ { op: 'remove', @@ -297,7 +289,6 @@ export class LdnServiceFormEditComponent { } ]; - // Make an HTTP PATCH request to apply the patch operation const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; this.http.patch(apiUrl, patchOperation).subscribe( @@ -355,4 +346,29 @@ export class LdnServiceFormEditComponent { automaticControl.setValue(!automaticControl.value); } } + + toggleEnabled() { + const newStatus = !this.formModel.get('enabled').value; + const serviceId = this.formModel.get('id').value; + const status = this.formModel.get('enabled').value; + + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + const patchOperation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.http.patch(apiUrl, [patchOperation]).subscribe( + () => { + console.log('Status updated successfully.'); + this.formModel.get('enabled').setValue(newStatus); + console.log(this.formModel.get('enabled')); + this.cdRef.detectChanges(); + }, + (error) => { + console.error('Error updating status:', error); + } + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index 481989092e9..e3795d6e96e 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -1,5 +1,4 @@
- {{ ldnServicesRD$ | async | json }}

{{ 'ldn-registered-services.title' | translate }}

diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 60b7e3cf5d0..67ccaa03200 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -917,6 +917,7 @@ "ldn-service.overview.table.clickToEnable": "Click to enable", "ldn-service.overview.table.clickToDisable": "Click to disable", + "ldn-service-status": "Status", "ldn-register-new-service.title": "Register a new service", "ldn-new-service.form.label.submit": "Submit", "ldn-new-service.form.label.name": "Name", From c75f61840fc319f21d8d2f42e3d33a1560a26cbf Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 6 Oct 2023 13:04:52 +0200 Subject: [PATCH 074/592] CST-11048 Spaced form updated error behaviour --- .../ldn-service-form-edit.component.html | 8 +++- .../ldn-service-form-edit.component.scss | 1 - .../ldn-service-form.component.html | 38 +++++++++++++++---- .../ldn-service-form.component.scss | 26 ++++++++++--- src/assets/i18n/en.json5 | 4 +- 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index f887eb2a2a9..6402e0b9535 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -143,7 +143,13 @@
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+   +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index 9a35ee9ad26..92ac744aed8 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -51,7 +51,6 @@ textarea { .invalid-field { border: 1px solid red; - background-color: #e89f9f; color: #000000; } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index db55ec285a9..d1f13baf322 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -9,6 +9,10 @@ type="text">
+
+   +
+
@@ -16,6 +20,10 @@ formControlName="description" id="description" name="description">
+
+   +
+
@@ -25,6 +33,10 @@ type="text">
+
+   +
+
@@ -34,6 +46,10 @@ type="text">
+
+   +
+
@@ -41,7 +57,7 @@
- + @@ -65,7 +81,7 @@
- +
@@ -91,6 +107,10 @@ {{ 'ldn-new-service.form.label.addPattern' | translate }} +
+   +
+
@@ -98,7 +118,7 @@
- + @@ -135,7 +155,9 @@ {{ 'ldn-new-service.form.label.addPattern' | translate }} - - - + +
+   +
+ diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index ade0744d4ce..92ac744aed8 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -7,7 +7,7 @@ form { margin-left: 300px; & > * { - width: 100%; + width: 100%; } } @@ -23,10 +23,6 @@ option:not(:first-child) { font-weight: bold; } -select { - width: 90%; -} - .trash-button { width: 40px; height: 40px; @@ -58,7 +54,6 @@ textarea { color: #000000; } - .toggle-switch { display: flex; align-items: center; @@ -98,3 +93,22 @@ textarea { transform: translateX(30px); } +.toggle-switch-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-end; + margin-top: 10px; +} + +.toggle-switch { + cursor: pointer; +} + + + + + + + + diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 67ccaa03200..7a68fc60c88 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -928,12 +928,12 @@ "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", - "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-new-service.form.label.inboundPattern": "Inbound Patterns", "ldn-new-service.form.label.placeholder.inboundPattern": "Select an Inbound Pattern", "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", "ldn-new-service.form.label.ItemFilter": "Item Filter", "ldn-new-service.form.label.automatic": "Automatic", - "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-new-service.form.label.outboundPattern": "Outbound Patterns", "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", "ldn-new-service.form.label.removeItemFilter": "Remove", From 2bf565392a0215d89f6f8a1d1c1ef90b99c0201c Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 6 Oct 2023 14:46:27 +0200 Subject: [PATCH 075/592] CST-10639 Added new fields in the item-view (Endorsed Reviewed and Dataset) --- .../publication/publication.component.html | 12 ++++++++++++ src/assets/i18n/en.json5 | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/src/app/item-page/simple/item-types/publication/publication.component.html b/src/app/item-page/simple/item-types/publication/publication.component.html index 3749f639644..e5aae243772 100644 --- a/src/app/item-page/simple/item-types/publication/publication.component.html +++ b/src/app/item-page/simple/item-types/publication/publication.component.html @@ -84,6 +84,18 @@ [label]="'item.page.uri'"> + + + + + +
{{"item.page.link.full" | translate}} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 2a22e715cc7..2de9e8ef3ec 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2410,6 +2410,12 @@ "item.page.citation": "Citation", + "item.page.endorsed-by": "Endorsed", + + "item.page.is-reviewed-by": "Review", + + "item.page.is-supplemented-by": "Dataset", + "item.page.collections": "Collections", "item.page.collections.loading": "Loading...", From 4dd339235f054329d35744ddb38402d020a2735c Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 6 Oct 2023 15:13:58 +0200 Subject: [PATCH 076/592] CST-10639 Fixed fields in the item-view (Endorsed Reviewed and Dataset) --- .../simple/item-types/publication/publication.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/item-page/simple/item-types/publication/publication.component.html b/src/app/item-page/simple/item-types/publication/publication.component.html index e5aae243772..3014fcb3020 100644 --- a/src/app/item-page/simple/item-types/publication/publication.component.html +++ b/src/app/item-page/simple/item-types/publication/publication.component.html @@ -89,11 +89,11 @@ [label]="'item.page.endorsed-by'">
From 71adb5b7c895173e5f95d7b7351ca82292309a07 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 6 Oct 2023 15:17:57 +0200 Subject: [PATCH 077/592] CST-10639 Fixed field in the item-view (Endorsement) --- src/assets/i18n/en.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 2de9e8ef3ec..564dfe49ea7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2410,7 +2410,7 @@ "item.page.citation": "Citation", - "item.page.endorsed-by": "Endorsed", + "item.page.endorsed-by": "Endorsement", "item.page.is-reviewed-by": "Review", From 8f63b54d713977c62c6ec775935a2c26e498a7eb Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 9 Oct 2023 15:55:24 +0200 Subject: [PATCH 078/592] CST-11045 Located component, working on adding new accordion --- .../models/notify-service-submission.model.ts | 25 +++++++++++++++++++ ...eitem-section-form-notify-service.model.ts | 17 +++++++++++++ .../models/workspaceitem-sections.model.ts | 4 +++ .../form/submission-form.component.html | 11 ++++++-- 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/app/core/submission/models/notify-service-submission.model.ts create mode 100644 src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts diff --git a/src/app/core/submission/models/notify-service-submission.model.ts b/src/app/core/submission/models/notify-service-submission.model.ts new file mode 100644 index 00000000000..f2075103ae6 --- /dev/null +++ b/src/app/core/submission/models/notify-service-submission.model.ts @@ -0,0 +1,25 @@ +/** + * An interface to represent a notifyService object + */ +export class NotifyServiceObject { + + /** + * The notifyService object + */ + id: string; + + /** + * The access condition name + */ + name: string; + + /** + * Possible start date of the access condition + */ + startDate: string; + + /** + * Possible end date of the access condition + */ + endDate: string; +} diff --git a/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts b/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts new file mode 100644 index 00000000000..b614eb91402 --- /dev/null +++ b/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts @@ -0,0 +1,17 @@ +import {NotifyServiceObject} from './notify-service-submission.model' +/** + * An interface to represent the submission's item accesses condition. + */ +export interface WorkspaceitemSectionNotifyServiceRequestItemDissemination extends NotifyServiceObject { + /** + * The access condition id + */ + id: string; + + /** + * Boolean that indicates whether the current item must be findable via search or browse. + */ + discoverable: boolean; + + +} diff --git a/src/app/core/submission/models/workspaceitem-sections.model.ts b/src/app/core/submission/models/workspaceitem-sections.model.ts index a3ccd49dace..f5747c33269 100644 --- a/src/app/core/submission/models/workspaceitem-sections.model.ts +++ b/src/app/core/submission/models/workspaceitem-sections.model.ts @@ -5,6 +5,7 @@ import { WorkspaceitemSectionUploadObject } from './workspaceitem-section-upload import { WorkspaceitemSectionCcLicenseObject } from './workspaceitem-section-cc-license.model'; import {WorkspaceitemSectionIdentifiersObject} from './workspaceitem-section-identifiers.model'; import { WorkspaceitemSectionSherpaPoliciesObject } from './workspaceitem-section-sherpa-policies.model'; +import { WorkspaceitemSectionNotifyServiceRequestItemDissemination } from './workspaceitem-section-form-notify-service.model'; /** * An interface to represent submission's section object. @@ -25,4 +26,7 @@ export type WorkspaceitemSectionDataType | WorkspaceitemSectionAccessesObject | WorkspaceitemSectionSherpaPoliciesObject | WorkspaceitemSectionIdentifiersObject + | WorkspaceitemSectionNotifyServiceRequestItemDissemination | string; + + diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index 4a916cfe238..fa04a6793cf 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,6 +1,7 @@
+

ds-submission-upload-files

@@ -9,7 +10,9 @@
- ds-submission-form-collection

+
+

ds-submission-form-section-add

@@ -28,12 +32,15 @@
+

ds-submission-section-container

+ [sectionData]="object"> +
From 9216073b5bc15e134d669ec57d0ac65b0205b157 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 11 Oct 2023 12:34:48 +0200 Subject: [PATCH 079/592] CST-12174 Coar form pages are now sized correctly, finishing up save button and alias for api call --- .../ldn-service-form-edit.component.html | 213 +++++++++----- .../ldn-service-form-edit.component.scss | 26 +- .../ldn-service-form-edit.component.ts | 52 +++- .../ldn-service-form.component.html | 272 ++++++++++-------- .../ldn-service-form.component.scss | 26 +- .../ldn-service-form.component.ts | 9 +- 6 files changed, 370 insertions(+), 228 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 6402e0b9535..516dce41378 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,11 +1,11 @@ -
+
- +
- -
+ +
@@ -13,9 +13,9 @@
-
@@ -23,6 +23,7 @@  
+
-
+ +
+ + +
 
- -
- - -
+ +
+ + +
 
- -
- - -
+ +
+ + +
 
- -
- - - -
- - - -
- - - -
- - - -
- -
- -
- -
-
-
-
-
- - - -
- -
- -
+ +
+
+ +
+
+ +
+
+ +
+
+
+
-
+
+ + + + +
+
+ +
+ + +
+ + + +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
-
+ {{ 'ldn-new-service.form.label.addPattern' | translate }} - {{ 'ldn-new-service.form.label.addPattern' | translate }}
 
- -
- - - -
- - - -
- -
- - - - - -
- -
- -
+ +
+
+ +
+
+ +
+
+
+
+
+
-
+
+ + + + +
+
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+
+
-
+
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }}
 
+ + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 92ac744aed8..eb6c97c90a7 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -1,14 +1,9 @@ form { - display: flex; - flex-direction: column; - align-items: flex-start; max-width: 800px; font-size: 14px; - margin-left: 300px; + margin-left: 100px; + position: relative; - & > * { - width: 100%; - } } input[type="text"], @@ -105,6 +100,23 @@ textarea { cursor: pointer; } +.label-box{ + margin-left:11px; +} + +.label-box-2{ + margin-left:14px; +} + +.label-box-3{ + margin-left:5px; +} + +form button.btn.btn-primary[type="submit"] { + position: absolute; + bottom: 0px; + right: -10px; +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 608a7ada23b..b5a1ce8cf29 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -130,19 +130,20 @@ export class LdnServiceFormComponent implements OnInit { notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } - removeInboundPattern(patternGroup: FormGroup) { + removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + notifyServiceInboundPatternsArray.removeAt(index); } + addOutboundPattern() { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } - removeOutboundPattern(patternGroup: FormGroup) { + removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + notifyServiceOutboundPatternsArray.removeAt(index); } private createOutboundPatternFormGroup(): FormGroup { From 8de0e76b72e39f3ce5a34eaadaadfc72e7fbf0ba Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 11 Oct 2023 15:35:28 +0200 Subject: [PATCH 080/592] CST-12174 Ldn services are now retrieved with the remotadata object --- .../ldn-services-data.service.ts | 52 +++++--- .../ldn-services-directory.component.html | 2 +- .../ldn-services-directory.component.ts | 25 +++- .../ldn-service.resource-type.ts | 2 +- .../ldn-services-model/ldn-services.model.ts | 3 + .../ldn-service-bulk-delete.service.ts | 117 ------------------ src/app/core/core.module.ts | 5 +- 7 files changed, 66 insertions(+), 140 deletions(-) delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index 43755adb3c0..09670cc0649 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -24,25 +24,45 @@ import { hasValue } from '../../../shared/empty.util'; import { LdnService } from '../ldn-services-model/ldn-services.model'; import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; + import { PatchData, PatchDataImpl } from '../../../core/data/base/patch-data'; + import { ChangeAnalyzer } from '../../../core/data/change-analyzer'; +import { Operation } from 'fast-json-patch'; +import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; -@Injectable() -@dataService(LDN_SERVICE) -export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData { - private findAllData: FindAllDataImpl; // Corrected the type - private deleteData: DeleteDataImpl; // Corrected the type + @Injectable() + @dataService(LDN_SERVICE) + export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData { + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService, - protected notificationsService: NotificationsService, - ) { - super('ldnservices', requestService, rdbService, objectCache, halService); + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); - this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); - this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); - } + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, 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, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + } + + patch(object: LdnService, operations: Operation[]): Observable> { + throw new Error('Method not implemented.'); + } + update(object: LdnService): Observable> { + throw new Error('Method not implemented.'); + } + commitUpdates(method?: RestRequestMethod): void { + throw new Error('Method not implemented.'); + } + createPatchFromCache(object: LdnService): Observable { + throw new Error('Method not implemented.'); + } findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index e3795d6e96e..4c9b3c3f04a 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -23,7 +23,7 @@

{{ 'ldn-registered-services.title' | translate }}

{{ ldnService.name }} {{ ldnService.description }} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 9d19ad56c75..345f5182aa1 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -12,6 +12,7 @@ import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { HttpClient } from '@angular/common/http'; +import { getFirstCompletedRemoteData } from "../../../core/shared/operators"; @Component({ selector: 'ds-ldn-services-directory', templateUrl: './ldn-services-directory.component.html', @@ -33,8 +34,12 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { isProcessingSub: Subscription; private modalRef: any; + + + constructor( protected processLdnService: LdnServicesService, + private ldnServicesService: LdnServicesService, protected paginationService: PaginationService, protected modalService: NgbModal, public ldnDirectoryService: LdnDirectoryService, @@ -44,9 +49,9 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } ngOnInit(): void { - /*this.ldnDirectoryService.listLdnServices();*/ - this.findAllServices(); + this.setLdnServices2(); this.setLdnServices(); + /*this.ldnDirectoryService.listLdnServices();*/ /*this.ldnServicesRD$.subscribe(data => { console.log('searchByLdnUrl()', data); });*/ @@ -62,10 +67,22 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } setLdnServices() { + this.ldnServicesService.findAll().pipe(getFirstCompletedRemoteData()).subscribe((remoteData) => { + + if (remoteData.hasSucceeded) { + const ldnservices = remoteData.payload.page; + console.log(ldnservices); + } else { + console.error('Error fetching LDN services:', remoteData.errorMessage); + } + }); + } + + setLdnServices2() { this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.processLdnService.findAll(config, true, false)) + switchMap((config) => this.ldnServicesService.findAll(config, true, false)) + ); - console.log(); } ngOnDestroy(): void { diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts index 937fac255d6..e5684e8c342 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -6,4 +6,4 @@ */ import { ResourceType } from '../../../core/shared/resource-type'; -export const LDN_SERVICE = new ResourceType('ldnservices'); +export const LDN_SERVICE = new ResourceType('ldnservice'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts index bdb8bc51232..ec28193a938 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -26,6 +26,9 @@ export class LdnService extends CacheableObject { @autoserialize url: string; + @autoserialize + enabled: boolean; + @autoserialize ldnUrl: string; diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts deleted file mode 100644 index 6805cd7f932..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject, count, from } from 'rxjs'; -import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { TranslateService } from '@ngx-translate/core'; -import { isNotEmpty } from '../../../shared/empty.util'; -import { concatMap, filter, tap } from 'rxjs/operators'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; -import { RemoteData } from '../../../core/data/remote-data'; -import { LdnService } from '../ldn-services-model/ldn-services.model'; -@Injectable({ - providedIn: 'root' -}) -/** - * Service to facilitate removing ldn services in bulk. - */ -export class LdnServicesBulkDeleteService { - - /** - * Array to track the services to be deleted - */ - ldnServicesToDelete: string[] = []; - - /** - * Behavior subject to track whether the delete is processing - * @protected - */ - protected isProcessingBehaviorSubject: BehaviorSubject = new BehaviorSubject(false); - - constructor( - protected processLdnService: LdnServicesService, - protected notificationsService: NotificationsService, - protected translateService: TranslateService - ) { - } - - /** - * Add or remove a process id to/from the list - * If the id is already present it will be removed, otherwise it will be added. - * - * @param notifyServiceName - The process id to add or remove - */ - toggleDelete(notifyServiceName: string) { - if (this.isToBeDeleted(notifyServiceName)) { - this.ldnServicesToDelete.splice(this.ldnServicesToDelete.indexOf(notifyServiceName), 1); - } else { - this.ldnServicesToDelete.push(notifyServiceName); - } - } - - /** - * Checks if the provided service id is present in the to be deleted list - * @param notifyServiceName - */ - isToBeDeleted(notifyServiceName: string) { - return this.ldnServicesToDelete.includes(notifyServiceName); - } - - /** - * Clear the list of services to be deleted - */ - clearAllServices() { - this.ldnServicesToDelete.splice(0); - } - - /** - * Get the amount of processes selected for deletion - */ - getAmountOfSelectedServices() { - return this.ldnServicesToDelete.length; - } - - /** - * Returns a behavior subject to indicate whether the bulk delete is processing - */ - isProcessing$() { - return this.isProcessingBehaviorSubject; - } - - /** - * Returns whether there currently are values selected for deletion - */ - hasSelected(): boolean { - return isNotEmpty(this.ldnServicesToDelete); - } - - /** - * Delete all selected processes one by one - * When the deletion for a process fails, an error notification will be shown with the process id, - * but it will continue deleting the other processes. - * At the end it will show a notification stating the amount of successful deletes - * The successfully deleted processes will be removed from the list of selected values, the failed ones will be retained. - */ - deleteSelectedLdnServices() { - this.isProcessingBehaviorSubject.next(true); - - from([...this.ldnServicesToDelete]).pipe( - concatMap((notifyServiceName) => { - return this.processLdnService.delete(notifyServiceName).pipe( - getFirstCompletedRemoteData(), - tap((rd: RemoteData) => { - if (rd.hasFailed) { - this.notificationsService.error(this.translateService.get('process.bulk.delete.error.head'), this.translateService.get('process.bulk.delete.error.body', {processId: notifyServiceName})); - } else { - this.toggleDelete(notifyServiceName); - } - }) - ); - }), - filter((rd: RemoteData) => rd.hasSucceeded), - count(), - ).subscribe((value) => { - this.notificationsService.success(this.translateService.get('process.bulk.delete.success', {count: value})); - this.isProcessingBehaviorSubject.next(false); - }); - } -} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index e1b1fc88110..1990bde77e1 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -188,6 +188,7 @@ import { BulkAccessConditionOptions } from './config/models/bulk-access-conditio import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model'; import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { LdnService } from '../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -392,7 +393,9 @@ export const models = ItemRequest, BulkAccessConditionOptions, SuggestionTarget, - SuggestionSource + SuggestionSource, + LdnService + ]; @NgModule({ From 1c376b296413434a23d256268346741b071b082c Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 17 Oct 2023 16:28:36 +0200 Subject: [PATCH 081/592] CST-12174 Implemented data-service for the api calls --- .../admin-ldn-services.module.ts | 2 + .../ldn-service-form-edit.component.html | 6 +- .../ldn-service-form-edit.component.ts | 653 +++++++++--------- .../ldn-service-form.component.html | 2 +- .../ldn-service-form.component.ts | 341 ++++----- .../ldn-services-data.service.ts | 110 +-- .../ldn-services-directory.component.html | 6 +- .../ldn-services-directory.component.ts | 267 +++---- .../ldn-services-guard.service.ts | 2 +- .../ldn-service-constraint.model.ts | 26 - .../ldn-service-patterns.model.ts | 13 + .../ldn-service.constrain.model.ts | 3 + .../ldn-service.resource-type.ts | 1 + .../ldn-services-model/ldn-services.model.ts | 21 +- src/app/admin/admin-routing-paths.ts | 8 +- 15 files changed, 719 insertions(+), 742 deletions(-) delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index 1fd67d53b9a..c3642ea88d9 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -6,6 +6,7 @@ import { SharedModule } from '../../shared/shared.module'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; +import { FormsModule } from '@angular/forms'; @@ -14,6 +15,7 @@ import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service CommonModule, SharedModule, AdminLdnServicesRoutingModule, + FormsModule ], declarations: [ LdnServicesOverviewComponent, diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 516dce41378..988e0a53a15 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -112,7 +112,7 @@
-
@@ -176,7 +176,7 @@
-
@@ -215,7 +215,7 @@

{{'service.overview.create.modal' | translate }}

{{ 'service.overview.delete.body' | translate }}
-
{{ ldnService.name }} {{ ldnService.description }} {{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} @@ -70,7 +70,7 @@

{{'service.overview.delete.header' | translate }}

-
diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 345f5182aa1..933dff89015 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,5 +1,4 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -11,170 +10,122 @@ import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-service import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; -import { HttpClient } from '@angular/common/http'; -import { getFirstCompletedRemoteData } from "../../../core/shared/operators"; +import { Operation } from 'fast-json-patch'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { Router } from '@angular/router'; + @Component({ - selector: 'ds-ldn-services-directory', - templateUrl: './ldn-services-directory.component.html', - styleUrls: ['./ldn-services-directory.component.scss'], + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], + changeDetection: ChangeDetectionStrategy.Default }) export class LdnServicesOverviewComponent implements OnInit, OnDestroy { - selectedServiceId: number | null = null; - servicesData: any[] = []; - @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; - ldnServicesRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 + selectedServiceId: string | number | null = null; + servicesData: any[] = []; + @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + isProcessingSub: Subscription; + private modalRef: any; + + constructor( + protected ldnServicesService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + private cdRef: ChangeDetectorRef, + private notificationService: NotificationsService, + private translateService: TranslateService, + private router: Router, + ) { + } + + ngOnInit(): void { + this.setLdnServices(); + } + + setLdnServices() { + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, true, false).pipe( + getFirstCompletedRemoteData() + )) + ); + + this.ldnServicesRD$.subscribe((rd: RemoteData>) => { + console.log(rd); + if (rd.hasSucceeded) { + this.notificationService.success(this.translateService.get('notification.loaded.success')); + } else { + this.notificationService.error(this.translateService.get('notification.loaded.failure')); + } }); - isProcessingSub: Subscription; - private modalRef: any; - - - - - constructor( - protected processLdnService: LdnServicesService, - private ldnServicesService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - public ldnDirectoryService: LdnDirectoryService, - private http: HttpClient, - private cdRef: ChangeDetectorRef - ) { - } - - ngOnInit(): void { - this.setLdnServices2(); - this.setLdnServices(); - /*this.ldnDirectoryService.listLdnServices();*/ - /*this.ldnServicesRD$.subscribe(data => { - console.log('searchByLdnUrl()', data); - });*/ - - /*this.ldnServicesRD$.pipe( - tap(data => { - console.log('ldnServicesRD$ data:', data); - }) - ).subscribe(() => { - this.searchByLdnUrl(); - });*/ - - } - - setLdnServices() { - this.ldnServicesService.findAll().pipe(getFirstCompletedRemoteData()).subscribe((remoteData) => { - - if (remoteData.hasSucceeded) { - const ldnservices = remoteData.payload.page; - console.log(ldnservices); - } else { - console.error('Error fetching LDN services:', remoteData.errorMessage); - } - }); - } - - setLdnServices2() { - this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.ldnServicesService.findAll(config, true, false)) + } - ); + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); } - - ngOnDestroy(): void { - this.paginationService.clearPagination(this.pageConfig.id); - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); + } + + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } + + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } + + selectServiceToDelete(serviceId: number) { + this.selectedServiceId = serviceId; + this.openDeleteModal(this.deleteModal); + } + + deleteSelected(serviceId: string, ldnServicesService: LdnServicesService): void { + if (this.selectedServiceId !== null) { + ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + this.servicesData = this.servicesData.filter(service => service.id !== serviceId); + this.cdRef.detectChanges(); + this.closeModal(); + this.notificationService.success(this.translateService.get('notification.created.success')); + } else { + this.notificationService.error(this.translateService.get('notification.created.failure')); + this.cdRef.detectChanges(); } + }); } - - openDeleteModal(content) { - this.modalRef = this.modalService.open(content); - } - - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); - } - - - findAllServices(): void { - this.retrieveAll().subscribe( - (response) => { - this.servicesData = response._embedded.ldnservices; - console.log('ServicesData =', this.servicesData); - this.cdRef.detectChanges(); - }, - (error) => { - console.error('Error:', error); - } - ); - } - - retrieveAll(): Observable { - const url = 'http://localhost:8080/server/api/ldn/ldnservices'; - return this.http.get(url); - } - - - - - deleteSelected() { - if (this.selectedServiceId !== null) { - const deleteUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.selectedServiceId}`; - this.http.delete(deleteUrl).subscribe( - () => { - this.closeModal(); - this.findAllServices(); - }, - (error) => { - console.error('Error deleting service:', error); - } - ); + } + + + toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { + const newStatus = !ldnService.enabled; + let status = ldnService.enabled; + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + ldnServicesService.patch(ldnService, [patchOperation]).pipe(getFirstCompletedRemoteData()).subscribe( + () => { + if (status !== newStatus) { + this.notificationService.success(this.translateService.get('ldn-enable-service.notification.success.title'), + this.translateService.get('ldn-enable-service.notification.success.content')); + } else { + this.notificationService.error(this.translateService.get('ldn-enable-service.notification.error.title'), + this.translateService.get('ldn-enable-service.notification.error.content')); + } } - } - - selectServiceToDelete(serviceId: number) { - this.selectedServiceId = serviceId; - this.openDeleteModal(this.deleteModal); - } - - toggleStatus(ldnService: any): void { - const newStatus = !ldnService.enabled; - - const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`; - const patchOperation = { - op: 'replace', - path: '/enabled', - value: newStatus, - }; - - this.http.patch(apiUrl, [patchOperation]).subscribe( - () => { - console.log('Status updated successfully.'); - ldnService.enabled = newStatus; - this.cdRef.detectChanges(); - }, - (error) => { - console.error('Error updating status:', error); - } - ); - } - - fetchServiceData(serviceId: string): void { - const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; - - this.http.get(apiUrl).subscribe( - (data: any) => { - console.log(data); - }, - (error) => { - console.error('Error fetching service data:', error); - } - ); - } + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts index 85235b4370f..21123ede4af 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; + @Injectable({ providedIn: 'root' diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts deleted file mode 100644 index 704a3e7d8c4..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * A cosntrain that can be used when running a service - */ -export class LdnServiceConstraint { - /** - * The name of the constrain - */ - name: string; - - /** - * The value of the constrain - */ - value: string; -} - -export const EndorsmentConstrain = [ - { - name: 'Type 1 Item', - value: 'Type1' - }, - { - name: 'Type 2 Item', - value: 'Type2' - }, -]; diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts new file mode 100644 index 00000000000..1e67ccfeeeb --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts @@ -0,0 +1,13 @@ +import { autoserialize } from 'cerialize'; + +/** + * notify service patterns + */ +export class NotifyServicePattern { + @autoserialize + pattern: string; + @autoserialize + constraint: string; + @autoserialize + automatic: string; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts new file mode 100644 index 00000000000..6eda1944433 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts @@ -0,0 +1,3 @@ +export class ldnServiceConstrain { + void: any; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts index e5684e8c342..859ecb739ec 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -7,3 +7,4 @@ import { ResourceType } from '../../../core/shared/resource-type'; export const LDN_SERVICE = new ResourceType('ldnservice'); +export const LDN_SERVICE_CONSTRAINT = new ResourceType('ldnservice'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts index ec28193a938..82731b3cb1a 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -1,12 +1,16 @@ import { ResourceType } from '../../../core/shared/resource-type'; import { CacheableObject } from '../../../core/cache/cacheable-object.model'; -import { autoserialize, deserialize } from 'cerialize'; +import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize'; import { LDN_SERVICE } from './ldn-service.resource-type'; import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { NotifyServicePattern } from './ldn-service-patterns.model'; + + @typedObject +@inheritSerialization(CacheableObject) export class LdnService extends CacheableObject { static type = LDN_SERVICE; @@ -15,7 +19,10 @@ export class LdnService extends CacheableObject { type: ResourceType; @autoserialize - id?: number; + id: number; + + @deserializeAs('id') + uuid: string; @autoserialize name: string; @@ -49,13 +56,3 @@ export class LdnService extends CacheableObject { return this._links.self.href; } } - - -class NotifyServicePattern { - @autoserialize - pattern: string; - @autoserialize - constraint?: string; - @autoserialize - automatic?: boolean; -} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index df0459ff534..511680bfd80 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -4,6 +4,8 @@ import { getAdminModuleRoute } from '../app-routing-paths'; export const REGISTRIES_MODULE_PATH = 'registries'; export const NOTIFICATIONS_MODULE_PATH = 'notifications'; +export const LDN_PATH = 'ldn'; + export function getRegistriesModuleRoute() { return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString(); } @@ -12,4 +14,8 @@ export function getNotificationsModuleRoute() { return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); } -export const LDN_PATH = 'ldn'; +export function getLdnServicesModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), LDN_PATH).toString(); +} + + From ba0b110647e23a736341c1d3609c9ed9c0340e19 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 17 Oct 2023 17:46:47 +0200 Subject: [PATCH 082/592] CST-12174 added resetForm and leave edit for edit-form and overview page --- .../ldn-service-form-edit.component.html | 34 +++++++++++++++++++ .../ldn-service-form-edit.component.ts | 10 ++++++ 2 files changed, 44 insertions(+) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 988e0a53a15..9f5515960ba 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -194,6 +194,11 @@ +
+ +
@@ -224,3 +229,32 @@

{{'service.overview.create.modal' | translate }}

+ + + +
+ + + + +
+
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index bd184ea174f..4a5187a5d7e 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -29,6 +29,7 @@ import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; export class LdnServiceFormEditComponent implements OnInit { formModel: FormGroup; @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; + @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; @@ -286,6 +287,10 @@ export class LdnServiceFormEditComponent implements OnInit { this.modalRef = this.modalService.open(content); } + openResetFormModal(content) { + this.modalRef = this.modalService.open(content); + } + patchService() { const patchOperations = this.generatePatchOperations(); @@ -347,6 +352,11 @@ export class LdnServiceFormEditComponent implements OnInit { this.router.navigateByUrl('admin/ldn/services'); } + resetFormAndLeave() { + this.sendBack(); + this.closeModal(); + } + private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', From 6d794cd51f7de4d8032c747f1320445275a85ff2 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 18 Oct 2023 09:29:52 +0200 Subject: [PATCH 083/592] [CST-12235] LDN inbox mechanism for home (partial commit) --- .../notify-info/notify-info.service.ts | 19 ++++++++- src/app/home-page/home-page.component.ts | 39 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts index a88181a9abd..b489677634f 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -1,14 +1,17 @@ import { Injectable } from '@angular/core'; -import { getFirstSucceededRemoteData } from '../../shared/operators'; +import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../shared/operators'; import { ConfigurationDataService } from '../../data/configuration-data.service'; import { map, Observable } from 'rxjs'; import { DefaultAppConfig } from '../../../../config/default-app-config'; +import { ConfigurationProperty } from '../../shared/configuration-property.model'; @Injectable({ providedIn: 'root' }) export class NotifyInfoService { + private relationLink = 'http://www.w3.org/ns/ldp#inbox'; + constructor( private configService: ConfigurationDataService, ) {} @@ -24,6 +27,16 @@ export class NotifyInfoService { ); } + getCoarLdnLocalInboxUrl(): Observable { + return this.configService.findByPropertyName('ldn.notify.local-inbox-endpoint').pipe( + getFirstSucceededRemoteData(), + getRemoteDataPayload(), + map((response: ConfigurationProperty) => { + return response.values; + }) + ); + } + getCoarLdnRestApiUrl(): string { const appConfig = new DefaultAppConfig(); const restConfig = appConfig.rest; @@ -35,4 +48,8 @@ export class NotifyInfoService { return `${ssl ? 'https' : 'http'}://${host}:${port}${namespace}`; } + + getRelationLink(): string{ + return this.relationLink; + } } diff --git a/src/app/home-page/home-page.component.ts b/src/app/home-page/home-page.component.ts index c151cbbb164..1e0833c0d1b 100644 --- a/src/app/home-page/home-page.component.ts +++ b/src/app/home-page/home-page.component.ts @@ -1,9 +1,14 @@ -import { Component, OnInit } from '@angular/core'; -import { map } from 'rxjs/operators'; +import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core'; +import { map, switchMap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { Site } from '../core/shared/site.model'; import { environment } from '../../environments/environment'; +import { isPlatformServer } from '@angular/common'; +import { ServerResponseService } from '../core/services/server-response.service'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; +import { LinkDefinition, LinkHeadService } from '../core/services/link-head.service'; + @Component({ selector: 'ds-home-page', styleUrls: ['./home-page.component.scss'], @@ -13,10 +18,24 @@ export class HomePageComponent implements OnInit { site$: Observable; recentSubmissionspageSize: number; + constructor( private route: ActivatedRoute, + private responseService: ServerResponseService, + private notifyInfoService: NotifyInfoService, + protected linkHeadService: LinkHeadService, + @Inject(PLATFORM_ID) private platformId: string ) { this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize; + this.notifyInfoService.isCoarConfigEnabled().pipe( + switchMap((coarLdnEnabled: boolean) => { + if (coarLdnEnabled) { + return this.notifyInfoService.getCoarLdnLocalInboxUrl(); + } + }) + ).subscribe((coarRestApiUrls: string[]) => { + this.initPageLinks(coarRestApiUrls); + }); } ngOnInit(): void { @@ -24,4 +43,18 @@ export class HomePageComponent implements OnInit { map((data) => data.site as Site), ); } + + private initPageLinks(coarRestApiUrls: string[]): void { + const rel = this.notifyInfoService.getRelationLink(); + coarRestApiUrls.forEach((coarRestApiUrl: string) => { + let tag: LinkDefinition = { + href: coarRestApiUrl, + rel: rel + }; + this.linkHeadService.addTag(tag); + if (isPlatformServer(this.platformId)) { + this.responseService.setHeader('Link', `<${coarRestApiUrl}>; rel="${rel}"`); + } + }); + } } From 2eb71604eeab4906de39da3d4b744b03bd04e28e Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 18 Oct 2023 18:46:06 +0200 Subject: [PATCH 084/592] CST-12174 created new remotadata service for itemfilters, pages are updated in real time when editing/creating/deleting services related stuff, added modals to confirm/reset --- .../admin-ldn-services.module.ts | 4 +- .../ldn-service-form-edit.component.html | 21 +++-- .../ldn-service-form-edit.component.ts | 53 ++++++++--- .../ldn-service-form.component.html | 76 ++++++++++++++-- .../ldn-service-form.component.ts | 91 ++++++++++++++----- .../ldn-itemfilters-data.service.ts | 48 ++++++++++ .../ldn-services-data.service.ts | 3 + .../ldn-services-directory.component.ts | 15 ++- .../ldn-service-itemfilters.ts | 32 +++++++ .../ldn-service.resource-type.ts | 4 +- .../ldn-services-model/ldn-services.model.ts | 2 +- .../ldn-directory.service.ts | 47 ++-------- src/app/core/core.module.ts | 6 +- 13 files changed, 304 insertions(+), 98 deletions(-) create mode 100644 src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index c3642ea88d9..c82250fcec7 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -7,6 +7,7 @@ import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.compon import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; import { FormsModule } from '@angular/forms'; +import { LdnItemfiltersService } from './ldn-services-data/ldn-itemfilters-data.service'; @@ -22,6 +23,7 @@ import { FormsModule } from '@angular/forms'; LdnServiceNewComponent, LdnServiceFormComponent, LdnServiceFormEditComponent, - ] + ], + providers: [LdnItemfiltersService] }) export class AdminLdnServicesModule { } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 9f5515960ba..5d33d21505e 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,4 +1,4 @@ -
+
@@ -95,8 +95,8 @@
@@ -159,12 +159,13 @@
- + + +
@@ -249,7 +250,7 @@

{{'service.overview.reset-form.modal' | translate }}

{{ 'service.overview.reset-form.body' | translate }}
-
@@ -149,12 +149,13 @@
- - + +
@@ -182,6 +183,69 @@  
+
+ +
+ + +
+ + + + +
+
+ + + +
+ + + + +
+
+ diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index bfee1467d7d..25b7ab70d53 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -1,4 +1,13 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnInit, + Output, + TemplateRef, + ViewChild +} from '@angular/core'; import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; @@ -12,6 +21,13 @@ import { RemoteData } from '../../../core/data/remote-data'; import { LdnService } from '../ldn-services-model/ldn-services.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { Itemfilter } from '../ldn-services-model/ldn-service-itemfilters'; +import { Observable } from 'rxjs'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { LdnItemfiltersService } from '../ldn-services-data/ldn-itemfilters-data.service'; +import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; @Component({ @@ -28,11 +44,21 @@ import { TranslateService } from '@ngx-translate/core'; }) export class LdnServiceFormComponent implements OnInit { formModel: FormGroup; + private modalRef: any; + @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; + @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; - public itemFilterList: any[]; + itemfiltersRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); @@ -51,11 +77,14 @@ export class LdnServiceFormComponent implements OnInit { constructor( private ldnServicesService: LdnServicesService, - private ldnDirectoryService: LdnDirectoryService, + private ldnItemfiltersService: LdnItemfiltersService, private formBuilder: FormBuilder, private router: Router, private notificationsService: NotificationsService, - private translateService: TranslateService + private translateService: TranslateService, + private cdRef: ChangeDetectorRef, + protected modalService: NgbModal, + ) { this.formModel = this.formBuilder.group({ @@ -75,15 +104,19 @@ export class LdnServiceFormComponent implements OnInit { } ngOnInit(): void { - this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { - console.log(itemFilters); - this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ - name: filter.id - })); - }); + this.setItemfilters(); } - + setItemfilters() { + this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( + getFirstCompletedRemoteData()); + console.log(this.itemfiltersRD$); + this.itemfiltersRD$.subscribe((rd: RemoteData>) => { + if (rd.hasSucceeded) { + console.log(rd); + } + }); + } /*createLdnService(values: any) { this.formModel.get('name').markAsTouched(); this.formModel.get('url').markAsTouched(); @@ -106,7 +139,7 @@ export class LdnServiceFormComponent implements OnInit { ).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { this.notificationsService.success(this.translateService.get('notification.created.success')); - this.submitForm.emit(values); + this.onSubmit.emit(values); } else { this.notificationsService.error(this.translateService.get('notification.created.failure', )); this.cancelForm.emit(); @@ -116,6 +149,17 @@ export class LdnServiceFormComponent implements OnInit { }*/ onSubmit() { + this.openConfirmModal(this.confirmModal); + } + + openConfirmModal(content) { + this.modalRef = this.modalService.open(content); + } + + openResetFormModal(content) { + this.modalRef = this.modalService.open(content); + } + createService(){ this.formModel.get('name').markAsTouched(); this.formModel.get('url').markAsTouched(); this.formModel.get('ldnUrl').markAsTouched(); @@ -125,6 +169,7 @@ export class LdnServiceFormComponent implements OnInit { const ldnUrl = this.formModel.get('ldnUrl').value; if (!name || !url || !ldnUrl) { + this.closeModal(); return; } @@ -133,26 +178,28 @@ export class LdnServiceFormComponent implements OnInit { const ldnServiceData = this.ldnServicesService.create(values); ldnServiceData.pipe( - getFirstCompletedRemoteData() - ).subscribe((ldnNewService) => { - console.log(ldnNewService); - }); - - ldnServiceData.pipe( - getFirstCompletedRemoteData() + getFirstCompletedRemoteData() ).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { this.notificationsService.success(this.translateService.get('notification.created.success')); - this.submitForm.emit(); this.sendBack(); } else { this.notificationsService.error(this.translateService.get('notification.created.failure')); - this.cancelForm.emit(); } }); } + resetFormAndLeave() { + this.sendBack(); + this.closeModal(); + } + + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } + addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); @@ -184,6 +231,8 @@ export class LdnServiceFormComponent implements OnInit { this.router.navigateByUrl('admin/ldn/services'); } + + private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: [''], diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts new file mode 100644 index 00000000000..692e1a5db9e --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts @@ -0,0 +1,48 @@ +import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { LDN_SERVICE_CONSTRAINT_FILTERS } from '../ldn-services-model/ldn-service.resource-type'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; + +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { Itemfilter } from '../ldn-services-model/ldn-service-itemfilters'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; + + + +/** + * A service responsible for fetching/sending data from/to the REST API on the itemfilters endpoint + */ +@Injectable() +@dataService(LDN_SERVICE_CONSTRAINT_FILTERS) +export class LdnItemfiltersService extends IdentifiableDataService implements FindAllData { + private findAllData: FindAllDataImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('itemfilters', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + } + + getEndpoint() { + return this.halService.getEndpoint(this.linkPath); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index 83098f7f7c6..d2ef16fadae 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -32,6 +32,9 @@ import { ldnServiceConstrain } from '../ldn-services-model/ldn-service.constrain import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; import { hasValue } from 'src/app/shared/empty.util'; +/** + * A service responsible for fetching/sending data from/to the REST API on the ldnservices endpoint + */ @Injectable() @dataService(LDN_SERVICE) export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 933dff89015..9bc06027875 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -5,13 +5,13 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { LdnService } from '../ldn-services-model/ldn-services.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { switchMap } from 'rxjs/operators'; +import { map, switchMap } from 'rxjs/operators'; import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { Operation } from 'fast-json-patch'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { Router } from '@angular/router'; @@ -55,8 +55,9 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { setLdnServices() { this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.ldnServicesService.findAll(config, true, false).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( getFirstCompletedRemoteData() + )) ); @@ -96,6 +97,14 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { this.servicesData = this.servicesData.filter(service => service.id !== serviceId); + this.ldnServicesRD$ = this.ldnServicesRD$.pipe( + map((remoteData: RemoteData>) => { + if (remoteData.hasSucceeded) { + remoteData.payload.page = remoteData.payload.page.filter(service => service.id.toString() !== serviceId); + } + return remoteData; + }) + ); this.cdRef.detectChanges(); this.closeModal(); this.notificationService.success(this.translateService.get('notification.created.success')); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts new file mode 100644 index 00000000000..865fa0b3ea1 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts @@ -0,0 +1,32 @@ +import { autoserialize, inheritSerialization, deserialize } from 'cerialize'; +import { LDN_SERVICE_CONSTRAINT_FILTER } from './ldn-service.resource-type'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { ResourceType } from '../../../core/shared/resource-type'; + +/** A single filter value and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class Itemfilter extends CacheableObject { + static type = LDN_SERVICE_CONSTRAINT_FILTER; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: string; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts index 859ecb739ec..05a881e7e74 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -7,4 +7,6 @@ import { ResourceType } from '../../../core/shared/resource-type'; export const LDN_SERVICE = new ResourceType('ldnservice'); -export const LDN_SERVICE_CONSTRAINT = new ResourceType('ldnservice'); +export const LDN_SERVICE_CONSTRAINT_FILTERS = new ResourceType('itemfilters'); + +export const LDN_SERVICE_CONSTRAINT_FILTER = new ResourceType('itemfilter'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts index 82731b3cb1a..e0725b58517 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -8,7 +8,7 @@ import { NotifyServicePattern } from './ldn-service-patterns.model'; - +/** An LdnService and its properties. */ @typedObject @inheritSerialization(CacheableObject) export class LdnService extends CacheableObject { diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts index 5ed32f5bb77..3499759f03b 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -1,57 +1,26 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable, tap } from 'rxjs'; -import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { map, Observable } from 'rxjs'; +import { LdnServicesService } from "../ldn-services-data/ldn-services-data.service"; @Injectable({ providedIn: 'root', }) export class LdnDirectoryService { - private baseUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; - constructor(private http: HttpClient) {} - + constructor(private http: HttpClient, + private ldnServicesService: LdnServicesService) {} + public getItemFilters(): Observable { - public listLdnServices(): Observable { - const endpoint = `${this.baseUrl}`; - return this.http.get(endpoint).pipe( - tap(data => { - console.log('listLdnServices() Data:', data); + return this.ldnServicesService.findAll().pipe( + map((servicesData) => { + return servicesData; }) ); } - public getLdnServiceById(id: string): Observable { - const endpoint = `${this.baseUrl}/${id}`; - return this.http.get(endpoint); - } - - public createLdnService(ldnService: LdnService): Observable { - return this.http.post(this.baseUrl, ldnService); - } - - public updateLdnService(id: string, ldnService: LdnService): Observable { - const endpoint = `${this.baseUrl}/${id}`; - return this.http.put(endpoint, ldnService); - } - - public deleteLdnService(id: string): Observable { - const endpoint = `${this.baseUrl}/${id}`; - return this.http.delete(endpoint); - } - - public searchLdnServicesByLdnUrl(ldnUrl: string): Observable { - const endpoint = `${this.baseUrl}/search/byLdnUrl?ldnUrl=${ldnUrl}`; - return this.http.get(endpoint); - } - - public getItemFilters(): Observable { - const itemFiltersEndpoint = `${this.itemFilterEndpoint}`; - return this.http.get(itemFiltersEndpoint); - } - } diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 1990bde77e1..88da00f02c8 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -189,6 +189,8 @@ import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model'; import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { LdnService } from '../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { LdnItemfiltersService } from '../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service'; +import { Itemfilter } from "../admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters"; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -313,6 +315,7 @@ const PROVIDERS = [ OrcidHistoryDataService, SupervisionOrderDataService, LdnServicesService, + LdnItemfiltersService ]; /** @@ -394,7 +397,8 @@ export const models = BulkAccessConditionOptions, SuggestionTarget, SuggestionSource, - LdnService + LdnService, + Itemfilter ]; From a55eb97a6ac5bd4ee4a32d07b09369d5d2fa286a Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Fri, 20 Oct 2023 16:04:40 +0200 Subject: [PATCH 085/592] [CST-12043] fix: normalization for boolean --- src/app/shared/form/builder/form-builder.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/form/builder/form-builder.service.ts b/src/app/shared/form/builder/form-builder.service.ts index cf6f38bf7b8..8bd449a07d1 100644 --- a/src/app/shared/form/builder/form-builder.service.ts +++ b/src/app/shared/form/builder/form-builder.service.ts @@ -196,6 +196,7 @@ export class FormBuilderService extends DynamicFormService { return new FormFieldMetadataValueObject((controlValue as any).value, controlLanguage, authority, (controlValue as any).display, place, (controlValue as any).confidence); } } + return controlValue; }; const iterateControlModels = (findGroupModel: DynamicFormControlModel[], controlModelIndex: number = 0): void => { From ffdeca69f45ff4b0ce811f237a314fc672816777 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Fri, 20 Oct 2023 16:07:31 +0200 Subject: [PATCH 086/592] [CST-12043] feature: add primary bitstream switch --- .../workspaceitem-section-upload.model.ts | 5 +- .../custom-switch.component.html | 2 +- .../objects/submission-objects.actions.ts | 25 +++++ .../objects/submission-objects.reducer.ts | 47 ++++++++- .../section-upload-file-edit.component.html | 6 +- .../section-upload-file-edit.component.ts | 69 +++++++------ .../edit/section-upload-file-edit.model.ts | 13 +++ .../file/section-upload-file.component.html | 9 +- .../file/section-upload-file.component.ts | 97 ++++++++++++++++++- .../themed-section-upload-file.component.ts | 8 ++ .../upload/section-upload.component.html | 28 +++--- .../upload/section-upload.component.ts | 35 +++---- .../sections/upload/section-upload.service.ts | 36 ++++++- 13 files changed, 303 insertions(+), 77 deletions(-) diff --git a/src/app/core/submission/models/workspaceitem-section-upload.model.ts b/src/app/core/submission/models/workspaceitem-section-upload.model.ts index f98e0584ebc..d992567df4c 100644 --- a/src/app/core/submission/models/workspaceitem-section-upload.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-upload.model.ts @@ -4,7 +4,10 @@ import { WorkspaceitemSectionUploadFileObject } from './workspaceitem-section-up * An interface to represent submission's upload section data. */ export interface WorkspaceitemSectionUploadObject { - + /** + * Primary bitstream flag + */ + primary: string | null; /** * A list of [[WorkspaceitemSectionUploadFileObject]] */ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html index ed117a50219..572c99ad3a7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html @@ -13,7 +13,7 @@ (blur)="onBlur($event)" (change)="onChange($event)" (focus)="onFocus($event)"/> -
+
@@ -41,6 +42,7 @@

{{ 'ldn-registered-services.title' | translate }}

class="btn btn-outline-dark"> +
- - - - - - + + + + + + @@ -72,7 +72,8 @@

{{'service.overview.delete.header' | translate }}

-
diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index bedcabb2713..0999c82c196 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -3,23 +3,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ServicesDirectoryComponent } from './services-directory.component'; describe('ServicesDirectoryComponent', () => { - let component: ServicesDirectoryComponent; - let fixture: ComponentFixture; + let component: ServicesDirectoryComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ ServicesDirectoryComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ServicesDirectoryComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ServicesDirectoryComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ServicesDirectoryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 91904d6bc57..3db9231ac2e 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,4 +1,12 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + TemplateRef, + ViewChild +} from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -11,130 +19,128 @@ import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { Operation } from 'fast-json-patch'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'ds-ldn-services-directory', - templateUrl: './ldn-services-directory.component.html', - styleUrls: ['./ldn-services-directory.component.scss'], - changeDetection: ChangeDetectionStrategy.Default + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], + changeDetection: ChangeDetectionStrategy.Default }) export class LdnServicesOverviewComponent implements OnInit, OnDestroy { - selectedServiceId: string | number | null = null; - servicesData: any[] = []; - @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; - ldnServicesRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - isProcessingSub: Subscription; - private modalRef: any; - - - constructor( - protected ldnServicesService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - private cdRef: ChangeDetectorRef, - private notificationService: NotificationsService, - private translateService: TranslateService, - ) { - } - - ngOnInit(): void { - this.setLdnServices(); - } - - setLdnServices() { - this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( - getFirstCompletedRemoteData() - )) - ); - } - - ngOnDestroy(): void { - this.paginationService.clearPagination(this.pageConfig.id); - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); + selectedServiceId: string | number | null = null; + servicesData: any[] = []; + @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + isProcessingSub: Subscription; + private modalRef: any; + + + constructor( + protected ldnServicesService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + private cdRef: ChangeDetectorRef, + private notificationService: NotificationsService, + private translateService: TranslateService, + ) { } - } - - openDeleteModal(content) { - this.modalRef = this.modalService.open(content); - } - - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); - } - - selectServiceToDelete(serviceId: number) { - this.selectedServiceId = serviceId; - this.openDeleteModal(this.deleteModal); - } - - deleteSelected(serviceId: string, ldnServicesService: LdnServicesService): void { - if (this.selectedServiceId !== null) { - ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { - if (rd.hasSucceeded) { - this.servicesData = this.servicesData.filter(service => service.id !== serviceId); - this.ldnServicesRD$ = this.ldnServicesRD$.pipe( - map((remoteData: RemoteData>) => { - if (remoteData.hasSucceeded) { - remoteData.payload.page = remoteData.payload.page.filter(service => service.id.toString() !== serviceId); - } - return remoteData; - }) - ); - this.cdRef.detectChanges(); - this.closeModal(); - this.notificationService.success(this.translateService.get('ldn-service-delete.notification.success.title'), - this.translateService.get('ldn-service-delete.notification.success.content')); - } else { - this.notificationService.error(this.translateService.get('ldn-service-delete.notification.error.title'), - this.translateService.get('ldn-service-delete.notification.error.content')); - this.cdRef.detectChanges(); - } - }); + + ngOnInit(): void { + this.setLdnServices(); } - } + setLdnServices() { + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( + getFirstCompletedRemoteData() + )) + ); + } + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + } + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } - toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { - const newStatus = !ldnService.enabled; - const originalStatus = ldnService.enabled; + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } - const patchOperation: Operation = { - op: 'replace', - path: '/enabled', - value: newStatus, - }; + selectServiceToDelete(serviceId: number) { + this.selectedServiceId = serviceId; + this.openDeleteModal(this.deleteModal); + } - ldnServicesService.patch(ldnService, [patchOperation]).pipe(getFirstCompletedRemoteData()).subscribe( - (rd: RemoteData) => { - if (rd.hasSucceeded) { - ldnService.enabled = newStatus; - this.notificationService.success(this.translateService.get('ldn-enable-service.notification.success.title'), - this.translateService.get('ldn-enable-service.notification.success.content')); - } else { - ldnService.enabled = originalStatus; - this.notificationService.error(this.translateService.get('ldn-enable-service.notification.error.title'), - this.translateService.get('ldn-enable-service.notification.error.content')); - } + deleteSelected(serviceId: string, ldnServicesService: LdnServicesService): void { + if (this.selectedServiceId !== null) { + ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + this.servicesData = this.servicesData.filter(service => service.id !== serviceId); + this.ldnServicesRD$ = this.ldnServicesRD$.pipe( + map((remoteData: RemoteData>) => { + if (remoteData.hasSucceeded) { + remoteData.payload.page = remoteData.payload.page.filter(service => service.id.toString() !== serviceId); + } + return remoteData; + }) + ); + this.cdRef.detectChanges(); + this.closeModal(); + this.notificationService.success(this.translateService.get('ldn-service-delete.notification.success.title'), + this.translateService.get('ldn-service-delete.notification.success.content')); + } else { + this.notificationService.error(this.translateService.get('ldn-service-delete.notification.error.title'), + this.translateService.get('ldn-service-delete.notification.error.content')); + this.cdRef.detectChanges(); + } + }); } - ); - } + } + + + toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { + const newStatus = !ldnService.enabled; + const originalStatus = ldnService.enabled; + + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + ldnServicesService.patch(ldnService, [patchOperation]).pipe(getFirstCompletedRemoteData()).subscribe( + (rd: RemoteData) => { + if (rd.hasSucceeded) { + ldnService.enabled = newStatus; + this.notificationService.success(this.translateService.get('ldn-enable-service.notification.success.title'), + this.translateService.get('ldn-enable-service.notification.success.content')); + } else { + ldnService.enabled = originalStatus; + this.notificationService.error(this.translateService.get('ldn-enable-service.notification.error.title'), + this.translateService.get('ldn-enable-service.notification.error.content')); + } + } + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts index 21123ede4af..8919f063570 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts @@ -4,26 +4,28 @@ import { Observable } from 'rxjs'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class LdnServicesGuard implements CanActivate { - constructor( - //private notifyInfoService: NotifyInfoService, - private router: Router - ) {} - canActivate( - route: ActivatedRouteSnapshot, - state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { - return true; - /*return this.notifyInfoService.isCoarConfigEnabled().pipe( - map(coarLdnEnabled => { - if (coarLdnEnabled) { - return true; - } else { - return this.router.parseUrl('/404'); - } - }) - );*/ - } + constructor( + //private notifyInfoService: NotifyInfoService, + private router: Router + ) { + } + + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + return true; + /*return this.notifyInfoService.isCoarConfigEnabled().pipe( + map(coarLdnEnabled => { + if (coarLdnEnabled) { + return true; + } else { + return this.router.parseUrl('/404'); + } + }) + );*/ + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts index 30af31cab82..9b66ad6788a 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts @@ -3,15 +3,15 @@ import { TestBed } from '@angular/core/testing'; import { LdnServicesGuard } from './ldn-services-guard.service'; describe('LdnServicesGuard', () => { - let guard: LdnServicesGuard; + let guard: LdnServicesGuard; - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(LdnServicesGuard); - }); + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(LdnServicesGuard); + }); - it('should be created', () => { - // @ts-ignore - expect(guard).toBeTruthy(); - }); + it('should be created', () => { + // @ts-ignore + expect(guard).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts index 865fa0b3ea1..6aceada3df9 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts @@ -1,7 +1,6 @@ -import { autoserialize, inheritSerialization, deserialize } from 'cerialize'; +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { LDN_SERVICE_CONSTRAINT_FILTER } from './ldn-service.resource-type'; import { CacheableObject } from '../../../core/cache/cacheable-object.model'; -import { HALLink } from '../../../core/shared/hal-link.model'; import { typedObject } from '../../../core/cache/builders/build-decorators'; import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; import { ResourceType } from '../../../core/shared/resource-type'; diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts index 1e67ccfeeeb..1103056e471 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts @@ -4,10 +4,10 @@ import { autoserialize } from 'cerialize'; * notify service patterns */ export class NotifyServicePattern { - @autoserialize - pattern: string; - @autoserialize - constraint: string; - @autoserialize - automatic: string; + @autoserialize + pattern: string; + @autoserialize + constraint: string; + @autoserialize + automatic: string; } diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts index 040e4d37b8a..d9e45d91a9c 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts @@ -2,7 +2,7 @@ * List of services statuses */ export enum LdnServiceStatus { - UNKOWN, - DISABLED, - ENABLED, + UNKOWN, + DISABLED, + ENABLED, } diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts index 6eda1944433..69a9baf2739 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts @@ -1,3 +1,3 @@ export class ldnServiceConstrain { - void: any; + void: any; } diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts index e0725b58517..8631ef24511 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -7,7 +7,6 @@ import { typedObject } from '../../../core/cache/builders/build-decorators'; import { NotifyServicePattern } from './ldn-service-patterns.model'; - /** An LdnService and its properties. */ @typedObject @inheritSerialization(CacheableObject) diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts index e24508e942d..ab4f78dc6be 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts @@ -3,15 +3,15 @@ import { TestBed } from '@angular/core/testing'; import { LdnDirectoryService } from './ldn-directory.service'; describe('LdnDirectoryService', () => { - let service: LdnDirectoryService; + let service: LdnDirectoryService; - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(LdnDirectoryService); - }); + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnDirectoryService); + }); - it('should be created', () => { - // @ts-ignore - expect(service).toBeTruthy(); - }); + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts index 3499759f03b..92446b4677f 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -4,22 +4,24 @@ import { map, Observable } from 'rxjs'; import { LdnServicesService } from "../ldn-services-data/ldn-services-data.service"; @Injectable({ - providedIn: 'root', + providedIn: 'root', }) export class LdnDirectoryService { - private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; + private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; - constructor(private http: HttpClient, - private ldnServicesService: LdnServicesService) {} - public getItemFilters(): Observable { + constructor(private http: HttpClient, + private ldnServicesService: LdnServicesService) { + } - return this.ldnServicesService.findAll().pipe( - map((servicesData) => { - return servicesData; - }) - ); - } + public getItemFilters(): Observable { + + return this.ldnServicesService.findAll().pipe( + map((servicesData) => { + return servicesData; + }) + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts index 38e1a4de2b9..922b63a8718 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts @@ -3,15 +3,15 @@ import { TestBed } from '@angular/core/testing'; import { LdnServicesBulkDeleteService } from './ldn-service-bulk-delete.service'; describe('LdnServiceBulkDeleteService', () => { - let service: LdnServicesBulkDeleteService; + let service: LdnServicesBulkDeleteService; - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(LdnServicesBulkDeleteService); - }); + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnServicesBulkDeleteService); + }); - it('should be created', () => { - // @ts-ignore - expect(service).toBeTruthy(); - }); + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); }); From e2ad9fe7072f785c2756b3ddcdca77ca48d991ff Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 13:27:27 +0200 Subject: [PATCH 094/592] CST-12174 Updated delete services to mark for deletion on outboundpatterns as well --- .../admin-ldn-services-routing.module.ts | 2 - .../ldn-service-form-edit.component.html | 17 +++--- .../ldn-service-form-edit.component.ts | 53 ++++++++++++++----- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 2d3c68f7cb7..43dc4f34624 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver'; import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; -import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @@ -15,7 +14,6 @@ import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service component: LdnServicesOverviewComponent, resolve: {breadcrumb: I18nBreadcrumbResolver}, data: {title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new'}, - canActivate: [LdnServicesGuard] }, { path: 'new', diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index bcd597845d3..330e055b376 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -84,7 +84,7 @@

{{ 'ldn-edit-registered-service.title' | translate }} -
+
{{ 'ldn-edit-registered-service.title' | translate }}
-
- +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 93622f9df09..d6429635323 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -56,7 +56,8 @@ export class LdnServiceFormEditComponent implements OnInit { @Input() public constraint: string; @Input() public automatic: boolean; @Input() public headerKey: string; - markedForDeletion: number[] = []; + markedForDeletionInboundPattern: number[] = []; + markedForDeletionOutboundPattern: number[] = []; protected serviceId: string; private originalInboundPatterns: any[] = []; private originalOutboundPatterns: any[] = []; @@ -259,7 +260,8 @@ export class LdnServiceFormEditComponent implements OnInit { } patchService() { - this.deleteMarkedPatterns(); + this.deleteMarkedInboundPatterns(); + this.deleteMarkedOutboundPatterns(); const patchOperations = this.generatePatchOperations(); @@ -282,31 +284,58 @@ export class LdnServiceFormEditComponent implements OnInit { this.closeModal(); } - markForDeletion(index: number) { - if (!this.markedForDeletion.includes(index)) { - this.markedForDeletion.push(index); + markForInboundPatternDeletion(index: number) { + if (!this.markedForDeletionInboundPattern.includes(index)) { + this.markedForDeletionInboundPattern.push(index); } } - unmarkForDeletion(index: number) { - const i = this.markedForDeletion.indexOf(index); + unmarkForInboundPatternDeletion(index: number) { + const i = this.markedForDeletionInboundPattern.indexOf(index); if (i !== -1) { - this.markedForDeletion.splice(i, 1); + this.markedForDeletionInboundPattern.splice(i, 1); } } - deleteMarkedPatterns() { - this.markedForDeletion.sort((a, b) => b - a); + markForOutboundPatternDeletion(index: number) { + if (!this.markedForDeletionOutboundPattern.includes(index)) { + this.markedForDeletionOutboundPattern.push(index); + } + } + + unmarkForOutboundPatternDeletion(index: number) { + const i = this.markedForDeletionOutboundPattern.indexOf(index); + if (i !== -1) { + this.markedForDeletionOutboundPattern.splice(i, 1); + } + } + + deleteMarkedInboundPatterns() { + this.markedForDeletionInboundPattern.sort((a, b) => b - a); const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - for (const index of this.markedForDeletion) { + for (const index of this.markedForDeletionInboundPattern) { if (index >= 0 && index < patternsArray.length) { this.deletedInboundPatterns.push(index); patternsArray.removeAt(index); } } - this.markedForDeletion = []; + this.markedForDeletionInboundPattern = []; + } + + deleteMarkedOutboundPatterns() { + this.markedForDeletionOutboundPattern.sort((a, b) => b - a); + const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + + for (const index of this.markedForDeletionOutboundPattern) { + if (index >= 0 && index < patternsArray.length) { + this.deletedOutboundPatterns.push(index); + patternsArray.removeAt(index); + } + } + + this.markedForDeletionOutboundPattern = []; } private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { From 4ecaeabe40148aeef573e9fff44c03b48cb9f417 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 13:27:46 +0200 Subject: [PATCH 095/592] CST-12174 removed not needed guards --- .../ldn-services-guard.service.ts | 31 ------------------- .../ldn-services.guard.spec.ts | 17 ---------- 2 files changed, 48 deletions(-) delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts deleted file mode 100644 index 8919f063570..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; -import { Observable } from 'rxjs'; - - -@Injectable({ - providedIn: 'root' -}) -export class LdnServicesGuard implements CanActivate { - - constructor( - //private notifyInfoService: NotifyInfoService, - private router: Router - ) { - } - - canActivate( - route: ActivatedRouteSnapshot, - state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { - return true; - /*return this.notifyInfoService.isCoarConfigEnabled().pipe( - map(coarLdnEnabled => { - if (coarLdnEnabled) { - return true; - } else { - return this.router.parseUrl('/404'); - } - }) - );*/ - } -} diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts deleted file mode 100644 index 9b66ad6788a..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { LdnServicesGuard } from './ldn-services-guard.service'; - -describe('LdnServicesGuard', () => { - let guard: LdnServicesGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(LdnServicesGuard); - }); - - it('should be created', () => { - // @ts-ignore - expect(guard).toBeTruthy(); - }); -}); From ce3ba35866bcc334e7601db47b7dc4debb1faef0 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 13:44:15 +0200 Subject: [PATCH 096/592] CST-12174 added isNew Check for patterns deeltion --- .../ldn-service-form-edit.component.ts | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index d6429635323..fa460afbca4 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -200,23 +200,6 @@ export class LdnServiceFormEditComponent implements OnInit { notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } - removeOutboundPattern(index: number): void { - const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - const patternGroup = patternsArray.at(index) as FormGroup; - const patternValue = patternGroup.value; - - if (index < 0 || index >= patternsArray.length || patternValue.isNew) { - patternsArray.removeAt(index); - return; - } - - - this.deletedOutboundPatterns.push(index); - - patternsArray.removeAt(index); - this.cdRef.detectChanges(); - } - toggleAutomatic(i: number) { const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); @@ -316,22 +299,34 @@ export class LdnServiceFormEditComponent implements OnInit { for (const index of this.markedForDeletionInboundPattern) { if (index >= 0 && index < patternsArray.length) { - this.deletedInboundPatterns.push(index); - patternsArray.removeAt(index); + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; + if (patternValue.isNew) { + patternsArray.removeAt(index); + } else { + this.deletedInboundPatterns.push(index); + } } } this.markedForDeletionInboundPattern = []; } + deleteMarkedOutboundPatterns() { this.markedForDeletionOutboundPattern.sort((a, b) => b - a); const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; for (const index of this.markedForDeletionOutboundPattern) { if (index >= 0 && index < patternsArray.length) { - this.deletedOutboundPatterns.push(index); - patternsArray.removeAt(index); + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; + if (patternValue.isNew) { + patternsArray.removeAt(index); + } else { + + this.deletedOutboundPatterns.push(index); + } } } From d877d6f8827901e42ab7ad59f4ad402ea02fe814 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 14:05:50 +0200 Subject: [PATCH 097/592] CST-12174 small layout fix --- .../ldn-service-form-edit.component.html | 9 +++++---- .../ldn-service-form/ldn-service-form.component.ts | 6 +++--- src/assets/i18n/en.json5 | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 330e055b376..368b312cd1d 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -267,12 +267,13 @@

{{'service.overview.reset-form.modal' | translate }}

{{ 'service.overview.reset-form.body' | translate }}
- - +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index ff42ffb4dc9..6b908cdae28 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -149,9 +149,9 @@ export class LdnServiceFormComponent implements OnInit { getFirstCompletedRemoteData() ).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { - this.notificationsService.success(this.translateService.get('ldn-service-notification.created.success.title')); - (this.translateService.get('ldn-service-notification.created.success.title'), - this.translateService.get('ldn-service-notification.created.success.body')); + this.notificationsService.success(this.translateService.get('ldn-service-notification.created.success.title'), + this.translateService.get('ldn-service-notification.created.success.body')); + this.sendBack(); this.closeModal(); } else { diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7cded8573d4..40f01500221 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -962,6 +962,7 @@ "ldn-service-delete.notification.success.content": "The service has been deleted", "ldn-service-delete.notification.error.title": "Failed Deletion", "ldn-service-delete.notification.error.content": "The service has not been deleted", + "service.overview.reset-form.reset-return": "Return", "service.overview.delete": "Delete service", "ldn-edit-service.title": "Edit service", "ldn-edit-service.form.label.name": "Name", From b3262ec290cb57c77ae0b4aebb11d9c296c06f66 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 14:11:00 +0200 Subject: [PATCH 098/592] CST-12180 added div container --- .../notify-info/notify-info.component.html | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html index 101cf867cc4..03ed39a8262 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.html +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -1,16 +1,15 @@ - - - - {{ 'coar-notify-support.title' | translate }} - - -

{{ 'coar-notify-support.title' | translate }}

-

+
+ + {{ 'coar-notify-support.title' | translate }} + + +

{{ 'coar-notify-support.title' | translate }}

+

-

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

-

+

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

+

-

{{ 'coar-notify-support.message-moderation.title' | translate }}

-

- - +

{{ 'coar-notify-support.message-moderation.title' | translate }}

+

+ +
From 422a223c40718b8a89c81caeff913208fc5227bc Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Tue, 24 Oct 2023 15:14:55 +0200 Subject: [PATCH 099/592] [CST-12235] support for the LDN inbox for root & /home & /item/:uuid pages --- .../notify-info/notify-info.service.ts | 19 ++++-- src/app/home-page/home-page.component.ts | 47 +++++++++++--- .../full/full-item-page.component.spec.ts | 2 + .../full/full-item-page.component.ts | 4 +- .../simple/item-page.component.spec.ts | 9 +++ .../item-page/simple/item-page.component.ts | 61 ++++++++++++++++++- 6 files changed, 125 insertions(+), 17 deletions(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts index b489677634f..4b2d572d3cc 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -10,7 +10,10 @@ import { ConfigurationProperty } from '../../shared/configuration-property.model }) export class NotifyInfoService { - private relationLink = 'http://www.w3.org/ns/ldp#inbox'; + /** + * The relation link for the inbox + */ + private _inboxRelationLink = 'http://www.w3.org/ns/ldp#inbox'; constructor( private configService: ConfigurationDataService, @@ -27,7 +30,11 @@ export class NotifyInfoService { ); } - getCoarLdnLocalInboxUrl(): Observable { + /** + * Get the url of the local inbox from the REST configuration + * @returns the url of the local inbox + */ + getCoarLdnLocalInboxUrls(): Observable { return this.configService.findByPropertyName('ldn.notify.local-inbox-endpoint').pipe( getFirstSucceededRemoteData(), getRemoteDataPayload(), @@ -49,7 +56,11 @@ export class NotifyInfoService { return `${ssl ? 'https' : 'http'}://${host}:${port}${namespace}`; } - getRelationLink(): string{ - return this.relationLink; + /** + * Method to get the relation link for the inbox + * @returns the relation link for the inbox + */ + getInboxRelationLink(): string { + return this._inboxRelationLink; } } diff --git a/src/app/home-page/home-page.component.ts b/src/app/home-page/home-page.component.ts index 1e0833c0d1b..585fd06fe69 100644 --- a/src/app/home-page/home-page.component.ts +++ b/src/app/home-page/home-page.component.ts @@ -1,23 +1,28 @@ -import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core'; +import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { map, switchMap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; -import { Observable, of } from 'rxjs'; +import { Observable } from 'rxjs'; import { Site } from '../core/shared/site.model'; import { environment } from '../../environments/environment'; import { isPlatformServer } from '@angular/common'; import { ServerResponseService } from '../core/services/server-response.service'; import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; import { LinkDefinition, LinkHeadService } from '../core/services/link-head.service'; +import { isNotEmpty } from '../shared/empty.util'; @Component({ selector: 'ds-home-page', styleUrls: ['./home-page.component.scss'], templateUrl: './home-page.component.html' }) -export class HomePageComponent implements OnInit { +export class HomePageComponent implements OnInit, OnDestroy { site$: Observable; recentSubmissionspageSize: number; + /** + * An array of LinkDefinition objects representing inbox links for the home page. + */ + inboxLinks: LinkDefinition[] = []; constructor( private route: ActivatedRoute, @@ -27,14 +32,18 @@ export class HomePageComponent implements OnInit { @Inject(PLATFORM_ID) private platformId: string ) { this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize; + // Get COAR REST API URLs from REST configuration + // only if COAR configuration is enabled this.notifyInfoService.isCoarConfigEnabled().pipe( switchMap((coarLdnEnabled: boolean) => { if (coarLdnEnabled) { - return this.notifyInfoService.getCoarLdnLocalInboxUrl(); + return this.notifyInfoService.getCoarLdnLocalInboxUrls(); } }) ).subscribe((coarRestApiUrls: string[]) => { - this.initPageLinks(coarRestApiUrls); + if (coarRestApiUrls.length > 0) { + this.initPageLinks(coarRestApiUrls); + } }); } @@ -44,17 +53,37 @@ export class HomePageComponent implements OnInit { ); } + /** + * Initializes page links for COAR REST API URLs. + * @param coarRestApiUrls An array of COAR REST API URLs. + */ private initPageLinks(coarRestApiUrls: string[]): void { - const rel = this.notifyInfoService.getRelationLink(); + const rel = this.notifyInfoService.getInboxRelationLink(); + let links = ''; coarRestApiUrls.forEach((coarRestApiUrl: string) => { + // Add link to head let tag: LinkDefinition = { href: coarRestApiUrl, rel: rel }; + this.inboxLinks.push(tag); this.linkHeadService.addTag(tag); - if (isPlatformServer(this.platformId)) { - this.responseService.setHeader('Link', `<${coarRestApiUrl}>; rel="${rel}"`); - } + + links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`; + }); + + if (isPlatformServer(this.platformId)) { + // Add link to response header + this.responseService.setHeader('Link', links); + } + } + + /** + * It removes the inbox links from the head of the html. + */ + ngOnDestroy(): void { + this.inboxLinks.forEach((link: LinkDefinition) => { + this.linkHeadService.removeTag(`href='${link.href}'`); }); } } diff --git a/src/app/item-page/full/full-item-page.component.spec.ts b/src/app/item-page/full/full-item-page.component.spec.ts index 9fc078c2cd7..c1917f77f42 100644 --- a/src/app/item-page/full/full-item-page.component.spec.ts +++ b/src/app/item-page/full/full-item-page.component.spec.ts @@ -23,6 +23,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { ServerResponseService } from '../../core/services/server-response.service'; import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; const mockItem: Item = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])), @@ -122,6 +123,7 @@ describe('FullItemPageComponent', () => { { provide: ServerResponseService, useValue: serverResponseService }, { provide: SignpostingDataService, useValue: signpostingDataService }, { provide: LinkHeadService, useValue: linkHeadService }, + { provide: NotifyInfoService, useValue: {} }, { provide: PLATFORM_ID, useValue: 'server' } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/item-page/full/full-item-page.component.ts b/src/app/item-page/full/full-item-page.component.ts index 31dd2c5fc28..da79fc04ccc 100644 --- a/src/app/item-page/full/full-item-page.component.ts +++ b/src/app/item-page/full/full-item-page.component.ts @@ -19,6 +19,7 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/ import { ServerResponseService } from '../../core/services/server-response.service'; import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; /** * This component renders a full item page. @@ -55,9 +56,10 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit, protected responseService: ServerResponseService, protected signpostingDataService: SignpostingDataService, protected linkHeadService: LinkHeadService, + protected notifyInfoService: NotifyInfoService, @Inject(PLATFORM_ID) protected platformId: string, ) { - super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService, platformId); + super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService,notifyInfoService, platformId); } /*** AoT inheritance fix, will hopefully be resolved in the near future **/ diff --git a/src/app/item-page/simple/item-page.component.spec.ts b/src/app/item-page/simple/item-page.component.spec.ts index b3202108f43..b8354496da8 100644 --- a/src/app/item-page/simple/item-page.component.spec.ts +++ b/src/app/item-page/simple/item-page.component.spec.ts @@ -26,6 +26,7 @@ import { ServerResponseService } from '../../core/services/server-response.servi import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service'; import { SignpostingLink } from '../../core/data/signposting-links.model'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; const mockItem: Item = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])), @@ -62,6 +63,7 @@ describe('ItemPageComponent', () => { let serverResponseService: jasmine.SpyObj; let signpostingDataService: jasmine.SpyObj; let linkHeadService: jasmine.SpyObj; + let notifyInfoService: jasmine.SpyObj; const mockMetadataService = { /* eslint-disable no-empty,@typescript-eslint/no-empty-function */ @@ -94,6 +96,12 @@ describe('ItemPageComponent', () => { removeTag: jasmine.createSpy('removeTag'), }); + notifyInfoService = jasmine.createSpyObj('NotifyInfoService', { + getInboxRelationLink: 'http://www.w3.org/ns/ldp#inbox', + isCoarConfigEnabled: observableOf(true), + getCoarLdnLocalInboxUrls: observableOf(['http://test.org', 'http://test2.org']), + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot({ loader: { @@ -112,6 +120,7 @@ describe('ItemPageComponent', () => { { provide: ServerResponseService, useValue: serverResponseService }, { provide: SignpostingDataService, useValue: signpostingDataService }, { provide: LinkHeadService, useValue: linkHeadService }, + { provide: NotifyInfoService, useValue: notifyInfoService}, { provide: PLATFORM_ID, useValue: 'server' }, ], diff --git a/src/app/item-page/simple/item-page.component.ts b/src/app/item-page/simple/item-page.component.ts index b9be6bebfb6..2e4e3575724 100644 --- a/src/app/item-page/simple/item-page.component.ts +++ b/src/app/item-page/simple/item-page.component.ts @@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit, PLATFORM import { ActivatedRoute, Router } from '@angular/router'; import { isPlatformServer } from '@angular/common'; -import { Observable } from 'rxjs'; -import { map, take } from 'rxjs/operators'; +import { Observable, combineLatest } from 'rxjs'; +import { map, switchMap, take } from 'rxjs/operators'; import { ItemDataService } from '../../core/data/item-data.service'; import { RemoteData } from '../../core/data/remote-data'; @@ -21,6 +21,7 @@ import { SignpostingDataService } from '../../core/data/signposting-data.service import { SignpostingLink } from '../../core/data/signposting-links.model'; import { isNotEmpty } from '../../shared/empty.util'; import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from 'src/app/core/coar-notify/notify-info/notify-info.service'; /** * This component renders a simple item page. @@ -68,6 +69,13 @@ export class ItemPageComponent implements OnInit, OnDestroy { */ signpostingLinks: SignpostingLink[] = []; + /** + * An array of LinkDefinition objects representing inbox links for the item page. + */ + inboxTags: LinkDefinition[] = []; + + coarRestApiUrls: string[] = []; + constructor( protected route: ActivatedRoute, protected router: Router, @@ -77,6 +85,7 @@ export class ItemPageComponent implements OnInit, OnDestroy { protected responseService: ServerResponseService, protected signpostingDataService: SignpostingDataService, protected linkHeadService: LinkHeadService, + protected notifyInfoService: NotifyInfoService, @Inject(PLATFORM_ID) protected platformId: string ) { this.initPageLinks(); @@ -106,7 +115,8 @@ export class ItemPageComponent implements OnInit, OnDestroy { */ private initPageLinks(): void { this.route.params.subscribe(params => { - this.signpostingDataService.getLinks(params.id).pipe(take(1)).subscribe((signpostingLinks: SignpostingLink[]) => { + combineLatest([this.signpostingDataService.getLinks(params.id).pipe(take(1)), this.getCoarLdnLocalInboxUrls()]) + .subscribe(([signpostingLinks, coarRestApiUrls]) => { let links = ''; this.signpostingLinks = signpostingLinks; @@ -124,6 +134,11 @@ export class ItemPageComponent implements OnInit, OnDestroy { this.linkHeadService.addTag(tag); }); + if (coarRestApiUrls.length > 0) { + let inboxLinks = this.initPageInboxLinks(coarRestApiUrls); + links = links + (isNotEmpty(links) ? ', ' : '') + inboxLinks; + } + if (isPlatformServer(this.platformId)) { this.responseService.setHeader('Link', links); } @@ -131,9 +146,49 @@ export class ItemPageComponent implements OnInit, OnDestroy { }); } + /** + * Sets the COAR LDN local inbox URL if COAR configuration is enabled. + * If the COAR LDN local inbox URL is retrieved successfully, initializes the page inbox links. + */ + private getCoarLdnLocalInboxUrls(): Observable { + return this.notifyInfoService.isCoarConfigEnabled().pipe( + switchMap((coarLdnEnabled: boolean) => { + if (coarLdnEnabled) { + return this.notifyInfoService.getCoarLdnLocalInboxUrls(); + } + }) + ); + } + + /** + * Initializes the page inbox links. + * @param coarRestApiUrls - An array of COAR REST API URLs. + */ + private initPageInboxLinks(coarRestApiUrls: string[]): string { + const rel = this.notifyInfoService.getInboxRelationLink(); + let links = ''; + + coarRestApiUrls.forEach((coarRestApiUrl: string) => { + // Add link to head + let tag: LinkDefinition = { + href: coarRestApiUrl, + rel: rel + }; + this.inboxTags.push(tag); + this.linkHeadService.addTag(tag); + + links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`; + }); + + return links; + } + ngOnDestroy(): void { this.signpostingLinks.forEach((link: SignpostingLink) => { this.linkHeadService.removeTag(`href='${link.href}'`); }); + this.inboxTags.forEach((link: LinkDefinition) => { + this.linkHeadService.removeTag(`href='${link.href}'`); + }); } } From 494295cd97ce81bbb45b73d515b9656528326833 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 15:26:11 +0200 Subject: [PATCH 100/592] CST-11045 added sections parts --- ...eitem-section-form-notify-service.model.ts | 16 ++- .../ldn-service/ldn-service.component.html | 0 .../ldn-service/ldn-service.component.scss | 0 .../ldn-service/ldn-service.component.spec.ts | 23 ++++ .../ldn-service/ldn-service.component.ts | 129 ++++++++++++++++++ .../sections/ldn-service/ldn-service.model.ts | 27 ++++ src/app/submission/sections/sections-type.ts | 1 + src/app/submission/submission.module.ts | 3 + 8 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.html create mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.scss create mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.spec.ts create mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.ts create mode 100644 src/app/submission/sections/ldn-service/ldn-service.model.ts diff --git a/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts b/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts index b614eb91402..c952dc61009 100644 --- a/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-form-notify-service.model.ts @@ -1,17 +1,21 @@ import {NotifyServiceObject} from './notify-service-submission.model' +import { LdnService } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; /** - * An interface to represent the submission's item accesses condition. + * An interface to represent the submission's item ldn-services condition. */ export interface WorkspaceitemSectionNotifyServiceRequestItemDissemination extends NotifyServiceObject { /** - * The access condition id + * The ldn-review service */ - id: string; + reviewService: LdnService; /** - * Boolean that indicates whether the current item must be findable via search or browse. + * The ldn-endorse service */ - discoverable: boolean; - + endorseService: LdnService; + /** + * The ldn-ingest service + */ + ingestService: LdnService; } diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.html b/src/app/submission/sections/ldn-service/ldn-service.component.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.scss b/src/app/submission/sections/ldn-service/ldn-service.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts b/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts new file mode 100644 index 00000000000..ec36f1f010b --- /dev/null +++ b/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceComponent } from './ldn-service.component'; + +describe('LdnServiceComponent', () => { + let component: LdnServiceComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LdnServiceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.ts b/src/app/submission/sections/ldn-service/ldn-service.component.ts new file mode 100644 index 00000000000..6690395e722 --- /dev/null +++ b/src/app/submission/sections/ldn-service/ldn-service.component.ts @@ -0,0 +1,129 @@ +import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core'; +import { DynamicFormControlEvent } from '@ng-dynamic-forms/core'; +import { Observable, Subscription } from 'rxjs'; +import { SectionModelComponent } from '../models/section.model'; +import { renderSectionFor } from '../sections-decorator'; +import { SectionsType } from '../sections-type'; +import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; +import { FormComponent } from '../../../shared/form/form.component'; +import { CollectionDataService } from '../../../core/data/collection-data.service'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { SectionFormOperationsService } from '../form/section-form-operations.service'; +import { FormService } from '../../../shared/form/form.service'; +import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; +import { SectionsService } from '../sections.service'; +import { SubmissionService } from '../../submission.service'; +import { TranslateService } from '@ngx-translate/core'; +import { SectionDataObject } from '../models/section-data.model'; +import { + WorkspaceitemSectionNotifyServiceRequestItemDissemination +} from '../../../core/submission/models/workspaceitem-section-form-notify-service.model'; +import { hasValue } from '../../../shared/empty.util'; +/** + * This component represents a section that contains the submission ldn-service form. + */ +@Component({ + selector: 'ds-ldn-service', + templateUrl: './ldn-service.component.html', + styleUrls: ['./ldn-service.component.scss'] +}) +@renderSectionFor(SectionsType.LdnService) +export class LdnServiceComponent extends SectionModelComponent { + + /** + * The [[JsonPatchOperationPathCombiner]] object + * @type {JsonPatchOperationPathCombiner} + */ + protected pathCombiner: JsonPatchOperationPathCombiner; + + /** + * Array to track all subscriptions and unsubscribe them onDestroy + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * A boolean representing if div should start collapsed + */ + public isCollapsed = false; + + /** + * The FormComponent reference + */ + @ViewChild('formRef') private formRef: FormComponent; + + /** + * Initialize instance variables + * + * @param {ChangeDetectorRef} changeDetectorRef + * @param {CollectionDataService} collectionDataService + * @param {FormBuilderService} formBuilderService + * @param {SectionFormOperationsService} formOperationsService + * @param {FormService} formService + * @param {JsonPatchOperationsBuilder} operationsBuilder + * @param {SectionsService} sectionService + * @param {SubmissionService} submissionService + * @param {TranslateService} translateService + * @param {string} injectedCollectionId + * @param {SectionDataObject} injectedSectionData + * @param {string} injectedSubmissionId + */ + constructor(protected changeDetectorRef: ChangeDetectorRef, + protected collectionDataService: CollectionDataService, + protected formBuilderService: FormBuilderService, + protected formOperationsService: SectionFormOperationsService, + protected formService: FormService, + protected operationsBuilder: JsonPatchOperationsBuilder, + protected sectionService: SectionsService, + protected submissionService: SubmissionService, + protected translateService: TranslateService, + @Inject('collectionIdProvider') public injectedCollectionId: string, + @Inject('sectionDataProvider') public injectedSectionData: SectionDataObject, + @Inject('submissionIdProvider') public injectedSubmissionId: string) { + super(injectedCollectionId, injectedSectionData, injectedSubmissionId); + } + + /** + * Initialize all instance variables + */ + onSectionInit() { + this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionData.id); + this.subs.push( + this.sectionService.getSectionData(this.submissionId, this.sectionData.id, this.sectionData.sectionType) + .subscribe((ldnServicesSection: WorkspaceitemSectionNotifyServiceRequestItemDissemination) => { + console.log(ldnServicesSection); + }) + ); + } + + + + /** + * Method called when a form dfChange event is fired. + * Dispatch form operations based on changes. + */ + onChange(event: DynamicFormControlEvent) { + const path = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event); + const value = this.formOperationsService.getFieldValueFromChangeEvent(event); + if (value) { + this.operationsBuilder.add(this.pathCombiner.getPath(path), value.value.toString(), false, true); + this.sectionService.dispatchRemoveSectionErrors(this.submissionId, this.sectionData.id); + } else { + this.operationsBuilder.remove(this.pathCombiner.getPath(path)); + } + } + + /** + * Unsubscribe from all subscriptions + */ + onSectionDestroy() { + this.subs + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); + } + + protected getSectionStatus(): Observable { + return undefined; + } + +} diff --git a/src/app/submission/sections/ldn-service/ldn-service.model.ts b/src/app/submission/sections/ldn-service/ldn-service.model.ts new file mode 100644 index 00000000000..fb441dd3628 --- /dev/null +++ b/src/app/submission/sections/ldn-service/ldn-service.model.ts @@ -0,0 +1,27 @@ +export const SECTION_LDN_SERVICE_FORM_LAYOUT = { + + granted: { + element: { + container: 'custom-control custom-checkbox pl-1', + control: 'custom-control-input', + label: 'custom-control-label pt-1' + } + } +}; + +export const SECTION_LDN_SERVICE_FORM_MODEL = [ + { + id: 'granted', + label: 'submission.sections.license.granted-label', + required: true, + value: false, + validators: { + required: null + }, + errorMessages: { + required: 'submission.sections.license.required', + notgranted: 'submission.sections.license.notgranted' + }, + type: 'CHECKBOX', + } +]; diff --git a/src/app/submission/sections/sections-type.ts b/src/app/submission/sections/sections-type.ts index 6bca8a72526..40f6f85e0e4 100644 --- a/src/app/submission/sections/sections-type.ts +++ b/src/app/submission/sections/sections-type.ts @@ -9,4 +9,5 @@ export enum SectionsType { SherpaPolicies = 'sherpaPolicy', Identifiers = 'identifiers', Collection = 'collection', + LdnService = 'ldn-service' } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index cf0ab2b369a..8f35bb4420c 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -67,6 +67,7 @@ import { } from './sections/sherpa-policies/metadata-information/metadata-information.component'; import { SectionFormOperationsService } from './sections/form/section-form-operations.service'; import {SubmissionSectionIdentifiersComponent} from './sections/identifiers/section-identifiers.component'; +import { LdnServiceComponent } from './sections/ldn-service/ldn-service.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -76,6 +77,7 @@ const ENTRY_COMPONENTS = [ SubmissionSectionCcLicensesComponent, SubmissionSectionAccessesComponent, SubmissionSectionSherpaPoliciesComponent, + LdnServiceComponent ]; const DECLARATIONS = [ @@ -114,6 +116,7 @@ const DECLARATIONS = [ CoreModule.forRoot(), SharedModule, StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(), EffectsModule.forFeature(submissionEffects), JournalEntitiesModule.withEntryComponents(), ResearchEntitiesModule.withEntryComponents(), From c93c2a62344a57995f9ba60567b912118d296426 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 24 Oct 2023 16:52:03 +0200 Subject: [PATCH 101/592] CST-12174 fixed red selected form section both for inbound and outbound pattens --- .../ldn-service-form-edit.component.html | 21 +++++++++++-------- .../ldn-service-form-edit.component.scss | 4 +--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 368b312cd1d..568f3ed46fa 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -79,12 +79,12 @@

{{ 'ldn-edit-registered-service.title' | translate }}
+ formGroupName="notifyServiceInboundPatterns" [class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)"> -
+
{{ 'ldn-edit-registered-service.title' | translate }}
-
+
- diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index b686e6533bc..0b244d76dbc 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -1,8 +1,6 @@ form { - max-width: 800px; font-size: 14px; position: relative; - } input[type="text"], @@ -127,7 +125,7 @@ form button.btn.btn-primary[type="submit"] { } .marked-for-deletion { - background-color: #ffcccc; + background-color: lighten($red, 30%); } From f006bb3dffbf6241b9e6612478f3894d1c23b8cb Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Wed, 25 Oct 2023 18:01:27 +0200 Subject: [PATCH 102/592] [CST-12043] fix: dependencies for unit test --- .../models/custom-switch/custom-switch.component.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.spec.ts index ceb498fe567..4d626e7cdd3 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.spec.ts @@ -1,11 +1,12 @@ import { DynamicFormsCoreModule, DynamicFormService } from '@ng-dynamic-forms/core'; import { UntypedFormGroup, ReactiveFormsModule } from '@angular/forms'; import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; -import { DebugElement } from '@angular/core'; +import { DebugElement} from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { DynamicCustomSwitchModel } from './custom-switch.model'; import { CustomSwitchComponent } from './custom-switch.component'; +import { TranslateModule } from '@ngx-translate/core'; describe('CustomSwitchComponent', () => { @@ -20,9 +21,10 @@ describe('CustomSwitchComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ + TranslateModule.forRoot(), ReactiveFormsModule, NoopAnimationsModule, - DynamicFormsCoreModule.forRoot() + DynamicFormsCoreModule.forRoot(), ], declarations: [CustomSwitchComponent] From 7cee04dd2d3786a11174b1f263a29fb6064175f7 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Wed, 25 Oct 2023 18:29:48 +0200 Subject: [PATCH 103/592] [CST-12044] feature: badge for primary bitstream --- .../core/data/bitstream-data.service.spec.ts | 34 ++++++++++++++++++ src/app/core/data/bitstream-data.service.ts | 36 +++++++++++++++++-- .../file-section/file-section.component.html | 5 ++- .../file-section.component.spec.ts | 17 ++++++++- .../file-section/file-section.component.ts | 12 +++++++ 5 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/app/core/data/bitstream-data.service.spec.ts b/src/app/core/data/bitstream-data.service.spec.ts index 89178f8dd21..ccdff75fdb9 100644 --- a/src/app/core/data/bitstream-data.service.spec.ts +++ b/src/app/core/data/bitstream-data.service.spec.ts @@ -21,6 +21,11 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import objectContaining = jasmine.objectContaining; import { RemoteData } from './remote-data'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { BundleDataService } from './bundle-data.service'; +import { ItemMock } from 'src/app/shared/mocks/item.mock'; +import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from 'src/app/shared/remote-data.utils'; +import { Bundle } from '../shared/bundle.model'; +import { cold } from 'jasmine-marbles'; describe('BitstreamDataService', () => { let service: BitstreamDataService; @@ -29,6 +34,7 @@ describe('BitstreamDataService', () => { let halService: HALEndpointService; let bitstreamFormatService: BitstreamFormatDataService; let rdbService: RemoteDataBuildService; + let bundleDataService: BundleDataService; const bitstreamFormatHref = 'rest-api/bitstreamformats'; const bitstream1 = Object.assign(new Bitstream(), { @@ -62,6 +68,7 @@ describe('BitstreamDataService', () => { bitstreamFormatService = jasmine.createSpyObj('bistreamFormatService', { getBrowseEndpoint: observableOf(bitstreamFormatHref) }); + rdbService = getMockRemoteDataBuildService(); TestBed.configureTestingModule({ @@ -76,6 +83,7 @@ describe('BitstreamDataService', () => { ], }); service = TestBed.inject(BitstreamDataService); + bundleDataService = TestBed.inject(BundleDataService); }); describe('composition', () => { @@ -118,6 +126,32 @@ describe('BitstreamDataService', () => { expect(service.invalidateByHref).toHaveBeenCalledWith('fake-bitstream1-self'); }); + describe('findPrimaryBitstreamByItemAndName', () => { + it('should return primary bitstream', () => { + const exprected$ = cold('(a|)', { a: bitstream1} ); + const bundle = Object.assign(new Bundle(), { + primaryBitstream: observableOf(createSuccessfulRemoteDataObject(bitstream1)), + }); + spyOn(bundleDataService, 'findByItemAndName').and.returnValue(observableOf(createSuccessfulRemoteDataObject(bundle))); + expect(service.findPrimaryBitstreamByItemAndName(ItemMock, 'ORIGINAL')).toBeObservable(exprected$); + }); + + it('should return null if primary bitstream has not be succeeded ', () => { + const exprected$ = cold('(a|)', { a: null} ); + const bundle = Object.assign(new Bundle(), { + primaryBitstream: observableOf(createFailedRemoteDataObject()), + }); + spyOn(bundleDataService, 'findByItemAndName').and.returnValue(observableOf(createSuccessfulRemoteDataObject(bundle))); + expect(service.findPrimaryBitstreamByItemAndName(ItemMock, 'ORIGINAL')).toBeObservable(exprected$); + }); + + it('should return EMPTY if nothing where found', () => { + const exprected$ = cold('(|)', {} ); + spyOn(bundleDataService, 'findByItemAndName').and.returnValue(observableOf(createFailedRemoteDataObject())); + expect(service.findPrimaryBitstreamByItemAndName(ItemMock, 'ORIGINAL')).toBeObservable(exprected$); + }); + }); + it('should be able to delete multiple bitstreams', () => { service.removeMultiple([bitstream1, bitstream2]); diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index bb4ec281665..97949ffa25c 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -1,9 +1,9 @@ import { HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable, EMPTY } from 'rxjs'; import { find, map, switchMap, take } from 'rxjs/operators'; import { hasValue } from '../../shared/empty.util'; -import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { FollowLinkConfig, followLink } from '../../shared/utils/follow-link-config.model'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { Bitstream } from '../shared/bitstream.model'; @@ -34,6 +34,7 @@ import { NoContent } from '../shared/NoContent.model'; import { IdentifiableDataService } from './base/identifiable-data.service'; import { dataService } from './base/data-service.decorator'; import { Operation, RemoveOperation } from 'fast-json-patch'; +import { getFirstCompletedRemoteData } from '../shared/operators'; /** * A service to retrieve {@link Bitstream}s from the REST API @@ -201,6 +202,37 @@ export class BitstreamDataService extends IdentifiableDataService imp return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow); } + + /** + * + * Make a request to get primary bitstream + * in all current use cases, and having it simplifies this method + * + * @param item the {@link Item} the {@link Bundle} is a part of + * @param bundleName the name of the {@link Bundle} we want to find + * {@link Bitstream}s for + * @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 + * @return {Observable} + * Return an observable that constains primary bitstream information or null + */ + public findPrimaryBitstreamByItemAndName(item: Item, bundleName: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable { + return this.bundleService.findByItemAndName(item, bundleName, useCachedVersionIfAvailable, reRequestOnStale, followLink('primaryBitstream')).pipe( + getFirstCompletedRemoteData(), + switchMap((rd: RemoteData) => { + if (!rd.hasSucceeded) { + return EMPTY; + } + return rd.payload.primaryBitstream.pipe( + getFirstCompletedRemoteData(), + map((rdb: RemoteData) => rdb.hasSucceeded ? rdb.payload : null) + ); + }) + ); + } + /** * Make a new FindListRequest with given search method * diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.html b/src/app/item-page/simple/field-components/file-section/file-section.component.html index cd708510e8c..38b2905beaa 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.html +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.html @@ -2,7 +2,10 @@
- {{ dsoNameService.getName(file) }} + + Primary + {{ dsoNameService.getName(file) }} + ({{(file?.sizeBytes) | dsFileSize }}) diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts index 8acf405b55f..4a825e50c91 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts @@ -25,7 +25,8 @@ describe('FileSectionComponent', () => { let fixture: ComponentFixture; const bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', { - findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([])) + findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([])), + findPrimaryBitstreamByItemAndName: observableOf(null) }); const mockBitstream: Bitstream = Object.assign(new Bitstream(), @@ -81,6 +82,20 @@ describe('FileSectionComponent', () => { fixture.detectChanges(); })); + it('should set the id of primary bitstream', () => { + comp.primaryBitsreamId = undefined; + bitstreamDataService.findPrimaryBitstreamByItemAndName.and.returnValue(observableOf(mockBitstream)); + comp.ngOnInit(); + expect(comp.primaryBitsreamId).toBe(mockBitstream.id); + }); + + it('should not set the id of primary bitstream', () => { + comp.primaryBitsreamId = undefined; + bitstreamDataService.findPrimaryBitstreamByItemAndName.and.returnValue(observableOf(null)); + comp.ngOnInit(); + expect(comp.primaryBitsreamId).toBeUndefined(); + }); + describe('when the bitstreams are loading', () => { beforeEach(() => { comp.bitstreams$.next([mockBitstream]); diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.ts b/src/app/item-page/simple/field-components/file-section/file-section.component.ts index 3c41731c5f4..76f33de9063 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.ts +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.ts @@ -39,6 +39,8 @@ export class FileSectionComponent implements OnInit { pageSize: number; + primaryBitsreamId: string; + constructor( protected bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, @@ -50,9 +52,19 @@ export class FileSectionComponent implements OnInit { } ngOnInit(): void { + this.getPrimaryBitstreamId(); this.getNextPage(); } + private getPrimaryBitstreamId() { + this.bitstreamDataService.findPrimaryBitstreamByItemAndName(this.item, 'ORIGINAL', true, true).subscribe((primaryBitstream: Bitstream | null) => { + if (!primaryBitstream) { + return; + } + this.primaryBitsreamId = primaryBitstream?.id; + }); + } + /** * This method will retrieve the next page of Bitstreams from the external BitstreamDataService call. * It'll retrieve the currentPage from the class variables and it'll add the next page of bitstreams with the From c644cc5102517d5bdd10cb54cdaf9aac5a01cda8 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Wed, 25 Oct 2023 18:30:54 +0200 Subject: [PATCH 104/592] [CST-12044] feature: add code coverage flag --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2116da6a0e3..53044bbd637 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "build:prod": "yarn run build:ssr", "build:ssr": "ng build --configuration production && ng run dspace-angular:server:production", "test": "ng test --source-map=true --watch=false --configuration test", - "test:watch": "nodemon --exec \"ng test --source-map=true --watch=true --configuration test\"", + "test:watch": "nodemon --exec \"ng test --source-map=true --code-coverage --watch=true --configuration test\"", "test:headless": "ng test --source-map=true --watch=false --configuration test --browsers=ChromeHeadless --code-coverage", "lint": "ng lint", "lint-fix": "ng lint --fix=true", From 7ed4d1457df7e9d794c2b28e63dfd44f726387df Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 25 Oct 2023 21:09:07 +0200 Subject: [PATCH 105/592] CST-11045 Provided coarnotify section logic and dataservices for configs --- .../ldn-services-data.service.ts | 6 +- .../ldn-service.constrain.model.ts | 2 +- src/app/core/core.module.ts | 12 +- .../form/submission-form.component.html | 5 + .../section-container.component.html | 4 +- .../ldn-service/ldn-service.component.scss | 0 .../ldn-service/ldn-service.component.spec.ts | 23 -- .../ldn-service/ldn-service.component.ts | 129 -------- .../coar-notify-config-data.service.ts | 122 +++++++ .../section-coar-notify-model.ts | 74 +++++ ...ction-coar-notify-service.resource-type.ts | 13 + ...coar-notify-workspaceitems-data-service.ts | 117 +++++++ .../section-coar-notify.component.html | 31 ++ .../section-coar-notify.component.scss} | 0 .../section-coar-notify.component.spec.ts | 23 ++ .../section-coar-notify.component.ts | 308 ++++++++++++++++++ ...mission-coar-notify-workspaceitem.model.ts | 35 ++ .../submission-coar-notify.config.ts | 39 +++ src/app/submission/sections/sections-type.ts | 2 +- src/app/submission/submission.module.ts | 10 +- src/app/submission/submission.service.ts | 1 + 21 files changed, 792 insertions(+), 164 deletions(-) delete mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.scss delete mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.spec.ts delete mode 100644 src/app/submission/sections/ldn-service/ldn-service.component.ts create mode 100644 src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify-workspaceitems-data-service.ts create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify.component.html rename src/app/submission/sections/{ldn-service/ldn-service.component.html => section-coar-notify/section-coar-notify.component.scss} (100%) create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts create mode 100644 src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts create mode 100644 src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts create mode 100644 src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index 35f9bee04f2..cdd259447a1 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -28,7 +28,7 @@ import { ChangeAnalyzer } from '../../../core/data/change-analyzer'; import { Operation } from 'fast-json-patch'; import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; import { CreateData, CreateDataImpl } from '../../../core/data/base/create-data'; -import { ldnServiceConstrain } from '../ldn-services-model/ldn-service.constrain.model'; +import { LdnServiceConstrain } from '../ldn-services-model/ldn-service.constrain.model'; import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; import { hasValue } from 'src/app/shared/empty.util'; @@ -92,7 +92,7 @@ export class LdnServicesService extends IdentifiableDataService impl return this.deleteData.deleteByHref(href, copyVirtualMetadata); } - public invoke(serviceName: string, serviceId: string, parameters: ldnServiceConstrain[], files: File[]): Observable> { + public invoke(serviceName: string, serviceId: string, parameters: LdnServiceConstrain[], files: File[]): Observable> { const requestId = this.requestService.generateRequestId(); this.getBrowseEndpoint().pipe( take(1), @@ -115,7 +115,7 @@ export class LdnServicesService extends IdentifiableDataService impl ); } - private getInvocationFormData(constrain: ldnServiceConstrain[], files: File[]): FormData { + private getInvocationFormData(constrain: LdnServiceConstrain[], files: File[]): FormData { const form: FormData = new FormData(); form.set('properties', JSON.stringify(constrain)); files.forEach((file: File) => { diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts index 69a9baf2739..500cefbd526 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts @@ -1,3 +1,3 @@ -export class ldnServiceConstrain { +export class LdnServiceConstrain { void: any; } diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 88da00f02c8..d0f2dbbbaf8 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -190,7 +190,11 @@ import { SuggestionSource } from './suggestion-notifications/reciter-suggestions import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { LdnService } from '../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; import { LdnItemfiltersService } from '../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service'; -import { Itemfilter } from "../admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters"; +import { Itemfilter } from '../admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters'; +import { + CoarNotifyConfigDataService +} from '../submission/sections/section-coar-notify/coar-notify-config-data.service'; +import { SubmissionCoarNotifyConfig } from '../submission/sections/section-coar-notify/submission-coar-notify.config'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -315,7 +319,8 @@ const PROVIDERS = [ OrcidHistoryDataService, SupervisionOrderDataService, LdnServicesService, - LdnItemfiltersService + LdnItemfiltersService, + CoarNotifyConfigDataService ]; /** @@ -398,7 +403,8 @@ export const models = SuggestionTarget, SuggestionSource, LdnService, - Itemfilter + Itemfilter, + SubmissionCoarNotifyConfig ]; diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index fa04a6793cf..c79364e2afb 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -38,9 +38,14 @@ [sectionData]="object"> +
+ diff --git a/src/app/submission/sections/container/section-container.component.html b/src/app/submission/sections/container/section-container.component.html index e6ae9d1b9c1..f39ba72ffab 100644 --- a/src/app/submission/sections/container/section-container.component.html +++ b/src/app/submission/sections/container/section-container.component.html @@ -42,10 +42,10 @@
-
+
aaaaaaaaa
-
\ No newline at end of file +
diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.scss b/src/app/submission/sections/ldn-service/ldn-service.component.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts b/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts deleted file mode 100644 index ec36f1f010b..00000000000 --- a/src/app/submission/sections/ldn-service/ldn-service.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { LdnServiceComponent } from './ldn-service.component'; - -describe('LdnServiceComponent', () => { - let component: LdnServiceComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ LdnServiceComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(LdnServiceComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.ts b/src/app/submission/sections/ldn-service/ldn-service.component.ts deleted file mode 100644 index 6690395e722..00000000000 --- a/src/app/submission/sections/ldn-service/ldn-service.component.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core'; -import { DynamicFormControlEvent } from '@ng-dynamic-forms/core'; -import { Observable, Subscription } from 'rxjs'; -import { SectionModelComponent } from '../models/section.model'; -import { renderSectionFor } from '../sections-decorator'; -import { SectionsType } from '../sections-type'; -import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; -import { FormComponent } from '../../../shared/form/form.component'; -import { CollectionDataService } from '../../../core/data/collection-data.service'; -import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; -import { SectionFormOperationsService } from '../form/section-form-operations.service'; -import { FormService } from '../../../shared/form/form.service'; -import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; -import { SectionsService } from '../sections.service'; -import { SubmissionService } from '../../submission.service'; -import { TranslateService } from '@ngx-translate/core'; -import { SectionDataObject } from '../models/section-data.model'; -import { - WorkspaceitemSectionNotifyServiceRequestItemDissemination -} from '../../../core/submission/models/workspaceitem-section-form-notify-service.model'; -import { hasValue } from '../../../shared/empty.util'; -/** - * This component represents a section that contains the submission ldn-service form. - */ -@Component({ - selector: 'ds-ldn-service', - templateUrl: './ldn-service.component.html', - styleUrls: ['./ldn-service.component.scss'] -}) -@renderSectionFor(SectionsType.LdnService) -export class LdnServiceComponent extends SectionModelComponent { - - /** - * The [[JsonPatchOperationPathCombiner]] object - * @type {JsonPatchOperationPathCombiner} - */ - protected pathCombiner: JsonPatchOperationPathCombiner; - - /** - * Array to track all subscriptions and unsubscribe them onDestroy - * @type {Array} - */ - protected subs: Subscription[] = []; - - /** - * A boolean representing if div should start collapsed - */ - public isCollapsed = false; - - /** - * The FormComponent reference - */ - @ViewChild('formRef') private formRef: FormComponent; - - /** - * Initialize instance variables - * - * @param {ChangeDetectorRef} changeDetectorRef - * @param {CollectionDataService} collectionDataService - * @param {FormBuilderService} formBuilderService - * @param {SectionFormOperationsService} formOperationsService - * @param {FormService} formService - * @param {JsonPatchOperationsBuilder} operationsBuilder - * @param {SectionsService} sectionService - * @param {SubmissionService} submissionService - * @param {TranslateService} translateService - * @param {string} injectedCollectionId - * @param {SectionDataObject} injectedSectionData - * @param {string} injectedSubmissionId - */ - constructor(protected changeDetectorRef: ChangeDetectorRef, - protected collectionDataService: CollectionDataService, - protected formBuilderService: FormBuilderService, - protected formOperationsService: SectionFormOperationsService, - protected formService: FormService, - protected operationsBuilder: JsonPatchOperationsBuilder, - protected sectionService: SectionsService, - protected submissionService: SubmissionService, - protected translateService: TranslateService, - @Inject('collectionIdProvider') public injectedCollectionId: string, - @Inject('sectionDataProvider') public injectedSectionData: SectionDataObject, - @Inject('submissionIdProvider') public injectedSubmissionId: string) { - super(injectedCollectionId, injectedSectionData, injectedSubmissionId); - } - - /** - * Initialize all instance variables - */ - onSectionInit() { - this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionData.id); - this.subs.push( - this.sectionService.getSectionData(this.submissionId, this.sectionData.id, this.sectionData.sectionType) - .subscribe((ldnServicesSection: WorkspaceitemSectionNotifyServiceRequestItemDissemination) => { - console.log(ldnServicesSection); - }) - ); - } - - - - /** - * Method called when a form dfChange event is fired. - * Dispatch form operations based on changes. - */ - onChange(event: DynamicFormControlEvent) { - const path = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event); - const value = this.formOperationsService.getFieldValueFromChangeEvent(event); - if (value) { - this.operationsBuilder.add(this.pathCombiner.getPath(path), value.value.toString(), false, true); - this.sectionService.dispatchRemoveSectionErrors(this.submissionId, this.sectionData.id); - } else { - this.operationsBuilder.remove(this.pathCombiner.getPath(path)); - } - } - - /** - * Unsubscribe from all subscriptions - */ - onSectionDestroy() { - this.subs - .filter((subscription) => hasValue(subscription)) - .forEach((subscription) => subscription.unsubscribe()); - } - - protected getSectionStatus(): Observable { - return undefined; - } - -} diff --git a/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts new file mode 100644 index 00000000000..7b8d3096671 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts @@ -0,0 +1,122 @@ +import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; +import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { map, take } from 'rxjs/operators'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { MultipartPostRequest } from '../../../core/data/request.models'; +import { RestRequest } from '../../../core/data/rest-request.model'; +import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type'; +import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; +import { CreateData, CreateDataImpl } from '../../../core/data/base/create-data'; +import { PatchData, PatchDataImpl } from '../../../core/data/base/patch-data'; +import { ChangeAnalyzer } from '../../../core/data/change-analyzer'; +import { Operation } from 'fast-json-patch'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; + + +/** + * A service responsible for fetching/sending data from/to the REST API on the CoarNotifyConfig endpoint + */ +@Injectable() +@dataService(SUBMISSION_COAR_NOTIFY_CONFIG) +export class CoarNotifyConfigDataService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { + createData: CreateDataImpl; + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('submissioncoarnotifyconfigs', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, 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, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + } + + + create(object: SubmissionCoarNotifyConfig): Observable> { + return this.createData.create(object); + } + + patch(object: SubmissionCoarNotifyConfig, operations: Operation[]): Observable> { + return this.patchData.patch(object, operations); + } + + update(object: SubmissionCoarNotifyConfig): Observable> { + return this.patchData.update(object); + } + + commitUpdates(method?: RestRequestMethod): void { + return this.patchData.commitUpdates(method); + } + + createPatchFromCache(object: SubmissionCoarNotifyConfig): Observable { + return this.patchData.createPatchFromCache(object); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, serviceId: string, files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'submissioncoarnotifyconfigmodel', serviceId).toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + public SubmissionCoarNotifyConfigModelWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } + + private getInvocationFormData(files: File[]): FormData { + const form: FormData = new FormData(); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } +} diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts new file mode 100644 index 00000000000..c8904fdca3f --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts @@ -0,0 +1,74 @@ +export const REQUEST_REVIEW_DROPDOWN = { + element: { + container: 'custom-control custom-select pl-1', + control: 'custom-select', + label: 'custom-control-label pt-1' + } +}; + +export const REQUEST_ENDORSEMENT_DROPDOWN = { + element: { + container: 'custom-control custom-select pl-1', + control: 'custom-select', + label: 'custom-control-label pt-1' + } +}; + +export const REQUEST_INGEST_DROPDOWN = { + element: { + container: 'custom-control custom-select pl-1', + control: 'custom-select', + label: 'custom-control-label pt-1' + } +}; + +export const SECTION_COAR_FORM_LAYOUT = { + requestReview: REQUEST_REVIEW_DROPDOWN, + requestEndorsement: REQUEST_ENDORSEMENT_DROPDOWN, + requestIngest: REQUEST_INGEST_DROPDOWN +}; + +export const SECTION_COAR_FORM_MODEL = [ + { + id: 'requestReview', + label: 'submission.sections.license.request-review-label', + required: false, + value: '', + validators: { + required: null + }, + errorMessages: { + required: 'submission.sections.license.required', + notgranted: 'submission.sections.license.notgranted' + }, + type: 'SELECT', + }, + { + id: 'requestEndorsement', + label: 'submission.sections.license.request-endorsement-label', + required: false, + value: '', + validators: { + required: null + }, + errorMessages: { + required: 'submission.sections.license.required', + notgranted: 'submission.sections.license.notgranted' + }, + type: 'SELECT', + }, + { + id: 'requestIngest', + label: 'submission.sections.license.request-ingest-label', + required: false, + value: '', + validators: { + required: null + }, + errorMessages: { + required: 'submission.sections.license.required', + notgranted: 'submission.sections.license.notgranted' + }, + type: 'SELECT', + } +]; diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts new file mode 100644 index 00000000000..53e41783ced --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts @@ -0,0 +1,13 @@ +/** + * The resource type for Ldn-Services + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +import { ResourceType } from '../../../core/shared/resource-type'; + + +export const SUBMISSION_COAR_NOTIFY_CONFIG = new ResourceType('submissioncoarnotifyconfig'); + +export const COAR_NOTIFY_WORKSPACEITEM = new ResourceType('workspaceitem'); + diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify-workspaceitems-data-service.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify-workspaceitems-data-service.ts new file mode 100644 index 00000000000..dd287b096ac --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify-workspaceitems-data-service.ts @@ -0,0 +1,117 @@ +import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; +import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { map, take } from 'rxjs/operators'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { MultipartPostRequest } from '../../../core/data/request.models'; +import { RestRequest } from '../../../core/data/rest-request.model'; +import { COAR_NOTIFY_WORKSPACEITEM } from './section-coar-notify-service.resource-type'; +import { LdnService } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; + + +/** + * A service responsible for fetching/sending data from/to the REST API on the ldnservices endpoint + */ +@Injectable() +@dataService(COAR_NOTIFY_WORKSPACEITEM) +export class SectionCoarNotifyWorkspaceitemsDataService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { + createData: CreateDataImpl; + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, 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, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + } + + + create(object: LdnService): Observable> { + return this.createData.create(object); + } + + patch(object: LdnService, operations: Operation[]): Observable> { + return this.patchData.patch(object, operations); + } + + update(object: LdnService): Observable> { + return this.patchData.update(object); + } + + commitUpdates(method?: RestRequestMethod): void { + return this.patchData.commitUpdates(method); + } + + createPatchFromCache(object: LdnService): Observable { + return this.patchData.createPatchFromCache(object); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, serviceId: string, parameters: ldnServiceConstrain[], files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes', serviceId).toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(parameters, files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } + + private getInvocationFormData(constrain: ldnServiceConstrain[], files: File[]): FormData { + const form: FormData = new FormData(); + form.set('properties', JSON.stringify(constrain)); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } +} diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html new file mode 100644 index 00000000000..4d0d92c7148 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -0,0 +1,31 @@ +
+ + + +
diff --git a/src/app/submission/sections/ldn-service/ldn-service.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss similarity index 100% rename from src/app/submission/sections/ldn-service/ldn-service.component.html rename to src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts new file mode 100644 index 00000000000..c83479284ae --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SubmissionSectionCoarNotifyComponent } from './section-coar-notify.component'; + +describe('LdnServiceComponent', () => { + let component: SubmissionSectionCoarNotifyComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SubmissionSectionCoarNotifyComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SubmissionSectionCoarNotifyComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts new file mode 100644 index 00000000000..992eae0b527 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -0,0 +1,308 @@ +import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core'; +import { DynamicFormControlEvent, DynamicFormControlModel, DynamicFormLayout } from '@ng-dynamic-forms/core'; +import { Observable, Subscription } from 'rxjs'; +import { SectionModelComponent } from '../models/section.model'; +import { renderSectionFor } from '../sections-decorator'; +import { SectionsType } from '../sections-type'; +import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; +import { FormComponent } from '../../../shared/form/form.component'; +import { CollectionDataService } from '../../../core/data/collection-data.service'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { SectionFormOperationsService } from '../form/section-form-operations.service'; +import { FormService } from '../../../shared/form/form.service'; +import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; +import { SectionsService } from '../sections.service'; +import { SubmissionService } from '../../submission.service'; +import { TranslateService } from '@ngx-translate/core'; +import { SectionDataObject } from '../models/section-data.model'; + +import { hasValue, isNotEmpty } from '../../../shared/empty.util'; + +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { isLoading } from '../../../core/data/request-entry-state.model'; +import { LdnService } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { SECTION_COAR_FORM_LAYOUT, SECTION_COAR_FORM_MODEL } from './section-coar-notify-model'; +import { + CoarNotifyConfigDataService +} from './coar-notify-config-data.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; +import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object'; +import { UntypedFormGroup } from '@angular/forms'; +import { AlertType } from '../../../shared/alert/aletr-type'; + +export interface CoarNotifyDropdownSelector { + ldnService: LdnService; +} + +/** + * This component represents a section that contains the submission section-coar-notify form. + */ +@Component({ + selector: 'ds-submission-section-coar-notify', + templateUrl: './section-coar-notify.component.html', + styleUrls: ['./section-coar-notify.component.scss'] +}) +@renderSectionFor(SectionsType.CoarNotify) + +export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent { + + requestReview: LdnService; + requestEndorsement: LdnService; + requestIngest: LdnService; + + coarNotifyConfigRD$: Observable>>; + + ldnServicesRD$: Observable>>; + + selectedServiceValues: any[] = []; + + /** + * The AlertType enumeration + * @type {AlertType} + */ + public AlertTypeEnum = AlertType; + /** + * The form model + * @type {DynamicFormControlModel[]} + */ + public formModel: DynamicFormControlModel[]; + /** + * The form id + * @type {string} + */ + public formId: string; + /** + * The [[DynamicFormLayout]] object + * @type {DynamicFormLayout} + */ + public formLayout: DynamicFormLayout = SECTION_COAR_FORM_LAYOUT; + /** + * A FormGroup that combines all inputs + */ + formGroup: UntypedFormGroup; + /** + * A boolean representing if div should start collapsed + */ + public isCollapsed = false; + protected readonly AlertType = AlertType; + /** + * The [[JsonPatchOperationPathCombiner]] object + * @type {JsonPatchOperationPathCombiner} + */ + protected pathCombiner: JsonPatchOperationPathCombiner; + /** + * A map representing all field on their way to be removed + * @type {Map} + */ + protected fieldsOnTheirWayToBeRemoved: Map = new Map(); + /** + * The [FormFieldPreviousValueObject] object + * @type {FormFieldPreviousValueObject} + */ + protected previousValue: FormFieldPreviousValueObject = new FormFieldPreviousValueObject(); + /** + * Array to track all subscriptions and unsubscribe them onDestroy + * @type {Array} + */ + protected subs: Subscription[] = []; + protected readonly isLoading = isLoading; + /** + * The FormComponent reference + */ + @ViewChild('formRef') private formRef: FormComponent; + + /** + * Initialize instance variables + * + * @param {ChangeDetectorRef} changeDetectorRef + * @param ldnServicesService + * @param {CollectionDataService} collectionDataService + * @param {FormBuilderService} formBuilderService + * @param {SectionFormOperationsService} formOperationsService + * @param {FormService} formService + * @param {JsonPatchOperationsBuilder} operationsBuilder + * @param {SectionsService} sectionService + * @param {SubmissionService} submissionService + * @param {TranslateService} translateService + * @param {CoarNotifyConfigDataService} coarNotifyConfigDataService + * @param {string} injectedCollectionId + * @param {SectionDataObject} injectedSectionData + * @param {string} injectedSubmissionId + */ + constructor(protected changeDetectorRef: ChangeDetectorRef, + protected ldnServicesService: LdnServicesService, + protected collectionDataService: CollectionDataService, + protected formBuilderService: FormBuilderService, + protected formOperationsService: SectionFormOperationsService, + protected formService: FormService, + protected operationsBuilder: JsonPatchOperationsBuilder, + protected sectionService: SectionsService, + protected submissionService: SubmissionService, + protected translateService: TranslateService, + protected coarNotifyConfigDataService: CoarNotifyConfigDataService, + @Inject('collectionIdProvider') public injectedCollectionId: string, + @Inject('sectionDataProvider') public injectedSectionData: SectionDataObject, + @Inject('submissionIdProvider') public injectedSubmissionId: string) { + super(injectedCollectionId, injectedSectionData, injectedSubmissionId); + } + + /** + * Initialize all instance variables + */ + onSectionInit() { + this.formModel = this.formBuilderService.fromJSON(SECTION_COAR_FORM_MODEL); + this.setCoarNotifyConfig(); + this.fetchLdnServices(); + this.coarNotifyConfigRD$.subscribe(data => { + console.log(data); + }); + this.ldnServicesRD$.subscribe(data => { + console.log(data); + }); + this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionData.id); + } + + /** + * Method called when section is initialized + * Retriev available NotifyConfigs + */ + setCoarNotifyConfig() { + this.coarNotifyConfigRD$ = this.coarNotifyConfigDataService.findAll().pipe( + getFirstCompletedRemoteData()); + } + + /** + * Handle the customEvent (ex. drag-drop move event). + * The customEvent is stored inside event.$event + * @param event + */ + onCustomEvent(event: DynamicFormControlEvent) { + this.formOperationsService.dispatchOperationsFromEvent( + this.pathCombiner, + event, + this.previousValue, + null); + } + + /** + * Method called when a form dfChange event is fired. + * Dispatch form operations based on changes. + */ + onChange(event: DynamicFormControlEvent) { + const path = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event); + const value = this.formOperationsService.getFieldValueFromChangeEvent(event); + if (value) { + this.operationsBuilder.add(this.pathCombiner.getPath(path), value.value.toString(), false, true); + this.sectionService.dispatchRemoveSectionErrors(this.submissionId, this.sectionData.id); + } else { + this.operationsBuilder.remove(this.pathCombiner.getPath(path)); + } + } + + /** + * Method called when a form remove event is fired. + * Dispatch form operations based on changes. + * + * @param event + * the [[DynamicFormControlEvent]] emitted + */ + onRemove(event: DynamicFormControlEvent): void { + const fieldId = this.formBuilderService.getId(event.model); + const fieldIndex = this.formOperationsService.getArrayIndexFromEvent(event); + + // Keep track that this field will be removed + if (this.fieldsOnTheirWayToBeRemoved.has(fieldId)) { + const indexes = this.fieldsOnTheirWayToBeRemoved.get(fieldId); + indexes.push(fieldIndex); + this.fieldsOnTheirWayToBeRemoved.set(fieldId, indexes); + } else { + this.fieldsOnTheirWayToBeRemoved.set(fieldId, [fieldIndex]); + } + + this.formOperationsService.dispatchOperationsFromEvent( + this.pathCombiner, + event, + this.previousValue, + this.hasStoredValue(fieldId, fieldIndex)); + + } + + /** + * Check if the specified form field has already a value stored + * + * @param fieldId + * the section data retrieved from the serverù + * @param index + * the section data retrieved from the server + */ + hasStoredValue(fieldId, index): boolean { + if (isNotEmpty(this.sectionData.data)) { + return this.sectionData.data.hasOwnProperty(fieldId) && + isNotEmpty(this.sectionData.data[fieldId][index]) && + !this.isFieldToRemove(fieldId, index); + } else { + return false; + } + } + + /** + * Check if the specified field is on the way to be removed + * + * @param fieldId + * the section data retrieved from the serverù + * @param index + * the section data retrieved from the server + */ + isFieldToRemove(fieldId, index) { + return this.fieldsOnTheirWayToBeRemoved.has(fieldId) && this.fieldsOnTheirWayToBeRemoved.get(fieldId).includes(index); + } + + /** + * Method called when a form dfFocus event is fired. + * Initialize [FormFieldPreviousValueObject] instance. + * + * @param event + * the [[DynamicFormControlEvent]] emitted + */ + onFocus(event: DynamicFormControlEvent): void { + const value = this.formOperationsService.getFieldValueFromChangeEvent(event); + const path = this.formBuilderService.getPath(event.model); + if (this.formBuilderService.hasMappedGroupValue(event.model)) { + this.previousValue.path = path; + this.previousValue.value = this.formOperationsService.getQualdropValueMap(event); + } else if (isNotEmpty(value) && ((typeof value === 'object' && isNotEmpty(value.value)) || (typeof value === 'string'))) { + this.previousValue.path = path; + this.previousValue.value = value; + } + } + + /** + * Unsubscribe from all subscriptions + */ + onSectionDestroy() { + this.subs + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); + } + + /** + * Method called when section is initialized + * Retriev available NotifyConfigs + */ + fetchLdnServices() { + this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( + getFirstCompletedRemoteData() + ); + } + + protected getSectionStatus(): Observable { + return undefined; + } + + hasInboundPattern(service: any, patternType: string): boolean { + return service.notifyServiceInboundPatterns.some(pattern => pattern.pattern === patternType); + } +} diff --git a/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts b/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts new file mode 100644 index 00000000000..85374502bcf --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts @@ -0,0 +1,35 @@ +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize'; + +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { COAR_NOTIFY_WORKSPACEITEM } from "./section-coar-notify-service.resource-type"; + + +/** An CoarNotify and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class SubmissionCoarNotifyWorkspaceitemModel extends CacheableObject { + static type = COAR_NOTIFY_WORKSPACEITEM; + + @excludeFromEquals + @autoserialize + endorsement?: number[]; + + @deserializeAs('id') + review?: number[]; + + @autoserialize + ingest?: number[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts b/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts new file mode 100644 index 00000000000..04973f80c88 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts @@ -0,0 +1,39 @@ +import { ResourceType } from '../../../core/shared/resource-type'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize'; + +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type'; + + +/** A SubmissionCoarNotifyConfig and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class SubmissionCoarNotifyConfig extends CacheableObject { + static type = SUBMISSION_COAR_NOTIFY_CONFIG; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: string; + + @deserializeAs('id') + uuid: string; + + @autoserialize + patterns: string[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/submission/sections/sections-type.ts b/src/app/submission/sections/sections-type.ts index 40f6f85e0e4..5f71d1731d5 100644 --- a/src/app/submission/sections/sections-type.ts +++ b/src/app/submission/sections/sections-type.ts @@ -9,5 +9,5 @@ export enum SectionsType { SherpaPolicies = 'sherpaPolicy', Identifiers = 'identifiers', Collection = 'collection', - LdnService = 'ldn-service' + CoarNotify = 'coarnotify' } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 8f35bb4420c..f4f479e2045 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -67,7 +67,11 @@ import { } from './sections/sherpa-policies/metadata-information/metadata-information.component'; import { SectionFormOperationsService } from './sections/form/section-form-operations.service'; import {SubmissionSectionIdentifiersComponent} from './sections/identifiers/section-identifiers.component'; -import { LdnServiceComponent } from './sections/ldn-service/ldn-service.component'; +import { SubmissionSectionCoarNotifyComponent } from './sections/section-coar-notify/section-coar-notify.component'; +import { + CoarNotifyConfigDataService +} from './sections/section-coar-notify/coar-notify-config-data.service'; +import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -77,7 +81,7 @@ const ENTRY_COMPONENTS = [ SubmissionSectionCcLicensesComponent, SubmissionSectionAccessesComponent, SubmissionSectionSherpaPoliciesComponent, - LdnServiceComponent + SubmissionSectionCoarNotifyComponent ]; const DECLARATIONS = [ @@ -138,6 +142,8 @@ const DECLARATIONS = [ SubmissionAccessesConfigDataService, SectionAccessesService, SectionFormOperationsService, + CoarNotifyConfigDataService, + LdnServicesService ] }) diff --git a/src/app/submission/submission.service.ts b/src/app/submission/submission.service.ts index 9eb8cf110a5..7057f78c2f0 100644 --- a/src/app/submission/submission.service.ts +++ b/src/app/submission/submission.service.ts @@ -298,6 +298,7 @@ export class SubmissionService { sectionObject.id = sectionId; sectionObject.sectionType = sections[sectionId].sectionType; availableSections.push(sectionObject); + console.log(sectionObject); }); return availableSections; }), From 90652b62cef72fcfb7bc29d7b3abee2f943d3fcb Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 25 Oct 2023 21:41:11 +0200 Subject: [PATCH 106/592] CST-12174 Added filters for empty string patterns removal --- .../ldn-service-form/ldn-service-form.component.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 6b908cdae28..55fa1638c49 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -131,17 +131,11 @@ export class LdnServiceFormComponent implements OnInit { return; } - const values = this.formModel.value; - - const inboundPatternValue = this.formModel.get('inboundPattern').value; - const outboundPatternValue = this.formModel.get('outboundPattern').value; + this.formModel.value.notifyServiceInboundPatterns = this.formModel.value.notifyServiceInboundPatterns.filter((pattern: { pattern: string; }) => pattern.pattern !== ''); + this.formModel.value.notifyServiceOutboundPatterns = this.formModel.value.notifyServiceOutboundPatterns.filter((pattern: { pattern: string; }) => pattern.pattern !== ''); - if (inboundPatternValue === '') { - values.notifyServiceInboundPatterns = []; - } - if (outboundPatternValue === '') { - values.notifyServiceOutboundPatterns = []; - } + console.log(this.formModel.value); + const values = this.formModel.value; const ldnServiceData = this.ldnServicesService.create(values); From 12c60b7fad2da85e1e2039fd962a4471450f98a3 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 25 Oct 2023 21:44:41 +0200 Subject: [PATCH 107/592] CST-12174 Removed console log --- .../ldn-service-form/ldn-service-form.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 55fa1638c49..a2c4919a4dd 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -134,7 +134,6 @@ export class LdnServiceFormComponent implements OnInit { this.formModel.value.notifyServiceInboundPatterns = this.formModel.value.notifyServiceInboundPatterns.filter((pattern: { pattern: string; }) => pattern.pattern !== ''); this.formModel.value.notifyServiceOutboundPatterns = this.formModel.value.notifyServiceOutboundPatterns.filter((pattern: { pattern: string; }) => pattern.pattern !== ''); - console.log(this.formModel.value); const values = this.formModel.value; const ldnServiceData = this.ldnServicesService.create(values); From 0682b7b45f14d6ae215c2a4770ee088ef2ed5954 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 25 Oct 2023 23:03:24 +0200 Subject: [PATCH 108/592] CST-11045 Dynamically creating dropdowns based on the coarconfig --- .../section-coar-notify.component.html | 38 ++++--------- .../section-coar-notify.component.ts | 57 ++++++++++++------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html index 4d0d92c7148..c9d79293ac8 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -1,31 +1,15 @@
- - +
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts index 992eae0b527..726f5ec6c44 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -57,12 +57,11 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent ldnServicesRD$: Observable>>; - selectedServiceValues: any[] = []; - /** - * The AlertType enumeration - * @type {AlertType} - */ + patterns: string[] = []; + selectedServices: { [key: string]: LdnService } = {}; + patternsLoaded = false; + public AlertTypeEnum = AlertType; /** * The form model @@ -171,7 +170,15 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ setCoarNotifyConfig() { this.coarNotifyConfigRD$ = this.coarNotifyConfigDataService.findAll().pipe( - getFirstCompletedRemoteData()); + getFirstCompletedRemoteData() + ); + + this.coarNotifyConfigRD$.subscribe((data) => { + if (data.hasSucceeded) { + this.patterns = data.payload.page[0].patterns; + this.patternsLoaded = true; + } + }); } /** @@ -181,10 +188,10 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ onCustomEvent(event: DynamicFormControlEvent) { this.formOperationsService.dispatchOperationsFromEvent( - this.pathCombiner, - event, - this.previousValue, - null); + this.pathCombiner, + event, + this.previousValue, + null); } /** @@ -223,10 +230,10 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent } this.formOperationsService.dispatchOperationsFromEvent( - this.pathCombiner, - event, - this.previousValue, - this.hasStoredValue(fieldId, fieldIndex)); + this.pathCombiner, + event, + this.previousValue, + this.hasStoredValue(fieldId, fieldIndex)); } @@ -241,8 +248,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent hasStoredValue(fieldId, index): boolean { if (isNotEmpty(this.sectionData.data)) { return this.sectionData.data.hasOwnProperty(fieldId) && - isNotEmpty(this.sectionData.data[fieldId][index]) && - !this.isFieldToRemove(fieldId, index); + isNotEmpty(this.sectionData.data[fieldId][index]) && + !this.isFieldToRemove(fieldId, index); } else { return false; } @@ -284,8 +291,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ onSectionDestroy() { this.subs - .filter((subscription) => hasValue(subscription)) - .forEach((subscription) => subscription.unsubscribe()); + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); } /** @@ -293,9 +300,19 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent * Retriev available NotifyConfigs */ fetchLdnServices() { - this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( + this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( getFirstCompletedRemoteData() - ); + ); + + this.ldnServicesRD$.subscribe((data) => { + if (this.patternsLoaded) { + this.patterns.forEach((pattern) => { + this.selectedServices[pattern] = data.payload.page.find((service) => + this.hasInboundPattern(service, `Request ${pattern}`) + ); + }); + } + }); } protected getSectionStatus(): Observable { From 462aafb487431d6fca72b5d4eb883fece04a4834 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Thu, 26 Oct 2023 12:51:01 +0200 Subject: [PATCH 109/592] [CST-12044] feature: add translation for badge --- .../field-components/file-section/file-section.component.html | 2 +- src/assets/i18n/en.json5 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.html b/src/app/item-page/simple/field-components/file-section/file-section.component.html index 38b2905beaa..eee29603a54 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.html +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.html @@ -3,7 +3,7 @@
- Primary + {{ 'item.page.bitstreams.primary' | translate }} {{ dsoNameService.getName(file) }} ({{(file?.sizeBytes) | dsFileSize }}) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index ecbc43a6602..66f02b59e24 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2435,6 +2435,8 @@ "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.collapse": "Collapse", + + "item.page.bitstreams.primary": "Primary", "item.page.filesection.original.bundle": "Original bundle", From 5ed9f46096404e50e20a9c096d3f4c3225a95bbc Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Thu, 26 Oct 2023 18:47:25 +0200 Subject: [PATCH 110/592] CST-11045 Improved css and remove console log and interpolation, added small notify regarding service compatibility --- .../ldn-services-data.service.ts | 4 ++ .../form/submission-form.component.html | 5 --- .../section-container.component.html | 2 +- .../section-coar-notify.component.html | 42 ++++++++++++------ .../section-coar-notify.component.scss | 15 +++++++ .../section-coar-notify.component.ts | 38 ++++++++++++++-- src/assets/i18n/en.json5 | 2 + src/assets/images/notify_logo.png | Bin 0 -> 19269 bytes 8 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 src/assets/images/notify_logo.png diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index cdd259447a1..5ffab2000ba 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -84,6 +84,10 @@ export class LdnServicesService extends IdentifiableDataService impl return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + /*findByPattern(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.find + }*/ + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { return this.deleteData.delete(objectId, copyVirtualMetadata); } diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index c79364e2afb..8fa1760d8fc 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,7 +1,6 @@
-

ds-submission-upload-files

@@ -10,7 +9,6 @@
-

ds-submission-form-collection

-

ds-submission-form-section-add

@@ -32,7 +29,6 @@
-

ds-submission-section-container

@@ -44,7 +40,6 @@
diff --git a/src/app/submission/sections/container/section-container.component.html b/src/app/submission/sections/container/section-container.component.html index f39ba72ffab..99bcec168f2 100644 --- a/src/app/submission/sections/container/section-container.component.html +++ b/src/app/submission/sections/container/section-container.component.html @@ -42,7 +42,7 @@
-
aaaaaaaaa +
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html index c9d79293ac8..75318b937f6 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -1,15 +1,29 @@ -
- - +
+ +
+ +
+ + {{selectedServices[pattern]?.name}} +
+ +
+
+ Select a service for {{ pattern }} of this item + + Coar-Notify-Pattern + + The selected service is compatible with the item according to its current status. {{ selectedServices[pattern].name }}: {{ selectedServices[pattern].description }} + + + {{ 'ldn-new-service.form.label.addPattern' | translate }} +
+
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss index e69de29bb2d..c06ef5951c9 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss @@ -0,0 +1,15 @@ +.add-pattern-link { + color: #0048ff; + cursor: pointer; +} +.ds-alert-coar{ + position: relative +} + +.coar-img-submission{ + position: absolute; top: 0; left: 0; width: 50px; height: 50px; +} + +.ds-alert-box{ + +} diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts index 726f5ec6c44..39c8c9753d4 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -61,6 +61,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent patterns: string[] = []; selectedServices: { [key: string]: LdnService } = {}; patternsLoaded = false; + selectedService: any; + public AlertTypeEnum = AlertType; /** @@ -181,6 +183,18 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent }); } + + addService() { + this.patterns.push(''); + } + + + removeService(index: number) { + if (index >= 0 && index < this.patterns.length) { + this.patterns.splice(index, 1); + } + } + /** * Handle the customEvent (ex. drag-drop move event). * The customEvent is stored inside event.$event @@ -301,25 +315,43 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ fetchLdnServices() { this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( - getFirstCompletedRemoteData() + getFirstCompletedRemoteData() ); this.ldnServicesRD$.subscribe((data) => { if (this.patternsLoaded) { this.patterns.forEach((pattern) => { this.selectedServices[pattern] = data.payload.page.find((service) => - this.hasInboundPattern(service, `Request ${pattern}`) + this.hasInboundPattern(service, pattern) ); + + //console.log('Pattern:', pattern); + //console.log('Service:', this.selectedServices[pattern]); + + if (this.selectedServices[pattern]) { + //console.log('Name:', this.selectedServices[pattern].name); + //console.log('Description:', this.selectedServices[pattern].description); + } }); } }); } + protected getSectionStatus(): Observable { return undefined; } hasInboundPattern(service: any, patternType: string): boolean { - return service.notifyServiceInboundPatterns.some(pattern => pattern.pattern === patternType); + //console.log('Pattern Type:', patternType); + //console.log('Inbound Patterns in Service:', service.notifyServiceInboundPatterns); + + const hasPattern = service.notifyServiceInboundPatterns.some((pattern: { pattern: string; }) => { + //console.log('Checking Pattern:', pattern.pattern); + return pattern.pattern === patternType; + }); + + //console.log('Has Inbound Pattern:', hasPattern); + return hasPattern; } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 40f01500221..58453db5188 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1982,6 +1982,8 @@ "info.coar-notify.breadcrumbs": "Notify Support", + "submission.sections.notify.info": "The selected service is compatible with the item according to its current status. {{ service.name }}: {{ service.description }}", + "info.feedback.head": "Feedback", "info.feedback.title": "Feedback", diff --git a/src/assets/images/notify_logo.png b/src/assets/images/notify_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0350c641df9cb51c2c6a81c0a6badb96adcd5c87 GIT binary patch literal 19269 zcmZU*Wn5I>7cV@3AcBDNlaNMGM5K{UB^BxJl5TM56orvAkd&5ghoMtaQehanOBlMF zyT|{%&zt9kADpw#uC>-)>$_r~4{9n3Bt$es5D0|ig`%tm1abojf#4Jp5`ZU{0iJ)r zpIfeq`W_Gn7Yp_uj(3ifCj`O-c_I5u%X?yDT3LhTMV;V=f|EeF7yj=j!D*IZ_WrNq z5466->8Ksx#%Od9L>Pp$%MLU5Csvnd`?L`m6wifH{H1-TDQEqh^(>k&7Q@%ZS1*cF ztMG2gE&P13q{9LVriG|I3L3`8{s$GUMhyN0PeAQ)u+PPwb7CLcE97IFr8fz|k|B_M z`b=tz#BO)>+;y1mr6BrsW@-ZfeC{BZy|%D74PeucZ@#!#l7~JId{eAoV2 zDA<(w(`sjQVJY*%)Mr_+SNB`Uj1U6EfEzgi5p&S_GA%0+2`hO5I`rH}y$w?*49pIU z&6OC_hYNw2dA&3E4Y8}8hmDQ98geMyfI!A7 zn%8i(o=+dg3;1CJ%*8J~yUFvt;$fZMSTfF~`Kgh(cS+>)L35;{zosy-*A=i=AHvG@IW}f47+_3`H6b#ilK`Q@%^Wy< z7rE=kgCVQ}YZ1&q>Tw+4qJD$*$H47mH`byj)=a-mMg8lv{?0&6ra*AmSeEW@w1IB~ z{0ML?70Us==;d%V)x|ruBjYBrMo;Ll>le+WM7?6aef>-oHS>&o{sDOHN%_Sc`v)U` z&SKNLBhC!4Pk1zm*R6_)e|U%_!btzk;tpoH8>(+}531nHEarE=7*JI&8H|r-$2u5v zD2wKh!9IDLWS~Z7Y5cKKss27-MMJt8F}pJl=74!YOZBx2H*;7WAktg_htxYFC4R3h z<^^e&r=7FhD$Xna8qWJrZ|%j%LUe|sVBp1;*rWn{im%po{n>i)@`ww6tN@XK1-kHS z5*K2`Zx|>Gps?q2)+U!y>!ZHGyK(IDXRW}mFZu@GFklJ6)qv8;zI7S9lDDl>Ww5;6 z0YuR1GefVvrzd-S``<(uussP0V`=yJ^&&9w4h48a(ZJcW@R8yX^TI13(92&bAAclE zSlAS^h8@-g3~SKWGw+Z`)CqWpZKdE%gvH2&c$+-h0JJ!XP$MqP&Lehp2AvyX!H+ga zx*7M^x0u1k62N>o@eF&UPR7^;QGw}X45@bTtoOj|4NQOvwiw)RKpR4~AN}t~pcyx( zCfF+z=vhauwXt?)l`2W+SYzb$Ipr!n6`WqbSM!*KF zh-#@qAX;7xl+f@sjBryk=G0hLT)zD&^9neE`!rQBsivtLnA-mRgF{CeXe@Z>HSnKc z=D(8=cZ@TK`m9y0D?AZq0@N{P_MC*ML#CDiE3qgUBHWe7 zx5p-T%cP>=L1fmcc0}4$;{!)#=p==9HcwjHfa!t7h%};A+A|Ru-4Uu7W{b+c3M#CO zw0MD)FIM(sMe$%9@}O=)iLim{-vgJGQ@gVj=R6ps=amf)#wd5(Oel zqdq+FkAjpB=IxL~`${CqXYO7y97xq7U)9|Me-+D`waDEmbJ>l&G5{A07jv7hXQ&N+ zc`I%DzjX3E zLcQIaeyxI^e|jZ+g96f#a1yUsZCN9eZ&Oo^`^U$E7c`Op z1ngE>3+E&`)f>=w3ns#jJm~iG7WwJ=MECVv)-Y83`&cDb&*@+Oak~~*TDJ0R+LN50 zcB0~9BdqbHXl#2;SL*nFL=wR;yv8Jom4Q{7-^h8#=8{IP8-Y4ks9W34u`*APs!{L; zhSBfsch0JP57}?rcUb{O1M7nouED5N3_lC1q~Dx$rK~qBtfi6*7VJBGUN2lrod@w6 z!HQpgqFu2R{+E?+Pax4F>t1BTX3fuXFK6syAD zqeFswja)dU{|@0Zd|VTtw>#OKI1Q}K9{1m_gZUd$%n*Et2I&^xZwIrEAdy2HaZ|rKSx{U-3!=+L99DIbU9<3C3jW{irRCwL?#{lIUJE zO_E=f&`f<3nyX83SqKNlg(kNyn6XCp0fX&loo2r@f(FJXM?<7piM6m)A{3rLJW)cK z*!ljb(+z{cq0e&O zaVe_WNJKZ7pyRYX9J%At(78PrP=(&5SzSm6B8OvV!0R9DaiiOW{f1QZ*#=Pq74%vK z(G%=zUv_%ASU8x=*eBXmaW&Mo?^Mk{qF-mQ-}TKofAGliFzM%F*~EcQNBX`waqr_I zcNK=tb+Xc?M2g3#x9cax#NKVgf_asATF(GORq#f#X__u(H8#03OoY(q6@g=#;SSA> zTY67DkAq<~A&V0;Ef~F3^NwYL!B6J73A3V`$;}sxKqg7~-2k+Rj>9dn)AFmGkM$>a ze6~pk7FTV@sQ~)#M(2#hK66 zia$V-;l_8XGVNAXh6$R)FIT{B)x5tmYt*Vr=sj0aAZv8O#kSNBsw5N|XpXLbrcgem zVJmP?l3>IYSX$vkn506$I=q~g%)S(-_GSIe7?xOR%y^ehvzT!dtEIv{c9&^tp5f%m zeb@f&Sr~Pcovc55MPpHzqU!88y?cXvim!T!6+9f+-J13a;V5S5nRc7Ywoxm6zzEL8 zJNCN|LnuFGe-S6bXYoTs^a zj})NjZLtu2>eb=A&w!`Q6c7i~<Z2TQ6u$rAc;$e^RMqyOuX?(ubBgDoPO5n(<@O$PjW21*M1_$e zvUoIbYpwU$LgXl=`h%H$D!ec|)YF}pn36J!Mkkd5Dg1>HBfOBduz*gIwjZBF)ABY+ zV*ONScg0wk(}uh~uPhw>9_>sd*XvnQ9{?Q%e2ygsK02`H*)ms-W0nQSj@jc%*~TKb zVg~yFptIWuN|$QDDf8L)(8}*Hq&jdrg9MTOAZ5S$K{hnHA3U#V-@D&3cj{p9MJU9a z5Si=@0Ohue{>d0nE>zhcsP9t%{c0NHH~BEu?|8`j=%8ry9@OnzJdNa;uJ(pdMzmNn z1Mr%5lcg-a9#8J;1rY3>G+w**zug@y+i!R_I_8B}LYPUpYXct%-2FPtB|Cfjw#ILP zfU81_kgfx3FWPPILWOt+_R9KOEv#*!m$oZ1DJFUvCOP{%JkdUbL+LPmqI2=w%ZJFt z`w_;U^Ps#G-%4LMtsFBdNO%?o!UcX7v=)0bEc)fPeV)nFMQ)s*3+s>}eeJ4rwnoo2 z$ptC{y;To@bDiYNJqfP|W_IF1ZbA3d{>@YMwwMtU-@B(D&lc7?g6HaUC)T&4`OgMj;B_Q=ai76U*BLhRU+xkzlg)w|Cw;6{= zZFw+L3ZK$U6Kb_~7nZCGt8`eBa`2amM}K=Vf^#L)+u`}7|F(FfMS;p)h6PEfO8T5& zhlYE~sMU*IZ@&@;KOpAljD}y+$;X#A6_fN6gXoJZtJp5lbY;JabLFN1mO(Yledd^i z)Yp4LE>=FYeWEttP>UzR7+4l!*>L|0L6b>-V_v9+pSa*xDbtJ6MK31eiQK%cK(h6= z3SnlmI$;hDRvzu7y3Alb8FW{nXg0O_YpB@45`TJ|gmb)U(*M z%b{**yJ%82J@jckhtSO;BUO8QE3i#E`A;)P&x4VrCUG@R_Jt*fe&6kum!$Ifl!&|a z>gPA5Jc%52Cn|Qt(PRBw!zt~v%oacdxmgy5hT2_TSvJn?`vU~5)6n^cb<1YJQi#lS z^pajx34Ogjaw3T=J`bA&tQC?P)`W=0j{Jbno1yjXJK~ZIsHyuz8?{(Ao7LYj;g%ex zZmt)!lg*5!(?!S&kK#*r#vs$3fYI(M3G||o#39NH)=C!7R?tIuk1=TYcsAD~Z{hNo8s zLOZ8cDZQ;jgI6rfTi{?7Za+*R-0n1VT)YYkyyDv|K9|rb`#Cz|8jV?hlZ1JZudN9T zfGdFfEDP6>3k8w-`jZ|eAwuunWT!;Q$9;)fAAW4k9X;UHnap@P`IpNvA5oai=CY&y$wk*%l*$mNr_}TEC238 zHlx8Du9IPJJSj`=h?aut0;;dL-~Z4y+Z2pEu)DRu%JBJ`FA)|-+tfwhWgSmy%FUa* zWwpnkF@AH=j&f;}W^}l|R4G$OnGn&S|D7x=Q|43ZAOPo8lLX1qkXD1CjpA!rgx8;` z2aB=XUE{j6zUj1p{218!9`MzG^Hm#JEfhHs3766#{4EIM-UTtjsL>LMZ!gzg33&(A zzdCo<5nXsX&BpM@l(W$EzY!ATcuJ z^?TDfWeF4N9D~kf!cB~T9KgL--cG%~^66Y;rTacB6=flUIXr%wL%wr3blJyRwq}JH zUeW125-)80cEZ=#*+@~A-Fu?qI(jyHeV+clx;(n3QMlI5W#MK{iAa}Z!;{s=%%nwk zo`3gPnk9Wva+&Ojk7N5%_|FONs>M?~k-PDtHoj}touLi==RuKw+Cz~pU1R6!?^Iz% z3%-XlW>4O$rB@w@rY%g)aaq)h#a%rqvGq}%jJ5R0H2HerG5(p=;oD6m8%9$n@A8QB z*@?$9uS(V%KbVABg=r(HmCM z>&?DI^x6A@!DWqsz=JziK)EKy&pEL)Oh#@J=#@nmB_!ok4sev@0q&Nd%3gMDH9K6u z_w!v-8^9B{x+)zBp-ynHPLLjk$|VtsF6{evY_+F-w25|egtniAfA`#yq36t~-40Sd znj`m42gr&v1TFaZ&h;hlkul24XJYNY#Xb{Mkj-Jv`f%=?ZR+{vF6CgokF3AR>KM0X zbIF4?AZ>Fc+f?>nIVj#X$H1k2qSi&niiX0Ck}dqV%Tb-04U22k(z(f3GeTZO7kWgM z;!D#Ddarqt36X)~oeT=H&0*Y^>y3zb4R0@xPBVk*DaC zxLqaowtf6eoex7eNeUHW1cz=W6;7Iy_s0r*Z@Qc}*8hOK{;P6+$`FE9iGsD(yR>wv zmziM#KUnMzI(?IuXscg!JFK789lo3t%^X~Hie1!HE{0hjN^(CdIcR)SEF`m&Vy2$2 z{TawMwOpnP0wq-Gw< z(_X8G`h7Up2~`ldv@m$Gb+IfKUsJBI1gSt}MEe#kzY@UpCSY=9~qIcd%7vg_Rko|&x?ENiMyTf`L z^WpEthyzzY%PkDNM&&rjMqOObxyx7JoAYqv5^TKQCeO{ug$MIZLH%Yyb&lWE;F@^j z%nnDTPcih{M!EFGsHZxfOPzeWPHt++^=0$5zW0*}_+;gku*SnHH^NF9pNk^4e%A9P z9;cC2_}IFZYp@ZJ{L^G1f0$eIJ>?ksUGA96z`FZCHe9_*DYIXw3T^mbG%|Ml*R%-t zo{28Kd?~y`cL$`e8aD1Ye5guow4G(|J$Kej0T5Uq%v#&p-suWgN`)$yY~5M}Xu?&y zOP^(zS`h&2KO68v9`f$dcKP^6IYtR7;sDYgsDO{Zh>iz zvgE~5zZ)2C!cRmZAmKkXWe>pdi5VHd9ZT!59f~}=X{ZZqpL4kB3q<9Cl1L|TDpJ*m zt5yLTM%nXV4Vd!#rE}=+?>Wn3ayi~h5Cf#edmc=m?^Ay0;Ctzh;piJ;Z@a`|3<4&v z=bU4uu^=tx89D{jScU!M2>zUttaS}vAH3HT3$LOva8ar^ zWcd3*V=RZ-_C_YXp*y=MZ`bp{Tg046;VT z0V`U6$|CheTMo#_7VupOz zoG5cCAengUJ3a!2%dMx(D*X0C|KpUQgbiu7-pj*GT<%qN<}iDT#`Bs>UDddSbU;$! zo3`&j;$oxEME2E9go;?W83rgvu88TV0nHXzd{Yejk;ZoR*avs^ZruEIa;8+^N-ZAL z?pM4^xZh_mlf=c=@kN^0_CK&cwEAmuM+qgIQDa%`!3mVD%+?d!yIAG&lBiQIv!a1| z0j%jP4dMG3e|8AM06ygW@BJ#KZ$3VT^2Wd`a*Up=t-W>Wd{j1mAp9Z&|7iqBz{P;v zq)-miDahnR!P`Ju`SNLSq+Yu~dXr6Oc`NcH)d%M$hw8gnd>Shs^Gc#}9(4&HWAzy*corm%TSuRfr+zPq>A4XX%;}8WFjuVPAL_ zdcs?2bx%B^d;^uBOZxw60r>EZ29;c94N8SQ*Kw5hg^VFNzNA%0FnoxbmtF3Z9bWPo z2Fx&}lW~abu;nw2VqI15v%eOIpigZU^aS&=fGFp!DhSYx{4TSavKK&V!mKX#I&Ak6 z1CN1#qY-}f9=OU6K+4UVv?>NWu%$?>RT^_vBQPXZ%^#`e(NbCY!@g@MyktdX&it4J zfhuyjn~?SVRJ-~#yposEe}*u-YUH*Y{2)DeltozO3sTbgnMN49!$L}19FW;#2j0OS zU^v!^AQ@Z+m(Hd9VS!+!qcJ?vhagB=hmDCl;4k3>CwKFrKsq;5h8UZA&#wZR|GZ#v zh#Fovb=8_bZ?d>(C1eCFbzKaeHGr-K8DI9|RDHiR%Isfb=J@$sAk*7sB70#i!VFO} zuZ>pkBz-K61X)Xy|2Yqp*xm6eBq3La?&If!gdS=TybWA@qhusL1RI^~cY5UxY{yCr z$G?6}0HvYPNnoCr@sqiNn&IRbXFxDq{D7Zch=k>fflReUAu*&-H6P#S9X4_ z3ug;UonNpSNBdu|IBnBH;rHaQ?vfE`moWzEOzCMr=vt82O@IrJVha+m)gQwD3PDiO z$p$U0;4A@Hm4qQO0jLXvolknMM*Oi_f_EHd(8DzgRkd}pNM8RY{uvrP& z4TbjINDro=>zT=)+kRJ=0P^`!56IEQD&SQgJvGRCH)4BK+;A(V-5Xx_ip?f0B+Vu) zCCwh=$ly@mzPg$(8l{1{(L(nR1V|7KAju3I-(Yxk!WVTGfX#eXw8a8a(dE>6+$P6) zsM2sn99`L0RN22$vq4TA`zE{*U?PwtXW__Cs*Eb9?{KWoewE^L2g*3C3znD%uZdy) zn`}@;2!ZrJKrQ4BQKY^R z1oE5idC5v`v{u~d>7ce(BM9tlo)rClBUYtlmYixAUT5$X#O?gl-{~cxm6|Nole6po%YD^lK6m-uG4#{q zsh2!@V)c!zkvwmxQpIWYAi_j+(DPySO(s?KX8lr-W#KFRE#gfbwAr2<3If6ITN9)_?g?_fwc+z&M;KtT3QN3^U5`MC*M&%e__6OvhhT$h(gq7^P-7#66 z?Z)hdw;_(1+BdvSK*2lvygzfJA2ibn&>qRy12dka~({h0X- zSkXp0Yn#T0oC+IaQ(s;4i3M5uPiiCmtJIu7gPo`r%{IQ8G{b{n#P)0J5N>}1mk>+C z9Go)`P=!@_AQ2s%@_P)W(yDVhQD?UKtlhjYOSUF=UM+um$=xrNN@ zg_Kuia*cg3if1sH%uL>f+G`I7kn>lrC_7#Ny74eeijlm`j`>Yw0&1H$_q^FVtAWm* zD&~af^@a=%mBcDdLfwE2hQ+YW0>Y=QN*Ar!z2RnN_(qz;bJyxLq|IZK1A*A9rs^o> zMAAdd8Y?8vjuo7Nu9%u%@_T16vS%byv^)GnlkuedN!KSX?`Cr63#he?KtDH7Gy~`* zNcrd3_yZRw$2!K-jhfB-%u;|dAmpG6vcb8~-TJgKplU2X?k?iA0lqdyW_=Xye?u+@ z^}%<+G4olilWq>|0xYTZ6h4J!>c9??b;z$$!_;pCZp7Ca%zj!YpL(zFM9zPJ&0xwH z<3M_+um9p+p3z&|?Q%UYu|GLnSdu5YjCktNuSv(A4WyNMVb;9%zUdh_r(N+Hkd}J- z#Lb3Xw{?B;dcjq*4fr0z^OC*kyy+`%tmFxkN6!lIBTX3DqF5}xKk{ztf+rGHLFT4G zLMOef7NG2&y&W*o-r<|p`rEKpmD{#Xr8jp{8AM)&t zf0!JSnNiNyE;Swb&*zN|t<%D=kA&>`)O4R@@O7Ly7qSyyRt-_VQ zjBTqJQu#w|9}^D#IC@@=583`Rj899ASQ(17REV=8MD{Fxcqb%WC?%X2CLK8fkjWf< zdV(DbgN_%akE6u_a2TfcE66i-M4UH0YZ@x=F4#!4R^6%`TauQzVF=k_VK~7w6Mng; z7ot`~Cu2MpUAjP;GT|CRX~;B&8@w&HCsMmNhD`laqg_iK&x)F8#73l_xq7nkpeW((BoJ#a=>TTHDdA9=Z&y_yqd#tXPudorg4iPFdx9p97}5i z-YWtJCzw0nfV%cz3?{WVo;k_Esl$w#C*!qcXK$>3PT5$K>`eG-V86S!C z1hTdQ-OYG3_D(DA&G$!R6|p6Oqb>B1rZ>Mqy68l& z<4DuKi7P2xkgRGqj0<71;NDc}uO48I-J?DR!V|#faMyk_ED|QRQWs1S#S)up(Y-UJ zWl9XWLJi}W^;l6(=E(eF1xuR)2c$7>GjSa^{!^9YRmP+I{Os~6Tu54Ka>qr#UR7!* zG3>Y!>%g+5?0n%GtMfC4e7$#LBmB|x6mKa%|1J-Pgv@f8Wd{W68Q)Q0QuiG z3ik8R#{c4@KOlMq>jc}69@7FNf^%uZ3bn*HJBZ10~6Z0;BkbkA#=}LhH=gUIj8jrMTt47>LgsMX|<$a+`Z{=BK8q z9Rxv;lMVR7vq5v2E=2ez1;x|2pPplEnP|^~)5-u3;}%-H;LGmS0`yC~aQMk6aE(eA zpKb#m2E@2}Z3oW!m*oldJj4(NrtRu?i;dj0Fw0(g^L$#461rO??$-f8W?s# z-A2kSFER`8-Es8BdD;Y11()}E`iCTYG9Ht`inm_|05<&vj=`SH*d-)`s()g4=YE8A zk@~h!TLjphi8OoyZgXCAnQSpwTD{ z@h&ruv22`@BGWvVwEi8J*X=>gLBWi|b*F*QDYV);8Aks15O4Z))-xOJZaM;=Q zt?oBHAZkaz058;4i9O36Pl{Kk)Gh7Y3~grJi13cHet_HJXRHuNHWjOJ|8N7SXhe6m zPvX$TPW5pYVl zl6jOcAg)F&hH@dDSp5^V>|+xn2vO?cH9JW(Y&`*KpnE>3@BqcbDKk(iD@_XI3V!m@ zhoAAeL=Gb`r=!qazm@(eC8fK-%Sn&j??zm`cDBqmvbG~JhHZdK*zRX{op=0*+PDQi z`nnF_wNSZ#EBV_0`QqSXRl+mPw5ad2-KsEZ2l}v;5$W4igI3 zz61yPo=alW{$g&2)7k;2ycpB%k~c?I(Bhlgh1i4(_sr={<(@f}^FQaz*qWfO-UNa6 z+w=<~-=B?WcPf+H|6f|9S%#lv-*x4#LBi*{#hmpM7gf?^rzR3yLCsEt^c-VfZe^Ly?|}ZNMK1)>nFi zdsxBRx^*M-j3?=9q-rQ3bHpM8=ymOjLw#RDTCnhSd#N@-3AV~w*zoPi%GGk*@Pj7VF7~EsN{RAi}O}xn_SpwXHCA^d1vlOJNvwRlzFE>8rkh7AS$v z5PfHGb`R3yN)H8lFVIC&#Syg!^<}uYfcg_&imzD7d9>g{r73)#kFQ3b=Dpe3$OUi#+r8O_QA7j)BYd8KpK{W-DEq`xJ`BooF00&am z<5q<(XD(Zu62VOY_c1`^p!R4<#=2ir34cQAi*@93xySL>ulQOZYLTDac6;(EOwVg& z0Q7XBu|@-kCj8`7ATbBu5X!=Hjk;IAb3%aPOXC<(&5~?c(*gLnRwPb(Ww& z7AWlpArNqfgLX6uFb9-2IVBv_4`wBD>Ude|-qd~oLM#NTO`bNT#E`jqcOz@`leOcO z@`D{a-sC7_N-c2ZA%li|dg@c9l?Y_#a=i}f3gFSD?U2Fl3)7x4r!RlxV}g)(Zer%=#P zl|4Js`+cyJ3$G9y3Q)%EP|C9K7$JDbcP=scCf$1DnH3N>P-Sb{COwdEzD`cv-QM;Am9KCkyL^TRRAkV!t2b0fTLPr0tr5TA@{S4 z&q2o}axtn6F5I6H+c%U&2?#X;d`VAhP%hu1(V2v_;pT)+g=Jcj*0cO$lX8LHNq}|# z#L0i{I?eTrP#fxle(mJUn_mGJ*Z*?03DS!epZSthlRkkM#!tFeW^=|p5RQa5-afP5 zc$3EkWS3q7C^4CEZBsmH?VPN6)g%FjVFWUa`rubUa?(vCkj{JpSlWRAM9bJ2fgBk6 z+=>L@W=~l<;m&eUshSb90)m6x=F>@ZUQ!JnfaxJ_)|=yz{hRN`dNZUzlwiV6B^AVq zM3Yy?@;OnkIhe@Nes&vCOI6Ooye^n+^C28SG2nt)|E2=b7K>NUO0c?VXT!a!4eX#Sd2B=&6z(5`A*aU; zzz*j;l0V!;Vh{8B<2FGgy-q*_Gd~hCmNR92;IF7en1BWfF;iMR4rmILb_~C!3O%}{ z*F9IK6G4TOzp^?Yyyw>f>fMjEf5{|=+{8|~Zl7kEO&&R0=NabY3nZNFnKQp%yvf@{ zYp>-UHTS=7a!ax5pdTp3B$;~p0>X_n2OJQj{HE`BG^Fv<>Ndaav8Jq%SZcu&a0YdU zUjbAxR9%V>VdtixXzl?bd3@DYne9$$8MzDM3n^bFfa!sKbs)*i)+YYCCu0L%9m@v< z7BRM<^Q83YgXl7)82}+e#-*`ISWSo{kb)c|>|)*jbZ8GvtTM}jB*L0R=wiEY!z0=4 zCK8~Sb;o48dQh+@8IboVR2>^zeU*-=tlUv9P+1MJyb10~;lSee|C6m}a@H9H+CQZl zi0r4)jnl@H-QrWaP6{%+TzXV8Pz8u@Qt(0gnSMnv>djgLh?#?X$}a!KK+OW+rl_?V z2@sDezM#4T_12TPXIyG@K0TP z!PQfKJw(zY9P(e>$mO~{+_3K9&}=w$h(=Z!D{78V~?&}Nb z7%&!>dwL0y3c6V4H9xOpH$HE-((kW`T*@ElCxyH)U*KwI;!DSo+t* zMNJE(P@E>Z1Rysis#={TB-Y(u0hW59X3Gu@zoJ!S>p018c@CV9D<#E?DwCJ@)mD0kaj0npl0V>&aOK=9HM zII0dH7%w7NI%9)#`ITm*b)X}h$Cp+6SN-HUym_@Ov;ZrmC*+>GAYee z9q#RR(>6{yu3KEpDzv^F>CA({f~#i?i$*p|xc3r9I%U>9y1@bH)-MCKgwgP8;O?1E zaFz>#d`>+G^2)Wl{OMZ`8|30QE*0uON!*lchf$Q(0-Io3eT>WW#L_sU%zPN^u8OAa z?t+6PNV}8H>kuJw)lmbY_9t$B5&pyt1N>5+3Q*pXp~LuixdE1+dx{wx5%Cy@F=4RO zdJp3}(2k8ytFA@vz1d*eZMj6)x~rUQJI|t1O^RAg)qkxz$*C}UXwdg#ob3X?^+;lvXOP5 zv0&?dC&}i2rDd0umVd>WB^&&e?E`Th@`Wlgw#i?9Ck`eMj@5uW45Yx-*HbXRu3mE?k;)=dR704V%le7z5*V1P%M34lhUX@cdCrvtVna;7_KL9 zi>H7o%Wb$$*c+e7xT$al3RD6$UVhh8%Xy*3-Q4Vh!^hM2W)*nb7P&4(V&PqkBymF; zMT-Ygu`CNbmp*jQi;wGG9?rQ7IgKgzb3^|CaakPOA%Lvai7A;f&g^nF-m%A7rVdwg zNC_a029}5hs0X9m=f4QlxA*DX15Vag^amYBHJ?6mOq3^5r+v*G;fhIsSu5m@>kXQ_ z`Mp0zHezweJ>^nkcj;S}KiquByusB|u`qyPET^T1fn8-?ljGg*j=In87bBQcg8?qH zp!kDJU(Y4Y3vKD^-HutX*4nX)Ku2fY-zMalG}6?ae;RJmPUgl_Mt@fm|9#J{c2G@K zO+B4f*kc9Jc9jRNMH!{a^UCaLo}KM1G&4Hw90#cJFtB}sSnqe%1+xN+6#dyVu72dM zR-Yz0zfH3B`tOAGS5%OP(OnE}Td0&b$X^E0YFPF9!B_nqp&EsavcBgDMel4+j-I$0 zD=<+u#l*G%jQti~d!eHWf>+H#udCatOFR7Xr0qztfXEs0^6YjEF=AC{zNui55Dv)L zPp@dK(7x^amgu%@ilkxZmoxXI68t#3Vq*W8p8#S@Tjubz-hJM)M-FwGHoIlMQeo%UKJuu@cie(-_r&`aNNx5I!lqt)EfTR$b(p)8NizaM?}mHXi&m&fAi0D&gDa zl!iWlNTqLgrIR}A=BE1`LuK>vcfLMNkuUGaoeEDSo%P!^4u5oL1vq6DND$Q)HGK@i z77o)8{7lLg3|^55VU=FGw1ba~v05^SaC(^vK^_9jzF}RziRUyh z16~s9$!T1Wm#_6xCEw-%WY!cEI!)ZMs6XRGSc&G1vhcyLAH{BKv9xPPde=`9#8YaW zgPXydf#NMR^0KC?J1V*$g_(i8QdU+4B@X%E$YTgHWUZOkXuXBNlFprfbU}9qdHmjO zpG)*_SzbD9iHetSM|#|2+rPZ#a-`Wy4zHAD^ajb;@+oCcv5meq%o(V~FcNY^`H&-j zjg?>*D2T?Ny|<2g0-(Ryt+lmzH}ALIrT~93+6gkIG|r?Y+)ut=Yv@-JSe-{3{NL<# z*Zlp3QOjsRmRUfkV%Kbtai1^`7mU!C4S&4xT5NREIFXt*AQ)VDoyC3^KtwBy-xw0- zSWJAiPK*?thXKxvxKs_wq?WLr2k<7-(Z1eVGN>m_5!jdr2d6e4%v@I1zBE!u5e+f4VfX9`#!yY67p;M>bO3^*OA%*E}7^O zj-2br+B6D8{oq-i@#Fd<4V|6l*Rle6+ipp2ZeH*6;<)>Wf!(x=-R=Gz%=ezO4Umex=!O zAg_;DsmtCSjdR7EJF{4@_2Jqt@G%GWRyvJZcmKq?+apcXj0)|-o8q37xTV`Za0{F7 zz`>{;rf+bUkdRlm^-jcH+=mO>+j@!TV3vmtaZ!E3jR~tKt`>iH{ta+gOU>AofTJsR zIle^w2vi4=JfrM2)f^lh##XWDFV%lr&KXpHr*Dl1LDJs^W)%ZJNz@;9?&k_$2IRFD zPK+c6U;)H47EhimiS{>~l7Zy?Fg%gwq9O!i#}LGMED@6xZ!ET#)Or|KO7)EL;}`QK zD*I@99laS<^$nu-mD)cO(<#?lLc-y+ftrEf67GNownUZ9Gr;c(F@R8Y)|}jW4)1U- z&DnoLPoL}X_f)h{sr!)5Vp72f-9FXo#H@&g9X;S0N70BKIj8VPn)?oa zd9H{eo14OpEF0%AM_(OmXrShK&s)x2jseepeHXbN+;i32Z3Oq1LE(s#vqj`MV!zuG z@vR6{-Fax43;gc`A}B@fz46P_q4{?sfWF}C7hm>YO}G_>u@(ROf`~LHHgtsYvsq05 z8JYk4%=k9H9X3l!E%vRP;a{xdD+mgPo5xe`fIt-pn7mXHV@R_>J@{Y54UDQa4N{T2 zJ0SHWF8aM(@_&6m!R0fQV*b;6ptFMw|013F_ve*Y+!VJ+m| z;oj&|%t$aT&->-CFQD|+&S7_** zc%n1Q+{f67$TV1PfFzZ1pms(^eJ5@sCp5v>(d2pC% z9^S*jId*goBB)?D@i}pF2nAtQ95E(KpPiyndcnUS^NK0r`K-a0Anst z3V1pPP<1I#^-|l`M;`*Dz`9viE)C^&KKgK>4RC;&p&<*nlmo1z>#%btu#9A25KW#I z_SDw($jm&@(J(-PRmXW2WWB!mR^SwPRCL7zP}i}8ziQDY@Cv$Jj8O4u3-wm40VV%+ z(hH;@Momo1oC|aja6R3&yoOicpb0r1ARZDHEvvgi4B{T3r!)TobuE`(5CztC)!+*2 z)GxqByyR=P74tyb`GJwdka}+hFk${%tFHANm=V8}Fo#T@33BdJ=~qps1T!3ug5B!1 zWLlUi=avO*V3VE#8+2YkIbU#Q^a3XNYQe$<>RQeVSWUqZqj7$w-in@jpoTbzhL^5K z((eYWg3O3{$1;As1Pk9Y(wpnbB?RYxIdaa{<;YD?y&)QK_`4s(6M5&lVg=SKC;8{U zIr6;Yg)T61Vi`?q?*r#EfaS*%wzc=~_9vMi;jc>02DZk4Q?5OwtXKZn27`*XfQ`~y z>%QxB6`WqP_Ux|Sq_S%<;SOx?r-I{$>)smC&D+j7uU+d~(E*g&x~`$;o_Z@dqV{FJ zF6UQH0uJ4NJ?2%{+u^-+v%=x;?qC=3=G|+FKD`ULka20-gpa=$!4i6XYjpa;XVt&?hH|y|Ez0P^j?iud9o&ZtmiG#SW~ZgripDYKO_^?C0~Cp=PsCMn)~fqEpUa{ zk*%{LFC6#|E(RUk%qxMV32=?_I!0iP4cyuf+(LWD^3jC{->rdWfB3(>{P;HB!wwQ| z`vdnlZgDhm*GdoWRmc~}Pso4J6f{ApwUNOwX+OI_&dO&Eza8f>R9tAwzw^Ki~rB6CGc Date: Thu, 26 Oct 2023 19:26:33 +0200 Subject: [PATCH 111/592] [CST-12145] parial commit --- .../quality-assurance-topic-data.service.ts | 7 +++- .../qa-event-notification.component.html | 6 ++- .../qa-event-notification.component.ts | 42 +++++++++++++++---- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts index 0f52771f515..92ae87e2523 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -17,6 +17,7 @@ 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'; import { hasValue } from 'src/app/shared/empty.util'; +import { SearchData, SearchDataImpl } from 'src/app/core/data/base/search-data'; /** * The service handling all Quality Assurance topic REST requests. @@ -26,6 +27,9 @@ import { hasValue } from 'src/app/shared/empty.util'; export class QualityAssuranceTopicDataService extends IdentifiableDataService { private findAllData: FindAllData; + private searchData: SearchData; + + private searchByTargetMethod = 'byTarget'; /** * Initialize service variables @@ -44,6 +48,7 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataServiceqa-event-notification works!

+ + asdfasdf + + +asfasdfasdf diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts index b5163e07570..ecb9904cef4 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -1,8 +1,12 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; import { QualityAssuranceEventDataService } from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { QualityAssuranceTopicDataService } from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; +import { QualityAssuranceTopicObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-topic.model'; +import { Observable, concatMap, from, map, mergeMap, of, switchMap, tap } from 'rxjs'; +import { QualityAssuranceEventObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model'; +import { AlertType } from 'src/app/shared/alert/aletr-type'; @Component({ selector: 'ds-qa-event-notification', @@ -15,20 +19,40 @@ export class QaEventNotificationComponent { @Input() item: Item; + events: QualityAssuranceEventObject[] = []; + + AlertTypeInfo = AlertType.Info; + constructor( - protected qualityAssuranceEventDataService: QualityAssuranceEventDataService, - protected qualityAssuranceTopicDataService: QualityAssuranceTopicDataService, + private qualityAssuranceEventDataService: QualityAssuranceEventDataService, + private qualityAssuranceTopicDataService: QualityAssuranceTopicDataService, ) { } ngOnInit(): void { - this.getTopics(); + this.getEventsByTopicsAndTarget(); } - getTopics(): void { - this.qualityAssuranceTopicDataService.getTopicsByTargetAndSource(this.item.id, 'coar-notify', {}, true, true).pipe( + getEventsByTopicsAndTarget(): void { + // TODO: add source 'coar-notify' + this.qualityAssuranceTopicDataService.getTopicsByTargetAndSource(this.item.id).pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + getPaginatedListPayload(), + tap((topics: QualityAssuranceTopicObject[]) => console.log(topics, 'topics')), + mergeMap((topics: QualityAssuranceTopicObject[]) => { + return from(topics).pipe( + concatMap((topic: QualityAssuranceTopicObject) => { + return this.qualityAssuranceEventDataService.getEventsByTopicAndTarget(topic.name, this.item.id).pipe( + tap((events: any) => console.log(events, 'events')), + ); + } ) + ); + }), getFirstCompletedRemoteData(), - ).subscribe((topics) => { - console.log(topics); - }); + getRemoteDataPayload(), + getPaginatedListPayload(), + ).subscribe((events: QualityAssuranceEventObject[]) => { + this.events = events; + console.log(events, 'events2')}); } } From b102ef7165e32ad39a01b9ad22752dddcfe4764a Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Thu, 26 Oct 2023 19:28:44 +0200 Subject: [PATCH 112/592] [CST-12235] changed property name to ldn.notify.inbox --- src/app/core/coar-notify/notify-info/notify-info.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts index 4b2d572d3cc..87bbc0a9cd9 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -35,7 +35,7 @@ export class NotifyInfoService { * @returns the url of the local inbox */ getCoarLdnLocalInboxUrls(): Observable { - return this.configService.findByPropertyName('ldn.notify.local-inbox-endpoint').pipe( + return this.configService.findByPropertyName('ldn.notify.inbox').pipe( getFirstSucceededRemoteData(), getRemoteDataPayload(), map((response: ConfigurationProperty) => { From e9dd340e712870faf8fe998ca431c638da81f479 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 27 Oct 2023 16:23:01 +0200 Subject: [PATCH 113/592] CST-11045 Added jsona5 text for coar submission section --- src/assets/i18n/en.json5 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 58453db5188..0a68ae39345 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -4762,6 +4762,8 @@ "submission.sections.submit.progressbar.sherpaPolicies": "Publisher open access policy information", + "submission.sections.submit.progressbar.coarnotify": "COAR Notify", + "submission.sections.sherpa-policy.title-empty": "No publisher policy information available. If your work has an associated ISSN, please enter it above to see any related publisher open access policies.", "submission.sections.status.errors.title": "Errors", From 92d66c911a303ad0054f271e867b5fe7c0c11f31 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 27 Oct 2023 16:24:17 +0200 Subject: [PATCH 114/592] CST-11045 CSS refactor + dropdown data correctly populated --- .../section-coar-notify.component.html | 52 ++++++---- .../section-coar-notify.component.scss | 15 ++- .../section-coar-notify.component.ts | 97 ++++++++++++------- src/app/submission/submission.module.ts | 33 ++++--- 4 files changed, 125 insertions(+), 72 deletions(-) diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html index 75318b937f6..f2c7fd09473 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -1,27 +1,41 @@
- -
- - {{selectedServices[pattern]?.name}} -
- -
+ +
+ +
+
+
Select a service for {{ pattern }} of this item - - Coar-Notify-Pattern - - The selected service is compatible with the item according to its current status. {{ selectedServices[pattern].name }}: {{ selectedServices[pattern].description }} - - +
+
+
+ Coar-Notify-Pattern + +
The selected service is compatible with the item according to its current status.
+
+
+ + +
{{ selectedServices[pattern].name }}: {{ selectedServices[pattern].description }}
+
+
+ +
{{ 'ldn-new-service.form.label.addPattern' | translate }}
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss index c06ef5951c9..f1504fdff6f 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss @@ -2,14 +2,21 @@ color: #0048ff; cursor: pointer; } -.ds-alert-coar{ + +.ds-alert-coar { position: relative } -.coar-img-submission{ - position: absolute; top: 0; left: 0; width: 50px; height: 50px; +.coar-img-submission { + max-height: var(--ds-header-logo-height); +} + +.icon-check { + color: rgba(6, 68, 6, 0.42); + font-size: var(--ds-header-logo-height); } -.ds-alert-box{ + +.ds-alert-box { } diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts index 39c8c9753d4..3cf040acd99 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -23,15 +23,14 @@ import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-servic import { isLoading } from '../../../core/data/request-entry-state.model'; import { LdnService } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; import { SECTION_COAR_FORM_LAYOUT, SECTION_COAR_FORM_MODEL } from './section-coar-notify-model'; -import { - CoarNotifyConfigDataService -} from './coar-notify-config-data.service'; +import { CoarNotifyConfigDataService } from './coar-notify-config-data.service'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object'; import { UntypedFormGroup } from '@angular/forms'; import { AlertType } from '../../../shared/alert/aletr-type'; +import { filter, map, take } from "rxjs/operators"; export interface CoarNotifyDropdownSelector { ldnService: LdnService; @@ -60,8 +59,11 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent patterns: string[] = []; selectedServices: { [key: string]: LdnService } = {}; + patternServices: { [key: string]: LdnService } = {}; + patternsLoaded = false; - selectedService: any; + patternObservables: Observable>[]>; + public AlertTypeEnum = AlertType; @@ -172,7 +174,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ setCoarNotifyConfig() { this.coarNotifyConfigRD$ = this.coarNotifyConfigDataService.findAll().pipe( - getFirstCompletedRemoteData() + getFirstCompletedRemoteData() ); this.coarNotifyConfigRD$.subscribe((data) => { @@ -202,10 +204,10 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ onCustomEvent(event: DynamicFormControlEvent) { this.formOperationsService.dispatchOperationsFromEvent( - this.pathCombiner, - event, - this.previousValue, - null); + this.pathCombiner, + event, + this.previousValue, + null); } /** @@ -244,10 +246,10 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent } this.formOperationsService.dispatchOperationsFromEvent( - this.pathCombiner, - event, - this.previousValue, - this.hasStoredValue(fieldId, fieldIndex)); + this.pathCombiner, + event, + this.previousValue, + this.hasStoredValue(fieldId, fieldIndex)); } @@ -262,8 +264,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent hasStoredValue(fieldId, index): boolean { if (isNotEmpty(this.sectionData.data)) { return this.sectionData.data.hasOwnProperty(fieldId) && - isNotEmpty(this.sectionData.data[fieldId][index]) && - !this.isFieldToRemove(fieldId, index); + isNotEmpty(this.sectionData.data[fieldId][index]) && + !this.isFieldToRemove(fieldId, index); } else { return false; } @@ -305,8 +307,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ onSectionDestroy() { this.subs - .filter((subscription) => hasValue(subscription)) - .forEach((subscription) => subscription.unsubscribe()); + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); } /** @@ -314,44 +316,73 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent * Retriev available NotifyConfigs */ fetchLdnServices() { - this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( - getFirstCompletedRemoteData() - ); + if (!this.ldnServicesRD$) { + this.ldnServicesRD$ = this.ldnServicesService.findAll().pipe( + getFirstCompletedRemoteData() + ); + } this.ldnServicesRD$.subscribe((data) => { if (this.patternsLoaded) { this.patterns.forEach((pattern) => { - this.selectedServices[pattern] = data.payload.page.find((service) => - this.hasInboundPattern(service, pattern) - ); + const servicesWithPattern = this.getServicesWithPattern(pattern, data?.payload?.page); + + if (servicesWithPattern.length > 0) { + this.selectedServices[pattern] = servicesWithPattern[0]; + } - //console.log('Pattern:', pattern); - //console.log('Service:', this.selectedServices[pattern]); + console.log('Pattern:', pattern); + console.log('Service:', this.selectedServices[pattern]); if (this.selectedServices[pattern]) { - //console.log('Name:', this.selectedServices[pattern].name); - //console.log('Description:', this.selectedServices[pattern].description); + console.log('Name:', this.selectedServices[pattern].name); + console.log('Description:', this.selectedServices[pattern].description); } }); } }); } + getServicesWithPattern(pattern: string, services: LdnService[] | null): LdnService[] { + if (services) { + return services.filter((service) => this.hasInboundPattern(service, pattern)); + } + return []; + } - protected getSectionStatus(): Observable { - return undefined; + + filterServices(pattern: string): LdnService[] { + let ldnServices: LdnService[] = []; + + this.ldnServicesRD$.pipe( + filter((rd) => rd.hasSucceeded), + map((rd) => rd.payload.page) + ).subscribe((services) => { + ldnServices = services.filter((service) => this.hasInboundPattern(service, pattern)); + }); + + return ldnServices; } + + + + hasInboundPattern(service: any, patternType: string): boolean { - //console.log('Pattern Type:', patternType); - //console.log('Inbound Patterns in Service:', service.notifyServiceInboundPatterns); + console.log('Pattern Type:', patternType); + console.log('Inbound Patterns in Service:', service.notifyServiceInboundPatterns); const hasPattern = service.notifyServiceInboundPatterns.some((pattern: { pattern: string; }) => { - //console.log('Checking Pattern:', pattern.pattern); + console.log('Checking Pattern:', pattern.pattern); return pattern.pattern === patternType; }); - //console.log('Has Inbound Pattern:', hasPattern); + console.log('Has Inbound Pattern:', hasPattern); return hasPattern; } + + protected getSectionStatus(): Observable { + return undefined; + } + } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index f4f479e2045..d839565f8d6 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -10,7 +10,7 @@ import { SubmissionFormFooterComponent } from './form/footer/submission-form-foo import { SubmissionFormComponent } from './form/submission-form.component'; import { SubmissionFormSectionAddComponent } from './form/section-add/submission-form-section-add.component'; import { SubmissionSectionContainerComponent } from './sections/container/section-container.component'; -import { CommonModule } from '@angular/common'; +import { CommonModule, NgOptimizedImage } from '@angular/common'; import { Action, StoreConfig, StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { submissionReducers, SubmissionState } from './submission.reducers'; @@ -115,21 +115,22 @@ const DECLARATIONS = [ ]; @NgModule({ - imports: [ - CommonModule, - CoreModule.forRoot(), - SharedModule, - StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), - EffectsModule.forFeature(), - EffectsModule.forFeature(submissionEffects), - JournalEntitiesModule.withEntryComponents(), - ResearchEntitiesModule.withEntryComponents(), - FormModule, - NgbModalModule, - NgbCollapseModule, - NgbAccordionModule, - UploadModule, - ], + imports: [ + CommonModule, + CoreModule.forRoot(), + SharedModule, + StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(), + EffectsModule.forFeature(submissionEffects), + JournalEntitiesModule.withEntryComponents(), + ResearchEntitiesModule.withEntryComponents(), + FormModule, + NgbModalModule, + NgbCollapseModule, + NgbAccordionModule, + UploadModule, + NgOptimizedImage, + ], declarations: DECLARATIONS, exports: [ ...DECLARATIONS, From e87c12cca30d98fc7ef19199323410a2f6cf082d Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Fri, 27 Oct 2023 18:28:52 +0200 Subject: [PATCH 115/592] [CST-12145] implementation of item-page & y dspace coar-notify notifications --- .../admin-notifications-routing.module.ts | 15 +++++ .../quality-assurance-event-data.service.ts | 18 +---- .../quality-assurance-topic-data.service.ts | 31 +-------- .../qa-event-notification.component.html | 12 ++-- .../qa-event-notification.component.scss | 8 +++ .../qa-event-notification.component.ts | 67 ++++++++++++++----- ...ace-qa-events-notifications.component.html | 12 +++- ...ace-qa-events-notifications.component.scss | 8 +++ ...space-qa-events-notifications.component.ts | 31 ++++----- .../quality-assurance-topics.component.ts | 8 +++ .../quality-assurance-topics.service.ts | 18 +++++ src/assets/i18n/en.json5 | 4 ++ src/assets/i18n/it.json5 | 8 +++ 13 files changed, 153 insertions(+), 87 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 60fa679777c..6d02ac82929 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -49,6 +49,21 @@ import { SourceDataResolver } from './admin-quality-assurance-source-page-compon showBreadcrumbsFluid: false } }, + { + canActivate: [ AuthenticatedGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/:targetId`, + component: AdminQualityAssuranceTopicsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireQualityAssuranceTopicsParams: AdminQualityAssuranceTopicsPageResolver + }, + data: { + title: 'admin.quality-assurance.page.title', + breadcrumbKey: 'admin.quality-assurance', + showBreadcrumbsFluid: false + } + }, { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}`, diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts index 5e9a4f430bd..6c333cc6f50 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts @@ -86,27 +86,11 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService[]): Observable>> { - options.searchParams = [ - { - fieldName: 'topic', - fieldValue: topic - } - ]; - - if (hasValue(target)) { - options.searchParams.push({ - fieldName: 'target', - fieldValue: target - }); - } - + public searchEventsByTopic(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow); } diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts index 92ae87e2523..626674a5ad9 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -16,8 +16,7 @@ import { IdentifiableDataService } from '../../../data/base/identifiable-data.se 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'; -import { hasValue } from 'src/app/shared/empty.util'; -import { SearchData, SearchDataImpl } from 'src/app/core/data/base/search-data'; +import { SearchData, SearchDataImpl } from '../../../../core/data/base/search-data'; /** * The service handling all Quality Assurance topic REST requests. @@ -68,34 +67,6 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataService>. - */ - public getTopicsByTargetAndSource(target: string, source?: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - options.searchParams = [ - { - fieldName: 'target', - fieldValue: target - } - ]; - - if (hasValue(source)) { - options.searchParams.push({ - fieldName: 'source', - fieldValue: source - }); - } - - return this.searchData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); - } - /** * Clear FindAll topics requests from cache */ diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html index be0e7ac763d..eb663fceb0e 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html @@ -1,5 +1,9 @@ - - asdfasdf - + +
+ +
+
{{'item.qa-event-notification.check.notification-info' | translate : {num: (events$ | async)?.length} }}
+ +
+
-asfasdfasdf diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss index e69de29bb2d..1cc0db27c84 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss @@ -0,0 +1,8 @@ + +.notify-logo { + max-height: var(--ds-header-logo-height); +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts index ecb9904cef4..455629c026f 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -1,12 +1,14 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; import { QualityAssuranceEventDataService } from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { QualityAssuranceTopicDataService } from '../../../core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service'; -import { QualityAssuranceTopicObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-topic.model'; -import { Observable, concatMap, from, map, mergeMap, of, switchMap, tap } from 'rxjs'; -import { QualityAssuranceEventObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-event.model'; -import { AlertType } from 'src/app/shared/alert/aletr-type'; +import { QualityAssuranceTopicObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-topic.model'; +import { Observable, concatMap, from, mergeMap } from 'rxjs'; +import { QualityAssuranceEventObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model'; +import { AlertType } from '../../../shared/alert/aletr-type'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; @Component({ selector: 'ds-qa-event-notification', @@ -15,44 +17,73 @@ import { AlertType } from 'src/app/shared/alert/aletr-type'; changeDetection: ChangeDetectionStrategy.OnPush, providers: [QualityAssuranceTopicDataService, QualityAssuranceEventDataService] }) -export class QaEventNotificationComponent { +/** + * Component for displaying quality assurance event notifications for an item. + */ +export class QaEventNotificationComponent implements OnInit { + /** + * The item to display quality assurance event notifications for. + */ @Input() item: Item; - events: QualityAssuranceEventObject[] = []; + /** + * An observable of quality assurance events for the item. + */ + events$: Observable; + /** + * The type of alert to display for the notification. + */ AlertTypeInfo = AlertType.Info; + /** + * The source of the quality assurance events. + */ + source = 'coar-notify'; + constructor( private qualityAssuranceEventDataService: QualityAssuranceEventDataService, private qualityAssuranceTopicDataService: QualityAssuranceTopicDataService, ) { } - ngOnInit(): void { + ngOnInit() { this.getEventsByTopicsAndTarget(); } - getEventsByTopicsAndTarget(): void { - // TODO: add source 'coar-notify' - this.qualityAssuranceTopicDataService.getTopicsByTargetAndSource(this.item.id).pipe( + /** + * Retrieves quality assurance events by topics and target. + * First, it retrieves the topics by target and source. + * -> target: item.id + * -> source: 'coar-notify' + * Then, it retrieves the events by topic and target. + */ + getEventsByTopicsAndTarget() { + const findListTopicOptions: FindListOptions = { + searchParams: [new RequestParam('source', this.source), new RequestParam('target', this.item.id)] + }; + + // const findListEventOptions: FindListOptions = { + // searchParams: [new RequestParam('topic', topic.name), new RequestParam('target', this.item.id)] + // }; + + this.events$ = this.qualityAssuranceTopicDataService.getTopics(findListTopicOptions).pipe( getFirstCompletedRemoteData(), getRemoteDataPayload(), getPaginatedListPayload(), - tap((topics: QualityAssuranceTopicObject[]) => console.log(topics, 'topics')), mergeMap((topics: QualityAssuranceTopicObject[]) => { return from(topics).pipe( concatMap((topic: QualityAssuranceTopicObject) => { - return this.qualityAssuranceEventDataService.getEventsByTopicAndTarget(topic.name, this.item.id).pipe( - tap((events: any) => console.log(events, 'events')), - ); + const findListEventOptions: FindListOptions = { + searchParams: [new RequestParam('topic', topic.name), new RequestParam('target', this.item.id)] + }; + return this.qualityAssuranceEventDataService.searchEventsByTopic(findListEventOptions); } ) ); }), getFirstCompletedRemoteData(), getRemoteDataPayload(), getPaginatedListPayload(), - ).subscribe((events: QualityAssuranceEventObject[]) => { - this.events = events; - console.log(events, 'events2')}); + ); } } diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html index db0611e8f8c..fb73cff9050 100644 --- a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html @@ -1 +1,11 @@ -

my-dspace-qa-events-notifications works!

+ + +
+ +
+
{{'item.qa-event-notification.check.notification-info' | translate : {num: source.totalEvents} }}
+ +
+
+
+
diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss index e69de29bb2d..1cc0db27c84 100644 --- a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss @@ -0,0 +1,8 @@ + +.notify-logo { + max-height: var(--ds-header-logo-height); +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts index d0c42d9bcb7..8b7127dd895 100644 --- a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts @@ -1,9 +1,7 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { QualityAssuranceSourceDataService } from '../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; -import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; -import { map } from 'rxjs'; -import { RemoteData } from 'src/app/core/data/remote-data'; -import { PaginatedList } from 'src/app/core/data/paginated-list.model'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../core/shared/operators'; +import { Observable, of, tap } from 'rxjs'; import { QualityAssuranceSourceObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-source.model'; @Component({ @@ -12,7 +10,9 @@ import { QualityAssuranceSourceObject } from 'src/app/core/suggestion-notificati styleUrls: ['./my-dspace-qa-events-notifications.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -export class MyDspaceQaEventsNotificationsComponent { +export class MyDspaceQaEventsNotificationsComponent implements OnInit { + + sources$: Observable = of([]); constructor(private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService) { } @@ -21,19 +21,16 @@ export class MyDspaceQaEventsNotificationsComponent { } getSources() { - this.qualityAssuranceSourceDataService.getSource('coar-notify') + this.sources$ = this.qualityAssuranceSourceDataService.getSources() .pipe( getFirstCompletedRemoteData(), - map((rd: RemoteData) => { - if (rd.hasSucceeded) { - return rd.payload; - } else { - throw new Error('Can\'t retrieve Quality Assurance source'); + tap((rd) => { + if (rd.hasFailed) { + throw new Error('Can\'t retrieve Quality Assurance sources'); } - }) - ) - .subscribe((sources) => { - console.log(sources); - }); + }), + getRemoteDataPayload(), + getPaginatedListPayload(), + ); } } diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts index 3c8b4f8f38a..6d96795ea39 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts @@ -60,6 +60,12 @@ export class QualityAssuranceTopicsComponent implements OnInit { */ public sourceId: string; + /** + * This property represents a targetId (item-id) which is used to retrive a topic + * @type {string} + */ + public targetId: string; + /** * Initialize the component variables. * @param {PaginationService} paginationService @@ -80,7 +86,9 @@ export class QualityAssuranceTopicsComponent implements OnInit { */ ngOnInit(): void { this.sourceId = this.activatedRoute.snapshot.paramMap.get('sourceId'); + this.targetId = this.activatedRoute.snapshot.paramMap.get('targetId'); this.qualityAssuranceTopicsService.setSourceId(this.sourceId); + this.qualityAssuranceTopicsService.setTargetId(this.targetId); this.topics$ = this.notificationsStateService.getQualityAssuranceTopics(); this.totalElements$ = this.notificationsStateService.getQualityAssuranceTopicsTotals(); } 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 6820791dffd..c94ffe72d47 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 @@ -13,6 +13,7 @@ import { import { RequestParam } from '../../../core/cache/models/request-param.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; /** * The service handling all Quality Assurance topic requests to the REST service. @@ -33,6 +34,11 @@ export class QualityAssuranceTopicsService { */ sourceId: string; + /** + * targetId used to get topics + */ + targetId: string; + /** * Return the list of Quality Assurance topics managing pagination and errors. * @@ -53,6 +59,10 @@ export class QualityAssuranceTopicsService { searchParams: [new RequestParam('source', this.sourceId)] }; + if (hasValue(this.targetId)) { + findListOptions.searchParams.push(new RequestParam('target', this.targetId)); + } + return this.qualityAssuranceTopicRestService.getTopics(findListOptions).pipe( getFirstCompletedRemoteData(), map((rd: RemoteData>) => { @@ -72,4 +82,12 @@ export class QualityAssuranceTopicsService { setSourceId(sourceId: string) { this.sourceId = sourceId; } + + /** + * set targetId which is used to get topics + * @param targetId string + */ + setTargetId(targetId: string) { + this.targetId = targetId; + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7a68fc60c88..7e0eea931ed 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2448,6 +2448,10 @@ "item.truncatable-part.show-less": "Collapse", + "item.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + "item.qa-event-notification-info.check.button": "Check", + "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", "workflow-item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", diff --git a/src/assets/i18n/it.json5 b/src/assets/i18n/it.json5 index 4131d0bee66..961fea3ae72 100644 --- a/src/assets/i18n/it.json5 +++ b/src/assets/i18n/it.json5 @@ -3723,6 +3723,14 @@ // "item.truncatable-part.show-less": "Collapse", "item.truncatable-part.show-less": "Riduci", + // "item.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + // TODO New key - Add a translation + "item.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + // "item.qa-event-notification-info.check.button": "Check", + // TODO New key - Add a translation + "item.qa-event-notification-info.check.button": "Check", + // "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", // TODO New key - Add a translation "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", From 8e0af9bceed05c9795d03966cd87b3462b21ebd4 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Mon, 30 Oct 2023 10:57:04 +0100 Subject: [PATCH 116/592] [CST-12145] commented code --- .../topics/quality-assurance-topic-data.service.ts | 12 ++++++++++++ .../qa-event-notification.component.ts | 6 +----- .../my-dspace-qa-events-notifications.component.ts | 8 ++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts index 626674a5ad9..bb98e6fabfd 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -67,6 +67,18 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataService[]): Observable>> { + return this.searchData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + /** * Clear FindAll topics requests from cache */ diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts index 455629c026f..0a26045e396 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -63,11 +63,7 @@ export class QaEventNotificationComponent implements OnInit { searchParams: [new RequestParam('source', this.source), new RequestParam('target', this.item.id)] }; - // const findListEventOptions: FindListOptions = { - // searchParams: [new RequestParam('topic', topic.name), new RequestParam('target', this.item.id)] - // }; - - this.events$ = this.qualityAssuranceTopicDataService.getTopics(findListTopicOptions).pipe( + this.events$ = this.qualityAssuranceTopicDataService.searchTopics(findListTopicOptions).pipe( getFirstCompletedRemoteData(), getRemoteDataPayload(), getPaginatedListPayload(), diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts index 8b7127dd895..9992ec9ff83 100644 --- a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts @@ -12,6 +12,9 @@ import { QualityAssuranceSourceObject } from 'src/app/core/suggestion-notificati }) export class MyDspaceQaEventsNotificationsComponent implements OnInit { + /** + * An Observable that emits an array of QualityAssuranceSourceObject. + */ sources$: Observable = of([]); constructor(private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService) { } @@ -20,6 +23,11 @@ export class MyDspaceQaEventsNotificationsComponent implements OnInit { this.getSources(); } + /** + * Retrieves the sources for Quality Assurance. + * @returns An Observable of the sources for Quality Assurance. + * @throws An error if the retrieval of Quality Assurance sources fails. + */ getSources() { this.sources$ = this.qualityAssuranceSourceDataService.getSources() .pipe( From 752cb4d4b04b0ee89cd4e4b74b8b98f449e17907 Mon Sep 17 00:00:00 2001 From: Mykhaylo Date: Mon, 30 Oct 2023 12:19:44 +0100 Subject: [PATCH 117/592] [CST-11178] show allowed correction types --- src/app/app-routing-paths.ts | 10 ++ src/app/core/core.module.ts | 4 + .../submission/correctiontype-data.service.ts | 89 ++++++++++++++ .../models/correction-type-mode.model.ts | 35 ++++++ .../correction-type-menu.component.html | 7 ++ .../correction-type-menu.component.spec.ts | 116 ++++++++++++++++++ .../correction-type-menu.component.ts | 105 ++++++++++++++++ 7 files changed, 366 insertions(+) create mode 100644 src/app/core/submission/correctiontype-data.service.ts create mode 100644 src/app/core/submission/models/correction-type-mode.model.ts create mode 100644 src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html create mode 100644 src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts create mode 100644 src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index fe2837c6e3f..8430454d630 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -132,3 +132,13 @@ export const SUBSCRIPTIONS_MODULE_PATH = 'subscriptions'; export function getSubscriptionsModuleRoute() { return `/${SUBSCRIPTIONS_MODULE_PATH}`; } + +export const EDIT_ITEM_PATH = 'edit-items'; +export function getEditItemPageRoute() { + return `/${EDIT_ITEM_PATH}`; +} +export const CORRECTION_TYPE_PATH = 'corrections'; +export function getCorrectionTypePageRoute(itemUuid: string, typeId: string) { + return `/items/${itemUuid}/${CORRECTION_TYPE_PATH}/${typeId}`; +} + diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index e176af7d550..0eeb476d69d 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -185,6 +185,8 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model'; import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model'; import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition'; import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; +import { CorrectionTypeMode } from './submission/models/correction-type-mode.model'; +import { CorrectionTypeDataService } from './submission/correctiontype-data.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -308,6 +310,7 @@ const PROVIDERS = [ OrcidQueueDataService, OrcidHistoryDataService, SupervisionOrderDataService + CorrectionTypeDataService, ]; /** @@ -387,6 +390,7 @@ export const models = Subscription, ItemRequest, BulkAccessConditionOptions + CorrectionTypeMode ]; @NgModule({ diff --git a/src/app/core/submission/correctiontype-data.service.ts b/src/app/core/submission/correctiontype-data.service.ts new file mode 100644 index 00000000000..4d293558f7f --- /dev/null +++ b/src/app/core/submission/correctiontype-data.service.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; + +import { dataService } from '../data/base/data-service.decorator'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RequestService } from '../data/request.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { IdentifiableDataService } from '../data/base/identifiable-data.service'; +import { SearchDataImpl } from '../data/base/search-data'; +import { CorrectionTypeMode } from './models/correction-type-mode.model'; +import { Observable, map } from 'rxjs'; +import { RemoteData } from '../data/remote-data'; +import { PaginatedList } from '../data/paginated-list.model'; +import { FindListOptions } from '../data/find-list-options.model'; +import { RequestParam } from '../cache/models/request-param.model'; +import { getAllSucceededRemoteDataPayload, getPaginatedListPayload } from '../shared/operators'; + +/** + * A service that provides methods to make REST requests with correctiontypes endpoint. + */ +@Injectable() +@dataService(CorrectionTypeMode.type) +export class CorrectionTypeDataService extends IdentifiableDataService { + protected linkPath = 'correctiontypes'; + protected searchByTopic = 'findByTopic'; + protected searchFindByItem = 'findByItem'; + private searchData: SearchDataImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('correctiontypes', requestService, rdbService, objectCache, halService); + + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + } + + /** + * Get the correction type by id + * @param id the id of the correction type + * @param useCachedVersionIfAvailable use the cached version if available + * @param reRequestOnStale re-request on stale + * @returns {Observable>} the correction type + */ + getCorrectionTypeById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable> { + return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale); + } + + /** + * Search for the correction types for the item + * @param itemUuid the uuid of the item + * @param useCachedVersionIfAvailable use the cached version if available + * @returns the list of correction types for the item + */ + findByItem(itemUuid: string, useCachedVersionIfAvailable): Observable>> { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', itemUuid)]; + return this.searchData.searchBy(this.searchFindByItem, options, useCachedVersionIfAvailable); + } + + /** + * Find the correction type for the topic + * @param topic the topic of the correction type to search for + * @param useCachedVersionIfAvailable use the cached version if available + * @param reRequestOnStale re-request on stale + * @returns the correction type for the topic + */ + findByTopic(topic: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable { + const options = new FindListOptions(); + options.searchParams = [ + { + fieldName: 'topic', + fieldValue: topic, + }, + ]; + + return this.searchData.searchBy(this.searchByTopic, options, useCachedVersionIfAvailable, reRequestOnStale).pipe( + getAllSucceededRemoteDataPayload(), + getPaginatedListPayload(), + map((list: CorrectionTypeMode[]) => { + return list[0]; + }) + ); + } +} diff --git a/src/app/core/submission/models/correction-type-mode.model.ts b/src/app/core/submission/models/correction-type-mode.model.ts new file mode 100644 index 00000000000..b9bb033d867 --- /dev/null +++ b/src/app/core/submission/models/correction-type-mode.model.ts @@ -0,0 +1,35 @@ +import { autoserialize, deserialize } from 'cerialize'; +import { typedObject } from '../../cache/builders/build-decorators'; +import { CacheableObject } from '../../cache/cacheable-object.model'; +import { ResourceType } from '../../shared/resource-type'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { HALLink } from '../../shared/hal-link.model'; + +@typedObject +export class CorrectionTypeMode extends CacheableObject { + static type = new ResourceType('correctiontype'); + + /** + * The object type + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: string; + + @autoserialize + topic: string; + + @autoserialize + discoveryConfiguration: string; + + @autoserialize + creationForm: string; + + @deserialize + _links: { + self: HALLink; + }; +} diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html new file mode 100644 index 00000000000..6504d6ecaf4 --- /dev/null +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html @@ -0,0 +1,7 @@ + + + diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts new file mode 100644 index 00000000000..0f2eb02f601 --- /dev/null +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts @@ -0,0 +1,116 @@ +import { Item } from './../../../core/shared/item.model'; +import { DSpaceObject } from './../../../core/shared/dspace-object.model'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CorrectionTypeMenuComponent } from './correction-type-menu.component'; +import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; +import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; +import { createPaginatedList } from '../../testing/utils.test'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../mocks/translate-loader.mock'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CorrectionTypeDataService } from '../../../core/submission/correctiontype-data.service'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { By } from '@angular/platform-browser'; +import { CorrectionTypeMode } from '../../../core/submission/models/correction-type-mode.model'; + +describe('CorrectionTypeMenuComponent', () => { + let component: CorrectionTypeMenuComponent; + let fixture: ComponentFixture; + let componentAsAny: any; + + let correctionTypeService: any; + let dso: DSpaceObject; + const notificationService = new NotificationsServiceStub(); + const correctionType: CorrectionTypeMode = Object.assign(new CorrectionTypeMode(), { + id: 'addpersonalpath', + creationForm:'manageRelation', + discoveryConfiguration: 'RELATION.PersonPath.Items', + topic: '/DSPACEUSERS/RELATIONADD/PERSONALPATH' + }); + + const correctionTypeObjRDList$ = createSuccessfulRemoteDataObject$(createPaginatedList([correctionType])); + + beforeEach(async () => { + dso = Object.assign(new Item(), { + id: 'test-item', + _links: { + self: { href: 'test-item-selflink' } + } + }); + + correctionTypeService = jasmine.createSpyObj('CorrectionTypeDataService', { + findByItem: jasmine.createSpy('findByItem') + }); + + await TestBed.configureTestingModule({ + declarations: [ CorrectionTypeMenuComponent ], + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }), + RouterTestingModule.withRoutes([])], + providers: [ + { provide: CorrectionTypeDataService, useValue: correctionTypeService }, + { provide: 'contextMenuObjectProvider', useValue: dso }, + { provide: 'contextMenuObjectTypeProvider', useValue: DSpaceObjectType.ITEM }, + { provide: NotificationsService, useValue: notificationService } + ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CorrectionTypeMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('when correction types are available', () => { + beforeEach(() => { + correctionTypeService.findByItem.and.returnValue(correctionTypeObjRDList$); + fixture = TestBed.createComponent(CorrectionTypeMenuComponent); + component = fixture.componentInstance; + componentAsAny = fixture.componentInstance; + component.contextMenuObject = dso; + fixture.detectChanges(); + }); + + it('should init properly', () => { + expect(componentAsAny.correctionTypes$.value).toEqual([correctionType]); + }); + + it('should render a button', () => { + const link = fixture.debugElement.query(By.css('button')); + expect(link).not.toBeNull(); + }); + }); + + describe('when is no data are available', () => { + beforeEach(() => { + correctionTypeService.findByItem.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([]))); + fixture = TestBed.createComponent(CorrectionTypeMenuComponent); + component = fixture.componentInstance; + componentAsAny = fixture.componentInstance; + component.contextMenuObject = dso; + fixture.detectChanges(); + }); + + it('should init edit mode properly', () => { + expect(componentAsAny.correctionTypes$.value).toEqual([]); + }); + + it('should render a button', () => { + const link = fixture.debugElement.query(By.css('button')); + expect(link).toBeNull(); + }); + }); +}); diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts new file mode 100644 index 00000000000..2f1b341b9fe --- /dev/null +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts @@ -0,0 +1,105 @@ +import { getAllSucceededRemoteDataPayload, getPaginatedListPayload } from './../../../core/shared/operators'; +import { CorrectionTypeDataService } from './../../../core/submission/correctiontype-data.service'; +import { DSpaceObject } from './../../../core/shared/dspace-object.model'; +import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; +import { ContextMenuEntryComponent } from '../context-menu-entry.component'; +import { ContextMenuEntryType } from '../context-menu-entry-type'; +import { BehaviorSubject, Observable, Subscription, map, startWith, tap } from 'rxjs'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { CorrectionTypeMode } from '../../../core/submission/models/correction-type-mode.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { hasValue, isNotEmpty } from '../../empty.util'; +import { rendersContextMenuEntriesForType } from '../context-menu.decorator'; +import { getCorrectionTypePageRoute } from '../../../app-routing-paths'; + +@Component({ + selector: 'ds-correction-type-menu', + templateUrl: './correction-type-menu.component.html', +}) +@rendersContextMenuEntriesForType(DSpaceObjectType.ITEM) +export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent implements OnInit, OnDestroy { + + /** + * The menu entry type + */ + public static menuEntryType: ContextMenuEntryType = ContextMenuEntryType.CorrectionType; + + /** + * A boolean representing if a request operation is pending + * @type {BehaviorSubject} + */ + public processing$ = new BehaviorSubject(false); + + /** + * Reference to NgbModal + */ + public modalRef: NgbModalRef; + + /** + * List of Edit Modes available on this item + * for the current user + */ + private correctionTypes$: BehaviorSubject = new BehaviorSubject([]); + + /** + * Variable to track subscription and unsubscribe it onDestroy + */ + private sub: Subscription; + + constructor( + @Inject('contextMenuObjectProvider') protected injectedContextMenuObject: DSpaceObject, + @Inject('contextMenuObjectTypeProvider') protected injectedContextMenuObjectType: DSpaceObjectType, + private correctionTypeService: CorrectionTypeDataService, + public notificationService: NotificationsService + ) { + super(injectedContextMenuObject, injectedContextMenuObjectType, ContextMenuEntryType.EditSubmission); + } + + ngOnInit(): void { + this.notificationService.claimedProfile.subscribe(() => { + this.getData(); + }); + } + + /** + * Check if edit mode is available + */ + getCorrectionTypes(): Observable { + return this.correctionTypes$; + } + + /** + * Check if edit mode is available + */ + isAvailable(): Observable { + return this.correctionTypes$.asObservable().pipe( + map((type) => isNotEmpty(type) && type.length > 0) + ); + } + + getData(): void { + this.sub = this.correctionTypeService.findByItem(this.contextMenuObject.id, true).pipe( + tap((types) => console.log(types)), + getAllSucceededRemoteDataPayload(), + getPaginatedListPayload(), + startWith([]) + ).subscribe((types: CorrectionTypeMode[]) => { + console.log(types); + this.correctionTypes$.next(types); + }); + } + + getTypeRoute(id: string) { + return getCorrectionTypePageRoute(this.contextMenuObject.id, id); + } + + /** + * Make sure the subscription is unsubscribed from when this component is destroyed + */ + ngOnDestroy(): void { + if (hasValue(this.sub)) { + this.sub.unsubscribe(); + } + } +} From bf67fee89b1d72f65d1f80f50f0cf8dca728dd52 Mon Sep 17 00:00:00 2001 From: Mykhaylo Date: Mon, 30 Oct 2023 12:21:38 +0100 Subject: [PATCH 118/592] [CST-11178][CST-11179] page to select the target item for "relation" correction suggestion --- src/app/app-routing.module.ts | 5 + .../quality-assurance-event-data.service.ts | 23 +- .../correction-type-menu.component.ts | 33 +-- .../correction-suggestion-page.decorator.ts | 15 ++ .../correction-suggestion-routing.module.ts | 23 ++ .../correction-suggestion.component.html | 3 + .../correction-suggestion.component.scss | 0 .../correction-suggestion.component.spec.ts | 25 ++ .../correction-suggestion.component.ts | 94 +++++++ .../correction-suggestion.module.ts | 39 +++ .../correction-types/correction-type-forms.ts | 3 + ...ge-relation-correction-type.component.html | 54 ++++ ...ge-relation-correction-type.component.scss | 0 ...relation-correction-type.component.spec.ts | 25 ++ ...nage-relation-correction-type.component.ts | 252 ++++++++++++++++++ src/themes/custom/lazy-theme.module.ts | 2 + 16 files changed, 576 insertions(+), 20 deletions(-) create mode 100644 src/app/shared/correction-suggestion/correction-suggestion-page.decorator.ts create mode 100644 src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts create mode 100644 src/app/shared/correction-suggestion/correction-suggestion.component.html create mode 100644 src/app/shared/correction-suggestion/correction-suggestion.component.scss create mode 100644 src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts create mode 100644 src/app/shared/correction-suggestion/correction-suggestion.component.ts create mode 100644 src/app/shared/correction-suggestion/correction-suggestion.module.ts create mode 100644 src/app/shared/correction-suggestion/correction-types/correction-type-forms.ts create mode 100644 src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html create mode 100644 src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.scss create mode 100644 src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts create mode 100644 src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index deb68f1ea92..28623e3ce66 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -238,6 +238,11 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone canActivate: [AuthenticatedGuard] }, { path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }, + { + path: 'items', + loadChildren: () => import('./shared/correction-suggestion/correction-suggestion.module') + .then((m) => m.CorrectionSuggestionModule) + }, ] } ], { diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts index 7f7e68afaab..c2acc7490a3 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { find, take } from 'rxjs/operators'; +import { find, switchMap, take } from 'rxjs/operators'; import { ReplaceOperation } from 'fast-json-patch'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; @@ -200,4 +200,25 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService(requestId); } + + /** + * Perform a post on an endpoint related to correction type + * @param data the data to post + * @returns the RestResponse as an Observable + */ + postData(data: string): Observable> { + const requestId = this.requestService.generateRequestId(); + const href$ = this.getBrowseEndpoint(); + + return href$.pipe( + switchMap((href: string) => { + const request = new PostRequest(requestId, href, data); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + return this.rdbService.buildFromRequestUUID(requestId); + }) + ); + } } diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts index 2f1b341b9fe..51aaafb7e42 100644 --- a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts @@ -4,8 +4,7 @@ import { DSpaceObject } from './../../../core/shared/dspace-object.model'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { ContextMenuEntryComponent } from '../context-menu-entry.component'; import { ContextMenuEntryType } from '../context-menu-entry-type'; -import { BehaviorSubject, Observable, Subscription, map, startWith, tap } from 'rxjs'; -import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { BehaviorSubject, Observable, Subscription, map, startWith} from 'rxjs'; import { CorrectionTypeMode } from '../../../core/submission/models/correction-type-mode.model'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { NotificationsService } from '../../notifications/notifications.service'; @@ -25,17 +24,6 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple */ public static menuEntryType: ContextMenuEntryType = ContextMenuEntryType.CorrectionType; - /** - * A boolean representing if a request operation is pending - * @type {BehaviorSubject} - */ - public processing$ = new BehaviorSubject(false); - - /** - * Reference to NgbModal - */ - public modalRef: NgbModalRef; - /** * List of Edit Modes available on this item * for the current user @@ -51,9 +39,9 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple @Inject('contextMenuObjectProvider') protected injectedContextMenuObject: DSpaceObject, @Inject('contextMenuObjectTypeProvider') protected injectedContextMenuObjectType: DSpaceObjectType, private correctionTypeService: CorrectionTypeDataService, - public notificationService: NotificationsService + public notificationService: NotificationsService, ) { - super(injectedContextMenuObject, injectedContextMenuObjectType, ContextMenuEntryType.EditSubmission); + super(injectedContextMenuObject, injectedContextMenuObjectType, ContextMenuEntryType.CorrectionType); } ngOnInit(): void { @@ -78,19 +66,26 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple ); } + /** + * Get correction types + * useCachedVersionIfAvailable = false to force refreshing the list + */ getData(): void { - this.sub = this.correctionTypeService.findByItem(this.contextMenuObject.id, true).pipe( - tap((types) => console.log(types)), + this.sub = this.correctionTypeService.findByItem(this.contextMenuObject.id, false).pipe( getAllSucceededRemoteDataPayload(), getPaginatedListPayload(), startWith([]) ).subscribe((types: CorrectionTypeMode[]) => { - console.log(types); this.correctionTypes$.next(types); }); } - getTypeRoute(id: string) { + /** + * Get the route to the correction type page + * @param id correction type id + * @returns the route to the correction type page + */ + getTypeRoute(id: string): string { return getCorrectionTypePageRoute(this.contextMenuObject.id, id); } diff --git a/src/app/shared/correction-suggestion/correction-suggestion-page.decorator.ts b/src/app/shared/correction-suggestion/correction-suggestion-page.decorator.ts new file mode 100644 index 00000000000..88f1c9f8025 --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion-page.decorator.ts @@ -0,0 +1,15 @@ +const pageMap = new Map(); + +export function renderCorrectionFor(creationMode: string) { + return function decorator(component: any) { + if (!component) { + return; + } + pageMap.set(creationMode, component); + }; +} + +export function getCorrectionComponent(creationMode: string) { + return pageMap.get(creationMode); +} + diff --git a/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts b/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts new file mode 100644 index 00000000000..e07e4749bbc --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts @@ -0,0 +1,23 @@ +import { ItemBreadcrumbResolver } from './../../core/breadcrumbs/item-breadcrumb.resolver'; +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { CorrectionSuggestionComponent } from './correction-suggestion.component'; + +const routes: Routes = [ + { + path: ':uuid/corrections/:correctionType', + component: CorrectionSuggestionComponent, + resolve: { + breadcrumb: ItemBreadcrumbResolver, + }, + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [ + ItemBreadcrumbResolver + ] +}) +export class CorrectionSuggestionRoutingModule { } diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.html b/src/app/shared/correction-suggestion/correction-suggestion.component.html new file mode 100644 index 00000000000..7cc498504ee --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.scss b/src/app/shared/correction-suggestion/correction-suggestion.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts new file mode 100644 index 00000000000..c5876712a90 --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CorrectionSuggestionComponent } from './correction-suggestion.component'; + +describe('CorrectionSuggestionComponent', () => { + let component: CorrectionSuggestionComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CorrectionSuggestionComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CorrectionSuggestionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.ts new file mode 100644 index 00000000000..2a2772a21dd --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.ts @@ -0,0 +1,94 @@ +import { getRemoteDataPayload } from './../../core/shared/operators'; +import { CorrectionTypeDataService } from './../../core/submission/correctiontype-data.service'; +import { Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core'; +import { CorrectionTypeMode } from '../../core/submission/models/correction-type-mode.model'; +import { GenericConstructor } from '../../core/shared/generic-constructor'; +import { getCorrectionComponent } from './correction-suggestion-page.decorator'; +import { ActivatedRoute, Params } from '@angular/router'; +import { hasValue } from '../empty.util'; +import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; + +@Component({ + selector: 'ds-correction-suggestion', + templateUrl: './correction-suggestion.component.html', + styleUrls: ['./correction-suggestion.component.scss'] +}) +export class CorrectionSuggestionComponent implements OnInit { + + /** + * The correction type object + */ + public correctionTypeObject: CorrectionTypeMode; + + /** + * The correction type id + */ + private correctionTypeId: string; + + /** + * The creation form + */ + private creationForm: string; + + /** + * The injector for the component + */ + public objectInjector: Injector; + + constructor( + private componentFactoryResolver: ComponentFactoryResolver, + private aroute: ActivatedRoute, + private correctionTypeDataService: CorrectionTypeDataService, + private injector: Injector, + ) { + this.aroute.params.subscribe((params: Params) => { + this.correctionTypeId = params.correctionType; + }); + } + + ngOnInit(): void { + this.initComponent(); + } + + /** + * Initialize the component by fetching the correction type object + * and rendering the correct component based on the creation form + */ + initComponent(): void { + if (hasValue(this.correctionTypeId)) { + this.correctionTypeDataService.getCorrectionTypeById(this.correctionTypeId) + .pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + ) + .subscribe((correctionType: CorrectionTypeMode) => { + if (hasValue(correctionType)) { + this.correctionTypeObject = correctionType; + this.creationForm = correctionType.creationForm; + this.componentFactoryResolver.resolveComponentFactory(this.getComponent()); + this.injectData(); + } + }); + } + } + + /** + * Inject the data into the component + */ + private injectData(): void { + this.objectInjector = Injector.create({ + providers: [ + { provide: 'correctionTypeObjectProvider', useValue: this.correctionTypeObject, deps: [] }, + ], + parent: this.injector, + }); + } + + /** + * Fetch the component depending on the creation form + * @returns {GenericConstructor} + */ + getComponent(): GenericConstructor { + return getCorrectionComponent(this.creationForm); + } +} diff --git a/src/app/shared/correction-suggestion/correction-suggestion.module.ts b/src/app/shared/correction-suggestion/correction-suggestion.module.ts new file mode 100644 index 00000000000..37204b441e6 --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-suggestion.module.ts @@ -0,0 +1,39 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CorrectionSuggestionComponent } from './correction-suggestion.component'; +import { SharedModule } from '../shared.module'; +import { CorrectionSuggestionRoutingModule } from './correction-suggestion-routing.module'; +import { ManageRelationCorrectionTypeComponent } from './correction-types/manage-relation-correction-type/manage-relation-correction-type.component'; +import { SearchModule } from '../search/search.module'; + +const COMPONENTS = [ + CorrectionSuggestionComponent, + ManageRelationCorrectionTypeComponent, +]; + +const ENTRY_COMPONENTS = [ + ManageRelationCorrectionTypeComponent, +]; + +@NgModule({ + declarations: [ + COMPONENTS, + ], + imports: [ + CommonModule, + CorrectionSuggestionRoutingModule, + SharedModule, + SearchModule + ], + exports: [ + COMPONENTS, + ] +}) +export class CorrectionSuggestionModule { + static withEntryComponents() { + return { + ngModule: CorrectionSuggestionModule, + providers: ENTRY_COMPONENTS.map((component) => ({ provide: component })) + }; + } + } diff --git a/src/app/shared/correction-suggestion/correction-types/correction-type-forms.ts b/src/app/shared/correction-suggestion/correction-types/correction-type-forms.ts new file mode 100644 index 00000000000..9faf8ca18be --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-types/correction-type-forms.ts @@ -0,0 +1,3 @@ +export enum CorrectionTypeForms { + MANAGE_RELATION = 'manageRelation', +} diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html new file mode 100644 index 00000000000..fe3f64e8db7 --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html @@ -0,0 +1,54 @@ +
+

+ {{ ( 'correction-type.manage-relation.' + (correctionType.topic | lowercase) + '.searchHeader' | translate) }} +

+
+
+
+ + + + + + + +
+ +

{{( 'correction-type.manage-relation.search.notFound' | translate)}}

+
+
+ +
+
+
+ +
+
+ +
+
+
diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.scss b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts new file mode 100644 index 00000000000..d012163f7b3 --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageRelationCorrectionTypeComponent } from './manage-relation-correction-type.component'; + +describe('ManageRelationCorrectionTypeComponent', () => { + let component: ManageRelationCorrectionTypeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageRelationCorrectionTypeComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageRelationCorrectionTypeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts new file mode 100644 index 00000000000..5f5d5b9c45e --- /dev/null +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -0,0 +1,252 @@ +import { NotificationsService } from './../../../notifications/notifications.service'; +import { OpenaireBrokerEventObject } from './../../../../core/openaire/broker/models/openaire-broker-event.model'; +import { getFirstSucceededRemoteDataPayload } from './../../../../core/shared/operators'; +import { ItemDataService } from './../../../../core/data/item-data.service'; +import { OpenaireBrokerEventRestService } from './../../../../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { Context } from './../../../../core/shared/context.model'; +import { CollectionElementLinkType } from './../../../object-collection/collection-element-link.type'; +import { DSpaceObject } from './../../../../core/shared/dspace-object.model'; +import { SearchResult } from './../../../search/models/search-result.model'; +import { RemoteData } from './../../../../core/data/remote-data'; +import { PaginatedList } from './../../../../core/data/paginated-list.model'; +import { PaginatedSearchOptions } from './../../../search/models/paginated-search-options.model'; +import { SelectableListService } from './../../../object-list/selectable-list/selectable-list.service'; +import { SearchService } from './../../../../core/shared/search/search.service'; +import { PaginationComponentOptions } from './../../../pagination/pagination-component-options.model'; +import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; +import { renderCorrectionFor } from '../../correction-suggestion-page.decorator'; +import { CorrectionTypeMode } from '../../../../core/submission/models/correction-type-mode.model'; +import { CorrectionTypeForms } from './../correction-type-forms'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { Observable, Subscription, of as observableOf, switchMap } from 'rxjs'; +import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; +import { ListableObject } from '../../../../shared/object-collection/shared/listable-object.model'; +import { Item } from '../../../../core/shared/item.model'; +import { ImportType } from '../../../../openaire/broker/project-entry-import-modal/project-entry-import-modal.component'; + +@Component({ + selector: 'ds-manage-relation-correction-type', + templateUrl: './manage-relation-correction-type.component.html', + styleUrls: ['./manage-relation-correction-type.component.scss'] +}) +@renderCorrectionFor(CorrectionTypeForms.MANAGE_RELATION) +export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy { + + /** + * The correction type object + */ + correctionType: CorrectionTypeMode; + + /** + * The item uuid from the parent object + */ + itemUuid: string; + + /** + * The project title from the parent object + */ + projectTitle = ''; + + /** + * Pagination options + */ + pagination: PaginationComponentOptions; + + /** + * The number of results per page + */ + pageSize = 3; + + /** + * Entities to show in the list + */ + localEntitiesRD$: Observable>>>; + + /** + * Search options to use for fetching projects + */ + searchOptions: PaginatedSearchOptions; + + /** + * The list of subscriptions + */ + protected subs: Subscription[] = []; + + /** + * Information about the data loading status + */ + isLoading$ = observableOf(true); + + /** + * The selected local entity + */ + selectedEntity: ListableObject; + + /** + * The type of link to render in listable elements + */ + linkTypes = CollectionElementLinkType; + + /** + * The context we're currently in (submission) + */ + context = Context.Search; + + /** + * List ID for selecting local entities + */ + entityListId = 'correction-suggestion-manage-relation'; + /** + * List ID for selecting local authorities + */ + authorityListId = 'correction-suggestion-manage-relation-authority'; + + /** + * ImportType enum + */ + importType = ImportType; + + /** + * The type of import the user currently has selected + */ + selectedImportType = ImportType.None; + + constructor( + @Inject('correctionTypeObjectProvider') private correctionTypeObject: CorrectionTypeMode, + public searchService: SearchService, + private selectService: SelectableListService, + private aroute: ActivatedRoute, + private openaireBrokerEventRestService: OpenaireBrokerEventRestService, + private itemService: ItemDataService, + private notificationsService: NotificationsService, + private router: Router + ) { + this.correctionType = correctionTypeObject; + this.aroute.params.subscribe((params: Params) => { + this.itemUuid = params.uuid; + }); + } + + /** + * Get the search results + */ + ngOnInit(): void { + this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'correction-suggestion-manage-relation', pageSize: this.pageSize }); + this.searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: this.correctionType.discoveryConfiguration, + scope: this.itemUuid, + pagination: this.pagination + } + )); + + this.localEntitiesRD$ = this.searchService.search(this.searchOptions); + this.subs.push( + this.localEntitiesRD$.subscribe( + () => this.isLoading$ = observableOf(false) + ) + ); + } + + + /** + * 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.correctionType.discoveryConfiguration, + query: (searchTitle) ? searchTitle.replace(filterRegEx, '') : searchTitle, + scope: this.itemUuid, + pagination: this.pagination + } + )); + this.localEntitiesRD$ = this.searchService.search(this.searchOptions); + this.subs.push( + this.localEntitiesRD$.subscribe( + () => this.isLoading$ = observableOf(false) + ) + ); + } + } + + /** + * 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); + } + + /** + * Perform the action based on the correction type + * by posting the data to the OpenAIRE Broker Event API. + * Data is formatted as follows, in the exact order: + * + * + * + */ + performAction() { + if (hasValue(this.selectedEntity)) { + const selectedItemLink = (this.selectedEntity as SearchResult).indexableObject._links.self.href; + + this.itemService.findById(this.itemUuid).pipe( + getFirstSucceededRemoteDataPayload(), + switchMap((item: Item) => { + console.log(item); + const data: string = item._links.self.href + '\n' + selectedItemLink + '\n' + this.correctionTypeObject._links.self.href; + return this.openaireBrokerEventRestService.postData(data); + }) + ).subscribe((res: RemoteData) => { + if (res.hasSucceeded) { + this.selectedImportType = ImportType.None; + // TODO: show success message based on the type of correction + this.notificationsService.success('Correction suggestion submitted', 'The correction suggestion has been submitted'); + this.deselectAllLists(); + this.back(); + } else { + this.notificationsService.error('Error submitting correction suggestion', 'The correction suggestion could not be submitted'); + } + }); + } + } + + /** + * Navigate back to the previous page + */ + back() { + this.router.navigate(['../'], { relativeTo: this.aroute }); + } + + /** + * Unsubscribe from all subscriptions. + */ + ngOnDestroy(): void { + this.deselectAllLists(); + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } +} diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index edb3f5478c9..bff10cdd5a3 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -1,3 +1,4 @@ +import { CorrectionSuggestionModule } from './../../app/shared/correction-suggestion/correction-suggestion.module'; import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { AdminRegistriesModule } from '../../app/admin/admin-registries/admin-registries.module'; @@ -299,6 +300,7 @@ const DECLARATIONS = [ NgxGalleryModule, FormModule, RequestCopyModule, + CorrectionSuggestionModule, ], declarations: DECLARATIONS, exports: [ From d49185e449faeacf32723330a488d4300737873a Mon Sep 17 00:00:00 2001 From: Mykhaylo Date: Mon, 30 Oct 2023 12:23:01 +0100 Subject: [PATCH 119/592] [CST-11178][CST-11179] POST action of correction suggestion --- .../quality-assurance-event-data.service.ts | 3 ++- .../correction-suggestion.component.ts | 2 +- ...nage-relation-correction-type.component.ts | 23 ++++++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts index c2acc7490a3..ae1538f7bb2 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts @@ -25,6 +25,7 @@ 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'; +import { HttpHeaders } from '@angular/common/http'; /** * The service handling all Quality Assurance topic REST requests. @@ -212,7 +213,7 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService { - const request = new PostRequest(requestId, href, data); + const request = new PostRequest(requestId, href, data, { headers: new HttpHeaders().set('Content-Type', 'text/uri-list') }); if (hasValue(this.responseMsToLive)) { request.responseMsToLive = this.responseMsToLive; } diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.ts index 2a2772a21dd..dcf379bd771 100644 --- a/src/app/shared/correction-suggestion/correction-suggestion.component.ts +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.ts @@ -6,7 +6,7 @@ import { GenericConstructor } from '../../core/shared/generic-constructor'; import { getCorrectionComponent } from './correction-suggestion-page.decorator'; import { ActivatedRoute, Params } from '@angular/router'; import { hasValue } from '../empty.util'; -import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; +import { getFirstCompletedRemoteData } from '../../core/shared/operators'; @Component({ selector: 'ds-correction-suggestion', diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 5f5d5b9c45e..3ad300a2a65 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -1,6 +1,6 @@ import { NotificationsService } from './../../../notifications/notifications.service'; import { OpenaireBrokerEventObject } from './../../../../core/openaire/broker/models/openaire-broker-event.model'; -import { getFirstSucceededRemoteDataPayload } from './../../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from './../../../../core/shared/operators'; import { ItemDataService } from './../../../../core/data/item-data.service'; import { OpenaireBrokerEventRestService } from './../../../../core/openaire/broker/events/openaire-broker-event-rest.service'; import { Context } from './../../../../core/shared/context.model'; @@ -23,6 +23,7 @@ import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { ListableObject } from '../../../../shared/object-collection/shared/listable-object.model'; import { Item } from '../../../../core/shared/item.model'; import { ImportType } from '../../../../openaire/broker/project-entry-import-modal/project-entry-import-modal.component'; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'ds-manage-relation-correction-type', @@ -119,7 +120,8 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy private openaireBrokerEventRestService: OpenaireBrokerEventRestService, private itemService: ItemDataService, private notificationsService: NotificationsService, - private router: Router + private router: Router, + private translate: TranslateService ) { this.correctionType = correctionTypeObject; this.aroute.params.subscribe((params: Params) => { @@ -134,8 +136,8 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'correction-suggestion-manage-relation', pageSize: this.pageSize }); this.searchOptions = Object.assign(new PaginatedSearchOptions( { - configuration: this.correctionType.discoveryConfiguration, - scope: this.itemUuid, + configuration: 'default', //this.correctionType.discoveryConfiguration, + scope: null, pagination: this.pagination } )); @@ -148,7 +150,6 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy ); } - /** * Perform a project search by title. */ @@ -215,19 +216,19 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy this.itemService.findById(this.itemUuid).pipe( getFirstSucceededRemoteDataPayload(), switchMap((item: Item) => { - console.log(item); - const data: string = item._links.self.href + '\n' + selectedItemLink + '\n' + this.correctionTypeObject._links.self.href; + const data: string = this.correctionTypeObject._links.self.href + '\n' + item._links.self.href + '\n' + selectedItemLink; return this.openaireBrokerEventRestService.postData(data); - }) + }), + getFirstCompletedRemoteData() ).subscribe((res: RemoteData) => { if (res.hasSucceeded) { this.selectedImportType = ImportType.None; - // TODO: show success message based on the type of correction - this.notificationsService.success('Correction suggestion submitted', 'The correction suggestion has been submitted'); + const message = 'correction-type.manage-relation.' + this.correctionTypeObject.id + '.notification.success'; + this.notificationsService.success(this.translate.instant(message)); this.deselectAllLists(); this.back(); } else { - this.notificationsService.error('Error submitting correction suggestion', 'The correction suggestion could not be submitted'); + this.notificationsService.error(this.translate.instant('correction-type.manage-relation.action.notification.error')); } }); } From eeefd867d471e1b1d7750695e208c4ec4eb0a1b9 Mon Sep 17 00:00:00 2001 From: Mykhaylo Date: Mon, 30 Oct 2023 12:24:10 +0100 Subject: [PATCH 120/592] [CST-11179][CST-11178] Fixes --- .../submission/correctiontype-data.service.ts | 18 +- .../models/correction-type-mode.model.ts | 2 +- .../correction-type-menu.component.spec.ts | 4 +- .../correction-type-menu.component.ts | 8 +- .../correction-suggestion.component.spec.ts | 59 ++++++- .../correction-suggestion.component.ts | 12 +- ...ge-relation-correction-type.component.html | 4 +- ...relation-correction-type.component.spec.ts | 154 +++++++++++++++++- ...nage-relation-correction-type.component.ts | 20 +-- 9 files changed, 240 insertions(+), 41 deletions(-) diff --git a/src/app/core/submission/correctiontype-data.service.ts b/src/app/core/submission/correctiontype-data.service.ts index 4d293558f7f..d9675894d32 100644 --- a/src/app/core/submission/correctiontype-data.service.ts +++ b/src/app/core/submission/correctiontype-data.service.ts @@ -8,7 +8,7 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { ObjectCacheService } from '../cache/object-cache.service'; import { IdentifiableDataService } from '../data/base/identifiable-data.service'; import { SearchDataImpl } from '../data/base/search-data'; -import { CorrectionTypeMode } from './models/correction-type-mode.model'; +import { CorrectionType } from './models/correction-type-mode.model'; import { Observable, map } from 'rxjs'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list.model'; @@ -20,12 +20,12 @@ import { getAllSucceededRemoteDataPayload, getPaginatedListPayload } from '../sh * A service that provides methods to make REST requests with correctiontypes endpoint. */ @Injectable() -@dataService(CorrectionTypeMode.type) -export class CorrectionTypeDataService extends IdentifiableDataService { +@dataService(CorrectionType.type) +export class CorrectionTypeDataService extends IdentifiableDataService { protected linkPath = 'correctiontypes'; protected searchByTopic = 'findByTopic'; protected searchFindByItem = 'findByItem'; - private searchData: SearchDataImpl; + private searchData: SearchDataImpl; constructor( protected requestService: RequestService, @@ -44,9 +44,9 @@ export class CorrectionTypeDataService extends IdentifiableDataService>} the correction type + * @returns {Observable>} the correction type */ - getCorrectionTypeById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable> { + getCorrectionTypeById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable> { return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale); } @@ -56,7 +56,7 @@ export class CorrectionTypeDataService extends IdentifiableDataService>> { + findByItem(itemUuid: string, useCachedVersionIfAvailable): Observable>> { const options = new FindListOptions(); options.searchParams = [new RequestParam('uuid', itemUuid)]; return this.searchData.searchBy(this.searchFindByItem, options, useCachedVersionIfAvailable); @@ -69,7 +69,7 @@ export class CorrectionTypeDataService extends IdentifiableDataService { + findByTopic(topic: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable { const options = new FindListOptions(); options.searchParams = [ { @@ -81,7 +81,7 @@ export class CorrectionTypeDataService extends IdentifiableDataService { + map((list: CorrectionType[]) => { return list[0]; }) ); diff --git a/src/app/core/submission/models/correction-type-mode.model.ts b/src/app/core/submission/models/correction-type-mode.model.ts index b9bb033d867..4daac538933 100644 --- a/src/app/core/submission/models/correction-type-mode.model.ts +++ b/src/app/core/submission/models/correction-type-mode.model.ts @@ -6,7 +6,7 @@ import { excludeFromEquals } from '../../utilities/equals.decorators'; import { HALLink } from '../../shared/hal-link.model'; @typedObject -export class CorrectionTypeMode extends CacheableObject { +export class CorrectionType extends CacheableObject { static type = new ResourceType('correctiontype'); /** diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts index 0f2eb02f601..a6713a12a8c 100644 --- a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.spec.ts @@ -13,7 +13,7 @@ import { CorrectionTypeDataService } from '../../../core/submission/correctionty import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { NotificationsService } from '../../notifications/notifications.service'; import { By } from '@angular/platform-browser'; -import { CorrectionTypeMode } from '../../../core/submission/models/correction-type-mode.model'; +import { CorrectionType } from '../../../core/submission/models/correction-type-mode.model'; describe('CorrectionTypeMenuComponent', () => { let component: CorrectionTypeMenuComponent; @@ -23,7 +23,7 @@ describe('CorrectionTypeMenuComponent', () => { let correctionTypeService: any; let dso: DSpaceObject; const notificationService = new NotificationsServiceStub(); - const correctionType: CorrectionTypeMode = Object.assign(new CorrectionTypeMode(), { + const correctionType: CorrectionType = Object.assign(new CorrectionType(), { id: 'addpersonalpath', creationForm:'manageRelation', discoveryConfiguration: 'RELATION.PersonPath.Items', diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts index 51aaafb7e42..ac209757b7a 100644 --- a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.ts @@ -5,7 +5,7 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { ContextMenuEntryComponent } from '../context-menu-entry.component'; import { ContextMenuEntryType } from '../context-menu-entry-type'; import { BehaviorSubject, Observable, Subscription, map, startWith} from 'rxjs'; -import { CorrectionTypeMode } from '../../../core/submission/models/correction-type-mode.model'; +import { CorrectionType } from '../../../core/submission/models/correction-type-mode.model'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { NotificationsService } from '../../notifications/notifications.service'; import { hasValue, isNotEmpty } from '../../empty.util'; @@ -28,7 +28,7 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple * List of Edit Modes available on this item * for the current user */ - private correctionTypes$: BehaviorSubject = new BehaviorSubject([]); + private correctionTypes$: BehaviorSubject = new BehaviorSubject([]); /** * Variable to track subscription and unsubscribe it onDestroy @@ -53,7 +53,7 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple /** * Check if edit mode is available */ - getCorrectionTypes(): Observable { + getCorrectionTypes(): Observable { return this.correctionTypes$; } @@ -75,7 +75,7 @@ export class CorrectionTypeMenuComponent extends ContextMenuEntryComponent imple getAllSucceededRemoteDataPayload(), getPaginatedListPayload(), startWith([]) - ).subscribe((types: CorrectionTypeMode[]) => { + ).subscribe((types: CorrectionType[]) => { this.correctionTypes$.next(types); }); } diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts index c5876712a90..cdb793f7ea8 100644 --- a/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.spec.ts @@ -1,14 +1,61 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - import { CorrectionSuggestionComponent } from './correction-suggestion.component'; +import { ActivatedRoute } from '@angular/router'; +import { CorrectionTypeDataService } from 'src/app/core/submission/correctiontype-data.service'; +import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { CommonModule } from '@angular/common'; +import { BrowserModule } from '@angular/platform-browser'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; describe('CorrectionSuggestionComponent', () => { let component: CorrectionSuggestionComponent; let fixture: ComponentFixture; + const correctionTypeMock = { + id: 'addpersonalpath', + topic: '/DSPACEUSERS/RELATIONADD/PERSONALPATH', + discoveryConfiguration: 'RELATION.PersonPath.Items', + creationForm: 'manageRelation', + type: 'correctiontype', + _links: { + self: { + href: 'https://rest.api/discover/configurations/addpersonalpath', + }, + }, + }; + + const correctionTypeMockRD$ = createSuccessfulRemoteDataObject$(correctionTypeMock); + + const mockActivatedRoute = { + snapshot:{ + params: { + correctionType: 'addpersonalpath' + } + } + }; + + let correctionTypeDataService: any; + beforeEach(async () => { + correctionTypeDataService = jasmine.createSpyObj('correctionTypeDataService', { + getCorrectionTypeById: jasmine.createSpy('getCorrectionTypeById') + }); + await TestBed.configureTestingModule({ - declarations: [ CorrectionSuggestionComponent ] + declarations: [ CorrectionSuggestionComponent ], + imports: [ + CommonModule, + BrowserModule, + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]), + ], + providers: [ + { provide: ActivatedRoute, useValue: mockActivatedRoute }, + { provide: CorrectionTypeDataService, useValue: correctionTypeDataService }, + ], + schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); }); @@ -16,10 +63,18 @@ describe('CorrectionSuggestionComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(CorrectionSuggestionComponent); component = fixture.componentInstance; + correctionTypeDataService.getCorrectionTypeById.and.returnValue(correctionTypeMockRD$); + spyOn(component, 'initComponent'); + fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should subscribe to route params and set correctionTypeId & initialize component', () => { + expect((component as any).correctionTypeId).toEqual('addpersonalpath'); + expect(component.initComponent).toHaveBeenCalled(); + }); }); diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.ts index dcf379bd771..5cd23e9b32f 100644 --- a/src/app/shared/correction-suggestion/correction-suggestion.component.ts +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.ts @@ -1,10 +1,10 @@ import { getRemoteDataPayload } from './../../core/shared/operators'; import { CorrectionTypeDataService } from './../../core/submission/correctiontype-data.service'; import { Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core'; -import { CorrectionTypeMode } from '../../core/submission/models/correction-type-mode.model'; +import { CorrectionType } from '../../core/submission/models/correction-type-mode.model'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { getCorrectionComponent } from './correction-suggestion-page.decorator'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { hasValue } from '../empty.util'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; @@ -18,7 +18,7 @@ export class CorrectionSuggestionComponent implements OnInit { /** * The correction type object */ - public correctionTypeObject: CorrectionTypeMode; + public correctionTypeObject: CorrectionType; /** * The correction type id @@ -41,9 +41,7 @@ export class CorrectionSuggestionComponent implements OnInit { private correctionTypeDataService: CorrectionTypeDataService, private injector: Injector, ) { - this.aroute.params.subscribe((params: Params) => { - this.correctionTypeId = params.correctionType; - }); + this.correctionTypeId = this.aroute.snapshot.params.correctionType; } ngOnInit(): void { @@ -61,7 +59,7 @@ export class CorrectionSuggestionComponent implements OnInit { getFirstCompletedRemoteData(), getRemoteDataPayload(), ) - .subscribe((correctionType: CorrectionTypeMode) => { + .subscribe((correctionType: CorrectionType) => { if (hasValue(correctionType)) { this.correctionTypeObject = correctionType; this.creationForm = correctionType.creationForm; diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html index fe3f64e8db7..f7e62857dfc 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html @@ -11,9 +11,9 @@

[placeholder]="'correction-type.manage-relation.search.placeholder' | translate" aria-label="" aria-describedby="">
+ (click)="projectTitle = ''">{{('correction-type.manage-relation.search.btn.clear' | translate)}} + (click)="search(projectTitle)">{{('correction-type.manage-relation.search.btn.search' | translate)}}

diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts index d012163f7b3..a329138c06b 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.spec.ts @@ -1,25 +1,173 @@ +import { ThemeService } from './../../../theme-support/theme.service'; + +import { SearchModule } from './../../../search/search.module'; +import { RouterMock } from './../../../mocks/router.mock'; +import { NotificationsService } from './../../../notifications/notifications.service'; +import { ItemDataService } from './../../../../core/data/item-data.service'; +import { OpenaireBrokerEventRestService } from './../../../../core/openaire/broker/events/openaire-broker-event-rest.service'; +import { Item } from './../../../../core/shared/item.model'; +import { SelectableListService } from './../../../object-list/selectable-list/selectable-list.service'; +import { OpenaireMockDspaceObject, getMockOpenaireBrokerEventRestService } from './../../../mocks/openaire.mock'; +import { PaginatedSearchOptions } from './../../../search/models/paginated-search-options.model'; +import { PaginationComponentOptions } from './../../../pagination/pagination-component-options.model'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ManageRelationCorrectionTypeComponent } from './manage-relation-correction-type.component'; +import { PageInfo } from './../../../../core/shared/page-info.model'; +import { buildPaginatedList } from './../../../../core/data/paginated-list.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from './../../../../shared/remote-data.utils'; +import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { SearchService } from './../../../../core/shared/search/search.service'; +import { of } from 'rxjs'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MockActivatedRoute } from './../../../../shared/mocks/active-router.mock'; +import { NotificationsServiceStub } from './../../../../shared/testing/notifications-service.stub'; +import { getMockTranslateService } from './../../../../shared/mocks/translate.service.mock'; +import { TranslateLoaderMock } from './../../../../shared/mocks/translate-loader.mock'; +import { SearchServiceStub } from './../../../../shared/testing/search-service.stub'; +import { BrowserModule } from '@angular/platform-browser'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { getMockThemeService } from './../../../../shared/mocks/theme-service.mock'; +import { ImportType } from './../../../../openaire/broker/project-entry-import-modal/project-entry-import-modal.component'; describe('ManageRelationCorrectionTypeComponent', () => { let component: ManageRelationCorrectionTypeComponent; + let compAsAny: any; let fixture: ComponentFixture; + const correctionTypeMock = { + id: 'addpersonalpath', + topic: '/DSPACEUSERS/RELATIONADD/PERSONALPATH', + discoveryConfiguration: 'RELATION.PersonPath.Items', + creationForm: 'manageRelation', + type: 'correctiontype', + _links: { + self: { + href: 'https://rest.api/discover/configurations/addpersonalpath', + }, + }, + }; + + const pagination = Object.assign( + new PaginationComponentOptions(), { + id: 'correction-suggestion-manage-relation', + pageSize: 3 + } + ); + + const uuid = '123e4567-e89b-12d3-a456-426614174003'; + + const searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: 'RELATION.PersonPath.Items', + scope: '123e4567-e89b-12d3-a456-426614174013', + 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); + + const searchServiceStub = Object.assign(new SearchServiceStub(), { + search: () => of(paginatedListRD), + }); + + const openaireBrokerEventRestServiceStub: any = getMockOpenaireBrokerEventRestService(); + + const itemDataService = { + findById: (id: string) => createSuccessfulRemoteDataObject$(new Item()) + }; + beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ ManageRelationCorrectionTypeComponent ] - }) - .compileComponents(); + declarations: [ManageRelationCorrectionTypeComponent, TestComponent ], + imports: [ + CommonModule, + BrowserModule, + NoopAnimationsModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }), + RouterTestingModule.withRoutes([]), + SearchModule + ], + providers: [ + { provide: 'correctionTypeObjectProvider', useValue: correctionTypeMock }, + { provide: SearchService, useValue: searchServiceStub }, + { provide: OpenaireBrokerEventRestService, useValue: openaireBrokerEventRestServiceStub }, + { provide: SelectableListService, useValue: jasmine.createSpyObj('selectableListService', ['deselect', 'select', 'deselectAll']) }, + { provide: ActivatedRoute, useValue: new MockActivatedRoute() }, + { provide: ItemDataService, useValue: itemDataService }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: Router, useValue: new RouterMock() }, + { provide: TranslateService, useValue: getMockTranslateService() }, + { provide: ThemeService, useValue: getMockThemeService() }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(ManageRelationCorrectionTypeComponent); component = fixture.componentInstance; + compAsAny = component as any; + component.localEntitiesRD$ = createSuccessfulRemoteDataObject$(paginatedList); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('search', () => { + it('should call SearchService.search', () => { + (searchServiceStub as any).search.and.returnValue(of(paginatedListRD)); + component.pagination = pagination; + component.search(''); + expect(compAsAny.searchService.search).toHaveBeenCalledWith(searchOptions); + }); + }); + + describe('selectEntity', () => { + const entity = Object.assign(new Item(), { uuid: uuid }); + beforeEach(() => { + component.selectEntity(entity); + }); + it('should set selected entity', () => { + expect(component.selectedEntity).toBe(entity); + }); + it('should set the import type to local entity', () => { + expect(component.selectedImportType).toEqual(ImportType.LocalEntity); + }); + }); + + afterEach(() => { + fixture.destroy(); + component = null; + compAsAny = null; + }); }); + +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 3ad300a2a65..9275101125e 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -15,9 +15,9 @@ import { SearchService } from './../../../../core/shared/search/search.service'; import { PaginationComponentOptions } from './../../../pagination/pagination-component-options.model'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { renderCorrectionFor } from '../../correction-suggestion-page.decorator'; -import { CorrectionTypeMode } from '../../../../core/submission/models/correction-type-mode.model'; +import { CorrectionType } from '../../../../core/submission/models/correction-type-mode.model'; import { CorrectionTypeForms } from './../correction-type-forms'; -import { ActivatedRoute, Params, Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { Observable, Subscription, of as observableOf, switchMap } from 'rxjs'; import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { ListableObject } from '../../../../shared/object-collection/shared/listable-object.model'; @@ -36,7 +36,7 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy /** * The correction type object */ - correctionType: CorrectionTypeMode; + correctionType: CorrectionType; /** * The item uuid from the parent object @@ -113,20 +113,18 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy selectedImportType = ImportType.None; constructor( - @Inject('correctionTypeObjectProvider') private correctionTypeObject: CorrectionTypeMode, - public searchService: SearchService, + @Inject('correctionTypeObjectProvider') private correctionTypeObject: CorrectionType, + private searchService: SearchService, private selectService: SelectableListService, private aroute: ActivatedRoute, private openaireBrokerEventRestService: OpenaireBrokerEventRestService, private itemService: ItemDataService, private notificationsService: NotificationsService, private router: Router, - private translate: TranslateService + private translateService: TranslateService ) { this.correctionType = correctionTypeObject; - this.aroute.params.subscribe((params: Params) => { - this.itemUuid = params.uuid; - }); + this.itemUuid = this.aroute.snapshot.params.uuid; } /** @@ -224,11 +222,11 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy if (res.hasSucceeded) { this.selectedImportType = ImportType.None; const message = 'correction-type.manage-relation.' + this.correctionTypeObject.id + '.notification.success'; - this.notificationsService.success(this.translate.instant(message)); + this.notificationsService.success(this.translateService.get(message)); this.deselectAllLists(); this.back(); } else { - this.notificationsService.error(this.translate.instant('correction-type.manage-relation.action.notification.error')); + this.notificationsService.error(this.translateService.get('correction-type.manage-relation.action.notification.error')); } }); } From d7857a6036c9bf08df3e1b3c7d7c3a17b87b82b5 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 9 Aug 2023 18:28:54 +0200 Subject: [PATCH 121/592] [CST-11179][CST-11178] fix --- .../manage-relation-correction-type.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 9275101125e..eee2053e8d3 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -134,8 +134,8 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'correction-suggestion-manage-relation', pageSize: this.pageSize }); this.searchOptions = Object.assign(new PaginatedSearchOptions( { - configuration: 'default', //this.correctionType.discoveryConfiguration, - scope: null, + configuration: this.correctionType.discoveryConfiguration, + scope: this.itemUuid, pagination: this.pagination } )); From c50dd72d9228fbfcc6d3deee9babf8d1fa876dab Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Thu, 10 Aug 2023 09:29:25 +0200 Subject: [PATCH 122/592] [CST-11178][CST-11179] allow access for authorized user only --- .../correction-type-menu.component.html | 2 +- .../correction-type-menu.component.ts | 17 +++++++++++++---- .../correction-suggestion-routing.module.ts | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html index 6504d6ecaf4..2f3b46279db 100644 --- a/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html +++ b/src/app/shared/context-menu/correction-type-menu/correction-type-menu.component.html @@ -1,4 +1,4 @@ - + From ac7cf5b4bac18baf236b3b3517702d9d3037f392 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 29 Aug 2023 11:30:29 +0200 Subject: [PATCH 127/592] [CST-11178] Fix issue while retrieving the id --- .../manage-relation-correction-type.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 4db0aff5283..3f8ebec197b 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -128,7 +128,7 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy private translateService: TranslateService ) { this.correctionType = correctionTypeObject; - this.itemUuid = this.aroute.snapshot.params.uuid; + this.itemUuid = this.aroute.snapshot.params.id; } /** From 1a525dfbe7bde36567a65e374d39202b2c23ff98 Mon Sep 17 00:00:00 2001 From: Mykhaylo Date: Mon, 30 Oct 2023 12:28:40 +0100 Subject: [PATCH 128/592] [CST-11179] Fixed breadcrumb & refresh & labels & redirection from /full page --- src/app/item-page/item-page-routing.module.ts | 6 +++++ .../correction-suggestion-routing.module.ts | 9 ++++--- .../correction-suggestion.component.ts | 4 ++- ...nage-relation-correction-type.component.ts | 26 +++++++++++-------- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/app/item-page/item-page-routing.module.ts b/src/app/item-page/item-page-routing.module.ts index 1d683201f0b..04e4ba21797 100644 --- a/src/app/item-page/item-page-routing.module.ts +++ b/src/app/item-page/item-page-routing.module.ts @@ -48,6 +48,12 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; .then((m) => m.CorrectionSuggestionModule), canActivate: [AuthenticatedGuard] }, + { + path: `full/${CORRECTION_TYPE_PATH}` , + loadChildren: () => import('../shared/correction-suggestion/correction-suggestion.module') + .then((m) => m.CorrectionSuggestionModule), + canActivate: [AuthenticatedGuard] + }, { path: ITEM_EDIT_PATH, loadChildren: () => import('./edit-item-page/edit-item-page.module') diff --git a/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts b/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts index 07b1066e6be..b562785f860 100644 --- a/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts +++ b/src/app/shared/correction-suggestion/correction-suggestion-routing.module.ts @@ -1,15 +1,16 @@ -import { ItemBreadcrumbResolver } from './../../core/breadcrumbs/item-breadcrumb.resolver'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { CorrectionSuggestionComponent } from './correction-suggestion.component'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; const routes: Routes = [ { path: ':correctionType', component: CorrectionSuggestionComponent, resolve: { - breadcrumb: ItemBreadcrumbResolver, - } + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'item-correction-suggestion.correction-type', breadcrumbKey: 'item-correction-suggestion.correction-type' }, } ]; @@ -17,7 +18,7 @@ const routes: Routes = [ imports: [RouterModule.forChild(routes)], exports: [RouterModule], providers: [ - ItemBreadcrumbResolver + I18nBreadcrumbResolver ] }) export class CorrectionSuggestionRoutingModule { } diff --git a/src/app/shared/correction-suggestion/correction-suggestion.component.ts b/src/app/shared/correction-suggestion/correction-suggestion.component.ts index 5cd23e9b32f..df70a1756fb 100644 --- a/src/app/shared/correction-suggestion/correction-suggestion.component.ts +++ b/src/app/shared/correction-suggestion/correction-suggestion.component.ts @@ -1,6 +1,6 @@ import { getRemoteDataPayload } from './../../core/shared/operators'; import { CorrectionTypeDataService } from './../../core/submission/correctiontype-data.service'; -import { Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core'; import { CorrectionType } from '../../core/submission/models/correction-type-mode.model'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { getCorrectionComponent } from './correction-suggestion-page.decorator'; @@ -40,6 +40,7 @@ export class CorrectionSuggestionComponent implements OnInit { private aroute: ActivatedRoute, private correctionTypeDataService: CorrectionTypeDataService, private injector: Injector, + private chd: ChangeDetectorRef, ) { this.correctionTypeId = this.aroute.snapshot.params.correctionType; } @@ -65,6 +66,7 @@ export class CorrectionSuggestionComponent implements OnInit { this.creationForm = correctionType.creationForm; this.componentFactoryResolver.resolveComponentFactory(this.getComponent()); this.injectData(); + this.chd.detectChanges(); } }); } diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 3f8ebec197b..63e388bf7fc 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -55,12 +55,11 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy /** * Pagination options */ - pagination: PaginationComponentOptions; - - /** - * The number of results per page - */ - pageSize = 3; + pagination: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'csmr', + pageSize: 3, + currentPage: 1 + }); /** * Entities to show in the list @@ -125,7 +124,7 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy private itemService: ItemDataService, private notificationsService: NotificationsService, private router: Router, - private translateService: TranslateService + private translateService: TranslateService, ) { this.correctionType = correctionTypeObject; this.itemUuid = this.aroute.snapshot.params.id; @@ -135,7 +134,6 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy * Get the search results */ ngOnInit(): void { - this.pagination = Object.assign(new PaginationComponentOptions(), { id: 'correction-suggestion-manage-relation', pageSize: this.pageSize }); this.searchOptions = Object.assign(new PaginatedSearchOptions( { configuration: this.correctionType.discoveryConfiguration, @@ -146,8 +144,12 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy this.localEntitiesRD$ = this.searchService.search(this.searchOptions); this.subs.push( - this.localEntitiesRD$.subscribe( - () => this.isLoading$ = observableOf(false) + this.localEntitiesRD$.pipe( + getFirstCompletedRemoteData(), + ).subscribe( + () => { + this.isLoading$ = observableOf(false); + } ) ); } @@ -169,7 +171,9 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy )); this.localEntitiesRD$ = this.searchService.search(this.searchOptions); this.subs.push( - this.localEntitiesRD$.subscribe( + this.localEntitiesRD$.pipe( + getFirstCompletedRemoteData(), + ).subscribe( () => this.isLoading$ = observableOf(false) ) ); From 143916c6049b1a13caa7bccc8edc06bb2263e3ed Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 6 Sep 2023 15:54:39 +0200 Subject: [PATCH 129/592] [CST-11178][CST-11179] fixed pagination for relationship management --- ...ge-relation-correction-type.component.html | 30 ++++---- ...nage-relation-correction-type.component.ts | 75 ++++++++++++------- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html index f7e62857dfc..32824cf6350 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.html @@ -11,26 +11,28 @@

[placeholder]="'correction-type.manage-relation.search.placeholder' | translate" aria-label="" aria-describedby="">
+ (click)="projectTitle = ''; search('')">{{('correction-type.manage-relation.search.btn.clear' | translate)}}

- - + + +
diff --git a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts index 63e388bf7fc..6e285c2987f 100644 --- a/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts +++ b/src/app/shared/correction-suggestion/correction-types/manage-relation-correction-type/manage-relation-correction-type.component.ts @@ -20,7 +20,7 @@ import { renderCorrectionFor } from '../../correction-suggestion-page.decorator' import { CorrectionType } from '../../../../core/submission/models/correction-type-mode.model'; import { CorrectionTypeForms } from '../correction-type-forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable, of as observableOf, Subscription, switchMap } from 'rxjs'; +import { finalize, Observable, of as observableOf, Subscription, switchMap } from 'rxjs'; import { hasValue, isNotEmpty } from '../../../empty.util'; import { ListableObject } from '../../../object-collection/shared/listable-object.model'; import { Item } from '../../../../core/shared/item.model'; @@ -55,9 +55,9 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy /** * Pagination options */ - pagination: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + pagination: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { id: 'csmr', - pageSize: 3, + pageSize: 10, currentPage: 1 }); @@ -99,11 +99,11 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy /** * List ID for selecting local entities */ - entityListId = 'correction-suggestion-manage-relation'; + entityListId = 'csmr'; /** * List ID for selecting local authorities */ - authorityListId = 'correction-suggestion-manage-relation-authority'; + authorityListId = 'csmr-authority'; /** * ImportType enum @@ -134,23 +134,33 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy * Get the search results */ ngOnInit(): void { - this.searchOptions = Object.assign(new PaginatedSearchOptions( - { - configuration: this.correctionType.discoveryConfiguration, - scope: this.itemUuid, - pagination: this.pagination - } - )); + this.getData(); + } - this.localEntitiesRD$ = this.searchService.search(this.searchOptions); - this.subs.push( - this.localEntitiesRD$.pipe( - getFirstCompletedRemoteData(), - ).subscribe( - () => { - this.isLoading$ = observableOf(false); + private getData(){ + this.localEntitiesRD$ = this.aroute.queryParams + .pipe( + switchMap((params) => { + if (hasValue(params)) { + this.pagination = Object.assign(new PaginationComponentOptions(),{ + ...this.pagination, + currentPage: params[`${this.pagination.id}.page`] || 1 + }); } - ) + + this.searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: this.correctionType.discoveryConfiguration, + scope: this.itemUuid, + pagination: this.pagination, + } + )); + + return this.searchService.search(this.searchOptions).pipe( + getFirstCompletedRemoteData(), + finalize(() => this.isLoading$ = observableOf(false)) + ); + }) ); } @@ -169,15 +179,24 @@ export class ManageRelationCorrectionTypeComponent implements OnInit, OnDestroy pagination: this.pagination } )); - this.localEntitiesRD$ = this.searchService.search(this.searchOptions); - this.subs.push( - this.localEntitiesRD$.pipe( - getFirstCompletedRemoteData(), - ).subscribe( - () => this.isLoading$ = observableOf(false) - ) - ); + } else { + this.searchOptions = Object.assign(new PaginatedSearchOptions( + { + configuration: this.correctionType.discoveryConfiguration, + scope: this.itemUuid, + pagination: this.pagination + } + )); } + + this.localEntitiesRD$ = this.searchService.search(this.searchOptions); + this.subs.push( + this.localEntitiesRD$.pipe( + getFirstCompletedRemoteData(), + ).subscribe( + () => this.isLoading$ = observableOf(false) + ) + ); } /** From ca64baca43b1e641f5ccbd4b7f9dcda03a0b31cd Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Mon, 30 Oct 2023 12:46:05 +0100 Subject: [PATCH 130/592] [CST-12043] feature: add title --- .../sections/upload/section-upload.component.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/app/submission/sections/upload/section-upload.component.html b/src/app/submission/sections/upload/section-upload.component.html index 5b245d37c2d..41e912e613a 100644 --- a/src/app/submission/sections/upload/section-upload.component.html +++ b/src/app/submission/sections/upload/section-upload.component.html @@ -18,6 +18,16 @@
+
+
+ {{ 'bitstream.edit.form.primaryBitstream.label' | translate }} +
+
+
+
+
+
+
Date: Mon, 30 Oct 2023 15:33:12 +0100 Subject: [PATCH 131/592] CST-11045 Dropdown behavior improved, working on multiple dropdowns --- .../section-coar-notify.component.html | 15 ++-- .../section-coar-notify.component.ts | 75 ++++++------------- 2 files changed, 31 insertions(+), 59 deletions(-) diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html index f2c7fd09473..2ce46d0520f 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -1,10 +1,11 @@
- +
- + + @@ -14,9 +15,9 @@
- Select a service for {{ pattern }} of this item -
-
+ Select a service for {{ pattern }} of this item +
+
Coar-Notify-Pattern @@ -27,7 +28,7 @@ -
{{ selectedServices[pattern].name }}: {{ selectedServices[pattern].description }}
+
{{ selectedServicesByPattern[pattern].name }}: {{ selectedServicesByPattern[pattern].description }}

- + @@ -79,6 +79,15 @@

{{ (showMore ? 'quality-assurance.event.table.less': 'quality-assurance.event.table.more') | translate }} + +

+ - - + + @@ -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 5d97dcade8d..99ee9827e81 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 feb90b52b37..6129d4d02d5 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 fb8b8bc9b00..a85d471e7db 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 bcbeef56830..91e200e85d2 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 1c3776b2d3bf8efe71132c7deae4371a36447f30 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Fri, 24 Nov 2023 11:28:38 +0100 Subject: [PATCH 218/592] [CST-12109] porting missing code --- config/config.yml | 6 +- .../admin-notifications-routing.module.ts | 5 +- src/app/admin/admin-routing.module.ts | 22 +++++-- src/app/app-routing.module.ts | 5 +- .../data/feature-authorization/feature-id.ts | 3 +- .../quality-assurance-source-data.service.ts | 3 +- .../quality-assurance-topic-data.service.ts | 39 ++++++++----- .../qa-event-notification.component.html | 9 +-- .../qa-event-notification.component.ts | 18 ++++-- .../shared/dso-page/dso-edit-menu.resolver.ts | 35 ++++++++--- .../dso-withdrawn-reinstate-modal.service.ts | 2 +- src/app/shared/shared.module.ts | 6 +- .../quality-assurance-topics.actions.ts | 8 ++- .../quality-assurance-topics.component.html | 8 ++- .../quality-assurance-topics.component.ts | 58 ++++++++++++++++--- .../quality-assurance-topics.effects.ts | 4 +- .../quality-assurance-topics.service.ts | 29 +++++----- .../suggestion-notifications-state.service.ts | 4 +- src/assets/i18n/en.json5 | 4 ++ 19 files changed, 185 insertions(+), 83 deletions(-) diff --git a/config/config.yml b/config/config.yml index b5eecd112f0..a5337cdd0d4 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,5 +1,5 @@ rest: - ssl: true - host: api7.dspace.org - port: 443 + ssl: false + host: localhost + port: 8080 nameSpace: /server 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 dc0d82c1d99..ab4d3f09faa 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -12,6 +12,9 @@ import { AdminQualityAssuranceEventsPageResolver } from './admin-quality-assuran 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'; +import { + SiteAdministratorGuard +} from '../../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; @NgModule({ imports: [ @@ -32,7 +35,7 @@ import { SourceDataResolver } from './admin-quality-assurance-source-page-compon } }, { - canActivate: [ AuthenticatedGuard ], + canActivate: [ SiteAdministratorGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}`, component: AdminQualityAssuranceSourcePageComponent, pathMatch: 'full', diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index a7d19a69357..65b16139c15 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -8,6 +8,9 @@ import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.ser import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; +import { + SiteAdministratorGuard +} from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; @NgModule({ imports: [ @@ -21,42 +24,49 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import path: REGISTRIES_MODULE_PATH, loadChildren: () => import('./admin-registries/admin-registries.module') .then((m) => m.AdminRegistriesModule), + canActivate: [SiteAdministratorGuard] }, { path: 'search', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminSearchPageComponent, - data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' } + data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }, + canActivate: [SiteAdministratorGuard] }, { path: 'workflow', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminWorkflowPageComponent, - data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' } + data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }, + canActivate: [SiteAdministratorGuard] }, { path: 'curation-tasks', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminCurationTasksComponent, - data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' } + data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }, + canActivate: [SiteAdministratorGuard] }, { path: 'metadata-import', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: MetadataImportPageComponent, - data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' } + data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' }, + canActivate: [SiteAdministratorGuard] }, { path: 'batch-import', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: BatchImportPageComponent, - data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' } + data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' }, + canActivate: [SiteAdministratorGuard] }, { path: 'system-wide-alert', resolve: { breadcrumb: I18nBreadcrumbResolver }, loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule), - data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'} + data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'}, + canActivate: [SiteAdministratorGuard] }, ]) ], diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0d7a0bd0f05..6c247eb9bfa 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,9 +3,6 @@ import { RouterModule, NoPreloading } from '@angular/router'; import { AuthBlockingGuard } from './core/auth/auth-blocking.guard'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; -import { - SiteAdministratorGuard -} from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; import { ACCESS_CONTROL_MODULE_PATH, ADMIN_MODULE_PATH, @@ -154,7 +151,7 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone path: ADMIN_MODULE_PATH, loadChildren: () => import('./admin/admin.module') .then((m) => m.AdminModule), - canActivate: [SiteAdministratorGuard, EndUserAgreementCurrentUserGuard] + canActivate: [EndUserAgreementCurrentUserGuard] }, { path: 'login', diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index 8fef45a9532..248698c1057 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -33,5 +33,6 @@ export enum FeatureID { CanSubmit = 'canSubmit', CanEditItem = 'canEditItem', CanRegisterDOI = 'canRegisterDOI', - CanSubscribe = 'canSubscribeDso', + CanSubscribe = 'canSubscribeDso' + } diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts index 30f3b848f4f..aed7f7541f8 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts @@ -16,7 +16,7 @@ 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'; -import { SearchData } from '../../../data/base/search-data'; +import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; /** * The service handling all Quality Assurance source REST requests. @@ -47,6 +47,7 @@ export class QualityAssuranceSourceDataService extends IdentifiableDataService { private findAllData: FindAllData; + private searchData: SearchData; + + private searchByTargetMethod = 'byTarget'; + private searchBySourceMethod = 'bySource'; /** * Initialize service variables @@ -43,23 +48,31 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataService>> - * The list of Quality Assurance topics. + * Search for Quality Assurance topics. + * @param options The search options. + * @param useCachedVersionIfAvailable Whether to use cached version if available. + * @param reRequestOnStale Whether to re-request on stale. + * @param linksToFollow The links to follow. + * @returns An observable of remote data containing a paginated list of Quality Assurance topics. + */ + public searchTopicsByTarget(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Searches for quality assurance topics by source. + * @param options The search options. + * @param useCachedVersionIfAvailable Whether to use a cached version if available. + * @param reRequestOnStale Whether to re-request the data if it's stale. + * @param linksToFollow The links to follow. + * @returns An observable of the remote data containing the paginated list of quality assurance topics. */ - public getTopics(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + public searchTopicsBySource(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(this.searchBySourceMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html index f2a06bd4fd3..10247001497 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html @@ -1,15 +1,12 @@
-
-
{{'item.qa-event-notification.check.notification-info' | translate : {num: - source.totalEvents } }}
-
-Added file diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts index c48d30851e5..fb6bad1b460 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -1,12 +1,13 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; -import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { Observable } from 'rxjs'; -import { AlertType } from '../../../shared/alert/aletr-type'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { RequestParam } from '../../../core/cache/models/request-param.model'; import { QualityAssuranceSourceDataService } from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; import { QualityAssuranceSourceObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; +import { map, tap } from 'rxjs/operators'; +import { RemoteData } from '../../../core/data/remote-data'; @Component({ selector: 'ds-qa-event-notification', templateUrl: './qa-event-notification.component.html', @@ -25,9 +26,8 @@ export class QaEventNotificationComponent { /** * The type of alert to display for the notification. */ - AlertTypeInfo = AlertType.Info; constructor( - private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService, + private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService ) { } /** * Returns an Observable of QualityAssuranceSourceObject[] for the current item. @@ -35,14 +35,20 @@ export class QaEventNotificationComponent { * Note: sourceId is composed as: id: "sourceName:" */ getQualityAssuranceSources$(): Observable { + console.log('ciao'); const findListTopicOptions: FindListOptions = { searchParams: [new RequestParam('target', this.item.uuid)] }; return this.qualityAssuranceSourceDataService.getSourcesByTarget(findListTopicOptions) .pipe( getFirstCompletedRemoteData(), - getRemoteDataPayload(), - getPaginatedListPayload(), + tap(console.log), + map((data: RemoteData) => { + if (data.hasSucceeded) { + return data.payload.page; + } + return []; + }) ); } } diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts index 2b270abc766..6e4985cfa31 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -8,7 +8,10 @@ import { LinkMenuItemModel } from '../menu/menu-item/models/link.model'; import { Item } from '../../core/shared/item.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { OnClickMenuItemModel } from '../menu/menu-item/models/onclick.model'; -import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { + getFirstCompletedRemoteData, + getRemoteDataPayload +} from '../../core/shared/operators'; import { map, switchMap } from 'rxjs/operators'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; @@ -22,6 +25,13 @@ import { ResearcherProfileDataService } from '../../core/profile/researcher-prof import { NotificationsService } from '../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { DsoWithdrawnReinstateModalService } from './dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { AuthService } from '../../core/auth/auth.service'; +import { + QualityAssuranceSourceDataService +} from '../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; +import { FindListOptions } from '../../core/data/find-list-options.model'; +import { RequestParam } from '../../core/cache/models/request-param.model'; /** * Creates the menus for the dspace object pages @@ -40,7 +50,9 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection protected researcherProfileService: ResearcherProfileDataService, protected notificationsService: NotificationsService, protected translate: TranslateService, - protected dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService + protected dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService, + private auth: AuthService, + private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService ) { } @@ -121,16 +133,20 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection */ protected getItemMenu(dso): Observable { if (dso instanceof Item) { + const findListTopicOptions: FindListOptions = { + searchParams: [new RequestParam('target', dso.uuid)] + }; return combineLatest([ this.authorizationService.isAuthorized(FeatureID.CanCreateVersion, dso.self), this.dsoVersioningModalService.isNewVersionButtonDisabled(dso), this.dsoVersioningModalService.getVersioningTooltipMessage(dso, 'item.page.version.hasDraft', 'item.page.version.create'), this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, dso.self), this.authorizationService.isAuthorized(FeatureID.CanClaimItem, dso.self), - this.authorizationService.isAuthorized(FeatureID.WithdrawItem, dso.self,), - this.authorizationService.isAuthorized(FeatureID.ReinstateItem, dso.self) + this.qualityAssuranceSourceDataService.getSourcesByTarget(findListTopicOptions).pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload()) ]).pipe( - map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem, canWithdrawItem, canReinstateItem]) => { + map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem, correction]) => { const isPerson = this.getDsoType(dso) === 'person'; return [ { @@ -177,12 +193,12 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection { id: 'withdrawn-item', active: false, - visible: canWithdrawItem, + visible: dso.isArchived && correction.totalElements === 0, model: { type: MenuItemType.ONCLICK, text:'item.page.withdrawn', function: () => { - this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-withdrawn', canWithdrawItem); + this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-withdrawn', dso.isArchived && correction.totalElements === 0); } } as OnClickMenuItemModel, icon: 'lock', @@ -191,12 +207,12 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection { id: 'reinstate-item', active: false, - visible: canReinstateItem, + visible: dso.isWithdrawn && correction.totalElements === 0, model: { type: MenuItemType.ONCLICK, text:'item.page.reinstate', function: () => { - this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-reinstate', canWithdrawItem); + this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-reinstate', dso.isWithdrawn && correction.totalElements === 0); } } as OnClickMenuItemModel, icon: 'unlock-keyhole', @@ -258,4 +274,5 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection return menu; }); } + } diff --git a/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts b/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts index ce491a89a50..242a5c1fc41 100644 --- a/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts +++ b/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts @@ -38,7 +38,7 @@ export class DsoWithdrawnReinstateModalService { const target = dso.id; // Open modal const activeModal = this.modalService.open(ItemWithdrawnReinstateModalComponent); - (activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).setWithdraw(!state); + (activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).setWithdraw(state); (activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).createQAEvent .pipe( take(1) diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 2881d46c2bd..b2b2420f105 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -288,6 +288,9 @@ import { QualityAssuranceEventDataService } from '../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; import { SplitPipe } from './utils/split.pipe'; +import { + QualityAssuranceSourceDataService +} from '../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; const MODULES = [ CommonModule, @@ -477,7 +480,8 @@ const PROVIDERS = [ TruncatableService, MockAdminGuard, AbstractTrackableComponent, - QualityAssuranceEventDataService + QualityAssuranceEventDataService, + QualityAssuranceSourceDataService ]; const DIRECTIVES = [ diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.actions.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.actions.ts index 2459d4352ab..482a85a9882 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.actions.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.actions.ts @@ -25,6 +25,8 @@ export class RetrieveAllTopicsAction implements Action { payload: { elementsPerPage: number; currentPage: number; + source: string; + target?: string; }; /** @@ -35,10 +37,12 @@ export class RetrieveAllTopicsAction implements Action { * @param currentPage * The page number to retrieve */ - constructor(elementsPerPage: number, currentPage: number) { + constructor(elementsPerPage: number, currentPage: number, source: string, target?: string) { this.payload = { elementsPerPage, - currentPage + currentPage, + source, + target }; } } 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 db8586f264d..ed91bbf6cab 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,7 +2,11 @@
@@ -15,7 +19,7 @@

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

[collectionSize]="(totalElements$ | async)" [hideGear]="false" [hideSortOptions]="true" - (paginationChange)="getQualityAssuranceTopics()"> + (paginationChange)="getQualityAssuranceTopics(sourceId, targetId)"> diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts index 3c8b4f8f38a..0f7a111089d 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-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, tap } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; import { @@ -15,7 +15,10 @@ import { } 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 { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; +import { Item } from '../../../core/shared/item.model'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; /** * Component to display the Quality Assurance topic list. @@ -60,6 +63,17 @@ export class QualityAssuranceTopicsComponent implements OnInit { */ public sourceId: string; + /** + * This property represents a targetId (item-id) which is used to retrive a topic + * @type {string} + */ + public targetId: string; + + /** + * The URL of the item page. + */ + public itemPageUrl: string; + /** * Initialize the component variables. * @param {PaginationService} paginationService @@ -71,16 +85,16 @@ export class QualityAssuranceTopicsComponent implements OnInit { private paginationService: PaginationService, private activatedRoute: ActivatedRoute, private notificationsStateService: SuggestionNotificationsStateService, - private qualityAssuranceTopicsService: QualityAssuranceTopicsService + private itemService: ItemDataService ) { + this.sourceId = this.activatedRoute.snapshot.params.sourceId; + this.targetId = this.activatedRoute.snapshot.params.targetId; } /** * Component initialization. */ ngOnInit(): void { - this.sourceId = this.activatedRoute.snapshot.paramMap.get('sourceId'); - this.qualityAssuranceTopicsService.setSourceId(this.sourceId); this.topics$ = this.notificationsStateService.getQualityAssuranceTopics(); this.totalElements$ = this.notificationsStateService.getQualityAssuranceTopicsTotals(); } @@ -93,7 +107,7 @@ export class QualityAssuranceTopicsComponent implements OnInit { this.notificationsStateService.isQualityAssuranceTopicsLoaded().pipe( take(1) ).subscribe(() => { - this.getQualityAssuranceTopics(); + this.getQualityAssuranceTopics(this.sourceId, this.targetId); }) ); } @@ -121,13 +135,15 @@ export class QualityAssuranceTopicsComponent implements OnInit { /** * Dispatch the Quality Assurance topics retrival. */ - public getQualityAssuranceTopics(): void { + public getQualityAssuranceTopics(source: string, target?: string): void { this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( distinctUntilChanged(), ).subscribe((options: PaginationComponentOptions) => { this.notificationsStateService.dispatchRetrieveQualityAssuranceTopics( options.pageSize, - options.currentPage + options.currentPage, + source, + target ); }); } @@ -150,6 +166,32 @@ export class QualityAssuranceTopicsComponent implements OnInit { } } + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } + + /** + * Returns the page route for the given item. + * @param item The item to get the page route for. + * @returns The page route for the given item. + */ + getItemPageRoute(item: Item): string { + return getItemPageRoute(item); + } + /** * Unsubscribe from all subscriptions. */ 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 13e36700001..92d7dc9e21c 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 @@ -37,7 +37,9 @@ export class QualityAssuranceTopicsEffects { switchMap(([action, currentState]: [RetrieveAllTopicsAction, any]) => { return this.qualityAssuranceTopicService.getTopics( action.payload.elementsPerPage, - action.payload.currentPage + action.payload.currentPage, + action.payload.source, + action.payload.target ).pipe( map((topics: PaginatedList) => new AddTopicsAction(topics.page, topics.totalPages, topics.currentPage, topics.totalElements) 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 6820791dffd..4144cd88758 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 @@ -13,6 +13,7 @@ import { import { RequestParam } from '../../../core/cache/models/request-param.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; /** * The service handling all Quality Assurance topic requests to the REST service. @@ -28,10 +29,6 @@ export class QualityAssuranceTopicsService { private qualityAssuranceTopicRestService: QualityAssuranceTopicDataService ) { } - /** - * sourceId used to get topics - */ - sourceId: string; /** * Return the list of Quality Assurance topics managing pagination and errors. @@ -43,17 +40,25 @@ export class QualityAssuranceTopicsService { * @return Observable> * The list of Quality Assurance topics. */ - public getTopics(elementsPerPage, currentPage): Observable> { + public getTopics(elementsPerPage, currentPage, source: string, target?: string): Observable> { const sortOptions = new SortOptions('name', SortDirection.ASC); - const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, currentPage: currentPage, sort: sortOptions, - searchParams: [new RequestParam('source', this.sourceId)] + searchParams: [new RequestParam('source', source)] }; - return this.qualityAssuranceTopicRestService.getTopics(findListOptions).pipe( + let request$: Observable>>; + + if (hasValue(target)) { + findListOptions.searchParams.push(new RequestParam('target', target)); + request$ = this.qualityAssuranceTopicRestService.searchTopicsByTarget(findListOptions); + } else { + request$ = this.qualityAssuranceTopicRestService.searchTopicsBySource(findListOptions); + } + + return request$.pipe( getFirstCompletedRemoteData(), map((rd: RemoteData>) => { if (rd.hasSucceeded) { @@ -64,12 +69,4 @@ export class QualityAssuranceTopicsService { }) ); } - - /** - * set sourceId which is used to get topics - * @param sourceId string - */ - setSourceId(sourceId: string) { - this.sourceId = sourceId; - } } diff --git a/src/app/suggestion-notifications/suggestion-notifications-state.service.ts b/src/app/suggestion-notifications/suggestion-notifications-state.service.ts index ec1ea2e0394..1fc54220188 100644 --- a/src/app/suggestion-notifications/suggestion-notifications-state.service.ts +++ b/src/app/suggestion-notifications/suggestion-notifications-state.service.ts @@ -118,8 +118,8 @@ export class SuggestionNotificationsStateService { * @param currentPage * The number of the current page. */ - public dispatchRetrieveQualityAssuranceTopics(elementsPerPage: number, currentPage: number): void { - this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage)); + public dispatchRetrieveQualityAssuranceTopics(elementsPerPage: number, currentPage: number, sourceId: string, targteId?: string): void { + this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage, sourceId, targteId)); } // Quality Assurance source diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 435e0a30588..f277a934233 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2604,6 +2604,10 @@ "item.qa.withdrawn.modal.submitted.header": "Sending withdrawn request...", + "item.qa-event-notification.check.notification-withdrawn": "You have requested to withdrawn this item.", + + "item.qa-event-notification-undo-withdrawn.check.button": "Undo request withdrawal", + "item.version.create.modal.submitted.text": "The new version is being created. This may take some time if the item has a lot of relationships.", "item.version.create.notification.success": "New version has been created with version number {{version}}", From e229be44d6450f9c50ed2d53f4b5d9cb7939fcd1 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 25 Nov 2023 14:21:57 +0100 Subject: [PATCH 219/592] 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 4cb9577fcb5..bd4c9334ad3 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 88efd2a711e..9522be29ce3 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 13d84e6e2e1..d4c0cd1a377 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -62,10 +62,11 @@
Footer Content
{{ 'footer.link.lyrasis' | translate}}

-
@@ -226,3 +235,20 @@ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7392b3da7ac..f6630d594db 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 233/592] 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 ce6d62efec3..c55592f3e77 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 4bf06bbadec..1f1559b50bd 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 56fece56b40..818a292e338 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 914b331413b..68171a23b29 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 38f119ad5bb..76b01b87096 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 f367d3779f2..4e77f4ed1b9 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 e69de29bb2d..8c6325f95a1 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 cac3fbd82d5..a741eacc867 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 @@
-
\ No newline at end of file +
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 0a2e9f0f926..45d8ed5d11c 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 @@
{{ 'service.overview.table.name' | translate }}{{ 'service.overview.table.description' | translate }}{{ 'service.overview.table.status' | translate }}{{ 'service.overview.table.actions' | translate }}
{{ 'service.overview.table.name' | translate }}{{ 'service.overview.table.description' | translate }}{{ 'service.overview.table.status' | translate }}{{ 'service.overview.table.actions' | translate }}
{{ ldnService.name }} {{ ldnService.description }} - + {{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }}
- - -
+ + +
-

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

+

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

From 7fcd82a7e85afaa8c5295def693b8519d4d2ae56 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 3 Nov 2023 11:28:47 +0100 Subject: [PATCH 151/592] CST-12179 removed console.log --- .../ldn-service-form/ldn-service-form.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index a8412ec9915..6a37880ff79 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -139,7 +139,6 @@ export class LdnServiceFormComponent implements OnInit { const hasOutboundPattern = this.checkPatterns(this.formModel.get('notifyServiceOutboundPatterns') as FormArray); if (!name || !url || !ldnUrl || !score || (!hasInboundPattern && !hasOutboundPattern)) { - console.log('qualcosa non va'); this.closeModal(); return; } From ef1bd9fa3dd823ac2a8b89d7e6fa9f7bbe269252 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Fri, 3 Nov 2023 12:18:19 +0100 Subject: [PATCH 152/592] [CST-12109] improve code --- .../models/quality-assurance-event.model.ts | 2 + ...m-withdrawn-reinstate-modal.component.html | 4 +- .../shared/dso-page/dso-edit-menu.resolver.ts | 14 ++-- .../dso-reinstate-modal.service.ts | 69 ------------------- .../dso-withdrawn-reinstate-modal.service.ts} | 17 +++-- .../quality-assurance-events.component.html | 15 +++- .../quality-assurance-events.component.ts | 8 ++- src/assets/i18n/en.json5 | 4 +- 8 files changed, 41 insertions(+), 92 deletions(-) delete mode 100644 src/app/shared/dso-page/dso-reinstate-service/dso-reinstate-modal.service.ts rename src/app/shared/dso-page/{dso-withdrawn-service/dso-withdrawn-modal.service.ts => dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts} (72%) 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 7517148def4..02d86bab700 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 @@ -28,6 +28,8 @@ export interface OpenaireQualityAssuranceEventMessageObject { */ type: string; + reason: string; + /** * The value suggested by Notifications */ diff --git a/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html b/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html index 1201fbee6f2..f0e248c647e 100644 --- a/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html +++ b/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html @@ -7,8 +7,8 @@

{{'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.reasons' | translate}} + {{'quality-assurance.event.table.actions' | translate}}
+

+ + {{eventElement.event.message.reason}}
+
+

+

{{'quality-assurance.event.table.suggestedProject' | translate}} 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 e34c121f359..18d05172858 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 @@ -151,9 +151,11 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ public hasDetailColumn(): boolean { return (this.showTopic.indexOf('/PROJECT') !== -1 || - this.showTopic.indexOf('/PID') !== -1 || - this.showTopic.indexOf('/SUBJECT') !== -1 || - this.showTopic.indexOf('/ABSTRACT') !== -1 + this.showTopic.indexOf('/PID') !== -1 || + this.showTopic.indexOf('/SUBJECT') !== -1 || + this.showTopic.indexOf('/WITHDRAWN') !== -1 || + this.showTopic.indexOf('/REINSTATE') !== -1 || + this.showTopic.indexOf('/ABSTRACT') !== -1 ); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4b03ce208f9..435e0a30588 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2594,7 +2594,7 @@ "item.version.create.modal.form.summary.label": "Summary", - "item.qa-withdrawn-reinstate.create.modal.form.summary.label": "Summary", + "item.qa-withdrawn-reinstate.create.modal.form.summary.label": "Reason", "item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version", @@ -3158,6 +3158,8 @@ "quality-assurance.event.table.project-details": "Project details", + "quality-assurance.event.table.reasons": "Reasons", + "quality-assurance.event.table.actions": "Actions", "quality-assurance.event.action.accept": "Accept suggestion", From f74efd62a54f95adacb2680fed1f9ef588f7757c Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Fri, 3 Nov 2023 17:54:45 +0100 Subject: [PATCH 153/592] [CST-12490] unit test fixes --- .../ldn-service-form-edit.component.spec.ts | 86 +++++++++++++++---- .../ldn-service-form.component.spec.ts | 83 +++++++++++++++--- .../ldn-service-new.component.ts | 22 +---- .../ldn-services-directory.component.spec.ts | 65 ++++++++++---- .../ldn-directory.service.spec.ts | 17 ---- .../ldn-directory.service.ts | 29 ------- .../ldn-service-bulk-delete.service.spec.ts | 17 ---- .../notify-info/notify-info.component.spec.ts | 11 ++- .../notify-info/notify-info.component.ts | 2 +- .../notify-info/notify-info.guard.spec.ts | 35 +++++++- .../notify-info/notify-info.guard.ts | 2 +- .../notify-info/notify-info.service.spec.ts | 36 +++++++- .../workspaceitem-data.service.spec.ts | 15 ++-- .../submission/workspaceitem-data.service.ts | 14 +++ src/app/footer/footer.component.spec.ts | 8 ++ .../full/full-item-page.component.spec.ts | 15 +++- .../full/full-item-page.component.ts | 2 +- .../simple/item-page.component.spec.ts | 17 ++-- .../suggestions-popup.component.spec.ts | 3 +- .../suggestions-popup.component.ts | 1 - src/environments/environment.test.ts | 4 + 21 files changed, 327 insertions(+), 157 deletions(-) delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts index 332d43cae3b..74a4fb4aba2 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts @@ -1,23 +1,79 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LdnServiceFormEditComponent } from './ldn-service-form-edit.component'; +import { ChangeDetectorRef, EventEmitter } from '@angular/core'; +import { ReactiveFormsModule, FormBuilder } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { PaginationService } from 'ngx-pagination'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { LdnItemfiltersService } from '../ldn-services-data/ldn-itemfilters-data.service'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { RouterStub } from '../../../shared/testing/router.stub'; +import { MockActivatedRoute } from '../../../shared/mocks/active-router.mock'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { of } from 'rxjs'; +import { RouteService } from '../../../core/services/route.service'; +import { provideMockStore } from '@ngrx/store/testing'; describe('LdnServiceFormEditComponent', () => { - let component: LdnServiceFormEditComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [LdnServiceFormEditComponent] - }) - .compileComponents(); - - fixture = TestBed.createComponent(LdnServiceFormEditComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + let component: LdnServiceFormEditComponent; + let fixture: ComponentFixture; + + let ldnServicesService: any; + let ldnItemfiltersService: any; + let cdRefStub: any; + let modalService: any; + + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; - it('should create', () => { - expect(component).toBeTruthy(); + beforeEach(async () => { + ldnServicesService = { + update: () => ({}), + }; + ldnItemfiltersService = { + findAll: () => of(['item1', 'item2']), + }; + cdRefStub = Object.assign({ + detectChanges: () => fixture.detectChanges() }); + modalService = { + open: () => {/*comment*/ + } + }; + + await TestBed.configureTestingModule({ + imports: [ReactiveFormsModule, TranslateModule.forRoot()], + declarations: [LdnServiceFormEditComponent], + providers: [ + { provide: LdnServicesService, useValue: ldnServicesService }, + { provide: LdnItemfiltersService, useValue: ldnItemfiltersService }, + { provide: Router, useValue: new RouterStub() }, + { provide: ActivatedRoute, useValue: new MockActivatedRoute() }, + { provide: ChangeDetectorRef, useValue: cdRefStub }, + { provide: NgbModal, useValue: modalService }, + { provide: NotificationsService, useValue: NotificationsServiceStub }, + { provide: TranslateService, useValue: translateServiceStub }, + { provide: PaginationService, useValue: {} }, + FormBuilder, + RouteService, + provideMockStore({ }), + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LdnServiceFormEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts index 757b6170911..c5c9f118178 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -1,25 +1,80 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LdnServiceFormComponent } from './ldn-service-form.component'; +import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { LdnItemfiltersService } from '../ldn-services-data/ldn-itemfilters-data.service'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { NotificationsService } from 'src/app/shared/notifications/notifications.service'; +import { Router } from '@angular/router'; +import { RouterStub } from 'src/app/shared/testing/router.stub'; +import { createPaginatedList } from 'src/app/shared/testing/utils.test'; +import { Itemfilter } from '../ldn-services-model/ldn-service-itemfilters'; +import { createSuccessfulRemoteDataObject$ } from 'src/app/shared/remote-data.utils'; +import { of } from 'rxjs'; +import { EventEmitter } from '@angular/core'; describe('LdnServiceFormComponent', () => { - let component: LdnServiceFormComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [LdnServiceFormComponent] - }) - .compileComponents(); + let component: LdnServiceFormComponent; + let fixture: ComponentFixture; + + let ldnServicesService: any; + let ldnItemfiltersService: any; + let notificationsService: any; + + const itemFiltersRdPL$ = createSuccessfulRemoteDataObject$(createPaginatedList([new Itemfilter()])); + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; + + beforeEach(async () => { + ldnItemfiltersService = jasmine.createSpyObj('ldnItemfiltersService', { + findAll: jasmine.createSpy('findAll'), }); - beforeEach(() => { - fixture = TestBed.createComponent(LdnServiceFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); + ldnServicesService = jasmine.createSpyObj('ldnServicesService', { + create: jasmine.createSpy('create'), }); - it('should create', () => { - expect(component).toBeTruthy(); + notificationsService = jasmine.createSpyObj('notificationsService', { + success: jasmine.createSpy('success'), + error: jasmine.createSpy('error'), }); + + await TestBed.configureTestingModule({ + imports: [ + ReactiveFormsModule, + RouterTestingModule, + NgbModalModule, + TranslateModule.forRoot() + ], + providers: [ + { provide: LdnItemfiltersService, useValue: ldnItemfiltersService }, + { provide: LdnServicesService, useValue: ldnServicesService }, + { provide: NotificationsService, useValue: notificationsService }, + { provide: TranslateService, useValue: translateServiceStub }, + { provide: Router, useValue: new RouterStub() }, + { provide: NgbModal, useValue: { open: () => {/*comment*/ } } }, + FormBuilder + ], + declarations: [LdnServiceFormComponent] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceFormComponent); + component = fixture.componentInstance; + ldnItemfiltersService.findAll.and.returnValue(itemFiltersRdPL$); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts index e92c06dc269..d3ad155e0d6 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts @@ -1,27 +1,9 @@ -import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; -import { LdnService } from "../ldn-services-model/ldn-services.model"; -import { ActivatedRoute } from "@angular/router"; -import { ProcessDataService } from "../../../core/data/processes/process-data.service"; -import { LinkService } from "../../../core/cache/builders/link.service"; +import { Component } from '@angular/core'; @Component({ selector: 'ds-ldn-service-new', templateUrl: './ldn-service-new.component.html', styleUrls: ['./ldn-service-new.component.scss'] }) -export class LdnServiceNewComponent implements OnInit { - /** - * Emits preselected process if there is one - */ - ldnService$?: Observable; - - constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) { - } - - /** - * If there's an id parameter, use this the process with this identifier as presets for the form - */ - ngOnInit() { - } +export class LdnServiceNewComponent { } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index 0999c82c196..4efa29bce89 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -1,25 +1,54 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { LdnServicesOverviewComponent } from './ldn-services-directory.component'; +import { ChangeDetectorRef, EventEmitter } from '@angular/core'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { of } from 'rxjs'; -import { ServicesDirectoryComponent } from './services-directory.component'; +describe('LdnServicesOverviewComponent', () => { + let component: LdnServicesOverviewComponent; + let fixture: ComponentFixture; -describe('ServicesDirectoryComponent', () => { - let component: ServicesDirectoryComponent; - let fixture: ComponentFixture; + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ServicesDirectoryComponent] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [LdnServicesOverviewComponent], + providers: [ + { provide: LdnServicesService, useValue: {} }, + { provide: PaginationService, useValue: new PaginationServiceStub() }, + { + provide: NgbModal, useValue: { + open: () => {/*comment*/ + } + } + }, + { provide: ChangeDetectorRef, useValue: {} }, + { provide: NotificationsService, useValue: NotificationsServiceStub }, + { provide: TranslateService, useValue: translateServiceStub }, + ] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ServicesDirectoryComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LdnServicesOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts deleted file mode 100644 index ab4f78dc6be..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { LdnDirectoryService } from './ldn-directory.service'; - -describe('LdnDirectoryService', () => { - let service: LdnDirectoryService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(LdnDirectoryService); - }); - - it('should be created', () => { - // @ts-ignore - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts deleted file mode 100644 index 92446b4677f..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { map, Observable } from 'rxjs'; -import { LdnServicesService } from "../ldn-services-data/ldn-services-data.service"; - -@Injectable({ - providedIn: 'root', -}) -export class LdnDirectoryService { - private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; - - - constructor(private http: HttpClient, - private ldnServicesService: LdnServicesService) { - } - - public getItemFilters(): Observable { - - return this.ldnServicesService.findAll().pipe( - map((servicesData) => { - return servicesData; - }) - ); - } - -} - - - diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts deleted file mode 100644 index 922b63a8718..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { LdnServicesBulkDeleteService } from './ldn-service-bulk-delete.service'; - -describe('LdnServiceBulkDeleteService', () => { - let service: LdnServicesBulkDeleteService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(LdnServicesBulkDeleteService); - }); - - it('should be created', () => { - // @ts-ignore - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts index eae3a3e3d63..e14fba61c19 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts @@ -1,14 +1,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NotifyInfoComponent } from './notify-info.component'; +import { NotifyInfoService } from './notify-info.service'; +import { TranslateModule } from '@ngx-translate/core'; describe('NotifyInfoComponent', () => { let component: NotifyInfoComponent; let fixture: ComponentFixture; + let notifyInfoServiceSpy: any; beforeEach(async () => { + notifyInfoServiceSpy = jasmine.createSpyObj('NotifyInfoService', ['getCoarLdnLocalInboxUrls']); + await TestBed.configureTestingModule({ - declarations: [ NotifyInfoComponent ] + imports: [TranslateModule.forRoot()], + declarations: [ NotifyInfoComponent ], + providers: [ + { provide: NotifyInfoService, useValue: notifyInfoServiceSpy } + ] }) .compileComponents(); }); diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index 2ff4b0bf2c4..7de2cf538ac 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -16,7 +16,7 @@ export class NotifyInfoComponent implements OnInit { */ coarRestApiUrl: Observable = of([]); - constructor(public notifyInfoService: NotifyInfoService) {} + constructor(private notifyInfoService: NotifyInfoService) {} ngOnInit() { this.coarRestApiUrl = this.notifyInfoService.getCoarLdnLocalInboxUrls(); diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts index 789140ebe45..81ac0db8d81 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts @@ -1,16 +1,49 @@ import { TestBed } from '@angular/core/testing'; import { NotifyInfoGuard } from './notify-info.guard'; +import { Router } from '@angular/router'; +import { NotifyInfoService } from './notify-info.service'; +import { of } from 'rxjs'; describe('NotifyInfoGuard', () => { let guard: NotifyInfoGuard; + let notifyInfoServiceSpy: any; + let router: any; beforeEach(() => { - TestBed.configureTestingModule({}); + notifyInfoServiceSpy = jasmine.createSpyObj('NotifyInfoService', ['isCoarConfigEnabled']); + router = jasmine.createSpyObj('Router', ['parseUrl']); + TestBed.configureTestingModule({ + providers: [ + NotifyInfoGuard, + { provide: NotifyInfoService, useValue: notifyInfoServiceSpy}, + { provide: Router, useValue: router} + ] + }); guard = TestBed.inject(NotifyInfoGuard); }); it('should be created', () => { expect(guard).toBeTruthy(); }); + + it('should return true if COAR config is enabled', (done) => { + notifyInfoServiceSpy.isCoarConfigEnabled.and.returnValue(of(true)); + + guard.canActivate(null, null).subscribe((result) => { + expect(result).toBe(true); + done(); + }); + }); + + it('should call parseUrl method of Router if COAR config is not enabled', (done) => { + notifyInfoServiceSpy.isCoarConfigEnabled.and.returnValue(of(false)); + router.parseUrl.and.returnValue(of('/404')); + + guard.canActivate(null, null).subscribe(() => { + expect(router.parseUrl).toHaveBeenCalledWith('/404'); + done(); + }); + }); + }); diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.ts index 4da9a42f21e..7af08216184 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.guard.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.ts @@ -16,7 +16,7 @@ export class NotifyInfoGuard implements CanActivate { canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot - ): Observable | Promise | boolean | UrlTree { + ): Observable { return this.notifyInfoService.isCoarConfigEnabled().pipe( map(coarLdnEnabled => { if (coarLdnEnabled) { diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts index b32d590cd69..092dab1655d 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts @@ -1,16 +1,50 @@ import { TestBed } from '@angular/core/testing'; import { NotifyInfoService } from './notify-info.service'; +import { ConfigurationDataService } from '../../data/configuration-data.service'; +import { of } from 'rxjs'; describe('NotifyInfoService', () => { let service: NotifyInfoService; + let configurationDataService: any; beforeEach(() => { - TestBed.configureTestingModule({}); + configurationDataService = { + findByPropertyName: jasmine.createSpy('findByPropertyName').and.returnValue(of({})), + }; + TestBed.configureTestingModule({ + providers: [ + NotifyInfoService, + { provide: ConfigurationDataService, useValue: configurationDataService }, + ] + }); service = TestBed.inject(NotifyInfoService); + configurationDataService = TestBed.inject(ConfigurationDataService); }); it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should retrieve and map coar configuration', () => { + const mockResponse = { payload: { values: ['true'] } }; + (configurationDataService.findByPropertyName as jasmine.Spy).and.returnValue(of(mockResponse)); + + service.isCoarConfigEnabled().subscribe((result) => { + expect(result).toBe(true); + }); + }); + + it('should retrieve and map LDN local inbox URLs', () => { + const mockResponse = { values: ['inbox1', 'inbox2'] }; + (configurationDataService.findByPropertyName as jasmine.Spy).and.returnValue(of(mockResponse)); + + service.getCoarLdnLocalInboxUrls().subscribe((result) => { + expect(result).toEqual(['inbox1', 'inbox2']); + }); + }); + + it('should return the inbox relation link', () => { + expect(service.getInboxRelationLink()).toBe('http://www.w3.org/ns/ldp#inbox'); + }); }); diff --git a/src/app/core/submission/workspaceitem-data.service.spec.ts b/src/app/core/submission/workspaceitem-data.service.spec.ts index e766a6a039c..2a3a3d343d1 100644 --- a/src/app/core/submission/workspaceitem-data.service.spec.ts +++ b/src/app/core/submission/workspaceitem-data.service.spec.ts @@ -19,7 +19,6 @@ import { Item } from '../shared/item.model'; import { WorkspaceItem } from './models/workspaceitem.model'; import { RequestEntry } from '../data/request-entry.model'; import { CoreState } from '../core-state.model'; -import { testSearchDataImplementation } from '../data/base/search-data.spec'; import { testDeleteDataImplementation } from '../data/base/delete-data.spec'; describe('WorkspaceitemDataService test', () => { @@ -84,17 +83,19 @@ describe('WorkspaceitemDataService test', () => { function initTestService() { hrefOnlyDataService = getMockHrefOnlyDataService(); return new WorkspaceitemDataService( + comparator, + halService, + http, + notificationsService, requestService, rdbService, objectCache, - halService, - notificationsService, + store, ); } describe('composition', () => { - const initService = () => new WorkspaceitemDataService(null, null, null, null, null); - testSearchDataImplementation(initService); + const initService = () => new WorkspaceitemDataService(null, null, null, null, null, null, null, null); testDeleteDataImplementation(initService); }); @@ -126,7 +127,7 @@ describe('WorkspaceitemDataService test', () => { service = initTestService(); spyOn((service as any), 'findByHref').and.callThrough(); - spyOn((service as any), 'getSearchByHref').and.returnValue(searchRequestURL$); + spyOn((service as any), 'getIDHref').and.callThrough(); }); afterEach(() => { @@ -138,7 +139,7 @@ describe('WorkspaceitemDataService test', () => { scheduler.schedule(() => service.findByItem('1234-1234', true, true, pageInfo)); scheduler.flush(); - expect((service as any).findByHref).toHaveBeenCalledWith(searchRequestURL$, true, true); + expect((service as any).findByHref).toHaveBeenCalled(); }); it('should return a RemoteData for the search', () => { diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 8a036f64439..f430dd43ea6 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -50,6 +50,20 @@ export class WorkspaceitemDataService extends IdentifiableDataService> { return this.deleteData.delete(objectId, copyVirtualMetadata); } + + /** + * Delete an existing object on the server + * @param href The self link of the object to be removed + * @param copyVirtualMetadata (optional parameter) the identifiers of the relationship types for which the virtual + * metadata should be saved as real metadata + * @return A RemoteData observable with an empty payload, but still representing the state of the request: statusCode, + * errorMessage, timeCompleted, etc + * Only emits once all request related to the DSO has been invalidated. + */ + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + /** * Return the WorkspaceItem object found through the UUID of an item * diff --git a/src/app/footer/footer.component.spec.ts b/src/app/footer/footer.component.spec.ts index 9f0250edc47..0d6069ece8e 100644 --- a/src/app/footer/footer.component.spec.ts +++ b/src/app/footer/footer.component.spec.ts @@ -17,16 +17,23 @@ import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { storeModuleConfig } from '../app.reducer'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataServiceStub } from '../shared/testing/authorization-service.stub'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; +import { of } from 'rxjs'; let comp: FooterComponent; let fixture: ComponentFixture; let de: DebugElement; let el: HTMLElement; +let notifyInfoServiceStub: any; + describe('Footer component', () => { // waitForAsync beforeEach beforeEach(waitForAsync(() => { + notifyInfoServiceStub = { + isCoarConfigEnabled: () => of(true) + }; return TestBed.configureTestingModule({ imports: [CommonModule, StoreModule.forRoot({}, storeModuleConfig), TranslateModule.forRoot({ loader: { @@ -38,6 +45,7 @@ describe('Footer component', () => { providers: [ FooterComponent, { provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub }, + { provide: NotifyInfoService, useValue: notifyInfoServiceStub }, ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); diff --git a/src/app/item-page/full/full-item-page.component.spec.ts b/src/app/item-page/full/full-item-page.component.spec.ts index c1917f77f42..c09c3177e3d 100644 --- a/src/app/item-page/full/full-item-page.component.spec.ts +++ b/src/app/item-page/full/full-item-page.component.spec.ts @@ -62,6 +62,7 @@ describe('FullItemPageComponent', () => { let serverResponseService: jasmine.SpyObj; let signpostingDataService: jasmine.SpyObj; let linkHeadService: jasmine.SpyObj; + let notifyInfoService: jasmine.SpyObj; const mocklink = { href: 'http://test.org', @@ -106,6 +107,12 @@ describe('FullItemPageComponent', () => { removeTag: jasmine.createSpy('removeTag'), }); + notifyInfoService = jasmine.createSpyObj('NotifyInfoService', { + isCoarConfigEnabled: observableOf(true), + getCoarLdnLocalInboxUrls: observableOf(['http://test.org']), + getInboxRelationLink: observableOf('http://test.org'), + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot({ loader: { @@ -123,7 +130,7 @@ describe('FullItemPageComponent', () => { { provide: ServerResponseService, useValue: serverResponseService }, { provide: SignpostingDataService, useValue: signpostingDataService }, { provide: LinkHeadService, useValue: linkHeadService }, - { provide: NotifyInfoService, useValue: {} }, + { provide: NotifyInfoService, useValue: notifyInfoService }, { provide: PLATFORM_ID, useValue: 'server' } ], schemas: [NO_ERRORS_SCHEMA] @@ -180,7 +187,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); describe('when the item is withdrawn and the user is not an admin', () => { @@ -209,7 +216,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); @@ -226,7 +233,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); }); diff --git a/src/app/item-page/full/full-item-page.component.ts b/src/app/item-page/full/full-item-page.component.ts index da79fc04ccc..09238c30ab4 100644 --- a/src/app/item-page/full/full-item-page.component.ts +++ b/src/app/item-page/full/full-item-page.component.ts @@ -59,7 +59,7 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit, protected notifyInfoService: NotifyInfoService, @Inject(PLATFORM_ID) protected platformId: string, ) { - super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService,notifyInfoService, platformId); + super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService, notifyInfoService, platformId); } /*** AoT inheritance fix, will hopefully be resolved in the near future **/ diff --git a/src/app/item-page/simple/item-page.component.spec.ts b/src/app/item-page/simple/item-page.component.spec.ts index b8354496da8..433b950cee2 100644 --- a/src/app/item-page/simple/item-page.component.spec.ts +++ b/src/app/item-page/simple/item-page.component.spec.ts @@ -75,6 +75,8 @@ describe('ItemPageComponent', () => { data: observableOf({ dso: createSuccessfulRemoteDataObject(mockItem) }) }); + const getCoarLdnLocalInboxUrls = ['http://InboxUrls.org', 'http://InboxUrls2.org']; + beforeEach(waitForAsync(() => { authService = jasmine.createSpyObj('authService', { isAuthenticated: observableOf(true), @@ -99,7 +101,7 @@ describe('ItemPageComponent', () => { notifyInfoService = jasmine.createSpyObj('NotifyInfoService', { getInboxRelationLink: 'http://www.w3.org/ns/ldp#inbox', isCoarConfigEnabled: observableOf(true), - getCoarLdnLocalInboxUrls: observableOf(['http://test.org', 'http://test2.org']), + getCoarLdnLocalInboxUrls: observableOf(getCoarLdnLocalInboxUrls), }); TestBed.configureTestingModule({ @@ -175,7 +177,7 @@ describe('ItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); @@ -184,7 +186,7 @@ describe('ItemPageComponent', () => { expect(comp.signpostingLinks).toEqual([mocklink, mocklink2]); // Check if linkHeadService.addTag() was called with the correct arguments - expect(linkHeadService.addTag).toHaveBeenCalledTimes(mockSignpostingLinks.length); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(mockSignpostingLinks.length + getCoarLdnLocalInboxUrls.length); let expected: LinkDefinition = mockSignpostingLinks[0] as LinkDefinition; expect(linkHeadService.addTag).toHaveBeenCalledWith(expected); expected = { @@ -195,8 +197,7 @@ describe('ItemPageComponent', () => { }); it('should set Link header on the server', () => { - - expect(serverResponseService.setHeader).toHaveBeenCalledWith('Link', ' ; rel="rel1" ; type="type1" , ; rel="rel2" '); + expect(serverResponseService.setHeader).toHaveBeenCalledWith('Link', ' ; rel="rel1" ; type="type1" , ; rel="rel2" , ; rel="http://www.w3.org/ns/ldp#inbox", ; rel="http://www.w3.org/ns/ldp#inbox"'); }); }); @@ -224,9 +225,9 @@ describe('ItemPageComponent', () => { expect(objectLoader.nativeElement).toBeDefined(); }); - it('should add the signposting links', () => { + it('should add the signposti`ng links`', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); }); @@ -243,7 +244,7 @@ describe('ItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); }); diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts index 67678354caf..242698b2342 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts @@ -17,7 +17,8 @@ describe('SuggestionsPopupComponent', () => { const suggestionStateService = jasmine.createSpyObj('SuggestionTargetsStateService', { hasUserVisitedSuggestions: jasmine.createSpy('hasUserVisitedSuggestions'), getCurrentUserSuggestionTargets: jasmine.createSpy('getCurrentUserSuggestionTargets'), - dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') + dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction'), + dispatchRefreshUserSuggestionsAction: jasmine.createSpy('dispatchRefreshUserSuggestionsAction') }); const mockNotificationInterpolation = { count: 12, source: 'source', suggestionId: 'id', displayName: 'displayName' }; diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts index c0f94cadce3..e6a98fbcd5a 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts @@ -31,7 +31,6 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { } public initializePopup() { - console.log('POPUP INIT dispatchRefreshUserSuggestionsAction'); this.reciterSuggestionStateService.dispatchRefreshUserSuggestionsAction(); const notifier = new Subject(); this.subscription = combineLatest([ diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index cb9d2c71303..806a45fbd56 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -262,6 +262,10 @@ export const environment: BuildConfig = { undoTimeout: 10000 // 10 seconds } }, + + + suggestion: [], + themes: [ { name: 'full-item-page-theme', From 41eb34b7f4a047760a9312347bf6c2bb86789c62 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 3 Nov 2023 22:10:10 +0100 Subject: [PATCH 154/592] [CST-12043] Add class for element container --- .../models/custom-switch/custom-switch.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html index cfda5d19d00..5beb8d52dab 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.html @@ -1,4 +1,4 @@ -

+
-
@@ -82,7 +82,7 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- Please enter a valid score (between 0 and 1). Use the “.” as decimal separator + {{ 'ldn-new-service.form.error.score' | translate }}

diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 4a3398b5fad..d64e5f90b90 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -11,7 +11,7 @@

{{ 'ldn-create-service.title' | translate }}

name="name" type="text">
- Name is required + {{ 'ldn-new-service.form.error.name' | translate }}
@@ -38,7 +38,7 @@

{{ 'ldn-create-service.title' | translate }}

name="url" type="text">
- URL is required + {{ 'ldn-new-service.form.error.url' | translate }}
@@ -55,7 +55,7 @@

{{ 'ldn-create-service.title' | translate }}

name="ldnUrl" type="text">
- LDN URL is required + {{ 'ldn-new-service.form.error.ldnurl' | translate }}
@@ -72,7 +72,7 @@

{{ 'ldn-create-service.title' | translate }}

name="score" type="text">
- Please enter a valid score (between 0 and 1). Use the “.” as decimal separator + {{ 'ldn-new-service.form.error.score' | translate }}
@@ -110,7 +110,7 @@

{{ 'ldn-create-service.title' | translate }}

[ngValue]="pattern.name">{{ pattern.name }}
- Please select at least a pattern. + {{ 'ldn-new-service.form.error.patterns' | translate }}
@@ -182,7 +182,7 @@

{{ 'ldn-create-service.title' | translate }}

[ngValue]="pattern.name">{{ pattern.name }}
- Please select at least a pattern. + {{ 'ldn-new-service.form.error.patterns' | translate }}
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 2c4c406530e..87ddbeb8937 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -131,7 +131,9 @@ form button.btn.btn-primary[type="submit"] { z-index: var(--ds-submission-footer-z-index); } - +div + div { + margin-bottom: 40px; +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index be244bbb1e8..2121cc803ba 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -939,6 +939,12 @@ "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", "ldn-new-service.form.label.ItemFilter": "Item Filter", "ldn-new-service.form.label.automatic": "Automatic", + "ldn-new-service.form.error.name": "Name is required", + "ldn-new-service.form.error.url": "URL is required", + "ldn-new-service.form.error.ldnurl": "LDN URL is required", + "ldn-new-service.form.error.patterns": "At least a pattern is required", + "ldn-new-service.form.error.score": "Please enter a valid score (between 0 and 1). Use the “.” as decimal separator", + "ldn-new-service.form.label.outboundPattern": "Outbound Patterns", "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", From f4b8c7f1f1deb128c9671e9fc054b1e28e6555a5 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 10 Nov 2023 10:44:39 +0100 Subject: [PATCH 164/592] CST-12179 Removed comments --- .../ldn-service-coar-patterns.ts | 105 +++++------------- 1 file changed, 27 insertions(+), 78 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts index a882d5db11f..8620bfc80c5 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts @@ -1,82 +1,31 @@ export const notifyPatterns = [ - //{ - 'ack-accept', - //name: 'ldn-service.form.pattern.acknowledge-and-accept.label', - //description: 'ldn-service.form.pattern.acknowledge-and-accept.description', - //category: 'ldn-service.form.pattern.acknowledge-and-accept.category' - //}, - //{ - 'ack-reject', - //name: 'ldn-service.form.pattern.acknowledge-and-reject.label', - //description: 'ldn-service.form.pattern.acknowledge-and-reject.description', - //category: 'ldn-service.form.pattern.acknowledge-and-reject.category' - //}, - //{ - 'ack-tentative-accept', - //name: 'ldn-service.form.pattern.acknowledge-and-tentatively-accept.label', - //description: 'ldn-service.form.pattern.acknowledge-and-tentatively-accept.description', - //category: 'ldn-service.form.pattern.acknowledge-and-tentatively-accept.category' - //}, - //{ - 'ack-tentative-reject', - //name: 'ldn-service.form.pattern.acknowledge-and-tentatively-reject.label', - //description: 'ldn-service.form.pattern.acknowledge-and-tentatively-reject.description', - //category: 'ldn-service.form.pattern.acknowledge-and-tentatively-reject.category' - //}, - //{ - 'announce-endorsement', - //name: 'ldn-service.form.pattern.announce-endorsement.label', - //description: 'ldn-service.form.pattern.announce-endorsement.description', - //category: 'ldn-service.form.pattern.announce-endorsement.category' - //}, - //{ - 'announce-ingest', - //name: 'ldn-service.form.pattern.announce-ingest.label', - //description: 'ldn-service.form.pattern.announce-ingest.description', - //category: 'ldn-service.form.pattern.announce-ingest.category' - //}, - //{ - 'announce-relationship', - //name: 'ldn-service.form.pattern.announce-relationship.label', - //description: 'ldn-service.form.pattern.announce-relationship.description', - //category: 'ldn-service.form.pattern.announce-relationship.category' - //}, - //{ - 'announce-review', - //name: 'ldn-service.form.pattern.announce-review.label', - //description: 'ldn-service.form.pattern.announce-review.description', - //category: 'ldn-service.form.pattern.announce-review.category' - //}, - //{ - 'announce-service-result', - //name: 'ldn-service.form.pattern.announce-service-result.label', - //description: 'ldn-service.form.pattern.announce-service-result.description', - //category: 'ldn-service.form.pattern.announce-service-result.category' - //}, - //{ - 'request-endorsement', - //name: 'ldn-service.form.pattern.request-endorsement.label', - //description: 'ldn-service.form.pattern.request-endorsement.description', - //category: 'ldn-service.form.pattern.request-endorsement.category' - //}, - //{ - 'request-ingest', - //name: 'ldn-service.form.pattern.request-ingest.label', - //description: 'ldn-service.form.pattern.request-ingest.description', - //category: 'ldn-service.form.pattern.request-ingest.category' - //}, - //{ - 'request-review', - //name: 'ldn-service.form.pattern.request-review.label', - //description: 'ldn-service.form.pattern.request-review.description', - //category: 'ldn-service.form.pattern.request-review.category' - //}, - //{ - 'undo-offer', - //name: 'ldn-service.form.pattern.undo-offer.label', - //description: 'ldn-service.form.pattern.undo-offer.description', - //category: 'ldn-service.form.pattern.undo-offer.category' - //} + + 'ack-accept', + + 'ack-reject', + + 'ack-tentative-accept', + + 'ack-tentative-reject', + + 'announce-endorsement', + + 'announce-ingest', + + 'announce-relationship', + + 'announce-review', + + 'announce-service-result', + + 'request-endorsement', + + 'request-ingest', + + 'request-review', + + 'undo-offer', + ]; From 6675f9cd6aa455bdfb193e3c76ed87875d40c091 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Fri, 10 Nov 2023 11:20:33 +0100 Subject: [PATCH 165/592] [CST-12535] improvements --- ...ality-assurance-topic-data.service.spec.ts | 19 +++++++++ .../quality-assurance-topic-data.service.ts | 20 ++++++++++ .../quality-assurance-topics.component.html | 6 ++- ...quality-assurance-topics.component.spec.ts | 2 + .../quality-assurance-topics.component.ts | 40 ++++++++++++++++++- src/assets/i18n/en.json5 | 2 + 6 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts index c9b1407a53b..277da6e4ba9 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.spec.ts @@ -81,6 +81,7 @@ describe('QualityAssuranceTopicDataService', () => { ); spyOn((service as any).searchData, 'searchBy').and.callThrough(); + spyOn((service as any), 'findById').and.callThrough(); }); describe('searchTopicsByTarget', () => { @@ -133,4 +134,22 @@ describe('QualityAssuranceTopicDataService', () => { }); }); + describe('getTopic', () => { + it('should call findByHref', (done) => { + service.getTopic(qualityAssuranceTopicObjectMorePid.id).subscribe( + (res) => { + expect((service as any).findById).toHaveBeenCalledWith(qualityAssuranceTopicObjectMorePid.id, true, true); + } + ); + done(); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.getTopic(qualityAssuranceTopicObjectMorePid.id); + const expected = cold('(a)', { + a: qaTopicObjectRD + }); + expect(result).toBeObservable(expected); + }); + }); }); diff --git a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts index 6944e43a565..86c8f5eeaae 100644 --- a/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -16,6 +16,7 @@ import { IdentifiableDataService } from '../../../data/base/identifiable-data.se import { dataService } from '../../../data/base/data-service.decorator'; import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; import { SearchData, SearchDataImpl } from '../../../../core/data/base/search-data'; +import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; /** * The service handling all Quality Assurance topic REST requests. @@ -24,6 +25,7 @@ import { SearchData, SearchDataImpl } from '../../../../core/data/base/search-da @dataService(QUALITY_ASSURANCE_TOPIC_OBJECT) export class QualityAssuranceTopicDataService extends IdentifiableDataService { + private findAllData: FindAllData; private searchData: SearchData; private searchByTargetMethod = 'byTarget'; @@ -45,6 +47,7 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataService> + * The Quality Assurance topic. + */ + public getTopic(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } 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 c13929bf8a5..68de6aec7ac 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,7 +2,11 @@

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

- {{'quality-assurance.topics.description'| translate:{source: sourceId} }} + {{'quality-assurance.topics.description'| translate:{source: sourceId} }} + + {{'quality-assurance.topics.description-with-target'| translate:{source: sourceId} }} + {{(getTargetItemTitle() | async)}} +
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 52700d778bb..4137fdfae1e 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 @@ -16,6 +16,7 @@ import { SuggestionNotificationsStateService } from '../../suggestion-notificati import { cold } from 'jasmine-marbles'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { ItemDataService } from '../../../core/data/item-data.service'; describe('QualityAssuranceTopicsComponent test suite', () => { let fixture: ComponentFixture; @@ -49,6 +50,7 @@ describe('QualityAssuranceTopicsComponent test suite', () => { }, }}}, { provide: PaginationService, useValue: paginationService }, + { provide: ItemDataService, useValue: {} }, QualityAssuranceTopicsComponent, ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts index b04bb4fbf2e..0f7a111089d 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.ts +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-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, tap } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; import { @@ -15,6 +15,10 @@ import { } 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 { ItemDataService } from '../../../core/data/item-data.service'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; +import { Item } from '../../../core/shared/item.model'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; /** * Component to display the Quality Assurance topic list. @@ -65,6 +69,11 @@ export class QualityAssuranceTopicsComponent implements OnInit { */ public targetId: string; + /** + * The URL of the item page. + */ + public itemPageUrl: string; + /** * Initialize the component variables. * @param {PaginationService} paginationService @@ -75,7 +84,8 @@ export class QualityAssuranceTopicsComponent implements OnInit { constructor( private paginationService: PaginationService, private activatedRoute: ActivatedRoute, - private notificationsStateService: SuggestionNotificationsStateService + private notificationsStateService: SuggestionNotificationsStateService, + private itemService: ItemDataService ) { this.sourceId = this.activatedRoute.snapshot.params.sourceId; this.targetId = this.activatedRoute.snapshot.params.targetId; @@ -156,6 +166,32 @@ export class QualityAssuranceTopicsComponent implements OnInit { } } + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } + + /** + * Returns the page route for the given item. + * @param item The item to get the page route for. + * @returns The page route for the given item. + */ + getItemPageRoute(item: Item): string { + return getItemPageRoute(item); + } + /** * Unsubscribe from all subscriptions. */ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index fd887d742c3..a559f4cccf8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3232,6 +3232,8 @@ "quality-assurance.topics.description": "Below you can see all the topics received from the subscriptions to {{source}}.", + "quality-assurance.topics.description-with-target": "Below you can see all the topics received from the subscriptions to {{source}} in regards to the", + "quality-assurance.source.description": "Below you can see all the notification's sources.", "quality-assurance.topics": "Current Topics", From 91b4d3dcd10cbd8248a41505eac96586707bac2b Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Fri, 10 Nov 2023 16:13:20 +0100 Subject: [PATCH 166/592] [DURACOM-204][#2622] Makes forgot-password link removable --- .../data/feature-authorization/feature-id.ts | 1 + .../password/log-in-password.component.html | 16 ++++++------ .../password/log-in-password.component.ts | 26 ++++++++++++++++--- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index 8fef45a9532..bd1f65b72d8 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -34,4 +34,5 @@ export enum FeatureID { CanEditItem = 'canEditItem', CanRegisterDOI = 'canRegisterDOI', CanSubscribe = 'canSubscribeDso', + EPersonForgotPassword = 'epersonForgotPassword', } diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.html b/src/app/shared/log-in/methods/password/log-in-password.component.html index 60477d141de..52f28e7190e 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.html +++ b/src/app/shared/log-in/methods/password/log-in-password.component.html @@ -29,11 +29,11 @@ [disabled]="!form.valid"> {{"login.form.submit" | translate}} - + + + diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.ts b/src/app/shared/log-in/methods/password/log-in-password.component.ts index 61323940192..1f96c4c0d8e 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.ts +++ b/src/app/shared/log-in/methods/password/log-in-password.component.ts @@ -1,9 +1,9 @@ -import { map } from 'rxjs/operators'; +import { combineLatest, Observable, shareReplay } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { Component, Inject, OnInit } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { select, Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; import { AuthenticateAction, ResetAuthenticationMessagesAction } from '../../../../core/auth/auth.actions'; import { getAuthenticationError, getAuthenticationInfo, } from '../../../../core/auth/selectors'; @@ -73,6 +73,17 @@ export class LogInPasswordComponent implements OnInit { */ public canRegister$: Observable; + /** + * Whether or not the current user (or anonymous) is authorized to register an account + */ + canForgot$: Observable; + + /** + * Shows the divider only if contains at least one link to show + */ + canShowDivider$: Observable; + + constructor( @Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod, @Inject('isStandalonePage') public isStandalonePage: boolean, @@ -114,8 +125,15 @@ export class LogInPasswordComponent implements OnInit { return message; }) ); - - this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration); + + this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration).pipe(shareReplay(1)); + this.canForgot$ = this.authorizationService.isAuthorized(FeatureID.EPersonForgotPassword).pipe(shareReplay(1)); + this.canShowDivider$ = + combineLatest([this.canRegister$, this.canForgot$]) + .pipe( + map(([canRegister, canForgot]) => canRegister || canForgot), + filter(Boolean) + ); } getRegisterRoute() { From 2429c3660b8ae370a8da945a9c3483b185b201e9 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Fri, 10 Nov 2023 16:49:06 +0100 Subject: [PATCH 167/592] [DURACOM-204][#2622] Makes forgot-password link removable --- .../log-in/methods/password/log-in-password.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.ts b/src/app/shared/log-in/methods/password/log-in-password.component.ts index 1f96c4c0d8e..008eb11eef1 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.ts +++ b/src/app/shared/log-in/methods/password/log-in-password.component.ts @@ -64,7 +64,7 @@ export class LogInPasswordComponent implements OnInit { /** * The authentication form. - * @type {FormGroup} + * @type {UntypedFormGroup} */ public form: UntypedFormGroup; @@ -125,7 +125,7 @@ export class LogInPasswordComponent implements OnInit { return message; }) ); - + this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration).pipe(shareReplay(1)); this.canForgot$ = this.authorizationService.isAuthorized(FeatureID.EPersonForgotPassword).pipe(shareReplay(1)); this.canShowDivider$ = From 71af428a16322d966f7240cf1348ca82a1e49cf9 Mon Sep 17 00:00:00 2001 From: Vlad Nouski Date: Fri, 10 Nov 2023 18:13:09 +0100 Subject: [PATCH 168/592] [CST-12044] refactor: styles --- .../upload/file/themed-section-upload-file.component.ts | 2 +- src/assets/i18n/en.json5 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/file/themed-section-upload-file.component.ts b/src/app/submission/sections/upload/file/themed-section-upload-file.component.ts index 3bc334673e3..952813e03c9 100644 --- a/src/app/submission/sections/upload/file/themed-section-upload-file.component.ts +++ b/src/app/submission/sections/upload/file/themed-section-upload-file.component.ts @@ -18,7 +18,7 @@ export class ThemedSubmissionSectionUploadFileComponent @Input() availableAccessConditionOptions: any[]; /** - * The indicator is the primary bitstream + * The indicator is the primary bitstream * it will be null if no primary bitstream is set for the ORIGINAL bundle * @type {boolean, null} */ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 66f02b59e24..818c25e58f7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2435,7 +2435,7 @@ "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.collapse": "Collapse", - + "item.page.bitstreams.primary": "Primary", "item.page.filesection.original.bundle": "Original bundle", From 3aaeaa63979108e51571e7b7ac739c39b8f3e9d5 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 10 Nov 2023 19:41:11 +0100 Subject: [PATCH 169/592] CST-12179 Removed comments --- .../ldn-service-form-edit.component.html | 497 ++++++++---------- .../ldn-service-form.component.html | 461 ++++++++-------- .../ldn-service-form.component.scss | 6 +- 3 files changed, 435 insertions(+), 529 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index d4029e91ea0..2ba1b7028d4 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,310 +1,271 @@
-
-
-

{{ 'ldn-edit-registered-service.title' | translate }}

-
- -
- -
- -
-
-
-
+ +
+

{{ 'ldn-edit-registered-service.title' | translate }}

+
+ +
+ +
+ +
+
+
+
-
- - -
- {{ 'ldn-new-service.form.error.name' | translate }} -
-
+
+ + +
-
-   -
+ +
+ + +
- -
- - -
+ +
+ + +
-
-   -
- -
- - -
- {{ 'ldn-new-service.form.error.url' | translate }} -
-
+ +
+ + +
-
-   -
- -
- - -
- {{ 'ldn-new-service.form.error.ldnurl' | translate }} -
-
+
+
+ +
+
+ +
+
+ +
+
+
+
-
-   -
+
+ + - -
- - -
- {{ 'ldn-new-service.form.error.score' | translate }} + +
+
+
-
-
-   -
+
+ + + +
-
-
- -
-
- -
-
- -
-
+
+ +
+
-
+
-
- - - - -
-
- -
- -
- - - -
- -
- -
-
-
-
- - -
- - - - -
-
-
+
+
+ + +
+
+ +
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+
+ +
+
+ +
+
+ +
+
+
+
-
-   -
+
+ + + + +
+
+ +
+
+ + + +
-
-
- -
-
- -
-
- +
+ +
+
-
-
-
+
-
- - - - -
-
- -
-
- - - -
- -
- -
-
-
-
- -
- - -
-
-
+
+
+ + +
+
+ +
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} - -
-   -
- - + +
-
+
- + - + +
-
+
- + - + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index d64e5f90b90..325caeb2fed 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,298 +1,247 @@
-
-
-

{{ 'ldn-create-service.title' | translate }}

-
- -
- - -
- {{ 'ldn-new-service.form.error.name' | translate }} -
-
+ +
+

{{ 'ldn-create-service.title' | translate }}

+
+ +
+ + +
-
-   -
- -
- - -
+ +
+ + +
-
-   -
- -
- - -
- {{ 'ldn-new-service.form.error.url' | translate }} -
-
+ +
+ + +
-
-   -
- -
- - -
- {{ 'ldn-new-service.form.error.ldnurl' | translate }} -
-
+ +
+ + +
-
-   -
- -
- - -
- {{ 'ldn-new-service.form.error.score' | translate }} -
-
+ +
+
+ +
+
+ +
+
+ +
+
+
+
-
-   -
+
- -
-
- -
-
- -
-
- -
-
-
-
+ -
- - - - -
-
- -
- {{ 'ldn-new-service.form.error.patterns' | translate }} -
-
- - -
- - - -
- -
- -
-
-
-
- -
- -
-
-
-
- {{ 'ldn-new-service.form.label.addPattern' | translate }} +
+
+ +
-
-   -
+
+ + + +
- -
-
- -
-
- -
-
-
-
+
+ +
+
+
+ +
+ +
+ +
-
- - - - -
-
- -
- {{ 'ldn-new-service.form.error.patterns' | translate }} -
-
-
- - - -
- -
- -
-
-
-
- -
- -
-
-
+ {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+
+ +
+
+ +
+
+ +
+
+
+
-
+
+ + + + +
+
+ +
+
+ + + +
- {{ 'ldn-new-service.form.label.addPattern' | translate }} - -
-   -
+
+ +
+
+
+
-
+
+
- + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + + +
-
+
- + - + +
-
+
- + - + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 87ddbeb8937..eb5a70c7ee2 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -1,8 +1,6 @@ form { - max-width: 800px; font-size: 14px; position: relative; - } input[type="text"], @@ -131,9 +129,7 @@ form button.btn.btn-primary[type="submit"] { z-index: var(--ds-submission-footer-z-index); } -div + div { - margin-bottom: 40px; -} + From 075c53a1f48d0572e20278fc4f4ad444e3281e54 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 10 Nov 2023 20:00:42 +0100 Subject: [PATCH 170/592] CST-12179 Using json5 and error are logged under the various sections if the form is not valid we simply close the modal --- .../ldn-service-form-edit.component.html | 22 +++++++++++++++ .../ldn-service-form.component.html | 28 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 2ba1b7028d4..67eada6b7be 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -20,6 +20,9 @@

{{ 'ldn-edit-registered-service.title' | translate }} +
+ {{ 'ldn-new-service.form.error.name' | translate }} +

@@ -36,6 +39,9 @@

{{ 'ldn-edit-registered-service.title' | translate }} +
+ {{ 'ldn-new-service.form.error.url' | translate }} +

@@ -47,6 +53,22 @@

{{ 'ldn-edit-registered-service.title' | translate }} +
+ {{ 'ldn-new-service.form.error.ldnurl' | translate }} +
+

+ + +
+ + +
+ {{ 'ldn-new-service.form.error.score' | translate }} +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 325caeb2fed..1baa5c50664 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -10,6 +10,9 @@

{{ 'ldn-create-service.title' | translate }}

[placeholder]="'ldn-new-service.form.placeholder.name' | translate" formControlName="name" id="name" name="name" type="text"> +
+ {{ 'ldn-new-service.form.error.name' | translate }} +
@@ -28,6 +31,9 @@

{{ 'ldn-create-service.title' | translate }}

[placeholder]="'ldn-new-service.form.placeholder.url' | translate" formControlName="url" id="url" name="url" type="text"> +
+ {{ 'ldn-new-service.form.error.url' | translate }} +
@@ -39,8 +45,22 @@

{{ 'ldn-create-service.title' | translate }}

id="ldnUrl" name="ldnUrl" type="text"> +
+ {{ 'ldn-new-service.form.error.ldnurl' | translate }} +
+
+ +
+ + +
+ {{ 'ldn-new-service.form.error.score' | translate }} +
-
@@ -71,6 +91,9 @@

{{ 'ldn-create-service.title' | translate }}

+
+ {{ 'ldn-new-service.form.error.patterns' | translate }} +
@@ -138,6 +161,9 @@

{{ 'ldn-create-service.title' | translate }}

+
+ {{ 'ldn-new-service.form.error.patterns' | translate }} +
From 786e2ee43eb346ade23bdd625f729470080da955 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Mon, 13 Nov 2023 15:17:34 +0100 Subject: [PATCH 171/592] [CST-12608] qaevents page improvements --- .../quality-assurance-events.component.html | 12 +++- ...quality-assurance-events.component.spec.ts | 2 + .../quality-assurance-events.component.ts | 66 ++++++++++++++++++- .../quality-assurance-topics.component.html | 2 +- src/assets/i18n/en.json5 | 4 +- 5 files changed, 79 insertions(+), 7 deletions(-) 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 7f1b166d24c..d5e8a5c709e 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 @@ -4,13 +4,19 @@

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

- + + + + + + {{(getTargetItemTitle() | async)}} +
@@ -157,7 +163,7 @@

- + {{'quality-assurance.events.back' | translate}} 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 04ece87fbb3..a4254962b25 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 @@ -42,6 +42,7 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti 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 { ItemDataService } from 'src/app/core/data/item-data.service'; describe('QualityAssuranceEventsComponent test suite', () => { let fixture: ComponentFixture; @@ -118,6 +119,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, { provide: PaginationService, useValue: paginationService }, + { provide: ItemDataService, useValue: {} }, QualityAssuranceEventsComponent ], schemas: [NO_ERRORS_SCHEMA] 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 742047e76f8..fee2557a123 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 @@ -1,5 +1,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { Location } from '@angular/common'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; @@ -26,10 +27,12 @@ import { ProjectEntryImportModalComponent, QualityAssuranceEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { Item } from '../../../core/shared/item.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; +import { ItemDataService } from '../../../core/data/item-data.service'; /** * Component to display the Quality Assurance event list. @@ -105,6 +108,26 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ protected subs: Subscription[] = []; + /** + * The target item id, retrieved from the topic-id composition. + */ + public targetId: string; + + /** + * The URL of the item page/target. + */ + public itemPageUrl: string; + + /** + * Plain topic name (without the source id) + */ + public selectedTopicName: string; + + /** + * The source id, retrieved from the topic-id composition. + */ + public sourceId: string; + /** * Initialize the component variables. * @param {ActivatedRoute} activatedRoute @@ -120,7 +143,9 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { private notificationsService: NotificationsService, private qualityAssuranceEventRestService: QualityAssuranceEventDataService, private paginationService: PaginationService, - private translateService: TranslateService + private translateService: TranslateService, + private itemService: ItemDataService, + private _location: Location ) { } @@ -137,6 +162,10 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { const regEx = /!/g; this.showTopic = id.replace(regEx, '/'); this.topic = id; + const splitList = this.showTopic?.split(':'); + this.targetId = splitList.length > 2 ? splitList.pop() : null; + this.sourceId = splitList[0]; + this.selectedTopicName = splitList[1]; return this.getQualityAssuranceEvents(); }) ).subscribe((events: QualityAssuranceEventData[]) => { @@ -423,4 +452,37 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { last() ); } + + /** + * Returns the page route for the given item. + * @param item The item to get the page route for. + * @returns The page route for the given item. + */ + public getItemPageRoute(item: Item): string { + return getItemPageRoute(item); + } + + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + public getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } + + /** + * Navigates back to the previous location in the browser's history stack. + */ + public goBack() { + this._location.back(); + } } 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 68de6aec7ac..5fa32d46fcb 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 @@ -44,7 +44,7 @@

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

diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d4d3cb77fa2..e306274e061 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3260,7 +3260,9 @@ "quality-assurance.source.error.service.retrieve": "An error occurred while loading the Quality Assurance source", - "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic.", + "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}}.", + + "quality-assurance.events.description-with-topic-and-target": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}} and ", "quality-assurance.loading": "Loading ...", From 721b80a0e678880772c89412e114eb8189ed37b4 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Tue, 14 Nov 2023 13:13:39 +0100 Subject: [PATCH 172/592] CST-12455 Changes for the page to be using an ngbdropdown logic are still required and being worked on --- .../ldn-service-form-edit.component.html | 121 ++++++++++++------ .../ldn-service-form-edit.component.scss | 8 +- .../ldn-service-form-edit.component.ts | 56 +++++++- .../ldn-service-form.component.html | 100 +++++++++++---- .../ldn-service-form.component.scss | 10 +- .../ldn-service-form.component.ts | 26 ++++ 6 files changed, 247 insertions(+), 74 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 56105ce8052..192a6633a20 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -69,12 +69,12 @@

{{ 'ldn-edit-registered-service.title' | translate }}{{ 'ldn-new-service.form.label.inboundPattern' | translate }}

- +
-
- +
+
-
+
@@ -86,33 +86,54 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- -
- -
- - - +
+
+ + + + +
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+ +
+
+
-
- -
-
-
+
+ + + +
+ +
+ +
+
+
@@ -150,7 +171,7 @@

{{ 'ldn-edit-registered-service.title' | translate }}

-
+
@@ -162,16 +183,36 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- +
+
+ + + + +
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+ +
+
+
- +
@@ -214,7 +255,7 @@

{{ 'ldn-edit-registered-service.title' | translate }} {{ 'ldn-new-service.form.label.submit' | translate }}
-
@@ -243,7 +284,7 @@

{{'service.overview.edit.modal' | translate }}

-
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index 0b244d76dbc..2fc1e693f01 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -1,3 +1,6 @@ +@import '../../../shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.scss'; +@import '../../../shared/form/form.component.scss'; + form { font-size: 14px; position: relative; @@ -28,7 +31,6 @@ textarea { .add-pattern-link { color: #0048ff; cursor: pointer; - margin-left: 10px; } .remove-pattern-link { @@ -93,6 +95,10 @@ textarea { margin-top: 10px; } +.small-text { + font-size: 0.7em; + color: #888; +} .toggle-switch { cursor: pointer; margin-top: 3px; diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index f0422e39e41..cb2805f0692 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -5,7 +5,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; import { animate, state, style, transition, trigger } from '@angular/animations'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import {NgbDropdownConfig, NgbModal} from '@ng-bootstrap/ng-bootstrap'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { LdnService } from '../ldn-services-model/ldn-services.model'; @@ -19,6 +19,7 @@ import { Observable } from 'rxjs'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import {pattern} from "isbot"; @Component({ selector: 'ds-ldn-service-form-edit', @@ -65,6 +66,8 @@ export class LdnServiceFormEditComponent implements OnInit { private deletedOutboundPatterns: number[] = []; private modalRef: any; private service: LdnService; + selectedOutboundPatterns: string[]; + selectedInboundPatterns: string[]; constructor( protected ldnServicesService: LdnServicesService, @@ -164,8 +167,10 @@ export class LdnServiceFormEditComponent implements OnInit { this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); this.createReplaceOperation(patchOperations, 'url', '/url'); - this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); + + + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns', this.selectedInboundPatterns); + this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns', this.selectedOutboundPatterns); this.deletedInboundPatterns.forEach(index => { const removeOperation: Operation = { @@ -201,6 +206,37 @@ export class LdnServiceFormEditComponent implements OnInit { } + selectOutboundPattern(patternValue: string, index: number): void { + // this.selectedOutboundPatterns = patternValue; + const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray).controls[index] + console.log((this.formModel.get('notifyServiceOutboundPatterns') as FormArray)) + patternArray.patchValue({pattern: patternValue} ) + //console.log(patternArray); + //this.getPatternControlNames(index) + } + + selectInboundPattern(patternValue: string, index: number): void { + // this.selectedInboundPatterns = patternValue; + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray).controls[index] + console.log((this.formModel.get('notifyServiceInboundPatterns') as FormArray)) + console.log(patternArray) + //console.log(patternArray); + //this.getPatternControlNames(index) + } + + + + getOutboundPatternControlNames(index: number) { + const patternArrayValue = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray).controls[index]?.value + return patternArrayValue + } + + getInboundPatternControlNames(index: number) { + const patternArrayValue = (this.formModel.get('notifyServiceInboundPatterns') as FormArray).controls[index]?.value + return patternArrayValue + } + + toggleAutomatic(i: number) { const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); if (automaticControl) { @@ -245,6 +281,7 @@ export class LdnServiceFormEditComponent implements OnInit { patchService() { this.deleteMarkedInboundPatterns(); this.deleteMarkedOutboundPatterns(); + const patchOperations = this.generatePatchOperations(); @@ -343,11 +380,16 @@ export class LdnServiceFormEditComponent implements OnInit { } } - private handlePatterns(patchOperations: any[], formArrayName: string): void { + private handlePatterns(patchOperations: any[], formArrayName: string, selectedPatterns: string[]): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; + console.warn('Calling setValueForControlInOutboundArray', formArrayName, i, selectedPatterns); + this.setValueForControlInOutboundArray(formArrayName, i, selectedPatterns[i] ) + const patternValue = patternGroup.value; if (patternGroup.dirty) { @@ -406,4 +448,10 @@ export class LdnServiceFormEditComponent implements OnInit { automatic: '', }); } + + setValueForControlInOutboundArray(formArrayName: string, index: number, value: string) { + const formArray = this.formModel.get(formArrayName) as FormArray; + console.warn('inside setValueForControlInOutboundArray', formArray); + formArray.at(index).setValue(value); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 1b4aa9048d1..de7949614d7 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -60,10 +60,10 @@

{{ 'ldn-create-service.title' | translate }}

- +
-
- +
+
@@ -76,18 +76,41 @@

{{ 'ldn-create-service.title' | translate }}

-
- +
+
+
+ + + + +
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.inboundPattern' | translate) }}
+
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+ +
+
+
- +
{{ 'ldn-create-service.title' | translate }}

+

@@ -129,7 +153,7 @@

{{ 'ldn-create-service.title' | translate }}

- +
@@ -145,16 +169,37 @@

{{ 'ldn-create-service.title' | translate }}

- +
+
+ + + + +
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+ +
+
+
+
- + -
-
-
+
+ +
+
+
-
+
{{ 'ldn-edit-registered-service.title' | translate }}
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.description' | translate) : ('' | translate) }}
- +
+
-
-
-
-
+
+
+

{{ 'ldn-edit-registered-service.title' | translate }}

+
+ +
+ +
+ +
+
+
+
-
- - -
+
+ + +
-
-   -
+
+   +
- -
- - -
+ +
+ + +
-
-   -
+
+   +
- -
- - -
+ +
+ + +
-
-   -
+
+   +
- -
- - -
+ +
+ + +
-
-   -
+
+   +
-
-
- -
-
- -
-
- +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+ + + + +
+
+
+
+ + + + +
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+ +
+
-
+
+ +
+ + + +
+ +
+ +
+
-
+
-
- - - - -
-
-
-
- - - - -
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
-
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}
- -
- -
-
-
-
- -
- - - -
- -
- -
-
-
-
- - -
- - - - -
-
-
+
+ + + + +
+ +
- {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
+ {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-
- -
-
- -
-
- -
-
-
-
+
+   +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
-
- - - - -
-
-
-
- - - - -
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
-
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.description' | translate) : ('' | translate) }}
- -
- -
-
-
-
- -
- - - -
- -
- -
-
-
-
- -
- - -
+
+ + + + +
+
+
+
+ + + + +
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedOutboundPatterns ? ('ldn-service.form.pattern.' + selectedOutboundPatterns + '.description' | translate) : ('' | translate) }}
+ +
+
+
+
+
+ +
+ + -
+
- {{ 'ldn-new-service.form.label.addPattern' | translate }} - +
+ +
+
+
+
-
-   -
-
- + +
+ + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+   +
+ +
-
+
- + - + +
-
+
- + - + +
From 35c45850e796539eddf7f56e100005e133c30f02 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 15 Nov 2023 11:57:14 +0100 Subject: [PATCH 175/592] CST-12455 Itemfilter dropdown for the edit inboundpatterns is working, now changing all remaining code and finalizing task --- .../ldn-service-form-edit.component.html | 37 +++++++++++++++---- .../ldn-service-form-edit.component.ts | 14 +++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 0ea17d6fdd6..51abf43f04d 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -103,11 +103,11 @@

{{ 'ldn-edit-registered-service.title' | translate }} -
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.outboundPattern' | translate) }}
+
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.label' | translate) : ('ldn-new-service.form.label.placeholder.inboundPattern' | translate) }}
{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}
-
+
+
+
+

diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 9c0e60040ce..fdb07226aa8 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -67,6 +67,7 @@ export class LdnServiceFormEditComponent implements OnInit { private modalRef: any; private service: LdnService; selectedOutboundPatterns: string[]; + selectedInboundItemfilters: any; selectedInboundPatterns: string[]; constructor( @@ -214,6 +215,16 @@ export class LdnServiceFormEditComponent implements OnInit { //this.getPatternControlNames(index) } + selectInboundItemFilter(filterValue: string, index: number): void { + // this.selectedOutboundPatterns = patternValue; + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) + console.log((this.formModel.get('notifyServiceInboundPatterns') as FormArray)) + filterArray.controls[index].patchValue({constraint: filterValue} ) + + //console.log(patternArray); + //this.getPatternControlNames(index) + } + selectInboundPattern(patternValue: string, index: number): void { // this.selectedOutboundPatterns = patternValue; const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) @@ -474,4 +485,7 @@ export class LdnServiceFormEditComponent implements OnInit { //console.warn('inside setValueForControlInOutboundArray', formArray); //formArray.at(index).setValue(value); //} + + + } From 778a06724b33e036ce4ed4080d276f981e3e1dac Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Wed, 15 Nov 2023 12:48:53 +0100 Subject: [PATCH 176/592] CST-12455 Edit page logic is working now finishing up the styling for the page --- .../ldn-service-form-edit.component.html | 50 +- .../ldn-service-form-edit.component.ts | 800 +++++++++--------- 2 files changed, 437 insertions(+), 413 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 51abf43f04d..2940ee00398 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -108,7 +108,8 @@

{{ 'ldn-edit-registered-service.title' | translate }}{{ selectedInboundPatterns ? ('ldn-service.form.pattern.' + selectedInboundPatterns + '.description' | translate) : ('' | translate) }}

-

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

diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index fecd9113d64..e01964a4fb8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3375,6 +3375,10 @@ "quality-assurance.event.table.more": "Show more", + "quality-assurance.event.table.event.message.serviceName": "Service Name:", + + "quality-assurance.event.table.event.message.link": "Link:", + "quality-assurance.event.project.found": "Bound to the local record:", "quality-assurance.event.project.notFound": "No local record found", From 53ba509ff9f052d3291a171d8de8099fd82b5504 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Fri, 17 Nov 2023 17:18:16 +0100 Subject: [PATCH 192/592] [CST-11523] footer component unit tests --- src/app/footer/footer.component.spec.ts | 75 +++++++++++++++++++++---- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/src/app/footer/footer.component.spec.ts b/src/app/footer/footer.component.spec.ts index 0d6069ece8e..010d4e22c2f 100644 --- a/src/app/footer/footer.component.spec.ts +++ b/src/app/footer/footer.component.spec.ts @@ -1,5 +1,5 @@ // ... test imports -import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, inject, TestBed,waitForAsync } from '@angular/core/testing'; import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'; @@ -9,6 +9,7 @@ import { By } from '@angular/platform-browser'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { StoreModule } from '@ngrx/store'; +import { of } from 'rxjs'; // Load the implementations that should be tested import { FooterComponent } from './footer.component'; @@ -18,22 +19,21 @@ import { storeModuleConfig } from '../app.reducer'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataServiceStub } from '../shared/testing/authorization-service.stub'; import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; -import { of } from 'rxjs'; +import { environment } from 'src/environments/environment'; + let comp: FooterComponent; +let compAny: any; let fixture: ComponentFixture; let de: DebugElement; let el: HTMLElement; -let notifyInfoServiceStub: any; +let notifyInfoService = { + isCoarConfigEnabled: () => of(true) +}; describe('Footer component', () => { - - // waitForAsync beforeEach beforeEach(waitForAsync(() => { - notifyInfoServiceStub = { - isCoarConfigEnabled: () => of(true) - }; return TestBed.configureTestingModule({ imports: [CommonModule, StoreModule.forRoot({}, storeModuleConfig), TranslateModule.forRoot({ loader: { @@ -45,7 +45,7 @@ describe('Footer component', () => { providers: [ FooterComponent, { provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub }, - { provide: NotifyInfoService, useValue: notifyInfoServiceStub }, + { provide: NotifyInfoService, useValue: notifyInfoService } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -54,9 +54,8 @@ describe('Footer component', () => { // synchronous beforeEach beforeEach(() => { fixture = TestBed.createComponent(FooterComponent); - - comp = fixture.componentInstance; // component test instance - + comp = fixture.componentInstance; + compAny = comp as any; // query for the title

by CSS element selector de = fixture.debugElement.query(By.css('p')); el = de.nativeElement; @@ -67,4 +66,56 @@ describe('Footer component', () => { expect(app).toBeTruthy(); })); + + it('should set showPrivacyPolicy to the value of environment.info.enablePrivacyStatement', () => { + expect(comp.showPrivacyPolicy).toBe(environment.info.enablePrivacyStatement); + }); + + it('should set showEndUserAgreement to the value of environment.info.enableEndUserAgreement', () => { + expect(comp.showEndUserAgreement).toBe(environment.info.enableEndUserAgreement); + }); + + describe('showCookieSettings', () => { + it('should call cookies.showSettings() if cookies is defined', () => { + const cookies = jasmine.createSpyObj('cookies', ['showSettings']); + compAny.cookies = cookies; + comp.showCookieSettings(); + expect(cookies.showSettings).toHaveBeenCalled(); + }); + + it('should not call cookies.showSettings() if cookies is undefined', () => { + compAny.cookies = undefined; + expect(() => comp.showCookieSettings()).not.toThrow(); + }); + + it('should return false', () => { + expect(comp.showCookieSettings()).toBeFalse(); + }); + }); + + describe('when coarLdnEnabled is true', () => { + beforeEach(() => { + spyOn(notifyInfoService, 'isCoarConfigEnabled').and.returnValue(of(true)); + fixture.detectChanges(); + }); + + it('should set coarLdnEnabled based on notifyInfoService', () => { + expect(comp.coarLdnEnabled).toBeTruthy(); + // Check if COAR Notify section is rendered + const notifySection = fixture.debugElement.query(By.css('.notify-enabled')); + expect(notifySection).toBeTruthy(); + }); + + it('should redirect to info/coar-notify-support', () => { + // Check if the link to the COAR Notify support page is present + const routerLink = fixture.debugElement.query(By.css('a[routerLink="info/coar-notify-support"].coar-notify-support-route')); + expect(routerLink).toBeTruthy(); + }); + + it('should have an img tag with the class "n-coar" when coarLdnEnabled is true', fakeAsync(() => { + // Check if the img tag with the class "n-coar" is present + const imgTag = fixture.debugElement.query(By.css('.notify-enabled img.n-coar')); + expect(imgTag).toBeTruthy(); + })); + }); }); From 3c96abb64fba6af18695922028f6cf674b920275 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 17 Nov 2023 17:23:35 +0100 Subject: [PATCH 193/592] CST-12498 Provided working mock, finishing the tests files --- .../ldnServicesRD$-mock.ts | 137 ++++++++++++++++-- .../ldn-services-directory.component.ts | 21 +++ 2 files changed, 148 insertions(+), 10 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index 3bd1bf249f8..3f559c6c48c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -2,9 +2,13 @@ import {LdnService} from '../ldn-services-model/ldn-services.model'; import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; import {RemoteData} from '../../../core/data/remote-data'; import {PaginatedList} from '../../../core/data/paginated-list.model'; -import {Observable, of} from 'rxjs'; -// Create a mock data object for a single LDN notify service +import {Observable, of} from "rxjs"; +import {createSuccessfulRemoteDataObject$} from "../../../shared/remote-data.utils"; + export const mockLdnService: LdnService = { + uuid: "1", + enabled: false, + score: 0, id: 1, name: 'Service Name', description: 'Service Description', @@ -14,30 +18,147 @@ export const mockLdnService: LdnService = { { pattern: 'patternA', constraint: 'itemFilterA', - automatic: false, + automatic: 'false', }, { pattern: 'patternB', constraint: 'itemFilterB', - automatic: true, + automatic: 'true', }, ], notifyServiceOutboundPatterns: [ { pattern: 'patternC', constraint: 'itemFilterC', + automatic: 'true', }, ], type: LDN_SERVICE, _links: { self: { - href: 'http://localhost/api/ldn/ldnservices/1', + href: 'http://localhost/api/ldn/ldnservices/1' }, }, + get self(): string { + return ""; + }, }; +//export const mockLdnServiceRD$: Observable>> = of((mockLdnService as unknown) as RemoteData>); +export const mockLdnServiceRD$: Observable> = createSuccessfulRemoteDataObject$(mockLdnService); + -const mockLdnServices = { +export const mockLdnServices: LdnService[] = [{ + uuid: "1", + enabled: false, + score: 0, + id: 1, + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: 'false', + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: 'true', + }, + ], + notifyServiceOutboundPatterns: [ + { + pattern: 'patternC', + constraint: 'itemFilterC', + automatic: 'true', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1' + }, + }, + get self(): string { + return ""; + }, +},{ + uuid: "2", + enabled: false, + score: 0, + id: 2, + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: 'false', + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: 'true', + }, + ], + notifyServiceOutboundPatterns: [ + { + pattern: 'patternC', + constraint: 'itemFilterC', + automatic: 'true', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1' + }, + }, + get self(): string { + return ""; + }, +} +] +export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); + + +/*export const mockLdnServiceRD$: RemoteData> = { + errorMessage: null, + lastUpdated: 1700176600821, + msToLive: 900000, + payload: { + page: [mockLdnService], + pageInfo: { + elementsPerPage: 20, + totalPages: 1, + totalElements: 1, + currentPage: 1, + }, + type: {value: "paginated-list"}, + _links: { + self: { + href: "http://localhost:8080/server/api/ldn/ldnservices?size=20&sort=dc.title,ASC" + }, + page: [ + { + "href": "http://localhost/api/ldn/ldnservices/1" + } + ] + }, + }, + statusCode: 200, + state: 'Success', + timeCompleted: 1700176600821, +}*/ + + + +const mockLdnServices2 = { payload: { elementsPerPage: 20, totalPages: 1, @@ -63,7 +184,3 @@ const mockLdnServices = { hasSucceeded: true, msToLive: 0, }; - - -// Create a mock ldnServicesRD$ observable -export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index ac9354a3e48..99e420568cd 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -22,6 +22,7 @@ import {Operation} from 'fast-json-patch'; import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {TranslateService} from '@ngx-translate/core'; +import {mockLdnServiceRD$, mockLdnServicesRD$} from "../ldn-service-serviceMock/ldnServicesRD$-mock"; @Component({ @@ -36,6 +37,9 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { servicesData: any[] = []; @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; ldnServicesRD$: Observable>>; + //TODO: remove mocks an put in test after finishing + mockLdnServiceRD$: Observable>>; + mockLdnServicesRD$: Observable>>; config: FindListOptions = Object.assign(new FindListOptions(), { elementsPerPage: 20 }); @@ -47,6 +51,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { private modalRef: any; + constructor( protected ldnServicesService: LdnServicesService, protected paginationService: PaginationService, @@ -68,6 +73,22 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { )) ); + this.mockLdnServiceRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( + getFirstCompletedRemoteData() + )) + + ); + this.mockLdnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( + getFirstCompletedRemoteData() + )) + + ); + this.ldnServicesRD$.subscribe((rd: RemoteData>) => {console.log('realremotedata:',rd);}) + this.mockLdnServiceRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata:',rd);}) + this.mockLdnServicesRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata[ldnservice]:',rd);}) + } ngOnDestroy(): void { From 92b791ed153b0981ee0ca1c2fa212f0663a792c4 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 17 Nov 2023 20:34:28 +0100 Subject: [PATCH 194/592] CST-12498 Added tests, still needs cleanup and check on one behaviour --- .../ldnServicesRD$-mock.ts | 3 +- .../ldn-services-directory.component.spec.ts | 119 ++++++++++++++---- .../ldn-services-directory.component.ts | 34 +++-- 3 files changed, 112 insertions(+), 44 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index 3f559c6c48c..5d409964c26 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -45,7 +45,8 @@ export const mockLdnService: LdnService = { }; //export const mockLdnServiceRD$: Observable>> = of((mockLdnService as unknown) as RemoteData>); -export const mockLdnServiceRD$: Observable> = createSuccessfulRemoteDataObject$(mockLdnService); +//export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(createPaginatedList(mockLdnService[0])as PaginatedList); +export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(mockLdnService); export const mockLdnServices: LdnService[] = [{ diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index 87a1da27a1c..6912379b786 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -1,18 +1,26 @@ -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; -import {ChangeDetectorRef, EventEmitter} from '@angular/core'; -import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; -import {TranslateModule, TranslateService} from '@ngx-translate/core'; -import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; -import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; -import {PaginationService} from '../../../core/pagination/pagination.service'; -import {PaginationServiceStub} from '../../../shared/testing/pagination-service.stub'; -import {of} from 'rxjs'; +import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; +import { ChangeDetectorRef, EventEmitter, TemplateRef, ViewChild } from '@angular/core'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { of } from 'rxjs'; +import { LdnService } from "../ldn-services-model/ldn-services.model"; +import { PaginatedList } from "../../../core/data/paginated-list.model"; +import { RemoteData } from "../../../core/data/remote-data"; +import { LdnServicesOverviewComponent } from './ldn-services-directory.component'; describe('LdnServicesOverviewComponent', () => { let component: LdnServicesOverviewComponent; let fixture: ComponentFixture; + let ldnServicesService: LdnServicesService; + let paginationService: PaginationService; + let modalService: NgbModal; + let notificationsService: NotificationsService; + let translateService: TranslateService; const translateServiceStub = { get: () => of('translated-text'), @@ -26,29 +34,92 @@ describe('LdnServicesOverviewComponent', () => { imports: [TranslateModule.forRoot()], declarations: [LdnServicesOverviewComponent], providers: [ - {provide: LdnServicesService, useValue: {}}, - {provide: PaginationService, useValue: new PaginationServiceStub()}, - { - provide: NgbModal, useValue: { - open: () => {/*comment*/ - } - } - }, - {provide: ChangeDetectorRef, useValue: {}}, - {provide: NotificationsService, useValue: NotificationsServiceStub}, - {provide: TranslateService, useValue: translateServiceStub}, + { provide: LdnServicesService, useValue: jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']) }, + { provide: PaginationService, useValue: new PaginationServiceStub() }, + { provide: NgbModal, useValue: { open: () => { /*comment*/ } } }, + { provide: ChangeDetectorRef, useValue: {} }, + { provide: NotificationsService, useValue: NotificationsServiceStub }, + { provide: TranslateService, useValue: translateServiceStub }, ] - }) - .compileComponents(); + }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(LdnServicesOverviewComponent); component = fixture.componentInstance; + ldnServicesService = TestBed.inject(LdnServicesService); + paginationService = TestBed.inject(PaginationService); + modalService = TestBed.inject(NgbModal); + notificationsService = TestBed.inject(NotificationsService); + translateService = TestBed.inject(TranslateService); + component.modalRef = jasmine.createSpyObj({ close: null }); + component.isProcessingSub = jasmine.createSpyObj({ unsubscribe: null }); + component.ldnServicesRD$ = of({} as RemoteData>); // You can adjust the mock data as needed fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('ngOnInit', () => { + it('should call setLdnServices', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + })); + + it('should set ldnServicesRD$ with mock data', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + const mockData = { /* your mock data here */ }; + component.ldnServicesRD$ = of(mockData as RemoteData>); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + // Add more expectations based on your mock data and component behavior + })); + }); + + describe('ngOnDestroy', () => { + it('should call paginationService.clearPagination and unsubscribe', () => { + spyOn(paginationService, 'clearPagination'); + spyOn(component.isProcessingSub, 'unsubscribe'); + component.ngOnDestroy(); + expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); + expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); + }); + }); + + describe('openDeleteModal', () => { + it('should open delete modal', () => { + spyOn(modalService, 'open'); + component.openDeleteModal(component.deleteModal); + expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); + }); + }); + + describe('closeModal', () => { + it('should close modal and detect changes', () => { + spyOn(component.modalRef, 'close'); + spyOn(component.cdRef, 'detectChanges'); + component.closeModal(); + expect(component.modalRef.close).toHaveBeenCalled(); + expect(component.cdRef.detectChanges).toHaveBeenCalled(); + }); + }); + + describe('deleteSelected', () => { + it('should delete selected service and update data', fakeAsync(() => { + const serviceId = '123'; + const mockRemoteData = { /* insert mock data with service id 123 */ }; + spyOn(component, 'setLdnServices').and.callThrough(); + const deleteSpy = spyOn(ldnServicesService, 'delete').and.returnValue(of(mockRemoteData as RemoteData>)); + component.selectedServiceId = serviceId; + component.deleteSelected(serviceId, ldnServicesService); + tick(); + expect(deleteSpy).toHaveBeenCalledWith(serviceId); + expect(mockRemoteData) + })); + }); }); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 99e420568cd..476d8ef1b59 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -22,7 +22,7 @@ import {Operation} from 'fast-json-patch'; import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {TranslateService} from '@ngx-translate/core'; -import {mockLdnServiceRD$, mockLdnServicesRD$} from "../ldn-service-serviceMock/ldnServicesRD$-mock"; +import { mockLdnServiceRD$ } from "../ldn-service-serviceMock/ldnServicesRD$-mock"; @Component({ @@ -38,8 +38,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; ldnServicesRD$: Observable>>; //TODO: remove mocks an put in test after finishing - mockLdnServiceRD$: Observable>>; - mockLdnServicesRD$: Observable>>; + //mockLdnServiceRD$: Observable>; + // mockLdnServicesRD$: Observable>>; config: FindListOptions = Object.assign(new FindListOptions(), { elementsPerPage: 20 }); @@ -48,17 +48,17 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { pageSize: 20 }); isProcessingSub: Subscription; - private modalRef: any; + modalRef: any; constructor( - protected ldnServicesService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - private cdRef: ChangeDetectorRef, - private notificationService: NotificationsService, - private translateService: TranslateService, + protected ldnServicesService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public cdRef: ChangeDetectorRef, + private notificationService: NotificationsService, + private translateService: TranslateService, ) { } @@ -72,22 +72,18 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { getFirstCompletedRemoteData() )) - ); - this.mockLdnServiceRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( - getFirstCompletedRemoteData() - )) + );/* + this.mockLdnServiceRD$ = mockLdnServiceRD$ - ); this.mockLdnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( getFirstCompletedRemoteData() )) - ); + );this.paginationService.getFindListOptions(this.pageConfig.id, this.config) this.ldnServicesRD$.subscribe((rd: RemoteData>) => {console.log('realremotedata:',rd);}) - this.mockLdnServiceRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata:',rd);}) - this.mockLdnServicesRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata[ldnservice]:',rd);}) + this.mockLdnServiceRD$.subscribe((rd: RemoteData) => {console.log('mockremotedata:',rd);}) + this.mockLdnServicesRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata[ldnservice]:',rd);})*/ } From bdd2a8bcab6b75eba52e43dccea7c80ff28f371b Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 17 Nov 2023 21:19:38 +0100 Subject: [PATCH 195/592] CST-12498 Tests added, need to check TODOs in ldn-services-directory.component.spec.ts --- .../ldn-services-directory.component.spec.ts | 241 ++++++++++-------- 1 file changed, 132 insertions(+), 109 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index 6912379b786..8213e5bc535 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -1,125 +1,148 @@ -import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; -import { ChangeDetectorRef, EventEmitter, TemplateRef, ViewChild } from '@angular/core'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; -import { TranslateModule, TranslateService } from '@ngx-translate/core'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; -import { of } from 'rxjs'; -import { LdnService } from "../ldn-services-model/ldn-services.model"; -import { PaginatedList } from "../../../core/data/paginated-list.model"; -import { RemoteData } from "../../../core/data/remote-data"; -import { LdnServicesOverviewComponent } from './ldn-services-directory.component'; +import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; +import {ChangeDetectorRef, EventEmitter} from '@angular/core'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; +import {TranslateModule, TranslateService} from '@ngx-translate/core'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; +import {PaginationService} from '../../../core/pagination/pagination.service'; +import {PaginationServiceStub} from '../../../shared/testing/pagination-service.stub'; +import {of} from 'rxjs'; +import {LdnService} from "../ldn-services-model/ldn-services.model"; +import {PaginatedList} from "../../../core/data/paginated-list.model"; +import {RemoteData} from "../../../core/data/remote-data"; +import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; describe('LdnServicesOverviewComponent', () => { - let component: LdnServicesOverviewComponent; - let fixture: ComponentFixture; - let ldnServicesService: LdnServicesService; - let paginationService: PaginationService; - let modalService: NgbModal; - let notificationsService: NotificationsService; - let translateService: TranslateService; + let component: LdnServicesOverviewComponent; + let fixture: ComponentFixture; + let ldnServicesService: LdnServicesService; + let paginationService: PaginationService; + let modalService: NgbModal; + let notificationsService: NotificationsService; + let translateService: TranslateService; - const translateServiceStub = { - get: () => of('translated-text'), - onLangChange: new EventEmitter(), - onTranslationChange: new EventEmitter(), - onDefaultLangChange: new EventEmitter() - }; + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot()], - declarations: [LdnServicesOverviewComponent], - providers: [ - { provide: LdnServicesService, useValue: jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']) }, - { provide: PaginationService, useValue: new PaginationServiceStub() }, - { provide: NgbModal, useValue: { open: () => { /*comment*/ } } }, - { provide: ChangeDetectorRef, useValue: {} }, - { provide: NotificationsService, useValue: NotificationsServiceStub }, - { provide: TranslateService, useValue: translateServiceStub }, - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [LdnServicesOverviewComponent], + providers: [ + {provide: LdnServicesService, useValue: jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch'])}, + {provide: PaginationService, useValue: new PaginationServiceStub()}, + { + provide: NgbModal, useValue: { + open: () => { /*comment*/ + } + } + }, + {provide: ChangeDetectorRef, useValue: {}}, + {provide: NotificationsService, useValue: NotificationsServiceStub}, + {provide: TranslateService, useValue: translateServiceStub}, + ] + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LdnServicesOverviewComponent); - component = fixture.componentInstance; - ldnServicesService = TestBed.inject(LdnServicesService); - paginationService = TestBed.inject(PaginationService); - modalService = TestBed.inject(NgbModal); - notificationsService = TestBed.inject(NotificationsService); - translateService = TestBed.inject(TranslateService); - component.modalRef = jasmine.createSpyObj({ close: null }); - component.isProcessingSub = jasmine.createSpyObj({ unsubscribe: null }); - component.ldnServicesRD$ = of({} as RemoteData>); // You can adjust the mock data as needed - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LdnServicesOverviewComponent); + component = fixture.componentInstance; + ldnServicesService = TestBed.inject(LdnServicesService); + paginationService = TestBed.inject(PaginationService); + modalService = TestBed.inject(NgbModal); + notificationsService = TestBed.inject(NotificationsService); + translateService = TestBed.inject(TranslateService); + component.modalRef = jasmine.createSpyObj({close: null}); + component.isProcessingSub = jasmine.createSpyObj({unsubscribe: null}); + component.ldnServicesRD$ = of({} as RemoteData>); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { - it('should call setLdnServices', fakeAsync(() => { - spyOn(component, 'setLdnServices').and.callThrough(); - component.ngOnInit(); - tick(); - expect(component.setLdnServices).toHaveBeenCalled(); - })); + describe('ngOnInit', () => { + it('should call setLdnServices', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + })); - it('should set ldnServicesRD$ with mock data', fakeAsync(() => { - spyOn(component, 'setLdnServices').and.callThrough(); - const mockData = { /* your mock data here */ }; - component.ldnServicesRD$ = of(mockData as RemoteData>); - component.ngOnInit(); - tick(); - expect(component.setLdnServices).toHaveBeenCalled(); - // Add more expectations based on your mock data and component behavior - })); - }); + it('should set ldnServicesRD$ with mock data', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + const mockData = { + payload: { + page: [ + {id: 1, name: 'Service 1', description: 'Description 1', enabled: true}, + {id: 2, name: 'Service 2', description: 'Description 2', enabled: false}, + {id: 3, name: 'Service 3', description: 'Description 3', enabled: true}, + ], + totalElements: 3 + } + } as RemoteData>; + component.ldnServicesRD$ = of(mockData as RemoteData>); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + fixture.detectChanges(); + console.log(fixture.nativeElement.innerHTML); + console.log('Mock Data:', mockData); + const tableRows = fixture.nativeElement.querySelectorAll('tbody tr'); + console.log('Table Rows:', tableRows); + //TODO: check why the tbody tr length table rows is 0 when i sjhould be 3 accordingly to the mock + expect(tableRows.length).toBe(mockData.payload.page.length); + const firstRowContent = tableRows[0].textContent; + expect(firstRowContent).toContain('Service 1'); + expect(firstRowContent).toContain('Description 1'); + })); + }); - describe('ngOnDestroy', () => { - it('should call paginationService.clearPagination and unsubscribe', () => { - spyOn(paginationService, 'clearPagination'); - spyOn(component.isProcessingSub, 'unsubscribe'); - component.ngOnDestroy(); - expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); - expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); + describe('ngOnDestroy', () => { + it('should call paginationService.clearPagination and unsubscribe', () => { + spyOn(paginationService, 'clearPagination'); + spyOn(component.isProcessingSub, 'unsubscribe'); + component.ngOnDestroy(); + expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); + expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); + }); }); - }); - describe('openDeleteModal', () => { - it('should open delete modal', () => { - spyOn(modalService, 'open'); - component.openDeleteModal(component.deleteModal); - expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); + describe('openDeleteModal', () => { + it('should open delete modal', () => { + spyOn(modalService, 'open'); + component.openDeleteModal(component.deleteModal); + expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); + }); }); - }); - describe('closeModal', () => { - it('should close modal and detect changes', () => { - spyOn(component.modalRef, 'close'); - spyOn(component.cdRef, 'detectChanges'); - component.closeModal(); - expect(component.modalRef.close).toHaveBeenCalled(); - expect(component.cdRef.detectChanges).toHaveBeenCalled(); + describe('closeModal', () => { + it('should close modal and detect changes', () => { + spyOn(component.modalRef, 'close'); + spyOn(component.cdRef, 'detectChanges'); + component.closeModal(); + expect(component.modalRef.close).toHaveBeenCalled(); + expect(component.cdRef.detectChanges).toHaveBeenCalled(); + }); }); - }); - describe('deleteSelected', () => { - it('should delete selected service and update data', fakeAsync(() => { - const serviceId = '123'; - const mockRemoteData = { /* insert mock data with service id 123 */ }; - spyOn(component, 'setLdnServices').and.callThrough(); - const deleteSpy = spyOn(ldnServicesService, 'delete').and.returnValue(of(mockRemoteData as RemoteData>)); - component.selectedServiceId = serviceId; - component.deleteSelected(serviceId, ldnServicesService); - tick(); - expect(deleteSpy).toHaveBeenCalledWith(serviceId); - expect(mockRemoteData) - })); - }); + describe('deleteSelected', () => { + it('should delete selected service and update data', fakeAsync(() => { + const serviceId = '123'; + //TODO: finish up this test to use a mockdata containing something + const mockRemoteData = { /* insert mock data with service id 123 */}; + spyOn(component, 'setLdnServices').and.callThrough(); + const deleteSpy = spyOn(ldnServicesService, 'delete').and.returnValue(of(mockRemoteData as RemoteData>)); + component.selectedServiceId = serviceId; + component.deleteSelected(serviceId, ldnServicesService); + tick(); + expect(deleteSpy).toHaveBeenCalledWith(serviceId); + })); + }); }); From d1ae9adaac67a96c339b01aad6a3a174c79a81f1 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Sat, 18 Nov 2023 01:09:52 +0100 Subject: [PATCH 196/592] CST-12498 Added javadocs --- .../ldn-services-directory.component.ts | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 476d8ef1b59..4fc503026b3 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -66,6 +66,9 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { this.setLdnServices(); } + /** + * Sets up the LDN services by fetching and observing the paginated list of services. + */ setLdnServices() { this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( @@ -94,20 +97,39 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } } + /** + * Opens the delete confirmation modal. + * + * @param {any} content - The content of the modal. + */ openDeleteModal(content) { this.modalRef = this.modalService.open(content); } + /** + * Closes the currently open modal and triggers change detection. + */ closeModal() { this.modalRef.close(); this.cdRef.detectChanges(); } + /** + * Sets the selected LDN service ID for deletion and opens the delete confirmation modal. + * + * @param {number} serviceId - The ID of the service to be deleted. + */ selectServiceToDelete(serviceId: number) { this.selectedServiceId = serviceId; this.openDeleteModal(this.deleteModal); } + /** + * Deletes the selected LDN service. + * + * @param {string} serviceId - The ID of the service to be deleted. + * @param {LdnServicesService} ldnServicesService - The service for managing LDN services. + */ deleteSelected(serviceId: string, ldnServicesService: LdnServicesService): void { if (this.selectedServiceId !== null) { ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { @@ -134,7 +156,12 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } } - + /** + * Toggles the status (enabled/disabled) of an LDN service. + * + * @param {any} ldnService - The LDN service object. + * @param {LdnServicesService} ldnServicesService - The service for managing LDN services. + */ toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { const newStatus = !ldnService.enabled; const originalStatus = ldnService.enabled; @@ -159,6 +186,4 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } ); } - - } From f7ca7a688d1cff0ab98a79dfed537b792fbd31f5 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Sat, 18 Nov 2023 01:13:17 +0100 Subject: [PATCH 197/592] CST-12498 Added javadocs --- .../ldn-services-directory.component.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 4fc503026b3..3d1341b4711 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -25,6 +25,11 @@ import {TranslateService} from '@ngx-translate/core'; import { mockLdnServiceRD$ } from "../ldn-service-serviceMock/ldnServicesRD$-mock"; +/** + * The `LdnServicesOverviewComponent` is a component that provides an overview of LDN (Linked Data Notifications) services. + * It displays a paginated list of LDN services, allows users to edit and delete services, + * toggle the status of each service directly form the page and allows for creation of new services redirecting the user on the creation form + */ @Component({ selector: 'ds-ldn-services-directory', templateUrl: './ldn-services-directory.component.html', From 80991e650191e67cff190fe774be2d9fb777e54b Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 10:11:01 +0100 Subject: [PATCH 198/592] CST-12498 Fixed create form labels alignment --- .../ldn-service-form/ldn-service-form.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index bc71eda994f..650fd8d3be1 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -178,7 +178,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
@@ -202,7 +202,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
@@ -301,7 +301,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
From f35e6ae0dc7f35c2d534690e6cce706f528346a8 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 13:09:42 +0100 Subject: [PATCH 199/592] CST-12498 Fixed tests for directory, no more failing ones --- .../ldn-service-form.component.ts | 103 +++++++- .../ldn-itemfilters-data.service.ts | 14 ++ .../ldn-services-directory.component.spec.ts | 233 +++++++++--------- 3 files changed, 226 insertions(+), 124 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 2d589547bc7..28aa6c4ef05 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -19,7 +19,10 @@ import {PaginationComponentOptions} from '../../../shared/pagination/pagination- import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; - +/** + * Angular component representing the form for creating or editing LDN services. + * This component handles the creation, validation, and submission of LDN service data. + */ @Component({ selector: 'ds-ldn-service-form', templateUrl: './ldn-service-form.component.html', @@ -100,23 +103,43 @@ export class LdnServiceFormComponent implements OnInit { } + /** + * Sets up the item filters by fetching and observing the paginated list of item filters. + */ setItemfilters() { this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( getFirstCompletedRemoteData()); } + /** + * Handles the form submission by opening the confirmation modal. + */ onSubmit() { this.openConfirmModal(this.confirmModal); } + /** + * Opens the confirmation modal. + * + * @param {any} content - The content of the modal. + */ openConfirmModal(content) { this.modalRef = this.modalService.open(content); } + /** + * Opens the reset form modal. + * + * @param {any} content - The content of the modal. + */ openResetFormModal(content) { this.modalRef = this.modalService.open(content); } + /** + * Handles the creation of an LDN service by validating form fields, + * and submitting the form data to the LDN services endpoint. + */ createService() { this.formModel.get('name').markAsTouched(); this.formModel.get('score').markAsTouched(); @@ -175,6 +198,12 @@ export class LdnServiceFormComponent implements OnInit { }); } + /** + * Checks if at least one pattern in the specified form array has a value. + * + * @param {FormArray} formArray - The form array containing patterns to check. + * @returns {boolean} - True if at least one pattern has a value, otherwise false. + */ checkPatterns(formArray: FormArray): boolean { for (let i = 0; i < formArray.length; i++) { const pattern = formArray.at(i).get('pattern').value; @@ -185,37 +214,65 @@ export class LdnServiceFormComponent implements OnInit { return false; } - + /** + * Closes the currently open modal and returns to the services directory.. + */ resetFormAndLeave() { this.sendBack(); this.closeModal(); } + /** + * Closes the currently open modal and triggers change detection. + */ closeModal() { this.modalRef.close(); this.cdRef.detectChanges(); } + /** + * Adds a new inbound pattern form group to the notifyServiceInboundPatterns form array. + */ addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } + /** + * Removes the inbound pattern form group at the specified index from the notifyServiceInboundPatterns form array. + * + * @param {number} index - The index of the inbound pattern form group to remove. + * @memberof LdnServiceFormComponent + */ removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.removeAt(index); } + /** + * Adds a new outbound pattern form group to the notifyServiceOutboundPatterns form array. + */ addOutboundPattern() { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } + /** + * Removes the outbound pattern form group at the specified index from the notifyServiceOutboundPatterns form array. + * + * @param {number} index - The index of the outbound pattern form group to remove. + */ removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; notifyServiceOutboundPatternsArray.removeAt(index); } + /** + * Toggles the value of the 'automatic' control at the specified index in the notifyServiceInboundPatterns form array. + * + * @param {number} i - The index of the 'automatic' control to toggle. + * @memberof LdnServiceFormComponent + */ toggleAutomatic(i: number) { const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); if (automaticControl) { @@ -223,7 +280,12 @@ export class LdnServiceFormComponent implements OnInit { } } - + /** + * Selects an outbound pattern for a specific index in the notifyServiceOutboundPatterns form array. + * + * @param {string} patternValue - The selected pattern value. + * @param {number} index - The index of the outbound pattern in the form array. + */ selectOutboundPattern(patternValue: string, index: number): void { const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) patternArray.controls[index].patchValue({pattern: patternValue}) @@ -231,6 +293,12 @@ export class LdnServiceFormComponent implements OnInit { } + /** + * Selects an inbound pattern for a specific index in the form array. + * + * @param {string} patternValue - The selected pattern value. + * @param {number} index - The index of the inbound pattern in the form array. + */ selectInboundPattern(patternValue: string, index: number): void { const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) patternArray.controls[index].patchValue({pattern: patternValue}) @@ -238,21 +306,40 @@ export class LdnServiceFormComponent implements OnInit { } + /** + * Selects an inbound item filter for a specific index in the form array. + * + * @param {string} filterValue - The selected item filter value. + * @param {number} index - The index of the inbound item filter in the form array. + */ selectInboundItemFilter(filterValue: string, index: number): void { const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) filterArray.controls[index].patchValue({constraint: filterValue}) } + /** + * Selects an outbound item filter for a specific index in the form array. + * + * @param {string} filterValue - The selected item filter value. + * @param {number} index - The index of the outbound item filter in the form array. + */ selectOutboundItemFilter(filterValue: string, index: number) { const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) filterArray.controls[index].patchValue({constraint: filterValue}) } + /** + * Sends the user back to the LDN services list. + */ private sendBack() { this.router.navigateByUrl('admin/ldn/services'); } - - + /** + * Creates a form group for an outbound pattern in the notifyServiceOutboundPatterns form array. + * + * @private + * @returns {FormGroup} - The created form group. + */ private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: [''], @@ -261,6 +348,12 @@ export class LdnServiceFormComponent implements OnInit { }); } + /** + * Creates a form group for an inbound pattern in the notifyServiceInboundPatterns form array. + * + * @private + * @returns {FormGroup} - The created form group. + */ private createInboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: [''], diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts index 7aa6231b4d4..15a7bcccdaa 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts @@ -37,10 +37,24 @@ export class LdnItemfiltersService extends IdentifiableDataService i this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } + /** + * Gets the endpoint URL for the itemfilters. + * + * @returns {string} - The endpoint URL. + */ getEndpoint() { return this.halService.getEndpoint(this.linkPath); } + /** + * Finds all itemfilters based on the provided options and link configurations. + * + * @param {FindListOptions} options - The options for finding a list of itemfilters. + * @param {boolean} useCachedVersionIfAvailable - Whether to use the cached version if available. + * @param {boolean} reRequestOnStale - Whether to re-request the data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Configurations for following specific links. + * @returns {Observable>>} - An observable of remote data containing a paginated list of itemfilters. + */ findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index 8213e5bc535..c5ec66c7574 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -12,137 +12,132 @@ import {LdnService} from "../ldn-services-model/ldn-services.model"; import {PaginatedList} from "../../../core/data/paginated-list.model"; import {RemoteData} from "../../../core/data/remote-data"; import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; +import {createSuccessfulRemoteDataObject$} from "../../../shared/remote-data.utils"; +import {createPaginatedList} from "../../../shared/testing/utils.test"; -describe('LdnServicesOverviewComponent', () => { - let component: LdnServicesOverviewComponent; - let fixture: ComponentFixture; - let ldnServicesService: LdnServicesService; - let paginationService: PaginationService; - let modalService: NgbModal; - let notificationsService: NotificationsService; - let translateService: TranslateService; +describe('LdnServicesOverviewComponent', ( ) => { + let component: LdnServicesOverviewComponent; + let fixture: ComponentFixture; + let ldnServicesService; + let paginationService; + let modalService: NgbModal; + let notificationsService: NotificationsService; + let translateService: TranslateService; - const translateServiceStub = { - get: () => of('translated-text'), - onLangChange: new EventEmitter(), - onTranslationChange: new EventEmitter(), - onDefaultLangChange: new EventEmitter() - }; + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot()], - declarations: [LdnServicesOverviewComponent], - providers: [ - {provide: LdnServicesService, useValue: jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch'])}, - {provide: PaginationService, useValue: new PaginationServiceStub()}, - { - provide: NgbModal, useValue: { - open: () => { /*comment*/ - } - } - }, - {provide: ChangeDetectorRef, useValue: {}}, - {provide: NotificationsService, useValue: NotificationsServiceStub}, - {provide: TranslateService, useValue: translateServiceStub}, - ] - }).compileComponents(); - }); + beforeEach(async () => { + paginationService = new PaginationServiceStub(); + ldnServicesService = jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']) + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [LdnServicesOverviewComponent], + providers: [ + { + provide: LdnServicesService, + useValue: ldnServicesService + }, + {provide: PaginationService, useValue: paginationService}, + { + provide: NgbModal, useValue: { + open: () => { /*comment*/} + } + }, + {provide: ChangeDetectorRef, useValue: {}}, + {provide: NotificationsService, useValue: NotificationsServiceStub}, + {provide: TranslateService, useValue: translateServiceStub}, + ] + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LdnServicesOverviewComponent); - component = fixture.componentInstance; - ldnServicesService = TestBed.inject(LdnServicesService); - paginationService = TestBed.inject(PaginationService); - modalService = TestBed.inject(NgbModal); - notificationsService = TestBed.inject(NotificationsService); - translateService = TestBed.inject(TranslateService); - component.modalRef = jasmine.createSpyObj({close: null}); - component.isProcessingSub = jasmine.createSpyObj({unsubscribe: null}); - component.ldnServicesRD$ = of({} as RemoteData>); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LdnServicesOverviewComponent); + component = fixture.componentInstance; + ldnServicesService = TestBed.inject(LdnServicesService); + paginationService = TestBed.inject(PaginationService); + modalService = TestBed.inject(NgbModal); + notificationsService = TestBed.inject(NotificationsService); + translateService = TestBed.inject(TranslateService); + component.modalRef = jasmine.createSpyObj({close: null}); + component.isProcessingSub = jasmine.createSpyObj({unsubscribe: null}); + component.ldnServicesRD$ = of({} as RemoteData>); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { - it('should call setLdnServices', fakeAsync(() => { - spyOn(component, 'setLdnServices').and.callThrough(); - component.ngOnInit(); - tick(); - expect(component.setLdnServices).toHaveBeenCalled(); - })); + describe('ngOnInit', () => { + it('should call setLdnServices', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + })); - it('should set ldnServicesRD$ with mock data', fakeAsync(() => { - spyOn(component, 'setLdnServices').and.callThrough(); - const mockData = { - payload: { - page: [ - {id: 1, name: 'Service 1', description: 'Description 1', enabled: true}, - {id: 2, name: 'Service 2', description: 'Description 2', enabled: false}, - {id: 3, name: 'Service 3', description: 'Description 3', enabled: true}, - ], - totalElements: 3 - } - } as RemoteData>; - component.ldnServicesRD$ = of(mockData as RemoteData>); - component.ngOnInit(); - tick(); - expect(component.setLdnServices).toHaveBeenCalled(); - fixture.detectChanges(); - console.log(fixture.nativeElement.innerHTML); - console.log('Mock Data:', mockData); - const tableRows = fixture.nativeElement.querySelectorAll('tbody tr'); - console.log('Table Rows:', tableRows); - //TODO: check why the tbody tr length table rows is 0 when i sjhould be 3 accordingly to the mock - expect(tableRows.length).toBe(mockData.payload.page.length); - const firstRowContent = tableRows[0].textContent; - expect(firstRowContent).toContain('Service 1'); - expect(firstRowContent).toContain('Description 1'); - })); - }); + it('should set ldnServicesRD$ with mock data', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + const testData: LdnService[] = Object.assign([new LdnService()], [ + {id: 1, name: 'Service 1', description: 'Description 1', enabled: true}, + {id: 2, name: 'Service 2', description: 'Description 2', enabled: false}, + {id: 3, name: 'Service 3', description: 'Description 3', enabled: true}]); - describe('ngOnDestroy', () => { - it('should call paginationService.clearPagination and unsubscribe', () => { - spyOn(paginationService, 'clearPagination'); - spyOn(component.isProcessingSub, 'unsubscribe'); - component.ngOnDestroy(); - expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); - expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); - }); - }); + const mockLdnServicesRD = createPaginatedList(testData) + component.ldnServicesRD$ = createSuccessfulRemoteDataObject$(mockLdnServicesRD); + fixture.detectChanges(); + + const tableRows = fixture.debugElement.nativeElement.querySelectorAll('tbody tr'); + expect(tableRows.length).toBe(testData.length); + const firstRowContent = tableRows[0].textContent; + expect(firstRowContent).toContain('Service 1'); + expect(firstRowContent).toContain('Description 1'); + })); + }); - describe('openDeleteModal', () => { - it('should open delete modal', () => { - spyOn(modalService, 'open'); - component.openDeleteModal(component.deleteModal); - expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); - }); + describe('ngOnDestroy', () => { + it('should call paginationService.clearPagination and unsubscribe', () => { + // spyOn(paginationService, 'clearPagination'); + // spyOn(component.isProcessingSub, 'unsubscribe'); + component.ngOnDestroy(); + expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); + expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); }); + }); - describe('closeModal', () => { - it('should close modal and detect changes', () => { - spyOn(component.modalRef, 'close'); - spyOn(component.cdRef, 'detectChanges'); - component.closeModal(); - expect(component.modalRef.close).toHaveBeenCalled(); - expect(component.cdRef.detectChanges).toHaveBeenCalled(); - }); + describe('openDeleteModal', () => { + it('should open delete modal', () => { + spyOn(modalService, 'open'); + component.openDeleteModal(component.deleteModal); + expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); }); + }); - describe('deleteSelected', () => { - it('should delete selected service and update data', fakeAsync(() => { - const serviceId = '123'; - //TODO: finish up this test to use a mockdata containing something - const mockRemoteData = { /* insert mock data with service id 123 */}; - spyOn(component, 'setLdnServices').and.callThrough(); - const deleteSpy = spyOn(ldnServicesService, 'delete').and.returnValue(of(mockRemoteData as RemoteData>)); - component.selectedServiceId = serviceId; - component.deleteSelected(serviceId, ldnServicesService); - tick(); - expect(deleteSpy).toHaveBeenCalledWith(serviceId); - })); + describe('closeModal', () => { + it('should close modal and detect changes', () => { + // spyOn(component.modalRef, 'close'); + spyOn(component.cdRef, 'detectChanges'); + component.closeModal(); + expect(component.modalRef.close).toHaveBeenCalled(); + expect(component.cdRef.detectChanges).toHaveBeenCalled(); }); + }); + + describe('deleteSelected', () => { + it('should delete selected service and update data', fakeAsync(() => { + const serviceId = '123'; + const mockRemoteData = { /* just an empty object to retrieve as as RemoteData> */}; + spyOn(component, 'setLdnServices').and.callThrough(); + const deleteSpy = ldnServicesService.delete.and.returnValue(of(mockRemoteData as RemoteData>)); + component.selectedServiceId = serviceId; + component.deleteSelected(serviceId, ldnServicesService); + tick(); + expect(deleteSpy).toHaveBeenCalledWith(serviceId); + })); + }); }); From 36778a09cbb04349dbb61e7bc4ab1b3f854ce2ba Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 13:27:39 +0100 Subject: [PATCH 200/592] CST-12498 Added last javadocs and removed console.log and comments --- .../ldn-service-form-edit.component.ts | 133 ++++++++++++++++-- .../ldnServicesRD$-mock.ts | 61 -------- .../ldn-services-data.service.ts | 74 +++++++++- .../ldn-services-directory.component.ts | 19 +-- .../ldn-service-patterns.model.ts | 2 +- 5 files changed, 199 insertions(+), 90 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 002aaf68122..a9659b4cce2 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -21,6 +21,10 @@ import {FindListOptions} from '../../../core/data/find-list-options.model'; import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; import {NotifyServicePattern} from "../ldn-services-model/ldn-service-patterns.model"; + +/** + * Component for editing LDN service through a form that allows to edit the properties of the selected service + */ @Component({ selector: 'ds-ldn-service-form-edit', templateUrl: './ldn-service-form-edit.component.html', @@ -109,12 +113,18 @@ export class LdnServiceFormEditComponent implements OnInit { this.setItemfilters(); } + /** + * Sets item filters using LDN item filters service + */ setItemfilters() { this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( getFirstCompletedRemoteData()); } - + /** + * Fetches LDN service data by ID and updates the form + * @param serviceId - The ID of the LDN service + */ fetchServiceData(serviceId: string): void { this.ldnServicesService.findById(serviceId).pipe( getFirstCompletedRemoteData() @@ -139,6 +149,11 @@ export class LdnServiceFormEditComponent implements OnInit { ); } + /** + * Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown.. + * @param formArrayName - The name of the form array to be populated + * @param isOutbound - A boolean indicating whether the patterns are outbound (true) or inbound (false) + */ filterPatternObjectsAndPickLabel(formArrayName: string, isOutbound: boolean) { const PatternsArray = this.formModel.get(formArrayName) as FormArray; PatternsArray.clear(); @@ -168,7 +183,10 @@ export class LdnServiceFormEditComponent implements OnInit { } - + /** + * Generates an array of patch operations based on form changes + * @returns Array of patch operations + */ generatePatchOperations(): any[] { const patchOperations: any[] = []; @@ -201,44 +219,75 @@ export class LdnServiceFormEditComponent implements OnInit { return patchOperations; } + /** + * Submits the form by opening the confirmation modal + */ onSubmit() { this.openConfirmModal(this.confirmModal); } + /** + * Adds a new inbound pattern form group to the array of inbound patterns in the form + */ addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } + /** + * Adds a new outbound pattern form group to the array of outbound patterns in the form + */ addOutboundPattern() { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } - + /** + * Selects an outbound pattern by updating its values based on the provided pattern value and index + * @param patternValue - The selected pattern value + * @param index - The index of the outbound pattern in the array + */ selectOutboundPattern(patternValue: string, index: number): void { const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) patternArray.controls[index].patchValue({pattern: patternValue}) patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) } - + /** + * Selects an outbound item filter by updating its value based on the provided filter value and index + * @param filterValue - The selected filter value + * @param index - The index of the inbound pattern in the array + */ selectOutboundItemFilter(filterValue: string, index: number) { const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) filterArray.controls[index].patchValue({constraint: filterValue}) } + /** + * Selects an inbound pattern by updating its values based on the provided pattern value and index + * @param patternValue - The selected pattern value + * @param index - The index of the inbound pattern in the array + */ selectInboundPattern(patternValue: string, index: number): void { const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) patternArray.controls[index].patchValue({pattern: patternValue}) patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) } + /** + * Selects an inbound item filter by updating its value based on the provided filter value and index + * @param filterValue - The selected filter value + * @param index - The index of the inbound pattern in the array + */ selectInboundItemFilter(filterValue: string, index: number): void { const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) filterArray.controls[index].patchValue({constraint: filterValue}) } + /** + * Toggles the automatic property of an inbound pattern at the specified index + * @param i - The index of the inbound pattern in the array + */ toggleAutomatic(i: number) { const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); if (automaticControl) { @@ -246,6 +295,9 @@ export class LdnServiceFormEditComponent implements OnInit { } } + /** + * Toggles the enabled status of the LDN service by sending a patch request + */ toggleEnabled() { const newStatus = !this.formModel.get('enabled').value; @@ -266,20 +318,33 @@ export class LdnServiceFormEditComponent implements OnInit { ); } - + /** + * Closes the modal + */ closeModal() { this.modalRef.close(); this.cdRef.detectChanges(); } + /** + * Opens a confirmation modal with the specified content + * @param content - The content to be displayed in the modal + */ openConfirmModal(content) { this.modalRef = this.modalService.open(content); } + /** + * Opens a reset form modal with the specified content + * @param content - The content to be displayed in the modal + */ openResetFormModal(content) { this.modalRef = this.modalService.open(content); } + /** + * Patches the LDN service by retrieving and sending patch operations geenrated in generatePatchOperations() + */ patchService() { this.deleteMarkedInboundPatterns(); this.deleteMarkedOutboundPatterns(); @@ -304,17 +369,28 @@ export class LdnServiceFormEditComponent implements OnInit { }); } + /** + * Resets the form and navigates back to the LDN services page + */ resetFormAndLeave() { this.sendBack(); this.closeModal(); } + /** + * Marks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ markForInboundPatternDeletion(index: number) { if (!this.markedForDeletionInboundPattern.includes(index)) { this.markedForDeletionInboundPattern.push(index); } } + /** + * Unmarks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ unmarkForInboundPatternDeletion(index: number) { const i = this.markedForDeletionInboundPattern.indexOf(index); if (i !== -1) { @@ -322,19 +398,29 @@ export class LdnServiceFormEditComponent implements OnInit { } } + /** + * Marks the specified outbound pattern for deletion + * @param index - The index of the outbound pattern in the array + */ markForOutboundPatternDeletion(index: number) { if (!this.markedForDeletionOutboundPattern.includes(index)) { this.markedForDeletionOutboundPattern.push(index); } } + /** + * Unmarks the specified outbound pattern for deletion + * @param index - The index of the outbound pattern in the array + */ unmarkForOutboundPatternDeletion(index: number) { const i = this.markedForDeletionOutboundPattern.indexOf(index); if (i !== -1) { this.markedForDeletionOutboundPattern.splice(i, 1); } } - + /** + * Deletes marked inbound patterns from the form model + */ deleteMarkedInboundPatterns() { this.markedForDeletionInboundPattern.sort((a, b) => b - a); const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; @@ -354,7 +440,9 @@ export class LdnServiceFormEditComponent implements OnInit { this.markedForDeletionInboundPattern = []; } - + /** + * Deletes marked outbound patterns from the form model + */ deleteMarkedOutboundPatterns() { this.markedForDeletionOutboundPattern.sort((a, b) => b - a); const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; @@ -375,7 +463,12 @@ export class LdnServiceFormEditComponent implements OnInit { this.markedForDeletionOutboundPattern = []; } - + /** + * Creates a replace operation and adds it to the patch operations if the form control is dirty + * @param patchOperations - The array to store patch operations + * @param formControlName - The name of the form control + * @param path - The JSON Patch path for the operation + */ private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { if (this.formModel.get(formControlName).dirty) { patchOperations.push({ @@ -386,6 +479,11 @@ export class LdnServiceFormEditComponent implements OnInit { } } + /** + * Handles patterns in the form array, checking if an add or replace operations is required + * @param patchOperations - The array to store patch operations + * @param formArrayName - The name of the form array + */ private handlePatterns(patchOperations: any[], formArrayName: string): void { const patternsArray = this.formModel.get(formArrayName) as FormArray @@ -416,10 +514,17 @@ export class LdnServiceFormEditComponent implements OnInit { } } + /** + * Navigates back to the LDN services page + */ private sendBack() { this.router.navigateByUrl('admin/ldn/services'); } + /** + * Creates a form group for outbound patterns + * @returns The form group for outbound patterns + */ private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', @@ -429,6 +534,10 @@ export class LdnServiceFormEditComponent implements OnInit { }); } + /** + * Creates a form group for inbound patterns + * @returns The form group for inbound patterns + */ private createInboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', @@ -439,6 +548,10 @@ export class LdnServiceFormEditComponent implements OnInit { }); } + /** + * Initializes an existing form group for outbound patterns + * @returns The initialized form group for outbound patterns + */ private initializeOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', @@ -447,6 +560,10 @@ export class LdnServiceFormEditComponent implements OnInit { }); } + /** + * Initializes an existing form group for inbound patterns + * @returns The initialized form group for inbound patterns + */ private initializeInboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index 5d409964c26..005bf0cf0d1 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -44,8 +44,6 @@ export const mockLdnService: LdnService = { }, }; -//export const mockLdnServiceRD$: Observable>> = of((mockLdnService as unknown) as RemoteData>); -//export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(createPaginatedList(mockLdnService[0])as PaginatedList); export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(mockLdnService); @@ -126,62 +124,3 @@ export const mockLdnServices: LdnService[] = [{ } ] export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); - - -/*export const mockLdnServiceRD$: RemoteData> = { - errorMessage: null, - lastUpdated: 1700176600821, - msToLive: 900000, - payload: { - page: [mockLdnService], - pageInfo: { - elementsPerPage: 20, - totalPages: 1, - totalElements: 1, - currentPage: 1, - }, - type: {value: "paginated-list"}, - _links: { - self: { - href: "http://localhost:8080/server/api/ldn/ldnservices?size=20&sort=dc.title,ASC" - }, - page: [ - { - "href": "http://localhost/api/ldn/ldnservices/1" - } - ] - }, - }, - statusCode: 200, - state: 'Success', - timeCompleted: 1700176600821, -}*/ - - - -const mockLdnServices2 = { - payload: { - elementsPerPage: 20, - totalPages: 1, - totalElements: 1, - currentPage: 1, - first: undefined, - prev: undefined, - next: undefined, - last: undefined, - page: [mockLdnService], - type: LDN_SERVICE, - self: undefined, - getPageLength: function () { - return this.page.length; - }, - _links: { - self: { - href: 'http://localhost/api/ldn/ldnservices/1', - }, - page: [], - }, - }, - hasSucceeded: true, - msToLive: 0, -}; diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts index b8d28f08869..e7c2f471591 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -35,7 +35,15 @@ import {SearchDataImpl} from '../../../core/data/base/search-data'; import {RequestParam} from '../../../core/cache/models/request-param.model'; /** - * A service responsible for fetching/sending data from/to the REST API on the ldnservices endpoint + * Injectable service responsible for fetching/sending data from/to the REST API on the ldnservices endpoint. + * + * @export + * @class LdnServicesService + * @extends {IdentifiableDataService} + * @implements {FindAllData} + * @implements {DeleteData} + * @implements {PatchData} + * @implements {CreateData} */ @Injectable() @dataService(LDN_SERVICE) @@ -65,41 +73,103 @@ export class LdnServicesService extends IdentifiableDataService impl this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); } - + /** + * Creates an LDN service by sending a POST request to the REST API. + * + * @param {LdnService} object - The LDN service object to be created. + * @returns {Observable>} - Observable containing the result of the creation operation. + */ create(object: LdnService): Observable> { return this.createData.create(object); } + /** + * Updates an LDN service by applying a set of operations through a PATCH request to the REST API. + * + * @param {LdnService} object - The LDN service object to be updated. + * @param {Operation[]} operations - The patch operations to be applied. + * @returns {Observable>} - Observable containing the result of the update operation. + */ patch(object: LdnService, operations: Operation[]): Observable> { return this.patchData.patch(object, operations); } + /** + * Updates an LDN service by sending a PUT request to the REST API. + * + * @param {LdnService} object - The LDN service object to be updated. + * @returns {Observable>} - Observable containing the result of the update operation. + */ update(object: LdnService): Observable> { return this.patchData.update(object); } + /** + * Commits pending updates by sending a PATCH request to the REST API. + * + * @param {RestRequestMethod} [method] - The HTTP method to be used for the request. + */ commitUpdates(method?: RestRequestMethod): void { return this.patchData.commitUpdates(method); } + /** + * Creates a patch representing the changes made to the LDN service in the cache. + * + * @param {LdnService} object - The LDN service object for which to create the patch. + * @returns {Observable} - Observable containing the patch operations. + */ createPatchFromCache(object: LdnService): Observable { return this.patchData.createPatchFromCache(object); } + /** + * Retrieves all LDN services from the REST API based on the provided options. + * + * @param {FindListOptions} [options] - The options to be applied to the request. + * @param {boolean} [useCachedVersionIfAvailable] - Flag indicating whether to use cached data if available. + * @param {boolean} [reRequestOnStale] - Flag indicating whether to re-request data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Optional links to follow during the request. + * @returns {Observable>>} - Observable containing the result of the request. + */ findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + /** + * Retrieves LDN services based on the inbound pattern from the REST API. + * + * @param {string} pattern - The inbound pattern to be used in the search. + * @param {FindListOptions} [options] - The options to be applied to the request. + * @param {boolean} [useCachedVersionIfAvailable] - Flag indicating whether to use cached data if available. + * @param {boolean} [reRequestOnStale] - Flag indicating whether to re-request data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Optional links to follow during the request. + * @returns {Observable>>} - Observable containing the result of the request. + */ findByInboundPattern(pattern: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { const params = [new RequestParam('pattern', pattern)]; const findListOptions = Object.assign(new FindListOptions(), options, {searchParams: params}); return this.searchData.searchBy(this.findByPatternEndpoint, findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + /** + * Deletes an LDN service by sending a DELETE request to the REST API. + * + * @param {string} objectId - The ID of the LDN service to be deleted. + * @param {string[]} [copyVirtualMetadata] - Optional virtual metadata to be copied during the deletion. + * @returns {Observable>} - Observable containing the result of the deletion operation. + */ public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { return this.deleteData.delete(objectId, copyVirtualMetadata); } + /** + * Deletes an LDN service by its HATEOAS link. + * + * @param {string} href - The HATEOAS link of the LDN service to be deleted. + * @param {string[]} [copyVirtualMetadata] - Optional virtual metadata to be copied during the deletion. + * @returns {Observable>} - Observable containing the result of the deletion operation. + */ public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { return this.deleteData.deleteByHref(href, copyVirtualMetadata); } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 3d1341b4711..12d196023e1 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -22,7 +22,6 @@ import {Operation} from 'fast-json-patch'; import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {TranslateService} from '@ngx-translate/core'; -import { mockLdnServiceRD$ } from "../ldn-service-serviceMock/ldnServicesRD$-mock"; /** @@ -42,9 +41,6 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { servicesData: any[] = []; @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; ldnServicesRD$: Observable>>; - //TODO: remove mocks an put in test after finishing - //mockLdnServiceRD$: Observable>; - // mockLdnServicesRD$: Observable>>; config: FindListOptions = Object.assign(new FindListOptions(), { elementsPerPage: 20 }); @@ -79,20 +75,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( getFirstCompletedRemoteData() )) - - );/* - this.mockLdnServiceRD$ = mockLdnServiceRD$ - - this.mockLdnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( - getFirstCompletedRemoteData() - )) - - );this.paginationService.getFindListOptions(this.pageConfig.id, this.config) - this.ldnServicesRD$.subscribe((rd: RemoteData>) => {console.log('realremotedata:',rd);}) - this.mockLdnServiceRD$.subscribe((rd: RemoteData) => {console.log('mockremotedata:',rd);}) - this.mockLdnServicesRD$.subscribe((rd: RemoteData>) => {console.log('mockremotedata[ldnservice]:',rd);})*/ - + ); } ngOnDestroy(): void { diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts index 7fb8072a6f3..295426ba878 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts @@ -1,7 +1,7 @@ import {autoserialize} from 'cerialize'; /** - * notify service patterns + * A single notify service pattern and his properties */ export class NotifyServicePattern { @autoserialize From 532f4725b261ce4b60e3c3d24675f237ffe04dbd Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 13:29:44 +0100 Subject: [PATCH 201/592] CST-12498 Final refactor --- .../ldn-service-form-edit.component.ts | 7 +++++-- .../ldn-service-form.component.ts | 3 ++- .../ldnServicesRD$-mock.ts | 2 +- .../ldn-services-directory.component.spec.ts | 5 +++-- .../ldn-services-directory.component.ts | 15 +++++++-------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index a9659b4cce2..b4ec221d5b6 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -183,6 +183,7 @@ export class LdnServiceFormEditComponent implements OnInit { } + /** * Generates an array of patch operations based on form changes * @returns Array of patch operations @@ -253,6 +254,7 @@ export class LdnServiceFormEditComponent implements OnInit { patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) } + /** * Selects an outbound item filter by updating its value based on the provided filter value and index * @param filterValue - The selected filter value @@ -370,8 +372,8 @@ export class LdnServiceFormEditComponent implements OnInit { } /** - * Resets the form and navigates back to the LDN services page - */ + * Resets the form and navigates back to the LDN services page + */ resetFormAndLeave() { this.sendBack(); this.closeModal(); @@ -418,6 +420,7 @@ export class LdnServiceFormEditComponent implements OnInit { this.markedForDeletionOutboundPattern.splice(i, 1); } } + /** * Deletes marked inbound patterns from the form model */ diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 28aa6c4ef05..d903fec63e0 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -137,7 +137,7 @@ export class LdnServiceFormComponent implements OnInit { } /** - * Handles the creation of an LDN service by validating form fields, + * Handles the creation of an LDN service by retrieving and validating form fields, * and submitting the form data to the LDN services endpoint. */ createService() { @@ -334,6 +334,7 @@ export class LdnServiceFormComponent implements OnInit { private sendBack() { this.router.navigateByUrl('admin/ldn/services'); } + /** * Creates a form group for an outbound pattern in the notifyServiceOutboundPatterns form array. * diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index 005bf0cf0d1..bf40c34efe0 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -84,7 +84,7 @@ export const mockLdnServices: LdnService[] = [{ get self(): string { return ""; }, -},{ +}, { uuid: "2", enabled: false, score: 0, diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index c5ec66c7574..35bf3d598ce 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -15,7 +15,7 @@ import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; import {createSuccessfulRemoteDataObject$} from "../../../shared/remote-data.utils"; import {createPaginatedList} from "../../../shared/testing/utils.test"; -describe('LdnServicesOverviewComponent', ( ) => { +describe('LdnServicesOverviewComponent', () => { let component: LdnServicesOverviewComponent; let fixture: ComponentFixture; let ldnServicesService; @@ -45,7 +45,8 @@ describe('LdnServicesOverviewComponent', ( ) => { {provide: PaginationService, useValue: paginationService}, { provide: NgbModal, useValue: { - open: () => { /*comment*/} + open: () => { /*comment*/ + } } }, {provide: ChangeDetectorRef, useValue: {}}, diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index 12d196023e1..826b4b4154d 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -27,7 +27,7 @@ import {TranslateService} from '@ngx-translate/core'; /** * The `LdnServicesOverviewComponent` is a component that provides an overview of LDN (Linked Data Notifications) services. * It displays a paginated list of LDN services, allows users to edit and delete services, - * toggle the status of each service directly form the page and allows for creation of new services redirecting the user on the creation form + * toggle the status of each service directly form the page and allows for creation of new services redirecting the user on the creation/edit form */ @Component({ selector: 'ds-ldn-services-directory', @@ -52,14 +52,13 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { modalRef: any; - constructor( - protected ldnServicesService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - public cdRef: ChangeDetectorRef, - private notificationService: NotificationsService, - private translateService: TranslateService, + protected ldnServicesService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public cdRef: ChangeDetectorRef, + private notificationService: NotificationsService, + private translateService: TranslateService, ) { } From 21d9785ca73e794dfe7d8a0217b9fd94449e0065 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Mon, 20 Nov 2023 13:52:13 +0100 Subject: [PATCH 202/592] [CST-12700] fixes --- .../ldn-service-form-edit.component.html | 49 +++++++++---------- .../ldn-service-form-edit.component.scss | 5 -- .../ldn-service-form-edit.component.ts | 41 ++++++++-------- .../ldn-service-form.component.html | 44 +++++++---------- .../ldn-service-form.component.scss | 6 --- .../ldn-service-form.component.ts | 25 +++++----- src/app/shared/mocks/suggestion.mock.ts | 1 - .../suggestions-page-routing.module.ts | 1 - src/assets/i18n/en.json5 | 13 +++-- 9 files changed, 79 insertions(+), 106 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 794923b42f8..1438cb6ce48 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -5,7 +5,7 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- +
@@ -15,7 +15,7 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- + {{ 'ldn-edit-registered-service.title' | translate }}
- +
- + {{ 'ldn-edit-registered-service.title' | translate }}
- + {{ 'ldn-edit-registered-service.title' | translate }}
- +
{{ 'ldn-new-service.form.error.score' | translate }} @@ -78,14 +79,14 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- +
- +
- +
@@ -213,11 +214,11 @@

{{ 'ldn-edit-registered-service.title' | translate }}
- +
- +
@@ -336,28 +337,23 @@

{{ 'ldn-edit-registered-service.title' | translate }}

- {{ 'ldn-new-service.form.label.addPattern' | translate }} - + class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }} +
- - -
- -
@@ -407,7 +402,7 @@

{{'service.overview.reset-form.modal' | translate }}

id="reset-delete">{{ 'service.overview.reset-form.reset-confirm' | translate }}

diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index c43c3807dd9..91666cde50c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -124,11 +124,6 @@ textarea { margin-left: 5px; } -form button.btn.btn-primary[type="submit"] { - position: absolute; - right: 8px; -} - .submission-form-footer { border-radius: var(--bs-card-border-radius); bottom: 0; diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 002aaf68122..0a5a4d7080b 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -19,7 +19,7 @@ import {Observable} from 'rxjs'; import {PaginationService} from '../../../core/pagination/pagination.service'; import {FindListOptions} from '../../../core/data/find-list-options.model'; import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; -import {NotifyServicePattern} from "../ldn-services-model/ldn-service-patterns.model"; +import {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model'; @Component({ selector: 'ds-ldn-service-form-edit', @@ -69,6 +69,7 @@ export class LdnServiceFormEditComponent implements OnInit { private deletedOutboundPatterns: number[] = []; private modalRef: any; private service: LdnService; + private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select'; constructor( protected ldnServicesService: LdnServicesService, @@ -132,8 +133,8 @@ export class LdnServiceFormEditComponent implements OnInit { type: this.service.type, enabled: this.service.enabled }); - this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false) - this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true) + this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false); + this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true); } }, ); @@ -144,9 +145,9 @@ export class LdnServiceFormEditComponent implements OnInit { PatternsArray.clear(); let servicesToUse; if (isOutbound) { - servicesToUse = this.service.notifyServiceOutboundPatterns + servicesToUse = this.service.notifyServiceOutboundPatterns; } else { - servicesToUse = this.service.notifyServiceInboundPatterns + servicesToUse = this.service.notifyServiceInboundPatterns; } servicesToUse.forEach((patternObj: NotifyServicePattern) => { @@ -159,12 +160,12 @@ export class LdnServiceFormEditComponent implements OnInit { const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), { ...patternObj, patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label') - }) + }); patternFormGroup.patchValue(newPatternObjWithLabel); PatternsArray.push(patternFormGroup); this.cdRef.detectChanges(); - }) + }); } @@ -217,26 +218,26 @@ export class LdnServiceFormEditComponent implements OnInit { selectOutboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } selectOutboundItemFilter(filterValue: string, index: number) { - const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } selectInboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } selectInboundItemFilter(filterValue: string, index: number): void { - const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } toggleAutomatic(i: number) { @@ -387,7 +388,7 @@ export class LdnServiceFormEditComponent implements OnInit { } private handlePatterns(patchOperations: any[], formArrayName: string): void { - const patternsArray = this.formModel.get(formArrayName) as FormArray + const patternsArray = this.formModel.get(formArrayName) as FormArray; for (let i = 0; i < patternsArray.length; i++) { @@ -423,7 +424,7 @@ export class LdnServiceFormEditComponent implements OnInit { private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', - patternLabel: 'Select a pattern', + patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), constraint: '', isNew: true, }); @@ -432,7 +433,7 @@ export class LdnServiceFormEditComponent implements OnInit { private createInboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', - patternLabel: 'Select a pattern', + patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), constraint: '', automatic: false, isNew: true diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index bc71eda994f..f5be7c1051d 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,10 +1,10 @@
-
+

{{ 'ldn-create-service.title' | translate }}

-
+
{{ 'ldn-create-service.title' | translate }}

[placeholder]="'ldn-new-service.form.placeholder.score' | translate" formControlName="score" id="score" name="score" + class="form-control" type="text">
{{ 'ldn-new-service.form.error.score' | translate }} @@ -79,7 +80,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
@@ -202,12 +203,7 @@

{{ 'ldn-create-service.title' | translate }}

-
- -
-
+
@@ -311,25 +307,19 @@

{{ 'ldn-create-service.title' | translate }}

- {{ 'ldn-new-service.form.label.addPattern' | translate }} - -
-  
- @@ -348,14 +338,14 @@

{{'service.overview.create.modal' | translate }}

@@ -368,7 +358,7 @@

{{'service.overview.create.modal' | translate }}

-
+
@@ -202,7 +202,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
@@ -301,7 +301,7 @@

{{ 'ldn-create-service.title' | translate }}

-
+
From b1d2b78b40d30991a47b0514f61e26ae0c25126c Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Mon, 20 Nov 2023 15:17:14 +0100 Subject: [PATCH 204/592] [CST-12700] added missing label --- src/assets/i18n/en.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 023f55e3ff7..3cf74b2b244 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -999,6 +999,7 @@ "ldn-new-service.form.error.patterns": "At least a pattern is required", "ldn-new-service.form.error.score": "Please enter a valid score (between 0 and 1). Use the “.” as decimal separator", + "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", "ldn-new-service.form.label.outboundPattern": "Outbound Patterns", "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", From 4a9bfb03463037ff750398514611c70a7fad6763 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 15:39:17 +0100 Subject: [PATCH 205/592] CST-12498 rollback --- .../ldn-service-form-edit.component.spec.ts | 1 + .../ldn-service-form/ldn-service-form.component.spec.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts index a2fa801e6d7..2fa27ac743c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts @@ -28,6 +28,7 @@ describe('LdnServiceFormEditComponent', () => { const translateServiceStub = { get: () => of('translated-text'), + instant: () => 'translated-text', onLangChange: new EventEmitter(), onTranslationChange: new EventEmitter(), onDefaultLangChange: new EventEmitter() diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts index 70a4b76ed3a..5db8e66c332 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -25,12 +25,14 @@ describe('LdnServiceFormComponent', () => { let notificationsService: any; const itemFiltersRdPL$ = createSuccessfulRemoteDataObject$(createPaginatedList([new Itemfilter()])); + const translateServiceStub = { get: () => of('translated-text'), + instant: () => 'translated-text', onLangChange: new EventEmitter(), onTranslationChange: new EventEmitter(), onDefaultLangChange: new EventEmitter() - }; +}; beforeEach(async () => { ldnItemfiltersService = jasmine.createSpyObj('ldnItemfiltersService', { From 53599491e12bb1063600234cca28f3511eb19ca8 Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Mon, 20 Nov 2023 15:43:29 +0100 Subject: [PATCH 206/592] CST-12498 lint fix --- .../ldn-service-form-edit.component.ts | 36 +++++++++---------- .../ldn-service-form.component.ts | 20 +++++------ .../ldnServicesRD$-mock.ts | 18 +++++----- .../ldn-services-directory.component.spec.ts | 14 ++++---- src/app/core/data/data.service.ts | 1 - src/app/shared/mocks/suggestion.mock.ts | 1 - .../suggestions-page-routing.module.ts | 1 - src/assets/i18n/en.json5 | 8 ++--- 8 files changed, 48 insertions(+), 51 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index b4ec221d5b6..408d0b6ecd1 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -19,7 +19,7 @@ import {Observable} from 'rxjs'; import {PaginationService} from '../../../core/pagination/pagination.service'; import {FindListOptions} from '../../../core/data/find-list-options.model'; import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; -import {NotifyServicePattern} from "../ldn-services-model/ldn-service-patterns.model"; +import {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model'; /** @@ -142,8 +142,8 @@ export class LdnServiceFormEditComponent implements OnInit { type: this.service.type, enabled: this.service.enabled }); - this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false) - this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true) + this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false); + this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true); } }, ); @@ -159,9 +159,9 @@ export class LdnServiceFormEditComponent implements OnInit { PatternsArray.clear(); let servicesToUse; if (isOutbound) { - servicesToUse = this.service.notifyServiceOutboundPatterns + servicesToUse = this.service.notifyServiceOutboundPatterns; } else { - servicesToUse = this.service.notifyServiceInboundPatterns + servicesToUse = this.service.notifyServiceInboundPatterns; } servicesToUse.forEach((patternObj: NotifyServicePattern) => { @@ -174,12 +174,12 @@ export class LdnServiceFormEditComponent implements OnInit { const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), { ...patternObj, patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label') - }) + }); patternFormGroup.patchValue(newPatternObjWithLabel); PatternsArray.push(patternFormGroup); this.cdRef.detectChanges(); - }) + }); } @@ -249,9 +249,9 @@ export class LdnServiceFormEditComponent implements OnInit { * @param index - The index of the outbound pattern in the array */ selectOutboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } @@ -261,8 +261,8 @@ export class LdnServiceFormEditComponent implements OnInit { * @param index - The index of the inbound pattern in the array */ selectOutboundItemFilter(filterValue: string, index: number) { - const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } /** @@ -271,9 +271,9 @@ export class LdnServiceFormEditComponent implements OnInit { * @param index - The index of the inbound pattern in the array */ selectInboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } /** @@ -282,8 +282,8 @@ export class LdnServiceFormEditComponent implements OnInit { * @param index - The index of the inbound pattern in the array */ selectInboundItemFilter(filterValue: string, index: number): void { - const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } /** @@ -488,7 +488,7 @@ export class LdnServiceFormEditComponent implements OnInit { * @param formArrayName - The name of the form array */ private handlePatterns(patchOperations: any[], formArrayName: string): void { - const patternsArray = this.formModel.get(formArrayName) as FormArray + const patternsArray = this.formModel.get(formArrayName) as FormArray; for (let i = 0; i < patternsArray.length; i++) { diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index d903fec63e0..be2d117650c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -287,9 +287,9 @@ export class LdnServiceFormComponent implements OnInit { * @param {number} index - The index of the outbound pattern in the form array. */ selectOutboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } @@ -300,9 +300,9 @@ export class LdnServiceFormComponent implements OnInit { * @param {number} index - The index of the inbound pattern in the form array. */ selectInboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - patternArray.controls[index].patchValue({pattern: patternValue}) - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}) + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); } @@ -313,8 +313,8 @@ export class LdnServiceFormComponent implements OnInit { * @param {number} index - The index of the inbound item filter in the form array. */ selectInboundItemFilter(filterValue: string, index: number): void { - const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } /** @@ -324,8 +324,8 @@ export class LdnServiceFormComponent implements OnInit { * @param {number} index - The index of the outbound item filter in the form array. */ selectOutboundItemFilter(filterValue: string, index: number) { - const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray) - filterArray.controls[index].patchValue({constraint: filterValue}) + const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); } /** diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts index bf40c34efe0..02090b16024 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -2,11 +2,11 @@ import {LdnService} from '../ldn-services-model/ldn-services.model'; import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; import {RemoteData} from '../../../core/data/remote-data'; import {PaginatedList} from '../../../core/data/paginated-list.model'; -import {Observable, of} from "rxjs"; -import {createSuccessfulRemoteDataObject$} from "../../../shared/remote-data.utils"; +import {Observable, of} from 'rxjs'; +import {createSuccessfulRemoteDataObject$} from '../../../shared/remote-data.utils'; export const mockLdnService: LdnService = { - uuid: "1", + uuid: '1', enabled: false, score: 0, id: 1, @@ -40,7 +40,7 @@ export const mockLdnService: LdnService = { }, }, get self(): string { - return ""; + return ''; }, }; @@ -48,7 +48,7 @@ export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(mockLdnServic export const mockLdnServices: LdnService[] = [{ - uuid: "1", + uuid: '1', enabled: false, score: 0, id: 1, @@ -82,10 +82,10 @@ export const mockLdnServices: LdnService[] = [{ }, }, get self(): string { - return ""; + return ''; }, }, { - uuid: "2", + uuid: '2', enabled: false, score: 0, id: 2, @@ -119,8 +119,8 @@ export const mockLdnServices: LdnService[] = [{ }, }, get self(): string { - return ""; + return ''; }, } -] +]; export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts index 35bf3d598ce..664edcb27dc 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -8,12 +8,12 @@ import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service import {PaginationService} from '../../../core/pagination/pagination.service'; import {PaginationServiceStub} from '../../../shared/testing/pagination-service.stub'; import {of} from 'rxjs'; -import {LdnService} from "../ldn-services-model/ldn-services.model"; -import {PaginatedList} from "../../../core/data/paginated-list.model"; -import {RemoteData} from "../../../core/data/remote-data"; +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {RemoteData} from '../../../core/data/remote-data'; import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; -import {createSuccessfulRemoteDataObject$} from "../../../shared/remote-data.utils"; -import {createPaginatedList} from "../../../shared/testing/utils.test"; +import {createSuccessfulRemoteDataObject$} from '../../../shared/remote-data.utils'; +import {createPaginatedList} from '../../../shared/testing/utils.test'; describe('LdnServicesOverviewComponent', () => { let component: LdnServicesOverviewComponent; @@ -33,7 +33,7 @@ describe('LdnServicesOverviewComponent', () => { beforeEach(async () => { paginationService = new PaginationServiceStub(); - ldnServicesService = jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']) + ldnServicesService = jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']); await TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], declarations: [LdnServicesOverviewComponent], @@ -89,7 +89,7 @@ describe('LdnServicesOverviewComponent', () => { {id: 2, name: 'Service 2', description: 'Description 2', enabled: false}, {id: 3, name: 'Service 3', description: 'Description 3', enabled: true}]); - const mockLdnServicesRD = createPaginatedList(testData) + const mockLdnServicesRD = createPaginatedList(testData); component.ldnServicesRD$ = createSuccessfulRemoteDataObject$(mockLdnServicesRD); fixture.detectChanges(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 1433ebacce2..43b60f874d0 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -25,7 +25,6 @@ import { RequestParam } from '../cache/models/request-param.model'; import { ObjectCacheEntry } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; -import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteData, getRemoteDataPayload } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; diff --git a/src/app/shared/mocks/suggestion.mock.ts b/src/app/shared/mocks/suggestion.mock.ts index fd1a7c41f1e..8b1ab7acd55 100644 --- a/src/app/shared/mocks/suggestion.mock.ts +++ b/src/app/shared/mocks/suggestion.mock.ts @@ -1,7 +1,6 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Item } from '../../core/shared/item.model'; import { SearchResult } from '../search/models/search-result.model'; -import { SuggestionsService } from '../../suggestion-notifications/reciter-suggestions/suggestions.service'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- diff --git a/src/app/suggestions-page/suggestions-page-routing.module.ts b/src/app/suggestions-page/suggestions-page-routing.module.ts index 20ed658707e..05dc6321b70 100644 --- a/src/app/suggestions-page/suggestions-page-routing.module.ts +++ b/src/app/suggestions-page/suggestions-page-routing.module.ts @@ -5,7 +5,6 @@ import { SuggestionsPageResolver } from './suggestions-page.resolver'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; -import { SiteAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; @NgModule({ imports: [ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index e01964a4fb8..10e490d915e 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -892,7 +892,7 @@ "coar-notify-support.title": "COAR Notify Protocol", - "coar-notify-support-title.content":"Here, we fully support the COAR Notify protocol, which is designed to enhance the communication between repositories. To learn more about the COAR Notify protocol, you can visit their official website here.", + "coar-notify-support-title.content": "Here, we fully support the COAR Notify protocol, which is designed to enhance the communication between repositories. To learn more about the COAR Notify protocol, you can visit their official website here.", "coar-notify-support.ldn-inbox.title": "LDN InBox", @@ -905,7 +905,7 @@ "service.overview.delete.header": "Delete Service", "ldn-registered-services.title": "Registered Services", - "ldn-registered-services.table.name":"Name", + "ldn-registered-services.table.name": "Name", "ldn-registered-services.table.description": "Description", "ldn-registered-services.table.status": "Status", "ldn-registered-services.table.action": "Action", @@ -1012,7 +1012,7 @@ "service.detail.return": "Cancel", "service.overview.reset-form.body": "Are you sure you want to discard those changes and leave?", "service.overview.reset-form.modal": "Discard Service Changes", - "service.overview.reset-form.reset-confirm":"Discard", + "service.overview.reset-form.reset-confirm": "Discard", "admin.registries.services-formats.modify.success.head": "Successful Edit", "admin.registries.services-formats.modify.success.content": "The service has been edited", "admin.registries.services-formats.modify.failure.head": "Failed Edit", @@ -2043,7 +2043,7 @@ "info.feedback.breadcrumbs": "Feedback", - "info.coar-notify-support.title":"Notify Support", + "info.coar-notify-support.title": "Notify Support", "info.coar-notify.breadcrumbs": "Notify Support", From d46248e99be7383fe3308d37d1d77be56b81f427 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Mon, 20 Nov 2023 16:48:14 +0100 Subject: [PATCH 207/592] [CST-11884] added notify related information in the item details page --- .../metadata-uri-values.component.html | 2 +- .../metadata-values.component.ts | 10 ++++++++ .../publication/publication.component.html | 24 +++++++++---------- .../untyped-item/untyped-item.component.html | 12 ++++++++++ src/assets/i18n/en.json5 | 6 +++++ 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html index 9091beb6c7d..4cef0a15920 100644 --- a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html +++ b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html @@ -1,5 +1,5 @@ - + {{ linktext || mdValue.value }} diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index cbbae9006da..fcf98b094df 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -4,6 +4,7 @@ import { APP_CONFIG, AppConfig } from '../../../../config/app-config.interface'; import { BrowseDefinition } from '../../../core/shared/browse-definition.model'; import { hasValue } from '../../../shared/empty.util'; import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type'; +import { environment } from './../../../../environments/environment'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -90,4 +91,13 @@ export class MetadataValuesComponent implements OnChanges { } return queryParams; } + + /** + * Checks if the given link value is an internal link. + * @param linkValue - The link value to check. + * @returns True if the link value starts with the base URL defined in the environment configuration, false otherwise. + */ + hasInternalLink(linkValue: string): boolean { + return linkValue.startsWith(environment.ui.baseUrl); + } } diff --git a/src/app/item-page/simple/item-types/publication/publication.component.html b/src/app/item-page/simple/item-types/publication/publication.component.html index 3014fcb3020..40932ff2f9f 100644 --- a/src/app/item-page/simple/item-types/publication/publication.component.html +++ b/src/app/item-page/simple/item-types/publication/publication.component.html @@ -84,18 +84,18 @@ [label]="'item.page.uri'"> - - - - - - + + + + + +
{{"item.page.link.full" | translate}} diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html index 904b7e039cc..9e07287b49b 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -70,6 +70,18 @@ [label]="'item.page.uri'"> + + + + + +
{{"item.page.link.full" | translate}} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index e01964a4fb8..c7bbc7e5f0a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2625,6 +2625,12 @@ "item.page.uri": "URI", + "item.page.endorsment": "Endorsment", + + "item.page.review": "Review", + + "item.page.dataset": "Dataset", + "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.collapse": "Collapse", From 442426bb2e75002db5975f30cb03eb496f8c5d0d Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Tue, 21 Nov 2023 18:38:49 +0100 Subject: [PATCH 208/592] [CST-12709] partial implementation with mock data --- src/app/core/core.module.ts | 10 +- .../notify-services-status-data.service.ts | 49 ++++++++ src/app/item-page/item-page.module.ts | 6 +- .../item-page/simple/item-page.component.html | 1 + .../notify-requests-status.component.html | 5 + .../notify-requests-status.component.scss | 0 .../notify-requests-status.component.ts | 108 ++++++++++++++++++ .../notify-requests-status.model.ts | 68 +++++++++++ .../notify-requests-status.resource-type.ts | 8 ++ .../notify-status.enum.ts | 5 + .../request-status-alert-box.component.html | 32 ++++++ .../request-status-alert-box.component.scss | 7 ++ ...request-status-alert-box.component.spec.ts | 51 +++++++++ .../request-status-alert-box.component.ts | 82 +++++++++++++ src/assets/i18n/en.json5 | 6 + 15 files changed, 434 insertions(+), 4 deletions(-) create mode 100644 src/app/core/data/notify-services-status-data.service.ts create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.scss create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts create mode 100644 src/app/item-page/simple/notify-requests-status/notify-status.enum.ts create mode 100644 src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html create mode 100644 src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss create mode 100644 src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts create mode 100644 src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index d0f2dbbbaf8..eef4f1f68e2 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -195,6 +195,9 @@ import { CoarNotifyConfigDataService } from '../submission/sections/section-coar-notify/coar-notify-config-data.service'; import { SubmissionCoarNotifyConfig } from '../submission/sections/section-coar-notify/submission-coar-notify.config'; +import { NotifyRequestsStatus } from '../item-page/simple/notify-requests-status/notify-requests-status.model'; +import { NotifyRequestsStatusDataService } from './data/notify-services-status-data.service'; + /** * When not in production, endpoint responses can be mocked for testing purposes @@ -320,7 +323,8 @@ const PROVIDERS = [ SupervisionOrderDataService, LdnServicesService, LdnItemfiltersService, - CoarNotifyConfigDataService + CoarNotifyConfigDataService, + NotifyRequestsStatusDataService ]; /** @@ -404,8 +408,8 @@ export const models = SuggestionSource, LdnService, Itemfilter, - SubmissionCoarNotifyConfig - + SubmissionCoarNotifyConfig, + NotifyRequestsStatus, ]; @NgModule({ diff --git a/src/app/core/data/notify-services-status-data.service.ts b/src/app/core/data/notify-services-status-data.service.ts new file mode 100644 index 00000000000..67bfe18c802 --- /dev/null +++ b/src/app/core/data/notify-services-status-data.service.ts @@ -0,0 +1,49 @@ +import { Injectable } from '@angular/core'; +import { RequestService } from './request.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { IdentifiableDataService } from './base/identifiable-data.service'; +import { dataService } from './base/data-service.decorator'; +import { NotifyRequestsStatus } from '../../item-page/simple/notify-requests-status/notify-requests-status.model'; +import { NOTIFYREQUEST} from '../../item-page/simple/notify-requests-status/notify-requests-status.resource-type'; +import { Observable, map, take, tap } from 'rxjs'; +import { RemoteData } from './remote-data'; +import { GetRequest } from './request.models'; + + +@Injectable() +@dataService(NOTIFYREQUEST) +export class NotifyRequestsStatusDataService extends IdentifiableDataService { + + private notifyRequestLink = 'notifyrequests'; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected rdb: RemoteDataBuildService, + ) { + super('ldn', requestService, rdbService, objectCache, halService); + } + + /** + * Retrieves the status of notify requests for a specific item. + * @param itemUuid The UUID of the item. + * @returns An Observable that emits the remote data containing the notify requests status. + */ + getNotifyRequestsStatus(itemUuid: string): Observable> { + const href$ = this.halService.getEndpoint(this.notifyRequestLink).pipe( + tap((url: string) => console.log('url', url) ), + map((url: string) => url + '/' + itemUuid), + ); + + href$.pipe(take(1)).subscribe((url: string) => { + const request = new GetRequest(this.requestService.generateRequestId(), url); + this.requestService.send(request, true); + }); + + return this.rdb.buildFromHref(href$); + } +} diff --git a/src/app/item-page/item-page.module.ts b/src/app/item-page/item-page.module.ts index 5aa1b6e508f..7fd7b3b6236 100644 --- a/src/app/item-page/item-page.module.ts +++ b/src/app/item-page/item-page.module.ts @@ -61,6 +61,8 @@ import { ThemedFullFileSectionComponent } from './full/field-components/file-section/themed-full-file-section.component'; import { QaEventNotificationComponent } from './simple/qa-event-notification/qa-event-notification.component'; +import { NotifyRequestsStatusComponent } from './simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component'; +import { RequestStatusAlertBoxComponent } from './simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -104,7 +106,9 @@ const DECLARATIONS = [ ItemAlertsComponent, ThemedItemAlertsComponent, BitstreamRequestACopyPageComponent, - QaEventNotificationComponent + QaEventNotificationComponent, + NotifyRequestsStatusComponent, + RequestStatusAlertBoxComponent ]; @NgModule({ diff --git a/src/app/item-page/simple/item-page.component.html b/src/app/item-page/simple/item-page.component.html index 37a5e0c4cbf..dc8ed87a86a 100644 --- a/src/app/item-page/simple/item-page.component.html +++ b/src/app/item-page/simple/item-page.component.html @@ -3,6 +3,7 @@
+ diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html new file mode 100644 index 00000000000..7736e888967 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html @@ -0,0 +1,5 @@ + + + + + diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.scss b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts new file mode 100644 index 00000000000..bd6e1983ed9 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts @@ -0,0 +1,108 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { Observable, of } from 'rxjs'; +import { NotifyRequestsStatus, NotifyStatuses } from '../notify-requests-status.model'; +import { NotifyRequestsStatusDataService } from 'src/app/core/data/notify-services-status-data.service'; +import { RequestStatusEnum } from '../notify-status.enum'; + +@Component({ + selector: 'ds-notify-requests-status', + templateUrl: './notify-requests-status.component.html', + styleUrls: ['./notify-requests-status.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class NotifyRequestsStatusComponent { + + /** + * The UUID of the item. + */ + @Input() itemUuid: string; + + /** + * Map that stores the status of requests and their corresponding notify statuses. + * The keys of the map are instances of the RequestStatusEnum enum, + * and the values are arrays of NotifyStatuses objects. + */ + statusMap: Map = new Map(); + + notifyRequestStatus$: Observable = of( Object.assign(new NotifyRequestsStatus(), { + notifyStatuses: [ + { + serviceName: 'test', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'test1', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'Review Platform', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'Demo Environment', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'Additional Information', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'Notification Service', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'test2', + serviceUrl: 'test', + status: RequestStatusEnum.REJECTED, + }, + { + serviceName: 'test3', + serviceUrl: 'test', + status: RequestStatusEnum.REQUESTED, + }, + { + serviceName: 'test4', + serviceUrl: 'test', + status: RequestStatusEnum.REQUESTED, + } + ], + itemUuid: '8d5fda2d-f380-467e-a86b-0436ac699dab', + })); + + constructor( + private notifyInfoService: NotifyRequestsStatusDataService, + ) { } + + ngOnInit(): void { + this.notifyInfoService.getNotifyRequestsStatus(this.itemUuid).subscribe((data) => { + console.log(data, 'asdasdsa'); + }); + + this.notifyRequestStatus$.subscribe((data) => { + this.groupDataByStatus(data); + console.log(this.statusMap); + }); + } + + /** + * Groups the notify requests status data by status. + * @param notifyRequestsStatus The notify requests status data. + */ + private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus): void { + notifyRequestsStatus.notifyStatuses.forEach((notifyStatus: NotifyStatuses) => { + const status = notifyStatus.status; + + if (!this.statusMap.has(status)) { + this.statusMap.set(status, []); + } + + this.statusMap.get(status)?.push(notifyStatus); + }); + } +} diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts new file mode 100644 index 00000000000..ab4e41b2c6b --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts @@ -0,0 +1,68 @@ +// eslint-disable-next-line max-classes-per-file +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { ResourceType } from '../../../core/shared/resource-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { NOTIFYREQUEST } from './notify-requests-status.resource-type'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { RequestStatusEnum } from './notify-status.enum'; + +/** + * Represents the status of notify requests for an item. + */ +@typedObject +@inheritSerialization(CacheableObject) +export class NotifyRequestsStatus implements CacheableObject { + static type = NOTIFYREQUEST; + + /** + * The object type. + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + /** + * The notify statuses. + */ + @autoserialize + notifyStatuses: NotifyStatuses[]; + + /** + * The UUID of the item. + */ + @autoserialize + itemUuid: string; + + /** + * The links associated with the notify requests status. + */ + @deserialize + _links: { + self: HALLink; + [k: string]: HALLink | HALLink[]; + }; +} + +/** + * Represents the status of a notification request. + */ +export class NotifyStatuses { + /** + * The name of the service. + */ + serviceName: string; + + /** + * The URL of the service. + */ + serviceUrl: string; + + /** + * The status of the notification request. + */ + status: RequestStatusEnum; +} + + diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts new file mode 100644 index 00000000000..da7ab2c881a --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts @@ -0,0 +1,8 @@ +import {ResourceType} from '../../../core/shared/resource-type'; +/** + * The resource type for the root endpoint + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const NOTIFYREQUEST = new ResourceType('notifyrequest'); diff --git a/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts b/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts new file mode 100644 index 00000000000..e44c6141302 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts @@ -0,0 +1,5 @@ +export enum RequestStatusEnum { + ACCEPTED = 'ACCEPTED', + REJECTED = 'REJECTED', + REQUESTED = 'REQUESTED', +} diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html new file mode 100644 index 00000000000..5ffc715109d --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html @@ -0,0 +1,32 @@ + +
+ + + +
+ +
+
+
+
+
+
+
diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss new file mode 100644 index 00000000000..f852bb8454c --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss @@ -0,0 +1,7 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts new file mode 100644 index 00000000000..f32c9f3bc2e --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts @@ -0,0 +1,51 @@ +import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing'; +import { RequestStatusAlertBoxComponent } from './request-status-alert-box.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { RequestStatusEnum } from '../notify-status.enum'; + +describe('RequestStatusAlertBoxComponent', () => { + let component: RequestStatusAlertBoxComponent; + let componentAsAny: any; + let fixture: ComponentFixture; + + const mockData = [ + { + serviceName: 'test', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'test1', + serviceUrl: 'test', + status: RequestStatusEnum.REJECTED, + }, + ]; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [RequestStatusAlertBoxComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RequestStatusAlertBoxComponent); + component = fixture.componentInstance; + component.data = mockData; + component.displayOptions = { + alertType: 'alert-danger', + text: 'request-status-alert-box.rejected', + }; + componentAsAny = component; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should display the alert box when data is available', fakeAsync(() => { + const alertBoxElement = fixture.nativeElement.querySelector('.alert'); + expect(alertBoxElement).toBeTruthy(); + })); +}); diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts new file mode 100644 index 00000000000..355980836a7 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts @@ -0,0 +1,82 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + type OnInit, +} from '@angular/core'; +import { NotifyStatuses } from '../notify-requests-status.model'; +import { RequestStatusEnum } from '../notify-status.enum'; + +@Component({ + selector: 'ds-request-status-alert-box', + templateUrl: './request-status-alert-box.component.html', + styleUrls: ['./request-status-alert-box.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +/** + * Represents a component that displays the status of a request. + */ +export class RequestStatusAlertBoxComponent implements OnInit { + /** + * The status of the request. + */ + @Input() status: RequestStatusEnum; + + /** + * The input data for the request status alert box component. + * @type {NotifyStatuses[]} + */ + @Input() data: NotifyStatuses[] = []; + + /** + * The display options for the request status alert box. + */ + displayOptions: NotifyRequestDisplayOptions; + + ngOnInit(): void { + this.prepareDataToDisplay(); + } + + /** + * Prepares the data to be displayed based on the current status. + */ + private prepareDataToDisplay() { + switch (this.status) { + case RequestStatusEnum.ACCEPTED: + this.displayOptions = { + alertType: 'alert-info', + text: 'request-status-alert-box.accepted', + }; + break; + + case RequestStatusEnum.REJECTED: + this.displayOptions = { + alertType: 'alert-danger', + text: 'request-status-alert-box.rejected', + }; + break; + + case RequestStatusEnum.REQUESTED: + this.displayOptions = { + alertType: 'alert-warning', + text: 'request-status-alert-box.requested', + }; + break; + } + } +} + +/** + * Represents the display options for a notification request. + */ +export interface NotifyRequestDisplayOptions { + /** + * The type of alert to display. + * Possible values are 'alert-danger', 'alert-warning', or 'alert-info'. + */ + alertType: 'alert-danger' | 'alert-warning' | 'alert-info'; + /** + * The text to display in the notification. + */ + text: string; +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3cf74b2b244..e754d257228 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5697,4 +5697,10 @@ "access-control-option-end-date-note": "Select the date until which the related access condition is applied", + "request-status-alert-box.accepted": "The request for
{{ serviceName }} has been taken in charge.", + + "request-status-alert-box.rejected": "The request for {{ serviceName }} has been rejected.", + + "request-status-alert-box.requested": "The request for {{ serviceName }} is pending.", + } From df0f1920dcf01587671921461bf1fa4570500175 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 22 Nov 2023 15:20:59 +0100 Subject: [PATCH 209/592] [CST-12709] unit tests and final fixes --- .../notify-services-status-data.service.ts | 9 +- .../notify-requests-status.component.spec.ts | 84 +++++++++++ .../notify-requests-status.component.ts | 134 ++++++++---------- .../notify-requests-status.model.ts | 4 +- .../notify-requests-status.resource-type.ts | 2 +- .../qa-event-notification.component.ts | 5 +- 6 files changed, 153 insertions(+), 85 deletions(-) create mode 100644 src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts diff --git a/src/app/core/data/notify-services-status-data.service.ts b/src/app/core/data/notify-services-status-data.service.ts index 67bfe18c802..6809ebf8426 100644 --- a/src/app/core/data/notify-services-status-data.service.ts +++ b/src/app/core/data/notify-services-status-data.service.ts @@ -16,8 +16,6 @@ import { GetRequest } from './request.models'; @dataService(NOTIFYREQUEST) export class NotifyRequestsStatusDataService extends IdentifiableDataService { - private notifyRequestLink = 'notifyrequests'; - constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, @@ -25,7 +23,7 @@ export class NotifyRequestsStatusDataService extends IdentifiableDataService> { - const href$ = this.halService.getEndpoint(this.notifyRequestLink).pipe( - tap((url: string) => console.log('url', url) ), - map((url: string) => url + '/' + itemUuid), + const href$ = this.getEndpoint().pipe( + map((url: string) => url + '/' + itemUuid ), ); href$.pipe(take(1)).subscribe((url: string) => { diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts new file mode 100644 index 00000000000..1498265ca4e --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts @@ -0,0 +1,84 @@ +import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; +import { NotifyRequestsStatusComponent } from './notify-requests-status.component'; +import { NotifyRequestsStatusDataService } from 'src/app/core/data/notify-services-status-data.service'; +import { NotifyRequestsStatus } from '../notify-requests-status.model'; +import { RequestStatusEnum } from '../notify-status.enum'; +import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; +import { TranslateModule } from '@ngx-translate/core'; + +describe('NotifyRequestsStatusComponent', () => { + let component: NotifyRequestsStatusComponent; + let fixture: ComponentFixture; + let notifyInfoServiceSpy; + + const mock: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [], + itemuuid: 'testUuid' + }); + + beforeEach(() => { + notifyInfoServiceSpy = { + getNotifyRequestsStatus:() => createSuccessfulRemoteDataObject$(mock) + }; + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [NotifyRequestsStatusComponent], + providers: [ + { provide: NotifyRequestsStatusDataService, useValue: notifyInfoServiceSpy } + ] + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotifyRequestsStatusComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should fetch data from the service on initialization', fakeAsync(() => { + const mockData: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [], + itemuuid: 'testUuid' + }); + component.itemUuid = mockData.itemuuid; + spyOn(notifyInfoServiceSpy, 'getNotifyRequestsStatus').and.callThrough(); + component.ngOnInit(); + fixture.detectChanges(); + tick(); + + expect(notifyInfoServiceSpy.getNotifyRequestsStatus).toHaveBeenCalledWith('testUuid'); + expect(component.statusMap.size).toBe(0); + })); + + it('should group data by status', () => { + const mockData: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [ + { + serviceName: 'test1', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'test2', + serviceUrl: 'test', + status: RequestStatusEnum.REJECTED, + }, + { + serviceName: 'test3', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + ], + itemUuid: 'testUuid' + }); + fixture.detectChanges(); + (component as any).groupDataByStatus(mockData); + + expect(component.statusMap.size).toBe(2); + expect(component.statusMap.get(RequestStatusEnum.ACCEPTED)?.length).toBe(2); + expect(component.statusMap.get(RequestStatusEnum.REJECTED)?.length).toBe(1); + }); +}); diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts index bd6e1983ed9..8b93b624950 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts @@ -1,17 +1,29 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { Observable, of } from 'rxjs'; -import { NotifyRequestsStatus, NotifyStatuses } from '../notify-requests-status.model'; -import { NotifyRequestsStatusDataService } from 'src/app/core/data/notify-services-status-data.service'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnDestroy, + OnInit, +} from '@angular/core'; +import { Subscription, filter } from 'rxjs'; +import { + NotifyRequestsStatus, + NotifyStatuses, +} from '../notify-requests-status.model'; +import { NotifyRequestsStatusDataService } from '../../../../core/data/notify-services-status-data.service'; import { RequestStatusEnum } from '../notify-status.enum'; - +import { + getFirstCompletedRemoteData, + getRemoteDataPayload, +} from '../../../../core/shared/operators'; +import { hasValue } from '../../../../shared/empty.util'; @Component({ selector: 'ds-notify-requests-status', templateUrl: './notify-requests-status.component.html', styleUrls: ['./notify-requests-status.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class NotifyRequestsStatusComponent { - +export class NotifyRequestsStatusComponent implements OnInit, OnDestroy { /** * The UUID of the item. */ @@ -24,85 +36,57 @@ export class NotifyRequestsStatusComponent { */ statusMap: Map = new Map(); - notifyRequestStatus$: Observable = of( Object.assign(new NotifyRequestsStatus(), { - notifyStatuses: [ - { - serviceName: 'test', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'test1', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'Review Platform', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'Demo Environment', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'Additional Information', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'Notification Service', - serviceUrl: 'test', - status: RequestStatusEnum.ACCEPTED, - }, - { - serviceName: 'test2', - serviceUrl: 'test', - status: RequestStatusEnum.REJECTED, - }, - { - serviceName: 'test3', - serviceUrl: 'test', - status: RequestStatusEnum.REQUESTED, - }, - { - serviceName: 'test4', - serviceUrl: 'test', - status: RequestStatusEnum.REQUESTED, - } - ], - itemUuid: '8d5fda2d-f380-467e-a86b-0436ac699dab', - })); - - constructor( - private notifyInfoService: NotifyRequestsStatusDataService, - ) { } + /** + * An array of subscriptions. + */ + subs: Subscription[] = []; - ngOnInit(): void { - this.notifyInfoService.getNotifyRequestsStatus(this.itemUuid).subscribe((data) => { - console.log(data, 'asdasdsa'); - }); + constructor(private notifyInfoService: NotifyRequestsStatusDataService) {} - this.notifyRequestStatus$.subscribe((data) => { - this.groupDataByStatus(data); - console.log(this.statusMap); - }); - } + ngOnInit(): void { + this.subs.push( + this.notifyInfoService + .getNotifyRequestsStatus(this.itemUuid) + .pipe( + getFirstCompletedRemoteData(), + filter((data) => hasValue(data)), + getRemoteDataPayload() + ) + .subscribe((data: NotifyRequestsStatus) => { + if (hasValue(data)) { + this.groupDataByStatus(data); + } + }) + ); + } /** * Groups the notify requests status data by status. * @param notifyRequestsStatus The notify requests status data. */ private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus): void { - notifyRequestsStatus.notifyStatuses.forEach((notifyStatus: NotifyStatuses) => { - const status = notifyStatus.status; + notifyRequestsStatus.notifyStatus.forEach( + (notifyStatus: NotifyStatuses) => { + const status = notifyStatus.status; + + if (!this.statusMap.has(status)) { + this.statusMap.set(status, []); + } - if (!this.statusMap.has(status)) { - this.statusMap.set(status, []); + this.statusMap.get(status)?.push(notifyStatus); } + ); + } - this.statusMap.get(status)?.push(notifyStatus); + /** + * Lifecycle hook that is called when the component is destroyed. + * Unsubscribes from any active subscriptions. + */ + ngOnDestroy(): void { + this.subs.forEach((sub) => { + if (hasValue(sub)) { + sub.unsubscribe(); + } }); } } diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts index ab4e41b2c6b..81d393ddde9 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts @@ -27,13 +27,13 @@ export class NotifyRequestsStatus implements CacheableObject { * The notify statuses. */ @autoserialize - notifyStatuses: NotifyStatuses[]; + notifyStatus: NotifyStatuses[]; /** * The UUID of the item. */ @autoserialize - itemUuid: string; + itemuuid: string; /** * The links associated with the notify requests status. diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts index da7ab2c881a..53b5545fd47 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts @@ -5,4 +5,4 @@ import {ResourceType} from '../../../core/shared/resource-type'; * Needs to be in a separate file to prevent circular * dependencies in webpack. */ -export const NOTIFYREQUEST = new ResourceType('notifyrequest'); +export const NOTIFYREQUEST = new ResourceType('notifyrequests'); diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts index 30393367a3e..1ecd084cfd9 100644 --- a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -1,12 +1,14 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; -import { Observable } from 'rxjs'; +import { Observable, filter } from 'rxjs'; import { AlertType } from '../../../shared/alert/aletr-type'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { RequestParam } from '../../../core/cache/models/request-param.model'; import { QualityAssuranceSourceDataService } from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; import { QualityAssuranceSourceObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; +import { PaginatedList } from 'src/app/core/data/paginated-list.model'; +import { hasValue } from 'src/app/shared/empty.util'; @Component({ selector: 'ds-qa-event-notification', @@ -47,6 +49,7 @@ export class QaEventNotificationComponent { .pipe( getFirstCompletedRemoteData(), getRemoteDataPayload(), + filter((pl: PaginatedList) => hasValue(pl)), getPaginatedListPayload(), ); } From 75ac289ff6833ceb8b6d4c91d38ae5790848f44b Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 22 Nov 2023 16:20:15 +0100 Subject: [PATCH 210/592] [CST-12709] chages --- .../notify-requests-status.component.html | 4 +- .../notify-requests-status.component.spec.ts | 14 +++-- .../notify-requests-status.component.ts | 63 +++++++------------ 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html index 7736e888967..c68255f2eda 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html @@ -1,5 +1,5 @@ - - + + diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts index 1498265ca4e..0ec4febc0be 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts @@ -50,7 +50,9 @@ describe('NotifyRequestsStatusComponent', () => { tick(); expect(notifyInfoServiceSpy.getNotifyRequestsStatus).toHaveBeenCalledWith('testUuid'); - expect(component.statusMap.size).toBe(0); + component.requestMap$.subscribe((map) => { + expect(map.size).toBe(0); + }); })); it('should group data by status', () => { @@ -74,11 +76,13 @@ describe('NotifyRequestsStatusComponent', () => { ], itemUuid: 'testUuid' }); + spyOn(notifyInfoServiceSpy, 'getNotifyRequestsStatus').and.returnValue(createSuccessfulRemoteDataObject$(mockData)); fixture.detectChanges(); (component as any).groupDataByStatus(mockData); - - expect(component.statusMap.size).toBe(2); - expect(component.statusMap.get(RequestStatusEnum.ACCEPTED)?.length).toBe(2); - expect(component.statusMap.get(RequestStatusEnum.REJECTED)?.length).toBe(1); + component.requestMap$.subscribe((map) => { + expect(map.size).toBe(2); + expect(map.get(RequestStatusEnum.ACCEPTED)?.length).toBe(2); + expect(map.get(RequestStatusEnum.REJECTED)?.length).toBe(1); + }); }); }); diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts index 8b93b624950..a04ed96363e 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts @@ -2,10 +2,9 @@ import { ChangeDetectionStrategy, Component, Input, - OnDestroy, OnInit, } from '@angular/core'; -import { Subscription, filter } from 'rxjs'; +import { Observable, filter, map } from 'rxjs'; import { NotifyRequestsStatus, NotifyStatuses, @@ -23,70 +22,52 @@ import { hasValue } from '../../../../shared/empty.util'; styleUrls: ['./notify-requests-status.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class NotifyRequestsStatusComponent implements OnInit, OnDestroy { +export class NotifyRequestsStatusComponent implements OnInit { /** * The UUID of the item. */ @Input() itemUuid: string; /** - * Map that stores the status of requests and their corresponding notify statuses. - * The keys of the map are instances of the RequestStatusEnum enum, - * and the values are arrays of NotifyStatuses objects. + * Observable representing the request map. + * The map contains request status enums as keys and arrays of notify statuses as values. */ - statusMap: Map = new Map(); + requestMap$: Observable>; - /** - * An array of subscriptions. - */ - subs: Subscription[] = []; - - constructor(private notifyInfoService: NotifyRequestsStatusDataService) {} + constructor(private notifyInfoService: NotifyRequestsStatusDataService) { } ngOnInit(): void { - this.subs.push( - this.notifyInfoService - .getNotifyRequestsStatus(this.itemUuid) - .pipe( - getFirstCompletedRemoteData(), - filter((data) => hasValue(data)), - getRemoteDataPayload() - ) - .subscribe((data: NotifyRequestsStatus) => { - if (hasValue(data)) { - this.groupDataByStatus(data); - } + this.requestMap$ = this.notifyInfoService + .getNotifyRequestsStatus(this.itemUuid) + .pipe( + getFirstCompletedRemoteData(), + filter((data) => hasValue(data)), + getRemoteDataPayload(), + filter((data: NotifyRequestsStatus) => hasValue(data)), + map((data: NotifyRequestsStatus) => { + return this.groupDataByStatus(data); }) - ); + ); } /** * Groups the notify requests status data by status. * @param notifyRequestsStatus The notify requests status data. */ - private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus): void { + private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus) { + const statusMap: Map = new Map(); notifyRequestsStatus.notifyStatus.forEach( (notifyStatus: NotifyStatuses) => { const status = notifyStatus.status; - if (!this.statusMap.has(status)) { - this.statusMap.set(status, []); + if (!statusMap.has(status)) { + statusMap.set(status, []); } - this.statusMap.get(status)?.push(notifyStatus); + statusMap.get(status)?.push(notifyStatus); } ); - } - /** - * Lifecycle hook that is called when the component is destroyed. - * Unsubscribes from any active subscriptions. - */ - ngOnDestroy(): void { - this.subs.forEach((sub) => { - if (hasValue(sub)) { - sub.unsubscribe(); - } - }); + return statusMap; } } From dbdfcea06a4f42f1d44524163795d52122224301 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Wed, 22 Nov 2023 17:58:11 +0100 Subject: [PATCH 211/592] [CST-12718] Added validations on LDN Service form --- .../ldn-service-form-edit.component.html | 13 ++++++++++- .../ldn-service-form-edit.component.ts | 23 ++++++++++++++++--- .../ldn-service-form.component.html | 13 ++++++++++- .../ldn-service-form.component.ts | 16 +++++++------ .../ldn-services-directory.component.ts | 4 ++-- src/assets/i18n/en.json5 | 2 ++ 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 1438cb6ce48..c27ca98b608 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -69,8 +69,11 @@

{{ 'ldn-edit-registered-service.title' | translate }} + type="number">
{{ 'ldn-new-service.form.error.score' | translate }}
@@ -160,6 +163,10 @@

{{ 'ldn-edit-registered-service.title' | translate }}
+

[placeholder]="'ldn-new-service.form.placeholder.score' | translate" formControlName="score" id="score" name="score" + min="0" + max="1" + step=".01" class="form-control" - type="text"> + type="number">
{{ 'ldn-new-service.form.error.score' | translate }}
@@ -153,6 +156,10 @@

{{ 'ldn-create-service.title' | translate }}

class="dropdown-menu scrollable-dropdown-menu w-100 " ngbDropdownMenu>
+

class="dropdown-menu scrollable-dropdown-menu w-100 " ngbDropdownMenu>
+ @@ -387,17 +386,11 @@

{{'service.overview.edit.modal' | translate }}

class="btn btn-primary">{{ 'service.detail.update' | translate }}
-
- -
- -
+
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 47d53bf457b..74ddc478725 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -334,13 +334,8 @@

{{ 'ldn-create-service.title' | translate }}

- -
- + -
- -
- -
+
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 008e27558fb..b3be86c2bd5 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -923,7 +923,7 @@ "service.overview.create.body": "Please confirm the creation of this service.", "ldn-service-status": "Status", "service.confirm.create": "Create", - "service.refuse.create": "Discard", + "service.refuse.create": "Cancel", "ldn-register-new-service.title": "Register a new service", "ldn-new-service.form.label.submit": "Save", "ldn-new-service.form.label.name": "Name", @@ -1006,12 +1006,12 @@ "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", "service.overview.delete.body": "Are you sure you want to delete this service?", - "service.overview.edit.body": "Are you sure you want to confirm those service changes?", + "service.overview.edit.body": "Are you sure you want to confirm the changes?", "service.overview.edit.modal": "Edit Service", "service.detail.update": "Edit Service", "service.detail.return": "Cancel", - "service.overview.reset-form.body": "Are you sure you want to discard those changes and leave?", - "service.overview.reset-form.modal": "Discard Service Changes", + "service.overview.reset-form.body": "Are you sure you want to discard the changes and leave?", + "service.overview.reset-form.modal": "Discard Changes", "service.overview.reset-form.reset-confirm": "Discard", "admin.registries.services-formats.modify.success.head": "Successful Edit", "admin.registries.services-formats.modify.success.content": "The service has been edited", @@ -1028,7 +1028,7 @@ "ldn-service-delete.notification.success.content": "The service has been deleted", "ldn-service-delete.notification.error.title": "Failed Deletion", "ldn-service-delete.notification.error.content": "The service has not been deleted", - "service.overview.reset-form.reset-return": "Return", + "service.overview.reset-form.reset-return": "Cancel", "service.overview.delete": "Delete service", "ldn-edit-service.title": "Edit service", "ldn-edit-service.form.label.name": "Name", From d257380670ee1fb51511a442d88ee75c66462836 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Thu, 23 Nov 2023 14:42:49 +0100 Subject: [PATCH 214/592] [CST-12768] other fixes --- .../ldn-services-directory.component.html | 12 ++++++++++-- .../notify-info/notify-info.component.html | 2 +- .../notify-info/notify-info.component.ts | 17 ++++++++++++++++- src/assets/i18n/en.json5 | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index e19f986e1a5..52cb7f47507 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -24,8 +24,16 @@

{{ 'ldn-registered-services.title' | translate }}

{{ ldnService.name }}{{ ldnService.description }}{{ ldnService.name }} + + +
+ {{ ldnService.description }} +
+
+
+
{{ 'coar-notify-support.title' | translate }}

{{ 'coar-notify-support.ldn-inbox.title' | translate }}

-

+

{{ 'coar-notify-support.message-moderation.title' | translate }}

diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts index 7de2cf538ac..b124b7baa1e 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { NotifyInfoService } from './notify-info.service'; -import { Observable, of } from 'rxjs'; +import { Observable, map, of } from 'rxjs'; @Component({ selector: 'ds-notify-info', @@ -21,4 +21,19 @@ export class NotifyInfoComponent implements OnInit { ngOnInit() { this.coarRestApiUrl = this.notifyInfoService.getCoarLdnLocalInboxUrls(); } + + /** + * Generates HTML code for COAR REST API links. + * @returns An Observable that emits the generated HTML code. + */ + generateCoarRestApiLinksHTML() { + return this.coarRestApiUrl.pipe( + // transform the data into HTML + map((urls) => { + return urls.map(url => ` + ${url} + `).join(','); + }) + ); + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 008e27558fb..1995e681101 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -896,7 +896,7 @@ "coar-notify-support.ldn-inbox.title": "LDN InBox", - "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at {ldnInboxUrl}ldn/inbox. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", + "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at {ldnInboxUrl}. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", "coar-notify-support.message-moderation.title": "Message Moderation", From 86bbd26145bb7a9442e45abbd1e9ca931f19c4b9 Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Thu, 23 Nov 2023 15:04:36 +0100 Subject: [PATCH 215/592] [CST-12768] unit test fix --- .../coar-notify/notify-info/notify-info.component.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts index e14fba61c19..bd18c1cbaab 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts @@ -3,8 +3,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NotifyInfoComponent } from './notify-info.component'; import { NotifyInfoService } from './notify-info.service'; import { TranslateModule } from '@ngx-translate/core'; +import { of } from 'rxjs'; -describe('NotifyInfoComponent', () => { +fdescribe('NotifyInfoComponent', () => { let component: NotifyInfoComponent; let fixture: ComponentFixture; let notifyInfoServiceSpy: any; @@ -25,6 +26,8 @@ describe('NotifyInfoComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(NotifyInfoComponent); component = fixture.componentInstance; + component.coarRestApiUrl = of([]); + spyOn(component, 'generateCoarRestApiLinksHTML').and.returnValue(of('')); fixture.detectChanges(); }); From 117415230bbcb67ab7dccdd032a264c6ca0e7d4f Mon Sep 17 00:00:00 2001 From: Alisa Ismailati Date: Thu, 23 Nov 2023 15:05:08 +0100 Subject: [PATCH 216/592] [CST-12768] small change --- .../core/coar-notify/notify-info/notify-info.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts index bd18c1cbaab..881e1b67fb2 100644 --- a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts +++ b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts @@ -5,7 +5,7 @@ import { NotifyInfoService } from './notify-info.service'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; -fdescribe('NotifyInfoComponent', () => { +describe('NotifyInfoComponent', () => { let component: NotifyInfoComponent; let fixture: ComponentFixture; let notifyInfoServiceSpy: any; From 430ee3846a2446e16914764e71c1d0c5e739ae2c Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 23 Nov 2023 21:04:02 +0100 Subject: [PATCH 217/592] 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 c0c77f44ebc..1e61f2cdb2f 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 @@

{{messagePrefix + '.headMembers' | translate}}

{{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 dbf32bb7074..1522723bdd3 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 237/592] 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 a48c4d15bfd..649aa9b43db 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.head' | translate}}

{{'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 277f6e49988..b3dda9091d9 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 1522723bdd3..3fa71678b86 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 238/592] 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 c370fe4f20d..4aa4c9af161 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}}