Add poll meta info component

Adds a component to display the assignment polls meta info
This commit is contained in:
Sean 2020-12-01 13:46:12 +01:00
parent 9ddb3a9179
commit 9c738b5d8e
12 changed files with 158 additions and 36 deletions

View File

@ -67,6 +67,10 @@ export class AssignmentPoll extends BasePoll<
return this.pollmethod === AssignmentPollMethod.YNA; return this.pollmethod === AssignmentPollMethod.YNA;
} }
public get hasGlobalOption(): boolean {
return this.global_yes || this.global_no || this.global_abstain;
}
public get pollmethodFields(): CalculablePollKey[] { public get pollmethodFields(): CalculablePollKey[] {
if (this.pollmethod === AssignmentPollMethod.YN) { if (this.pollmethod === AssignmentPollMethod.YN) {
return ['yes', 'no']; return ['yes', 'no'];

View File

@ -5,6 +5,7 @@ import { SharedModule } from 'app/shared/shared.module';
import { PollsModule } from 'app/site/polls/polls.module'; import { PollsModule } from 'app/site/polls/polls.module';
import { AssignmentPollDetailComponent } from './components/assignment-poll-detail/assignment-poll-detail.component'; import { AssignmentPollDetailComponent } from './components/assignment-poll-detail/assignment-poll-detail.component';
import { AssignmentPollDialogComponent } from './components/assignment-poll-dialog/assignment-poll-dialog.component'; import { AssignmentPollDialogComponent } from './components/assignment-poll-dialog/assignment-poll-dialog.component';
import { AssignmentPollMetaInfoComponent } from './components/assignment-poll-meta-info/assignment-poll-meta-info.component';
import { AssignmentPollRoutingModule } from './assignment-poll-routing.module'; import { AssignmentPollRoutingModule } from './assignment-poll-routing.module';
import { AssignmentPollVoteComponent } from './components/assignment-poll-vote/assignment-poll-vote.component'; import { AssignmentPollVoteComponent } from './components/assignment-poll-vote/assignment-poll-vote.component';
import { AssignmentPollComponent } from './components/assignment-poll/assignment-poll.component'; import { AssignmentPollComponent } from './components/assignment-poll/assignment-poll.component';
@ -14,7 +15,8 @@ import { AssignmentPollComponent } from './components/assignment-poll/assignment
AssignmentPollComponent, AssignmentPollComponent,
AssignmentPollDetailComponent, AssignmentPollDetailComponent,
AssignmentPollVoteComponent, AssignmentPollVoteComponent,
AssignmentPollDialogComponent AssignmentPollDialogComponent,
AssignmentPollMetaInfoComponent
], ],
exports: [AssignmentPollComponent, AssignmentPollVoteComponent], exports: [AssignmentPollComponent, AssignmentPollVoteComponent],
imports: [CommonModule, AssignmentPollRoutingModule, SharedModule, PollsModule] imports: [CommonModule, AssignmentPollRoutingModule, SharedModule, PollsModule]

View File

@ -102,19 +102,7 @@
</div> </div>
<!-- Meta Infos --> <!-- Meta Infos -->
<div *ngIf="poll" class="assignment-poll-meta"> <os-assignment-poll-meta-info [poll]="poll" [showCandidates]="showCandidatesInMetaInfo"></os-assignment-poll-meta-info>
<small *ngIf="poll.groups && poll.type && poll.type !== 'analog'">
{{ 'Groups' | translate }}:
<span *ngFor="let group of poll.groups; let i = index">
{{ group.getTitle() | translate }}<span *ngIf="i < poll.groups.length - 1">, </span>
</span>
</small>
<small *ngIf="poll.onehundred_percent_base">
{{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }}
</small>
</div>
</ng-template> </ng-template>
<!-- More Menu --> <!-- More Menu -->

View File

@ -30,12 +30,6 @@
} }
} }
.assignment-poll-meta {
display: grid;
text-align: right;
padding-top: 20px;
}
.openslides-theme .pbl-ngrid-no-data { .openslides-theme .pbl-ngrid-no-data {
top: 10%; top: 10%;
} }

