Result PDF for Voting
- Add result PDF for Motion and Assignments - Add "getPercentBase" for Assignment
This commit is contained in:
parent
6044c63c28
commit
93dc78c7d6
@ -1,3 +1,4 @@
|
|||||||
|
import { CalculablePollKey } from 'app/site/polls/services/poll.service';
|
||||||
import { AssignmentOption } from './assignment-option';
|
import { AssignmentOption } from './assignment-option';
|
||||||
import { BasePoll } from '../poll/base-poll';
|
import { BasePoll } from '../poll/base-poll';
|
||||||
|
|
||||||
@ -23,6 +24,16 @@ export class AssignmentPoll extends BasePoll<AssignmentPoll, AssignmentOption> {
|
|||||||
public global_abstain: boolean;
|
public global_abstain: boolean;
|
||||||
public description: string;
|
public description: string;
|
||||||
|
|
||||||
|
public get pollmethodFields(): CalculablePollKey[] {
|
||||||
|
if (this.pollmethod === AssignmentPollMethods.YN) {
|
||||||
|
return ['yes', 'no'];
|
||||||
|
} else if (this.pollmethod === AssignmentPollMethods.YNA) {
|
||||||
|
return ['yes', 'no', 'abstain'];
|
||||||
|
} else if (this.pollmethod === AssignmentPollMethods.Votes) {
|
||||||
|
return ['yes'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public constructor(input?: any) {
|
public constructor(input?: any) {
|
||||||
super(AssignmentPoll.COLLECTIONSTRING, input);
|
super(AssignmentPoll.COLLECTIONSTRING, input);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { CalculablePollKey } from 'app/site/polls/services/poll.service';
|
||||||
import { BasePoll } from '../poll/base-poll';
|
import { BasePoll } from '../poll/base-poll';
|
||||||
import { MotionOption } from './motion-option';
|
import { MotionOption } from './motion-option';
|
||||||
|
|
||||||
@ -16,6 +17,15 @@ export class MotionPoll extends BasePoll<MotionPoll, MotionOption> {
|
|||||||
public motion_id: number;
|
public motion_id: number;
|
||||||
public pollmethod: MotionPollMethods;
|
public pollmethod: MotionPollMethods;
|
||||||
|
|
||||||
|
public get pollmethodFields(): CalculablePollKey[] {
|
||||||
|
const ynField: CalculablePollKey[] = ['yes', 'no'];
|
||||||
|
if (this.pollmethod === MotionPollMethods.YN) {
|
||||||
|
return ynField;
|
||||||
|
} else if (this.pollmethod === MotionPollMethods.YNA) {
|
||||||
|
return ynField.concat(['abstain']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public constructor(input?: any) {
|
public constructor(input?: any) {
|
||||||
super(MotionPoll.COLLECTIONSTRING, input);
|
super(MotionPoll.COLLECTIONSTRING, input);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
<div *ngIf="assignment">
|
<div *ngIf="assignment">
|
||||||
<!-- PDF -->
|
<!-- PDF -->
|
||||||
<button mat-menu-item (click)="onDownloadPdf()">
|
<button mat-menu-item (click)="onDownloadPdf()">
|
||||||
<!-- TODO: results or description. Results if published -->
|
|
||||||
<mat-icon>picture_as_pdf</mat-icon>
|
<mat-icon>picture_as_pdf</mat-icon>
|
||||||
<span translate>PDF</span>
|
<span translate>PDF</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -2,7 +2,7 @@ import { BehaviorSubject } from 'rxjs';
|
|||||||
|
|
||||||
import { ChartData } from 'app/shared/components/charts/charts.component';
|
import { ChartData } from 'app/shared/components/charts/charts.component';
|
||||||
import { AssignmentPoll, AssignmentPollMethods } from 'app/shared/models/assignments/assignment-poll';
|
import { AssignmentPoll, AssignmentPollMethods } from 'app/shared/models/assignments/assignment-poll';
|
||||||
import { PollColor, PollState } from 'app/shared/models/poll/base-poll';
|
import { PercentBase, PollColor, PollState } from 'app/shared/models/poll/base-poll';
|
||||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||||
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
|
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
|
||||||
import { PollData, ViewBasePoll } from 'app/site/polls/models/view-base-poll';
|
import { PollData, ViewBasePoll } from 'app/site/polls/models/view-base-poll';
|
||||||
@ -80,7 +80,8 @@ export class ViewAssignmentPoll extends ViewBasePoll<AssignmentPoll> implements
|
|||||||
yes: candidate.yes,
|
yes: candidate.yes,
|
||||||
no: candidate.no,
|
no: candidate.no,
|
||||||
abstain: candidate.abstain,
|
abstain: candidate.abstain,
|
||||||
user: candidate.user.full_name
|
user: candidate.user.full_name,
|
||||||
|
showPercent: true
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => b.yes - a.yes);
|
.sort((a, b) => b.yes - a.yes);
|
||||||
|
|
||||||
@ -97,8 +98,41 @@ export class ViewAssignmentPoll extends ViewBasePoll<AssignmentPoll> implements
|
|||||||
return super.getNextStates();
|
return super.getNextStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sumOptionsYN(): number {
|
||||||
|
return this.options.reduce((o, n) => {
|
||||||
|
o += n.yes > 0 ? n.yes : 0;
|
||||||
|
o += n.no > 0 ? n.no : 0;
|
||||||
|
return o;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sumOptionsYNA(): number {
|
||||||
|
return this.options.reduce((o, n) => {
|
||||||
|
o += n.abstain > 0 ? n.abstain : 0;
|
||||||
|
return o;
|
||||||
|
}, this.sumOptionsYN());
|
||||||
|
}
|
||||||
|
|
||||||
public getPercentBase(): number {
|
public getPercentBase(): number {
|
||||||
return 0;
|
const base: PercentBase = this.poll.onehundred_percent_base;
|
||||||
|
let totalByBase: number;
|
||||||
|
switch (base) {
|
||||||
|
case PercentBase.YN:
|
||||||
|
totalByBase = this.sumOptionsYN();
|
||||||
|
break;
|
||||||
|
case PercentBase.YNA:
|
||||||
|
totalByBase = this.sumOptionsYNA();
|
||||||
|
break;
|
||||||
|
case PercentBase.Valid:
|
||||||
|
totalByBase = this.poll.votesvalid;
|
||||||
|
break;
|
||||||
|
case PercentBase.Cast:
|
||||||
|
totalByBase = this.poll.votescast;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return totalByBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,12 @@ import { Injectable } from '@angular/core';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { HtmlToPdfService } from 'app/core/pdf-services/html-to-pdf.service';
|
import { HtmlToPdfService } from 'app/core/pdf-services/html-to-pdf.service';
|
||||||
|
import { ParsePollNumberPipe } from 'app/shared/pipes/parse-poll-number.pipe';
|
||||||
|
import { PollKeyVerbosePipe } from 'app/shared/pipes/poll-key-verbose.pipe';
|
||||||
|
import { PollPercentBasePipe } from 'app/shared/pipes/poll-percent-base.pipe';
|
||||||
|
import { PollData } from 'app/site/polls/models/view-base-poll';
|
||||||
import { ViewAssignment } from '../models/view-assignment';
|
import { ViewAssignment } from '../models/view-assignment';
|
||||||
|
import { ViewAssignmentPoll } from '../models/view-assignment-poll';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a PDF document from a single assignment
|
* Creates a PDF document from a single assignment
|
||||||
@ -20,7 +25,13 @@ export class AssignmentPdfService {
|
|||||||
* @param pdfDocumentService PDF functions
|
* @param pdfDocumentService PDF functions
|
||||||
* @param htmlToPdfService Convert the assignment detail html text to pdf
|
* @param htmlToPdfService Convert the assignment detail html text to pdf
|
||||||
*/
|
*/
|
||||||
public constructor(private translate: TranslateService, private htmlToPdfService: HtmlToPdfService) {}
|
public constructor(
|
||||||
|
private translate: TranslateService,
|
||||||
|
private htmlToPdfService: HtmlToPdfService,
|
||||||
|
private pollKeyVerbose: PollKeyVerbosePipe,
|
||||||
|
private parsePollNumber: ParsePollNumberPipe,
|
||||||
|
private pollPercentBase: PollPercentBasePipe
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function to control the pdf generation.
|
* Main function to control the pdf generation.
|
||||||
@ -140,44 +151,20 @@ export class AssignmentPdfService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a candidate line in the results table
|
|
||||||
*
|
|
||||||
* @param candidateName The name of the candidate
|
|
||||||
* @param pollOption the poll options (yes, no, maybe [...])
|
|
||||||
* @returns a line in the table
|
|
||||||
*/
|
|
||||||
// TODO: type the result.
|
|
||||||
/*private electedCandidateLine(candidateName: string, pollOption: ViewAssignmentOption): object {
|
|
||||||
if (pollOption.is_elected) {
|
|
||||||
this.showIsElected = true;
|
|
||||||
return {
|
|
||||||
text: candidateName + '*',
|
|
||||||
bold: true
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
text: candidateName
|
|
||||||
};
|
|
||||||
}*
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the poll result table for all published polls
|
* Creates the poll result table for all published polls
|
||||||
*
|
*
|
||||||
* @param assignment the ViewAssignment to create the document for
|
* @param assignment the ViewAssignment to create the document for
|
||||||
* @returns the table as pdfmake object
|
* @returns the table as pdfmake object
|
||||||
*/
|
*/
|
||||||
// TODO: type the result
|
|
||||||
private createPollResultTable(assignment: ViewAssignment): object {
|
private createPollResultTable(assignment: ViewAssignment): object {
|
||||||
/*const resultBody = [];
|
const resultBody = [];
|
||||||
for (let pollIndex = 0; pollIndex < assignment.polls.length; pollIndex++) {
|
for (const poll of assignment.polls) {
|
||||||
const poll = assignment.polls[pollIndex];
|
if (poll.isPublished) {
|
||||||
if (poll.published) {
|
|
||||||
const pollTableBody = [];
|
const pollTableBody = [];
|
||||||
|
|
||||||
resultBody.push({
|
resultBody.push({
|
||||||
text: `${this.translate.instant('Ballot')} ${pollIndex + 1}`,
|
text: poll.title,
|
||||||
bold: true,
|
bold: true,
|
||||||
style: 'textItem',
|
style: 'textItem',
|
||||||
margin: [0, 15, 0, 0]
|
margin: [0, 15, 0, 0]
|
||||||
@ -194,56 +181,22 @@ export class AssignmentPdfService {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let optionIndex = 0; optionIndex < poll.options.length; optionIndex++) {
|
const tableData = poll.generateTableData();
|
||||||
const pollOption = poll.options[optionIndex];
|
|
||||||
|
|
||||||
const candidateName = pollOption.user.full_name;
|
for (const pollResult of tableData) {
|
||||||
const votes = pollOption.votes; // 0 = yes, 1 = no, 2 = abstain0 = yes, 1 = no, 2 = abstain
|
const resultLine = this.getPollResult(pollResult, poll);
|
||||||
const tableLine = [];
|
|
||||||
tableLine.push(this.electedCandidateLine(candidateName, pollOption));
|
|
||||||
|
|
||||||
if (poll.pollmethod === 'votes') {
|
const tableLine = [
|
||||||
tableLine.push({
|
|
||||||
text: this.parseVoteValue(votes[0].value, votes[0].weight, poll, pollOption)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const resultBlock = votes.map(vote =>
|
|
||||||
this.parseVoteValue(vote.value, vote.weight, poll, pollOption)
|
|
||||||
);
|
|
||||||
|
|
||||||
tableLine.push({
|
|
||||||
text: resultBlock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pollTableBody.push(tableLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// push the result lines
|
|
||||||
const summaryLine = this.pollService.getVoteOptionsByPoll(poll).map(key => {
|
|
||||||
// TODO: Refractor into pollService to make this easier.
|
|
||||||
// Return an object with untranslated lable: string, specialLabel: string and (opt) percent: number
|
|
||||||
const conclusionLabel = this.translate.instant(this.pollService.getLabel(key));
|
|
||||||
const specialLabel = this.translate.instant(this.pollService.getSpecialLabel(poll[key]));
|
|
||||||
let percentLabel = '';
|
|
||||||
if (!this.pollService.isAbstractValue(this.pollService.calculationDataFromPoll(poll), key)) {
|
|
||||||
percentLabel = ` (${this.pollService.getValuePercent(
|
|
||||||
this.pollService.calculationDataFromPoll(poll),
|
|
||||||
key
|
|
||||||
)}%)`;
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
{
|
||||||
text: conclusionLabel,
|
text: pollResult.user
|
||||||
style: 'tableConclude'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: specialLabel + percentLabel,
|
text: resultLine
|
||||||
style: 'tableConclude'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
});
|
|
||||||
|
|
||||||
pollTableBody.push(...summaryLine);
|
pollTableBody.push(tableLine);
|
||||||
|
}
|
||||||
|
|
||||||
resultBody.push({
|
resultBody.push({
|
||||||
table: {
|
table: {
|
||||||
@ -256,52 +209,19 @@ export class AssignmentPdfService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the legend to the result body
|
return resultBody;
|
||||||
// if (assignment.polls.length > 0 && isElectedSemaphore) {
|
|
||||||
if (assignment.polls.length > 0 && this.showIsElected) {
|
|
||||||
resultBody.push({
|
|
||||||
text: `* = ${this.translate.instant('is elected')}`,
|
|
||||||
margin: [0, 5, 0, 0]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultBody;*/
|
|
||||||
throw new Error('TODO');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a translated voting result with numbers and percent-value depending in the polloptions
|
* Converts pollData to a printable string representation
|
||||||
* I.e: "Yes 25 (22,2%)" or just "10"
|
|
||||||
*
|
|
||||||
* @param optionLabel Usually Yes or No
|
|
||||||
* @param value the amount of votes
|
|
||||||
* @param poll the specific poll
|
|
||||||
* @param option the corresponding poll option
|
|
||||||
* @returns a string a nicer number representation: "Yes 25 (22,2%)" or just "10"
|
|
||||||
*/
|
*/
|
||||||
/*private parseVoteValue(
|
private getPollResult(votingResult: PollData, poll: ViewAssignmentPoll): string {
|
||||||
optionLabel: PollVoteValue,
|
const resultList = poll.pollmethodFields.map(field => {
|
||||||
value: number,
|
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(field));
|
||||||
poll: ViewAssignmentPoll,
|
const resultValue = this.parsePollNumber.transform(votingResult[field]);
|
||||||
option: ViewAssignmentOption
|
const resultInPercent = this.pollPercentBase.transform(votingResult[field], poll);
|
||||||
): string {
|
return `${votingKey}: ${resultValue} ${resultInPercent ? resultInPercent : ''}`;
|
||||||
let resultString = '';
|
});
|
||||||
const label = this.translate.instant(this.pollService.getLabel(optionLabel));
|
return resultList.join('\n');
|
||||||
const valueString = this.pollService.getSpecialLabel(value);
|
|
||||||
const percentNr = this.pollService.getPercent(
|
|
||||||
this.pollService.calculationDataFromPoll(poll),
|
|
||||||
option,
|
|
||||||
optionLabel
|
|
||||||
);
|
|
||||||
|
|
||||||
resultString += `${label} ${valueString}`;
|
|
||||||
if (
|
|
||||||
percentNr &&
|
|
||||||
!this.pollService.isAbstractOption(this.pollService.calculationDataFromPoll(poll), option, optionLabel)
|
|
||||||
) {
|
|
||||||
resultString += ` (${percentNr}%)`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${resultString}\n`;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -68,8 +68,12 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public get result(): ViewMotionOption {
|
||||||
|
return this.options[0];
|
||||||
|
}
|
||||||
|
|
||||||
public get hasVotes(): boolean {
|
public get hasVotes(): boolean {
|
||||||
return !!this.options[0].votes.length;
|
return !!this.result.votes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public initChartLabels(): string[] {
|
public initChartLabels(): string[] {
|
||||||
@ -130,7 +134,7 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public anySpecialVotes(): boolean {
|
public anySpecialVotes(): boolean {
|
||||||
return this.options[0].yes < 0 || this.options[0].no < 0 || this.options[0].abstain < 0;
|
return this.result.yes < 0 || this.result.no < 0 || this.result.abstain < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,23 +149,22 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
|||||||
|
|
||||||
public getPercentBase(): number {
|
public getPercentBase(): number {
|
||||||
const base: PercentBase = this.poll.onehundred_percent_base;
|
const base: PercentBase = this.poll.onehundred_percent_base;
|
||||||
const options = this.options[0];
|
|
||||||
|
|
||||||
let totalByBase: number;
|
let totalByBase: number;
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case PercentBase.YN:
|
case PercentBase.YN:
|
||||||
if (options.yes >= 0 && options.no >= 0) {
|
if (this.result.yes >= 0 && this.result.no >= 0) {
|
||||||
totalByBase = options.sumYN();
|
totalByBase = this.result.sumYN();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PercentBase.YNA:
|
case PercentBase.YNA:
|
||||||
if (options.yes >= 0 && options.no >= 0 && options.abstain >= 0) {
|
if (this.result.yes >= 0 && this.result.no >= 0 && this.result.abstain >= 0) {
|
||||||
totalByBase = options.sumYNA();
|
totalByBase = this.result.sumYNA();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PercentBase.Valid:
|
case PercentBase.Valid:
|
||||||
// auslagern
|
// auslagern
|
||||||
if (options.yes >= 0 && options.no >= 0 && options.abstain >= 0) {
|
if (this.result.yes >= 0 && this.result.no >= 0 && this.result.abstain >= 0) {
|
||||||
totalByBase = this.poll.votesvalid;
|
totalByBase = this.poll.votesvalid;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -55,7 +55,6 @@ export class MotionPollDetailComponent extends BasePollDetailComponent<ViewMotio
|
|||||||
|
|
||||||
public openDialog(): void {
|
public openDialog(): void {
|
||||||
this.pollDialog.openDialog(this.poll);
|
this.pollDialog.openDialog(this.poll);
|
||||||
console.log('this.poll: ', this.poll.hasVotes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onDeleted(): void {
|
protected onDeleted(): void {
|
||||||
|
@ -11,6 +11,9 @@ import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions
|
|||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||||
import { ViewUnifiedChange, ViewUnifiedChangeType } from 'app/shared/models/motions/view-unified-change';
|
import { ViewUnifiedChange, ViewUnifiedChangeType } from 'app/shared/models/motions/view-unified-change';
|
||||||
|
import { ParsePollNumberPipe } from 'app/shared/pipes/parse-poll-number.pipe';
|
||||||
|
import { PollKeyVerbosePipe } from 'app/shared/pipes/poll-key-verbose.pipe';
|
||||||
|
import { PollPercentBasePipe } from 'app/shared/pipes/poll-percent-base.pipe';
|
||||||
import { getRecommendationTypeName } from 'app/shared/utils/recommendation-type-names';
|
import { getRecommendationTypeName } from 'app/shared/utils/recommendation-type-names';
|
||||||
import { MotionExportInfo } from './motion-export.service';
|
import { MotionExportInfo } from './motion-export.service';
|
||||||
import { ChangeRecoMode, InfoToExport, LineNumberingMode, PERSONAL_NOTE_ID } from '../motions.constants';
|
import { ChangeRecoMode, InfoToExport, LineNumberingMode, PERSONAL_NOTE_ID } from '../motions.constants';
|
||||||
@ -61,7 +64,10 @@ export class MotionPdfService {
|
|||||||
private pdfDocumentService: PdfDocumentService,
|
private pdfDocumentService: PdfDocumentService,
|
||||||
private htmlToPdfService: HtmlToPdfService,
|
private htmlToPdfService: HtmlToPdfService,
|
||||||
private linenumberingService: LinenumberingService,
|
private linenumberingService: LinenumberingService,
|
||||||
private commentRepo: MotionCommentSectionRepositoryService
|
private commentRepo: MotionCommentSectionRepositoryService,
|
||||||
|
private pollKeyVerbose: PollKeyVerbosePipe,
|
||||||
|
private pollPercentBase: PollPercentBasePipe,
|
||||||
|
private parsePollNumber: ParsePollNumberPipe
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,31 +368,20 @@ export class MotionPdfService {
|
|||||||
const column1 = [];
|
const column1 = [];
|
||||||
const column2 = [];
|
const column2 = [];
|
||||||
const column3 = [];
|
const column3 = [];
|
||||||
motion.polls.map((poll, index) => {
|
motion.polls.forEach(poll => {
|
||||||
/*if (poll.has_votes) {
|
if (poll.hasVotes) {
|
||||||
if (motion.motion.polls.length > 1) {
|
const tableData = poll.generateTableData();
|
||||||
column1.push(index + 1 + '. ' + this.translate.instant('Vote'));
|
tableData.forEach(votingResult => {
|
||||||
column2.push('');
|
const resultKey = this.translate.instant(this.pollKeyVerbose.transform(votingResult.key));
|
||||||
column3.push('');
|
const resultValue = this.parsePollNumber.transform(votingResult.value);
|
||||||
|
column1.push(`${resultKey}:`);
|
||||||
|
column2.push(resultValue);
|
||||||
|
if (votingResult.showPercent) {
|
||||||
|
const resultInPercent = this.pollPercentBase.transform(votingResult.value, poll);
|
||||||
|
column3.push(resultInPercent);
|
||||||
}
|
}
|
||||||
const values: CalculablePollKey[] = ['yes', 'no', 'abstain'];
|
|
||||||
if (poll.votesvalid) {
|
|
||||||
values.push('votesvalid');
|
|
||||||
}
|
|
||||||
if (poll.votesinvalid) {
|
|
||||||
values.push('votesinvalid');
|
|
||||||
}
|
|
||||||
if (poll.votescast) {
|
|
||||||
values.push('votescast');
|
|
||||||
}
|
|
||||||
values.map(value => {
|
|
||||||
column1.push(`${this.translate.instant(this.pollService.getLabel(value))}:`);
|
|
||||||
column2.push(`${this.translate.instant(this.pollService.getSpecialLabel(poll[value]))}`);
|
|
||||||
this.pollService.isAbstractValue(poll, value)
|
|
||||||
? column3.push('')
|
|
||||||
: column3.push(`(${this.pollService.calculatePercentage(poll, value)} %)`);
|
|
||||||
});
|
});
|
||||||
}*/
|
}
|
||||||
});
|
});
|
||||||
metaTableBody.push([
|
metaTableBody.push([
|
||||||
{
|
{
|
||||||
@ -653,15 +648,6 @@ export class MotionPdfService {
|
|||||||
margin: [0, 25, 0, 10]
|
margin: [0, 25, 0, 10]
|
||||||
});
|
});
|
||||||
|
|
||||||
// determine the width of the reason depending on line numbering
|
|
||||||
// currently not used
|
|
||||||
// let columnWidth: string;
|
|
||||||
// if (lnMode === LineNumberingMode.Outside) {
|
|
||||||
// columnWidth = '80%';
|
|
||||||
// } else {
|
|
||||||
// columnWidth = '100%';
|
|
||||||
// }
|
|
||||||
|
|
||||||
reason.push(this.htmlToPdfService.addPlainText(motion.reason));
|
reason.push(this.htmlToPdfService.addPlainText(motion.reason));
|
||||||
|
|
||||||
return reason;
|
return reason;
|
||||||
|
@ -132,24 +132,6 @@ export abstract class PollService {
|
|||||||
.subscribe(settings => (this.isElectronicVotingEnabled = settings.ENABLE_ELECTRONIC_VOTING));
|
.subscribe(settings => (this.isElectronicVotingEnabled = settings.ENABLE_ELECTRONIC_VOTING));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieve special labels for a poll value
|
|
||||||
* {@link specialPollVotes}. Positive values will return as string
|
|
||||||
* representation of themselves
|
|
||||||
*
|
|
||||||
* @param value check value for special numbers
|
|
||||||
* @returns the label for a non-positive value, according to
|
|
||||||
*/
|
|
||||||
public getSpecialLabel(value: number): string {
|
|
||||||
// if (value >= 0) {
|
|
||||||
// return value.toString();
|
|
||||||
// // TODO: toLocaleString(lang); but translateService is not usable here, thus lang is not well defined
|
|
||||||
// }
|
|
||||||
// const vote = this.specialPollVotes.find(special => special[0] === value);
|
|
||||||
// return vote ? vote[1] : 'Undocumented special (negative) value';
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the default poll data to the object. To be extended in subclasses
|
* Assigns the default poll data to the object. To be extended in subclasses
|
||||||
* @param poll the poll/object to fill
|
* @param poll the poll/object to fill
|
||||||
@ -160,140 +142,6 @@ export abstract class PollService {
|
|||||||
poll.type = PollType.Analog;
|
poll.type = PollType.Analog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the percentage the given key reaches.
|
|
||||||
*
|
|
||||||
* @param poll
|
|
||||||
* @param key
|
|
||||||
* @returns a percentage number with two digits, null if the value cannot be calculated (consider 0 !== null)
|
|
||||||
*/
|
|
||||||
public calculatePercentage(poll: ViewBasePoll, key: CalculablePollKey): number | null {
|
|
||||||
const baseNumber = this.getBaseAmount(poll);
|
|
||||||
if (!baseNumber) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (key) {
|
|
||||||
case 'abstain':
|
|
||||||
if (poll.onehundred_percent_base === PercentBase.YN) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'votesinvalid':
|
|
||||||
if (poll.onehundred_percent_base !== PercentBase.Cast) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'votesvalid':
|
|
||||||
if (![PercentBase.Cast, PercentBase.Valid].includes(poll.onehundred_percent_base)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'votescast':
|
|
||||||
if (poll.onehundred_percent_base !== PercentBase.Cast) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Math.round(((poll[key] * 100) / baseNumber) * 100) / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number representing 100 percent for a given MotionPoll, depending
|
|
||||||
* on the configuration and the votes given.
|
|
||||||
*
|
|
||||||
* @param poll
|
|
||||||
* @returns the positive number representing 100 percent of the poll, 0 if
|
|
||||||
* the base cannot be calculated
|
|
||||||
*/
|
|
||||||
public getBaseAmount(poll: ViewBasePoll): number {
|
|
||||||
/*if (!poll) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
switch (this.percentBase) {
|
|
||||||
case 'CAST':
|
|
||||||
if (!poll.votescast) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (poll.votesinvalid < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return poll.votescast;
|
|
||||||
case 'VALID':
|
|
||||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return poll.votesvalid ? poll.votesvalid : 0;
|
|
||||||
case 'YES_NO_ABSTAIN':
|
|
||||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return poll.yes + poll.no + poll.abstain;
|
|
||||||
case 'YES_NO':
|
|
||||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain === -1) {
|
|
||||||
// It is not allowed to set 'Abstain' to 'majority' but exclude it from calculation.
|
|
||||||
// Setting 'Abstain' to 'undocumented' is possible, of course.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return poll.yes + poll.no;
|
|
||||||
}*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates which number is needed for the quorum to be surpassed
|
|
||||||
* TODO: Methods still hard coded to mirror the server's.
|
|
||||||
*
|
|
||||||
* @param poll
|
|
||||||
* @param method (optional) majority calculation method. If none is given,
|
|
||||||
* the default as set in the config will be used.
|
|
||||||
* @returns the first integer number larger than the required majority,
|
|
||||||
* undefined if a quorum cannot be calculated.
|
|
||||||
*/
|
|
||||||
public calculateQuorum(poll: ViewBasePoll, method?: string): number {
|
|
||||||
if (!method) {
|
|
||||||
method = this.defaultMajorityMethod;
|
|
||||||
}
|
|
||||||
const baseNumber = this.getBaseAmount(poll);
|
|
||||||
if (!baseNumber) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const calc = PollMajorityMethod.find(m => m.value === method);
|
|
||||||
return calc && calc.calc ? calc.calc(baseNumber) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a value is abstract (percentages cannot be calculated)
|
|
||||||
*
|
|
||||||
* @param poll
|
|
||||||
* @param value
|
|
||||||
* @returns true if the percentages should not be calculated
|
|
||||||
*/
|
|
||||||
public isAbstractValue(poll: ViewBasePoll, value: CalculablePollKey): boolean {
|
|
||||||
// if (this.getBaseAmount(poll) === 0) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// switch (this.percentBase) {
|
|
||||||
// case 'YES_NO':
|
|
||||||
// if (['votescast', 'votesinvalid', 'votesvalid', 'abstain'].includes(value)) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case 'YES_NO_ABSTAIN':
|
|
||||||
// if (['votescast', 'votesinvalid', 'votesvalid'].includes(value)) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case 'VALID':
|
|
||||||
// if (['votesinvalid', 'votescast'].includes(value)) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// if (poll[value] < 0) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getVerboseNameForValue(key: string, value: string): string {
|
public getVerboseNameForValue(key: string, value: string): string {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'majority_method':
|
case 'majority_method':
|
||||||
|
Loading…
Reference in New Issue
Block a user