Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Project):added modal for confirmation when membe ris removed #6265

Merged
merged 5 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/app/projectmanagement/overview.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ <h3>
</button>

<button
(click)="removeCheckedMembers()"
(click)="showConfirmationModalRemoveMembers()"
[disabled]="checked_member_list.length <= 0 || remove_members_clicked"
class="btn btn-outline-danger"
style="margin-bottom: 5px"
Expand Down Expand Up @@ -1075,9 +1075,10 @@ <h3>
<tr *ngFor="let member of project_members" [ngStyle]="{ color: member.isAdmin ? '#005AA9' : 'black' }">
<td *ngIf="project_application.user_is_admin || is_vo_admin">
<input
(change)="checkUnCheckMember(member.memberId)"
(change)="checkUnCheckMember(member)"
*ngIf="userinfo?.MemberId.toString() !== member.memberId.toString()"
[checked]="isMemberChecked(member.memberId)"
[checked]="isMemberChecked(member)"
[disabled]="member.isPi"
id="{{ member.userId }}"
name="member.userId"
type="checkbox"
Expand Down Expand Up @@ -1110,7 +1111,7 @@ <h3>
<td *ngIf="project_application.user_is_pi || project_application.user_is_admin || is_vo_admin">
<div class="btn-group" role="group">
<button
(click)="promoteAdmin(member.userId, member.userName); notificationModal.show()"
(click)="promoteAdmin(member.userId, member.userName)"
*ngIf="!member.isAdmin"
class="btn btn-primary"
style="margin: 2px"
Expand All @@ -1120,7 +1121,7 @@ <h3>
</button>

<button
(click)="removeAdmin(member.userId, member.userName); notificationModal.show()"
(click)="removeAdmin(member.userId, member.userName)"
*ngIf="
member.isAdmin && userinfo?.MemberId.toString() !== member.memberId.toString() && !member.isPi
"
Expand All @@ -1132,7 +1133,7 @@ <h3>
<i class="fa fa-minus-circle"></i>&nbsp; Remove Admin status
</button>
<button
(click)="removeMember(member.memberId, member.userName); notificationModal.show()"
(click)="showConfirmationModalRemoveMember(member)"
*ngIf="userinfo?.MemberId.toString() !== member.memberId.toString()"
[id]="'remove_member_' + member.userName"
[disabled]="member?.isPi"
Expand Down
127 changes: 96 additions & 31 deletions src/app/projectmanagement/overview.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import { DeleteApplicationModal } from './modals/delete-member-application-modal/delete-application-modal.component'
import { AddUserModalComponent } from './modals/add-user-modal/add-user-modal.component'
import { UserApplicationsModalComponent } from './modals/user-applications-modal/user-applications-modal.component'
import { ConfirmationActions } from 'app/shared/modal/confirmation_actions'
import { ConfirmationModalComponent } from 'app/shared/modal/confirmation-modal.component'

