Client side changes

This commit is contained in:
Sean Engelhardt 2020-02-13 15:15:42 +01:00 committed by FinnStutzenstein
parent 0b37c5a857
commit 6ba0d0c5e6
5 changed files with 89 additions and 57 deletions

View File

@ -5,49 +5,46 @@
</div> </div>
<ng-container *ngIf="vmanager.canVote(poll)"> <ng-container *ngIf="vmanager.canVote(poll)">
<!-- TODO: Someone should make this pretty --> <!-- TODO: Someone should make this pretty -->
<span *ngIf="poll.user_has_voted_valid">Your vote is valid!</span> <span *ngIf="poll.user_has_voted_valid">Your vote is valid!</span>
<span *ngIf="poll.user_has_voted_invalid">DANGER: Your vote is invalid!</span> <span *ngIf="poll.user_has_voted_invalid">DANGER: Your vote is invalid!</span>
<span *ngIf="poll.user_has_not_voted">You have not give any voting here!</span> <span *ngIf="poll.user_has_not_voted">You have not give any voting here!</span>
<!-- Leftover votes --> <!-- Leftover votes -->
<h4 *ngIf="poll.pollmethod === pollMethods.Votes"> <h4 *ngIf="poll.pollmethod === pollMethods.Votes && poll.votes_amount > 1 && !currentVotes.global">
{{ 'Votes for this poll' | translate }}: {{ poll.votes_amount }} {{ 'Votes for this poll' | translate }}: {{ getVotesCount() }}/{{ poll.votes_amount }}
<!-- ({{ getVotesCount() }}/{{ poll.votes_amount }} {{ 'Votes' | translate }}) -->
</h4> </h4>
<!-- Options and Actions --> <!-- Options and Actions -->
<div *ngFor="let option of poll.options; let i = index"> <div *ngFor="let option of poll.options; let i = index">
<div *ngIf="option.user_has_voted"> <div *ngIf="poll.type !== PollType.Pseudoanonymous || !option.user_has_voted">
TODO: DO not show buttons, becuase, the user has already voted for this one <div
</div> [ngClass]="{
<div 'yna-grid': poll.pollmethod === pollMethods.YNA,
[ngClass]="{ 'yn-grid': poll.pollmethod === pollMethods.YN,
'yna-grid': poll.pollmethod === pollMethods.YNA, 'single-vote-grid': poll.pollmethod === pollMethods.Votes
'yn-grid': poll.pollmethod === pollMethods.YN, }"
'single-vote-grid': poll.pollmethod === pollMethods.Votes >
}" <div class="vote-candidate-name">
> <span *ngIf="option.user">{{ option.user.getFullName() }}</span>
<div class="vote-candidate-name"> <span *ngIf="!option.user">{{ 'Unknown user' | translate }}</span>
<span *ngIf="option.user">{{ option.user.getFullName() }}</span> </div>
<span *ngIf="!option.user">{{ 'Unknown user' | translate }}</span>
</div>
<div *ngFor="let action of voteActions"> <div *ngFor="let action of voteActions">
<button <button
mat-raised-button mat-raised-button
(click)="saveSingleVote(option.id, action.vote)" (click)="saveSingleVote(option.id, action.vote)"
[ngClass]="currentVotes[option.id] ? action.css : ''" [ngClass]="currentVotes[option.id] === action.label ? action.css : ''"
> >
<mat-icon> {{ action.icon }}</mat-icon> <mat-icon> {{ action.icon }}</mat-icon>
</button> </button>
<span *ngIf="poll.pollmethod !== pollMethods.Votes" class="vote-label"> <span *ngIf="poll.pollmethod !== pollMethods.Votes" class="vote-label">
{{ action.label | translate }} {{ action.label | translate }}
</span> </span>
</div>
</div> </div>
<mat-divider *ngIf="poll.options.length - 1 > i"></mat-divider>
</div> </div>
<mat-divider *ngIf="poll.options.length - 1 > i"></mat-divider>
</div> </div>
<!-- global no/abstain --> <!-- global no/abstain -->

View File

