Skip to content

Commit 5ec1ff3

Browse files
Mattia Vianellivins01-4science
authored andcommitted
Merged in DSC-1111-latest-version-maintenance (pull request DSpace#1409)
DSC-1111 latest version maintenance Approved-by: Vincenzo Mecca
2 parents a77762a + d8501ae commit 5ec1ff3

12 files changed

Lines changed: 297 additions & 210 deletions

File tree

src/app/collection-page/collection-form/collection-form.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import { Collection } from '../../core/shared/collection.model';
1414
import { ComColFormComponent } from '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component';
1515
import { NotificationsService } from '../../shared/notifications/notifications.service';
16-
import { CommunityDataService } from '../../core/data/community-data.service';
16+
import { CollectionDataService } from '../../core/data/collection-data.service';
1717
import { AuthService } from '../../core/auth/auth.service';
1818
import { RequestService } from '../../core/data/request.service';
1919
import { ObjectCacheService } from '../../core/cache/object-cache.service';
@@ -34,7 +34,7 @@ import { SubmissionDefinitionsConfigDataService } from '../../core/config/submis
3434
import { ConfigObject } from '../../core/config/models/config.model';
3535
import { NONE_ENTITY_TYPE } from '../../core/shared/item-relationships/item-type.resource-type';
3636
import { hasNoValue, isNotNull } from 'src/app/shared/empty.util';
37-
37+
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
3838

3939
/**
4040
* Form used for creating and editing collections
@@ -85,13 +85,14 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
8585
protected translate: TranslateService,
8686
protected notificationsService: NotificationsService,
8787
protected authService: AuthService,
88-
protected dsoService: CommunityDataService,
88+
protected dsoService: CollectionDataService,
8989
protected requestService: RequestService,
9090
protected objectCache: ObjectCacheService,
9191
protected entityTypeService: EntityTypeDataService,
9292
protected chd: ChangeDetectorRef,
93+
protected modalService: NgbModal,
9394
protected submissionDefinitionService: SubmissionDefinitionsConfigDataService) {
94-
super(formService, translate, notificationsService, authService, requestService, objectCache);
95+
super(formService, translate, notificationsService, authService, requestService, objectCache, modalService);
9596
}
9697

9798
ngOnInit(): void {

src/app/collection-page/create-collection-page/create-collection-page.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ <h2 id="sub-header" class="border-bottom pb-2">{{'collection.create.sub-head' |
55
</div>
66
</div>
77
<ds-collection-form (submitForm)="onSubmit($event)"
8+
[isCreation]="true"
89
(back)="navigateToHome()"
910
(finish)="navigateToNewPage()"></ds-collection-form>
1011
</div>

src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
</div>
1818
</div>
1919
<ds-collection-form [dso]="(dsoRD$ | async)?.payload"
20+
[isCreation]="false"
2021
(submitForm)="onSubmit($event)"
2122
(back)="navigateToHomePage()"
2223
(finish)="navigateToHomePage()"></ds-collection-form>

src/app/community-page/community-form/community-form.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { AuthService } from '../../core/auth/auth.service';
1414
import { RequestService } from '../../core/data/request.service';
1515
import { ObjectCacheService } from '../../core/cache/object-cache.service';
1616
import { environment } from '../../../environments/environment';
17+
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
1718

1819
/**
1920
* Form used for creating and editing communities
@@ -78,8 +79,9 @@ export class CommunityFormComponent extends ComColFormComponent<Community> imple
7879
protected authService: AuthService,
7980
protected dsoService: CommunityDataService,
8081
protected requestService: RequestService,
81-
protected objectCache: ObjectCacheService) {
82-
super(formService, translate, notificationsService, authService, requestService, objectCache);
82+
protected objectCache: ObjectCacheService,
83+
protected modalService: NgbModal) {
84+
super(formService, translate, notificationsService, authService, requestService, objectCache, modalService);
8385
}
8486

8587
ngOnChanges(changes: SimpleChanges) {

src/app/community-page/create-community-page/create-community-page.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
<div class="row">
33
<div class="col-12 pb-4">
44
<ng-container *ngVar="(parentRD$ | async)?.payload as parent">
5-
<h2 *ngIf="!parent" id="header" class="border-bottom pb-2">{{ 'community.create.head' | translate }}</h2>
5+
<h2 *ngIf="!parent" id="header" class="border-bottom p-2">{{ 'community.create.head' | translate }}</h2>
66
<h2 *ngIf="parent" id="sub-header" class="border-bottom pb-2">{{ 'community.create.sub-head' | translate:{ parent: dsoNameService.getName(parent) } }}</h2>
77
</ng-container>
88
</div>
99
</div>
1010
<ds-community-form (submitForm)="onSubmit($event)"
11+
[isCreation]="true"
1112
(back)="navigateToHome()"
1213
(finish)="navigateToNewPage()"></ds-community-form>
1314
</div>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<ds-community-form [dso]="(dsoRD$ | async)?.payload"
2+
[isCreation]="false"
23
(submitForm)="onSubmit($event)"
34
(back)="navigateToHomePage()"
45
(finish)="navigateToHomePage()"></ds-community-form>
5-

src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,17 @@
44
<label>{{type.value + '.edit.logo.label' | translate}}</label>
55
</div>
66
<ng-container *ngVar="(dso?.logo | async)?.payload as logo">
7-
<div class="col-12 d-inline-block alert" [ngClass]="{'alert-danger': markLogoForDeletion}" id="logo-section" *ngIf="logo">
7+
<div class="col-12 d-inline-block alert" id="logo-section" *ngIf="logo">
88
<div class="row">
99
<div class="col-8 d-inline-block">
1010
<ds-comcol-page-logo [logo]="logo"></ds-comcol-page-logo>
1111
</div>
1212
<div class="col-4 d-inline-block">
13-
<div *ngIf="logo" class="btn-group btn-group-sm float-right" role="group">
14-
<button *ngIf="!markLogoForDeletion" type="button" class="btn btn-danger"
15-
title="{{type.value + '.edit.logo.delete.title' | translate}}"
16-
(click)="deleteLogo()">
17-
<i class="fas fa-trash" aria-hidden="true"></i>
18-
</button>
19-
<button *ngIf="markLogoForDeletion" type="button" class="btn btn-warning"
20-
title="{{type.value + '.edit.logo.delete-undo.title' | translate}}"
21-
(click)="undoDeleteLogo()">
22-
<i class="fas fa-undo" aria-hidden="true"></i>
13+
<div *ngIf="logo" class="float-right">
14+
<button
15+
(click)="confirmLogoDeleteWithModal()"
16+
class="btn btn-danger"
17+
type="button">{{ 'community.edit.logo.delete.title' | translate }}
2318
</button>
2419
</div>
2520
</div>
@@ -42,7 +37,8 @@
4237
[formModel]="formModel"
4338
[displayCancel]="false"
4439
(submitForm)="onSubmit()">
45-
<button before (click)="back.emit()" class="btn btn-outline-secondary" type="button">
40+
<button (click)="back.emit()" before class="btn btn-outline-secondary" type="button">
4641
<i class="fas fa-arrow-left"></i> {{ type.value + '.edit.return' | translate }}
4742
</button>
4843
</ds-form>
44+

src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts

Lines changed: 53 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { NotificationsServiceStub } from '../../../testing/notifications-service
1919
import { VarDirective } from '../../../utils/var.directive';
2020
import { ComColFormComponent } from './comcol-form.component';
2121
import { Operation } from 'fast-json-patch';
22-
import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils';
22+
import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils';
2323

2424
describe('ComColFormComponent', () => {
2525
let comp: ComColFormComponent<any>;
@@ -61,7 +61,8 @@ describe('ComColFormComponent', () => {
6161
const logoEndpoint = 'rest/api/logo/endpoint';
6262
const dsoService = Object.assign({
6363
getLogoEndpoint: () => observableOf(logoEndpoint),
64-
deleteLogo: () => createSuccessfulRemoteDataObject$({})
64+
deleteLogo: () => createSuccessfulRemoteDataObject$({}),
65+
findById: () => createSuccessfulRemoteDataObject$({})
6566
});
6667
const notificationsService = new NotificationsServiceStub();
6768

@@ -70,7 +71,8 @@ describe('ComColFormComponent', () => {
7071
/* eslint-enable no-empty, @typescript-eslint/no-empty-function */
7172

7273
const requestServiceStub = jasmine.createSpyObj('requestService', {
73-
removeByHrefSubstring: {}
74+
removeByHrefSubstring: {},
75+
setStaleByHrefSubstring: {}
7476
});
7577
const objectCacheStub = jasmine.createSpyObj('objectCache', {
7678
remove: {}
@@ -148,8 +150,6 @@ describe('ComColFormComponent', () => {
148150
type: Community.type,
149151
}
150152
),
151-
uploader: undefined,
152-
deleteLogo: false,
153153
operations: operations,
154154
}
155155
);
@@ -158,32 +158,22 @@ describe('ComColFormComponent', () => {
158158

159159
describe('onCompleteItem', () => {
160160
beforeEach(() => {
161-
spyOn(comp.finish, 'emit');
162161
comp.onCompleteItem();
163162
});
164163

165164
it('should show a success notification', () => {
166165
expect(notificationsService.success).toHaveBeenCalled();
167166
});
168-
169-
it('should emit finish', () => {
170-
expect(comp.finish.emit).toHaveBeenCalled();
171-
});
172167
});
173168

174169
describe('onUploadError', () => {
175170
beforeEach(() => {
176-
spyOn(comp.finish, 'emit');
177171
comp.onUploadError();
178172
});
179173

180174
it('should show an error notification', () => {
181175
expect(notificationsService.error).toHaveBeenCalled();
182176
});
183-
184-
it('should emit finish', () => {
185-
expect(comp.finish.emit).toHaveBeenCalled();
186-
});
187177
});
188178
});
189179

@@ -204,6 +194,11 @@ describe('ComColFormComponent', () => {
204194
it('should initialize the uploadFilesOptions with a POST method', () => {
205195
expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.POST);
206196
});
197+
198+
it('should not show the delete logo button', () => {
199+
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
200+
expect(button).toBeFalsy();
201+
});
207202
});
208203

