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
4 changes: 3 additions & 1 deletion client/src/app/domain/models/meetings/meeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ export class Settings {

// General poll settings
public poll_enable_max_yes_votes: boolean;
public poll_default_required_majority: `no_majority` | `two_third_majority` | `absolute_majority`;
public poll_default_required_majority:
`no_majority` | `two_third_majority` | `absolute_majority` | `simple_majority`;

public poll_default_live_voting_enabled: boolean;
public poll_enable_max_votes_per_option: boolean;
public poll_default_allow_invalid: boolean;
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/domain/models/poll/poll-config-rating-score.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HasMeetingId } from '../../interfaces/has-meeting-id';
import { PollRequiredMajority } from '.';
import { BasePollConfigModel } from './base-poll-config';
import { SelectionRequiredMajority } from './poll-config-selection';
import { BaseOnehundredPercentBase } from './poll-config-types';

export type RatingScoreOnehundredPercentBase = BaseOnehundredPercentBase | `yes_no`;
Expand All @@ -14,7 +14,7 @@ export class PollConfigRatingScore extends BasePollConfigModel<PollConfigRatingS
public max_vote_sum!: number;
public min_vote_sum!: number;
public onehundred_percent_base!: RatingScoreOnehundredPercentBase;
public required_majority!: PollRequiredMajority;
public required_majority!: SelectionRequiredMajority;

public constructor(input?: Partial<PollConfigRatingScore>) {
super(PollConfigRatingScore.COLLECTION, input);
Expand Down
3 changes: 2 additions & 1 deletion client/src/app/domain/models/poll/poll-config-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BasePollConfigModel } from './base-poll-config';
import { BaseOnehundredPercentBase } from './poll-config-types';

export type SelectionOnehundredPercentBase = BaseOnehundredPercentBase | `no_general`;
export type SelectionRequiredMajority = PollRequiredMajority | `simple_majority`;

