include per-poll values, some travis fix

This commit is contained in:
Maximilian Krambach 2019-04-05 12:13:34 +02:00
parent e6daf32924
commit 464fb89b53
8 changed files with 70 additions and 27 deletions

View File

@ -181,12 +181,11 @@ export class AssignmentRepositoryService extends BaseAgendaContentObjectReposito
assignment_id: originalPoll.assignment_id, assignment_id: originalPoll.assignment_id,
votes: votes, votes: votes,
votesabstain: null, votesabstain: null,
votescast: null, votescast: poll.votescast || null,
votesinvalid: null, votesinvalid: poll.votesinvalid || null,
votesno: null, votesno: null,
votesvalid: null votesvalid: poll.votesvalid || null
}; };
// TODO no response, no error shown, votes are not accepted
const restPath = `/rest/assignments/poll/${originalPoll.id}/`; const restPath = `/rest/assignments/poll/${originalPoll.id}/`;
await this.httpService.put(restPath, data); await this.httpService.put(restPath, data);
} }

View File

@ -180,6 +180,8 @@ export abstract class PollService {
return 'progress-red'; return 'progress-red';
case 'abstain': case 'abstain':
return 'progress-yellow'; return 'progress-yellow';
case 'votes':
return 'progress-green';
default: default:
return ''; return '';
} }

View File

@ -41,8 +41,34 @@
</div> </div>
<mat-divider *ngIf="data.poll.pollmethod !== 'votes'"></mat-divider> <mat-divider *ngIf="data.poll.pollmethod !== 'votes'"></mat-divider>
</div> </div>
<mat-form-field>
<input
type="number"
matInput
[value]="getSumValue('votesvalid')"
(change)="setSumValue('votesvalid', $event.target.value)"
/>
<mat-label translate>Valid votes</mat-label>
</mat-form-field>
<mat-form-field>
<input
type="number"
matInput
[value]="getSumValue('votesinvalid')"
(change)="setSumValue('votesinvalid', $event.target.value)"
/>
<mat-label translate>Invalid votes</mat-label>
</mat-form-field>
<mat-form-field>
<input
type="number"
matInput
[value]="getSumValue('votestotal')"
(change)="setSumValue('votestotal', $event.target.value)"
/>
<mat-label translate>Total votes</mat-label>
</mat-form-field>
<!-- TODO: total votes -->
</div> </div>
<div class="submit-buttons"> <div class="submit-buttons">
<button mat-button (click)="submit()">{{ 'Save' | translate }}</button> <button mat-button (click)="submit()">{{ 'Save' | translate }}</button>

View File

@ -8,6 +8,11 @@ import { Poll } from 'app/shared/models/assignments/poll';
import { PollOption } from 'app/shared/models/assignments/poll-option'; import { PollOption } from 'app/shared/models/assignments/poll-option';
import { ViewUser } from 'app/site/users/models/view-user'; import { ViewUser } from 'app/site/users/models/view-user';
/**
* Vote entries included once for summary (e.g. total votes cast)
*/
type summaryPollKeys = 'votescast' | 'votesvalid' | 'votesinvalid';
/** /**
* A dialog for updating the values of an assignment-related poll. * A dialog for updating the values of an assignment-related poll.
*/ */
@ -29,11 +34,6 @@ export class AssignmentPollDialogComponent {
*/ */
public optionPollKeys: PollVoteValue[]; public optionPollKeys: PollVoteValue[];
/**
* Vote entries included once for summary (e.g. total votes cast)
*/
public summaryPollKeys: CalculablePollKey[];
/** /**
* Constructor. Retrieves necessary metadata from the pollService, * Constructor. Retrieves necessary metadata from the pollService,
* injects the poll itself * injects the poll itself
@ -146,4 +146,24 @@ export class AssignmentPollDialogComponent {
const val = candidate.votes.find(v => v.value === value); const val = candidate.votes.find(v => v.value === value);
return val ? val.weight : undefined; return val ? val.weight : undefined;
} }
/**
* Retrieves a per-poll value
*
* @param value
* @returns integer or null
*/
public getSumValue(value: summaryPollKeys): number | null {
return this.data.poll[value] || null;
}
/**
* Sets a per-poll value
*
* @param value
* @param weight
*/
public setSumValue(value: summaryPollKeys, weight: string): void {
this.data.poll[value] = +weight;
}
} }