/**
* Projectoverview component.
Expand All @@ -59,6 +61,8 @@
})
export class OverviewComponent extends ApplicationBaseClassComponent implements OnInit, OnDestroy {
bsModalRef: BsModalRef
protected readonly ConfirmationActions = ConfirmationActions

modificationRequestDisabled: boolean = false
lifetimeExtensionDisabled: boolean = false
creditsExtensionDisabled: boolean = false
Expand Down Expand Up @@ -105,7 +109,7 @@
simple_vm_logo: string = 'static/webapp/assets/img/simpleVM_Logo.svg'
openstack_logo: string = 'static/webapp/assets/img/openstack_plain_red.svg'
kubernetes_logo: string = 'static/webapp/assets/img/kubernetes_logo.svg'
checked_member_list: number[] = []
checked_member_list: ProjectMember[] = []
// modal variables for User list
public project_members: ProjectMember[] = []
public isLoaded: boolean = false
Expand Down Expand Up @@ -722,10 +726,11 @@
if (!this.allSet) {
this.project_members.forEach((member: ProjectMember): void => {
if (
!this.isMemberChecked(parseInt(member.memberId.toString(), 10)) &&
this.userinfo.MemberId.toString() !== member.memberId.toString()
!this.isMemberChecked(member) &&
this.userinfo.MemberId.toString() !== member.memberId.toString() &&
!member.isPi
) {
this.checked_member_list.push(parseInt(member.memberId.toString(), 10))
this.checked_member_list.push(member)
}
})
this.allSet = true
Expand All @@ -734,52 +739,101 @@
this.allSet = false
}
}

isMemberChecked(id: number): boolean {
return this.checked_member_list.indexOf(id) > -1
isMemberChecked(member: ProjectMember): boolean {
return this.checked_member_list.some(checked_member => checked_member.memberId === member.memberId)
}
indexOfMemberChecked(member_id): number {
return this.checked_member_list.findIndex(member => member.memberId === member_id)
}

checkIfAllMembersChecked(): void {
let all_set: boolean = true
this.project_members.forEach((member: ProjectMember): void => {
if (
!this.isMemberChecked(parseInt(member.memberId.toString(), 10)) &&
this.userinfo.MemberId !== member.memberId
) {
if (!this.isMemberChecked(member) && this.userinfo.MemberId !== member.memberId && !member.isPi) {
all_set = false
}
})

this.allSet = all_set
}

checkUnCheckMember(id: number): void {
const indexOf: number = this.checked_member_list.indexOf(id)
checkUnCheckMember(member: ProjectMember): void {
const indexOf: number = this.indexOfMemberChecked(member.memberId)
if (indexOf !== -1) {
this.checked_member_list.splice(indexOf, 1)
this.allSet = false
} else {
this.checked_member_list.push(id)
this.checked_member_list.push(member)
this.checkIfAllMembersChecked()
}
}

showConfirmationModalRemoveMembers(): void {
const action = this.ConfirmationActions.REMOVE_MEMBERS
const member_names_as_string = this.checked_member_list
.map(member => `${member.firstName} ${member.lastName}`)
.join('<br>')
const initialState = {
application: this.project_application,
action,
additional_msg: member_names_as_string
}

this.bsModalRef = this.modalService.show(ConfirmationModalComponent, { initialState, class: 'modal-lg' })
this.subscribeToBsModalRef()
}

showConfirmationModalRemoveMember(member: ProjectMember): void {
const action = this.ConfirmationActions.REMOVE_MEMBER
const initialState = {
application: this.project_application,
action,
additional_msg: `${member.firstName} ${member.lastName}`
}

this.bsModalRef = this.modalService.show(ConfirmationModalComponent, { initialState, class: 'modal-lg' })
this.subscription.add(
this.bsModalRef.content.event.subscribe((event: any) => {
const action: ConfirmationActions = event.action

Check warning on line 797 in src/app/projectmanagement/overview.component.ts

View workflow job for this annotation

GitHub Actions / tslinting-check

'action' is already declared in the upper scope on line 787 column 9

Check warning on line 797 in src/app/projectmanagement/overview.component.ts

View workflow job for this annotation

GitHub Actions / tslinting-check

'action' is already declared in the upper scope on line 787 column 9
if (action === ConfirmationActions.REMOVE_MEMBER) {
this.removeMember(member)
}
})
)
}

subscribeToBsModalRef(): void {
this.subscription.add(
this.bsModalRef.content.event.subscribe((event: any) => {
const action: ConfirmationActions = event.action
switch (action) {
case ConfirmationActions.REMOVE_MEMBERS: {
this.removeCheckedMembers()
break
}
default:
break
}
})
)
}

removeCheckedMembers(): void {
this.remove_members_clicked = true

const members_in: ProjectMember[] = []

const observables: Observable<number>[] = this.checked_member_list.map(
(id: number): Observable<any> =>
(member: ProjectMember): Observable<any> =>
this.groupService.removeMember(
Number(this.project_application.project_application_perun_id),
id,
member.memberId,
this.project_application.project_application_compute_center.FacilityId
)
)
forkJoin(observables).subscribe((): void => {
this.project_members.forEach((member: ProjectMember): void => {
if (!this.isMemberChecked(parseInt(member.memberId.toString(), 10))) {
if (!this.isMemberChecked(member)) {
members_in.push(member)
}
})
Expand Down Expand Up @@ -814,14 +868,15 @@
.toPromise()
.then((result: any): void => {
if (result.status === 200) {
this.updateNotificationModal('Success', `${username} promoted to Admin`, true, 'success')
this.notificationModal.showSuccessFullNotificationModal('Success', `${username} promoted to Admin`)

this.getMembersOfTheProject()
} else {
this.updateNotificationModal('Failed', `${username} could not be promoted to Admin!`, true, 'danger')
this.notificationModal.showDangerNotificationModal('Failed', `${username} could not be promoted to Admin!`)
}
})
.catch((): void => {
this.updateNotificationModal('Failed', `${username} could not be promoted to Admin!`, true, 'danger')
this.notificationModal.showDangerNotificationModal('Failed', `${username} could not be promoted to Admin!`)
})
}

Expand All @@ -839,50 +894,60 @@
.toPromise()
.then((result: any): void => {
if (result.status === 200) {
this.updateNotificationModal('Success', `${name} was removed as Admin`, true, 'success')
this.notificationModal.showSuccessFullNotificationModal('Success', `${name} was removed as Admin`)

this.getMembersOfTheProject()
} else {
this.updateNotificationModal('Failed', `${name} could not be removed as Admin!`, true, 'danger')
this.notificationModal.showDangerNotificationModal('Failed', `${name} could not be removed as Admin!`)
}
})
.catch((): void => {
this.updateNotificationModal('Failed', `${name} could not be removed as Admin!`, true, 'danger')
this.notificationModal.showDangerNotificationModal('Failed', `${name} could not be removed as Admin!`)
})
}

/**
* Remove a member from a group.
*
* @param memberid of the member
* @param name of the member
*/
public removeMember(memberid: number, name: string): void {
if (this.userinfo.MemberId.toString() === memberid.toString()) {
public removeMember(member: ProjectMember): void {
if (this.userinfo.MemberId.toString() === member.memberId.toString()) {
return
}
const indexOf: number = this.checked_member_list.indexOf(memberid)
const indexOf: number = this.indexOfMemberChecked(member.memberId)
if (indexOf !== -1) {
this.checked_member_list.splice(indexOf, 1)
this.allSet = false
}

this.subscription.add(
this.groupService
.removeMember(
this.project_application.project_application_perun_id,
memberid,
member.memberId,
this.project_application.project_application_compute_center.FacilityId
)
.subscribe(
(result: any): void => {
if (result.status === 200) {
this.updateNotificationModal('Success', `Member ${name} removed from the group`, true, 'success')
this.notificationModal.showSuccessFullNotificationModal(
'Success',
`Member ${member.firstName} ${member.lastName} removed from the group`
)
this.getMembersOfTheProject()
} else {
this.updateNotificationModal('Failed', `Member ${name} could not be removed !`, true, 'danger')
this.notificationModal.showDangerNotificationModal(
'Failed',
`Member ${member.firstName} ${member.lastName} could not be removed !`
)
}
},
(): void => {
this.updateNotificationModal('Failed', `Member ${name} could not be removed !`, true, 'danger')
this.notificationModal.showDangerNotificationModal(
'Failed',
`Member ${member.firstName} ${member.lastName} could not be removed !`
)
}
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ export abstract class AbstractBaseModalComponent {

async hide(): Promise<void> {
console.log('close modal abstract')
this.modalService.hide()
this.modalService.hide(this.modalId)

//Fix when calling hide and show form within a modal -- if it is called directly after another the new modal won't open
await this.sleep(200)
await this.sleep(300)
}

private async sleep(ms: number): Promise<void> {
Expand Down
7 changes: 6 additions & 1 deletion src/app/shared/modal/confirmation-modal.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ <h4 class="modal-title text-dark" data-test-id="confirmation_modal_title">{{ mod
id="confirmation_modal_message"
>
<p data-test-id="confirmation_modal_message">
{{ modalMessage }} for {{ application.project_application_shortname }}?
{{ modalMessage }}: {{ application.project_application_shortname }}?
</p>
@if (additional_msg) {
<div class="alert alert-warning" role="alert">
<span [innerHTML]="additional_msg"></span>
</div>
}
</div>
</div>
<div class="modal-footer">
Expand Down
26 changes: 18 additions & 8 deletions src/app/shared/modal/confirmation-modal.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Injectable, OnDestroy, OnInit } from '@angular/core'
import { Component, EventEmitter, Injectable, OnInit } from '@angular/core'
import { BsModalService } from 'ngx-bootstrap/modal'
import { Application } from '../../applications/application.model/application.model'
import { ConfirmationTypes } from './confirmation_types'
Expand All @@ -13,13 +13,14 @@ import { AbstractBaseModalComponent } from './abstract-base-modal/abstract-base-
templateUrl: './confirmation-modal.component.html',
providers: []
})
export class ConfirmationModalComponent extends AbstractBaseModalComponent implements OnDestroy, OnInit {
export class ConfirmationModalComponent extends AbstractBaseModalComponent implements OnInit {
protected readonly ConfirmationTypes = ConfirmationTypes

application: Application = null
modalTitle: string = ''
modalMessage: string = ''
application_center: string = ''
additional_msg: string = ''
action: ConfirmationActions
type: ConfirmationTypes
request_failed: boolean = false
Expand Down Expand Up @@ -56,7 +57,9 @@ export class ConfirmationModalComponent extends AbstractBaseModalComponent imple
selectedCenter: this.application_center
},
[ConfirmationActions.DISABLE_APPLICATION]: { action: ConfirmationActions.DISABLE_APPLICATION },
[ConfirmationActions.ENABLE_APPLICATION]: { action: ConfirmationActions.ENABLE_APPLICATION }
[ConfirmationActions.ENABLE_APPLICATION]: { action: ConfirmationActions.ENABLE_APPLICATION },
[ConfirmationActions.REMOVE_MEMBERS]: { action: ConfirmationActions.REMOVE_MEMBERS },
[ConfirmationActions.REMOVE_MEMBER]: { action: ConfirmationActions.REMOVE_MEMBER }
}

const selectedAction = actionsMap[this.action]
Expand Down Expand Up @@ -92,7 +95,8 @@ export class ConfirmationModalComponent extends AbstractBaseModalComponent imple
return 'Declination'
case ConfirmationTypes.RESET_PI:
return 'Reset PI'

case ConfirmationTypes.REMOVE:
return 'Removal'
default:
break
}
Expand Down Expand Up @@ -172,6 +176,16 @@ export class ConfirmationModalComponent extends AbstractBaseModalComponent imple
title: 'Decline Termination',
type: ConfirmationTypes.DECLINE,
message: 'Do you really want to decline the termination of this project'
},
[ConfirmationActions.REMOVE_MEMBERS]: {
title: 'Remove Members',
type: ConfirmationTypes.REMOVE,
message: `Do you really want to remove the member(s) from the project`
},
[ConfirmationActions.REMOVE_MEMBER]: {
title: 'Remove Member',
type: ConfirmationTypes.REMOVE,
message: `Do you really want to remove the member from the project`
}
}

Expand All @@ -183,8 +197,4 @@ export class ConfirmationModalComponent extends AbstractBaseModalComponent imple
this.modalMessage = data.message
}
}

ngOnDestroy(): void {
this.bsModalRef.hide()
}
}
Loading
Loading