diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index ff1c51461f..3292ebeb69 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -254,8 +254,8 @@ "admin.access-control.groups.no-items": "No groups found with this in their name or this as UUID", "admin.access-control.groups.notification.deleted.success": "Successfully deleted group \"{{name}}\"", - // TODO - "admin.access-control.groups.notification.deleted.failure": "Failed to delete group \"{{name}}\" (Not yet implemented)", + + "admin.access-control.groups.notification.deleted.failure": "Failed to delete group \"{{name}}\"", "admin.access-control.groups.form.head.create": "Create group", @@ -264,6 +264,8 @@ "admin.access-control.groups.form.groupName": "Group name", + "admin.access-control.groups.form.groupDescription": "Description", + "admin.access-control.groups.form.button.return": "Return", "admin.access-control.groups.form.notification.created.success": "Successfully created group \"{{name}}\"", @@ -290,6 +292,8 @@ "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.", + "admin.access-control.groups.form.members-list.no-members-yet": "No members in group yet, search and add.", "admin.access-control.groups.form.members-list.button.see-all": "Search all", @@ -312,6 +316,8 @@ "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{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", "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet, search and add.", 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 7ef0592d91..eb75a1d024 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 @@ -109,13 +109,14 @@ export class GroupFormComponent implements OnInit, OnDestroy { required: true, }); this.groupDescription = new DynamicTextAreaModel({ - id: 'description', + id: 'groupDescription', label: groupDescription, - name: 'dc.description', + name: 'groupDescription', required: false, }); this.formModel = [ this.groupName, + this.groupDescription ]; this.formGroup = this.formBuilderService.createFormGroup(this.formModel); this.subs.push(this.groupDataService.getActiveGroup().subscribe((group: Group) => { @@ -160,7 +161,6 @@ export class GroupFormComponent implements OnInit, OnDestroy { } else { this.editGroup(group, values); } - this.clearFields(); } ); } @@ -176,26 +176,20 @@ export class GroupFormComponent implements OnInit, OnDestroy { getRemoteDataPayload()) .subscribe((group: Group) => { this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.created.success', { name: group.name })); + this.setActiveGroup(group.id); this.submitForm.emit(group); })); } /** - * //TODO + * // TODO * @param group * @param values */ editGroup(group: Group, values) { - // TODO - } - - /** - * Reset all input-fields to be empty - */ - clearFields() { - this.formGroup.patchValue({ - groupName: '', - }); + // TODO (backend) + console.log('TODO implement editGroup', values); + this.notificationsService.error('TODO implement editGroup (not yet implemented in backend) '); } /** 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 d794976db0..545e23d0bb 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 @@ -26,6 +26,9 @@ export class MembersListComponent implements OnInit, OnDestroy { @Input() messagePrefix: string; + /** + * EPeople being displayed, initially all members, after search result of search + */ ePeople: Observable>>; /** @@ -91,23 +94,45 @@ export class MembersListComponent implements OnInit, OnDestroy { this.ePeople = this.ePersonDataService.getEPeople(options); } + /** + * Deletes a given EPerson from the members list of the group currently being edited + * @param ePerson EPerson we want to delete as member from group that is currently being edited + */ deleteMemberFromGroup(ePerson: EPerson) { - // TODO - console.log('deleteMember TODO', ePerson); - // this.forceUpdateEPeople(); + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { + if (activeGroup != null) { + this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson); + this.forceUpdateEPeople(activeGroup); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); + } + }); } + /** + * Adds a given EPerson to the members list of the group currently being edited + * @param ePerson EPerson we want to add as member to group that is currently being edited + */ addMemberToGroup(ePerson: EPerson) { - // TODO - console.log('addMember TODO', ePerson); - // this.forceUpdateEPeople(); + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { + if (activeGroup != null) { + this.groupDataService.addMemberToGroup(activeGroup, ePerson); + this.forceUpdateEPeople(activeGroup); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); + } + }); } - isMemberOfGroup(ePerson: EPerson): Observable { + /** + * Whether or not the given ePerson is a member of the group currently being edited + * @param possibleMember EPerson that is a possible member (being tested) of the group currently being edited + */ + isMemberOfGroup(possibleMember: EPerson): Observable { return this.groupDataService.getActiveGroup().pipe(take(1), mergeMap((group: Group) => { if (group != null) { - return this.groupDataService.findAllByHref(ePerson._links.groups.href, { + return this.groupDataService.findAllByHref(possibleMember._links.groups.href, { currentPage: 0, elementsPerPage: Number.MAX_SAFE_INTEGER }) @@ -137,10 +162,15 @@ export class MembersListComponent implements OnInit, OnDestroy { /** * Force-update the list of EPeople by first clearing the cache related to EPeople, then performing * a new REST call + * @param activeGroup Group currently being edited */ - public forceUpdateEPeople() { + public forceUpdateEPeople(activeGroup: Group) { + this.groupDataService.clearGroupsRequests(); this.ePersonDataService.clearEPersonRequests(); - this.search({ query: '', scope: 'metadata' }) + this.ePeople = this.ePersonDataService.findAllByHref(activeGroup._links.epersons.href, { + currentPage: 1, + elementsPerPage: this.config.pageSize + }) } /** 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 afa226ef76..deeb1826d6 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 @@ -25,6 +25,9 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { @Input() messagePrefix: string; + /** + * Groups being displayed, initially all subgroups, after search result of search + */ groups: Observable>>; /** @@ -88,6 +91,10 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { this.groups = this.groupDataService.getGroups(options); } + /** + * Whether or not the given group is a subgroup of the group currently being edited + * @param possibleSubgroup Group that is a possible subgroup (being tested) of the group currently being edited + */ isSubgroupOfGroup(possibleSubgroup: Group): Observable { return this.groupDataService.getActiveGroup().pipe(take(1), mergeMap((group: Group) => { @@ -104,19 +111,37 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { } else { return observableOf(false); } - })) + })); } - deleteSubgroupFromGroup(group: Group) { - // TODO - console.log('deleteSubgroup TODO', group); - // this.forceUpdateGroup(); + /** + * Deletes given subgroup from the group currently being edited + * @param subgroup Group we want to delete from the subgroups of the group currently being edited + */ + deleteSubgroupFromGroup(subgroup: Group) { + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { + if (activeGroup != null) { + this.groupDataService.deleteSubGroupFromGroup(activeGroup, subgroup); + this.forceUpdateGroups(activeGroup); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); + } + }); } - addSubgroupToGroup(group: Group) { - // TODO - console.log('addSubgroup TODO', group); - // this.forceUpdateGroup(); + /** + * Adds given subgroup to the group currently being edited + * @param subgroup Subgroup to add to group currently being edited + */ + addSubgroupToGroup(subgroup: Group) { + this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { + if (activeGroup != null) { + this.groupDataService.addSubGroupToGroup(activeGroup, subgroup); + this.forceUpdateGroups(activeGroup); + } else { + this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveGroup')); + } + }); } /** @@ -134,10 +159,14 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { /** * Force-update the list of groups by first clearing the cache related to groups, then performing a new REST call + * @param activeGroup Group currently being edited */ - public forceUpdateGroup() { + public forceUpdateGroups(activeGroup: Group) { this.groupDataService.clearGroupsRequests(); - this.search({ query: '' }) + this.groups = this.groupDataService.findAllByHref(activeGroup._links.groups.href, { + currentPage: 1, + elementsPerPage: this.config.pageSize + }) } /** 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 62912c94fb..e6a8b931ee 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 @@ -91,6 +91,9 @@ export class GroupsRegistryComponent { * Delete Group */ deleteGroup(group: Group) { + // TODO (backend) + console.log('TODO implement editGroup', group); + this.notificationsService.error('TODO implement deleteGroup (not yet implemented in backend)'); if (hasValue(group.id)) { this.groupService.deleteGroup(group).pipe(take(1)).subscribe((success: boolean) => { if (success) { @@ -112,7 +115,7 @@ export class GroupsRegistryComponent { } /** - * Get the amount of members (epersons embedded value of a group) //TODO + * Get the amount of members (epersons embedded value of a group) * @param group */ getMembers(group: Group): Observable>> { diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index 86fe8a88cd..b6233bf015 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { createSelector, select, Store } from '@ngrx/store'; @@ -20,10 +20,12 @@ 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 { FindListOptions, FindListRequest } from '../data/request.models'; +import { DeleteRequest, FindListOptions, FindListRequest, PostRequest } 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 { EPerson } from './models/eperson.model'; import { Group } from './models/group.model'; import { dataService } from '../cache/builders/build-decorators'; import { GROUP } from './models/group.resource-type'; @@ -41,6 +43,8 @@ const editGroupSelector = createSelector(groupRegistryStateSelector, (groupRegis export class GroupDataService extends DataService { protected linkPath = 'groups'; protected browseEndpoint = ''; + protected ePersonsEndpoint = 'epersons'; + protected subgroupsEndpoint = 'subgroups'; constructor( protected comparator: DSOChangeAnalyzer, @@ -132,7 +136,6 @@ export class GroupDataService extends DataService { if (isUpdate) { return this.updateGroup(group); } else { - console.log('group create', group) return this.create(group, null); } } @@ -142,10 +145,62 @@ export class GroupDataService extends DataService { * @param {DSpaceObject} ePerson The given object */ updateGroup(group: Group): Observable> { - // TODO + // TODO return null; } + /** + * Adds given subgroup as a subgroup to the given active group + * @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) { + const requestId = this.requestService.generateRequestId(); + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint, subgroup.self, options); + this.requestService.configure(postRequest); + } + + /** + * Deletes a given subgroup from the subgroups of the given active group + * @param activeGroup Group we want to delete subgroup from + * @param subgroup Subgroup we want to delete from activeGroup + */ + deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group) { + const requestId = this.requestService.generateRequestId(); + const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint + '/' + subgroup.id); + this.requestService.configure(deleteRequest); + } + + /** + * Adds given ePerson as member to given group + * @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) { + const requestId = this.requestService.generateRequestId(); + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint, ePerson.self, options); + this.requestService.configure(postRequest); + } + + /** + * Deletes a given ePerson from the members of the given active group + * @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) { + const requestId = this.requestService.generateRequestId(); + const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint + '/' + ePerson.id); + this.requestService.configure(deleteRequest); + } + /** * Method to retrieve the group that is currently being edited */