Enhance poll dialog layout

declutters the the poll dialogs
This commit is contained in:
Sean 2020-12-09 17:25:34 +01:00 committed by Emanuel Schütze
parent 78cfa4875e
commit e2cabbaf62
10 changed files with 124 additions and 107 deletions

View File

@ -3,6 +3,7 @@
[matTooltip]="iconTooltip"
[class]="iconAction ? 'pointer' : ''"
(click)="iconClick()"
[color]="color"
>{{ icon }}</mat-icon
>
<span class="content-node" [ngClass]="noWrap ? 'single-line' : 'break-lines'">
@ -13,5 +14,6 @@
[matTooltip]="iconTooltip"
[class]="iconAction ? 'pointer' : ''"
(click)="iconClick()"
[color]="color"
>{{ icon }}</mat-icon
>

View File

@ -51,6 +51,9 @@ export class IconContainerComponent {
@Input()
public noWrap = false;
@Input()
public color: string;
/**
* Optional action for clicking on the icon.
*/

View File

@ -1,24 +1,3 @@
.submit-buttons {
display: flex;
justify-content: flex-end;
}
.meta-text {
font-style: italic;
margin-left: 10px;
margin-right: 10px;
mat-chip {
margin-left: 5px;
margin-right: 2px;
}
}
.candidate-name {
word-wrap: break-word;
width: 100%;
border-bottom: 1px solid grey;
}
.votes-grid {
display: grid;
grid-gap: 5px;
@ -29,12 +8,3 @@
width: 100%;
}
}
.sum-value {
display: flex;
justify-content: flex-end;
}
.width-600 {
max-width: 600px;
}

View File

@ -9,13 +9,22 @@
</mat-card-title>
<!-- Type and State -->
<div class="italic spacer-bottom-20">
<span *osPerms="'assignments.can_manage'; and: poll.type === 'pseudoanonymous'">
<button mat-icon-button color="warn" (click)="openVotingWarning()">
<mat-icon> warning </mat-icon>
</button>
<div class="type-and-state italic spacer-bottom-20">
<span *osPerms="'assignments.can_manage'; and: poll.isEVoting">
<os-icon-container
class="poll-type"
icon="info"
size="large"
color="primary"
[swap]="true"
[showIcon]="poll.isAnon"
(iconAction)="openVotingWarning()"
>
{{ poll.typeVerbose | translate }}
</os-icon-container>
<span *ngIf="poll.isAnon">&nbsp;</span>
&middot;&nbsp;
</span>
<span *ngIf="poll.type !== 'analog'"> {{ poll.typeVerbose | translate }} &middot; </span>
<span>
{{ poll.stateVerbose | translate }}
</span>

View File

@ -19,4 +19,14 @@
display: flex;
margin: auto 0;
}
.type-and-state {
display: flex;
span {
display: flex;
}
.poll-type {
width: fit-content;
}
}
}

View File

@ -21,21 +21,28 @@
<!-- Subtitle -->
<div class="italic spacer-bottom-20">
<span *osPerms="'motions.can_manage_polls'; and: poll.type === 'pseudoanonymous'">
<button mat-icon-button color="warn" (click)="openVotingWarning()">
<mat-icon>warning</mat-icon>
</button>
</span>
<!-- Type and State -->
<div class="type-and-state italic spacer-bottom-20">
<span *osPerms="permission.motionsCanManagePolls; and: poll.isEVoting">
<os-icon-container
class="poll-type"
icon="info"
color="primary"
[swap]="true"
[showIcon]="poll.isAnon"
(iconAction)="openVotingWarning()"
>
{{ poll.typeVerbose | translate }}
</os-icon-container>
<span *ngIf="poll.isAnon">&nbsp;</span>
&middot;&nbsp;
</span>
<!-- Subtitle -->
<span *ngIf="pollService.isElectronicVotingEnabled && poll.type !== 'analog'">
{{ poll.typeVerbose | translate }} &middot;
</span>
<!-- State chip -->
<span>
{{ poll.stateVerbose | translate }}
</span>
<!-- State -->
<span>
{{ poll.stateVerbose | translate }}
</span>
</div>
</div>
<!-- Change state button -->

View File

