Skip to content

Commit 4c63490

Browse files
Merge pull request #3 from iam-vir-harshit/for-2869
Fix for #2869
2 parents 8553b24 + 5f70d41 commit 4c63490

File tree

7 files changed

+170
-0
lines changed

7 files changed

+170
-0
lines changed

src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ <h2>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h2>
6464
<th scope="col" class="align-middle">{{messagePrefix + '.table.id' | translate}}</th>
6565
<th scope="col" class="align-middle">{{messagePrefix + '.table.name' | translate}}</th>
6666
<th scope="col" class="align-middle">{{messagePrefix + '.table.collectionOrCommunity' | translate}}</th>
67+
<th scope="col" class="align-middle">{{messagePrefix + '.table.remove' | translate}}</th>
6768
</tr>
6869
</thead>
6970
<tbody>
@@ -78,6 +79,13 @@ <h2>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h2>
7879
<td class="align-middle">
7980
{{ dsoNameService.getName((group.object | async)?.payload) }}
8081
</td>
82+
<td class="align-middle">
83+
<button *ngIf="canDelete$ | async" before (click)="deleteGroupFromMember(group)"
84+
type="button" [ngClass]="['btn btn-sm delete-button', 'btn-outline-danger']"
85+
title="{{messagePrefix + '.table.edit.buttons.removegroup' | translate: { name: dsoNameService.getName(group) } }}">
86+
<i class="fas fa-trash-alt fa-fw"></i>
87+
</button>
88+
</td>
8189
</tr>
8290
</tbody>
8391
</table>

src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,38 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
597597
}
598598
}
599599

600+
/**
601+
* Deletes a given group from the Group list of the eperson currently being edited present in
602+
* @param group group we want to delete as of which the current eperson being edited is member of
603+
*/
604+
deleteGroupFromMember(group: Group) {
605+
this.epersonService.getActiveEPerson().pipe(take(1)).subscribe((activeEPerson: EPerson) => {
606+
if (activeEPerson != null) {
607+
const response = this.groupsDataService.deleteMemberFromGroup(group, activeEPerson);
608+
this.showNotifications('deleteMembership', response, this.dsoNameService.getName(group), activeEPerson);
609+
} else {
610+
this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.noActiveEPerson'));
611+
}
612+
});
613+
}
614+
615+
/**
616+
* Shows a notification based on the success/failure of the request
617+
* @param messageSuffix Suffix for message
618+
* @param response RestResponse observable containing success/failure request
619+
* @param nameObject Object request was about
620+
* @param activeEPerson EPerson currently being edited
621+
*/
622+
showNotifications(messageSuffix: string, response: Observable<RemoteData<any>>, nameObject: string, activeEPerson: EPerson) {
623+
response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData<any>) => {
624+
if (rd.hasSucceeded) {
625+
this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.success.' + messageSuffix, { name: nameObject }));
626+
} else {
627+
this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.' + messageSuffix, { name: nameObject }));
628+
}
629+
});
630+
}
631+
600632
/**
601633
* Cancel the current edit when component is destroyed & unsub all subscriptions
602634
*/

src/app/access-control/group-registry/group-form/members-list/members-list.component.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22
<h2 class="border-bottom pb-2">{{messagePrefix + '.head' | translate}}</h2>
33

44
<h3>{{messagePrefix + '.headMembers' | translate}}</h3>
5+
6+
<form [formGroup]="searchCurrentMembersForm" (ngSubmit)="searchMembers(searchCurrentMembersForm.value)" class="d-flex justify-content-between">
7+
<div class="flex-grow-1 mr-3">
8+
<div class="form-group input-group mr-3">
9+
<input type="text" name="queryCurrentMembers" id="queryCurrentMembers" formControlName="queryCurrentMembers"
10+
class="form-control" aria-label="Search input">
11+
<span class="input-group-append">
12+
<button type="submit" class="search-button btn btn-primary">
13+
<i class="fas fa-search"></i> {{ messagePrefix + '.search.button' | translate }}</button>
14+
</span>
15+
</div>
16+
</div>
17+
<div>
18+
<button (click)="clearCurrentMembersFormAndResetResult()"
19+
class="btn btn-secondary">{{messagePrefix + '.button.see-all' | translate}}</button>
20+
</div>
21+
</form>
522