@ -86,7 +86,13 @@ export class AssignmentPollVoteComponent extends BasePollVoteComponent<ViewAssig
} }
} }
public getVotesCount(): number {
return Object.keys(this.currentVotes).filter(key => this.currentVotes[key]).length;
}
protected updateVotes(): void { protected updateVotes(): void {
console.log('currentVotes: ', this.currentVotes);
if (this.user && this.votes && this.poll) { if (this.user && this.votes && this.poll) {
const filtered = this.votes.filter( const filtered = this.votes.filter(
vote => vote.option.poll_id === this.poll.id && vote.user_id === this.user.id vote => vote.option.poll_id === this.poll.id && vote.user_id === this.user.id

View File

@ -81,7 +81,9 @@
formControlName="votes_amount" formControlName="votes_amount"
min="1" min="1"
required required
/> />
<mat-hint *ngIf="showSingleAmountHint"> {{ 'Multiple votes are disabled due to security reasons' | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<mat-checkbox formControlName="global_no">{{ PollPropertyVerbose.global_no | translate }}</mat-checkbox> <mat-checkbox formControlName="global_no">{{ PollPropertyVerbose.global_no | translate }}</mat-checkbox>
<mat-checkbox formControlName="global_abstain">{{ <mat-checkbox formControlName="global_abstain">{{

View File

@ -77,6 +77,8 @@ export class PollFormComponent extends BaseViewComponent implements OnInit {
*/ */
public publishImmediately = true; public publishImmediately = true;
public showSingleAmountHint = false;
/** /**
* Constructor. Retrieves necessary metadata from the pollService, * Constructor. Retrieves necessary metadata from the pollService,
* injects the poll itself * injects the poll itself
@ -124,31 +126,61 @@ export class PollFormComponent extends BaseViewComponent implements OnInit {
this.updatePollValues(this.contentForm.value); this.updatePollValues(this.contentForm.value);
this.subscriptions.push( this.subscriptions.push(
// changes to whole form
this.contentForm.valueChanges.subscribe(values => { this.contentForm.valueChanges.subscribe(values => {
this.updatePollValues(values); this.updatePollValues(values);
}),
// poll method changes
this.contentForm.get('pollmethod').valueChanges.subscribe(method => {
let forbiddenBases: string[];
if (method === 'YN') {
forbiddenBases = [PercentBase.YNA, PercentBase.Cast];
} else if (method === 'YNA') {
forbiddenBases = [PercentBase.Cast];
} else if (method === 'votes') {
forbiddenBases = [PercentBase.YN, PercentBase.YNA];
if (this.contentForm.get('type').value === PollType.Pseudoanonymous) {
this.setVotesAmountCtrl();
}
}
const percentBases = {};
for (const [key, value] of Object.entries(PercentBaseVerbose)) {
if (!forbiddenBases.includes(key)) {
percentBases[key] = value;
}
}
this.percentBases = percentBases;
// TODO: update selected base
this.setVotesAmountCtrl();
}),
// poll type changes
this.contentForm.get('type').valueChanges.subscribe(() => {
this.setVotesAmountCtrl();
}) })
); );
}
// update the percent bases when the poll method changes /**
this.contentForm.get('pollmethod').valueChanges.subscribe(method => { * Disable votes_amount form control if the poll type is anonymous
let forbiddenBases: string[]; * and the poll method is votes.
if (method === 'YN') { * TODO: Enabling this requires at least another layout and some rework
forbiddenBases = [PercentBase.YNA, PercentBase.Cast]; */
} else if (method === 'YNA') { private setVotesAmountCtrl(): void {
forbiddenBases = [PercentBase.Cast]; // Disable "Amounts of votes" if anonymous and yes-method
} else if (method === 'votes') { const votesAmountCtrl = this.contentForm.get('votes_amount');
forbiddenBases = [PercentBase.YN, PercentBase.YNA]; if (
} this.contentForm.get('type').value === PollType.Pseudoanonymous &&
this.contentForm.get('pollmethod').value === 'votes'
const percentBases = {}; ) {
for (const [key, value] of Object.entries(PercentBaseVerbose)) { votesAmountCtrl.disable();
if (!forbiddenBases.includes(key)) { votesAmountCtrl.setValue(1);
percentBases[key] = value; this.showSingleAmountHint = true;
} } else {
} votesAmountCtrl.enable();
this.percentBases = percentBases; this.showSingleAmountHint = false;
// TODO: update selected base }
});
} }
public getValues<V extends ViewBasePoll>(): Partial<V> { public getValues<V extends ViewBasePoll>(): Partial<V> {
@ -193,8 +225,8 @@ export class PollFormComponent extends BaseViewComponent implements OnInit {
majority_method: ['', Validators.required], majority_method: ['', Validators.required],
votes_amount: [1, [Validators.required, Validators.min(1)]], votes_amount: [1, [Validators.required, Validators.min(1)]],
groups_id: [], groups_id: [],
global_no: [], global_no: [false],
global_abstain: [] global_abstain: [false]
}); });
} }
} }

View File

@ -473,11 +473,6 @@ class AssignmentPollViewSet(BasePollViewSet):
) )
amount_sum += amount amount_sum += amount
if amount_sum <= 0:
raise ValidationError(
{"detail": "You must give at least one vote"}
)
if amount_sum > poll.votes_amount: if amount_sum > poll.votes_amount:
raise ValidationError( raise ValidationError(
{ {