[CST-12109] implemented withdrawn-reinstate requests

This commit is contained in:
Mykhaylo Boychuk
2023-11-01 14:29:26 +01:00
parent 143916c604
commit 9094d8233f
28 changed files with 292 additions and 1017 deletions

View File

@@ -237,13 +237,7 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone
.then((m) => m.SubscriptionsPageRoutingModule),
canActivate: [AuthenticatedGuard]
},
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent },
{
path: 'items',
loadChildren: () => import('./shared/correction-suggestion/correction-suggestion.module')
.then((m) => m.CorrectionSuggestionModule),
canActivate: [AuthenticatedGuard]
},
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }
]
}
], {

View File

@@ -185,7 +185,6 @@ 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';
/**
@@ -309,8 +308,8 @@ const PROVIDERS = [
OrcidAuthService,
OrcidQueueDataService,
OrcidHistoryDataService,
SupervisionOrderDataService
CorrectionTypeDataService,
SupervisionOrderDataService,
CorrectionTypeDataService
];
/**
@@ -390,7 +389,6 @@ export const models =
Subscription,
ItemRequest,
BulkAccessConditionOptions
CorrectionTypeMode
];
@NgModule({

View File

@@ -207,7 +207,7 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu
* @param data the data to post
* @returns the RestResponse as an Observable
*/
postData(data: string): Observable<RemoteData<OpenaireBrokerEventObject>> {
postData(data: string): Observable<RemoteData<QualityAssuranceEventObject>> {
const requestId = this.requestService.generateRequestId();
const href$ = this.getBrowseEndpoint();
@@ -218,7 +218,7 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu
request.responseMsToLive = this.responseMsToLive;
}
this.requestService.send(request);
return this.rdbService.buildFromRequestUUID<OpenaireBrokerEventObject>(requestId);
return this.rdbService.buildFromRequestUUID<QualityAssuranceEventObject>(requestId);
})
);
}

View File

@@ -16,7 +16,6 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
import { VersionPageComponent } from './version-page/version-page/version-page.component';
import { BitstreamRequestACopyPageComponent } from './bitstreams/request-a-copy/bitstream-request-a-copy-page.component';
import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
import { CORRECTION_TYPE_PATH, REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
import { OrcidPageComponent } from './orcid-page/orcid-page.component';
import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver';
@@ -42,18 +41,6 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver';
path: 'full',
component: ThemedFullItemPageComponent,
},
{
path: CORRECTION_TYPE_PATH,
loadChildren: () => import('../shared/correction-suggestion/correction-suggestion.module')
.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')

View File

@@ -16,10 +16,14 @@ import { RelatedItemsComponent } from './simple/related-items/related-items-comp
import {
ThemedMetadataRepresentationListComponent
} from './simple/metadata-representation-list/themed-metadata-representation-list.component';
import {
ItemWithdrawnReinstateModalComponent
} from '../shared/correction-suggestion/withdrawn-reinstate-modal.component';
const ENTRY_COMPONENTS = [
ItemVersionsDeleteModalComponent,
ItemVersionsSummaryModalComponent,
ItemWithdrawnReinstateModalComponent
];

View File

@@ -1,7 +0,0 @@
<ng-container *ngIf="(hasCorrectionTypeAvailable() | async)">
<button ngbDropdownItem
*ngFor="let type of (getCorrectionTypes() | async)"
[routerLink]="getTypeRoute(type.id)"
[innerHTML]="('context-menu.actions.correction-type.btn.' + type.id | translate)">
</button>
</ng-container>

View File

@@ -1,116 +0,0 @@
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 { CorrectionType } from '../../../core/submission/models/correction-type-mode.model';
describe('CorrectionTypeMenuComponent', () => {
let component: CorrectionTypeMenuComponent;
let fixture: ComponentFixture<CorrectionTypeMenuComponent>;
let componentAsAny: any;
let correctionTypeService: any;
let dso: DSpaceObject;
const notificationService = new NotificationsServiceStub();
const correctionType: CorrectionType = Object.assign(new CorrectionType(), {
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();
});
});
});

View File

