diff --git a/client/src/app/shared/components/motion-poll-detail-content/motion-poll-detail-content.component.scss b/client/src/app/shared/components/motion-poll-detail-content/motion-poll-detail-content.component.scss index 5f6eda914..01b374641 100644 --- a/client/src/app/shared/components/motion-poll-detail-content/motion-poll-detail-content.component.scss +++ b/client/src/app/shared/components/motion-poll-detail-content/motion-poll-detail-content.component.scss @@ -1,4 +1,4 @@ -@import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .result-wrapper { display: grid; @@ -21,18 +21,6 @@ text-align: right; } } - - .yes { - color: $votes-yes-color; - } - - .no { - color: $votes-no-color; - } - - .abstain { - color: $votes-abstain-color; - } } .doughnut-chart { diff --git a/client/src/app/shared/models/poll/base-poll.ts b/client/src/app/shared/models/poll/base-poll.ts index c998fce03..f4d178beb 100644 --- a/client/src/app/shared/models/poll/base-poll.ts +++ b/client/src/app/shared/models/poll/base-poll.ts @@ -77,6 +77,22 @@ export abstract class BasePoll< return this.onehundred_percent_base === PercentBase.Cast; } + public get isAnalog(): boolean { + return this.type === PollType.Analog; + } + + public get isNamed(): boolean { + return this.type === PollType.Named; + } + + public get isAnon(): boolean { + return this.type === PollType.Pseudoanonymous; + } + + public get isEVoting(): boolean { + return this.isNamed || this.isAnon; + } + /** * Determine if the state is finished or published */ diff --git a/client/src/app/shared/pipes/poll-percent-base.pipe.ts b/client/src/app/shared/pipes/poll-percent-base.pipe.ts index da48a9c6d..cfec9d13c 100644 --- a/client/src/app/shared/pipes/poll-percent-base.pipe.ts +++ b/client/src/app/shared/pipes/poll-percent-base.pipe.ts @@ -36,12 +36,10 @@ export class PollPercentBasePipe implements PipeTransform { totalByBase = this.motionPollService.getPercentBase(poll); } - if (totalByBase) { + if (totalByBase && totalByBase > 0) { const percentNumber = (value / totalByBase) * 100; - if (percentNumber > 0) { - const result = percentNumber % 1 === 0 ? percentNumber : percentNumber.toFixed(this.decimalPlaces); - return `(${result} %)`; - } + const result = percentNumber % 1 === 0 ? percentNumber : percentNumber.toFixed(this.decimalPlaces); + return `(${result} %)`; } return null; } 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 da6b6a668..0c4e7aecc 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 @@ -263,7 +263,7 @@ diff --git a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail-component.scss-theme.scss b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail-component.scss-theme.scss index 15514244e..4bcdd6b67 100644 --- a/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail-component.scss-theme.scss +++ b/client/src/app/site/assignments/components/assignment-poll-detail/assignment-poll-detail-component.scss-theme.scss @@ -9,4 +9,21 @@ border-bottom: 1px solid mat-color($background, focused-button); } } + + .openslides-theme .pbl-ngrid-row:hover { + background-color: mat-color($background, card); + } + + .openslides-theme os-list-view-table os-sort-filter-bar .custom-table-header { + &, + .action-buttons .input-container input { + background: mat-color($background, card); + } + } + + .openslides-theme .pbl-ngrid-header-cell:first-child { + &::after { + border-right: 1px solid mat-color($background, focused-button); + } + } } 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 7ea552e39..053be9365 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 @@ -27,7 +27,7 @@ Candidates - + Yes @@ -35,8 +35,8 @@ Votes - No - Abstain + No + Abstain 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 1dc97d084..df8b0a1ed 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 @@ -1,5 +1,5 @@ -@import '~assets/styles/variables.scss'; @import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .assignment-result-wrapper { .assignment-result-table { @@ -88,30 +88,6 @@ padding-top: 20px; } -.voted-yes { - color: $votes-yes-color; -} - -.voted-no { - color: $votes-no-color; -} - -.voted-abstain { - color: $votes-abstain-color; -} - -// theme -.openslides-theme .pbl-ngrid-row:hover { - background-color: #f9f9f9; -} - -.openslides-theme os-list-view-table os-sort-filter-bar .custom-table-header { - &, - .action-buttons .input-container input { - background: white; - } -} - .openslides-theme .pbl-ngrid-no-data { top: 10%; } @@ -128,6 +104,5 @@ top: 0; right: -1px; height: 100%; - border-right: 1px solid #e0e0e0; } } 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 44518a516..1d8cb421b 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 @@ -1,7 +1,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { PblColumnDefinition } from '@pebula/ngrid'; @@ -49,7 +49,8 @@ export class AssignmentPollDetailComponent extends BasePollDetailComponent - - + +

+ {{ pollHint }} +

{{ 'Votes for this poll' | translate }}: {{ getVotesCount() }}/{{ poll.votes_amount }}

@@ -32,10 +34,12 @@
+ + +
+ {{ 'Edit to enter votes.' | translate }} +
@@ -70,9 +74,18 @@
+ + + +
- + visibility 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 47fa85aa5..d41715abc 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 @@ -1,4 +1,5 @@ @import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .assignment-poll-wrapper { position: relative; @@ -17,16 +18,4 @@ margin-left: auto; } } - - .start-poll-button { - color: green !important; - } - - .stop-poll-button { - color: $poll-stop-color; - } - - .publish-poll-button { - color: $poll-publish-color; - } } 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 151eafe5a..26f1b0ae0 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 @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -21,8 +21,7 @@ import { ViewAssignmentPoll } from '../../models/view-assignment-poll'; @Component({ selector: 'os-assignment-poll', templateUrl: './assignment-poll.component.html', - styleUrls: ['./assignment-poll.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./assignment-poll.component.scss'] }) export class AssignmentPollComponent extends BasePollComponent implements OnInit { @Input() diff --git a/client/src/app/site/assignments/services/assignment-poll-pdf.service.ts b/client/src/app/site/assignments/services/assignment-poll-pdf.service.ts index 89cca7cf4..3cb908c06 100644 --- a/client/src/app/site/assignments/services/assignment-poll-pdf.service.ts +++ b/client/src/app/site/assignments/services/assignment-poll-pdf.service.ts @@ -190,7 +190,7 @@ export class AssignmentPollPdfService extends PollPdfService { */ private createPollHint(poll: ViewAssignmentPoll): object { return { - text: poll.description || '', + text: poll.assignment.default_poll_description || '', style: 'description' }; } 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 dccf4abb0..c75fcf4fd 100644 --- a/client/src/app/site/assignments/services/assignment-poll.service.ts +++ b/client/src/app/site/assignments/services/assignment-poll.service.ts @@ -32,6 +32,8 @@ export class AssignmentPollService extends PollService { public defaultPollMethod: AssignmentPollMethod; + private sortByVote: boolean; + /** * Constructor. Subscribes to the configuration values needed * @param config ConfigService @@ -53,6 +55,7 @@ export class AssignmentPollService extends PollService { config .get(AssignmentPoll.defaultPollMethodConfig) .subscribe(method => (this.defaultPollMethod = method)); + config.get('assignment_poll_sort_poll_result_by_votes').subscribe(sort => (this.sortByVote = sort)); } public getDefaultPollData(contextId?: number): AssignmentPoll { @@ -74,38 +77,47 @@ export class AssignmentPollService extends PollService { } private getGlobalVoteKeys(poll: ViewAssignmentPoll): VotingResult[] { + // debugger; return [ { vote: 'amount_global_no', - showPercent: false, - hide: poll.amount_global_no === -2 || poll.amount_global_no === 0 + showPercent: this.showPercentOfValidOrCast(poll), + hide: poll.amount_global_no === -2 || !poll.amount_global_no }, { vote: 'amount_global_abstain', - showPercent: false, - hide: poll.amount_global_abstain === -2 || poll.amount_global_abstain === 0 + showPercent: this.showPercentOfValidOrCast(poll), + hide: poll.amount_global_abstain === -2 || !poll.amount_global_abstain } ]; } public generateTableData(poll: ViewAssignmentPoll): PollTableData[] { - const tableData: PollTableData[] = poll.options.map(candidate => ({ - votingOption: candidate.user.short_name, - votingOptionSubtitle: candidate.user.getLevelAndNumber(), - class: 'user', - value: super.getVoteTableKeys(poll).map( - key => - ({ - vote: key.vote, - amount: candidate[key.vote], - icon: key.icon, - hide: key.hide, - showPercent: key.showPercent - } as VotingResult) - ) - })); - tableData.push(...this.formatVotingResultToTableData(super.getSumTableKeys(poll), poll)); + const tableData: PollTableData[] = poll.options + .sort((a, b) => { + if (this.sortByVote) { + return b.yes - a.yes; + } else { + return b.weight - a.weight; + } + }) + .map(candidate => ({ + votingOption: candidate.user.short_name, + votingOptionSubtitle: candidate.user.getLevelAndNumber(), + class: 'user', + value: super.getVoteTableKeys(poll).map( + key => + ({ + vote: key.vote, + amount: candidate[key.vote], + icon: key.icon, + hide: key.hide, + showPercent: key.showPercent + } as VotingResult) + ) + })); tableData.push(...this.formatVotingResultToTableData(this.getGlobalVoteKeys(poll), poll)); + tableData.push(...this.formatVotingResultToTableData(super.getSumTableKeys(poll), poll)); return tableData; } 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 ea382e4dc..918069b01 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 @@ -31,8 +31,9 @@
{{ 'No results to show' | translate }}
-
- +
+ +
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 42265dfe5..1372bdc13 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 @@ -1,5 +1,4 @@ -@import '~assets/styles/variables.scss'; -@import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .poll-content { text-align: right; @@ -30,18 +29,6 @@ height: 500px; } -.voted-yes { - color: $votes-yes-color; -} - -.voted-no { - color: $votes-no-color; -} - -.voted-abstain { - color: $votes-abstain-color; -} - .openslides-theme .pbl-ngrid-no-data { top: 10%; } 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 aa23e46ee..9df02a37a 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,14 +1,14 @@ +
+ +
-
- -
@@ -19,8 +19,12 @@
- - {{ 'You already voted on this poll' | translate }} - +
+ +
+ {{ 'You already voted on this poll.' | translate }} +
diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.scss b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.scss index b4bb22d38..d13eb0a9c 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.scss +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.scss @@ -1,4 +1,5 @@ @import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .vote-button-grid { display: grid; @@ -19,24 +20,15 @@ .user-has-voted { display: flex; + text-align: center; > * { margin-top: 1em; margin-left: auto; margin-right: auto; } -} -.voted-yes { - background-color: $votes-yes-color; - color: $vote-active-color; -} - -.voted-no { - background-color: $votes-no-color; - color: $vote-active-color; -} - -.voted-abstain { - background-color: $votes-abstain-color; - color: $vote-active-color; + .vote-submitted { + color: $votes-yes-color; + font-size: 200%; + } } diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.ts b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.ts index 1d8aebf65..2aefdc954 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.ts +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll-vote/motion-poll-vote.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; @@ -6,20 +6,16 @@ import { TranslateService } from '@ngx-translate/core'; import { OperatorService } from 'app/core/core-services/operator.service'; import { MotionPollRepositoryService } from 'app/core/repositories/motions/motion-poll-repository.service'; -import { MotionVoteRepositoryService } from 'app/core/repositories/motions/motion-vote-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { VotingService } from 'app/core/ui-services/voting.service'; -import { MotionPollMethod } from 'app/shared/models/motions/motion-poll'; -import { PollType } from 'app/shared/models/poll/base-poll'; import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll'; -import { ViewMotionVote } from 'app/site/motions/models/view-motion-vote'; import { BasePollVoteComponent } from 'app/site/polls/components/base-poll-vote.component'; interface VoteOption { - vote: 'Y' | 'N' | 'A'; - css: string; - icon: string; - label: string; + vote?: 'Y' | 'N' | 'A'; + css?: string; + icon?: string; + label?: string; } @Component({ @@ -27,19 +23,8 @@ interface VoteOption { templateUrl: './motion-poll-vote.component.html', styleUrls: ['./motion-poll-vote.component.scss'] }) -export class MotionPollVoteComponent extends BasePollVoteComponent implements OnInit { - /** - * holds the last saved vote - * - * TODO: There will be a bug. This has to be reset if the currently observed poll changes it's state back - * to started - */ - public currentVote: ViewMotionVote; - - public MotionPollMethod = MotionPollMethod; - - private votes: ViewMotionVote[]; - +export class MotionPollVoteComponent extends BasePollVoteComponent { + public currentVote: VoteOption = {}; public voteOptions: VoteOption[] = [ { vote: 'Y', @@ -67,52 +52,23 @@ export class MotionPollVoteComponent extends BasePollVoteComponent { - this.votes = votes; - this.updateVotes(); - }) - ); - } - - protected updateVotes(): void { - if (this.user && this.votes && this.poll) { - this.currentVote = null; - const filtered = this.votes.filter( - vote => vote.option.poll_id === this.poll.id && vote.user_id === this.user.id - ); - if (filtered.length) { - if (filtered.length > 1) { - // output warning and continue to keep the error case user friendly - console.error('A user should never have more than one vote on the same poll.'); - } - this.currentVote = filtered[0]; - } - } - } - /** * TODO: 'Y' | 'N' | 'A' should refer to some ENUM */ public saveVote(vote: 'Y' | 'N' | 'A'): void { - if (this.poll.type === PollType.Pseudoanonymous) { - const title = this.translate.instant('Are you sure?'); - const content = this.translate.instant('Your decision cannot be changed afterwards'); - this.promptService.open(title, content).then(confirmed => { - if (confirmed) { - this.pollRepo.vote(vote, this.poll.id).catch(this.raiseError); - } - }); - } else { - this.pollRepo.vote(vote, this.poll.id).catch(this.raiseError); - } + this.currentVote.vote = vote; + const title = this.translate.instant('Are you sure?'); + const content = this.translate.instant('Your decision cannot be changed afterwards'); + this.promptService.open(title, content).then(confirmed => { + if (confirmed) { + 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 6edc09b8f..7da49cb23 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 @@ -1,4 +1,4 @@ - +
@@ -56,7 +56,7 @@
- + visibility diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.scss b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.scss index 152d0e8e2..77539c2f7 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.scss +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.scss @@ -1,4 +1,5 @@ @import '~assets/styles/poll-colors.scss'; +@import '~assets/styles/poll-styles-common.scss'; .poll-link-wrapper { outline: none; @@ -46,18 +47,6 @@ div + div { margin-top: 20px; } - - .yes { - color: $votes-yes-color; - } - - .no { - color: $votes-no-color; - } - - .abstain { - color: $votes-abstain-color; - } } } } @@ -75,18 +64,6 @@ margin-bottom: auto; } -.start-poll-button { - color: green !important; -} - -.stop-poll-button { - color: $poll-stop-color; -} - -.publish-poll-button { - color: $poll-publish-color; -} - .motion-couting-in-progress-hint { margin-top: 1em; font-style: italic; diff --git a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.ts b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.ts index 2d298da17..0ebc61f08 100644 --- a/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.ts +++ b/client/src/app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.ts @@ -7,7 +7,6 @@ import { TranslateService } from '@ngx-translate/core'; import { MotionPollRepositoryService } from 'app/core/repositories/motions/motion-poll-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { VotingPrivacyWarningComponent } from 'app/shared/components/voting-privacy-warning/voting-privacy-warning.component'; -import { PollType } from 'app/shared/models/poll/base-poll'; import { infoDialogSettings } from 'app/shared/utils/dialog-settings'; import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll'; import { MotionPollDialogService } from 'app/site/motions/services/motion-poll-dialog.service'; @@ -15,6 +14,7 @@ import { MotionPollPdfService } from 'app/site/motions/services/motion-poll-pdf. import { MotionPollService } from 'app/site/motions/services/motion-poll.service'; import { BasePollComponent } from 'app/site/polls/components/base-poll.component'; import { PollService, PollTableData } from 'app/site/polls/services/poll.service'; +import { OperatorService } from 'app/core/core-services/operator.service'; /** * Component to show a motion-poll. @@ -48,16 +48,25 @@ export class MotionPollComponent extends BasePollComponent { return this.motionPollService.showChart(this.poll); } - public get hideChangeState(): boolean { - return this.poll.isPublished || (this.poll.isCreated && this.poll.type === PollType.Analog); - } - public get reducedPollTableData(): PollTableData[] { return this.motionPollService .generateTableData(this.poll) .filter(data => ['yes', 'no', 'abstain', 'votesinvalid'].includes(data.votingOption)); } + public get showPoll(): boolean { + if (this.poll) { + if ( + this.operator.hasPerms('motions.can_manage_polls') || + this.poll.isPublished || + (this.poll.isEVoting && !this.poll.isCreated) + ) { + return true; + } + } + return false; + } + /** * Constructor. * @@ -77,7 +86,8 @@ export class MotionPollComponent extends BasePollComponent { pollDialog: MotionPollDialogService, public pollService: PollService, private pdfService: MotionPollPdfService, - private motionPollService: MotionPollService + private motionPollService: MotionPollService, + private operator: OperatorService ) { super(titleService, matSnackBar, translate, dialog, promptService, pollRepo, pollDialog); } diff --git a/client/src/app/site/polls/components/base-poll-detail.component.ts b/client/src/app/site/polls/components/base-poll-detail.component.ts index 076060d50..475ec08ad 100644 --- a/client/src/app/site/polls/components/base-poll-detail.component.ts +++ b/client/src/app/site/polls/components/base-poll-detail.component.ts @@ -42,15 +42,15 @@ export abstract class BasePollDetailComponent extends Ba */ public voteOptionStyle = { Y: { - css: 'voted-yes', + css: 'yes', icon: 'thumb_up' }, N: { - css: 'voted-no', + css: 'no', icon: 'thumb_down' }, A: { - css: 'voted-abstain', + css: 'abstain', icon: 'trip_origin' } }; @@ -151,8 +151,6 @@ export abstract class BasePollDetailComponent extends Ba this.pollDialog.openDialog(viewPoll); } - protected onDeleted(): void {} - /** * Called after the poll has been loaded. Meant to be overwritten by subclasses who need initial access to the poll */ @@ -166,6 +164,8 @@ export abstract class BasePollDetailComponent extends Ba protected abstract hasPerms(): boolean; + protected abstract onDeleted(): void; + protected get canSeeVotes(): boolean { return (this.hasPerms && this.poll.isFinished) || this.poll.isPublished; } diff --git a/client/src/app/site/polls/components/base-poll.component.ts b/client/src/app/site/polls/components/base-poll.component.ts index e52711a23..6bb93a1c9 100644 --- a/client/src/app/site/polls/components/base-poll.component.ts +++ b/client/src/app/site/polls/components/base-poll.component.ts @@ -8,7 +8,7 @@ import { BehaviorSubject } from 'rxjs'; import { BasePollDialogService } from 'app/core/ui-services/base-poll-dialog.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { ChartData } from 'app/shared/components/charts/charts.component'; -import { PollState } from 'app/shared/models/poll/base-poll'; +import { PollState, PollType } from 'app/shared/models/poll/base-poll'; import { BaseViewComponent } from 'app/site/base/base-view'; import { BasePollRepositoryService } from '../services/base-poll-repository.service'; import { ViewBasePoll } from '../models/view-base-poll'; @@ -33,6 +33,10 @@ export abstract class BasePollComponent extends BaseView } }; + public get hideChangeState(): boolean { + return this._poll.isPublished || (this._poll.isCreated && this._poll.type === PollType.Analog); + } + public constructor( titleService: Title, matSnackBar: MatSnackBar, diff --git a/client/src/app/site/polls/services/poll.service.ts b/client/src/app/site/polls/services/poll.service.ts index ad640505a..a3eb9560a 100644 --- a/client/src/app/site/polls/services/poll.service.ts +++ b/client/src/app/site/polls/services/poll.service.ts @@ -234,23 +234,27 @@ export abstract class PollService { ); } + public showPercentOfValidOrCast(poll: PollData | ViewBasePoll): boolean { + return poll.onehundred_percent_base === PercentBase.Valid || poll.onehundred_percent_base === PercentBase.Cast; + } + public getSumTableKeys(poll: PollData | ViewBasePoll): VotingResult[] { return [ { vote: 'votesvalid', hide: poll.votesvalid === -2, - showPercent: - poll.onehundred_percent_base === PercentBase.Valid || - poll.onehundred_percent_base === PercentBase.Cast + showPercent: this.showPercentOfValidOrCast(poll) }, { vote: 'votesinvalid', icon: 'not_interested', + // TODO || PollType === analog hide: poll.votesinvalid === -2, showPercent: poll.onehundred_percent_base === PercentBase.Cast }, { vote: 'votescast', + // TODO || PollType === analog hide: poll.votescast === -2, showPercent: poll.onehundred_percent_base === PercentBase.Cast } diff --git a/client/src/app/slides/all-slides.ts b/client/src/app/slides/all-slides.ts index 5c26a4e32..e0529236e 100644 --- a/client/src/app/slides/all-slides.ts +++ b/client/src/app/slides/all-slides.ts @@ -44,8 +44,7 @@ export const allSlides: SlideManifest[] = [ { slide: 'motions/motion-poll', path: 'motions/motion-poll', - loadChildren: () => - import('./motions/motion-poll/motion-poll-slide.module').then(m => m.MotionPollSlideModule), + loadChildren: () => import('./motions/motion-poll/motion-poll-slide.module').then(m => m.MotionPollSlideModule), verboseName: 'Motion Poll', elementIdentifiers: ['name', 'id'], canBeMappedToModel: true @@ -137,7 +136,8 @@ export const allSlides: SlideManifest[] = [ { slide: 'assignments/assignment-poll', path: 'assignments/assignment-poll', - loadChildren: () => import('./assignments/assignment-poll/assignment-poll-slide.module').then(m => m.AssignmentPollSlideModule), + loadChildren: () => + import('./assignments/assignment-poll/assignment-poll-slide.module').then(m => m.AssignmentPollSlideModule), verboseName: 'Assignment Poll', elementIdentifiers: ['name', 'id'], canBeMappedToModel: true diff --git a/client/src/assets/styles/poll-colors.scss b/client/src/assets/styles/poll-colors.scss index 068ffee95..c5df5bc8c 100644 --- a/client/src/assets/styles/poll-colors.scss +++ b/client/src/assets/styles/poll-colors.scss @@ -5,6 +5,6 @@ $votes-yes-color: #4caf50; $votes-no-color: #cc6c5b; $votes-abstain-color: #a6a6a6; $vote-active-color: white; -$poll-create-color: #4caf50; +$poll-start-color: #4caf50; $poll-stop-color: #ff5252; $poll-publish-color: #e6b100; diff --git a/client/src/assets/styles/poll-styles-common.scss b/client/src/assets/styles/poll-styles-common.scss new file mode 100644 index 000000000..7612dfb4a --- /dev/null +++ b/client/src/assets/styles/poll-styles-common.scss @@ -0,0 +1,40 @@ +@import '~assets/styles/poll-colors.scss'; + +.yes { + color: $votes-yes-color; +} + +.no { + color: $votes-no-color; +} + +.abstain { + color: $votes-abstain-color; +} + +.voted-yes { + background-color: $votes-yes-color; + color: $vote-active-color; +} + +.voted-no { + background-color: $votes-no-color; + color: $vote-active-color; +} + +.voted-abstain { + background-color: $votes-abstain-color; + color: $vote-active-color; +} + +.start-poll-button { + color: $poll-start-color; +} + +.stop-poll-button { + color: $poll-stop-color; +} + +.publish-poll-button { + color: $poll-publish-color; +} diff --git a/openslides/assignments/config_variables.py b/openslides/assignments/config_variables.py index dbbf14601..92ed8149c 100644 --- a/openslides/assignments/config_variables.py +++ b/openslides/assignments/config_variables.py @@ -65,12 +65,22 @@ def get_config_variables(): subgroup="Ballot", ) + yield ConfigVariable( + name="assignment_poll_sort_poll_result_by_votes", + default_value=True, + input_type="boolean", + label="Sort election results by amount of votes", + weight=420, + group="Elections", + subgroup="Ballot", + ) + yield ConfigVariable( name="assignment_poll_add_candidates_to_list_of_speakers", default_value=True, input_type="boolean", label="Put all candidates on the list of speakers", - weight=420, + weight=425, group="Elections", subgroup="Ballot", )