OpenSlides/client/src/app/site/assignments/components/assignment-poll/assignment-poll-dialog.component.ts
2019-04-08 10:16:47 +02:00

170 lines
5.3 KiB
TypeScript

import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA, MatSnackBar } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { AssignmentPollService } from '../../services/assignment-poll.service';
import { CalculablePollKey, PollVoteValue } from 'app/core/ui-services/poll.service';
import { Poll } from 'app/shared/models/assignments/poll';
import { PollOption } from 'app/shared/models/assignments/poll-option';
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.
*/
@Component({
selector: 'os-assignment-poll-dialog',
templateUrl: './assignment-poll-dialog.component.html',
styleUrls: ['./assignment-poll-dialog.component.scss']
})
export class AssignmentPollDialogComponent {
/**
* List of accepted special non-numerical values.
* See {@link PollService.specialPollVotes}
*/
public specialValues: [number, string][];
/**
* vote entries for each option in this component. Is empty if method
* requires one vote per candidate
*/
public optionPollKeys: PollVoteValue[];
/**
* Constructor. Retrieves necessary metadata from the pollService,
* injects the poll itself
*/
public constructor(
public dialogRef: MatDialogRef<AssignmentPollDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { poll: Poll; users: ViewUser[] },
private matSnackBar: MatSnackBar,
private translate: TranslateService,
private pollService: AssignmentPollService
) {
this.specialValues = this.pollService.specialPollVotes;
switch (this.data.poll.pollmethod) {
case 'votes':
this.optionPollKeys = ['Yes'];
break;
case 'yn':
this.optionPollKeys = ['Yes', 'No'];
break;
case 'yna':
this.optionPollKeys = ['Yes', 'No', 'Abstain'];
break;
}
}
/**
* Close the dialog, submitting nothing. Triggered by the cancel button and
* default angular cancelling behavior
*/
public cancel(): void {
this.dialogRef.close();
}
/**
* Validates candidates input (every candidate has their options filled in),
* submits and closes the dialog if successfull, else displays an error popup.
* TODO better validation
*/
public submit(): void {
const error = this.data.poll.options.find(dataoption => {
for (const key of this.optionPollKeys) {
const keyValue = dataoption.votes.find(o => o.value === key);
if (!keyValue || keyValue.weight === undefined) {
return true;
}
}
});
if (error) {
this.matSnackBar.open(
this.translate.instant('Please fill in the values for each candidate'),
this.translate.instant('OK'),
{
duration: 1000
}
);
} else {
this.dialogRef.close(this.data.poll);
}
}
/**
* TODO: currently unused
*
* @param key poll option to be labeled
* @returns a label for a poll option
*/
public getLabel(key: CalculablePollKey): string {
return this.pollService.getLabel(key);
}
/**
* Get the (full) name of a pollOption candidate
*
* @param the id of the candidate
* @returns the full_name property
*/
public getName(candidateId: number): string {
const user = this.data.users.find(c => c.id === candidateId);
return user ? user.full_name : 'unknown user';
// TODO error handling
}
/**
* Updates a vote value
*
* @param value the value to update
* @param candidate the candidate for whom to update the value
* @param newData the new value
*/
public setValue(value: PollVoteValue, candidate: PollOption, newData: number): void {
const vote = candidate.votes.find(v => v.value === value);
if (vote) {
vote.weight = +newData;
} else {
candidate.votes.push({
value: value,
weight: +newData
});
}
}
/**
* Retrieves the current value for a voting option
*
* @param value the vote value (e.g. 'Abstain')
* @param candidate the pollOption
* @returns the currently entered number or undefined if no number has been set
*/
public getValue(value: PollVoteValue, candidate: PollOption): number {
const val = candidate.votes.find(v => v.value === value);
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;
}
}