From 61b7731073bf4b988f5dbcd0b6ae2f6a35e60707 Mon Sep 17 00:00:00 2001 From: Sean Engelhardt Date: Fri, 6 Mar 2020 13:21:16 +0100 Subject: [PATCH] Enhance charts and tables for assignments Also some various improvements --- .../app/core/translate/marked-translations.ts | 1 + .../app/core/ui-services/banner.service.ts | 3 +- .../core/ui-services/voting-banner.service.ts | 16 ++-- .../components/banner/banner.component.html | 3 + .../components/banner/banner.component.scss | 5 +- .../banner/banner.component.scss-theme.scss | 4 +- .../components/charts/charts.component.ts | 38 +++++---- .../check-input/check-input.component.ts | 10 +-- .../voting-privacy-warning.component.html | 18 +++++ .../voting-privacy-warning.component.scss | 0 .../voting-privacy-warning.component.spec.ts | 26 ++++++ .../voting-privacy-warning.component.ts | 12 +++ .../src/app/shared/models/poll/base-poll.ts | 4 + client/src/app/shared/shared.module.ts | 11 ++- .../assignment-detail.component.ts | 2 +- .../assignment-poll-detail.component.html | 76 ++++++++++-------- .../assignment-poll-detail.component.scss | 80 +++++++++++-------- .../assignment-poll-detail.component.ts | 18 ++--- .../assignment-poll-dialog.component.spec.ts | 34 ++++++++ .../assignment-poll-dialog.component.ts | 26 +++--- .../assignment-poll-vote.component.html | 8 +- .../assignment-poll-vote.component.ts | 14 +++- .../assignment-poll.component.html | 31 ++++--- .../assignment-poll.component.scss | 7 -- .../assignment-poll.component.ts | 27 +------ .../models/view-assignment-poll.ts | 26 +++--- .../services/assignment-poll.service.ts | 17 ++-- .../site/motions/models/view-motion-poll.ts | 4 + .../motion-detail.component.html | 23 ++++-- .../motion-detail.component.scss | 7 +- .../motion-detail/motion-detail.component.ts | 2 +- .../motion-poll-detail.component.html | 3 +- .../motion-poll-dialog.component.ts | 19 +++-- .../motion-poll-vote.component.ts | 17 +++- .../motion-poll/motion-poll.component.html | 45 +++++------ .../motion-poll/motion-poll.component.scss | 6 +- .../motion-poll/motion-poll.component.ts | 65 ++++----------- .../workflow-detail.component.ts | 6 +- .../motions/services/motion-poll.service.ts | 12 ++- .../components/base-poll-dialog.component.ts | 18 ++++- .../poll-form/poll-form.component.html | 5 +- .../poll-form/poll-form.component.scss | 7 ++ .../poll-form/poll-form.component.ts | 25 +++++- .../poll-progress.component.html | 8 +- .../poll-progress.component.scss | 6 +- .../app/site/polls/models/view-base-option.ts | 4 + .../app/site/polls/models/view-base-poll.ts | 16 ++-- .../app/site/polls/services/poll.service.ts | 74 ++++++++--------- .../assignment-poll-slide-data.ts | 2 +- .../assignment-poll-slide.component.html | 2 +- openslides/assignments/config_variables.py | 2 +- 51 files changed, 528 insertions(+), 367 deletions(-) create mode 100644 client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.html create mode 100644 client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.scss create mode 100644 client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.spec.ts create mode 100644 client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.ts create mode 100644 client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.spec.ts diff --git a/client/src/app/core/translate/marked-translations.ts b/client/src/app/core/translate/marked-translations.ts index 66b1808ae..0f035365c 100644 --- a/client/src/app/core/translate/marked-translations.ts +++ b/client/src/app/core/translate/marked-translations.ts @@ -173,6 +173,7 @@ _('Number of all participants'); _('Use the following custom number'); _('Custom number of ballot papers'); _('Voting'); +_('Click here to vote'); // subgroup PDF export _('PDF export'); _('Title for PDF documents of motions'); diff --git a/client/src/app/core/ui-services/banner.service.ts b/client/src/app/core/ui-services/banner.service.ts index d91e325a4..7bc1a6619 100644 --- a/client/src/app/core/ui-services/banner.service.ts +++ b/client/src/app/core/ui-services/banner.service.ts @@ -7,8 +7,7 @@ export interface BannerDefinition { class?: string; icon?: string; text?: string; - bgColor?: string; - color?: string; + subText?: string; link?: string; largerOnMobileView?: boolean; } diff --git a/client/src/app/core/ui-services/voting-banner.service.ts b/client/src/app/core/ui-services/voting-banner.service.ts index 6c72e7c7c..6d24cfe66 100644 --- a/client/src/app/core/ui-services/voting-banner.service.ts +++ b/client/src/app/core/ui-services/voting-banner.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; +import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll'; import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll'; import { ViewBasePoll } from 'app/site/polls/models/view-base-poll'; import { PollListObservableService } from 'app/site/polls/services/poll-list-observable.service'; @@ -15,6 +16,8 @@ import { VotingService } from './voting.service'; export class VotingBannerService { private currentBanner: BannerDefinition; + private subText = 'Click here to vote'; + public constructor( pollListObservableService: PollListObservableService, private banner: BannerService, @@ -58,6 +61,7 @@ export class VotingBannerService { private createBanner(text: string, link: string): BannerDefinition { return { text: text, + subText: this.subText, link: link, icon: 'how_to_vote', largerOnMobileView: true @@ -72,11 +76,13 @@ export class VotingBannerService { * @returns The title. */ private getTextForPoll(poll: ViewBasePoll): string { - return poll instanceof ViewMotionPoll - ? `${this.translate.instant('Motion') + ' ' + poll.motion.getIdentifierOrTitle()}: ${this.translate.instant( - 'Voting is open' - )}` - : `${poll.getTitle()}: ${this.translate.instant('Ballot is open')}`; + if (poll instanceof ViewMotionPoll) { + return `${this.translate.instant('Motion')} ${poll.motion.getIdentifierOrTitle()}: ${this.translate.instant( + 'Voting opened' + )}`; + } else if (poll instanceof ViewAssignmentPoll) { + return `${poll.assignment.getTitle()}: ${this.translate.instant('Ballot openened!')}`; + } } /** diff --git a/client/src/app/shared/components/banner/banner.component.html b/client/src/app/shared/components/banner/banner.component.html index df3bb7d76..a3bd4b20e 100644 --- a/client/src/app/shared/components/banner/banner.component.html +++ b/client/src/app/shared/components/banner/banner.component.html @@ -16,6 +16,9 @@ diff --git a/client/src/app/shared/components/banner/banner.component.scss b/client/src/app/shared/components/banner/banner.component.scss index 9e0aa2ceb..539b3ce2c 100644 --- a/client/src/app/shared/components/banner/banner.component.scss +++ b/client/src/app/shared/components/banner/banner.component.scss @@ -3,12 +3,12 @@ .banner { &.larger-on-mobile { @include set-breakpoint-lower(sm) { - height: 40px; + min-height: 40px; } } position: relative; // was fixed before to prevent the overflow - height: 20px; + min-height: 20px; line-height: 20px; width: 100%; text-align: center; @@ -18,7 +18,6 @@ border-bottom: 1px solid white; a { - display: flex; align-items: center; justify-content: center; text-decoration: none; diff --git a/client/src/app/shared/components/banner/banner.component.scss-theme.scss b/client/src/app/shared/components/banner/banner.component.scss-theme.scss index 0eef81f1c..20866ad83 100644 --- a/client/src/app/shared/components/banner/banner.component.scss-theme.scss +++ b/client/src/app/shared/components/banner/banner.component.scss-theme.scss @@ -2,10 +2,10 @@ /** Custom component theme. Only lives in a specific scope */ @mixin os-banner-style($theme) { - $primary: map-get($theme, primary); + $accent: map-get($theme, accent); /** style for the offline-banner */ .banner { - background: mat-color($primary, 900); + background: mat-color($accent, 500); } } diff --git a/client/src/app/shared/components/charts/charts.component.ts b/client/src/app/shared/components/charts/charts.component.ts index 70b7fe482..0c24b665e 100644 --- a/client/src/app/shared/components/charts/charts.component.ts +++ b/client/src/app/shared/components/charts/charts.component.ts @@ -199,14 +199,24 @@ export class ChartsComponent extends BaseViewComponent { labels: {} }, scales: { - xAxes: [{ ticks: { beginAtZero: true, stepSize: 1 } }], - yAxes: [{ ticks: { beginAtZero: true } }] - }, - plugins: { - datalabels: { - anchor: 'end', - align: 'end' - } + xAxes: [ + { + gridLines: { + drawOnChartArea: false + }, + ticks: { beginAtZero: true, stepSize: 1 }, + stacked: true + } + ], + yAxes: [ + { + gridLines: { + drawOnChartArea: false + }, + ticks: { beginAtZero: true, mirror: true, labelOffset: -20 }, + stacked: true + } + ] } }; @@ -251,16 +261,6 @@ export class ChartsComponent extends BaseViewComponent { super(title, translate, matSnackbar); } - /** - * Changes the chart-options, if the `stackedBar` is used. - */ - private setupStackedBar(): void { - this.chartOptions.scales = Object.assign(this.chartOptions.scales, { - xAxes: [{ stacked: true }], - yAxes: [{ stacked: true }] - }); - } - private setupBar(): void { if (!this.chartData.every(date => date.barThickness && date.maxBarThickness)) { this.chartData = this.chartData.map(chartDate => ({ @@ -284,7 +284,6 @@ export class ChartsComponent extends BaseViewComponent { fontSize: 14, boxWidth: 40 }; - break; } this.cd.detectChanges(); } @@ -292,7 +291,6 @@ export class ChartsComponent extends BaseViewComponent { private checkChartType(chartType?: ChartType): void { let type = chartType || this._type; if (type === 'stackedBar') { - this.setupStackedBar(); this.setupBar(); type = 'horizontalBar'; } diff --git a/client/src/app/shared/components/check-input/check-input.component.ts b/client/src/app/shared/components/check-input/check-input.component.ts index 0b4a29356..22292dd3a 100644 --- a/client/src/app/shared/components/check-input/check-input.component.ts +++ b/client/src/app/shared/components/check-input/check-input.component.ts @@ -88,12 +88,10 @@ export class CheckInputComponent extends BaseViewComponent implements OnInit, Co * @param obj the value from the parent form. Type "any" is required by the interface */ public writeValue(obj: string | number): void { - if (obj) { - if (obj === this.checkboxValue) { - this.checkboxStateChanged(true); - } else { - this.contentForm.patchValue(obj); - } + if (obj && obj === this.checkboxValue) { + this.checkboxStateChanged(true); + } else { + this.contentForm.patchValue(obj); } } diff --git a/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.html b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.html new file mode 100644 index 000000000..d28ec9c38 --- /dev/null +++ b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.html @@ -0,0 +1,18 @@ +

