- {{'DIALOGS.REMOVE_MEMBERS.DESCRIPTION' | translate}}
+ {{(!!data.groupId ? 'DIALOGS.REMOVE_MEMBERS.DESCRIPTION_GROUP' : 'DIALOGS.REMOVE_MEMBERS.DESCRIPTION') | translate}}
@@ -36,6 +36,6 @@
{{'DIALOGS.REMOVE_MEMBERS.TITLE' | translate}}
class="ml-2"
color="warn"
(click)="onSubmit()">
- {{'DIALOGS.DELETE_GROUP.DELETE' | translate}}
+ {{(!!data.groupId ? 'DIALOGS.REMOVE_MEMBERS.REMOVE_GROUP' : 'DIALOGS.REMOVE_MEMBERS.REMOVE') | translate}}
diff --git a/apps/admin-gui/src/app/shared/components/dialogs/remove-members-dialog/remove-members-dialog.component.ts b/apps/admin-gui/src/app/shared/components/dialogs/remove-members-dialog/remove-members-dialog.component.ts
index 3c8a5917d..f84328667 100644
--- a/apps/admin-gui/src/app/shared/components/dialogs/remove-members-dialog/remove-members-dialog.component.ts
+++ b/apps/admin-gui/src/app/shared/components/dialogs/remove-members-dialog/remove-members-dialog.component.ts
@@ -3,10 +3,11 @@ import {MAT_DIALOG_DATA, MatDialogRef, MatTableDataSource} from '@angular/materi
import {NotificatorService} from '../../../../core/services/common/notificator.service';
import {TranslateService} from '@ngx-translate/core';
import { RichMember } from '@perun-web-apps/perun/models';
-import { MembersService } from '@perun-web-apps/perun/services';
+import { GroupService, MembersService } from '@perun-web-apps/perun/services';
export interface RemoveMembersDialogData {
members: RichMember[];
+ groupId?: number;
}
@Component({
selector: 'app-remove-members-dialog',
@@ -19,6 +20,7 @@ export class RemoveMembersDialogComponent implements OnInit {
public dialogRef: MatDialogRef
,
@Inject(MAT_DIALOG_DATA) public data: RemoveMembersDialogData,
private membersService: MembersService,
+ private groupService: GroupService,
private notificator: NotificatorService,
private translate: TranslateService
) { }
@@ -38,14 +40,25 @@ export class RemoveMembersDialogComponent implements OnInit {
onSubmit() {
this.loading = true;
- this.membersService.deleteMembers(this.data.members.map(m => m.id)).subscribe(() => {
- this.translate.get('DIALOGS.REMOVE_MEMBERS.SUCCESS').subscribe(successMessage => {
- this.notificator.showSuccess(successMessage);
- this.dialogRef.close(true);
- this.loading = false;
- });
- }, () => {
- this.loading = false;
- });
+ if (!!this.data.groupId) {
+ this.groupService.removeMembers(this.data.groupId, this.data.members.map(m => m.id))
+ .subscribe(() => this.onSuccess(), () => this.onError());
+ } else {
+ this.membersService.deleteMembers(this.data.members.map(m => m.id))
+ .subscribe(() => this.onSuccess(), () => this.onError());
+ }
+ }
+
+ onSuccess() {
+ const message = !!this.data.groupId ?
+ this.translate.instant('DIALOGS.REMOVE_MEMBERS.SUCCESS_GROUP'):
+ this.translate.instant('DIALOGS.REMOVE_MEMBERS.SUCCESS');
+ this.notificator.showSuccess(message);
+ this.dialogRef.close(true);
+ this.loading = false;
+ }
+
+ onError() {
+ this.loading = false;
}
}
diff --git a/apps/admin-gui/src/app/shared/pipes/member-candidate-email.pipe.ts b/apps/admin-gui/src/app/shared/pipes/member-candidate-email.pipe.ts
index b03487ace..1a4a74a38 100644
--- a/apps/admin-gui/src/app/shared/pipes/member-candidate-email.pipe.ts
+++ b/apps/admin-gui/src/app/shared/pipes/member-candidate-email.pipe.ts
@@ -8,7 +8,7 @@ import { parseEmail, parseUserEmail } from '@perun-web-apps/perun/utils';
export class MemberCandidateEmailPipe implements PipeTransform {
transform(value: MemberCandidate): any {
- return value.member ? parseEmail(value.member) : parseUserEmail(value.richUser);
+ return !!value.member && !!value.member.memberAttributes ? parseEmail(value.member) : parseUserEmail(value.richUser);
}
}
diff --git a/apps/admin-gui/src/app/vos/pages/group-detail-page/group-members/group-members.component.ts b/apps/admin-gui/src/app/vos/pages/group-detail-page/group-members/group-members.component.ts
index 36f8206bd..c5c337e0e 100644
--- a/apps/admin-gui/src/app/vos/pages/group-detail-page/group-members/group-members.component.ts
+++ b/apps/admin-gui/src/app/vos/pages/group-detail-page/group-members/group-members.component.ts
@@ -4,6 +4,9 @@ import {SelectionModel} from '@angular/cdk/collections';
import { GroupService, MembersService } from '@perun-web-apps/perun/services';
import { Group, RichMember } from '@perun-web-apps/perun/models';
import { Urns } from '@perun-web-apps/perun/urns';
+import { AddMemberDialogComponent } from '../../../../shared/components/dialogs/add-member-dialog/add-member-dialog.component';
+import { MatDialog } from '@angular/material';
+import { RemoveMembersDialogComponent } from '../../../../shared/components/dialogs/remove-members-dialog/remove-members-dialog.component';
@Component({
selector: 'app-group-members',
@@ -17,10 +20,13 @@ export class GroupMembersComponent implements OnInit {
// used for router animation
@HostBinding('class.router-component') true;
- constructor(private membersService: MembersService,
- private groupService: GroupService,
- protected route: ActivatedRoute,
- protected router: Router) { }
+ constructor(
+ private membersService: MembersService,
+ private groupService: GroupService,
+ protected route: ActivatedRoute,
+ protected router: Router,
+ private dialog: MatDialog
+ ) { }
group: Group;
@@ -66,7 +72,22 @@ export class GroupMembersComponent implements OnInit {
}
onAddMember() {
+ const dialogRef = this.dialog.open(AddMemberDialogComponent, {
+ width: '1000px',
+ data: {
+ voId: this.group.voId,
+ group: this.group,
+ entityId: this.group.id,
+ theme: 'group-theme',
+ type: 'group',
+ }
+ });
+ dialogRef.afterClosed().subscribe(() => {
+ if (this.firstSearchDone) {
+ this.refreshTable();
+ }
+ });
}
onKeyInput(event: KeyboardEvent) {
@@ -76,6 +97,19 @@ export class GroupMembersComponent implements OnInit {
}
onRemoveMembers() {
+ const dialogRef = this.dialog.open(RemoveMembersDialogComponent, {
+ width: '450px',
+ data: {
+ groupId: this.group.id,
+ members: this.selection.selected
+ }
+ });
+
+ dialogRef.afterClosed().subscribe(wereMembersDeleted => {
+ if (wereMembersDeleted) {
+ this.refreshTable();
+ }
+ });
}
refreshTable() {
diff --git a/apps/admin-gui/src/app/vos/pages/vo-detail-page/vo-members/vo-members.component.ts b/apps/admin-gui/src/app/vos/pages/vo-detail-page/vo-members/vo-members.component.ts
index f2e893ca8..8abc0964d 100644
--- a/apps/admin-gui/src/app/vos/pages/vo-detail-page/vo-members/vo-members.component.ts
+++ b/apps/admin-gui/src/app/vos/pages/vo-detail-page/vo-members/vo-members.component.ts
@@ -92,7 +92,11 @@ export class VoMembersComponent implements OnInit {
onAddMember() {
const dialogRef = this.dialog.open(AddMemberDialogComponent, {
width: '1000px',
- data: {voId: this.vo.id, theme: 'vo-theme'}
+ data: {
+ entityId: this.vo.id,
+ theme: 'vo-theme',
+ type: 'vo'
+ }
});
dialogRef.afterClosed().subscribe(() => {
diff --git a/apps/admin-gui/src/assets/i18n/en.json b/apps/admin-gui/src/assets/i18n/en.json
index 1fa235dc3..bc26a73cf 100644
--- a/apps/admin-gui/src/assets/i18n/en.json
+++ b/apps/admin-gui/src/assets/i18n/en.json
@@ -601,8 +601,12 @@
"REMOVE_MEMBERS": {
"TITLE": "Confirm removal",
"DESCRIPTION": "Following members will be removed from VO and their settings will be lost.\n\nYou can consider changing their status to \"DISABLED\", which will prevent them from accessing VO resources.",
+ "DESCRIPTION_GROUP": "Following members will be removed from group. They will lose access to resources provided by this group.",
"ASK": "Do you want to proceed?",
- "SUCCESS": "Selected members were deleted"
+ "SUCCESS": "Selected members were deleted",
+ "SUCCESS_GROUP": "Selected members were removed",
+ "REMOVE": "Delete",
+ "REMOVE_GROUP": "Remove"
},
"REMOVE_RESOURCES": {
"TITLE": "Confirm removal",
diff --git a/libs/perun/services/src/lib/group.service.ts b/libs/perun/services/src/lib/group.service.ts
index b853b2a92..7d605b7cf 100644
--- a/libs/perun/services/src/lib/group.service.ts
+++ b/libs/perun/services/src/lib/group.service.ts
@@ -78,4 +78,18 @@ export class GroupService {
getVoOfGroup(id: number, showNotificationOnError = true): Observable {
return this.apiService.get(`json/groupsManager/getVo?group=${id}`, new HttpParams(), showNotificationOnError);
}
+
+ addMembers(group: number, members: number[], showNotificationOnError: boolean = true): Observable {
+ return this.apiService.post('json/groupsManager/addMembers', {
+ group: group,
+ members: members
+ }, showNotificationOnError);
+ }
+
+ removeMembers(group: number, members: number[], showNotificationOnError: boolean = true): Observable {
+ return this.apiService.post('json/groupsManager/removeMembers', {
+ group: group,
+ members: members
+ }, showNotificationOnError);
+ }
}
diff --git a/libs/perun/services/src/lib/members.service.ts b/libs/perun/services/src/lib/members.service.ts
index faefa7d30..4b9f2499e 100644
--- a/libs/perun/services/src/lib/members.service.ts
+++ b/libs/perun/services/src/lib/members.service.ts
@@ -3,7 +3,7 @@ import {Observable} from 'rxjs';
import {HttpParams} from '@angular/common/http';
import { PERUN_API_SERVICE } from '@perun-web-apps/perun/tokens';
import { PerunApiService } from './perun-api-service';
-import { Member, RichMember } from '@perun-web-apps/perun/models';
+import { Candidate, Group, Member, RichMember } from '@perun-web-apps/perun/models';
@Injectable({
providedIn: 'root'
@@ -76,13 +76,50 @@ export class MembersService {
}, showNotificationOnError);
}
- addMember(voId: number, userId: number, showNotificationOnError = true): Observable {
+ createMember(voId: number, userId: number, showNotificationOnError = true): Observable {
return this.apiService.post('json/membersManager/createMember', {
vo: voId,
user: userId
}, showNotificationOnError);
}
+ createMemberWithGroups(
+ voId: number,
+ userId: number,
+ groups: Group[],
+ showNotificationOnError = true
+ ): Observable {
+ return this.apiService.post('json/membersManager/createMember', {
+ vo: voId,
+ user: userId,
+ groups: groups
+ }, showNotificationOnError);
+ }
+
+ createMemberForCandidateWithGroups(
+ voId: number,
+ candidate: Candidate,
+ groups: Group[],
+ showNotificationOnError = true
+ ): Observable {
+ return this.apiService.post('json/membersManager/createMember', {
+ vo: voId,
+ candidate: candidate,
+ groups: groups
+ }, showNotificationOnError);
+ }
+
+ createMemberForCandidate(
+ voId: number,
+ candidate: Candidate,
+ showNotificationOnError = true
+ ): Observable {
+ return this.apiService.post('json/membersManager/createMember', {
+ vo: voId,
+ candidate: candidate
+ }, showNotificationOnError);
+ }
+
getMemberByUser(voId: number, userId: number, showNotificationOnError = true): Observable {
return this.apiService.post('json/membersManager/getMemberByUser', {
'vo': voId,
diff --git a/libs/perun/services/src/lib/vo.service.ts b/libs/perun/services/src/lib/vo.service.ts
index ef9feebe1..94acf4fc3 100644
--- a/libs/perun/services/src/lib/vo.service.ts
+++ b/libs/perun/services/src/lib/vo.service.ts
@@ -26,13 +26,15 @@ export class VoService {
return this.apiService.get(`json/vosManager/getVoById?id=${id}`, new HttpParams(), showNotificationOnError);
}
- getCompleteCandidates(voId: number, attrNames: string[], searchString: string,
+ getCompleteCandidates(id: number, entity : 'group' | 'vo', attrNames: string[], searchString: string,
showNotificationOnError = true): Observable {
- return this.apiService.post('json/vosManager/getCompleteCandidates', {
- vo: voId,
+ const payload = {
attrNames: attrNames,
searchString: searchString
- }, showNotificationOnError);
+ };
+ payload[entity] = id;
+
+ return this.apiService.post('json/vosManager/getCompleteCandidates', payload, showNotificationOnError);
}
removeVo(voId:number, force:boolean, showNotificationOnError = true): Observable {