[DURACOM-134] Administer workflow actions fixed

This commit is contained in:
Alisa Ismailati
2023-04-28 18:03:52 +02:00
parent c89adf4f81
commit 2895cfe083
15 changed files with 342 additions and 9 deletions

View File

@@ -11,7 +11,7 @@ import { URLCombiner } from '../../../../../core/url-combiner/url-combiner';
import { WorkspaceItemAdminWorkflowActionsComponent } from './workspace-item-admin-workflow-actions.component'; import { WorkspaceItemAdminWorkflowActionsComponent } from './workspace-item-admin-workflow-actions.component';
import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model';
import { import {
getWorkflowItemDeleteRoute, getWorkspaceItemDeleteRoute,
} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; } from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths';
import { Item } from '../../../../../core/shared/item.model'; import { Item } from '../../../../../core/shared/item.model';
import { RemoteData } from '../../../../../core/data/remote-data'; import { RemoteData } from '../../../../../core/data/remote-data';
@@ -83,7 +83,7 @@ describe('WorkspaceItemAdminWorkflowActionsComponent', () => {
it('should render a delete button with the correct link', () => { it('should render a delete button with the correct link', () => {
const button = fixture.debugElement.query(By.css('a.delete-link')); const button = fixture.debugElement.query(By.css('a.delete-link'));
const link = button.nativeElement.href; const link = button.nativeElement.href;
expect(link).toContain(new URLCombiner(getWorkflowItemDeleteRoute(wsi.id)).toString()); expect(link).toContain(new URLCombiner(getWorkspaceItemDeleteRoute(wsi.id)).toString());
}); });
it('should render a policies button with the correct link', () => { it('should render a policies button with the correct link', () => {

View File

@@ -11,7 +11,7 @@ import {
SupervisionOrderGroupSelectorComponent SupervisionOrderGroupSelectorComponent
} from './supervision-order-group-selector/supervision-order-group-selector.component'; } from './supervision-order-group-selector/supervision-order-group-selector.component';
import { import {
getWorkflowItemDeleteRoute getWorkspaceItemDeleteRoute
} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; } from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths';
import { ITEM_EDIT_AUTHORIZATIONS_PATH } from '../../../../../item-page/edit-item-page/edit-item-page.routing-paths'; import { ITEM_EDIT_AUTHORIZATIONS_PATH } from '../../../../../item-page/edit-item-page/edit-item-page.routing-paths';
import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model';
@@ -105,10 +105,10 @@ export class WorkspaceItemAdminWorkflowActionsComponent implements OnInit {
} }
/** /**
* Returns the path to the delete page of this workflow item * Returns the path to the delete page of this workspace item
*/ */
getDeleteRoute(): string { getDeleteRoute(): string {
return getWorkflowItemDeleteRoute(this.wsi.id); return getWorkspaceItemDeleteRoute(this.wsi.id);
} }
/** /**

View File

@@ -1,5 +1,5 @@
import { URLCombiner } from '../core/url-combiner/url-combiner'; import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getWorkflowItemModuleRoute } from '../app-routing-paths'; import { getWorkflowItemModuleRoute, getWorkspaceItemModuleRoute } from '../app-routing-paths';
export function getWorkflowItemPageRoute(wfiId: string) { export function getWorkflowItemPageRoute(wfiId: string) {
return new URLCombiner(getWorkflowItemModuleRoute(), wfiId).toString(); return new URLCombiner(getWorkflowItemModuleRoute(), wfiId).toString();
@@ -24,8 +24,13 @@ export function getAdvancedWorkflowRoute(wfiId: string) {
return new URLCombiner(getWorkflowItemModuleRoute(), wfiId, ADVANCED_WORKFLOW_PATH).toString(); return new URLCombiner(getWorkflowItemModuleRoute(), wfiId, ADVANCED_WORKFLOW_PATH).toString();
} }
export function getWorkspaceItemDeleteRoute(wsiId: string) {
return new URLCombiner(getWorkspaceItemModuleRoute(), wsiId, WORKSPACE_ITEM_DELETE_PATH).toString();
}
export const WORKFLOW_ITEM_EDIT_PATH = 'edit'; export const WORKFLOW_ITEM_EDIT_PATH = 'edit';
export const WORKFLOW_ITEM_DELETE_PATH = 'delete'; export const WORKFLOW_ITEM_DELETE_PATH = 'delete';
export const WORKFLOW_ITEM_VIEW_PATH = 'view'; export const WORKFLOW_ITEM_VIEW_PATH = 'view';
export const WORKFLOW_ITEM_SEND_BACK_PATH = 'sendback'; export const WORKFLOW_ITEM_SEND_BACK_PATH = 'sendback';
export const ADVANCED_WORKFLOW_PATH = 'advanced'; export const ADVANCED_WORKFLOW_PATH = 'advanced';
export const WORKSPACE_ITEM_DELETE_PATH = 'delete';

View File

@@ -0,0 +1,26 @@
import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { Component } from '@angular/core';
import { WorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page.component';
/**
* Themed wrapper for WorkspaceItemsDeletePageComponent
*/
@Component({
selector: 'ds-themed-workspace-items-delete',
styleUrls: [],
templateUrl: './../../shared/theme-support/themed.component.html'
})
export class ThemedWorkspaceItemsDeletePageComponent extends ThemedComponent<WorkspaceItemsDeletePageComponent> {
protected getComponentName(): string {
return 'WorkspaceItemsDeletePageComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import(`./workspaceitems-delete-page.component`);
}
}

View File

@@ -0,0 +1,24 @@
<div class="container">
<h2>{{ 'workspace-item.delete.header' | translate }}</h2>
<ds-modify-item-overview *ngIf="(dso$ | async)" [item]="(dso$ | async)"></ds-modify-item-overview>
<button class="btn btn-default" (click)="previousPage()">{{ 'workspace-item.delete.button.cancel' | translate }}</button>
<button class="btn btn-danger" (click)="$event.preventDefault();confirmDelete(content)">{{ 'workspace-item.delete.button.confirm' | translate }}</button>
</div>
<ng-template #content let-c="close" let-d="dismiss" id="delete-modal">
<div class="modal-header">
<h4 class="modal-title text-danger">{{ 'workspace-item.delete.header' | translate }}</h4>
<button type="button" id="delete_close" class="close" aria-label="Close" (click)="d('cancel')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>{{ 'submission.general.discard.confirm.info' | translate }}</p>
</div>
<div class="modal-footer">
<button type="button" id="delete_cancel" class="btn btn-secondary"
(click)="c('cancel')">{{ 'submission.general.discard.confirm.cancel' | translate }}</button>
<button type="button" id="delete_confirm" class="btn btn-danger"
(click)="c('ok')">{{ 'submission.general.discard.confirm.submit' | translate }}</button>
</div>
</ng-template>

View File

@@ -0,0 +1,4 @@
:host ::ng-deep ds-modify-item-overview table {
display: inline-table !important;
}

View File

@@ -0,0 +1,110 @@
import { RouteService } from '../..//core/services/route.service';
import { NotificationsService } from '../..//shared/notifications/notifications.service';
import { WorkspaceitemDataService } from '../..//core/submission/workspaceitem-data.service';
import { RouterMock } from './../../shared/mocks/router.mock';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { WorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page.component';
import { ActivatedRoute, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
import { Location } from '@angular/common';
import { of as observableOf } from 'rxjs';
import { routeServiceStub } from '../../shared/testing/route-service.stub';
import { LocationStub } from '../../shared/testing/location.stub';
import { By } from '@angular/platform-browser';
import { ActivatedRouteStub } from 'src/app/shared/testing/active-router.stub';
import { createSuccessfulRemoteDataObject } from 'src/app/shared/remote-data.utils';
import { WorkspaceItem } from 'src/app/core/submission/models/workspaceitem.model';
import { DSpaceObject } from 'src/app/core/shared/dspace-object.model';
describe('WorkspaceitemsDeletePageComponent', () => {
let component: WorkspaceItemsDeletePageComponent;
let fixture: ComponentFixture<WorkspaceItemsDeletePageComponent>;
const workspaceitemDataServiceSpy = jasmine.createSpyObj('WorkspaceitemDataService', {
delete: jasmine.createSpy('delete')
});
const wsi = new WorkspaceItem();
wsi.id = '1234';
const dso = new DSpaceObject();
dso.uuid = '1234';
const translateServiceStub = {
get: () => observableOf('test-message'),
onLangChange: new EventEmitter(),
onTranslationChange: new EventEmitter(),
onDefaultLangChange: new EventEmitter()
};
const modalService = {
open: () => {/** empty */},
};
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [WorkspaceItemsDeletePageComponent],
providers: [
{
provide: ActivatedRoute,
useValue: new ActivatedRouteStub(
{},
{
wsi: createSuccessfulRemoteDataObject(wsi),
dso: createSuccessfulRemoteDataObject(dso),
}
),
},
{ provide: Router, useValue: new RouterMock() },
{
provide: WorkspaceitemDataService,
useValue: workspaceitemDataServiceSpy,
},
{ provide: Location, useValue: new LocationStub() },
{ provide: NgbModal, useValue: modalService },
{
provide: NotificationsService,
useValue: new NotificationsServiceStub(),
},
{ provide: TranslateService, useValue: translateServiceStub },
{ provide: RouteService, useValue: routeServiceStub },
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(WorkspaceItemsDeletePageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should have the current WorkspaceItem', () => {
console.log( (component as any).activatedRoute, 'data wsi');
(component as any).activatedRoute.data.subscribe((data) => {
console.log(data, 'dataaa');
expect(data.wsi.payload.id).toEqual('1234');
});
});
it('should delete the target workspace item', () => {
spyOn((component as any).modalService, 'open').and.returnValue({});
component.confirmDelete(By.css('#delete-modal'));
fixture.detectChanges();
expect((component as any).modalService.open).toHaveBeenCalled();
});
it('should call workspaceItemService.delete', () => {
spyOn(workspaceitemDataServiceSpy, 'delete').and.returnValue(observableOf(createSuccessfulRemoteDataObject({})));
component.sendDeleteRequest();
expect((component as any).workspaceItemService.delete).toHaveBeenCalledWith('1234');
});
});

View File

@@ -0,0 +1,111 @@
import { NotificationsService } from 'src/app/shared/notifications/notifications.service';
import { NoContent } from './../../core/shared/NoContent.model';
import { RouteService } from 'src/app/core/services/route.service';
import { getFirstCompletedRemoteData, getRemoteDataPayload } from './../../core/shared/operators';
import { RemoteData } from 'src/app/core/data/remote-data';
import { Component, OnInit } from '@angular/core';
import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model';
import { Observable, map, switchMap, take } from 'rxjs';
import { ActivatedRoute, Data, Params, Router } from '@angular/router';
import { Location } from '@angular/common';
import { WorkspaceitemDataService } from 'src/app/core/submission/workspaceitem-data.service';
import { TranslateService } from '@ngx-translate/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { DSpaceObject } from 'src/app/core/shared/dspace-object.model';
@Component({
selector: 'ds-workspaceitems-delete-page',
templateUrl: './workspaceitems-delete-page.component.html',
styleUrls: ['./workspaceitems-delete-page.component.scss']
})
export class WorkspaceItemsDeletePageComponent implements OnInit {
/**
* The workspaceitem to delete
*/
public wsi$: Observable<WorkspaceItem>;
/**
* The dspace object
*/
public dso$: Observable<DSpaceObject>;
/**
* The previous query parameters
*/
private previousQueryParameters?: Params;
constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private routeService: RouteService,
private workspaceItemService: WorkspaceitemDataService,
private notificationsService: NotificationsService,
private translationService: TranslateService,
private location: Location,
private modalService: NgbModal,
) { }
ngOnInit(): void {
this.wsi$ = this.activatedRoute.data.pipe(map((data: Data) => data.wsi as RemoteData<WorkspaceItem>), getRemoteDataPayload());
this.dso$ = this.activatedRoute.data.pipe(map((data: Data) => data.dso as RemoteData<WorkspaceItem>), getRemoteDataPayload());
this.previousQueryParameters = (this.location.getState() as { [key: string]: any }).previousQueryParams;
}
/**
* Navigates to the previous url
* If there's not previous url, it continues to the mydspace page instead
*/
previousPage() {
this.routeService.getPreviousUrl().pipe(take(1))
.subscribe((url: string) => {
let params: Params = {};
if (!url) {
url = '/mydspace';
params = this.previousQueryParameters;
}
if (url.split('?').length > 1) {
for (const param of url.split('?')[1].split('&')) {
params[param.split('=')[0]] = decodeURIComponent(param.split('=')[1]);
}
}
void this.router.navigate([url.split('?')[0]], { queryParams: params });
}
);
}
/**
* Open the modal to confirm the deletion of the workspaceitem
*/
public async confirmDelete(content) {
await this.modalService.open(content).result.then(
(result) => {
if (result === 'ok') {
this.sendDeleteRequest();
}
}
);
}
/**
* Delete the target workspaceitem object
*/
sendDeleteRequest() {
this.wsi$.pipe(
switchMap((wsi: WorkspaceItem) => this.workspaceItemService.delete(wsi.id).pipe(
getFirstCompletedRemoteData(),
))
).subscribe((response: RemoteData<NoContent>) => {
if (response.hasSucceeded) {
const title = this.translationService.get('workspace-item.delete.notification.success.title');
const content = this.translationService.get('workspace-item.delete.title');
this.notificationsService.success(title, content);
this.previousPage();
} else {
const title = this.translationService.get('workspace-item.delete.notification.error.title');
const content = this.translationService.get('workspace-item.delete.notification.error.content');
this.notificationsService.error(title, content);
}
});
}
}

View File

@@ -7,6 +7,8 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso
import { ThemedFullItemPageComponent } from '../item-page/full/themed-full-item-page.component'; import { ThemedFullItemPageComponent } from '../item-page/full/themed-full-item-page.component';
import { ItemFromWorkspaceResolver } from './item-from-workspace.resolver'; import { ItemFromWorkspaceResolver } from './item-from-workspace.resolver';
import { WorkspaceItemPageResolver } from './workspace-item-page.resolver'; import { WorkspaceItemPageResolver } from './workspace-item-page.resolver';
import { WorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page/workspaceitems-delete-page.component';
import { ThemedWorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page/themed-workspaceitems-delete-page.component';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -34,7 +36,27 @@ import { WorkspaceItemPageResolver } from './workspace-item-page.resolver';
breadcrumb: I18nBreadcrumbResolver breadcrumb: I18nBreadcrumbResolver
}, },
data: { title: 'workspace-item.view.title', breadcrumbKey: 'workspace-item.view' } data: { title: 'workspace-item.view.title', breadcrumbKey: 'workspace-item.view' }
} },
{
canActivate: [AuthenticatedGuard],
path: 'delete',
component: WorkspaceItemsDeletePageComponent,
resolve: {
dso: ItemFromWorkspaceResolver,
breadcrumb: I18nBreadcrumbResolver
},
data: { title: 'workspace-item.delete', breadcrumbKey: 'workspace-item.delete' }
},
{
canActivate: [AuthenticatedGuard],
path: 'delete',
component: ThemedWorkspaceItemsDeletePageComponent,
resolve: {
dso: ItemFromWorkspaceResolver,
breadcrumb: I18nBreadcrumbResolver
},
data: { title: 'workspace-item.delete', breadcrumbKey: 'workspace-item.delete' }
},
] ]
} }
]) ])

