From 1903530f77cf2ab83089aeb16a9b38185b7ecdee Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 19 Oct 2020 12:36:18 +0200 Subject: [PATCH] 74179: Deleting groups notifications, authorisation check, button on edit group page --- .../group-form/group-form.component.html | 5 + .../group-form/group-form.component.spec.ts | 6 ++ .../group-form/group-form.component.ts | 67 ++++++++++++- .../groups-registry.component.html | 26 ++--- .../groups-registry.component.spec.ts | 8 +- .../groups-registry.component.ts | 96 +++++++++++++++---- src/app/core/eperson/group-data.service.ts | 11 ++- .../core/eperson/models/group-dto.model.ts | 17 ++++ src/assets/i18n/en.json5 | 20 +++- 9 files changed, 215 insertions(+), 41 deletions(-) create mode 100644 src/app/core/eperson/models/group-dto.model.ts diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html index 2f76e45429..2742b1db50 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html +++ b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html @@ -9,6 +9,11 @@ +
+ +

{{messagePrefix + '.head.edit' | translate}}

diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts index 5878500f1d..eab9114900 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts @@ -14,6 +14,7 @@ import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-d import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { RestResponse } from '../../../../core/cache/response.models'; import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service'; +import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { RemoteData } from '../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; @@ -40,6 +41,7 @@ describe('GroupFormComponent', () => { let builderService: FormBuilderService; let ePersonDataServiceStub: any; let groupsDataServiceStub: any; + let authorizationService: AuthorizationDataService; let router; let groups; @@ -88,6 +90,9 @@ describe('GroupFormComponent', () => { return createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])) } }; + authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) + }); builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); router = new RouterMock(); @@ -115,6 +120,7 @@ describe('GroupFormComponent', () => { { provide: HALEndpointService, useValue: {} }, { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }), params: observableOf({}) } }, { provide: Router, useValue: router }, + { provide: AuthorizationDataService, useValue: authorizationService }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts index d81eac1e92..55d520cafb 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts @@ -1,6 +1,7 @@ import { Component, EventEmitter, HostListener, OnDestroy, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormControlModel, DynamicFormLayout, @@ -8,15 +9,20 @@ import { DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs/internal/Observable'; import { combineLatest } from 'rxjs/internal/observable/combineLatest'; import { Subscription } from 'rxjs/internal/Subscription'; -import { take } from 'rxjs/operators'; +import { switchMap, take } from 'rxjs/operators'; import { RestResponse } from '../../../../core/cache/response.models'; +import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; import { PaginatedList } from '../../../../core/data/paginated-list'; +import { RequestService } from '../../../../core/data/request.service'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; import { GroupDataService } from '../../../../core/eperson/group-data.service'; import { Group } from '../../../../core/eperson/models/group.model'; import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators'; +import { ConfirmationModalComponent } from '../../../../shared/confirmation-modal/confirmation-modal.component'; import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; @@ -89,19 +95,34 @@ export class GroupFormComponent implements OnInit, OnDestroy { */ groupBeingEdited: Group; + /** + * Observable whether or not the logged in user is allowed to delete the Group + */ + canDelete$: Observable; + constructor(public groupDataService: GroupDataService, private ePersonDataService: EPersonDataService, private formBuilderService: FormBuilderService, private translateService: TranslateService, private notificationsService: NotificationsService, private route: ActivatedRoute, - protected router: Router) { + protected router: Router, + private authorizationService: AuthorizationDataService, + private modalService: NgbModal, + public requestService: RequestService) { } ngOnInit() { + this.initialisePage(); + } + + initialisePage() { this.subs.push(this.route.params.subscribe((params) => { this.setActiveGroup(params.groupId) })); + this.canDelete$ = this.groupDataService.getActiveGroup().pipe( + switchMap((group: Group) => this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined)) + ); combineLatest( this.translateService.get(`${this.messagePrefix}.groupName`), this.translateService.get(`${this.messagePrefix}.groupDescription`), @@ -269,6 +290,48 @@ export class GroupFormComponent implements OnInit, OnDestroy { }); } + /** + * Deletes the Group from the Repository. The Group will be the only that this form is showing. + * It'll either show a success or error message depending on whether the delete was successful or not. + */ + delete() { + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((group: Group) => { + const modalRef = this.modalService.open(ConfirmationModalComponent); + modalRef.componentInstance.dso = group; + modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-group.modal.header'; + modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-group.modal.info'; + modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-group.modal.cancel'; + modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-group.modal.confirm'; + modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { + if (confirm) { + if (hasValue(group.id)) { + this.groupDataService.deleteGroup(group).pipe(take(1)) + .subscribe(([success, optionalErrorMessage]: [boolean, string]) => { + if (success) { + this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.deleted.success', { name: group.name })); + this.reset(); + this.onCancel(); + } else { + this.notificationsService.error( + this.translateService.get(this.messagePrefix + '.notification.deleted.failure.title', { name: group.name }), + this.translateService.get(this.messagePrefix + '.notification.deleted.failure.content', { cause: optionalErrorMessage })); + } + }) + }} + }); + }) + } + + /** + * This method will ensure that the page gets reset and that the cache is cleared + */ + reset() { + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((group: Group) => { + this.requestService.removeByHrefSubstring(group.self); + }); + this.initialisePage(); + } + /** * Cancel the current edit when component is destroyed & unsub all subscriptions */ diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html index 3bd7d7ac4f..067f59a4c0 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html @@ -30,10 +30,10 @@ @@ -50,21 +50,21 @@ - - {{group.id}} - {{group.name}} - {{(getMembers(group) | async)?.payload?.totalElements + (getSubgroups(group) | async)?.payload?.totalElements}} + + {{groupDto.group.id}} + {{groupDto.group.name}} + {{(getMembers(groupDto.group) | async)?.payload?.totalElements + (getSubgroups(groupDto.group) | async)?.payload?.totalElements}}
- -
@@ -75,7 +75,7 @@
-