@@ -1,98 +0,0 @@
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, map, Observable, startWith, Subscription } from 'rxjs';
import { CorrectionType } from '../../../core/submission/models/correction-type-mode.model';
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
import { hasValue, isNotEmpty } from '../../empty.util';
import { rendersContextMenuEntriesForType } from '../context-menu.decorator';
import { CORRECTION_TYPE_PATH } 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;
/**
* List of Edit Modes available on this item
* for the current user
*/
private correctionTypes$: BehaviorSubject<CorrectionType[]> = new BehaviorSubject<CorrectionType[]>([]);
/**
* Variable to track subscription and unsubscribe it onDestroy
*/
private sub: Subscription;
isAuthorized$: Observable<boolean>;
constructor(
@Inject('contextMenuObjectProvider') protected injectedContextMenuObject: DSpaceObject,
@Inject('contextMenuObjectTypeProvider') protected injectedContextMenuObjectType: DSpaceObjectType,
private correctionTypeService: CorrectionTypeDataService,
) {
super(injectedContextMenuObject, injectedContextMenuObjectType, ContextMenuEntryType.CorrectionType);
}
ngOnInit(): void {
this.getData();
}
/**
* Check if edit mode is available
*/
getCorrectionTypes(): Observable<CorrectionType[]> {
return this.correctionTypes$.asObservable();
}
/**
* Check if any correction type are available
*/
hasCorrectionTypeAvailable(): Observable<boolean> {
return this.correctionTypes$.asObservable().pipe(
map((type) => isNotEmpty(type) && type.length > 0)
);
}
/**
* Get correction types
* useCachedVersionIfAvailable = false to force refreshing the list
*/
getData(): void {
this.sub = this.correctionTypeService.findByItem(this.contextMenuObject.id, false).pipe(
getAllSucceededRemoteDataPayload(),
getPaginatedListPayload(),
startWith([])
).subscribe((types: CorrectionType[]) => {
this.correctionTypes$.next(types);
});
}
/**
* Get the route to the correction type page
* @param typeId correction type id
* @returns the route to the correction type page
*/
getTypeRoute(typeId: string): string[] {
return ['./', CORRECTION_TYPE_PATH, typeId];
}
/**
* Make sure the subscription is unsubscribed from when this component is destroyed
*/
ngOnDestroy(): void {
if (hasValue(this.sub)) {
this.sub.unsubscribe();
}
}
}

View File

@@ -1,15 +0,0 @@
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);
}

View File

@@ -1,24 +0,0 @@
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: I18nBreadcrumbResolver
},
data: { title: 'item-correction-suggestion.correction-type', breadcrumbKey: 'item-correction-suggestion.correction-type' },
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [
I18nBreadcrumbResolver
]
})
export class CorrectionSuggestionRoutingModule { }

View File

@@ -1,3 +0,0 @@
<div class="container">
<ng-container *ngComponentOutlet="getComponent(); injector: objectInjector"></ng-container>
</div>

View File

@@ -1,80 +0,0 @@
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<CorrectionSuggestionComponent>;
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 ],
imports: [
CommonModule,
BrowserModule,
TranslateModule.forRoot(),
RouterTestingModule.withRoutes([]),
],
providers: [
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
{ provide: CorrectionTypeDataService, useValue: correctionTypeDataService },
],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
});
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();
});
});

View File

@@ -1,94 +0,0 @@
import { getRemoteDataPayload } from './../../core/shared/operators';
import { CorrectionTypeDataService } from './../../core/submission/correctiontype-data.service';
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';
import { ActivatedRoute } from '@angular/router';
import { hasValue } from '../empty.util';
import { getFirstCompletedRemoteData } from '../../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: CorrectionType;
/**
* 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,
private chd: ChangeDetectorRef,
) {
this.correctionTypeId = this.aroute.snapshot.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: CorrectionType) => {
if (hasValue(correctionType)) {
this.correctionTypeObject = correctionType;
this.creationForm = correctionType.creationForm;
this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
this.injectData();
this.chd.detectChanges();
}
});
}
}
/**
* 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<Component>}
*/
getComponent(): GenericConstructor<Component> {
return getCorrectionComponent(this.creationForm);
}
}

