Replaces the mat-table with a classic table

This commit is contained in:
GabrielMeyer 2020-01-31 13:18:07 +01:00 committed by FinnStutzenstein
parent 09b0d19de0
commit 294b75c320
13 changed files with 120 additions and 29 deletions

View File

@ -0,0 +1,8 @@
import { PollKeyVerbosePipe } from './poll-key-verbose.pipe';
describe('PollKeyVerbosePipe', () => {
it('create an instance', () => {
const pipe = new PollKeyVerbosePipe();
expect(pipe).toBeTruthy();
});
});

View File

@ -0,0 +1,24 @@
import { Pipe, PipeTransform } from '@angular/core';
const PollValues = {
votesvalid: 'Valid votes',
votesinvalid: 'Invalid votes',
votescast: 'Total votes cast',
votesno: 'Votes No',
votesabstain: 'Votes abstain',
yes: 'Yes',
no: 'No',
abstain: 'Abstain'
};
/**
* Pipe to transform a key from polls into a speaking word.
*/
@Pipe({
name: 'pollKeyVerbose'
})
export class PollKeyVerbosePipe implements PipeTransform {
public transform(value: string): string {
return PollValues[value];
}
}

View File

@ -121,6 +121,7 @@ import { MotionPollDialogComponent } from 'app/site/motions/modules/motion-poll/
import { AssignmentPollDialogComponent } from 'app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component'; import { AssignmentPollDialogComponent } from 'app/site/assignments/components/assignment-poll-dialog/assignment-poll-dialog.component';
import { ParsePollNumberPipe } from './pipes/parse-poll-number.pipe'; import { ParsePollNumberPipe } from './pipes/parse-poll-number.pipe';
import { ReversePipe } from './pipes/reverse.pipe'; import { ReversePipe } from './pipes/reverse.pipe';
import { PollKeyVerbosePipe } from './pipes/poll-key-verbose.pipe';
/** /**
* Share Module for all "dumb" components and pipes. * Share Module for all "dumb" components and pipes.
@ -283,7 +284,8 @@ import { ReversePipe } from './pipes/reverse.pipe';
MotionPollDialogComponent, MotionPollDialogComponent,
AssignmentPollDialogComponent, AssignmentPollDialogComponent,
ParsePollNumberPipe, ParsePollNumberPipe,
ReversePipe ReversePipe,
PollKeyVerbosePipe
], ],
declarations: [ declarations: [
PermsDirective, PermsDirective,
@ -339,7 +341,8 @@ import { ReversePipe } from './pipes/reverse.pipe';
MotionPollDialogComponent, MotionPollDialogComponent,
AssignmentPollDialogComponent, AssignmentPollDialogComponent,
ParsePollNumberPipe, ParsePollNumberPipe,
ReversePipe ReversePipe,
PollKeyVerbosePipe
], ],
providers: [ providers: [
{ {
@ -357,7 +360,8 @@ import { ReversePipe } from './pipes/reverse.pipe';
TrustPipe, TrustPipe,
LocalizedDatePipe, LocalizedDatePipe,
ParsePollNumberPipe, ParsePollNumberPipe,
ReversePipe ReversePipe,
PollKeyVerbosePipe
], ],
entryComponents: [ entryComponents: [
SortBottomSheetComponent, SortBottomSheetComponent,

View File

@ -5,7 +5,7 @@ import { AssignmentPoll, AssignmentPollMethods } from 'app/shared/models/assignm
import { PollColor } from 'app/shared/models/poll/base-poll'; import { PollColor } from 'app/shared/models/poll/base-poll';
import { BaseViewModel } from 'app/site/base/base-view-model'; import { BaseViewModel } from 'app/site/base/base-view-model';
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
import { ViewBasePoll } from 'app/site/polls/models/view-base-poll'; import { PollData, ViewBasePoll } from 'app/site/polls/models/view-base-poll';
import { ViewAssignment } from './view-assignment'; import { ViewAssignment } from './view-assignment';
import { ViewAssignmentOption } from './view-assignment-option'; import { ViewAssignmentOption } from './view-assignment-option';
@ -74,7 +74,7 @@ export class ViewAssignmentPoll extends ViewBasePoll<AssignmentPoll> implements
return data; return data;
} }
public generateTableData(): {}[] { public generateTableData(): PollData[] {
const data = this.options const data = this.options
.map(candidate => ({ .map(candidate => ({
yes: candidate.yes, yes: candidate.yes,

View File

@ -4,7 +4,7 @@ import { PollColor, PollState } from 'app/shared/models/poll/base-poll';
import { BaseViewModel } from 'app/site/base/base-view-model'; import { BaseViewModel } from 'app/site/base/base-view-model';
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
import { ViewMotionOption } from 'app/site/motions/models/view-motion-option'; import { ViewMotionOption } from 'app/site/motions/models/view-motion-option';
import { ViewBasePoll } from 'app/site/polls/models/view-base-poll'; import { PollData, ViewBasePoll } from 'app/site/polls/models/view-base-poll';
import { ViewMotion } from './view-motion'; import { ViewMotion } from './view-motion';
export interface MotionPollTitleInformation { export interface MotionPollTitleInformation {
@ -37,7 +37,7 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
return this.motion; return this.motion;
} }
public generateTableData(): {}[] { public generateTableData(): PollData[] {
let tableData = this.options.flatMap(vote => this.tableKeys.map(key => ({ key: key, value: vote[key] }))); let tableData = this.options.flatMap(vote => this.tableKeys.map(key => ({ key: key, value: vote[key] })));
tableData.push(...this.voteKeys.map(key => ({ key: key, value: this[key] }))); tableData.push(...this.voteKeys.map(key => ({ key: key, value: this[key] })));
tableData = tableData.map(entry => (entry.value >= 0 ? entry : { key: entry.key, value: null })); tableData = tableData.map(entry => (entry.value >= 0 ? entry : { key: entry.key, value: null }));

View File

@ -36,19 +36,18 @@
></os-charts> ></os-charts>
<!-- result table --> <!-- result table -->
<mat-table class="result-table" [dataSource]="poll.tableData"> <table class="result-table">
<ng-container matColumnDef="key" sticky> <tbody>
<mat-header-cell *matHeaderCellDef></mat-header-cell> <tr>
<mat-cell *matCellDef="let row">{{ row.key }}</mat-cell> <th></th>
</ng-container> <th translate>Votes</th>
<ng-container matColumnDef="value" sticky> </tr>
<mat-header-cell *matHeaderCellDef>Votes</mat-header-cell> <tr *ngFor="let row of poll.tableData">
<mat-cell *matCellDef="let row">{{ row.value }}</mat-cell> <td>{{ row.key | pollKeyVerbose | translate }}</td>
</ng-container> <td class="result-cell-definition">{{ row.value }}</td>
</tr>
<mat-header-row *matHeaderRowDef="columnDefinition"></mat-header-row> </tbody>
<mat-row *matRowDef="let row; columns: columnDefinition"></mat-row> </table>
</mat-table>
<!-- Named table: only show if votes are present --> <!-- Named table: only show if votes are present -->
<div class="named-result-table" *ngIf="poll.type === 'named' && votesDataSource.data"> <div class="named-result-table" *ngIf="poll.type === 'named' && votesDataSource.data">
@ -87,8 +86,6 @@
<div>{{ 'Required majority' | translate }}: {{ poll.majorityMethodVerbose | translate }}</div> <div>{{ 'Required majority' | translate }}: {{ poll.majorityMethodVerbose | translate }}</div>
<div>{{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }}</div> <div>{{ '100% base' | translate }}: {{ poll.percentBaseVerbose | translate }}</div>
</div> </div>
<os-projector-button [object]="poll"></os-projector-button>
</ng-container> </ng-container>
</ng-template> </ng-template>

View File

@ -24,6 +24,23 @@
.result-table { .result-table {
grid-area: results; grid-area: results;
tr {
height: 48px;
min-height: 48px;
th:first-child,
td:first-child {
padding-left: 24px;
}
th:last-child,
td:last-child {
padding-right: 24px;
}
.result-cell-definition {
text-align: center;
}
}
} }
.result-chart { .result-chart {

View File

@ -0,0 +1,12 @@
@import '~@angular/material/theming';
@mixin os-motion-poll-detail-style($theme) {
$background: map-get($theme, background);
.result-table {
border-collapse: collapse;
tr {
border-bottom: 1px solid mat-color($background, focused-button);
}
}
}

View File

@ -46,7 +46,7 @@
</div> </div>
<ng-template #votingResult> <ng-template #votingResult>
<div [routerLink]="pollLink"> <div [routerLink]="pollLink" class="poll-link-wrapper">
<ng-container <ng-container
[ngTemplateOutlet]="poll.hasVotes && poll.stateHasVotes ? viewTemplate : emptyTemplate" [ngTemplateOutlet]="poll.hasVotes && poll.stateHasVotes ? viewTemplate : emptyTemplate"
></ng-container> ></ng-container>
@ -58,7 +58,8 @@
<!-- empty helper div to center the grid wrapper --> <!-- empty helper div to center the grid wrapper -->
<div></div> <div></div>
<div class="doughnut-chart"> <div class="doughnut-chart">
<os-charts *ngIf="showChart" [type]="'doughnut'" [data]="chartDataSubject" [showLegend]="false"> </os-charts> <os-charts *ngIf="showChart" [type]="'doughnut'" [data]="chartDataSubject" [showLegend]="false">
</os-charts>
</div> </div>
<div class="vote-legend"> <div class="vote-legend">
<div class="votes-yes" *ngIf="isVoteDocumented(voteYes)"> <div class="votes-yes" *ngIf="isVoteDocumented(voteYes)">

View File

@ -1,12 +1,14 @@
@import '~assets/styles/poll-colors.scss'; @import '~assets/styles/poll-colors.scss';
.poll-link-wrapper {
outline: none;
}
.poll-preview-wrapper { .poll-preview-wrapper {
padding: 8px; padding: 8px;
background: white;
border: 1px solid rgba(0, 0, 0, 0.12); border: 1px solid rgba(0, 0, 0, 0.12);
.poll-title { .poll-title {
color: black;
text-decoration: none; text-decoration: none;
font-weight: 500; font-weight: 500;
} }

View File

@ -0,0 +1,9 @@
@import '~@angular/material/theming';
@mixin os-motion-poll-style($theme) {
$background: map-get($theme, background);
.poll-preview-wrapper {
background-color: mat-color($background, card);
}
}

View File

@ -13,6 +13,18 @@ export enum PollClassType {
Assignment = 'assignment' Assignment = 'assignment'
} }
/**
* Interface describes the possible data for the result-table.
*/
export interface PollData {
key?: string;
value?: number;
yes?: number;
no?: number;
abstain: number;
user?: string;
}
export const PollClassTypeVerbose = { export const PollClassTypeVerbose = {
motion: 'Motion poll', motion: 'Motion poll',
assignment: 'Assignment poll' assignment: 'Assignment poll'
@ -67,7 +79,9 @@ export const PercentBaseVerbose = {
}; };
export abstract class ViewBasePoll<M extends BasePoll<M, any> = any> extends BaseProjectableViewModel<M> { export abstract class ViewBasePoll<M extends BasePoll<M, any> = any> extends BaseProjectableViewModel<M> {
public get tableData(): {}[] { private _tableData: PollData[] = [];
public get tableData(): PollData[] {
if (!this._tableData.length) { if (!this._tableData.length) {
this._tableData = this.generateTableData(); this._tableData = this.generateTableData();
} }
@ -101,7 +115,6 @@ export abstract class ViewBasePoll<M extends BasePoll<M, any> = any> extends Bas
public get percentBaseVerbose(): string { public get percentBaseVerbose(): string {
return PercentBaseVerbose[this.onehundred_percent_base]; return PercentBaseVerbose[this.onehundred_percent_base];
} }
private _tableData: {}[] = [];
public abstract readonly pollClassType: 'motion' | 'assignment'; public abstract readonly pollClassType: 'motion' | 'assignment';
@ -131,7 +144,7 @@ export abstract class ViewBasePoll<M extends BasePoll<M, any> = any> extends Bas
public abstract generateChartData(): ChartData; public abstract generateChartData(): ChartData;
public abstract generateTableData(): {}[]; public abstract generateTableData(): PollData[];
} }
export interface ViewBasePoll<M extends BasePoll<M, any> = any> extends BasePoll<M, any> { export interface ViewBasePoll<M extends BasePoll<M, any> = any> extends BasePoll<M, any> {

View File

@ -28,6 +28,8 @@
@import './app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.components.scss-theme.scss'; @import './app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.components.scss-theme.scss';
@import './app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.scss-theme.scss'; @import './app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.scss-theme.scss';
@import './app/shared/components/banner/banner.component.scss-theme.scss'; @import './app/shared/components/banner/banner.component.scss-theme.scss';
@import './app/site/motions/modules/motion-poll/motion-poll/motion-poll.component.scss-theme.scss';
@import './app/site/motions/modules/motion-poll/motion-poll-detail/motion-poll-detail.component.scss-theme.scss';
/** fonts */ /** fonts */
@import './assets/styles/fonts.scss'; @import './assets/styles/fonts.scss';
@ -56,6 +58,8 @@ $narrow-spacing: (
@include os-amendment-create-wizard-style($theme); @include os-amendment-create-wizard-style($theme);
@include os-motion-detail-diff-style($theme); @include os-motion-detail-diff-style($theme);
@include os-banner-style($theme); @include os-banner-style($theme);
@include os-motion-poll-style($theme);
@include os-motion-poll-detail-style($theme);
} }
/** Load projector specific SCSS values */ /** Load projector specific SCSS values */