623
<ds-pagination *ngIf="(ePeopleMembersOfGroup | async)?.totalElements > 0"
724
[paginationOptions]="config"

src/app/access-control/group-registry/group-form/members-list/members-list.component.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,21 @@ export class MembersListComponent implements OnInit, OnDestroy {
172172
// The search form
173173
searchForm;
174174

175+
// The current member search form
176+
searchCurrentMembersForm;
177+
175178
// Current search in edit group - epeople search form
176179
currentSearchQuery: string;
177180

181+
// Current search in edit group - epeople current members search form
182+
currentMembersSearchQuery: string;
183+
178184
// Whether or not user has done a EPeople search yet
179185
searchDone: boolean;
180186

187+
// Whether or not user has done a EPeople Member search yet
188+
searchCurrentMembersDone: boolean;
189+
181190
// current active group being edited
182191
groupBeingEdited: Group;
183192

@@ -194,12 +203,18 @@ export class MembersListComponent implements OnInit, OnDestroy {
194203
public dsoNameService: DSONameService,
195204
) {
196205
this.currentSearchQuery = '';
206+
this.currentMembersSearchQuery = '';
197207
}
198208

199209
ngOnInit(): void {
200210
this.searchForm = this.formBuilder.group(({
201211
query: '',
202212
}));
213+
214+
this.searchCurrentMembersForm = this.formBuilder.group(({
215+
queryCurrentMembers: '',
216+
}));
217+
203218
this.subs.set(SubKey.ActiveGroup, this.groupDataService.getActiveGroup().subscribe((activeGroup: Group) => {
204219
if (activeGroup != null) {
205220
this.groupBeingEdited = activeGroup;
@@ -354,6 +369,55 @@ export class MembersListComponent implements OnInit, OnDestroy {
354369
}));
355370
}
356371

372+
/**
373+
* Search all EPeople who are a member of the current group by name, email or metadata
374+
* @param data Contains query param
375+
*/
376+
searchMembers(data: any) {
377+
this.unsubFrom(SubKey.Members);
378+
this.subs.set(SubKey.Members,
379+
this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
380+
switchMap((paginationOptions) => {
381+
const query: string = data.queryCurrentMembers;
382+
if (query != null && this.currentMembersSearchQuery !== query && this.groupBeingEdited) {
383+
this.currentMembersSearchQuery = query;
384+
this.paginationService.resetPage(this.config.id);
385+
}
386+
this.searchCurrentMembersDone = true;
387+
388+
return this.ePersonDataService.searchMembers(this.currentMembersSearchQuery, this.groupBeingEdited.id, {
389+
currentPage: paginationOptions.currentPage,
390+
elementsPerPage: paginationOptions.pageSize,
391+
}, false, true);
392+
}),
393+
getAllCompletedRemoteData(),
394+
map((rd: RemoteData<any>) => {
395+
if (rd.hasFailed) {
396+
this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure', { cause: rd.errorMessage }));
397+
} else {
398+
return rd;
399+
}
400+
}),
401+
switchMap((epersonListRD: RemoteData<PaginatedList<EPerson>>) => {
402+
const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => {
403+
const dto$: Observable<EpersonDtoModel> = observableCombineLatest(
404+
this.isMemberOfGroup(member), (isMember: ObservedValueOf<Observable<boolean>>) => {
405+
const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel();
406+
epersonDtoModel.eperson = member;
407+
epersonDtoModel.ableToDelete = isMember;
408+
return epersonDtoModel;
409+
});
410+
return dto$;
411+
})]);
412+
return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => {
413+
return buildPaginatedList(epersonListRD.payload.pageInfo, dtos);
414+
}));
415+
}),
416+
).subscribe((paginatedListOfDTOs: PaginatedList<EpersonDtoModel>) => {
417+
this.ePeopleMembersOfGroup.next(paginatedListOfDTOs);
418+
}));
419+
}
420+
357421
/**
358422
* unsub all subscriptions
359423
*/
@@ -391,4 +455,14 @@ export class MembersListComponent implements OnInit, OnDestroy {
391455
});
392456
this.search({ query: '' });
393457
}
458+
459+
/**
460+
* Reset all input-fields to be empty and search all search
461+
*/
462+
clearCurrentMembersFormAndResetResult() {
463+
this.searchCurrentMembersForm.patchValue({
464+
queryCurrentMembers:'',
465+
});
466+
this.searchMembers({ queryCurrentMembers: '' });
467+
}
394468
}