View File

@@ -1,39 +0,0 @@
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 }))
};
}
}

View File

@@ -1,3 +0,0 @@
export enum CorrectionTypeForms {
MANAGE_RELATION = 'manageRelation',
}

View File

@@ -1,56 +0,0 @@
<div class="row justify-content-center">
<h4>
{{ ( 'correction-type.manage-relation.' + (correctionType.topic | lowercase) + '.searchHeader' | translate) }}
</h4>
</div>
<div class="pt-3">
<div id="project-entities" class="mb-3">
<div id="project-search" class="input-group mb-3">
<input type="text" class="form-control" (keyup.enter)="search(projectTitle)" [(ngModel)]="projectTitle"
[placeholder]="'correction-type.manage-relation.search.placeholder' | translate" aria-label="" aria-describedby="">
<div class="input-group-append">
<button type="button" class="btn btn-outline-secondary" [disabled]="projectTitle === ''"
(click)="projectTitle = ''; search('')">{{('correction-type.manage-relation.search.btn.clear' | translate)}}</button>
<button type="button" class="btn btn-primary" [disabled]="projectTitle === ''"
(click)="search(projectTitle)">{{('correction-type.manage-relation.search.btn.search' | translate)}}</button>
</div>
</div>
<ds-loading *ngIf="(isLoading$ | async)" message="{{'loading.search-results' | translate}}"></ds-loading>
<ds-viewable-collection
*ngIf="(localEntitiesRD$ | async)?.payload?.page?.length > 0 && !(isLoading$ | async)"
[config]="pagination"
[sortConfig]="searchOptions?.sort"
[objects]="(localEntitiesRD$ | async)"
[hideGear]="true"
[selectable]="true"
[selectionConfig]="{ repeatable: false, listId: entityListId }"
[linkType]="linkTypes.Link"
[context]="context"
[hidePaginationDetail]="false"
(deselectObject)="deselectEntity()"
(selectObject)="selectEntity($event)">
</ds-viewable-collection>
<div *ngIf="(localEntitiesRD$ | async)?.payload?.page?.length < 1 && !(isLoading$ | async)">
<ds-alert [type]="'alert-info'">
<p class="lead mb-0">{{( 'correction-type.manage-relation.search.notFound' | translate)}}</p>
</ds-alert>
</div>
</div>
<div class="flex-row d-flex justify-content-between">
<div>
<button type="button" class="btn btn-outline-secondary" (click)="back()">
{{ ( 'correction-type.manage-relation.' + (correctionType.topic | lowercase) + '.cancel' | translate) }}
</button>
</div>
<div>
<button type="button" class="btn btn-primary" [disabled]="selectedImportType === importType.None" (click)="performAction()">
{{ ( 'correction-type.manage-relation.' + (correctionType.topic | lowercase) + '.submit' | translate) }}
</button>
</div>
</div>
</div>

View File

@@ -1,173 +0,0 @@
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<ManageRelationCorrectionTypeComponent>;
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, 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 {
}

View File

