71806: Curation tasks UI

This commit is contained in:
Yana De Pauw
2020-07-16 11:42:11 +02:00
parent 9d3f58770a
commit 2162153ae9
22 changed files with 620 additions and 9 deletions

View File

@@ -0,0 +1,4 @@
<div class="container">
<h2>{{'admin.curation-tasks.header' |translate }}</h2>
<ds-curation-form></ds-curation-form>
</div>

View File

@@ -0,0 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AdminCurationTasksComponent } from './admin-curation-tasks.component';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('AdminCurationTasksComponent', () => {
let comp: AdminCurationTasksComponent;
let fixture: ComponentFixture<AdminCurationTasksComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [AdminCurationTasksComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AdminCurationTasksComponent);
comp = fixture.componentInstance;
});
describe('init', () => {
it('should initialise the comp', () => {
expect(comp).toBeDefined();
expect(fixture.debugElement.nativeElement.innerHTML).toContain('ds-curation-form');
});
});
});

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
/**
* Component responsible for rendering the system wide Curation Task UI
*/
@Component({
selector: 'ds-admin-curation-task',
templateUrl: './admin-curation-tasks.component.html',
})
export class AdminCurationTasksComponent {
}

View File

@@ -6,6 +6,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
import { URLCombiner } from '../core/url-combiner/url-combiner'; import { URLCombiner } from '../core/url-combiner/url-combiner';
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
const REGISTRIES_MODULE_PATH = 'registries'; const REGISTRIES_MODULE_PATH = 'registries';
export const ACCESS_CONTROL_MODULE_PATH = 'access-control'; export const ACCESS_CONTROL_MODULE_PATH = 'access-control';
@@ -41,6 +42,12 @@ export function getAccessControlModulePath() {
component: AdminWorkflowPageComponent, component: AdminWorkflowPageComponent,
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' } data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }
}, },
{
path: 'curation-tasks',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminCurationTasksComponent,
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }
},
]) ])
], ],
providers: [ providers: [

View File

@@ -469,7 +469,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
model: { model: {
type: MenuItemType.LINK, type: MenuItemType.LINK,
text: 'menu.section.curation_task', text: 'menu.section.curation_task',
link: '' link: 'admin/curation-tasks'
} as LinkMenuItemModel, } as LinkMenuItemModel,
icon: 'filter', icon: 'filter',
index: 7 index: 7

View File

@@ -16,6 +16,7 @@ import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './adm
import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component'; import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component';
import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component'; import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component';
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -35,6 +36,7 @@ import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow
CommunityAdminSearchResultGridElementComponent, CommunityAdminSearchResultGridElementComponent,
CollectionAdminSearchResultGridElementComponent, CollectionAdminSearchResultGridElementComponent,
ItemAdminSearchResultActionsComponent, ItemAdminSearchResultActionsComponent,
AdminCurationTasksComponent,
WorkflowItemSearchResultAdminWorkflowListElementComponent, WorkflowItemSearchResultAdminWorkflowListElementComponent,
WorkflowItemSearchResultAdminWorkflowGridElementComponent, WorkflowItemSearchResultAdminWorkflowGridElementComponent,

View File

@@ -0,0 +1,6 @@
<div class="container">
<h3>{{'collection.curate.header' |translate:{collection: (collectionName$ |async)} }}</h3>
<ds-curation-form
[dsoHandle]="(dsoRD$|async)?.payload.handle"
></ds-curation-form>
</div>

View File

@@ -0,0 +1,69 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { CollectionCurateComponent } from './collection-curate.component';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
import { Collection } from '../../../core/shared/collection.model';
import { ActivatedRoute } from '@angular/router';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
describe('CollectionCurateComponent', () => {
let comp: CollectionCurateComponent;
let fixture: ComponentFixture<CollectionCurateComponent>;
let debugEl: DebugElement;
let routeStub;
let dsoNameService;
const collection = Object.assign(new Collection(), {
handle: '123456789/1', metadata: {'dc.title': ['Collection Name']}
});
beforeEach(async(() => {
routeStub = {
parent: {
data: observableOf({
dso: createSuccessfulRemoteDataObject(collection)
})
}
};
dsoNameService = jasmine.createSpyObj('dsoNameService', {
getName: 'Collection Name'
});
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [CollectionCurateComponent],
providers: [
{provide: ActivatedRoute, useValue: routeStub},
{provide: DSONameService, useValue: dsoNameService}
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CollectionCurateComponent);
comp = fixture.componentInstance;
debugEl = fixture.debugElement;
fixture.detectChanges();
});
describe('init', () => {
it('should initialise the comp', () => {
expect(comp).toBeDefined();
expect(debugEl.nativeElement.innerHTML).toContain('ds-curation-form');
});
it('should contain the collection information provided in the route', () => {
comp.dsoRD$.subscribe((value) => {
expect(value.payload.handle
).toEqual('123456789/1');
});
comp.collectionName$.subscribe((value) => {
expect(value).toEqual('Collection Name');
});
});
});
});

View File

@@ -1,4 +1,11 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { filter, map, take } from 'rxjs/operators';
import { RemoteData } from '../../../core/data/remote-data';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
import { Collection } from '../../../core/shared/collection.model';
import { hasValue } from '../../../shared/empty.util';
/** /**
* Component for managing a collection's curation tasks * Component for managing a collection's curation tasks
@@ -8,5 +15,26 @@ import { Component } from '@angular/core';
templateUrl: './collection-curate.component.html', templateUrl: './collection-curate.component.html',
}) })
export class CollectionCurateComponent { export class CollectionCurateComponent {
/* TODO: Implement Collection Edit - Curate */ dsoRD$: Observable<RemoteData<Collection>>;
collectionName$: Observable<string>;
constructor(
private route: ActivatedRoute,
private dsoNameService: DSONameService,
) {
}
ngOnInit(): void {
this.dsoRD$ = this.route.parent.data.pipe(
take(1),
map((data) => data.dso),
);
this.collectionName$ = this.dsoRD$.pipe(
filter((rd: RemoteData<Collection>) => hasValue(rd)),
map((rd: RemoteData<Collection>) => {
return this.dsoNameService.getName(rd.payload);
})
);
}
} }

View File

@@ -0,0 +1,6 @@
<div class="container">
<h3>{{'community.curate.header' |translate:{community: (communityName$ |async)} }}</h3>
<ds-curation-form
[dsoHandle]="(dsoRD$|async)?.payload.handle"
></ds-curation-form>
</div>

View File

@@ -0,0 +1,69 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
import { ActivatedRoute } from '@angular/router';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
import { CommunityCurateComponent } from './community-curate.component';
import { Community } from '../../../core/shared/community.model';
describe('CommunityCurateComponent', () => {
let comp: CommunityCurateComponent;
let fixture: ComponentFixture<CommunityCurateComponent>;
let debugEl: DebugElement;
let routeStub;
let dsoNameService;
const community = Object.assign(new Community(), {
handle: '123456789/1', metadata: {'dc.title': ['Community Name']}
});
beforeEach(async(() => {
routeStub = {
parent: {
data: observableOf({
dso: createSuccessfulRemoteDataObject(community)
})
}
};
dsoNameService = jasmine.createSpyObj('dsoNameService', {
getName: 'Community Name'
});
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [CommunityCurateComponent],
providers: [
{provide: ActivatedRoute, useValue: routeStub},
{provide: DSONameService, useValue: dsoNameService}
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CommunityCurateComponent);
comp = fixture.componentInstance;
debugEl = fixture.debugElement;
fixture.detectChanges();
});
describe('init', () => {
it('should initialise the comp', () => {
expect(comp).toBeDefined();
expect(debugEl.nativeElement.innerHTML).toContain('ds-curation-form');
});
it('should contain the community information provided in the route', () => {
comp.dsoRD$.subscribe((value) => {
expect(value.payload.handle
).toEqual('123456789/1');
});
comp.communityName$.subscribe((value) => {
expect(value).toEqual('Community Name');
});
});
});
});

View File

@@ -1,4 +1,12 @@
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Community } from '../../../core/shared/community.model';
import { ActivatedRoute } from '@angular/router';
import { map, take } from 'rxjs/operators';
import { RemoteData } from '../../../core/data/remote-data';
import { Observable } from 'rxjs';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
import { hasValue } from '../../../shared/empty.util';
import { filter } from 'rxjs/internal/operators/filter';
/** /**
* Component for managing a community's curation tasks * Component for managing a community's curation tasks
@@ -7,6 +15,29 @@ import { Component } from '@angular/core';
selector: 'ds-community-curate', selector: 'ds-community-curate',
templateUrl: './community-curate.component.html', templateUrl: './community-curate.component.html',
}) })
export class CommunityCurateComponent { export class CommunityCurateComponent implements OnInit {
/* TODO: Implement Community Edit - Curate */
dsoRD$: Observable<RemoteData<Community>>;
communityName$: Observable<string>;
constructor(
private route: ActivatedRoute,
private dsoNameService: DSONameService,
) {
}
ngOnInit(): void {
this.dsoRD$ = this.route.parent.data.pipe(
take(1),
map((data) => data.dso),
);
this.communityName$ = this.dsoRD$.pipe(
filter((rd: RemoteData<Community>) => hasValue(rd)),
map((rd: RemoteData<Community>) => {
return this.dsoNameService.getName(rd.payload);
})
);
}
} }