export class PollConfigSelection extends BasePollConfigModel<PollConfigSelection> {
public static COLLECTION = `poll_config_selection`;
Expand All @@ -14,7 +15,7 @@ export class PollConfigSelection extends BasePollConfigModel<PollConfigSelection
public allow_nota!: boolean;
public display_chart!: string;
public onehundred_percent_base!: SelectionOnehundredPercentBase;
public required_majority!: PollRequiredMajority;
public required_majority!: SelectionRequiredMajority;

public get max_vote_sum(): number {
return this.max_options_amount;
Expand Down
3 changes: 2 additions & 1 deletion client/src/app/domain/models/poll/poll-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export enum PollVisibility {
export enum PollRequiredMajority {
NoMajority = `no_majority`,
TwoThirdMajority = `two_third_majority`,
AbsoluteMajority = `absolute_majority`
AbsoluteMajority = `absolute_majority`,
SimpleMajority = `simple_majority`
}

/**
Expand Down
8 changes: 7 additions & 1 deletion client/src/app/domain/models/poll/poll-entitled-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ export class PollEntitledUser extends BaseModel<PollEntitledUser> {

public poll_id!: Id;
public meeting_user_id: Id;
public present: boolean;

public constructor(input?: Partial<PollEntitledUser>) {
super(PollEntitledUser.COLLECTION, input);
}

public static readonly REQUESTABLE_FIELDS: (keyof PollEntitledUser)[] = [`id`, `poll_id`, `meeting_user_id`];
public static readonly REQUESTABLE_FIELDS: (keyof PollEntitledUser)[] = [
`id`,
`poll_id`,
`meeting_user_id`,
`present`
];
}
2 changes: 2 additions & 0 deletions client/src/app/domain/models/poll/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class Poll extends BaseModel<Poll> {
public result!: string;
public anonymized!: boolean;
public published!: boolean;
public allow_empty!: boolean;
public allow_invalid!: boolean;
public allow_vote_split!: boolean;
public option_ids!: Id[];
Expand All @@ -42,6 +43,7 @@ export class Poll extends BaseModel<Poll> {
`result`,
`published`,
`anonymized`,
`allow_empty`,
`allow_invalid`,
`allow_vote_split`,
`live_voting_enabled`,
Expand Down
3 changes: 2 additions & 1 deletion client/src/app/domain/translations/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ export default {
'poll_percent_base.disabled': _(`Disabled (no percents)`),
'poll_required_majority.no_majority': _(`No majority`),
'poll_required_majority.two_third_majority': _(`Two thirds`),
'poll_required_majority.absolute_majority': _(`Absolute`)
'poll_required_majority.absolute_majority': _(`Absolute`),
'poll_required_majority.simple_majority': _(`Simple`)
};
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,6 @@ export class PollRepositoryService extends BaseMeetingRelatedRepository<ViewPoll
}

public async update(poll: ViewPoll, payload: PollUpdatePayload): Promise<void> {
if (payload.visibility === PollVisibility.Manually) {
return this.updateAnalogPoll(poll, payload);
}

return this.updateElectronicPoll(poll, payload);
}

private async createAnalogPoll(payload: any): Promise<Identifiable> {
delete payload.live_voting_enabled;

return this.voteApi.create(payload);
}

private async createElectronicPoll(payload: PollCreatePayload): Promise<Identifiable> {
if (payload.visibility !== PollVisibility.Named && payload.visibility !== PollVisibility.Open) {
delete payload.live_voting_enabled;
}

return this.voteApi.create(payload);
}

private async updateAnalogPoll(poll: ViewPoll, payload: PollUpdatePayload): Promise<void> {
if (poll.config.method === payload.method) {
delete payload[`method`];
}

return this.voteApi.update(poll.id, payload);
}

private async updateElectronicPoll(poll: ViewPoll, payload: PollUpdatePayload): Promise<void> {
if (poll.state !== PollState.Created) {
const methodConfig: {
display_chart?: string;
Expand All @@ -89,7 +59,8 @@ export class PollRepositoryService extends BaseMeetingRelatedRepository<ViewPoll
display_chart: methodConfig.display_chart,
onehundred_percent_base: methodConfig.onehundred_percent_base,
required_majority: methodConfig.required_majority
}
},
result: poll.visibility === PollVisibility.Manually && payload.result ? payload.result : undefined
});
} else if (poll.config.method === payload.method) {
delete payload[`method`];
Expand All @@ -98,6 +69,20 @@ export class PollRepositoryService extends BaseMeetingRelatedRepository<ViewPoll
return this.voteApi.update(poll.id, payload);
}

private async createAnalogPoll(payload: any): Promise<Identifiable> {
delete payload.live_voting_enabled;

return this.voteApi.create(payload);
}

private async createElectronicPoll(payload: PollCreatePayload): Promise<Identifiable> {
if (payload.visibility !== PollVisibility.Named && payload.visibility !== PollVisibility.Open) {
delete payload.live_voting_enabled;
}

return this.voteApi.create(payload);
}

public async delete(poll: Identifiable): Promise<void> {
return this.voteApi.deletePoll(poll.id);
}
Expand Down
7 changes: 4 additions & 3 deletions client/src/app/gateways/vote-api.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Service } from '@angular/core';

import { Id } from '../domain/definitions/key-types';
import { PollVisibility } from '../domain/models/poll/poll-constants';
Expand All @@ -20,13 +20,14 @@ export interface PollUpdatePayload {
option_type?: 'text' | 'meeting_user';
result?: unknown;
allow_vote_split: boolean;
allow_empty?: boolean;
}

@Injectable({ providedIn: 'root' })
@Service()
export class VoteApiService {
private readonly BASE = '/system/vote';

public constructor(private http: HttpService) {}
private http = inject(HttpService);

public create(payload: PollCreatePayload): Promise<any> {
return this.http.post(`${this.BASE}/poll`, payload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,46 @@ export abstract class BasePollDialogComponent extends BaseUiComponent {
public dialogRef = inject(MatDialogRef<BasePollDialogComponent>);
public pollData: ViewPoll = inject(MAT_DIALOG_DATA);

public currentPollData: ViewPoll = this.pollData;

public constructor() {
super();
this.addKeyListener();
}

public toggleAnalogPollForm(): void {
const payload = this.getPayload();
if (payload.result && !(payload.result instanceof String)) {
payload.result = JSON.stringify(payload.result);
}
this.currentPollData = Object.assign(this.currentPollData, payload);
this.analogPollFormOpen.set(!this.analogPollFormOpen());
}

/**
* Submits the values from dialog.
*/
public submitPoll(): void {
this.dialogRef.close(this.getPayload());
}

/**
* Returns the poll method related part of the payload
*/
public abstract methodPayload(): PollMethodPayload;

/**
* Returns the poll options related part of the payload
*/
public abstract optionsPayload(): PollOptionsPayload;

protected getPayload(): PollUpdatePayload {
const formValues = this.pollForm().getValues();
const visibility: PollVisibility = formValues?.visibility;

const payload: PollUpdatePayload = {
title: formValues?.title,
allow_empty: formValues?.allow_empty,
...this.methodPayload(),
...this.optionsPayload(),
visibility,
Expand All @@ -87,19 +113,9 @@ export abstract class BasePollDialogComponent extends BaseUiComponent {
}
}

this.dialogRef.close(payload);
return payload;
}

/**
* Returns the poll method related part of the payload
*/
public abstract methodPayload(): PollMethodPayload;

/**
* Returns the poll options related part of the payload
*/
public abstract optionsPayload(): PollOptionsPayload;

private addKeyListener(): void {
if (!this.dialogRef) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export abstract class PollFormBaseComponent {
protected abstract getPatchedFormData(data: Partial<ViewPoll>): Record<string, unknown>;
public abstract getSerialzedForm(): Record<string, unknown>;

public getSerialzedAdditionalData(): Record<string, unknown> {
return {};
}

private onDataUpdated(): void {
if (!this.data() || !this.form) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ <h3>{{ option.title }}</h3>
<div class="option">
<mat-form-field class="option-amount">
<mat-label>Global abstain</mat-label>
<input matInput type="number" [formField]="resultForm.abstain" />
<input matInput type="number" [formField]="resultForm.empty" />
</mat-form-field>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, input, OnInit, signal } from '@angular/core';
import { Component, computed, input, OnInit, signal } from '@angular/core';
import { applyEach, disabled, form, FormField, schema } from '@angular/forms/signals';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
Expand Down Expand Up @@ -39,7 +39,7 @@ interface OptionFormEntry {

interface PollEditResultModel {
options: OptionFormEntry[];
abstain: number;
empty: number;
nota: number;
invalid: number;
total_ballots: number;
Expand All @@ -59,8 +59,7 @@ interface PollEditResultModel {
FormField,
TranslatePipe,
NgTemplateOutlet
],
changeDetection: ChangeDetectionStrategy.OnPush
]
})
export class PollEditResultComponent implements OnInit {
public readonly pollData = input.required<Partial<Poll>>();
Expand All @@ -72,7 +71,7 @@ export class PollEditResultComponent implements OnInit {

private readonly model = signal<PollEditResultModel>({
options: [],
abstain: 0,
empty: 0,
nota: 0,
invalid: 0,
total_ballots: 0
Expand Down Expand Up @@ -102,8 +101,7 @@ export class PollEditResultComponent implements OnInit {
});

public showAbstain = computed(() => {
const cfg = this.pollConfigDataLax();
return cfg.min_options_amount === 0 && (cfg.min_vote_sum === 0 || cfg.min_vote_sum === undefined);
return this.pollData().allow_empty;
});

public showNota = computed(() => {
Expand Down Expand Up @@ -154,7 +152,7 @@ export class PollEditResultComponent implements OnInit {

this.model.set({
options: builtOptions,
abstain: this.showAbstain() ? (result[`abstain`] ?? null) : null,
empty: this.showAbstain() ? (result[`empty`] ?? null) : null,
nota: result[`nota`] ?? null,
invalid: result[`invalid`] ?? null,
total_ballots: result[`total_ballots`] ?? null
Expand All @@ -172,7 +170,7 @@ export class PollEditResultComponent implements OnInit {
.total_ballots()
.value.set(
data.invalid +
data.abstain +
data.empty +
data.nota +
data.options.reduce((p, c) => p + c.value.yes + c.value.no + c.value.abstain, 0)
);
Expand All @@ -181,7 +179,7 @@ export class PollEditResultComponent implements OnInit {
.total_ballots()
.value.set(
data.invalid +
data.abstain +
data.empty +
data.nota +
data.options.reduce((p, c) => Math.max(c.value.yes + c.value.no + c.value.abstain, p), 0)
);
Expand Down Expand Up @@ -223,7 +221,7 @@ export class PollEditResultComponent implements OnInit {
: serializedOptions),
...(m.invalid !== null ? { invalid: m.invalid } : {}),
...(m.total_ballots !== null ? { total_ballots: m.total_ballots } : {}),
...(this.showAbstain() ? { abstain: m.abstain } : {}),
...(this.showAbstain() ? { empty: m.empty } : {}),
...(this.showNota() ? { nota: m.nota } : {})
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import { Component, input } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatFormFieldModule } from '@angular/material/form-field';
Expand Down Expand Up @@ -26,8 +26,7 @@ export interface PollFormApproval {
TranslateKeyPipe
],
templateUrl: './poll-form-approval.component.html',
styleUrl: './poll-form-approval.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush
styleUrl: './poll-form-approval.component.scss'
})
export class PollFormApprovalComponent extends PollFormBaseComponent {
public hideMethod = input<boolean>(false);
Expand All @@ -38,7 +37,7 @@ export class PollFormApprovalComponent extends PollFormBaseComponent {
[`valid`, _('All valid ballots')],
[`cast`, _('All casted ballots')],
[`entitled`, _('All entitled users')],
// [`entitled_present`, _('Present entitled users')],
[`entitled_present`, _('Present entitled users')],
[`disabled`, _('Disabled (no percents)')]
];

Expand Down
Loading
Loading