@@ -1,278 +0,0 @@
import { NotificationsService } from '../../../notifications/notifications.service';
import { OpenaireBrokerEventObject } from '../../../../core/openaire/broker/models/openaire-broker-event.model';
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';
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 { CorrectionType } from '../../../../core/submission/models/correction-type-mode.model';
import { CorrectionTypeForms } from '../correction-type-forms';
import { ActivatedRoute, Router } from '@angular/router';
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';
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',
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: CorrectionType;
/**
* The item uuid from the parent object
*/
itemUuid: string;
/**
* The project title from the parent object
*/
projectTitle = '';
/**
* Pagination options
*/
pagination: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
id: 'csmr',
pageSize: 10,
currentPage: 1
});
/**
* Entities to show in the list
*/
localEntitiesRD$: Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>;
/**
* 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 = 'csmr';
/**
* List ID for selecting local authorities
*/
authorityListId = 'csmr-authority';
/**
* ImportType enum
*/
importType = ImportType;
/**
* The type of import the user currently has selected
*/
selectedImportType = ImportType.None;
constructor(
@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 translateService: TranslateService,
) {
this.correctionType = correctionTypeObject;
this.itemUuid = this.aroute.snapshot.params.id;
}
/**
* Get the search results
*/
ngOnInit(): void {
this.getData();
}
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))
);
})
);
}
/**
* 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
}
));
} 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)
)
);
}
/**
* 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:
* <item link>
* <selected entity link>
* <correction type link>
*/
performAction() {
if (hasValue(this.selectedEntity)) {
const selectedItemLink = (this.selectedEntity as SearchResult<DSpaceObject>).indexableObject._links.self.href;
this.itemService.findById(this.itemUuid).pipe(
getFirstSucceededRemoteDataPayload(),
switchMap((item: Item) => {
const data: string = this.correctionTypeObject._links.self.href + '\n' + item._links.self.href + '\n' + selectedItemLink;
return this.openaireBrokerEventRestService.postData(data);
}),
getFirstCompletedRemoteData()
).subscribe((res: RemoteData<OpenaireBrokerEventObject>) => {
if (res.hasSucceeded) {
this.selectedImportType = ImportType.None;
const message = 'correction-type.manage-relation.' + this.correctionTypeObject.id + '.notification.success';
this.notificationsService.success(this.translateService.get(message));
this.deselectAllLists();
this.back();
} else {
this.notificationsService.error(this.translateService.get('correction-type.manage-relation.action.notification.error'));
}
});
}
}
/**
* 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());
}
}

View File

@@ -0,0 +1,48 @@
<div *ngIf="!(this.submitted$ | async); else waiting">
<div *ngIf="(this.canWithdraw$ | async); else reinstateHeader" class="modal-header">
{{'item.qa.withdrawn.modal.header' | translate}}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="summary">{{'item.qa-withdrawn-reinstate.create.modal.form.summary.label' | translate }}:</label>
<input type="text" id="summary" class="form-control" [(ngModel)]="summary"
(keyup.enter)="onModalSubmit()"
placeholder="{{'item.qa.withdrown-reinstate.modal.form.summary.placeholder' | translate }}"/>
</div>
</div>
<div class="modal-footer space-children-mr">
<button class="btn btn-outline-secondary btn-sm ml-0"
type="button"
(click)="onModalClose()"
title="{{'item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip' | translate}}">
<i class="fas fa-times fa-fw"></i> {{'item.qa.withdrawn-reinstate.create.modal.button.cancel' | translate}}
</button>
<button class="btn btn-success btn-sm ml-0"
type="submit"
(click)="onModalSubmit()"
title="{{'item.qa.withdrawn-reinstate.modal.button.confirm.tooltip' | translate}}">
<i class="fas fa-check fa-fw"></i> {{'item.qa.withdrown-reinstate.create.modal.button.confirm' | translate}}
</button>
</div>
</div>
<ng-template #waiting>
<div class="modal-header">{{'item.qa.withdrawn.modal.submitted.header' | translate}}</div>
<div class="modal-body">
<div class="d-flex justify-content-center">
<ds-loading [showMessage]="false"></ds-loading>
</div>
</div>
</ng-template>
<ng-template #reinstateHeader>
<div *ngIf="this.canReinstate$ | async" class="modal-header">
{{'item.qa.reinstate.modal.header' | translate}}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</ng-template>

View File

@@ -0,0 +1,47 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ModalBeforeDismiss } from '../interfaces/modal-before-dismiss.interface';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
@Component({
selector: 'ds-item-withdrawn-reinstate-modal',
templateUrl: './item-withdrawn-reinstate-modal.component.html',
styleUrls: ['./item-withdrawn-reinstate-modal.component.scss']
})
export class ItemWithdrawnReinstateModalComponent implements ModalBeforeDismiss {
summary: string;
canWithdraw$: Observable<boolean> = of(false);
canReinstate$: Observable<boolean> = of(false);
submitted$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
@Output() createQAEvent: EventEmitter<string> = new EventEmitter<string>();
constructor(
protected activeModal: NgbActiveModal,
protected authorizationService: AuthorizationDataService
) {}
onModalClose() {
this.activeModal.close();
}
beforeDismiss(): boolean {
// prevent the modal from being dismissed after version creation is initiated
return !this.submitted$.getValue();
}
onModalSubmit() {
this.submitted$.next(true);
this.createQAEvent.emit(this.summary);
}
public setDso(dso: DSpaceObject) {
this.canWithdraw$ = this.authorizationService.isAuthorized(FeatureID.WithdrawItem, dso.self);
this.canReinstate$ = this.authorizationService.isAuthorized(FeatureID.ReinstateItem, dso.self);
}
}

View File

@@ -21,6 +21,8 @@ import { getDSORoute } from '../../app-routing-paths';
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
import { NotificationsService } from '../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { DsoWithdrawnModalService } from './dso-withdrawn-service/dso-withdrawn-modal.service';
import { DsoReinstateModalService } from './dso-reinstate-service/dso-reinstate-modal.service';
/**
* Creates the menus for the dspace object pages
@@ -39,6 +41,8 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
protected researcherProfileService: ResearcherProfileDataService,
protected notificationsService: NotificationsService,
protected translate: TranslateService,
protected dsoWithdrawnModalService: DsoWithdrawnModalService,
protected dsoReinstateModalService: DsoReinstateModalService
) {
}
@@ -125,8 +129,10 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
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),
]).pipe(
map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem]) => {
map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem, canWithdrawItem, canReinstateItem]) => {
const isPerson = this.getDsoType(dso) === 'person';
return [
{
@@ -170,6 +176,32 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
icon: 'hand-paper',
index: 3
},
{
id: 'withdrawn-item',
active: false,
visible: canWithdrawItem,
model: {
type: MenuItemType.ONCLICK,
function: () => {
this.dsoWithdrawnModalService.openCreateWithdrawnModal(dso);
}
} as OnClickMenuItemModel,
icon: 'lock',
index: 4
},
{
id: 'reinstate-item',
active: false,
visible: canReinstateItem,
model: {
type: MenuItemType.ONCLICK,
function: () => {
this.dsoReinstateModalService.openCreateReinstateModal(dso);
}
} as OnClickMenuItemModel,
icon: 'unlock-keyhole',
index: 5
}
];
}),
);

View File

@@ -0,0 +1,65 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ItemDataService } from '../../../core/data/item-data.service';
import { NotificationsService } from '../../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import {
QualityAssuranceEventDataService
} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service';
import { ItemWithdrawnReinstateModalComponent } from '../../correction-suggestion/withdrawn-reinstate-modal.component';
import { filter } from 'rxjs/operators';
import { RemoteData } from '../../../core/data/remote-data';
import {
QualityAssuranceEventObject
} from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model';
@Injectable({
providedIn: 'root'
})
export class DsoReinstateModalService {
constructor(
protected router: Router,
protected modalService: NgbModal,
protected itemService: ItemDataService,
private notificationsService: NotificationsService,
private translateService: TranslateService,
protected qaEventDataService: QualityAssuranceEventDataService
) {}
/**
* Open the reinstate modal for the provided dso
*/
openCreateReinstateModal(dso): void {
const selfHref = dso._links.self.href;
const data = 'https://localhost:8080/server/api/config/correctiontypes/reinstateRequest' + '\n' + selfHref;
// Open modal
const activeModal = this.modalService.open(ItemWithdrawnReinstateModalComponent);
(activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).setDso(dso);
(activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).submitted$
.pipe(
filter((val) => val)
).subscribe(
() => {
this.sendQARequest(data);
activeModal.close();
}
);
}
sendQARequest(data: string): void {
this.qaEventDataService.postData(data)
.subscribe((res: RemoteData<QualityAssuranceEventObject>) => {
if (res.hasSucceeded) {
const message = 'reinstate';
this.notificationsService.success(this.translateService.get(message));
} else {
this.notificationsService.error(this.translateService.get('correction-type.manage-relation.action.notification.error'));
}
});
}
}