View File

@@ -0,0 +1,20 @@
<form [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group">
<div class="row mb-2">
<div class="col-12 col-sm-6">
<label class="font-weight-bold" for="task">{{'curation.form.task-select.label' |translate }}</label>
<select id="task" formControlName="task" class="form-control">
<option *ngFor="let task of tasks" [ngValue]="task">
{{ task.label | translate }}
</option>
</select>
</div>
<div *ngIf="!hasHandleValue()" class="col-12 col-sm-6">
<label class="font-weight-bold" for="handle">{{'curation.form.handle.label' |translate }}</label>
<input id="handle" class="form-control" formControlName="handle">
<small class="text-muted">{{'curation.form.handle.hint' |translate }}</small>
</div>
</div>
<button class="btn btn-default btn-primary" type="submit">{{'curation.form.submit' |translate }}</button>
</div>
</form>

View File

@@ -0,0 +1,148 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CurationFormComponent } from './curation-form.component';
import { ScriptDataService } from '../core/data/processes/script-data.service';
import { ProcessDataService } from '../core/data/processes/process-data.service';
import { AuthService } from '../core/auth/auth.service';
import { of as observableOf } from 'rxjs';
import { RequestEntry } from '../core/data/request.reducer';
import { DSOSuccessResponse, RestResponse } from '../core/cache/response.models';
import { Process } from '../process-page/processes/process.model';
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
import { EPerson } from '../core/eperson/models/eperson.model';
import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub';
import { RouterStub } from '../shared/testing/router.stub';
import { NotificationsService } from '../shared/notifications/notifications.service';
import { Router } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
describe('CurationFormComponent', () => {
let comp: CurationFormComponent;
let fixture: ComponentFixture<CurationFormComponent>;
let scriptDataService: ScriptDataService;
let processDataService: ProcessDataService;
let authService: AuthService;
let notificationsService;
let router;
const requestEntry = Object.assign(new RequestEntry(),
{response: new DSOSuccessResponse(['process-link'], 200, 'success')});
const failedRequestEntry = Object.assign(new RequestEntry(),
{response: new RestResponse(false, 400, 'Bad Request')});
const process = Object.assign(new Process(), {processId: 'process-id'});
beforeEach(async(() => {
scriptDataService = jasmine.createSpyObj('scriptDataService', {
invoke: observableOf(requestEntry)
});
processDataService = jasmine.createSpyObj('processDataService', {
findByHref: createSuccessfulRemoteDataObject$(process)
});
authService = jasmine.createSpyObj('authService', {
getAuthenticatedUserFromStore: observableOf(Object.assign(new EPerson(), {email: 'test@mail'}))
});
notificationsService = new NotificationsServiceStub();
router = new RouterStub();
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), FormsModule, ReactiveFormsModule],
declarations: [CurationFormComponent],
providers: [
{provide: ScriptDataService, useValue: scriptDataService},
{provide: ProcessDataService, useValue: processDataService},
{provide: AuthService, useValue: authService},
{provide: NotificationsService, useValue: notificationsService},
{provide: Router, useValue: router},
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CurationFormComponent);
comp = fixture.componentInstance;
fixture.detectChanges();
});
describe('init', () => {
it('should initialise the comp and contain the different tasks', () => {
expect(comp).toBeDefined();
const elements = fixture.debugElement.queryAll(By.css('option'));
expect(elements.length).toEqual(3);
expect(elements[0].nativeElement.innerHTML).toContain('curation-task.task.profileformats.label');
expect(elements[1].nativeElement.innerHTML).toContain('curation-task.task.requiredmetadata.label');
expect(elements[2].nativeElement.innerHTML).toContain('curation-task.task.checklinks.label');
});
});
describe('hasHandleValue', () => {
it('should return true when a dsoHandle value was provided', () => {
comp.dsoHandle = 'some-handle';
fixture.detectChanges();
expect(comp.hasHandleValue()).toBeTrue();
});
it('should return false when no dsoHandle value was provided', () => {
expect(comp.hasHandleValue()).toBeFalse();
});
});
describe('submit', () => {
it('should submit the selected process and handle to the scriptservice and navigate to the corresponding process page', () => {
comp.dsoHandle = 'test-handle';
comp.submit();
expect(scriptDataService.invoke).toHaveBeenCalledWith('curate', [
{name: '-t', value: 'profileformats'},
{name: '-i', value: 'test-handle'},
{name: '-e', value: 'test@mail'},
], []);
expect(notificationsService.success).toHaveBeenCalled();
expect(processDataService.findByHref).toHaveBeenCalledWith('process-link');
expect(router.navigate).toHaveBeenCalledWith(['/processes', 'process-id']);
});
it('should the selected process and handle to the scriptservice and stay on the page on error', () => {
(scriptDataService.invoke as jasmine.Spy).and.returnValue(observableOf(failedRequestEntry));
comp.dsoHandle = 'test-handle';
comp.submit();
expect(scriptDataService.invoke).toHaveBeenCalledWith('curate', [
{name: '-t', value: 'profileformats'},
{name: '-i', value: 'test-handle'},
{name: '-e', value: 'test@mail'},
], []);
expect(notificationsService.error).toHaveBeenCalled();
expect(processDataService.findByHref).not.toHaveBeenCalled();
expect(router.navigate).not.toHaveBeenCalled();
});
});
it('should use the handle provided by the form when no dsoHandle is provided', () => {
comp.form.get('handle').patchValue('form-handle');
comp.submit();
expect(scriptDataService.invoke).toHaveBeenCalledWith('curate', [
{name: '-t', value: 'profileformats'},
{name: '-i', value: 'form-handle'},
{name: '-e', value: 'test@mail'},
], []);
});
it('should use "all" when the handle provided by the form is empty and when no dsoHandle is provided', () => {
comp.submit();
expect(scriptDataService.invoke).toHaveBeenCalledWith('curate', [
{name: '-t', value: 'profileformats'},
{name: '-i', value: 'all'},
{name: '-e', value: 'test@mail'},
], []);
});
});

