Client side changes
This commit is contained in:
parent
0b37c5a857
commit
6ba0d0c5e6
@ -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 -->
|
||||||
|
@ -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
|
||||||
|
@ -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">{{
|
||||||
|
@ -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]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user