Skip to content

Commit

Permalink
Merge pull request #76 from Vojtech-Sassmann/groupMembers
Browse files Browse the repository at this point in the history
AdminGUI - add and remove members from group
  • Loading branch information
Vojtech-Sassmann authored Nov 28, 2019
2 parents 4ea21d5 + 13fa7f6 commit 2d889a1
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h1 mat-dialog-title>{{'DIALOGS.ADD_MEMBERS.TITLE' | translate}}</h1>
<div class="no-bounce-scrollbar">
<mat-spinner *ngIf="loading" class="mr-auto ml-auto"></mat-spinner>
</div>
<div class="mt-3" *ngIf="members !== null && !loading">
<div class="mt-3" *ngIf="!!members && !loading">
<app-alert *ngIf="members.length === 0 && firstSearchDone" color="warn">
{{'DIALOGS.ADD_MEMBERS.NO_USERS_FOUND' | translate}}
</app-alert>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material';
import {TranslateService} from '@ngx-translate/core';
import {NotificatorService} from '../../../../core/services/common/notificator.service';
import {ActivatedRoute, Router} from '@angular/router';
import {SelectionModel} from '@angular/cdk/collections';
import { MembersService, RegistrarService, VoService } from '@perun-web-apps/perun/services';
import { MemberCandidate } from '@perun-web-apps/perun/models';
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { NotificatorService } from '../../../../core/services/common/notificator.service';
import { ActivatedRoute, Router } from '@angular/router';
import { SelectionModel } from '@angular/cdk/collections';
import { GroupService, MembersService, RegistrarService, VoService } from '@perun-web-apps/perun/services';
import { Group, MemberCandidate } from '@perun-web-apps/perun/models';
import { Urns } from '@perun-web-apps/perun/urns';

export interface AddMemberDialogData {
voId: number;
voId?: number;
entityId: number;
group?: Group;
theme: string;
type: 'vo' | 'group';
}

