diff --git a/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.html b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.html new file mode 100644 index 000000000..d044b69dc --- /dev/null +++ b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.html @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + +
Candidates + + Yes + + + Votes + + NoAbstain
+
+ + {{ row.votingOption | pollKeyVerbose | translate }} + + +
+ {{ row.votingOptionSubtitle }} +
+
+
+
+ + + {{ vote.amount | pollPercentBase: poll }} + + {{ vote.amount | parsePollNumber }} + +
+
+
diff --git a/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.scss b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.scss new file mode 100644 index 000000000..62680fbc6 --- /dev/null +++ b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.scss @@ -0,0 +1,49 @@ +@import '~assets/styles/poll-styles-common.scss'; + +.assignment-result-table { + margin-top: 2em; + display: block; + overflow-x: auto; + border-collapse: collapse; + + th { + font-weight: initial; + } + + tr { + height: 48px; + + td:first-child { + padding-right: 1em; + } + } + + tr.sums { + border-bottom: none; + td { + padding-top: 1em; + padding-bottom: 1em; + } + } + + .result { + text-align: right; + padding-left: 1em; + } + + .voting-option { + min-width: 200px; + width: 100%; + text-align: left; + } + + .user + .sums { + td { + padding-top: 2em; + } + } + + .single-result { + white-space: pre; + } +} diff --git a/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.spec.ts b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.spec.ts new file mode 100644 index 000000000..0dca52ab3 --- /dev/null +++ b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2EImportsModule } from 'e2e-imports.module'; + +import { AssignmentPollDetailContentComponent } from './assignment-poll-detail-content.component'; + +describe('AssignmentPollDetailContentComponent', () => { + let component: AssignmentPollDetailContentComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AssignmentPollDetailContentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.ts b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.ts new file mode 100644 index 000000000..d4ccb5677 --- /dev/null +++ b/client/src/app/shared/components/assignment-poll-detail-content/assignment-poll-detail-content.component.ts @@ -0,0 +1,55 @@ +import { Component, Input } from '@angular/core'; + +import { AssignmentPollMethod } from 'app/shared/models/assignments/assignment-poll'; +import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll'; +import { AssignmentPollService } from 'app/site/assignments/services/assignment-poll.service'; +import { PollData, PollTableData, VotingResult } from 'app/site/polls/services/poll.service'; + +@Component({ + selector: 'os-assignment-poll-detail-content', + templateUrl: './assignment-poll-detail-content.component.html', + styleUrls: ['./assignment-poll-detail-content.component.scss'] +}) +export class AssignmentPollDetailContentComponent { + @Input() + public poll: ViewAssignmentPoll | PollData; + + public constructor(private pollService: AssignmentPollService) {} + + private get method(): string { + return this.poll.pollmethod; + } + + public get isMethodY(): boolean { + return this.method === AssignmentPollMethod.Votes; + } + + public get isMethodYN(): boolean { + return this.method === AssignmentPollMethod.YN; + } + + public get isMethodYNA(): boolean { + return this.method === AssignmentPollMethod.YNA; + } + + public get tableData(): PollTableData[] { + return this.pollService.generateTableData(this.poll); + } + + public getVoteClass(votingResult: VotingResult): string { + return votingResult.vote; + } + + public voteFitsMethod(result: VotingResult): boolean { + if (this.isMethodY) { + if (result.vote === 'abstain' || result.vote === 'no') { + return false; + } + } else if (this.isMethodYN) { + if (result.vote === 'abstain') { + return false; + } + } + return true; + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index e0b01e055..5410a0328 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -123,6 +123,7 @@ 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'; import { MotionPollDetailContentComponent } from './components/motion-poll-detail-content/motion-poll-detail-content.component'; +import { AssignmentPollDetailContentComponent } from './components/assignment-poll-detail-content/assignment-poll-detail-content.component'; /** * Share Module for all "dumb" components and pipes. @@ -288,7 +289,8 @@ import { MotionPollDetailContentComponent } from './components/motion-poll-detai PollKeyVerbosePipe, PollPercentBasePipe, VotingPrivacyWarningComponent, - MotionPollDetailContentComponent + MotionPollDetailContentComponent, + AssignmentPollDetailContentComponent ], declarations: [ PermsDirective, @@ -347,7 +349,8 @@ import { MotionPollDetailContentComponent } from './components/motion-poll-detai PollKeyVerbosePipe, PollPercentBasePipe, VotingPrivacyWarningComponent, - MotionPollDetailContentComponent + MotionPollDetailContentComponent, + AssignmentPollDetailContentComponent ], providers: [ { 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 b7bf7662a..beb94f624 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 @@ -28,54 +28,9 @@ -
+
-
- - - - - - - - - - - - - -
Candidates - - Yes - - - Votes - - NoAbstain
-
- - {{ row.votingOption | pollKeyVerbose | translate }} - - -
- {{ row.votingOptionSubtitle }} -
-
-
-
- - - {{ vote.amount | pollPercentBase: poll }} - - {{ vote.amount | parsePollNumber }} - -
-
-
+
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 df8b0a1ed..12a0f856a 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,55 +1,4 @@ -@import '~assets/styles/poll-colors.scss'; -@import '~assets/styles/poll-styles-common.scss'; - .assignment-result-wrapper { - .assignment-result-table { - margin-top: 2em; - display: block; - overflow-x: auto; - border-collapse: collapse; - - th { - font-weight: initial; - } - - tr { - height: 48px; - - td:first-child { - padding-right: 1em; - } - } - - tr.sums { - border-bottom: none; - td { - padding-top: 1em; - padding-bottom: 1em; - } - } - - .result { - text-align: right; - padding-left: 1em; - } - - .voting-option { - min-width: 200px; - width: 100%; - text-align: left; - } - - .user + .sums { - td { - padding-top: 2em; - } - } - - .single-result { - white-space: pre; - } - } - .chart-wrapper { margin-top: 2em; .pie-chart { 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 c230f51f7..e1d4d1c3a 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 @@ -13,7 +13,6 @@ import { GroupRepositoryService } from 'app/core/repositories/users/group-reposi import { PromptService } from 'app/core/ui-services/prompt.service'; import { VoteValue } from 'app/shared/models/poll/base-vote'; import { BasePollDetailComponent } from 'app/site/polls/components/base-poll-detail.component'; -import { PollTableData, VotingResult } from 'app/site/polls/services/poll.service'; import { AssignmentPollDialogService } from '../../services/assignment-poll-dialog.service'; import { AssignmentPollService } from '../../services/assignment-poll.service'; import { ViewAssignmentPoll } from '../../models/view-assignment-poll'; @@ -121,27 +120,6 @@ export class AssignmentPollDetailComponent extends BasePollDetailComponent { if (this.sortByVote) { return b.yes - a.yes; } else { - return b.weight - a.weight; + // PollData does not have weight, we need to rely on the order of things. + if (a.weight && b.weight) { + 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) - ) - })); + .map((candidate: ViewAssignmentOption) => { + const pollTableEntry: PollTableData = { + 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) + ) + }; + + // Since pollData does not have any subtitle option + if (candidate instanceof ViewAssignmentOption) { + pollTableEntry.votingOption = candidate.user.short_name; + pollTableEntry.votingOptionSubtitle = candidate.user.getLevelAndNumber(); + } else { + pollTableEntry.votingOption = (candidate as PollDataOption).user.short_name; + } + + return pollTableEntry; + }); 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/polls/services/poll.service.ts b/client/src/app/site/polls/services/poll.service.ts index 5b36cace5..7484daf85 100644 --- a/client/src/app/site/polls/services/poll.service.ts +++ b/client/src/app/site/polls/services/poll.service.ts @@ -105,17 +105,22 @@ export interface PollData { pollmethod: string; type: string; onehundred_percent_base: string; - options: { - user?: { - short_name: string; - }; - yes?: number; - no?: number; - abstain?: number; - }[]; + options: PollDataOption[]; votesvalid: number; votesinvalid: number; votescast: number; + amount_global_no?: number; + amount_global_abstain?: number; +} + +export interface PollDataOption { + user?: { + short_name?: string; + }; + yes?: number; + no?: number; + abstain?: number; + weight?: number; } interface OpenSlidesSettings { @@ -126,7 +131,7 @@ interface OpenSlidesSettings { * Interface describes the possible data for the result-table. */ export interface PollTableData { - votingOption: string; + votingOption?: string; votingOptionSubtitle?: string; class?: string; value: VotingResult[]; diff --git a/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.html b/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.html index 46ee04518..e75c7a0a0 100644 --- a/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.html +++ b/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.html @@ -3,11 +3,7 @@

{{ data.data.assignment.title }}

{{ data.data.poll.title }}

-
- +
+
diff --git a/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.scss b/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.scss index 94c5fff87..7539039e2 100644 --- a/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.scss +++ b/client/src/app/slides/assignments/assignment-poll/assignment-poll-slide.component.scss @@ -5,7 +5,3 @@ .slidetitle { margin-bottom: 15px; } - -.charts-wrapper { - position: relative; -} diff --git a/openslides/assignments/projector.py b/openslides/assignments/projector.py index 413e22abc..243cb9348 100644 --- a/openslides/assignments/projector.py +++ b/openslides/assignments/projector.py @@ -63,7 +63,7 @@ async def assignment_poll_slide( options = get_models(all_data, "assignments/assignment-option", poll["options_id"]) for option in sorted(options, key=lambda option: option["weight"]): option_data: Dict[str, Any] = { - "user": {"full_name": await get_user_name(all_data, option["user_id"])} + "user": {"short_name": await get_user_name(all_data, option["user_id"])} } if poll["state"] == AssignmentPoll.STATE_PUBLISHED: option_data["yes"] = float(option["yes"]) diff --git a/requirements/production.txt b/requirements/production.txt index 58beedfb2..29773a280 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -16,3 +16,4 @@ roman>=2.0,<3.2 setuptools>=29.0,<42.0 typing_extensions>=3.6.6,<3.8 websockets>=8.0,<9.0 +twisted>=19.0,<20.0 \ No newline at end of file