209204
describe('and the dso contains a logo', () => {
@@ -222,96 +217,71 @@ describe('ComColFormComponent', () => {
222217
expect(comp.uploadFilesOptions.url).toEqual(logoEndpoint);
223218
});
224219

225-
it('should initialize the uploadFilesOptions with a PUT method', () => {
226-
expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.PUT);
220+
it('should show the delete logo button', () => {
221+
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
222+
expect(button).toBeTruthy();
227223
});
228224

229-
describe('submit with logo marked for deletion', () => {
225+
describe('when the delete logo button is clicked', () => {
230226
beforeEach(() => {
231-
spyOn(dsoService, 'deleteLogo').and.callThrough();
232-
comp.markLogoForDeletion = true;
233-
});
234-
235-
it('should call dsoService.deleteLogo on the DSO', () => {
236-
comp.onSubmit();
227+
spyOn(dsoService, 'deleteLogo').and.returnValue(createSuccessfulRemoteDataObject$({}));
228+
spyOn(comp, 'handleLogoDeletion').and.callThrough();
229+
spyOn(comp, 'createConfirmationModal').and.callThrough();
230+
spyOn(comp, 'subscribeToConfirmationResponse').and.callThrough();
231+
const deleteButton = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
232+
deleteButton.nativeElement.click();
237233
fixture.detectChanges();
238-
239-
expect(dsoService.deleteLogo).toHaveBeenCalledWith(comp.dso);
240234
});
241235

242-
describe('when dsoService.deleteLogo returns a successful response', () => {
243-
beforeEach(() => {
244-
dsoService.deleteLogo.and.returnValue(createSuccessfulRemoteDataObject$({}));
245-
comp.onSubmit();
246-
});
236+
it('should create a confirmation modal with the correct labels and properties', () => {
237+
const modalServiceSpy = spyOn((comp as any).modalService, 'open').and.callThrough();
247238

248-
it('should display a success notification', () => {
249-
expect(notificationsService.success).toHaveBeenCalled();
250-
});
251-
});
239+
const modalRef = comp.createConfirmationModal();
252240

253-
describe('when dsoService.deleteLogo returns an error response', () => {
254-
beforeEach(() => {
255-
dsoService.deleteLogo.and.returnValue(createFailedRemoteDataObject$('Error', 500));
256-
comp.onSubmit();
257-
});
241+
expect(modalServiceSpy).toHaveBeenCalled();
258242

259-
it('should display an error notification', () => {
260-
expect(notificationsService.error).toHaveBeenCalled();
261-
});
262-
});
263-
});
243+
expect(modalRef).toBeDefined();
244+
expect(modalRef.componentInstance).toBeDefined();
264245

265-
describe('deleteLogo', () => {
266-
beforeEach(() => {
267-
comp.deleteLogo();
268-
fixture.detectChanges();
246+
expect(modalRef.componentInstance.headerLabel).toBe('community-collection.edit.logo.delete.title');
247+
expect(modalRef.componentInstance.infoLabel).toBe('confirmation-modal.delete-community-collection-logo.info');
248+
expect(modalRef.componentInstance.cancelLabel).toBe('form.cancel');
249+
expect(modalRef.componentInstance.confirmLabel).toBe('community-collection.edit.logo.delete.title');
250+
expect(modalRef.componentInstance.confirmIcon).toBe('fas fa-trash');
269251
});
270252

271-
it('should set markLogoForDeletion to true', () => {
272-
expect(comp.markLogoForDeletion).toEqual(true);
253+
it('should call createConfirmationModal method', () => {
254+
expect(comp.createConfirmationModal).toHaveBeenCalled();
273255
});
274256

275-
it('should mark the logo section with a danger alert', () => {
276-
const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger'));
277-
expect(logoSection).toBeTruthy();
257+
it('should call subscribeToConfirmationResponse method', () => {
258+
expect(comp.subscribeToConfirmationResponse).toHaveBeenCalled();
278259
});
279260

280-
it('should hide the delete button', () => {
281-
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
282-
expect(button).not.toBeTruthy();
283-
});
261+
describe('when the modal is closed', () => {
284262

285-
it('should show the undo button', () => {
286-
const button = fixture.debugElement.query(By.css('#logo-section .btn-warning'));
287-
expect(button).toBeTruthy();
288-
});
289-
});
263+
let modalRef;
290264

291-
describe('undoDeleteLogo', () => {
292-
beforeEach(() => {
293-
comp.markLogoForDeletion = true;
294-
comp.undoDeleteLogo();
295-
fixture.detectChanges();
296-
});
265+
beforeEach(() => {
266+
modalRef = comp.createConfirmationModal();
267+
comp.subscribeToConfirmationResponse(modalRef);
268+
});
297269

298-
it('should set markLogoForDeletion to false', () => {
299-
expect(comp.markLogoForDeletion).toEqual(false);
300-
});
270+
it('should call handleLogoDeletion and dsoService.deleteLogo methods when deletion is confirmed', waitForAsync(() => {
271+
modalRef.componentInstance.confirmPressed();
301272

302-
it('should disable the danger alert on the logo section', () => {
303-
const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger'));
304-
expect(logoSection).not.toBeTruthy();
305-
});
273+
expect(comp.handleLogoDeletion).toHaveBeenCalled();
274+
expect(dsoService.deleteLogo).toHaveBeenCalled();
306275

307-
it('should show the delete button', () => {
308-
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
309-
expect(button).toBeTruthy();
310-
});
276+
}));
277+
278+
it('should not call handleLogoDeletion and dsoService.deleteLogo methods when deletion is refused', waitForAsync(() => {
279+
modalRef.componentInstance.cancelPressed();
280+
281+
expect(comp.handleLogoDeletion).not.toHaveBeenCalled();
282+
expect(dsoService.deleteLogo).not.toHaveBeenCalled();
283+
}));
311284

312-
it('should hide the undo button', () => {
313-
const button = fixture.debugElement.query(By.css('#logo-section .btn-warning'));
314-
expect(button).not.toBeTruthy();
315285
});
316286
});
317287
});

0 commit comments

Comments
 (0)