@Component({
Expand All @@ -24,6 +27,7 @@ export class AddMemberDialogComponent implements OnInit {
private dialogRef: MatDialogRef<AddMemberDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: AddMemberDialogData,
private memberService: MembersService,
private groupService: GroupService,
private voService: VoService,
private registrarService: RegistrarService,
private translate: TranslateService,
Expand Down Expand Up @@ -58,23 +62,40 @@ export class AddMemberDialogComponent implements OnInit {
onAdd(): void {
this.processing = true;
// TODO Adds only one member at the time. In the future there would be need to add more
this.memberService.addMember(this.data.voId, this.selection.selected[0].richUser.id).subscribe(() => {
this.translate.get('DIALOGS.ADD_MEMBERS.SUCCESS').subscribe(() => {
this.notificator.showSuccess(this.successMessage);
this.dialogRef.close();
this.processing = false;
});
});
const selectedMemberCandidate = this.selection.selected[0];

if (this.data.type === 'vo') {
if (!!selectedMemberCandidate.richUser) {
this.addUserToVo(selectedMemberCandidate);
} else {
this.addCandidateToVo(selectedMemberCandidate);
}
} else if (this.data.type === 'group') {
if (!!selectedMemberCandidate.member) {
this.addMemberToGroup(selectedMemberCandidate);
}
else if (!!selectedMemberCandidate.richUser) {
this.addUserToGroup(selectedMemberCandidate);
}
else if (!!selectedMemberCandidate.candidate) {
this.addCandidateToGroup(selectedMemberCandidate);
}
}
}

onInvite(): void {

// TODO Was not tested properly. Need to be tested on devel.
this.registrarService.sendInvitationToExistingUser(this.selection.selected[0].richUser.id, this.data.voId).subscribe(() => {
this.translate.get('DIALOGS.ADD_MEMBERS.SUCCESS_INVITE').subscribe(() => {
this.notificator.showSuccess(this.successInviteMessage);
this.dialogRef.close();
});
});
if (this.data.type === 'vo') {
this.registrarService.sendInvitationToExistingUser(this.selection.selected[0].richUser.id, this.data.entityId).subscribe(() => {
this.translate.get('DIALOGS.ADD_MEMBERS.SUCCESS_INVITE').subscribe(() => {
this.notificator.showSuccess(this.successInviteMessage);
this.dialogRef.close();
});
});
} else if (this.data.type === 'group') {
//TODO
}
}

onSearchByString() {
Expand All @@ -83,7 +104,10 @@ export class AddMemberDialogComponent implements OnInit {
this.selection.clear();

// TODO properly test it on devel when possible.
this.voService.getCompleteCandidates(this.data.voId,

this.voService.getCompleteCandidates(
this.data.entityId,
this.data.type,
[Urns.USER_DEF_ORGANIZATION, Urns.USER_DEF_PREFERRED_MAIL], this.searchString).subscribe(
members => {
this.members = members;
Expand All @@ -98,4 +122,47 @@ export class AddMemberDialogComponent implements OnInit {
this.theme = this.data.theme;
}

private addUserToVo(selectedMemberCandidate: MemberCandidate) {
this.memberService.createMember(this.data.entityId, selectedMemberCandidate.richUser.id).subscribe(() => {
this.onAddSuccess();
}, () => this.onError());
}

private addCandidateToVo(selectedMemberCandidate: MemberCandidate) {
this.memberService.createMemberForCandidate(
this.data.entityId, selectedMemberCandidate.candidate).subscribe(() => {
this.onAddSuccess();
}, () => this.onError());
}

private addUserToGroup(selectedMemberCandidate: MemberCandidate) {
this.memberService.createMemberWithGroups(
this.data.voId, selectedMemberCandidate.richUser.id, [this.data.group]).subscribe(() => {
this.onAddSuccess();
}, () => this.onError());
}

private addMemberToGroup(selectedMemberCandidate: MemberCandidate) {
this.groupService.addMembers(this.data.entityId, [selectedMemberCandidate.member.id]).subscribe(() => {
this.onAddSuccess();
}, () => this.onError());
}

private addCandidateToGroup(selectedMemberCandidate: MemberCandidate) {
this.memberService.createMemberForCandidateWithGroups(
this.data.voId, selectedMemberCandidate.candidate, [this.data.group]).subscribe(() => {
this.onAddSuccess();
}, () => this.onError());
}

private onAddSuccess() {
this.translate.get('DIALOGS.ADD_MEMBERS.SUCCESS').subscribe(() => {
this.notificator.showSuccess(this.successMessage);
this.dialogRef.close();
});
}

private onError() {
this.processing = false;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1 mat-dialog-title>{{'DIALOGS.REMOVE_MEMBERS.TITLE' | translate}}</h1>
<div mat-dialog-content *ngIf="!loading">
<p>
{{'DIALOGS.REMOVE_MEMBERS.DESCRIPTION' | translate}}
{{(!!data.groupId ? 'DIALOGS.REMOVE_MEMBERS.DESCRIPTION_GROUP' : 'DIALOGS.REMOVE_MEMBERS.DESCRIPTION') | translate}}
</p>

<div class="font-weight-bold">
Expand Down Expand Up @@ -36,6 +36,6 @@ <h1 mat-dialog-title>{{'DIALOGS.REMOVE_MEMBERS.TITLE' | translate}}</h1>
class="ml-2"
color="warn"
(click)="onSubmit()">
{{'DIALOGS.DELETE_GROUP.DELETE' | translate}}
{{(!!data.groupId ? 'DIALOGS.REMOVE_MEMBERS.REMOVE_GROUP' : 'DIALOGS.REMOVE_MEMBERS.REMOVE') | translate}}
</button>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -19,6 +20,7 @@ export class RemoveMembersDialogComponent implements OnInit {
public dialogRef: MatDialogRef<RemoveMembersDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: RemoveMembersDialogData,
private membersService: MembersService,
private groupService: GroupService,
private notificator: NotificatorService,
private translate: TranslateService
) { }
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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;

Expand Down Expand Up @@ -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) {
Expand All @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down
6 changes: 5 additions & 1 deletion apps/admin-gui/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
14 changes: 14 additions & 0 deletions libs/perun/services/src/lib/group.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,18 @@ export class GroupService {
getVoOfGroup(id: number, showNotificationOnError = true): Observable<Vo> {
return this.apiService.get(`json/groupsManager/getVo?group=${id}`, new HttpParams(), showNotificationOnError);
}

addMembers(group: number, members: number[], showNotificationOnError: boolean = true): Observable<void> {
return this.apiService.post('json/groupsManager/addMembers', {
group: group,
members: members
}, showNotificationOnError);
}

removeMembers(group: number, members: number[], showNotificationOnError: boolean = true): Observable<any> {
return this.apiService.post('json/groupsManager/removeMembers', {
group: group,
members: members
}, showNotificationOnError);
}
}
Loading

0 comments on commit 2d889a1

Please sign in to comment.