Skip to content

Commit f59510d

Browse files
authored
Merge pull request DSpace#2837 from 4Science/DURACOM-235
Enhanced community/colletion logo edit
2 parents 74f89f2 + b7d454f commit f59510d

13 files changed

Lines changed: 340 additions & 235 deletions

File tree

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
SimpleChange,
1313
SimpleChanges,
1414
} from '@angular/core';
15+
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
1516
import {
1617
DynamicFormControlModel,
1718
DynamicFormOptionConfig,
@@ -30,7 +31,7 @@ import {
3031

3132
import { AuthService } from '../../core/auth/auth.service';
3233
import { ObjectCacheService } from '../../core/cache/object-cache.service';
33-
import { CommunityDataService } from '../../core/data/community-data.service';
34+
import { CollectionDataService } from '../../core/data/collection-data.service';
3435
import { EntityTypeDataService } from '../../core/data/entity-type-data.service';
3536
import { RequestService } from '../../core/data/request.service';
3637
import { Collection } from '../../core/shared/collection.model';
@@ -95,12 +96,13 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
9596
protected translate: TranslateService,
9697
protected notificationsService: NotificationsService,
9798
protected authService: AuthService,
98-
protected dsoService: CommunityDataService,
99+
protected dsoService: CollectionDataService,
99100
protected requestService: RequestService,
100101
protected objectCache: ObjectCacheService,
101102
protected entityTypeService: EntityTypeDataService,
102-
protected chd: ChangeDetectorRef) {
103-
super(formService, translate, notificationsService, authService, requestService, objectCache);
103+
protected chd: ChangeDetectorRef,
104+
protected modalService: NgbModal) {
105+
super(formService, translate, notificationsService, authService, requestService, objectCache, modalService);
104106
}
105107

106108
ngOnInit(): void {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
</div>
77
</div>
88
<ds-collection-form (submitForm)="onSubmit($event)"
9-
(back)="navigateToHome()"
10-
(finish)="navigateToNewPage()"></ds-collection-form>
9+
[isCreation]="true"
10+
(back)="navigateToHome()"></ds-collection-form>
1111
</div>
1212

1313
<div class="container">

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
@@ -10,6 +10,7 @@ import {
1010
SimpleChange,
1111
SimpleChanges,
1212
} from '@angular/core';
13+
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
1314
import {
1415
DynamicFormControlModel,
1516
DynamicFormService,
@@ -108,8 +109,9 @@ export class CommunityFormComponent extends ComColFormComponent<Community> imple
108109
protected authService: AuthService,
109110
protected dsoService: CommunityDataService,
110111
protected requestService: RequestService,
111-
protected objectCache: ObjectCacheService) {
112-
super(formService, translate, notificationsService, authService, requestService, objectCache);
112+
protected objectCache: ObjectCacheService,
113+
protected modalService: NgbModal) {
114+
super(formService, translate, notificationsService, authService, requestService, objectCache, modalService);
113115
}
114116

115117
ngOnChanges(changes: SimpleChanges) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
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"
77
class="border-bottom pb-2">{{ 'community.create.sub-head' | translate:{ parent: dsoNameService.getName(parent) } }}</h2>
88
</ng-container>
99
</div>
1010
</div>
1111
<ds-community-form (submitForm)="onSubmit($event)"
12-
(back)="navigateToHome()"
13-
(finish)="navigateToNewPage()"></ds-community-form>
12+
[isCreation]="true"
13+
(back)="navigateToHome()"></ds-community-form>
1414
</div>
1515

1616
<div class="container">
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
<span>{{type.value + '.edit.logo.label' | translate}}</span>
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 [alternateText]="type.value + '.logo.alt'" [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>
@@ -43,7 +38,8 @@
4338
[formModel]="formModel"
4439
[displayCancel]="false"
4540
(submitForm)="onSubmit()">
46-
<button before (click)="back.emit()" class="btn btn-outline-secondary" type="button">
41+
<button (click)="back.emit()" before class="btn btn-outline-secondary" type="button">
4742
<i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type.value + '.edit.return' | translate }}
4843
</button>
4944
</ds-form>
45+

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

Lines changed: 51 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@ import { hasValue } from '../../../empty.util';
2929
import { FormComponent } from '../../../form/form.component';
3030
import { AuthServiceMock } from '../../../mocks/auth.service.mock';
3131
import { NotificationsService } from '../../../notifications/notifications.service';
32-
import {
33-
createFailedRemoteDataObject$,
34-
createSuccessfulRemoteDataObject$,
35-
} from '../../../remote-data.utils';
32+
import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils';
3633
import { NotificationsServiceStub } from '../../../testing/notifications-service.stub';
3734
import { UploaderComponent } from '../../../upload/uploader/uploader.component';
3835
import { VarDirective } from '../../../utils/var.directive';
@@ -80,6 +77,7 @@ describe('ComColFormComponent', () => {
8077
const dsoService = Object.assign({
8178
getLogoEndpoint: () => observableOf(logoEndpoint),
8279
deleteLogo: () => createSuccessfulRemoteDataObject$({}),
80+
findById: () => createSuccessfulRemoteDataObject$({}),
8381
});
8482
const notificationsService = new NotificationsServiceStub();
8583

@@ -89,6 +87,7 @@ describe('ComColFormComponent', () => {
8987

9088
const requestServiceStub = jasmine.createSpyObj('requestService', {
9189
removeByHrefSubstring: {},
90+
setStaleByHrefSubstring: {},
9291
});
9392
const objectCacheStub = jasmine.createSpyObj('objectCache', {
9493
remove: {},
@@ -175,8 +174,6 @@ describe('ComColFormComponent', () => {
175174
type: Community.type,
176175
},
177176
),
178-
uploader: undefined,
179-
deleteLogo: false,
180177
operations: operations,
181178
},
182179
);
@@ -185,32 +182,22 @@ describe('ComColFormComponent', () => {
185182

186183
describe('onCompleteItem', () => {
187184
beforeEach(() => {
188-
spyOn(comp.finish, 'emit');
189185
comp.onCompleteItem();
190186
});
191187

192188
it('should show a success notification', () => {
193189
expect(notificationsService.success).toHaveBeenCalled();
194190
});
195-
196-
it('should emit finish', () => {
197-
expect(comp.finish.emit).toHaveBeenCalled();
198-
});
199191
});
200192

201193
describe('onUploadError', () => {
202194
beforeEach(() => {
203-
spyOn(comp.finish, 'emit');
204195
comp.onUploadError();
205196
});
206197

207198
it('should show an error notification', () => {
208199
expect(notificationsService.error).toHaveBeenCalled();
209200
});
210-
211-
it('should emit finish', () => {
212-
expect(comp.finish.emit).toHaveBeenCalled();
213-
});
214201
});
215202
});
216203

@@ -231,6 +218,11 @@ describe('ComColFormComponent', () => {
231218
it('should initialize the uploadFilesOptions with a POST method', () => {
232219
expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.POST);
233220
});
221+
222+
it('should not show the delete logo button', () => {
223+
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
224+
expect(button).toBeFalsy();
225+
});
234226
});
235227

236228
describe('and the dso contains a logo', () => {
@@ -249,96 +241,71 @@ describe('ComColFormComponent', () => {
249241
expect(comp.uploadFilesOptions.url).toEqual(logoEndpoint);
250242
});
251243

252-
it('should initialize the uploadFilesOptions with a PUT method', () => {
253-
expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.PUT);
244+
it('should show the delete logo button', () => {
245+
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
246+
expect(button).toBeTruthy();
254247
});
255248

256-
describe('submit with logo marked for deletion', () => {
249+
describe('when the delete logo button is clicked', () => {
257250
beforeEach(() => {
258-
spyOn(dsoService, 'deleteLogo').and.callThrough();
259-
comp.markLogoForDeletion = true;
260-
});
261-
262-
it('should call dsoService.deleteLogo on the DSO', () => {
263-
comp.onSubmit();
251+
spyOn(dsoService, 'deleteLogo').and.returnValue(createSuccessfulRemoteDataObject$({}));
252+
spyOn(comp, 'handleLogoDeletion').and.callThrough();
253+
spyOn(comp, 'createConfirmationModal').and.callThrough();
254+
spyOn(comp, 'subscribeToConfirmationResponse').and.callThrough();
255+
const deleteButton = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
256+
deleteButton.nativeElement.click();
264257
fixture.detectChanges();
265-
266-
expect(dsoService.deleteLogo).toHaveBeenCalledWith(comp.dso);
267258
});
268259

269-
describe('when dsoService.deleteLogo returns a successful response', () => {
270-
beforeEach(() => {
271-
dsoService.deleteLogo.and.returnValue(createSuccessfulRemoteDataObject$({}));
272-
comp.onSubmit();
273-
});
260+
it('should create a confirmation modal with the correct labels and properties', () => {
261+
const modalServiceSpy = spyOn((comp as any).modalService, 'open').and.callThrough();
274262

275-
it('should display a success notification', () => {
276-
expect(notificationsService.success).toHaveBeenCalled();
277-
});
278-
});
263+
const modalRef = comp.createConfirmationModal();
279264

280-
describe('when dsoService.deleteLogo returns an error response', () => {
281-
beforeEach(() => {
282-
dsoService.deleteLogo.and.returnValue(createFailedRemoteDataObject$('Error', 500));
283-
comp.onSubmit();
284-
});
265+
expect(modalServiceSpy).toHaveBeenCalled();
285266

286-
it('should display an error notification', () => {
287-
expect(notificationsService.error).toHaveBeenCalled();
288-
});
289-
});
290-
});
267+
expect(modalRef).toBeDefined();
268+
expect(modalRef.componentInstance).toBeDefined();
291269

292-
describe('deleteLogo', () => {
293-
beforeEach(() => {
294-
comp.deleteLogo();
295-
fixture.detectChanges();
270+
expect(modalRef.componentInstance.headerLabel).toBe('community-collection.edit.logo.delete.title');
271+
expect(modalRef.componentInstance.infoLabel).toBe('confirmation-modal.delete-community-collection-logo.info');
272+
expect(modalRef.componentInstance.cancelLabel).toBe('form.cancel');
273+
expect(modalRef.componentInstance.confirmLabel).toBe('community-collection.edit.logo.delete.title');
274+
expect(modalRef.componentInstance.confirmIcon).toBe('fas fa-trash');
296275
});
297276

298-
it('should set markLogoForDeletion to true', () => {
299-
expect(comp.markLogoForDeletion).toEqual(true);
277+
it('should call createConfirmationModal method', () => {
278+
expect(comp.createConfirmationModal).toHaveBeenCalled();
300279
});
301280

302-
it('should mark the logo section with a danger alert', () => {
303-
const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger'));
304-
expect(logoSection).toBeTruthy();
281+
it('should call subscribeToConfirmationResponse method', () => {
282+
expect(comp.subscribeToConfirmationResponse).toHaveBeenCalled();
305283
});
306284

307-
it('should hide the delete button', () => {
308-
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
309-
expect(button).not.toBeTruthy();
310-
});
285+
describe('when the modal is closed', () => {
311286

312-
it('should show the undo button', () => {
313-
const button = fixture.debugElement.query(By.css('#logo-section .btn-warning'));
314-
expect(button).toBeTruthy();
315-
});
316-
});
287+
let modalRef;
317288

318-
describe('undoDeleteLogo', () => {
319-
beforeEach(() => {
320-
comp.markLogoForDeletion = true;
321-
comp.undoDeleteLogo();
322-
fixture.detectChanges();
323-
});
289+
beforeEach(() => {
290+
modalRef = comp.createConfirmationModal();
291+
comp.subscribeToConfirmationResponse(modalRef);
292+
});
324293

325-
it('should set markLogoForDeletion to false', () => {
326-
expect(comp.markLogoForDeletion).toEqual(false);
327-
});
294+
it('should call handleLogoDeletion and dsoService.deleteLogo methods when deletion is confirmed', waitForAsync(() => {
295+
modalRef.componentInstance.confirmPressed();
328296

329-
it('should disable the danger alert on the logo section', () => {
330-
const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger'));
331-
expect(logoSection).not.toBeTruthy();
332-
});
297+
expect(comp.handleLogoDeletion).toHaveBeenCalled();
298+
expect(dsoService.deleteLogo).toHaveBeenCalled();
333299

334-
it('should show the delete button', () => {
335-
const button = fixture.debugElement.query(By.css('#logo-section .btn-danger'));
336-
expect(button).toBeTruthy();
337-
});
300+
}));
301+
302+
it('should not call handleLogoDeletion and dsoService.deleteLogo methods when deletion is refused', waitForAsync(() => {
303+
modalRef.componentInstance.cancelPressed();
304+
305+
expect(comp.handleLogoDeletion).not.toHaveBeenCalled();
306+
expect(dsoService.deleteLogo).not.toHaveBeenCalled();
307+
}));
338308

339-
it('should hide the undo button', () => {
340-
const button = fixture.debugElement.query(By.css('#logo-section .btn-warning'));
341-
expect(button).not.toBeTruthy();
342309
});
343310
});
344311
});

0 commit comments

Comments
 (0)