View File

@@ -0,0 +1,103 @@
import { Component, Input, OnInit } from '@angular/core';
import { ScriptDataService } from '../core/data/processes/script-data.service';
import { environment } from '../../environments/environment';
import { CurationTask } from '../../config/curation-task.interface';
import { FormControl, FormGroup } from '@angular/forms';
import { getResponseFromEntry } from '../core/shared/operators';
import { DSOSuccessResponse } from '../core/cache/response.models';
import { AuthService } from '../core/auth/auth.service';
import { filter, switchMap, take } from 'rxjs/operators';
import { EPerson } from '../core/eperson/models/eperson.model';
import { NotificationsService } from '../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { hasValue, isEmpty } from '../shared/empty.util';
import { RemoteData } from '../core/data/remote-data';
import { Router } from '@angular/router';
import { ProcessDataService } from '../core/data/processes/process-data.service';
import { Process } from '../process-page/processes/process.model';
/**
* Component responsible for rendering the Curation Task form
*/
@Component({
selector: 'ds-curation-form',
templateUrl: './curation-form.component.html'
})
export class CurationFormComponent implements OnInit {
tasks: CurationTask[];
form: FormGroup;
@Input()
dsoHandle: string;
constructor(
private scriptDataService: ScriptDataService,
private processDataService: ProcessDataService,
private authService: AuthService,
private notificationsService: NotificationsService,
private translateService: TranslateService,
private router: Router
) {
}
ngOnInit(): void {
this.tasks = environment.curationTasks;
this.form = new FormGroup({
task: new FormControl(this.tasks[0]),
handle: new FormControl('')
});
}
/**
* Determines whether the inputted dsoHandle has a value
*/
hasHandleValue() {
if (hasValue(this.dsoHandle)) {
return true;
}
return false;
}
/**
* Submit the selected taskName and handle to the script data service to run the corresponding curation script
* Navigate to the process page on success
*/
submit() {
const taskName = (this.form.get('task').value as CurationTask).name;
let handle;
if (this.hasHandleValue()) {
handle = this.dsoHandle;
} else {
handle = this.form.get('handle').value;
if (isEmpty(handle)) {
handle = 'all';
}
}
this.authService.getAuthenticatedUserFromStore().pipe(
take(1),
switchMap((eperson: EPerson) => {
return this.scriptDataService.invoke('curate', [
{name: '-t', value: taskName},
{name: '-i', value: handle},
{name: '-e', value: eperson.email},
], []).pipe(getResponseFromEntry());
})
).subscribe((response: DSOSuccessResponse) => {
if (response.isSuccessful) {
this.notificationsService.success(this.translateService.get('curation.form.submit.success.head'),
this.translateService.get('curation.form.submit.success.content'));
this.processDataService.findByHref(response.resourceSelfLinks[0]).pipe(
filter((processRD: RemoteData<Process>) => hasValue(processRD) && hasValue(processRD.payload)),
take(1))
.subscribe((processRD: RemoteData<Process>) => {
this.router.navigate(['/processes', processRD.payload.processId]);
});
} else {
this.notificationsService.error(this.translateService.get('curation.form.submit.error.head'),
this.translateService.get('curation.form.submit.error.content'));
}
});
}
}

