diff --git a/client/src/app/core/ui-services/poll.service.ts b/client/src/app/core/ui-services/poll.service.ts
index 23f4e8bb4..09e522c51 100644
--- a/client/src/app/core/ui-services/poll.service.ts
+++ b/client/src/app/core/ui-services/poll.service.ts
@@ -169,6 +169,7 @@ export abstract class PollService {
public getSpecialLabel(value: number): string {
if (value >= 0) {
return value.toString();
+ // TODO: toLocaleString(lang); but translateService is not usable here, thus lang is not well defined
}
const vote = this.specialPollVotes.find(special => special[0] === value);
return vote ? vote[1] : 'Undocumented special (negative) value';
diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html
index f40ff7eb8..318a3fa98 100644
--- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html
+++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html
@@ -28,14 +28,22 @@
PDF
-
+
+
+
+
+
diff --git a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html
index 549422ef5..e1c4e374f 100644
--- a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html
+++ b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html
@@ -36,8 +36,8 @@
-
-
+
+
Projector
diff --git a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.scss b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.scss
index e69de29bb..5bd6af3bf 100644
--- a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.scss
+++ b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.scss
@@ -0,0 +1,4 @@
+/** Title */
+.mat-column-title {
+ padding-left: 10px;
+}
diff --git a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts
index ecfaae768..967e5a3e1 100644
--- a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts
+++ b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts
@@ -3,17 +3,12 @@ import { MatDialogRef, MAT_DIALOG_DATA, MatSnackBar } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { AssignmentPollOption } from 'app/shared/models/assignments/assignment-poll-option';
-import { AssignmentPollService } from '../../services/assignment-poll.service';
+import { AssignmentPollService, SummaryPollKey } from '../../services/assignment-poll.service';
import { CalculablePollKey, PollVoteValue } from 'app/core/ui-services/poll.service';
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
import { ViewAssignmentPoll } from '../../models/view-assignment-poll';
import { ViewAssignmentPollOption } from '../../models/view-assignment-poll-option';
-/**
- * Vote entries included once for summary (e.g. total votes cast)
- */
-type summaryPollKey = 'votescast' | 'votesvalid' | 'votesinvalid';
-
/**
* A dialog for updating the values of an assignment-related poll.
*/
@@ -26,7 +21,7 @@ export class AssignmentPollDialogComponent {
/**
* The summary values that will have fields in the dialog
*/
- public sumValues: summaryPollKey[] = ['votesvalid', 'votesinvalid', 'votescast'];
+ public sumValues: SummaryPollKey[] = ['votesvalid', 'votesinvalid', 'votescast'];
/**
* List of accepted special non-numerical values.
@@ -148,7 +143,7 @@ export class AssignmentPollDialogComponent {
* @param value
* @returns integer or undefined
*/
- public getSumValue(value: summaryPollKey): number | undefined {
+ public getSumValue(value: SummaryPollKey): number | undefined {
return this.data[value] || undefined;
}
@@ -158,7 +153,7 @@ export class AssignmentPollDialogComponent {
* @param value
* @param weight
*/
- public setSumValue(value: summaryPollKey, weight: string): void {
+ public setSumValue(value: SummaryPollKey, weight: string): void {
this.data[value] = parseFloat(weight);
}
diff --git a/client/src/app/site/assignments/services/assignment-poll.service.ts b/client/src/app/site/assignments/services/assignment-poll.service.ts
index 44f1ee992..71b41cffa 100644
--- a/client/src/app/site/assignments/services/assignment-poll.service.ts
+++ b/client/src/app/site/assignments/services/assignment-poll.service.ts
@@ -15,6 +15,11 @@ type AssignmentPollValues = 'auto' | 'votes' | 'yesnoabstain' | 'yesno';
export type AssignmentPollMethod = 'yn' | 'yna' | 'votes';
export type AssignmentPercentBase = 'YES_NO_ABSTAIN' | 'YES_NO' | 'VALID' | 'CAST' | 'DISABLED';
+/**
+ * Vote entries included once for summary (e.g. total votes cast)
+ */
+export type SummaryPollKey = 'votescast' | 'votesvalid' | 'votesinvalid' | 'votesno' | 'votesabstain';
+
/**
* Service class for assignment polls.
*/
diff --git a/client/src/app/slides/assignments/assignment/assignment-slide.component.html b/client/src/app/slides/assignments/assignment/assignment-slide.component.html
index edc11e288..5c66fea3f 100644
--- a/client/src/app/slides/assignments/assignment/assignment-slide.component.html
+++ b/client/src/app/slides/assignments/assignment/assignment-slide.component.html
@@ -1,3 +1,16 @@
-
TODO
+
+
{{ data.data.title }}
+
+
+
+
+
+
Candidates
+
+
+ {{ candidate.user }}
+ {{ candidate.elected ? 'star' : 'star_border' }}
+
+
diff --git a/client/src/app/slides/assignments/assignment/assignment-slide.component.ts b/client/src/app/slides/assignments/assignment/assignment-slide.component.ts
index 1a4d84fd1..2b3eb096a 100644
--- a/client/src/app/slides/assignments/assignment/assignment-slide.component.ts
+++ b/client/src/app/slides/assignments/assignment/assignment-slide.component.ts
@@ -17,12 +17,11 @@ export class AssignmentSlideComponent extends BaseSlideComponent) {
this._data = data;
- console.log('Data: ', data);
}
+
public get data(): SlideData {
return this._data;
}
- // UNTIL HERE
public constructor() {
super();
diff --git a/client/src/app/slides/assignments/poll/poll-slide-data.ts b/client/src/app/slides/assignments/poll/poll-slide-data.ts
index e72af43b1..532389dd3 100644
--- a/client/src/app/slides/assignments/poll/poll-slide-data.ts
+++ b/client/src/app/slides/assignments/poll/poll-slide-data.ts
@@ -1,4 +1,15 @@
import { AssignmentPercentBase, AssignmentPollMethod } from 'app/site/assignments/services/assignment-poll.service';
+import { PollVoteValue } from 'app/core/ui-services/poll.service';
+
+export interface PollSlideOption {
+ user: string;
+ is_elected: boolean;
+ votes: {
+ weight: PollVoteValue;
+ value: string;
+ percent?: string;
+ }[];
+}
export interface PollSlideData {
title: string;
@@ -13,5 +24,6 @@ export interface PollSlideData {
votesvalid?: string;
votesinvalid?: string;
votescast?: string;
+ options?: PollSlideOption[];
};
}
diff --git a/client/src/app/slides/assignments/poll/poll-slide.component.html b/client/src/app/slides/assignments/poll/poll-slide.component.html
index edc11e288..1d54257d7 100644
--- a/client/src/app/slides/assignments/poll/poll-slide.component.html
+++ b/client/src/app/slides/assignments/poll/poll-slide.component.html
@@ -1,3 +1,60 @@
-
TODO
+
{{ data.data.title }}
+
+
Waiting for results...
+
+
+
+
+
Candidates
+
+
+
Votes
+
+
+
+
+
+ star
+ {{ option.user }}
+
+
+
+ {{ vote.value | translate }}:
+
+ {{ labelValue(vote.weight) | translate }}
+
+
+ ({{ vote.percent }})
+
+
+
+
+
+
+
+ Valid votes
+
+
+ {{ labelValue(data.data.poll.votesvalid) | translate }}
+
+
+
+
+ Invalid votes
+
+
+ {{ labelValue(data.data.poll.votesinvalid) | translate }}
+
+
+
+
+ Total votes cast
+
+
+ {{ labelValue(data.data.poll.votescast) | translate }}
+
+
+
+
diff --git a/client/src/app/slides/assignments/poll/poll-slide.component.scss b/client/src/app/slides/assignments/poll/poll-slide.component.scss
index e69de29bb..04eb64c42 100644
--- a/client/src/app/slides/assignments/poll/poll-slide.component.scss
+++ b/client/src/app/slides/assignments/poll/poll-slide.component.scss
@@ -0,0 +1,20 @@
+.row {
+ display: table;
+ width: 100%;
+ .option-name {
+ display: table-cell;
+ padding: 5px;
+ border: 1px solid grey;
+ vertical-align: middle;
+ width: 70%;
+ .bold {
+ font-weight: bold;
+ }
+ }
+ .option-percents {
+ display: table-cell;
+ padding: 5px;
+ border: 1px solid grey;
+ width: 30%;
+ }
+}
diff --git a/client/src/app/slides/assignments/poll/poll-slide.component.ts b/client/src/app/slides/assignments/poll/poll-slide.component.ts
index f1bbaaf9e..4ad071ee0 100644
--- a/client/src/app/slides/assignments/poll/poll-slide.component.ts
+++ b/client/src/app/slides/assignments/poll/poll-slide.component.ts
@@ -1,5 +1,6 @@
import { Component, Input } from '@angular/core';
+import { AssignmentPollService, SummaryPollKey } from 'app/site/assignments/services/assignment-poll.service';
import { BaseSlideComponent } from 'app/slides/base-slide-component';
import { PollSlideData } from './poll-slide-data';
import { SlideData } from 'app/core/core-services/projector-data.service';
@@ -10,21 +11,87 @@ import { SlideData } from 'app/core/core-services/projector-data.service';
styleUrls: ['./poll-slide.component.scss']
})
export class PollSlideComponent extends BaseSlideComponent {
- // TODO: Remove the following block, if not needed.
- // This is just for debugging to get a console statement with all recieved
- // data from the server
private _data: SlideData;
+
+ public pollValues: SummaryPollKey[] = ['votesno', 'votesabstain', 'votesvalid', 'votesinvalid', 'votescast'];
+
@Input()
public set data(data: SlideData) {
this._data = data;
- console.log('Data: ', data);
+ this.setPercents();
}
+
public get data(): SlideData {
return this._data;
}
- // UNTIL HERE
- public constructor() {
+ public constructor(private pollService: AssignmentPollService) {
super();
}
+
+ public getVoteString(rawValue: string): string {
+ const num = parseFloat(rawValue);
+ if (!isNaN(num)) {
+ return this.pollService.getSpecialLabel(num);
+ }
+ return '-';
+ }
+
+ private setPercents(): void {
+ if (
+ this.data.data.assignments_poll_100_percent_base === 'DISABLED' ||
+ !this.data.data.poll.has_votes ||
+ !this.data.data.poll.options.length
+ ) {
+ return;
+ }
+ for (const option of this.data.data.poll.options) {
+ for (const vote of option.votes) {
+ const voteweight = parseFloat(vote.weight);
+ if (isNaN(voteweight) || voteweight < 0) {
+ return;
+ }
+ let base: number;
+ switch (this.data.data.assignments_poll_100_percent_base) {
+ case 'CAST':
+ base = this.data.data.poll.votescast ? parseFloat(this.data.data.poll.votescast) : 0;
+ break;
+ case 'VALID':
+ base = this.data.data.poll.votesvalid ? parseFloat(this.data.data.poll.votesvalid) : 0;
+ break;
+ case 'YES_NO':
+ case 'YES_NO_ABSTAIN':
+ const yesOption = option.votes.find(v => v.value === 'Yes');
+ const yes = yesOption ? parseFloat(yesOption.weight) : -1;
+ const noOption = option.votes.find(v => v.value === 'No');
+ const no = noOption ? parseFloat(noOption.weight) : -1;
+ const absOption = option.votes.find(v => v.value === 'Abstain');
+ const abs = absOption ? parseFloat(absOption.weight) : -1;
+ if (this.data.data.assignments_poll_100_percent_base === 'YES_NO_ABSTAIN') {
+ base = yes >= 0 && no >= 0 && abs >= 0 ? yes + no + abs : 0;
+ } else {
+ if (vote.value !== 'Abstain') {
+ base = yes >= 0 && no >= 0 ? yes + no : 0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (base) {
+ vote.percent = `${Math.round(((parseFloat(vote.weight) * 100) / base) * 100) / 100}%`;
+ }
+ }
+ }
+ }
+
+ /**
+ * Converts a number-like string to a simpler, more readable version
+ *
+ * @param input a server-sent string representing a numerical value
+ * @returns either the special label or a cleaned-up number of the inpu string
+ */
+ public labelValue(input: string): string {
+ return this.pollService.getSpecialLabel(parseFloat(input));
+ }
}
diff --git a/openslides/assignments/projector.py b/openslides/assignments/projector.py
index 1fb2e4d06..581166f25 100644
--- a/openslides/assignments/projector.py
+++ b/openslides/assignments/projector.py
@@ -87,7 +87,7 @@ async def poll_slide(
poll_data["options"] = [
{
- "user": await get_user_name(all_data, option["user_id"]),
+ "user": await get_user_name(all_data, option["candidate_id"]),
"is_elected": option["is_elected"],
"votes": option["votes"],
}