mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 03:23:07 +00:00
[CST-12109] implemented withdrawn-reinstate requests
This commit is contained in:
@@ -237,13 +237,7 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone
|
|||||||
.then((m) => m.SubscriptionsPageRoutingModule),
|
.then((m) => m.SubscriptionsPageRoutingModule),
|
||||||
canActivate: [AuthenticatedGuard]
|
canActivate: [AuthenticatedGuard]
|
||||||
},
|
},
|
||||||
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent },
|
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }
|
||||||
{
|
|
||||||
path: 'items',
|
|
||||||
loadChildren: () => import('./shared/correction-suggestion/correction-suggestion.module')
|
|
||||||
.then((m) => m.CorrectionSuggestionModule),
|
|
||||||
canActivate: [AuthenticatedGuard]
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
], {
|
], {
|
||||||
|
@@ -185,7 +185,6 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model';
|
|||||||
import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model';
|
import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model';
|
||||||
import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition';
|
import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition';
|
||||||
import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model';
|
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';
|
import { CorrectionTypeDataService } from './submission/correctiontype-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,8 +308,8 @@ const PROVIDERS = [
|
|||||||
OrcidAuthService,
|
OrcidAuthService,
|
||||||
OrcidQueueDataService,
|
OrcidQueueDataService,
|
||||||
OrcidHistoryDataService,
|
OrcidHistoryDataService,
|
||||||
SupervisionOrderDataService
|
SupervisionOrderDataService,
|
||||||
CorrectionTypeDataService,
|
CorrectionTypeDataService
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,7 +389,6 @@ export const models =
|
|||||||
Subscription,
|
Subscription,
|
||||||
ItemRequest,
|
ItemRequest,
|
||||||
BulkAccessConditionOptions
|
BulkAccessConditionOptions
|
||||||
CorrectionTypeMode
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@@ -207,7 +207,7 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu
|
|||||||
* @param data the data to post
|
* @param data the data to post
|
||||||
* @returns the RestResponse as an Observable
|
* @returns the RestResponse as an Observable
|
||||||
*/
|
*/
|
||||||
postData(data: string): Observable<RemoteData<OpenaireBrokerEventObject>> {
|
postData(data: string): Observable<RemoteData<QualityAssuranceEventObject>> {
|
||||||
const requestId = this.requestService.generateRequestId();
|
const requestId = this.requestService.generateRequestId();
|
||||||
const href$ = this.getBrowseEndpoint();
|
const href$ = this.getBrowseEndpoint();
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu
|
|||||||
request.responseMsToLive = this.responseMsToLive;
|
request.responseMsToLive = this.responseMsToLive;
|
||||||
}
|
}
|
||||||
this.requestService.send(request);
|
this.requestService.send(request);
|
||||||
return this.rdbService.buildFromRequestUUID<OpenaireBrokerEventObject>(requestId);
|
return this.rdbService.buildFromRequestUUID<QualityAssuranceEventObject>(requestId);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,6 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
||||||
import { BitstreamRequestACopyPageComponent } from './bitstreams/request-a-copy/bitstream-request-a-copy-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 { 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 { OrcidPageComponent } from './orcid-page/orcid-page.component';
|
||||||
import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
|
import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
|
||||||
import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver';
|
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',
|
path: 'full',
|
||||||
component: ThemedFullItemPageComponent,
|
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,
|
path: ITEM_EDIT_PATH,
|
||||||
loadChildren: () => import('./edit-item-page/edit-item-page.module')
|
loadChildren: () => import('./edit-item-page/edit-item-page.module')
|
||||||
|
@@ -16,10 +16,14 @@ import { RelatedItemsComponent } from './simple/related-items/related-items-comp
|
|||||||
import {
|
import {
|
||||||
ThemedMetadataRepresentationListComponent
|
ThemedMetadataRepresentationListComponent
|
||||||
} from './simple/metadata-representation-list/themed-metadata-representation-list.component';
|
} from './simple/metadata-representation-list/themed-metadata-representation-list.component';
|
||||||
|
import {
|
||||||
|
ItemWithdrawnReinstateModalComponent
|
||||||
|
} from '../shared/correction-suggestion/withdrawn-reinstate-modal.component';
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
ItemVersionsDeleteModalComponent,
|
ItemVersionsDeleteModalComponent,
|
||||||
ItemVersionsSummaryModalComponent,
|
ItemVersionsSummaryModalComponent,
|
||||||
|
ItemWithdrawnReinstateModalComponent
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -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>
|
|
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
@@ -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 { }
|
|
@@ -1,3 +0,0 @@
|
|||||||
<div class="container">
|
|
||||||
<ng-container *ngComponentOutlet="getComponent(); injector: objectInjector"></ng-container>
|
|
||||||
</div>
|
|
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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 }))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
export enum CorrectionTypeForms {
|
|
||||||
MANAGE_RELATION = 'manageRelation',
|
|
||||||
}
|
|
@@ -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>
|
|
@@ -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 {
|
|
||||||
|
|
||||||
}
|
|
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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>
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
@@ -21,6 +21,8 @@ import { getDSORoute } from '../../app-routing-paths';
|
|||||||
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
|
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
|
||||||
import { NotificationsService } from '../notifications/notifications.service';
|
import { NotificationsService } from '../notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
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
|
* Creates the menus for the dspace object pages
|
||||||
@@ -39,6 +41,8 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
|
|||||||
protected researcherProfileService: ResearcherProfileDataService,
|
protected researcherProfileService: ResearcherProfileDataService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService,
|
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.dsoVersioningModalService.getVersioningTooltipMessage(dso, 'item.page.version.hasDraft', 'item.page.version.create'),
|
||||||
this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, dso.self),
|
this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, dso.self),
|
||||||
this.authorizationService.isAuthorized(FeatureID.CanClaimItem, dso.self),
|
this.authorizationService.isAuthorized(FeatureID.CanClaimItem, dso.self),
|
||||||
|
this.authorizationService.isAuthorized(FeatureID.WithdrawItem, dso.self),
|
||||||
|
this.authorizationService.isAuthorized(FeatureID.ReinstateItem, dso.self),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem]) => {
|
map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem, canWithdrawItem, canReinstateItem]) => {
|
||||||
const isPerson = this.getDsoType(dso) === 'person';
|
const isPerson = this.getDsoType(dso) === 'person';
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -170,6 +176,32 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
|
|||||||
icon: 'hand-paper',
|
icon: 'hand-paper',
|
||||||
index: 3
|
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
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@@ -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'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -284,6 +284,9 @@ import {
|
|||||||
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
|
} 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 { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
|
||||||
import { NgxPaginationModule } from 'ngx-pagination';
|
import { NgxPaginationModule } from 'ngx-pagination';
|
||||||
|
import {
|
||||||
|
QualityAssuranceEventDataService
|
||||||
|
} from '../core/suggestion-notifications/qa/events/quality-assurance-event-data.service';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -471,7 +474,8 @@ const ENTRY_COMPONENTS = [
|
|||||||
const PROVIDERS = [
|
const PROVIDERS = [
|
||||||
TruncatableService,
|
TruncatableService,
|
||||||
MockAdminGuard,
|
MockAdminGuard,
|
||||||
AbstractTrackableComponent
|
AbstractTrackableComponent,
|
||||||
|
QualityAssuranceEventDataService
|
||||||
];
|
];
|
||||||
|
|
||||||
const DIRECTIVES = [
|
const DIRECTIVES = [
|
||||||
|
@@ -2562,6 +2562,12 @@
|
|||||||
|
|
||||||
"item.version.create.modal.header": "New version",
|
"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": "Create a new version for this item",
|
||||||
|
|
||||||
"item.version.create.modal.text.startingFrom": "starting from version {{version}}",
|
"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.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.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.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.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.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.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.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}}",
|
"item.version.create.notification.success": "New version has been created with version number {{version}}",
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import { CorrectionSuggestionModule } from './../../app/shared/correction-suggestion/correction-suggestion.module';
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { AdminRegistriesModule } from '../../app/admin/admin-registries/admin-registries.module';
|
import { AdminRegistriesModule } from '../../app/admin/admin-registries/admin-registries.module';
|
||||||
@@ -299,8 +298,7 @@ const DECLARATIONS = [
|
|||||||
SystemWideAlertModule,
|
SystemWideAlertModule,
|
||||||
NgxGalleryModule,
|
NgxGalleryModule,
|
||||||
FormModule,
|
FormModule,
|
||||||
RequestCopyModule,
|
RequestCopyModule
|
||||||
CorrectionSuggestionModule,
|
|
||||||
],
|
],
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
exports: [
|
exports: [
|
||||||
|
Reference in New Issue
Block a user