View File

@@ -3,6 +3,8 @@ import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module'; import { SharedModule } from '../shared/shared.module';
import { WorkspaceitemsEditPageRoutingModule } from './workspaceitems-edit-page-routing.module'; import { WorkspaceitemsEditPageRoutingModule } from './workspaceitems-edit-page-routing.module';
import { SubmissionModule } from '../submission/submission.module'; import { SubmissionModule } from '../submission/submission.module';
import { WorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page/workspaceitems-delete-page.component';
import { ThemedWorkspaceItemsDeletePageComponent } from './workspaceitems-delete-page/themed-workspaceitems-delete-page.component';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -11,7 +13,10 @@ import { SubmissionModule } from '../submission/submission.module';
SharedModule, SharedModule,
SubmissionModule, SubmissionModule,
], ],
declarations: [] declarations: [
WorkspaceItemsDeletePageComponent,
ThemedWorkspaceItemsDeletePageComponent,
]
}) })
/** /**
* This module handles all modules that need to access the workspaceitems edit page. * This module handles all modules that need to access the workspaceitems edit page.

View File

@@ -4959,10 +4959,24 @@
"workspace-item.view.title": "Workspace View", "workspace-item.view.title": "Workspace View",
"workspace-item.delete.breadcrumbs": "Workspace Delete",
"workspace-item.delete.header": "Delete workspace item",
"workspace-item.delete.button.confirm": "Delete",
"workspace-item.delete.button.cancel": "Cancel",
"workspace-item.delete.notification.success.title": "Deleted",
"workspace-item.delete.title": "This workspace item was successfully deleted",
"workspace-item.delete.notification.error.title": "Something went wrong",
"workspace-item.delete.notification.error.content": "The workspace item could not be deleted",
"workflow-item.advanced.title": "Advanced workflow", "workflow-item.advanced.title": "Advanced workflow",
"workflow-item.selectrevieweraction.notification.success.title": "Selected reviewer", "workflow-item.selectrevieweraction.notification.success.title": "Selected reviewer",
"workflow-item.selectrevieweraction.notification.success.content": "The reviewer for this workflow item has been successfully selected", "workflow-item.selectrevieweraction.notification.success.content": "The reviewer for this workflow item has been successfully selected",

View File

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { WorkspaceItemsDeletePageComponent as BaseComponent } from '../../../../../app/workspaceitems-edit-page/workspaceitems-delete-page/workspaceitems-delete-page.component';
@Component({
selector: 'ds-workspaceitems-delete-page',
templateUrl: '../../../../../app/workspaceitems-edit-page/workspaceitems-delete-page/workspaceitems-delete-page.component.html',
})
export class WorkspaceItemsDeletePageComponent extends BaseComponent {
}

View File

@@ -145,6 +145,7 @@ import {
MediaViewerVideoComponent MediaViewerVideoComponent
} from './app/item-page/media-viewer/media-viewer-video/media-viewer-video.component'; } from './app/item-page/media-viewer/media-viewer-video/media-viewer-video.component';
import { NgxGalleryModule } from '@kolkov/ngx-gallery'; import { NgxGalleryModule } from '@kolkov/ngx-gallery';
import { WorkspaceItemsDeletePageComponent } from './app/workspace-items-delete-page/workspace-items-delete/workspace-items-delete.component';
const DECLARATIONS = [ const DECLARATIONS = [
FileSectionComponent, FileSectionComponent,
@@ -212,6 +213,7 @@ const DECLARATIONS = [
MediaViewerComponent, MediaViewerComponent,
MediaViewerImageComponent, MediaViewerImageComponent,
MediaViewerVideoComponent, MediaViewerVideoComponent,
WorkspaceItemsDeletePageComponent,
]; ];
@NgModule({ @NgModule({