View File

@ -0,0 +1,44 @@
<ng-container *ngIf="poll">
<!-- Candidates -->
<small class="meta-info-left subtitle" *ngIf="poll.options?.length && showCandidates">
<div>
{{ 'Candidates' | translate }}:
<ol>
<li *ngFor="let option of poll.options">{{ getOptionTitle(option) | translate }}</li>
</ol>
</div>
<div *ngIf="hasGlobalOption">
{{ 'Options' | translate }}:
<ul>
<li *ngIf="poll.global_yes">{{ pollPropertyVerbose.global_yes | translate }}</li>
<li *ngIf="poll.global_no">{{ pollPropertyVerbose.global_no | translate }}</li>
<li *ngIf="poll.global_abstain">{{ pollPropertyVerbose.global_abstain | translate }}</li>
</ul>
</div>
</small>
<div class="meta-info-right subtitle">
<!-- Groups who can vote -->
<small *ngIf="poll.groups && poll.type && poll.type !== 'analog'">
{{ 'Entitled to vote' | translate }}:
<span *ngFor="let group of poll.groups; let i = index">
{{ group.getTitle() | translate }}<span *ngIf="i < poll.groups.length - 1">, </span>
</span>
<br />
</small>
<!-- Voting method -->
<small *ngIf="poll.pollmethod">
<span> {{ 'Voting method' | translate }}: {{ poll.pollmethodVerbose | translate }} </span>
<!-- amount of votes -->
<span *ngIf="poll.votes_amount > 1"> ({{ poll.votes_amount }} {{ 'Votes' | translate }})</span>
<br />
</small>
<!-- 100% base -->
<small *ngIf="poll.onehundred_percent_base">
{{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }}
</small>
</div>
</ng-container>

View File

@ -0,0 +1,23 @@
:host {
width: 100%;
padding-top: 20px;
display: grid;
grid-template-columns: 2fr auto;
}
.meta-info-left {
ul,
ol {
margin: 0;
padding-left: 2em;
}
div + div {
margin-top: 1em;
}
}
.meta-info-right {
text-align: right;
align-self: flex-end;
}

View File