@ -28,6 +28,16 @@
}
}
.type-and-state {
display: flex;
span {
display: flex;
}
.poll-type {
width: fit-content;
}
}
.poll-chart-wrapper {
cursor: pointer;
display: grid;

View File

@ -10,21 +10,26 @@
<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="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>{{ 'This field is required.' | translate }}</mat-error>
<mat-hint (click)="openVotingWarning()" *ngIf="showNonNominalWarning">
{{ 'Not suitable for formal secret voting!' | translate }}</mat-hint
>
</mat-form-field>
<div class="info-grid">
<!-- Poll Type -->
<mat-form-field *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-icon
color="primary"
matSuffix
*ngIf="showNonNominalWarning"
(click)="openVotingWarning($event)"
>
info
</mat-icon>
<mat-error>{{ 'This field is required.' | translate }}</mat-error>
</mat-form-field>
<!-- Groups entitled to Vote -->
<div class="suboption">
<!-- Groups entitled to Vote -->
<mat-form-field *ngIf="contentForm.get('type').value && contentForm.get('type').value !== 'analog'">
<os-search-value-selector
formControlName="groups_id"
@ -37,34 +42,36 @@
</mat-form-field>
</div>
<!-- Poll Methods -->
<mat-form-field *ngIf="pollMethods">
<mat-select
[placeholder]="PollPropertyVerbose.pollmethod | translate"
formControlName="pollmethod"
required
>
<mat-option *ngFor="let option of pollMethods | keyvalue: keepEntryOrder" [value]="option.key">
{{ option.value | translate }}
</mat-option>
</mat-select>
<mat-error>{{ 'This field is required.' | translate }}</mat-error>
</mat-form-field>
</ng-container>
<div class="info-grid">
<!-- Poll Methods -->
<mat-form-field *ngIf="pollMethods">
<mat-select
[placeholder]="PollPropertyVerbose.pollmethod | translate"
formControlName="pollmethod"
required
>
<mat-option *ngFor="let option of pollMethods | keyvalue: keepEntryOrder" [value]="option.key">
{{ option.value | translate }}
</mat-option>
</mat-select>
<mat-error>{{ 'This field is required.' | translate }}</mat-error>
</mat-form-field>
<!-- Amount of Votes and global options -->
<div class="suboption" *ngIf="showAmountAndGlobal(data)">
<mat-form-field>
<input
type="number"
matInput
placeholder="{{ PollPropertyVerbose.votes_amount | translate }}"
formControlName="votes_amount"
min="1"
required
/>
</mat-form-field>
<div class="global-options">
<!-- Amount of Votes -->
<mat-form-field *ngIf="showAmountAndGlobal(data)">
<input
type="number"
matInput
placeholder="{{ PollPropertyVerbose.votes_amount | translate }}"
formControlName="votes_amount"
min="1"
required
/>
</mat-form-field>
</div>
<!-- Amount of Votes and global options -->
<div class="global-options" *ngIf="showAmountAndGlobal(data)">
<mat-checkbox formControlName="global_yes">
{{ PollPropertyVerbose.global_yes | translate }}
</mat-checkbox>
@ -73,7 +80,7 @@
{{ PollPropertyVerbose.global_abstain | translate }}
</mat-checkbox>
</div>
</div>
</ng-container>
<!-- 100 Percent Base -->
<mat-form-field>

View File

@ -2,16 +2,11 @@
margin: 0;
}
.pollType {
.mat-hint {
color: red;
cursor: pointer;
}
}
.poll-preview-meta-info-form {
.suboption {
margin-left: 1.5em;
.info-grid {
display: grid;
column-gap: 1em;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
.mat-checkbox {

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
@ -29,7 +29,8 @@ import { PollService } from '../../services/poll.service';
@Component({
selector: 'os-poll-form',
templateUrl: './poll-form.component.html',
styleUrls: ['./poll-form.component.scss']
styleUrls: ['./poll-form.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class PollFormComponent<T extends ViewBasePoll, S extends PollService>
extends BaseViewComponentDirective
@ -160,14 +161,16 @@ export class PollFormComponent<T extends ViewBasePoll, S extends PollService>
this.contentForm.get('pollmethod').valueChanges.subscribe(method => {
if (method) {
this.updatePercentBases(method);
this.setVotesAmountCtrl();
this.setWarning();
}
}),
// poll type changes
this.contentForm.get('type').valueChanges.subscribe(() => {
this.setVotesAmountCtrl();
this.setWarning();
})
);
this.setWarning();
}
private disablePollType(): void {
@ -232,7 +235,7 @@ export class PollFormComponent<T extends ViewBasePoll, S extends PollService>
* Disable votes_amount form control if the poll type is anonymous
* and the poll method is votes.
*/
private setVotesAmountCtrl(): void {
private setWarning(): void {
if (this.contentForm.get('type').value === PollType.Pseudoanonymous) {
this.showNonNominalWarning = true;
} else {
@ -297,7 +300,8 @@ export class PollFormComponent<T extends ViewBasePoll, S extends PollService>
});
}
public openVotingWarning(): void {
public openVotingWarning(event: MouseEvent): void {
event.stopPropagation();
this.dialog.open(VotingPrivacyWarningComponent, infoDialogSettings);
}