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>
<ng-container *ngIf="vmanager.canVote(poll)">
<!-- TODO: Someone should make this pretty -->
<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_not_voted">You have not give any voting here!</span>
<!-- Leftover votes -->
<h4 *ngIf="poll.pollmethod === pollMethods.Votes">
{{ 'Votes for this poll' | translate }}: {{ poll.votes_amount }}
<!-- ({{ getVotesCount() }}/{{ poll.votes_amount }} {{ 'Votes' | translate }}) -->
<h4 *ngIf="poll.pollmethod === pollMethods.Votes && poll.votes_amount > 1 && !currentVotes.global">
{{ 'Votes for this poll' | translate }}: {{ getVotesCount() }}/{{ poll.votes_amount }}
</h4>
<!-- Options and Actions -->
<div *ngFor="let option of poll.options; let i = index">
<div *ngIf="option.user_has_voted">
TODO: DO not show buttons, becuase, the user has already voted for this one
</div>
<div
[ngClass]="{
'yna-grid': poll.pollmethod === pollMethods.YNA,
'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>
<span *ngIf="!option.user">{{ 'Unknown user' | translate }}</span>
</div>
<div *ngIf="poll.type !== PollType.Pseudoanonymous || !option.user_has_voted">
<div
[ngClass]="{
'yna-grid': poll.pollmethod === pollMethods.YNA,
'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>
<span *ngIf="!option.user">{{ 'Unknown user' | translate }}</span>
</div>
<div *ngFor="let action of voteActions">
<button
mat-raised-button
(click)="saveSingleVote(option.id, action.vote)"
[ngClass]="currentVotes[option.id] ? action.css : ''"
>
<mat-icon> {{ action.icon }}</mat-icon>
</button>
<span *ngIf="poll.pollmethod !== pollMethods.Votes" class="vote-label">
{{ action.label | translate }}
</span>
<div *ngFor="let action of voteActions">
<button
mat-raised-button
(click)="saveSingleVote(option.id, action.vote)"
[ngClass]="currentVotes[option.id] === action.label ? action.css : ''"
>
<mat-icon> {{ action.icon }}</mat-icon>
</button>
<span *ngIf="poll.pollmethod !== pollMethods.Votes" class="vote-label">
{{ action.label | translate }}
</span>
</div>
</div>
<mat-divider *ngIf="poll.options.length - 1 > i"></mat-divider>
</div>
<mat-divider *ngIf="poll.options.length - 1 > i"></mat-divider>
</div>
<!-- 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 {
console.log('currentVotes: ', this.currentVotes);
if (this.user && this.votes && this.poll) {
const filtered = this.votes.filter(
vote => vote.option.poll_id === this.poll.id && vote.user_id === this.user.id

View File

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

View File

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

View File

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