diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 3292ebeb69..5c311715ca 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -290,6 +290,14 @@ "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", + "admin.access-control.groups.form.members-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", + "admin.access-control.groups.form.members-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", @@ -316,6 +324,14 @@ "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "Failed to add subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "Successfully deleted subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "Failed to delete subgroup: \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", "admin.access-control.groups.form.subgroups-list.no-items": "No groups found with this in their name or this as UUID", diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts index 545e23d0bb..7bb41725b1 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts @@ -3,6 +3,7 @@ import { FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf, Subscription } from 'rxjs'; import { map, mergeMap, take } from 'rxjs/operators'; +import { RestResponse } from '../../../../../core/cache/response.models'; import { PaginatedList } from '../../../../../core/data/paginated-list'; import { RemoteData } from '../../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; @@ -101,7 +102,8 @@ export class MembersListComponent implements OnInit, OnDestroy { deleteMemberFromGroup(ePerson: EPerson) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson); + const response = this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson); + this.showNotifications('deleteMember', response, ePerson.name, activeGroup); this.forceUpdateEPeople(activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); @@ -116,7 +118,8 @@ export class MembersListComponent implements OnInit, OnDestroy { addMemberToGroup(ePerson: EPerson) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - this.groupDataService.addMemberToGroup(activeGroup, ePerson); + const response = this.groupDataService.addMemberToGroup(activeGroup, ePerson); + this.showNotifications('addMember', response, ePerson.name, activeGroup); this.forceUpdateEPeople(activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); @@ -132,15 +135,15 @@ export class MembersListComponent implements OnInit, OnDestroy { return this.groupDataService.getActiveGroup().pipe(take(1), mergeMap((group: Group) => { if (group != null) { - return this.groupDataService.findAllByHref(possibleMember._links.groups.href, { + return this.ePersonDataService.findAllByHref(group._links.epersons.href, { currentPage: 0, elementsPerPage: Number.MAX_SAFE_INTEGER }) .pipe( getSucceededRemoteData(), getRemoteDataPayload(), - map((listTotalGroups: PaginatedList) => listTotalGroups.page.filter((groupInList: Group) => groupInList.id === group.id)), - map((groups: Group[]) => groups.length > 0)) + map((listEPeopleInGroup: PaginatedList) => listEPeopleInGroup.page.filter((ePersonInList: EPerson) => ePersonInList.id === possibleMember.id)), + map((epeople: EPerson[]) => epeople.length > 0)) } else { return observableOf(false); } @@ -179,4 +182,21 @@ export class MembersListComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } + + /** + * Shows a notification based on the success/failure of the request + * @param messageSuffix Suffix for message + * @param response RestResponse observable containing success/failure request + * @param nameObject Object request was about + * @param activeGroup Group currently being edited + */ + showNotifications(messageSuffix: string, response: Observable, nameObject: string, activeGroup: Group) { + response.pipe(take(1)).subscribe((restResponse: RestResponse) => { + if (restResponse.isSuccessful) { + this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.success.' + messageSuffix, { name: nameObject })); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.' + messageSuffix, { name: nameObject })); + } + }) + } } diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts index deeb1826d6..890b95bfeb 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts @@ -3,6 +3,7 @@ import { FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf, Subscription } from 'rxjs'; import { map, mergeMap, take } from 'rxjs/operators'; +import { RestResponse } from '../../../../../core/cache/response.models'; import { PaginatedList } from '../../../../../core/data/paginated-list'; import { RemoteData } from '../../../../../core/data/remote-data'; import { GroupDataService } from '../../../../../core/eperson/group-data.service'; @@ -121,7 +122,8 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { deleteSubgroupFromGroup(subgroup: Group) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - this.groupDataService.deleteSubGroupFromGroup(activeGroup, subgroup); + const response = this.groupDataService.deleteSubGroupFromGroup(activeGroup, subgroup); + this.showNotifications('addSubgroup', response, subgroup.name, activeGroup); this.forceUpdateGroups(activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); @@ -136,7 +138,8 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { addSubgroupToGroup(subgroup: Group) { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup != null) { - this.groupDataService.addSubGroupToGroup(activeGroup, subgroup); + const response = this.groupDataService.addSubGroupToGroup(activeGroup, subgroup); + this.showNotifications('deleteSubgroup', response, subgroup.name, activeGroup); this.forceUpdateGroups(activeGroup); } else { this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); @@ -175,4 +178,21 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } + + /** + * Shows a notification based on the success/failure of the request + * @param messageSuffix Suffix for message + * @param response RestResponse observable containing success/failure request + * @param nameObject Object request was about + * @param activeGroup Group currently being edited + */ + showNotifications(messageSuffix: string, response: Observable, nameObject: string, activeGroup: Group) { + response.pipe(take(1)).subscribe((restResponse: RestResponse) => { + if (restResponse.isSuccessful) { + this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.success.' + messageSuffix, { name: nameObject })); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.' + messageSuffix, { name: nameObject })); + } + }) + } } 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 f9883bfd5b..d54ab7f2c7 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 @@ -50,7 +50,7 @@ {{group.id}} {{group.name}} - {{(getMembers(group) | async)?.payload?.totalElements}} + {{(getMembers(group) | async)?.payload?.totalElements + (getSubgroups(group) | async)?.payload?.totalElements}}
diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts index e6a8b931ee..ef86a914e1 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; @@ -22,7 +22,7 @@ import { followLink } from '../../../shared/utils/follow-link-config.model'; * A component used for managing all existing groups within the repository. * The admin can create, edit or delete groups here. */ -export class GroupsRegistryComponent { +export class GroupsRegistryComponent implements OnInit { messagePrefix = 'admin.access-control.groups.'; @@ -48,13 +48,16 @@ export class GroupsRegistryComponent { private translateService: TranslateService, private notificationsService: NotificationsService, private formBuilder: FormBuilder) { + this.searchForm = this.formBuilder.group(({ + query: '', + })); + } + + ngOnInit() { this.updateGroups({ currentPage: 1, elementsPerPage: this.config.pageSize }); - this.searchForm = this.formBuilder.group(({ - query: '', - })); } /** @@ -72,7 +75,7 @@ export class GroupsRegistryComponent { * Update the list of groups by fetching it from the rest api or cache */ private updateGroups(options) { - this.groups = this.groupService.getGroups(options, followLink('epersons')); + this.groups = this.groupService.getGroups(options, followLink('epersons'), followLink('groups')); } /** @@ -115,13 +118,21 @@ export class GroupsRegistryComponent { } /** - * Get the amount of members (epersons embedded value of a group) + * Get the members (epersons embedded value of a group) * @param group */ getMembers(group: Group): Observable>> { return this.ePersonDataService.findAllByHref(group._links.epersons.href); } + /** + * Get the subgroups (groups embedded value of a group) + * @param group + */ + getSubgroups(group: Group): Observable>> { + return this.groupService.findAllByHref(group._links.groups.href); + } + /** * Extract optional UUID from a group name => To be resolved to community or collection with link * (Or will be resolved in backend and added to group object, tbd) //TODO diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index b6233bf015..dc331d0b2c 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -16,15 +16,17 @@ import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { SearchParam } from '../cache/models/search-param.model'; import { ObjectCacheService } from '../cache/object-cache.service'; +import { RestResponse } from '../cache/response.models'; import { DataService } from '../data/data.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; -import { DeleteRequest, FindListOptions, FindListRequest, PostRequest } from '../data/request.models'; +import { DeleteRequest, FindListOptions, FindListRequest, PostRequest, RestRequest } from '../data/request.models'; import { RequestService } from '../data/request.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { getResponseFromEntry } from '../shared/operators'; import { EPerson } from './models/eperson.model'; import { Group } from './models/group.model'; import { dataService } from '../cache/builders/build-decorators'; @@ -154,7 +156,7 @@ export class GroupDataService extends DataService { * @param activeGroup Group we want to add subgroup to * @param subgroup Group we want to add as subgroup to activeGroup */ - addSubGroupToGroup(activeGroup: Group, subgroup: Group) { + addSubGroupToGroup(activeGroup: Group, subgroup: Group): Observable { const requestId = this.requestService.generateRequestId(); const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -162,6 +164,8 @@ export class GroupDataService extends DataService { options.headers = headers; const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint, subgroup.self, options); this.requestService.configure(postRequest); + + return this.fetchResponse(requestId); } /** @@ -169,10 +173,12 @@ export class GroupDataService extends DataService { * @param activeGroup Group we want to delete subgroup from * @param subgroup Subgroup we want to delete from activeGroup */ - deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group) { + deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group): Observable { const requestId = this.requestService.generateRequestId(); const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint + '/' + subgroup.id); this.requestService.configure(deleteRequest); + + return this.fetchResponse(requestId); } /** @@ -180,7 +186,7 @@ export class GroupDataService extends DataService { * @param activeGroup Group we want to add member to * @param ePerson EPerson we want to add as member to given activeGroup */ - addMemberToGroup(activeGroup: Group, ePerson: EPerson) { + addMemberToGroup(activeGroup: Group, ePerson: EPerson): Observable { const requestId = this.requestService.generateRequestId(); const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -188,6 +194,8 @@ export class GroupDataService extends DataService { options.headers = headers; const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint, ePerson.self, options); this.requestService.configure(postRequest); + + return this.fetchResponse(requestId); } /** @@ -195,10 +203,25 @@ export class GroupDataService extends DataService { * @param activeGroup Group we want to delete member from * @param ePerson EPerson we want to delete from members of given activeGroup */ - deleteMemberFromGroup(activeGroup: Group, ePerson: EPerson) { + deleteMemberFromGroup(activeGroup: Group, ePerson: EPerson): Observable { const requestId = this.requestService.generateRequestId(); const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint + '/' + ePerson.id); this.requestService.configure(deleteRequest); + + return this.fetchResponse(requestId); + } + + /** + * Gets the restResponse from the requestService + * @param requestId + */ + protected fetchResponse(requestId: string): Observable { + return this.requestService.getByUUID(requestId).pipe( + getResponseFromEntry(), + map((response: RestResponse) => { + return response; + }) + ); } /**