Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@
}
}
</div>
@if (activeMeetingSetting && canEditOwnDelegation(user)) {
<button mat-menu-item (click)="openDialogEditInfo(user)">
<mat-icon>edit</mat-icon>
<span>{{ 'Change your delegation' | translate }}</span>
</button>
}
}
</div>
<mat-divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { Observable, Subscription } from 'rxjs';
import { Id } from 'src/app/domain/definitions/key-types';
import { allAvailableTranslations, availableTranslations } from 'src/app/domain/definitions/languages';
import { getOmlVerboseName } from 'src/app/domain/definitions/organization-permission';
import { Permission } from 'src/app/domain/definitions/permission';
import { largeDialogSettings } from 'src/app/infrastructure/utils/dialog-settings';
import { mediumDialogSettings } from 'src/app/infrastructure/utils/dialog-settings';
import { ParticipantListInfoDialogService } from 'src/app/site/pages/meetings/pages/participants/pages/participant-list/modules/participant-list-info-dialog';
import { ActiveMeetingIdService } from 'src/app/site/pages/meetings/services/active-meeting-id.service';
import { MeetingSettingsService } from 'src/app/site/pages/meetings/services/meeting-settings.service';
import { ViewUser } from 'src/app/site/pages/meetings/view-models/view-user';
Expand Down Expand Up @@ -70,13 +72,21 @@ export class AccountButtonComponent extends BaseUiComponent implements OnInit {

public username = ``;
public isLoggedIn = false;
private _voteDelegationEnabled = false;

public show1337 = -20;

private get activeMeetingId(): Id | null {
return this.activeMeetingIdService.meetingId;
}

public get activeMeetingSetting(): boolean {
this.meetingSettingsService
.get(`users_enable_vote_delegations`)
.subscribe(enabled => (this._voteDelegationEnabled = enabled));
return this._voteDelegationEnabled;
}

private _isAllowedSelfSetPresent = false;
private _languageTrigger: MatMenuTrigger | undefined = undefined;
private clickCounter = 0;
Expand All @@ -88,6 +98,7 @@ export class AccountButtonComponent extends BaseUiComponent implements OnInit {
private userRepo: UserControllerService,
private authService: AuthService,
private dialog: MatDialog,
private participantListDialog: ParticipantListInfoDialogService,
private router: Router,
private theme: ThemeService,
private meetingSettingsService: MeetingSettingsService,
Expand Down Expand Up @@ -226,4 +237,33 @@ export class AccountButtonComponent extends BaseUiComponent implements OnInit {
}
return stringForUserPresent.replace(`{}`, this.user.short_name);
}

public canEditOwnDelegation(user: ViewUser): boolean {
if (
this.operator.hasPerms(Permission.userCanEditOwnDelegation) &&
!this.operator.hasPerms(Permission.userCanManage) &&
!this.operator.hasPerms(Permission.userCanUpdate)
) {
return this.operator.operatorId === user.id;
} else if (
this.operator.hasPerms(Permission.userCanManage) ||
this.operator.hasPerms(Permission.userCanUpdate)
) {
return true;
} else {
return false;
}
}

public async openDialogEditInfo(user: ViewUser): Promise<void> {
await this.participantListDialog.open({
user,
id: user.id,
name: user.getName(),
number: user.number(),
structure_level_ids: this.user.structure_level_ids(),
vote_delegations_from_ids: this.user.vote_delegations_from_meeting_user_ids(),
vote_delegated_to_id: this.user.vote_delegated_to_meeting_user_id()
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,7 @@ <h1 class="mock-h2" translate>Participants</h1>
<mat-icon>record_voice_over</mat-icon>
<span translate>Contributions</span>
</button>
<button
*osPerms="permission.userCanUpdate; or: canEditOwnDelegation(operator.user)"
mat-menu-item
(click)="openEditInfo(operator.user)"
>
<mat-icon>edit</mat-icon>
<span>{{ 'Change your delegation' | translate }}</span>
</button>

<button mat-menu-item (click)="pdfExportUserList()">
<mat-icon>picture_as_pdf</mat-icon>
<span>{{ 'List of participants (PDF)' | translate }}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,7 @@ export class ParticipantListComponent extends BaseMeetingListViewComponent<ViewU

/**
* This function opens the dialog,
* where the user can quick change the groups,
* the gender and the participant number.
* where the user can quick change the delegations.
*
* @param user is an instance of ViewUser. This is the given user, who will be modified.
*/
Expand All @@ -364,13 +363,7 @@ export class ParticipantListComponent extends BaseMeetingListViewComponent<ViewU
}
ev?.stopPropagation();
const dialogRef = await this.infoDialog.open({
id: user.id,
name: user.short_name,
group_ids: user.group_ids(),
number: user.number(),
structure_level_ids: user.structure_level_ids(),
vote_delegations_from_ids: user.vote_delegations_from_meeting_user_ids(),
vote_delegated_to_id: user.vote_delegated_to_meeting_user_id()
user
});

dialogRef.afterClosed().subscribe(async result => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,32 @@
<h1 mat-dialog-title>
<span>{{ 'Edit details for' | translate }} {{ infoDialog.name }}</span>
<span>{{ 'Edit your own delegation' | translate }}</span>
</h1>
<mat-dialog-content class="os-form-card-mobile">
<mat-form-field>
<mat-label>{{ 'Groups' | translate }}</mat-label>
<mat-select multiple [disabled]="canOnlyEditOwnDelegation" [(ngModel)]="infoDialog.group_ids">
@for (group of groupsObservable | async; track group) {
<mat-option [value]="group.id">
{{ group.getTitle() }}
</mat-option>
}
</mat-select>
</mat-form-field>
@if (showVoteDelegations) {
<mat-form-field>
<mat-label>{{ 'Voting right received from (principals)' | translate }}</mat-label>
<os-list-search-selector
[disableOptionWhenFn]="getDisableOptionFn(infoDialog.vote_delegations_from_ids)"
[inputListValues]="otherParticipantsObservable"
[multiple]="true"
[sortFn]="false"
[(ngModel)]="infoDialog.vote_delegations_from_ids"
/>
</mat-form-field>

<mat-form-field>
<mat-label>{{ 'Voting right delegated to (proxy)' | translate }}</mat-label>
<os-list-search-selector
[includeNone]="true"
[inputListValues]="otherParticipantsObservable"
[multiple]="false"
[sortFn]="false"
[(ngModel)]="infoDialog.vote_delegated_to_id"
/>
</mat-form-field>
}
<mat-form-field>
<mat-label>{{ 'Structure level' | translate }}</mat-label>
<os-list-search-selector
[disabled]="canOnlyEditOwnDelegation"
[includeNone]="true"
[inputListValues]="structureLevelObservable"
<mat-label>{{ 'Voting right received from (principals)' | translate }}</mat-label>
<os-repo-search-selector
[disableOptionWhenFn]="getDisableOptionFn(infoDialog.vote_delegations_from_ids)"
[multiple]="true"
[(ngModel)]="infoDialog.structure_level_ids"
[pipeFn]="excludeCurrentUserFn"
[repo]="userRepo"
[sortFn]="false"
[(ngModel)]="infoDialog.vote_delegations_from_ids"
/>
@if (setting?.helpText) {
<mat-hint>{{ setting.helpText | translate }}</mat-hint>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'Participant number' | translate }}</mat-label>
<input matInput type="text" [disabled]="canOnlyEditOwnDelegation" [(ngModel)]="infoDialog.number" />
<mat-form-field class="margin">
<mat-label>{{ 'Voting right delegated to (proxy)' | translate }}</mat-label>
<os-repo-search-selector
[includeNone]="true"
[multiple]="false"
[pipeFn]="excludeCurrentUserFn"
[repo]="userRepo"
[sortFn]="false"
[subscriptionConfig]="participantSubscriptionConfig"
[(ngModel)]="infoDialog.vote_delegated_to_id"
/>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.margin {
margin-top: 12px;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { Component, Inject, inject, OnDestroy, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { BehaviorSubject, Observable } from 'rxjs';
import { BehaviorSubject, filter, map, Observable } from 'rxjs';
import { Permission } from 'src/app/domain/definitions/permission';
import { Selectable } from 'src/app/domain/interfaces/selectable';
import { SubscriptionConfig } from 'src/app/domain/interfaces/subscription-config';
import { GENDERS } from 'src/app/domain/models/users/user';
import { UserRepositoryService } from 'src/app/gateways/repositories/users';
import { ViewGroup } from 'src/app/site/pages/meetings/pages/participants';
import { GroupControllerService } from 'src/app/site/pages/meetings/pages/participants/modules';
import { ParticipantControllerService } from 'src/app/site/pages/meetings/pages/participants/services/common/participant-controller.service';
import { ActiveMeetingIdService } from 'src/app/site/pages/meetings/services/active-meeting-id.service';
import { MeetingSettingsService } from 'src/app/site/pages/meetings/services/meeting-settings.service';
import { SettingsInput } from 'src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions';
import { ViewMeetingUser } from 'src/app/site/pages/meetings/view-models/view-meeting-user';
import { ViewUser } from 'src/app/site/pages/meetings/view-models/view-user';
import { OperatorService } from 'src/app/site/services/operator.service';
import { BaseUiComponent } from 'src/app/ui/base/base-ui-component';

import { getParticipantListSubscriptionConfig } from '../../../../../../participants.subscription';
import { StructureLevelControllerService } from '../../../../../structure-levels/services/structure-level-controller.service';
import { ViewStructureLevel } from '../../../../../structure-levels/view-models';
import { ParticipantListSortService } from '../../../../services/participant-list-sort/participant-list-sort.service';
Expand Down Expand Up @@ -52,37 +57,43 @@ export class ParticipantListInfoDialogComponent extends BaseUiComponent implemen
private readonly _otherParticipantsSubject = new BehaviorSubject<ViewMeetingUser[]>([]);
private _currentUser: ViewUser | null = null;
private _voteDelegationEnabled = false;
public userList = this.participantRepo.getViewModelListObservable();
protected participantSubscriptionConfig: SubscriptionConfig<any>;

protected setting: SettingsInput = {} as SettingsInput;

public constructor(
@Inject(MAT_DIALOG_DATA) public readonly infoDialog: InfoDialog,
private participantRepo: ParticipantControllerService,
private userSortService: ParticipantListSortService,
private groupRepo: GroupControllerService,
private structureLevelRepo: StructureLevelControllerService,
private activeMeetingIdService: ActiveMeetingIdService,
private meetingSettings: MeetingSettingsService,
private operator: OperatorService
private operator: OperatorService,
protected userRepo: UserRepositoryService = inject(UserRepositoryService)
) {
super();
}

public ngOnInit(): void {
this.userSortService.initSorting();
this.participantSubscriptionConfig = getParticipantListSubscriptionConfig(
this.activeMeetingIdService.meetingId
);
this.setting.helpText = 'You can only delete delegations you have received';
this._currentUser = this.participantRepo.getViewModel(this.infoDialog.id);
this.structureLevelObservable = this.structureLevelRepo.getViewModelListObservable();
this.subscriptions.push(
this.participantRepo
.getSortedViewModelListObservable(this.userSortService.repositorySortingKey)
.subscribe(participants =>
this._otherParticipantsSubject.next(
participants
.filter(participant => participant.id !== this._currentUser.id)
.map(participant => participant.getMeetingUser())
)
),
this.userRepo
.getGeneralViewModelObservable()
.pipe(filter((participant: ViewUser) => participant.id !== this._currentUser.id))
.subscribe((participant: ViewUser) => participant.getMeetingUser()),
this.meetingSettings
.get(`users_enable_vote_delegations`)
.subscribe(enabled => (this._voteDelegationEnabled = enabled))
);

this.structureLevelObservable = this.structureLevelRepo.getViewModelListObservable();
}

public override ngOnDestroy(): void {
Expand All @@ -99,4 +110,7 @@ export class ParticipantListInfoDialogComponent extends BaseUiComponent implemen
return _ => false;
}
}

public excludeCurrentUserFn: any = observable$ =>
observable$.pipe(map((users: ViewUser[]) => users.filter(user => user.id !== this._currentUser?.id)));
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { firstValueFrom } from 'rxjs';
import { Id } from 'src/app/domain/definitions/key-types';
import { Identifiable } from 'src/app/domain/interfaces';
import { infoDialogSettings } from 'src/app/infrastructure/utils/dialog-settings';
import { ViewUser } from 'src/app/site/pages/meetings/view-models/view-user';
import { BaseDialogService } from 'src/app/ui/base/base-dialog-service';

import { ParticipantControllerService } from '../../../../../services/common/participant-controller.service';
import { ParticipantListInfoDialogComponent } from '../components/participant-list-info-dialog/participant-list-info-dialog.component';

/**
Expand Down Expand Up @@ -52,9 +53,11 @@ export class ParticipantListInfoDialogService extends BaseDialogService<
Partial<InfoDialog>,
InfoDialog
> {
public async open(
data: Partial<InfoDialog> & Identifiable
): Promise<MatDialogRef<ParticipantListInfoDialogComponent, InfoDialog>> {
public constructor(private controller: ParticipantControllerService) {
super();
}

public async open(data: Partial<InfoDialog> & { user: ViewUser }): Promise<any> {
const module = await import(`../participant-list-info-dialog.module`).then(
m => m.ParticipantListInfoDialogModule
);
Expand All @@ -64,6 +67,12 @@ export class ParticipantListInfoDialogService extends BaseDialogService<
dialogRef.close(data);
}
});
return dialogRef;
const result = await firstValueFrom(dialogRef.afterClosed());
result.vote_delegated_to_id = result.vote_delegated_to_id === 0 ? null : result.vote_delegated_to_id;
this.update(result, data.user);
}

protected async update(payload: any, user: ViewUser): Promise<void> {
await this.controller.update(payload, user).resolve();
}
}
Loading