+ Online voting is impossible to secure +

+ +
+ + During voting, OpenSlides does not store the individual user ID of the voter. This in no way means that a + non-nominal vote is completely anonymous and secure. You cannot track the decisions of your voters after the + data has been submitted. The validity of the data cannot always be guaranteed, especially if you use OpenSlides + in a distributed online setup. You are responsible for your own actions. + +
+ +
+ +
diff --git a/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.scss b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.spec.ts b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.spec.ts new file mode 100644 index 000000000..9190d7963 --- /dev/null +++ b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2EImportsModule } from 'e2e-imports.module'; + +import { VotingPrivacyWarningComponent } from './voting-privacy-warning.component'; + +describe('VotingPrivacyWarningComponent', () => { + let component: VotingPrivacyWarningComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VotingPrivacyWarningComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.ts b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.ts new file mode 100644 index 000000000..da99280e7 --- /dev/null +++ b/client/src/app/shared/components/voting-privacy-warning/voting-privacy-warning.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'os-voting-privacy-warning', + templateUrl: './voting-privacy-warning.component.html', + styleUrls: ['./voting-privacy-warning.component.scss'] +}) +export class VotingPrivacyWarningComponent implements OnInit { + public constructor() {} + + public ngOnInit(): void {} +} diff --git a/client/src/app/shared/models/poll/base-poll.ts b/client/src/app/shared/models/poll/base-poll.ts index a78f1eb04..95166aada 100644 --- a/client/src/app/shared/models/poll/base-poll.ts +++ b/client/src/app/shared/models/poll/base-poll.ts @@ -76,6 +76,10 @@ export abstract class BasePoll< return this.onehundred_percent_base === PercentBase.Valid || this.onehundred_percent_base === PercentBase.Cast; } + public get isPercentBaseCast(): boolean { + return this.onehundred_percent_base === PercentBase.Cast; + } + /** * Determine if the state is finished or published */ diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 3c7209208..94fb404ff 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -114,7 +114,6 @@ import { LocalizedDatePipe } from './pipes/localized-date.pipe'; import { ChartsComponent } from './components/charts/charts.component'; import { CheckInputComponent } from './components/check-input/check-input.component'; import { BannerComponent } from './components/banner/banner.component'; -import { BasePollDialogComponent } from 'app/site/polls/components/base-poll-dialog.component'; 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'; @@ -122,6 +121,7 @@ import { ParsePollNumberPipe } from './pipes/parse-poll-number.pipe'; import { ReversePipe } from './pipes/reverse.pipe'; import { PollKeyVerbosePipe } from './pipes/poll-key-verbose.pipe'; import { PollPercentBasePipe } from './pipes/poll-percent-base.pipe'; +import { VotingPrivacyWarningComponent } from './components/voting-privacy-warning/voting-privacy-warning.component'; /** * Share Module for all "dumb" components and pipes. @@ -285,7 +285,8 @@ import { PollPercentBasePipe } from './pipes/poll-percent-base.pipe'; ParsePollNumberPipe, ReversePipe, PollKeyVerbosePipe, - PollPercentBasePipe + PollPercentBasePipe, + VotingPrivacyWarningComponent ], declarations: [ PermsDirective, @@ -342,7 +343,8 @@ import { PollPercentBasePipe } from './pipes/poll-percent-base.pipe'; ParsePollNumberPipe, ReversePipe, PollKeyVerbosePipe, - PollPercentBasePipe + PollPercentBasePipe, + VotingPrivacyWarningComponent ], providers: [ { @@ -373,7 +375,8 @@ import { PollPercentBasePipe } from './pipes/poll-percent-base.pipe'; ProgressSnackBarComponent, SuperSearchComponent, MotionPollDialogComponent, - AssignmentPollDialogComponent + AssignmentPollDialogComponent, + VotingPrivacyWarningComponent ] }) export class SharedModule {} diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts index 6ad6054f4..87d8bdd5a 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts @@ -313,7 +313,7 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn collectionString: ViewAssignmentPoll.COLLECTIONSTRING, assignment_id: this.assignment.id, assignment: this.assignment, - ...this.assignmentPollService.getDefaultPollData() + ...this.assignmentPollService.getDefaultPollData(this.assignment.id) }; this.pollDialog.openDialog(dialogData); diff --git a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.html b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.html index 61674131d..b5a93ec8f 100644 --- a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.html +++ b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.html @@ -20,14 +20,14 @@