View File

@@ -16,7 +16,9 @@
<div class="mb-4"> <div class="mb-4">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
<a *ngIf="!hideReturnButton" [routerLink]="getPageUrl((dsoRD$ | async)?.payload)" class="btn btn-outline-secondary">{{ type + '.edit.return' | translate }}</a> <div class="col-12">
<a *ngIf="!hideReturnButton" [routerLink]="getPageUrl((dsoRD$ | async)?.payload)" class="btn btn-outline-secondary">{{ type + '.edit.return' | translate }}</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -207,6 +207,7 @@ import { GroupSearchBoxComponent } from './resource-policies/form/eperson-group-
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component'; import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component'; import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
import { DsSelectComponent } from './ds-select/ds-select.component'; import { DsSelectComponent } from './ds-select/ds-select.component';
import { CurationFormComponent } from '../curation-form/curation-form.component';
const MODULES = [ const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here // Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -469,6 +470,7 @@ const ENTRY_COMPONENTS = [
ClaimedTaskActionsReturnToPoolComponent, ClaimedTaskActionsReturnToPoolComponent,
ClaimedTaskActionsEditMetadataComponent, ClaimedTaskActionsEditMetadataComponent,
FileDownloadLinkComponent, FileDownloadLinkComponent,
CurationFormComponent,
]; ];
const SHARED_ITEM_PAGE_COMPONENTS = [ const SHARED_ITEM_PAGE_COMPONENTS = [
@@ -526,7 +528,8 @@ const DIRECTIVES = [
...PIPES, ...PIPES,
...COMPONENTS, ...COMPONENTS,
...SHARED_ITEM_PAGE_COMPONENTS, ...SHARED_ITEM_PAGE_COMPONENTS,
...DIRECTIVES ...DIRECTIVES,
CurationFormComponent
], ],
entryComponents: [ entryComponents: [
...ENTRY_COMPONENTS ...ENTRY_COMPONENTS

View File

@@ -14,7 +14,11 @@
"404.page-not-found": "page not found", "404.page-not-found": "page not found",
"admin.curation-tasks.breadcrumbs": "System curation tasks",
"admin.curation-tasks.title": "System curation tasks",
"admin.curation-tasks.header": "System curation tasks",
"admin.registries.bitstream-formats.breadcrumbs": "Format registry", "admin.registries.bitstream-formats.breadcrumbs": "Format registry",
@@ -560,6 +564,8 @@
"collection.create.sub-head": "Create a Collection for Community {{ parent }}", "collection.create.sub-head": "Create a Collection for Community {{ parent }}",
"collection.curate.header": "Curate Collection: {{collection}}",
"collection.delete.cancel": "Cancel", "collection.delete.cancel": "Cancel",
"collection.delete.confirm": "Confirm", "collection.delete.confirm": "Confirm",
@@ -770,6 +776,8 @@
"community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}",
"community.curate.header": "Curate Community: {{community}}",
"community.delete.cancel": "Cancel", "community.delete.cancel": "Cancel",
"community.delete.confirm": "Confirm", "community.delete.confirm": "Confirm",
@@ -909,6 +917,32 @@
"curation-task.task.profileformats.label": "Profile Bitstream Formats",
"curation-task.task.requiredmetadata.label": "Check for Required Metadata",
"curation-task.task.checklinks.label": "Check Links in Metadata",
"curation.form.task-select.label": "Task: *",
"curation.form.submit": "Start",
"curation.form.submit.success.head": "The curation task has been started successfully",
"curation.form.submit.success.content": "You will be redirected to the corresponding process page.",
"curation.form.submit.error.head": "Running the curation task failed",
"curation.form.submit.error.content": "An error occured when trying to start the curation task.",
"curation.form.handle.label": "Handle of DSpace Object: *",
"curation.form.handle.hint": "Hint: Enter [your-handle-prefix]/0 to run a task across entire site (not all tasks may support this capability)",
"dso-selector.create.collection.head": "New collection", "dso-selector.create.collection.head": "New collection",
"dso-selector.create.community.head": "New community", "dso-selector.create.community.head": "New community",

View File

@@ -0,0 +1,9 @@
import { Config } from './config.interface';
/**
* An interface to represent a curation task in the configuration. A CurationTask has a name and a label.
*/
export interface CurationTask extends Config {
name: string;
label: string;
}

View File

@@ -11,6 +11,7 @@ import { ItemPageConfig } from './item-page-config.interface';
import { CollectionPageConfig } from './collection-page-config.interface'; import { CollectionPageConfig } from './collection-page-config.interface';
import { Theme } from './theme.inferface'; import { Theme } from './theme.inferface';
import {AuthConfig} from './auth-config.interfaces'; import {AuthConfig} from './auth-config.interfaces';
import { CurationTask } from './curation-task.interface';
export interface GlobalConfig extends Config { export interface GlobalConfig extends Config {
ui: ServerConfig; ui: ServerConfig;
@@ -31,4 +32,5 @@ export interface GlobalConfig extends Config {
item: ItemPageConfig; item: ItemPageConfig;
collection: CollectionPageConfig; collection: CollectionPageConfig;
theme: Theme; theme: Theme;
curationTasks: CurationTask[];
} }

View File

@@ -212,5 +212,19 @@ export const environment: GlobalConfig = {
}, },
theme: { theme: {
name: 'default', name: 'default',
} },
curationTasks: [
{
name: 'profileformats',
label: 'curation-task.task.profileformats.label'
},
{
name: 'requiredmetadata',
label: 'curation-task.task.requiredmetadata.label'
},
{
name: 'checklinks',
label: 'curation-task.task.checklinks.label'
}
]
}; };

View File

@@ -195,5 +195,19 @@ export const environment: Partial<GlobalConfig> = {
}, },
theme: { theme: {
name: 'default', name: 'default',
} },
curationTasks: [
{
name: 'profileformats',
label: 'curation-task.task.profileformats.label'
},
{
name: 'requiredmetadata',
label: 'curation-task.task.requiredmetadata.label'
},
{
name: 'checklinks',
label: 'curation-task.task.checklinks.label'
}
]
}; };