Refactor usage of PollService

prevents the direct use of the abstract
"PollService".
This commit is contained in:
Sean 2020-03-17 18:21:13 +01:00
parent 58483d7024
commit 0ab4532ac8
19 changed files with 82 additions and 45 deletions

View File

@ -8,6 +8,7 @@ import { PollState, PollType } from 'app/shared/models/poll/base-poll';
import { mediumDialogSettings } from 'app/shared/utils/dialog-settings';
import { BasePollDialogComponent } from 'app/site/polls/components/base-poll-dialog.component';
import { ViewBasePoll } from 'app/site/polls/models/view-base-poll';
import { PollService } from 'app/site/polls/services/poll.service';
/**
* Abstract class for showing a poll dialog. Has to be subclassed to provide the right `PollService`
@ -15,8 +16,8 @@ import { ViewBasePoll } from 'app/site/polls/models/view-base-poll';
@Injectable({
providedIn: 'root'
})
export abstract class BasePollDialogService<V extends ViewBasePoll> {
protected dialogComponent: ComponentType<BasePollDialogComponent<V>>;
export abstract class BasePollDialogService<V extends ViewBasePoll, S extends PollService> {
protected dialogComponent: ComponentType<BasePollDialogComponent<V, S>>;
public constructor(private dialog: MatDialog, private mapper: CollectionStringMapperService) {}

View File

@ -1,5 +1,6 @@
<os-poll-form
[data]="pollData"
[pollService]="assignmentPollService"
[pollMethods]="AssignmentPollMethodVerbose"
[percentBases]="AssignmentPollPercentBaseVerbose"
#pollForm

View File

@ -17,6 +17,7 @@ import {
import { BasePollDialogComponent } from 'app/site/polls/components/base-poll-dialog.component';
import { PollFormComponent } from 'app/site/polls/components/poll-form/poll-form.component';
import { ViewUser } from 'app/site/users/models/view-user';
import { AssignmentPollService } from '../../services/assignment-poll.service';
import { ViewAssignmentPoll } from '../../models/view-assignment-poll';
type OptionsObject = { user_id: number; user: ViewUser }[];
@ -29,7 +30,8 @@ type OptionsObject = { user_id: number; user: ViewUser }[];
templateUrl: './assignment-poll-dialog.component.html',
styleUrls: ['./assignment-poll-dialog.component.scss']
})
export class AssignmentPollDialogComponent extends BasePollDialogComponent<ViewAssignmentPoll> implements OnInit {
export class AssignmentPollDialogComponent extends BasePollDialogComponent<ViewAssignmentPoll, AssignmentPollService>
implements OnInit {
/**
* The summary values that will have fields in the dialog
*/
@ -44,7 +46,7 @@ export class AssignmentPollDialogComponent extends BasePollDialogComponent<ViewA
public specialValues: [number, string][];
@ViewChild('pollForm', { static: true })
protected pollForm: PollFormComponent<ViewAssignmentPoll>;
protected pollForm: PollFormComponent<ViewAssignmentPoll, AssignmentPollService>;
/**
* vote entries for each option in this component. Is empty if method
@ -80,7 +82,8 @@ export class AssignmentPollDialogComponent extends BasePollDialogComponent<ViewA
title: Title,
protected translate: TranslateService,
matSnackbar: MatSnackBar,
public dialogRef: MatDialogRef<BasePollDialogComponent<ViewAssignmentPoll>>,
public dialogRef: MatDialogRef<BasePollDialogComponent<ViewAssignmentPoll, AssignmentPollService>>,
public assignmentPollService: AssignmentPollService,
@Inject(MAT_DIALOG_DATA) public pollData: Partial<ViewAssignmentPoll>
) {
super(title, translate, matSnackbar, dialogRef);

View File

@ -25,7 +25,8 @@ import { ViewAssignmentPoll } from '../../models/view-assignment-poll';
templateUrl: './assignment-poll.component.html',
styleUrls: ['./assignment-poll.component.scss']
})
export class AssignmentPollComponent extends BasePollComponent<ViewAssignmentPoll> implements OnInit {
export class AssignmentPollComponent extends BasePollComponent<ViewAssignmentPoll, AssignmentPollService>
implements OnInit {
@Input()
public set poll(value: ViewAssignmentPoll) {
this.initPoll(value);

View File

@ -4,6 +4,7 @@ import { MatDialog } from '@angular/material';
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
import { BasePollDialogService } from 'app/core/ui-services/base-poll-dialog.service';
import { AssignmentPollDialogComponent } from 'app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component';
import { AssignmentPollService } from './assignment-poll.service';
import { ViewAssignmentPoll } from '../models/view-assignment-poll';
/**
@ -12,7 +13,7 @@ import { ViewAssignmentPoll } from '../models/view-assignment-poll';
@Injectable({
providedIn: 'root'
})
export class AssignmentPollDialogService extends BasePollDialogService<ViewAssignmentPoll> {
export class AssignmentPollDialogService extends BasePollDialogService<ViewAssignmentPoll, AssignmentPollService> {
protected dialogComponent = AssignmentPollDialogComponent;
public constructor(dialog: MatDialog, mapper: CollectionStringMapperService) {

View File

@ -1,4 +1,9 @@
<os-poll-form [data]="pollData" [percentBases]="PercentBaseVerbose" #pollForm></os-poll-form>
<os-poll-form
[data]="pollData"
[pollService]="motionPollService"
[percentBases]="PercentBaseVerbose"
#pollForm
></os-poll-form>
<ng-container *ngIf="pollForm.contentForm.get('type').value === 'analog'">
<div class="os-form-card-mobile" mat-dialog-content>
<form [formGroup]="dialogVoteForm">

View File

@ -7,6 +7,7 @@ import { TranslateService } from '@ngx-translate/core';
import { LOWEST_VOTE_VALUE } from 'app/shared/models/poll/base-poll';
import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll';
import { MotionPollService } from 'app/site/motions/services/motion-poll.service';
import { BasePollDialogComponent } from 'app/site/polls/components/base-poll-dialog.component';
import { PollFormComponent } from 'app/site/polls/components/poll-form/poll-form.component';
import { PercentBaseVerbose } from 'app/site/polls/models/view-base-poll';
@ -16,17 +17,19 @@ import { PercentBaseVerbose } from 'app/site/polls/models/view-base-poll';
templateUrl: './motion-poll-dialog.component.html',
styleUrls: ['./motion-poll-dialog.component.scss']
})
export class MotionPollDialogComponent extends BasePollDialogComponent<ViewMotionPoll> implements OnInit {
export class MotionPollDialogComponent extends BasePollDialogComponent<ViewMotionPoll, MotionPollService>
implements OnInit {
public PercentBaseVerbose = PercentBaseVerbose;
@ViewChild('pollForm', { static: false })
protected pollForm: PollFormComponent<ViewMotionPoll>;
protected pollForm: PollFormComponent<ViewMotionPoll, MotionPollService>;
public constructor(
title: Title,
translate: TranslateService,
matSnackbar: MatSnackBar,
public dialogRef: MatDialogRef<BasePollDialogComponent<ViewMotionPoll>>,
public motionPollService: MotionPollService,
public dialogRef: MatDialogRef<BasePollDialogComponent<ViewMotionPoll, MotionPollService>>,
private formBuilder: FormBuilder,
@Inject(MAT_DIALOG_DATA) public pollData: Partial<ViewMotionPoll>
) {

View File

@ -14,7 +14,7 @@ import { MotionPollDialogService } from 'app/site/motions/services/motion-poll-d
import { MotionPollPdfService } from 'app/site/motions/services/motion-poll-pdf.service';
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 { PollTableData } from 'app/site/polls/services/poll.service';
/**
* Component to show a motion-poll.
@ -24,7 +24,7 @@ import { PollService, PollTableData } from 'app/site/polls/services/poll.service
templateUrl: './motion-poll.component.html',
styleUrls: ['./motion-poll.component.scss']
})
export class MotionPollComponent extends BasePollComponent<ViewMotionPoll> {
export class MotionPollComponent extends BasePollComponent<ViewMotionPoll, MotionPollService> {
@Input()
public set poll(value: ViewMotionPoll) {
this.initPoll(value);
@ -41,11 +41,11 @@ export class MotionPollComponent extends BasePollComponent<ViewMotionPoll> {
}
public get showChart(): boolean {
return this.motionPollService.showChart(this.poll);
return this.pollService.showChart(this.poll);
}
public get reducedPollTableData(): PollTableData[] {
return this.motionPollService
return this.pollService
.generateTableData(this.poll)
.filter(data => ['yes', 'no', 'abstain', 'votesinvalid'].includes(data.votingOption));
}
@ -63,6 +63,10 @@ export class MotionPollComponent extends BasePollComponent<ViewMotionPoll> {
return false;
}
public get isEVotingEnabled(): boolean {
return this.pollService.isElectronicVotingEnabled;
}
/**
* Constructor.
*
@ -75,14 +79,13 @@ export class MotionPollComponent extends BasePollComponent<ViewMotionPoll> {
public constructor(
titleService: Title,
matSnackBar: MatSnackBar,
protected translate: TranslateService,
dialog: MatDialog,
promptService: PromptService,
public pollRepo: MotionPollRepositoryService,
pollDialog: MotionPollDialogService,
public pollService: PollService,
protected dialog: MatDialog,
protected pollRepo: MotionPollRepositoryService,
protected translate: TranslateService,
private pollService: MotionPollService,
private pdfService: MotionPollPdfService,
private motionPollService: MotionPollService,
private operator: OperatorService
) {
super(titleService, matSnackBar, translate, dialog, promptService, pollRepo, pollDialog);

View File

@ -4,6 +4,7 @@ import { MatDialog } from '@angular/material';
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
import { BasePollDialogService } from 'app/core/ui-services/base-poll-dialog.service';
import { MotionPollDialogComponent } from 'app/site/motions/modules/motion-poll/motion-poll-dialog/motion-poll-dialog.component';
import { MotionPollService } from './motion-poll.service';
import { ViewMotionPoll } from '../models/view-motion-poll';
/**
@ -12,7 +13,7 @@ import { ViewMotionPoll } from '../models/view-motion-poll';
@Injectable({
providedIn: 'root'
})
export class MotionPollDialogService extends BasePollDialogService<ViewMotionPoll> {
export class MotionPollDialogService extends BasePollDialogService<ViewMotionPoll, MotionPollService> {
protected dialogComponent = MotionPollDialogComponent;
public constructor(dialog: MatDialog, mapper: CollectionStringMapperService) {

View File

@ -100,7 +100,7 @@ export abstract class BasePollDetailComponent<V extends ViewBasePoll, S extends
protected route: ActivatedRoute,
protected groupRepo: GroupRepositoryService,
protected promptService: PromptService,
protected pollDialog: BasePollDialogService<V>,
protected pollDialog: BasePollDialogService<V, S>,
protected pollService: S,
protected votesRepo: BaseRepository<ViewBaseVote, BaseVote, object>
) {

View File

@ -10,15 +10,17 @@ import { VOTE_UNDOCUMENTED } from 'app/shared/models/poll/base-poll';
import { OneOfValidator } from 'app/shared/validators/one-of-validator';
import { BaseViewComponent } from 'app/site/base/base-view';
import { PollFormComponent } from './poll-form/poll-form.component';
import { PollService } from '../services/poll.service';
import { ViewBasePoll } from '../models/view-base-poll';
/**
* A dialog for updating the values of a poll.
*/
export abstract class BasePollDialogComponent<T extends ViewBasePoll> extends BaseViewComponent implements OnInit {
export abstract class BasePollDialogComponent<T extends ViewBasePoll, S extends PollService> extends BaseViewComponent
implements OnInit {
public publishImmediately: boolean;
protected pollForm: PollFormComponent<T>;
protected pollForm: PollFormComponent<T, S>;
public dialogVoteForm: FormGroup;
@ -26,7 +28,7 @@ export abstract class BasePollDialogComponent<T extends ViewBasePoll> extends Ba
title: Title,
protected translate: TranslateService,
matSnackbar: MatSnackBar,
public dialogRef: MatDialogRef<BasePollDialogComponent<T>>
public dialogRef: MatDialogRef<BasePollDialogComponent<T, S>>
) {
super(title, translate, matSnackbar);
}

View File

@ -11,9 +11,10 @@ import { ChartData } from 'app/shared/components/charts/charts.component';
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 { PollService } from '../services/poll.service';
import { ViewBasePoll } from '../models/view-base-poll';
export abstract class BasePollComponent<V extends ViewBasePoll> extends BaseViewComponent {
export abstract class BasePollComponent<V extends ViewBasePoll, S extends PollService> extends BaseViewComponent {
public chartDataSubject: BehaviorSubject<ChartData> = new BehaviorSubject([]);
protected _poll: V;
@ -41,10 +42,10 @@ export abstract class BasePollComponent<V extends ViewBasePoll> extends BaseView
titleService: Title,
matSnackBar: MatSnackBar,
protected translate: TranslateService,
public dialog: MatDialog,
protected dialog: MatDialog,
protected promptService: PromptService,
protected repo: BasePollRepositoryService,
protected pollDialog: BasePollDialogService<V>
protected pollDialog: BasePollDialogService<V, S>
) {
super(titleService, translate, matSnackBar);
}

View File

@ -22,14 +22,16 @@
<form [formGroup]="contentForm" class="poll-preview-meta-info-form">
<ng-container *ngIf="!data || !data.state || data.isCreated">
<!-- Poll Type -->
<mat-form-field class="pollType" *ngIf="pollService.isElectronicVotingEnabled">
<mat-form-field class="pollType" *ngIf="isEVotingEnabled">
<mat-select [placeholder]="PollPropertyVerbose.type | translate" formControlName="type" required>
<mat-option *ngFor="let option of pollTypes | keyvalue" [value]="option.key">
{{ option.value | translate }}
</mat-option>
</mat-select>
<mat-error translate>This field is required.</mat-error>
<mat-hint (click)="openVotingWarning()" *ngIf="showNonNominalWarning"> {{ 'Not suitable for formal secret voting!' | translate }}</mat-hint>
<mat-hint (click)="openVotingWarning()" *ngIf="showNonNominalWarning">
{{ 'Not suitable for formal secret voting!' | translate }}</mat-hint
>
</mat-form-field>
<!-- Groups entitled to Vote -->
@ -84,7 +86,6 @@
formControlName="votes_amount"
min="1"
required
/>
</mat-form-field>
<mat-checkbox formControlName="global_no">{{ PollPropertyVerbose.global_no | translate }}</mat-checkbox>

View File

@ -5,8 +5,8 @@ import { E2EImportsModule } from 'e2e-imports.module';
import { PollFormComponent } from './poll-form.component';
describe('PollFormComponent', () => {
let component: PollFormComponent<any>;
let fixture: ComponentFixture<PollFormComponent<any>>;
let component: PollFormComponent<any, any>;
let fixture: ComponentFixture<PollFormComponent<any, any>>;
beforeEach(async(() => {
TestBed.configureTestingModule({

View File

@ -30,7 +30,8 @@ import { PollService } from '../../services/poll.service';
templateUrl: './poll-form.component.html',
styleUrls: ['./poll-form.component.scss']
})
export class PollFormComponent<T extends ViewBasePoll> extends BaseViewComponent implements OnInit {
export class PollFormComponent<T extends ViewBasePoll, S extends PollService> extends BaseViewComponent
implements OnInit {
/**
* The form-group for the meta-info.
*/
@ -54,6 +55,9 @@ export class PollFormComponent<T extends ViewBasePoll> extends BaseViewComponent
@Input()
public data: Partial<T>;
@Input()
private pollService: S;
/**
* The different types the poll can accept.
*/
@ -87,6 +91,14 @@ export class PollFormComponent<T extends ViewBasePoll> extends BaseViewComponent
public showNonNominalWarning = false;
public get isEVotingEnabled(): boolean {
if (this.pollService) {
return this.pollService.isElectronicVotingEnabled;
} else {
return false;
}
}
/**
* Constructor. Retrieves necessary metadata from the pollService,
* injects the poll itself
@ -97,7 +109,6 @@ export class PollFormComponent<T extends ViewBasePoll> extends BaseViewComponent
snackbar: MatSnackBar,
private fb: FormBuilder,
private groupRepo: GroupRepositoryService,
public pollService: PollService,
private configService: ConfigService,
private dialog: MatDialog
) {

View File

@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { PollState } from 'app/shared/models/poll/base-poll';
import { AssignmentPollService } from 'app/site/assignments/services/assignment-poll.service';
import { BasePollSlideComponent } from 'app/slides/polls/base-poll-slide.component';
import { AssignmentPollSlideData } from './assignment-poll-slide-data';
@ -9,7 +10,10 @@ import { AssignmentPollSlideData } from './assignment-poll-slide-data';
templateUrl: './assignment-poll-slide.component.html',
styleUrls: ['./assignment-poll-slide.component.scss']
})
export class AssignmentPollSlideComponent extends BasePollSlideComponent<AssignmentPollSlideData> {
export class AssignmentPollSlideComponent extends BasePollSlideComponent<
AssignmentPollSlideData,
AssignmentPollService
> {
public PollState = PollState;
public options = { maintainAspectRatio: false, responsive: true, legend: { position: 'right' } };

View File

@ -2,7 +2,7 @@ import { Component } from '@angular/core';
import { PollState } from 'app/shared/models/poll/base-poll';
import { MotionPollService } from 'app/site/motions/services/motion-poll.service';
import { PollData, PollService, PollTableData } from 'app/site/polls/services/poll.service';
import { PollData, PollTableData } from 'app/site/polls/services/poll.service';
import { BasePollSlideComponent } from 'app/slides/polls/base-poll-slide.component';
import { MotionPollSlideData } from './motion-poll-slide-data';
@ -11,7 +11,7 @@ import { MotionPollSlideData } from './motion-poll-slide-data';
templateUrl: './motion-poll-slide.component.html',
styleUrls: ['./motion-poll-slide.component.scss']
})
export class MotionPollSlideComponent extends BasePollSlideComponent<MotionPollSlideData> {
export class MotionPollSlideComponent extends BasePollSlideComponent<MotionPollSlideData, MotionPollService> {
public PollState = PollState;
public pollData: PollData;
@ -19,7 +19,7 @@ export class MotionPollSlideComponent extends BasePollSlideComponent<MotionPollS
public voteNo: number;
public voteAbstain: number;
public constructor(pollService: PollService, private motionPollService: MotionPollService) {
public constructor(pollService: MotionPollService) {
super(pollService);
this.chartDataSubject.subscribe(() => {
if (this.data && this.data.data) {
@ -33,10 +33,10 @@ export class MotionPollSlideComponent extends BasePollSlideComponent<MotionPollS
}
public showChart(): boolean {
return this.motionPollService.showChart(this.pollData);
return this.pollService.showChart(this.pollData);
}
public getTableData(): PollTableData[] {
return this.motionPollService.generateTableData(this.pollData);
return this.pollService.generateTableData(this.pollData);
}
}

View File

@ -9,7 +9,7 @@ import { PollService } from 'app/site/polls/services/poll.service';
import { BasePollSlideData } from './base-poll-slide-data';
import { BaseSlideComponent } from '../base-slide-component';
export class BasePollSlideComponent<T extends BasePollSlideData> extends BaseSlideComponent<T> {
export class BasePollSlideComponent<T extends BasePollSlideData, S extends PollService> extends BaseSlideComponent<T> {
public chartDataSubject: BehaviorSubject<ChartData> = new BehaviorSubject([]);
@Input()
@ -29,7 +29,7 @@ export class BasePollSlideComponent<T extends BasePollSlideData> extends BaseSli
public constructor(
@Inject(forwardRef(() => PollService))
public pollService: PollService
public pollService: S
) {
super();
}

View File

@ -76,11 +76,10 @@ export class SlideManager {
}
/**
* Asynchronically load the slide's component factory, which is used to create
* Asynchronously load the slide's component factory, which is used to create
* the slide component.
*
* @param slideName The slide to search.
* @deprecated NgModuleFactoryLoader is deprecated and should be removed before version 9
*/
public async getSlideFactory<T extends BaseSlideComponent<object>>(
slideName: string