{{ poll.title }}

{{ poll.typeVerbose | translate }} -
-
- +
+ +
- - + - - + + - - +
Candidates + Candidates Yes @@ -35,42 +35,50 @@ Votes NoAbstainNoAbstain
- - {{ row.votingOption | pollKeyVerbose | translate }} - - -
- {{ row.votingOptionSubtitle }} -
-
-
+
+
+ + {{ row.votingOption | pollKeyVerbose | translate }} + + +
+ {{ row.votingOptionSubtitle }} +
+
+
+
- {{ vote.amount | parsePollNumber }} {{ vote.amount | pollPercentBase: poll }} + {{ vote.amount | parsePollNumber }}
+
- + +
@@ -112,7 +120,7 @@
-
+
{{ candidate }}
@@ -121,21 +129,21 @@
+ - -
- - {{ 'Groups' | translate }}: + +
+ + {{ 'Groups' | translate }}: - - {{ group.getTitle() | translate }}, - - + + {{ group.getTitle() | translate }}, + + - - {{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }} - -
+ + {{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }} +
diff --git a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.scss b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.scss index 94725e90f..1dc97d084 100644 --- a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.scss +++ b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.scss @@ -2,24 +2,22 @@ @import '~assets/styles/poll-colors.scss'; .assignment-result-wrapper { - margin-top: 2em; - display: grid; - grid-gap: 10px; - .assignment-result-table { + margin-top: 2em; + display: block; + overflow-x: auto; border-collapse: collapse; th { - text-align: left; font-weight: initial; } tr { height: 48px; - } - tr:last-child { - border-bottom: none; + td:first-child { + padding-right: 1em; + } } tr.sums { @@ -30,39 +28,57 @@ } } + .result { + text-align: right; + padding-left: 1em; + } + + .voting-option { + min-width: 200px; + width: 100%; + text-align: left; + } + .user + .sums { td { - padding-top: 4em; + padding-top: 2em; } } + + .single-result { + white-space: pre; + } } - .pie-chart { - margin-left: auto; - margin-right: auto; - width: 50%; - } -} - -.single-vote-result + .single-vote-result { - margin-top: 1em; -} - -.named-result-table { - .mat-form-field { - font-size: 14px; - width: 100%; + .chart-wrapper { + margin-top: 2em; + .pie-chart { + margin-left: auto; + margin-right: auto; + width: 50%; + } } - .single-votes-table { - display: block; - height: 500px; - } + .named-result-table { + .mat-form-field { + font-size: 14px; + width: 100%; + } - .vote-field { - text-align: center; - width: 100%; - padding-right: 12px; + .single-votes-table { + display: block; + height: 500px; + + .single-vote-result + .single-vote-result { + margin-top: 1em; + } + } + + .vote-field { + text-align: center; + width: 100%; + padding-right: 12px; + } } } diff --git a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.ts b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.ts index e59b4ee59..6420ae119 100644 --- a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.ts +++ b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail.component.ts @@ -34,11 +34,9 @@ export class AssignmentPollDetailComponent extends BasePollDetailComponent { + let component: AssignmentPollDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: {} + } + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AssignmentPollDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts index 9acb1b84b..5004194d0 100644 --- a/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts +++ b/client/src/app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component.ts @@ -85,15 +85,23 @@ export class AssignmentPollDialogComponent extends BasePollDialogComponent ({ - user_id: user.id, - user: user - }), - {} - ); + if (this.pollData) { + if (this.pollData.options) { + this.options = this.pollData.options; + } else if ( + this.pollData.assignment && + this.pollData.assignment.candidates && + this.pollData.assignment.candidates.length + ) { + this.options = this.pollData.assignment.candidates.map( + user => ({ + user_id: user.id, + user: user + }), + {} + ); + } + } this.subscriptions.push( this.pollForm.contentForm.get('pollmethod').valueChanges.subscribe(() => { diff --git a/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.html b/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.html index 2cc0d3069..711534cfe 100644 --- a/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.html +++ b/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.html @@ -1,5 +1,4 @@ - Your vote is valid! @@ -22,7 +21,12 @@ }" >
- {{ option.user.getFullName() }} + + {{ option.user.short_name }} +
+ {{ option.user.getLevelAndNumber() }} +
+
{{ 'Unknown user' | translate }}
diff --git a/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.ts b/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.ts index 8f4dce333..ef99f8f13 100644 --- a/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.ts +++ b/client/src/app/site/assignments/components/assignment-poll-vote/assignment-poll-vote.component.ts @@ -122,12 +122,17 @@ export class AssignmentPollVoteComponent extends BasePollVoteComponent { - if ((n === optionId && vote === 'Y') !== (this.currentVotes[n] === 'Yes')) { - o[n] = 1; // TODO: allow multiple votes per candidate - } else { - o[n] = 0; + o[n] = 0; + if (this.poll.votes_amount === 1) { + if (n === optionId && this.currentVotes[n] !== 'Yes') { + o[n] = 1; + } + } else if ((n === optionId) !== (this.currentVotes[n] === 'Yes')) { + o[n] = 1; } + return o; }, {}); } else { @@ -135,6 +140,7 @@ export class AssignmentPollVoteComponent extends BasePollVoteComponent +
@@ -21,7 +21,7 @@
-
- + +
+
+ +
+ + +
+ + {{ 'Counting is in progress' | translate }} + +
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 3f8ef3fbb..47fa85aa5 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 @@ -29,11 +29,4 @@ .publish-poll-button { color: $poll-publish-color; } - - .doughnut-chart { - display: block; - max-width: 300px; - margin-left: auto; - margin-right: auto; - } } diff --git a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.ts b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.ts index 9dd1fd9cb..151eafe5a 100644 --- a/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.ts +++ b/client/src/app/site/assignments/components/assignment-poll/assignment-poll.component.ts @@ -6,7 +6,6 @@ import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; -import { OperatorService } from 'app/core/core-services/operator.service'; import { AssignmentPollRepositoryService } from 'app/core/repositories/assignments/assignment-poll-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { ChartType } from 'app/shared/components/charts/charts.component'; @@ -39,7 +38,7 @@ export class AssignmentPollComponent extends BasePollComponent ({ - votingOption: key.vote, - class: 'sums', - value: [ - { - amount: this[key.vote], - hide: key.hide, - showPercent: key.showPercent - } as VotingResult - ] - })) + ...this.sumTableKeys + .filter(key => { + return !key.hide; + }) + .map(key => ({ + votingOption: key.vote, + class: 'sums', + value: [ + { + amount: this[key.vote], + hide: key.hide, + showPercent: key.showPercent + } as VotingResult + ] + })) ); return tableData; } 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 4dbbc79ec..f428d6647 100644 --- a/client/src/app/site/assignments/services/assignment-poll.service.ts +++ b/client/src/app/site/assignments/services/assignment-poll.service.ts @@ -54,14 +54,21 @@ export class AssignmentPollService extends PollService { .subscribe(method => (this.defaultPollMethod = method)); } - public getDefaultPollData(): AssignmentPoll { - const poll = new AssignmentPoll(super.getDefaultPollData()); - const length = this.pollRepo.getViewModelList().filter(item => item.assignment_id === poll.assignment_id) - .length; + public getDefaultPollData(contextId?: number): AssignmentPoll { + const poll = new AssignmentPoll({ + ...super.getDefaultPollData() + }); - poll.title = !length ? this.translate.instant('Ballot') : `${this.translate.instant('Ballot')} (${length + 1})`; + poll.title = this.translate.instant('Ballot'); poll.pollmethod = this.defaultPollMethod; + if (contextId) { + const length = this.pollRepo.getViewModelList().filter(item => item.assignment_id === contextId).length; + if (length) { + poll.title += ` (${length + 1})`; + } + } + return poll; } diff --git a/client/src/app/site/motions/models/view-motion-poll.ts b/client/src/app/site/motions/models/view-motion-poll.ts index 9d4cc0ce7..957ec7d31 100644 --- a/client/src/app/site/motions/models/view-motion-poll.ts +++ b/client/src/app/site/motions/models/view-motion-poll.ts @@ -34,6 +34,10 @@ export class ViewMotionPoll extends ViewBasePoll -
@@ -460,12 +465,16 @@
-
- -
+
diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss index 535e88b18..87e61c8ad 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss @@ -5,12 +5,7 @@ span { } .create-poll-button { - margin-top: 10px; - padding: 0px !important; - button { - display: block; - width: 100%; - } + margin-bottom: 1em; } .extra-controls-slot { diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts index b7941b02b..66cec02e8 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts @@ -1633,7 +1633,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, collectionString: ViewMotionPoll.COLLECTIONSTRING, motion_id: this.motion.id, motion: this.motion, - ...this.motionPollService.getDefaultPollData() + ...this.motionPollService.getDefaultPollData(this.motion.id) }; this.pollDialog.openDialog(dialogData); 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 0a12465e2..9fababa6a 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 @@ -67,9 +67,8 @@ -
+
{ +export class MotionPollDialogComponent extends BasePollDialogComponent implements OnInit { public PercentBaseVerbose = PercentBaseVerbose; @ViewChild('pollForm', { static: false }) @@ -30,6 +30,9 @@ export class MotionPollDialogComponent extends BasePollDialogComponent ) { super(title, translate, matSnackbar, dialogRef); + } + + public ngOnInit(): void { this.createDialog(); } @@ -54,12 +57,12 @@ export class MotionPollDialogComponent extends BasePollDialogComponent { + if (confirmed) { + this.pollRepo.vote(vote, this.poll.id).catch(this.raiseError); + } + }); + } else { + this.pollRepo.vote(vote, this.poll.id).catch(this.raiseError); + } } } diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.html b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.html index 25ca5369a..6edc09b8f 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.html +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.html @@ -6,11 +6,19 @@ - {{ poll.title }} + {{ poll.title | translate }}
+ + + + {{ poll.typeVerbose | translate }} · @@ -18,7 +26,7 @@ - {{ poll.stateVerbose }} + {{ poll.stateVerbose | translate }}
@@ -32,13 +40,8 @@
-
-