diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index e24171a4f..2730ea888 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -95,7 +95,6 @@ export class AppComponent { translate.use(translate.getLangs().includes(browserLang) ? browserLang : 'en'); // change default JS functions - this.overloadArrayToString(); this.overloadArrayFunctions(); this.overloadModulo(); @@ -118,7 +117,7 @@ export class AppComponent { * * TODO: Should be renamed */ - private overloadArrayToString(): void { + private overloadArrayFunctions(): void { Object.defineProperty(Array.prototype, 'toString', { value: function(): string { let string = ''; @@ -139,12 +138,7 @@ export class AppComponent { }, enumerable: false }); - } - /** - * Adds an implementation of flatMap and intersect. - */ - private overloadFlatMap(): void { Object.defineProperty(Array.prototype, 'flatMap', { value: function(o: any): any[] { const concatFunction = (x: any, y: any[]) => x.concat(y); @@ -154,10 +148,11 @@ export class AppComponent { enumerable: false }); + // intersect Object.defineProperty(Array.prototype, 'intersect', { value: function(other: T[]): T[] { - let a = this, - b = other; + let a = this; + let b = other; // indexOf to loop over shorter if (b.length > a.length) { [a, b] = [b, a]; @@ -167,6 +162,7 @@ export class AppComponent { enumerable: false }); + // mapToObject Object.defineProperty(Array.prototype, 'mapToObject', { value: function(f: (item: T) => { [key: string]: any }): { [key: string]: any } { return this.reduce((aggr, item) => { diff --git a/client/src/app/core/pdf-services/base-poll-pdf-service.ts b/client/src/app/core/pdf-services/base-poll-pdf-service.ts index 5e2e5de9e..d59a8c7e2 100644 --- a/client/src/app/core/pdf-services/base-poll-pdf-service.ts +++ b/client/src/app/core/pdf-services/base-poll-pdf-service.ts @@ -71,6 +71,7 @@ export abstract class PollPdfService { * @returns the amount of ballots, depending on the config settings */ protected getBallotCount(): number { + // TODO: seems to be broken switch (this.ballotCountSelection) { case 'NUMBER_OF_ALL_PARTICIPANTS': return this.userRepo.getViewModelList().length; diff --git a/client/src/app/shared/models/poll/base-poll.ts b/client/src/app/shared/models/poll/base-poll.ts index be98afe08..9aec1d218 100644 --- a/client/src/app/shared/models/poll/base-poll.ts +++ b/client/src/app/shared/models/poll/base-poll.ts @@ -52,6 +52,22 @@ export abstract class BasePoll = any> extends public onehundred_percent_base: PercentBase; public user_has_voted: boolean; + public get isStateCreated(): boolean { + return this.state === PollState.Created; + } + + public get isStateStarted(): boolean { + return this.state === PollState.Started; + } + + public get isStateFinished(): boolean { + return this.state === PollState.Finished; + } + + public get isStatePublished(): boolean { + return this.state === PollState.Published; + } + /** * Determine if the state is finished or published */ diff --git a/client/src/app/shared/models/poll/base-vote.ts b/client/src/app/shared/models/poll/base-vote.ts index 91325f4bc..f1aee007b 100644 --- a/client/src/app/shared/models/poll/base-vote.ts +++ b/client/src/app/shared/models/poll/base-vote.ts @@ -9,9 +9,9 @@ export const VoteValueVerbose = { }; export const GeneralValueVerbose = { - votesvalid: 'Votes valid', - votesinvalid: 'Votes invalid', - votescast: 'Votes cast', + votesvalid: 'Valid votes', + votesinvalid: 'Invalid votes', + votescast: 'Total votes cast', votesno: 'Votes No', votesabstain: 'Votes abstain' }; diff --git a/client/src/app/shared/pipes/parse-poll-number.pipe.spec.ts b/client/src/app/shared/pipes/parse-poll-number.pipe.spec.ts new file mode 100644 index 000000000..5e2523140 --- /dev/null +++ b/client/src/app/shared/pipes/parse-poll-number.pipe.spec.ts @@ -0,0 +1,20 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { ParsePollNumberPipe } from './parse-poll-number.pipe'; + +describe('ParsePollNumberPipe', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [ParsePollNumberPipe] + }); + TestBed.compileComponents(); + }); + + it('create an instance', inject([TranslateService], (translate: TranslateService) => { + const pipe = new ParsePollNumberPipe(translate); + expect(pipe).toBeTruthy(); + })); +}); diff --git a/client/src/app/shared/pipes/parse-poll-number.pipe.ts b/client/src/app/shared/pipes/parse-poll-number.pipe.ts new file mode 100644 index 000000000..c8c558a7d --- /dev/null +++ b/client/src/app/shared/pipes/parse-poll-number.pipe.ts @@ -0,0 +1,22 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import { TranslateService } from '@ngx-translate/core'; + +@Pipe({ + name: 'parsePollNumber' +}) +export class ParsePollNumberPipe implements PipeTransform { + public constructor(private translate: TranslateService) {} + + public transform(value: number): number | string { + const input = Math.trunc(value); + switch (input) { + case -1: + return this.translate.instant('majority'); + case -2: + return this.translate.instant('undocumented'); + default: + return input; + } + } +} diff --git a/client/src/app/shared/pipes/reverse.pipe.spec.ts b/client/src/app/shared/pipes/reverse.pipe.spec.ts new file mode 100644 index 000000000..fc22c38d6 --- /dev/null +++ b/client/src/app/shared/pipes/reverse.pipe.spec.ts @@ -0,0 +1,8 @@ +import { ReversePipe } from './reverse.pipe'; + +describe('ReversePipe', () => { + it('create an instance', () => { + const pipe = new ReversePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/client/src/app/shared/pipes/reverse.pipe.ts b/client/src/app/shared/pipes/reverse.pipe.ts new file mode 100644 index 000000000..9e52edc6c --- /dev/null +++ b/client/src/app/shared/pipes/reverse.pipe.ts @@ -0,0 +1,20 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +/** + * Invert the order of arrays in templates + * + * @example + * ```html + *
  • + * {{ user.name }} has the id: {{ user.id }} + *
  • + * ``` + */ +@Pipe({ + name: 'reverse' +}) +export class ReversePipe implements PipeTransform { + public transform(value: any[]): any[] { + return value.slice().reverse(); + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 696293c3c..319640470 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -119,6 +119,8 @@ import { BasePollDialogComponent } from 'app/site/polls/components/base-poll-dia import { PollFormComponent } from 'app/site/polls/components/poll-form/poll-form.component'; import { MotionPollDialogComponent } from 'app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component'; import { AssignmentPollDialogComponent } from 'app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component'; +import { ParsePollNumberPipe } from './pipes/parse-poll-number.pipe'; +import { ReversePipe } from './pipes/reverse.pipe'; /** * Share Module for all "dumb" components and pipes. @@ -279,7 +281,9 @@ import { AssignmentPollDialogComponent } from 'app/site/assignments/components/a BannerComponent, PollFormComponent, MotionPollDialogComponent, - AssignmentPollDialogComponent + AssignmentPollDialogComponent, + ParsePollNumberPipe, + ReversePipe ], declarations: [ PermsDirective, @@ -333,7 +337,9 @@ import { AssignmentPollDialogComponent } from 'app/site/assignments/components/a BannerComponent, PollFormComponent, MotionPollDialogComponent, - AssignmentPollDialogComponent + AssignmentPollDialogComponent, + ParsePollNumberPipe, + ReversePipe ], providers: [ { @@ -349,7 +355,9 @@ import { AssignmentPollDialogComponent } from 'app/site/assignments/components/a DecimalPipe, ProgressSnackBarComponent, TrustPipe, - LocalizedDatePipe + LocalizedDatePipe, + ParsePollNumberPipe, + ReversePipe ], entryComponents: [ SortBottomSheetComponent, diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html index 96cb6589c..eb82c8f25 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html @@ -65,20 +65,12 @@
    - - - - - - - - - - + + @@ -135,13 +127,17 @@ - - + +

    Candidates

    {{ group.getTitle() | translate }}
    -
    {{ 'Poll type' | translate }}: {{ poll.typeVerbose | translate }}
    -
    {{ 'Poll method' | translate }}: {{ poll.pollmethodVerbose | translate }}
    -
    {{ 'Majority method' | translate }}: {{ poll.majorityMethodVerbose | translate }}
    +
    {{ 'Voting type' | translate }}: {{ poll.typeVerbose | translate }}
    +
    {{ 'Election method' | translate }}: {{ poll.pollmethodVerbose | translate }}
    +
    {{ 'Required majority' | translate }}: {{ poll.majorityMethodVerbose | translate }}
    {{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }}
    + +
    -
    +

    Result

    diff --git a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.html b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.html index e984aca1f..f67ea8518 100644 --- a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.html +++ b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.html @@ -8,14 +8,14 @@ {{ option.user.getFullName() }} No user {{ option.candidate_id }}
    - +
    @@ -28,7 +28,7 @@ [placeholder]="generalValueVerbose[value] | translate" [checkboxValue]="-1" inputType="number" - [checkboxLabel]="'Majority' | translate" + [checkboxLabel]="'majority' | translate" [formControlName]="value" >
    diff --git a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.html b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.html index f1543a869..db66adf8f 100644 --- a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.html +++ b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.html @@ -1,4 +1,10 @@
    + +
    + +
    + +
    - -
    - -
    -
    - -
    -
    - - -
    -
    - - + + +
    + +
    +
    + +
    +
    + + +
    +
    diff --git a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.scss b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.scss index 7c8b40b80..bcc96c384 100644 --- a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.scss +++ b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.scss @@ -3,33 +3,10 @@ position: relative; padding: 0 15px; - .poll-main-content { - padding-top: 10px; - } - - .poll-grid { - display: grid; - grid-gap: 5px; - padding: 5px; - grid-template-columns: 30px auto 250px 150px; - .candidate-name { - word-wrap: break-word; - } - } - - .right-align { - text-align: right; - } - - .vote-input { - .mat-form-field-wrapper { - // padding-bottom: 0; - - .mat-form-field-infix { - width: 60px; - border-top: 0; - } - } + .poll-menu { + position: absolute; + top: 0; + right: 0; } .poll-properties { @@ -62,33 +39,4 @@ } } } - - .poll-menu { - position: absolute; - top: 0; - right: 0; - } - - .poll-quorum { - text-align: right; - margin-right: 10px; - mat-icon { - vertical-align: middle; - font-size: 100%; - } - } - - .top-aligned { - position: absolute; - top: 0; - left: 0; - } - - .wide { - width: 90%; - } - - .hint-form { - margin-top: 20px; - } } diff --git a/client/src/app/site/assignments/services/assignment-poll.service.ts b/client/src/app/site/assignments/services/assignment-poll.service.ts index d3ad17b52..13d315b1a 100644 --- a/client/src/app/site/assignments/services/assignment-poll.service.ts +++ b/client/src/app/site/assignments/services/assignment-poll.service.ts @@ -49,7 +49,7 @@ export class AssignmentPollService extends PollService { const length = this.pollRepo.getViewModelList().filter(item => item.assignment_id === poll.assignment_id) .length; - poll.title = !length ? this.translate.instant('Vote') : `${this.translate.instant('Vote')} (${length + 1})`; + poll.title = !length ? this.translate.instant('Ballot') : `${this.translate.instant('Ballot')} (${length + 1})`; poll.pollmethod = AssignmentPollMethods.YN; poll.assignment_id = poll.assignment_id; } diff --git a/client/src/app/site/config/components/config-overview/config-overview.component.html b/client/src/app/site/config/components/config-overview/config-overview.component.html index 140deffee..30b0f6261 100644 --- a/client/src/app/site/config/components/config-overview/config-overview.component.html +++ b/client/src/app/site/config/components/config-overview/config-overview.component.html @@ -25,6 +25,7 @@ home today assignment + pie_chart how_to_vote groups language diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html index 433dcee23..41cf9a52b 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html @@ -463,7 +463,7 @@
    diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.html b/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.html index de621c05b..fb4b65c77 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.html +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.html @@ -1,9 +1,9 @@
    -

    {{ 'Motion' | translate }} {{ poll.motion.id }}

    +

    {{ 'Motion' | translate }} {{ poll.motion.identifierOrTitle }}

    - - -
    - -
    - - - diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.scss b/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.scss index f09ea5838..355c9138a 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.scss +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.scss @@ -35,4 +35,8 @@ .named-result-table { grid-area: names; + .mat-form-field { + font-size: 14px; + width: 100%; + } } diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.html b/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.html index 0c04fa638..dbf278737 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.html +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.html @@ -6,41 +6,43 @@ [placeholder]="'Yes' | translate" [checkboxValue]="-1" inputType="number" - [checkboxLabel]="'Majority' | translate" + [checkboxLabel]="'majority' | translate" formControlName="Y" >
    -
    + + +
    Publish immediately diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.ts b/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.ts index 17954a2c5..652450db5 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.ts +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component.ts @@ -42,9 +42,6 @@ export class MotionPollDialogComponent extends BasePollDialogComponent { votesinvalid: data.votesinvalid, votescast: data.votescast }; - // if (data.pollmethod === 'YNA') { - // update.A = data.options[0].abstain; - // } if (this.dialogVoteForm) { const result = this.undoReplaceEmptyValues(update); @@ -64,9 +61,7 @@ export class MotionPollDialogComponent extends BasePollDialogComponent { votesinvalid: ['', [Validators.min(-2)]], votescast: ['', [Validators.min(-2)]] }); - // if (this.pollData.pollmethod === MotionPollMethods.YNA) { - // this.dialogVoteForm.addControl('A', this.fb.control('', [Validators.min(-2)])); - // } + if (this.pollData.poll) { this.updateDialogVoteForm(this.pollData); } diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.html b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.html index e3c602ec4..e0efc88ab 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.html +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.html @@ -1,6 +1,8 @@ +
    + +
    -

    - - {{ 'Poll type' | translate }}: {{ poll.typeVerbose | translate }} - +
    + {{ poll.typeVerbose | translate }} +
    -
    - +
    +
    -
    - - {{ voteYes }} - + +
    +
    +
    -
    - -
    -
    - - {{ voteNo }} - +
    +
    + + {{ voteYes | parsePollNumber }} + +
    +
    + + {{ voteNo | parsePollNumber }} + +
    +
    + + {{ voteAbstain | parsePollNumber }} + +
    +
    + +
    -
    - An empty poll - you have to enter votes. +
    + {{ 'An empty poll - you have to enter votes.' | translate }}
    + + + + + +
    + + +
    +
    + +