View File

@@ -0,0 +1,64 @@
import { Injectable } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Router } from '@angular/router';
import { ItemDataService } from '../../../core/data/item-data.service';
import { ItemWithdrawnReinstateModalComponent } from '../../correction-suggestion/withdrawn-reinstate-modal.component';
import {
QualityAssuranceEventDataService
} from '../../../core/suggestion-notifications/qa/events/quality-assurance-event-data.service';
import {
QualityAssuranceEventObject
} from '../../../core/suggestion-notifications/qa/models/quality-assurance-event.model';
import { RemoteData } from '../../../core/data/remote-data';
import { TranslateService } from '@ngx-translate/core';
import { NotificationsService } from '../../notifications/notifications.service';
import { filter } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DsoWithdrawnModalService {
constructor(
protected router: Router,
protected modalService: NgbModal,
protected itemService: ItemDataService,
private notificationsService: NotificationsService,
private translateService: TranslateService,
protected qaEventDataService: QualityAssuranceEventDataService
) {}
/**
* Open the create withdrawn modal for the provided dso
*/
openCreateWithdrawnModal(dso): void {
const selfHref = dso._links.self.href;
const data = 'https://localhost:8080/server/api/config/correctiontypes/withdrawnRequest' + '\n' + selfHref;
// Open modal
const activeModal = this.modalService.open(ItemWithdrawnReinstateModalComponent);
(activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).setDso(dso);
(activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).submitted$
.pipe(
filter((val) => val)
).subscribe(
() => {
this.sendQARequest(data);
activeModal.close();
}
);
}
sendQARequest(data: string): void {
this.qaEventDataService.postData(data)
.subscribe((res: RemoteData<QualityAssuranceEventObject>) => {
if (res.hasSucceeded) {
const message = 'withdrawn';
this.notificationsService.success(this.translateService.get(message));
} else {
this.notificationsService.error(this.translateService.get('correction-type.manage-relation.action.notification.error'));
}
});
}
}