View File

@ -67,7 +67,7 @@
{{ getCandidateName(option) }} {{ getCandidateName(option) }}
</div> </div>
<!-- Votes --> <!-- Votes -->
<div *ngIf="poll.published"> <div *ngIf="poll.published && poll.has_votes">
<div *ngFor="let vote of option.votes"> <div *ngFor="let vote of option.votes">
<div class="poll-progress on-transition-fade"> <div class="poll-progress on-transition-fade">
<span>{{ pollService.getLabel(vote.value) | translate }}:</span> <span>{{ pollService.getLabel(vote.value) | translate }}:</span>
@ -88,6 +88,7 @@
</div> </div>
<div <div
*ngIf=" *ngIf="
poll.has_votes &&
poll.published && poll.published &&
majorityChoice && majorityChoice &&
majorityChoice.value !== 'disabled' && majorityChoice.value !== 'disabled' &&
@ -106,13 +107,11 @@
<div> <div>
<!-- summary --> <!-- summary -->
<div *ngFor="let key of pollValues"> <div *ngFor="let key of pollValues">
<div *ngIf="!pollService.isAbstractValue(key)" class="poll-progress-bar"> <div>
<mat-progress-bar <span>{{ key | translate }}</span>:
mode="determinate" </div>
[value]="pollService.getPercent(key)" <div>
[ngClass]="pollService.getProgressBarColor(key)" {{ pollService.getSpecialLabel(poll[key]) }}
>
</mat-progress-bar>
</div> </div>
</div> </div>
</div> </div>

View File

@ -152,7 +152,8 @@ export class AssignmentPollComponent implements OnInit {
* @returns true if the quorum is successfully met * @returns true if the quorum is successfully met
*/ */
public quorumReached(option: PollOption): boolean { public quorumReached(option: PollOption): boolean {
const amount = option.votes.find(v => v.value === 'Yes').weight; const yesValue = this.poll.pollmethod === 'votes' ? 'Votes' : 'Yes';
const amount = option.votes.find(v => v.value === yesValue).weight;
const yesQuorum = this.pollService.yesQuorum(this.majorityChoice, this.poll, option); const yesQuorum = this.pollService.yesQuorum(this.majorityChoice, this.poll, option);
return yesQuorum && amount >= yesQuorum; return yesQuorum && amount >= yesQuorum;
} }

View File

@ -90,14 +90,15 @@ export class AssignmentPollService extends PollService {
} }
case 'CAST': case 'CAST':
return poll.votescast > 0 && poll.votesinvalid >= 0 ? poll.votescast : null; return poll.votescast > 0 && poll.votesinvalid >= 0 ? poll.votescast : null;
case 'VALID':
return poll.votesvalid > 0 ? poll.votesvalid : null;
default: default:
return null; return null;
} }
} }
/** /**
* Get the percentage for an option that calculates only on their own yes/no/abstain * Get the percentage for an option
* values
* *
* @param poll * @param poll
* @param option * @param option
@ -105,10 +106,7 @@ export class AssignmentPollService extends PollService {
* @returns a percentage number with two digits, null if the value cannot be calculated * @returns a percentage number with two digits, null if the value cannot be calculated
*/ */
public getPercent(poll: Poll, option: PollOption, value: PollVoteValue): number | null { public getPercent(poll: Poll, option: PollOption, value: PollVoteValue): number | null {
if (poll.pollmethod === 'votes') { const base = poll.pollmethod === 'votes' ? poll.pollBase : this.getOptionBaseAmount(poll, option);
return null;
}
const base = this.getOptionBaseAmount(poll, option);
if (!base) { if (!base) {
return null; return null;
} }

View File

@ -6,7 +6,6 @@ from openslides.utils.rest_api import (
DictField, DictField,
IntegerField, IntegerField,
ListField, ListField,
ListSerializer,
ModelSerializer, ModelSerializer,
SerializerMethodField, SerializerMethodField,
ValidationError, ValidationError,
@ -20,7 +19,6 @@ from .models import (
AssignmentPoll, AssignmentPoll,
AssignmentRelatedUser, AssignmentRelatedUser,
AssignmentVote, AssignmentVote,
models,
) )