src/app/core/eperson/eperson-data.service.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,34 @@ export class EPersonDataService extends IdentifiableDataService<EPerson> impleme
241241
return this.searchBy('isNotMemberOf', findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
242242
}
243243

244+
/**
245+
* Searches for all EPerons which are a member of a given group, via a passed in query
246+
* (searches all EPerson metadata and by exact UUID).
247+
* Endpoint used: /eperson/epesons/search/isMemberOf?query=<:string>&group=<:uuid>
248+
* @param query search query param
249+
* @param group UUID of group to include results from. Members of this group will only be returned.
250+
* @param options
251+
* @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's
252+
* no valid cached version. Defaults to true
253+
* @param reRequestOnStale Whether or not the request should automatically be re-
254+
* requested after the response becomes stale
255+
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which
256+
* {@link HALLink}s should be automatically resolved
257+
*/
258+
public searchMembers(query: string, group: string, options?: FindListOptions, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<EPerson>[]): Observable<RemoteData<PaginatedList<EPerson>>> {
259+
const searchParams = [new RequestParam('query', query), new RequestParam('group', group)];
260+
let findListOptions = new FindListOptions();
261+
if (options) {
262+
findListOptions = Object.assign(new FindListOptions(), options);
263+
}
264+
if (findListOptions.searchParams) {
265+
findListOptions.searchParams = [...findListOptions.searchParams, ...searchParams];
266+
} else {
267+
findListOptions.searchParams = searchParams;
268+
}
269+
return this.searchBy('isMemberOf', findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
270+
}
271+
244272
/**
245273
* Add a new patch to the object cache
246274
* The patch is derived from the differences between the given object and its version in the object cache

src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
import {
1818
ReactiveFormsModule,
1919
UntypedFormBuilder,
20+
UntypedFormGroup,
2021
} from '@angular/forms';
2122
import {
2223
Router,
@@ -94,6 +95,8 @@ export class ReviewersListComponent extends MembersListComponent implements OnIn
9495

9596
selectedReviewers: EPerson[] = [];
9697

98+
searchCurrentMembersForm: UntypedFormGroup;
99+
97100
constructor(
98101
protected groupService: GroupDataService,
99102
public ePersonDataService: EPersonDataService,
@@ -112,6 +115,10 @@ export class ReviewersListComponent extends MembersListComponent implements OnIn
112115
scope: 'metadata',
113116
query: '',
114117
}));
118+
119+
this.searchCurrentMembersForm = this.formBuilder.group(({
120+
queryCurrentMembers: '',
121+
}));
115122
}
116123

117124
ngOnChanges(changes: SimpleChanges): void {

src/assets/i18n/en.json5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@
348348

349349
"admin.access-control.epeople.form.table.collectionOrCommunity": "Collection/Community",
350350

351+
"admin.access-control.epeople.form.table.remove": "Remove",
352+
353+
"admin.access-control.epeople.form.table.edit.buttons.removegroup": "Remove member from group \"{{name}}\"",
354+
351355
"admin.access-control.epeople.form.memberOfNoGroups": "This EPerson is not a member of any groups",
352356

353357
"admin.access-control.epeople.form.goToGroups": "Add to groups",

0 commit comments

Comments
 (0)