View File

@@ -284,6 +284,9 @@ import {
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
import { NgxPaginationModule } from 'ngx-pagination';
import {
QualityAssuranceEventDataService
} from '../core/suggestion-notifications/qa/events/quality-assurance-event-data.service';
const MODULES = [
CommonModule,
@@ -471,7 +474,8 @@ const ENTRY_COMPONENTS = [
const PROVIDERS = [
TruncatableService,
MockAdminGuard,
AbstractTrackableComponent
AbstractTrackableComponent,
QualityAssuranceEventDataService
];
const DIRECTIVES = [

View File

@@ -2562,6 +2562,12 @@
"item.version.create.modal.header": "New version",
"item.qa.withdrawn.modal.header": "Send Withdrawn Item request",
"item.qa.reinstate.modal.header": "Send Reinstate Item request",
"item.qa.reinstate.create.modal.header": "New version",
"item.version.create.modal.text": "Create a new version for this item",
"item.version.create.modal.text.startingFrom": "starting from version {{version}}",
@@ -2570,16 +2576,30 @@
"item.version.create.modal.button.confirm.tooltip": "Create new version",
"item.qa.withdrawn-reinstate.modal.button.confirm.tooltip": "Send request",
"item.qa.withdrown-reinstate.create.modal.button.confirm": "Send Request",
"item.version.create.modal.button.cancel": "Cancel",
"item.qa.withdrawn-reinstate.create.modal.button.cancel": "Cancel",
"item.version.create.modal.button.cancel.tooltip": "Do not create new version",
"item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip": "Do not send request",
"item.version.create.modal.form.summary.label": "Summary",
"item.qa-withdrawn-reinstate.create.modal.form.summary.label": "Summary",
"item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version",
"item.qa.withdrown-reinstate.modal.form.summary.placeholder": "Indicates the reasons (optionaly)",
"item.version.create.modal.submitted.header": "Creating new version...",
"item.qa.withdrawn.modal.submitted.header": "Sending withdrawn request...",
"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}}",

View File

@@ -1,4 +1,3 @@
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,8 +298,7 @@ const DECLARATIONS = [
SystemWideAlertModule,
NgxGalleryModule,
FormModule,
RequestCopyModule,
CorrectionSuggestionModule,
RequestCopyModule
],
declarations: DECLARATIONS,
exports: [