@ -0,0 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { E2EImportsModule } from 'e2e-imports.module';
import { AssignmentPollMetaInfoComponent } from './assignment-poll-meta-info.component';
describe('AssignmentPollMetaInfoComponent', () => {
let component: AssignmentPollMetaInfoComponent;
let fixture: ComponentFixture<AssignmentPollMetaInfoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [E2EImportsModule],
declarations: [AssignmentPollMetaInfoComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AssignmentPollMetaInfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,37 @@
import { Component, Input } from '@angular/core';
import { ViewAssignmentOption } from 'app/site/assignments/models/view-assignment-option';
import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll';
import { UnknownUserLabel } from 'app/site/assignments/modules/assignment-poll/services/assignment-poll.service';
import { PollPropertyVerbose } from 'app/site/polls/models/view-base-poll';
@Component({
selector: 'os-assignment-poll-meta-info',
templateUrl: './assignment-poll-meta-info.component.html',
styleUrls: ['./assignment-poll-meta-info.component.scss']
})
export class AssignmentPollMetaInfoComponent {
public pollPropertyVerbose = PollPropertyVerbose;
private unknownUserLabel = UnknownUserLabel;
@Input()
public poll: ViewAssignmentPoll;
@Input()
public showCandidates = true;
public get hasGlobalOption(): boolean {
return this.poll.hasGlobalOption;
}
public constructor() {}
public userCanVoe(): boolean {
// this.poll.canBeVotedFor
return true;
}
public getOptionTitle(option: ViewAssignmentOption): string {
return option.user?.getShortName().trim() ?? this.unknownUserLabel;
}
}

View File

@ -74,17 +74,12 @@
<!-- The Vote --> <!-- The Vote -->
<os-assignment-poll-vote *ngIf="poll.canBeVotedFor()" [poll]="poll"></os-assignment-poll-vote> <os-assignment-poll-vote *ngIf="poll.canBeVotedFor()" [poll]="poll"></os-assignment-poll-vote>
<!-- More-Button --> <!-- Meta-Info -->
<div class="poll-detail-button-wrapper"> <os-assignment-poll-meta-info
<a [poll]="poll"
mat-icon-button [showCandidates]="showCandidatesInMetaInfo"
routerLink="/assignments/polls/{{ poll.id }}" *ngIf="showMetaInfo"
matTooltip="{{ 'More' | translate }}" ></os-assignment-poll-meta-info>
*ngIf="poll.isPublished"
>
<mat-icon class="small-icon"> visibility </mat-icon>
</a>
</div>
</div> </div>
</mat-card> </mat-card>

View File

@ -18,8 +18,5 @@
.poll-detail-button-wrapper { .poll-detail-button-wrapper {
display: flex; display: flex;
margin: auto 0; margin: auto 0;
> a {
margin-left: auto;
}
} }
} }

View File

@ -9,6 +9,7 @@ import { TranslateService } from '@ngx-translate/core';
import { OperatorService } from 'app/core/core-services/operator.service'; import { OperatorService } from 'app/core/core-services/operator.service';
import { AssignmentPollRepositoryService } from 'app/core/repositories/assignments/assignment-poll-repository.service'; import { AssignmentPollRepositoryService } from 'app/core/repositories/assignments/assignment-poll-repository.service';
import { PromptService } from 'app/core/ui-services/prompt.service'; import { PromptService } from 'app/core/ui-services/prompt.service';
import { VotingService } from 'app/core/ui-services/voting.service';
import { VotingPrivacyWarningComponent } from 'app/shared/components/voting-privacy-warning/voting-privacy-warning.component'; import { VotingPrivacyWarningComponent } from 'app/shared/components/voting-privacy-warning/voting-privacy-warning.component';
import { infoDialogSettings } from 'app/shared/utils/dialog-settings'; import { infoDialogSettings } from 'app/shared/utils/dialog-settings';
import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll'; import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll';
@ -67,6 +68,14 @@ export class AssignmentPollComponent
return false; return false;
} }
public get showMetaInfo(): boolean {
return !this.poll.stateHasVotes && this.operator.hasPerms(this.permission.assignmentsCanManage);
}
public get showCandidatesInMetaInfo(): boolean {
return !this.poll.stateHasVotes && !this.votingService.canVote(this.poll);
}
public constructor( public constructor(
titleService: Title, titleService: Title,
matSnackBar: MatSnackBar, matSnackBar: MatSnackBar,
@ -78,7 +87,8 @@ export class AssignmentPollComponent
private pollService: AssignmentPollService, private pollService: AssignmentPollService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private pdfService: AssignmentPollPdfService, private pdfService: AssignmentPollPdfService,
private operator: OperatorService private operator: OperatorService,
private votingService: VotingService
) { ) {
super(titleService, matSnackBar, translate, dialog, promptService, repo, pollDialog); super(titleService, matSnackBar, translate, dialog, promptService, repo, pollDialog);
} }

View File

@ -7,9 +7,10 @@ import { CinemaRoutingModule } from './cinema-routing.module';
import { CinemaComponent } from './components/cinema/cinema.component'; import { CinemaComponent } from './components/cinema/cinema.component';
import { MotionPollModule } from '../motions/modules/motion-poll/motion-poll.module'; import { MotionPollModule } from '../motions/modules/motion-poll/motion-poll.module';
import { PollCollectionComponent } from './components/poll-collection/poll-collection.component'; import { PollCollectionComponent } from './components/poll-collection/poll-collection.component';
import { PollsModule } from '../polls/polls.module';
@NgModule({ @NgModule({
imports: [CommonModule, CinemaRoutingModule, MotionPollModule, AssignmentPollModule, SharedModule], imports: [CommonModule, CinemaRoutingModule, MotionPollModule, AssignmentPollModule, SharedModule, PollsModule],
declarations: [CinemaComponent, PollCollectionComponent] declarations: [CinemaComponent, PollCollectionComponent]
}) })
export class CinemaModule {} export class CinemaModule {}