Add prettier list of speakers

Also cleans up some CSS and unifies some Drag-N-Drop Component
styles.
This commit is contained in:
Sean Engelhardt 2019-03-21 18:40:41 +01:00 committed by Emanuel Schütze
parent 63a2c6b05b
commit ab19d66022
6 changed files with 222 additions and 130 deletions

View File

@ -1,17 +1,17 @@
<div cdkDropList class="os-card" [cdkDropListDisabled]="!enable" (cdkDropListDropped)="drop($event)">
<div class="box line" *ngIf="!array.length">
<div cdkDropList [cdkDropListDisabled]="!enable" (cdkDropListDropped)="drop($event)">
<div class="line" *ngIf="!array.length">
<span translate>No data</span>
</div>
<div class="box line" *ngFor="let item of array; let i = index" cdkDrag>
<div class="section-one" cdkDragHandle *ngIf="enable">
<div class="line" *ngFor="let item of array; let i = index" cdkDrag>
<div class="section-one backgroundColorLight" cdkDragHandle *ngIf="enable">
<mat-icon>drag_indicator</mat-icon>
</div>
<div class="section-two">
<div class="section-two backgroundColorLight">
<!-- {number}. {item.getTitle()} -->
<span *ngIf="count">{{ i + 1 }}.&nbsp;</span>
<span>{{ item.getTitle() }}</span>
</div>
<div class="section-three">
<div class="section-three backgroundColorLight">
<!-- Extra controls slot using implicit template references -->
<ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template>
</div>

View File

@ -1,19 +1,11 @@
@import '~assets/styles/drag.scss';
.box {
width: 100%;
border-bottom: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87);
font-size: 14px;
}
.box:last-child {
border: none;
}
.line {
display: table;
width: 100%;
font-size: 14px;
min-height: 50px;
margin-bottom: 5px;
.section-one {
display: table-cell;
@ -28,7 +20,12 @@
.section-two {
display: table-cell;
vertical-align: middle;
width: 80%;
width: 100%;
padding-left: 20px;
span + span {
margin-left: 20px;
}
}
.section-three {

View File

@ -11,85 +11,100 @@
</div>
</os-head-bar>
<h1 class="title on-transition-fade" *ngIf="viewItem">{{ viewItem.getTitle() }}</h1>
<mat-card class="os-card speaker-card" *ngIf="viewItem">
<!-- Title -->
<h1 class="title on-transition-fade" *ngIf="viewItem">{{ viewItem.getTitle() }}</h1>
<mat-card class="speaker-card" *ngIf="viewItem">
<!-- List of finished speakers -->
<mat-expansion-panel *ngIf="finishedSpeakers && finishedSpeakers.length > 0" class="finished-list">
<mat-expansion-panel-header>
<mat-panel-title translate> Last speakers </mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<!-- {Number}. {full_name} {time} minutes (Start time: {begin_time}) [close button] -->
<mat-list-item *ngFor="let speaker of finishedSpeakers; let number = index">
<div class="finished-prefix">
<span>{{ number + 1 }}. {{ speaker }}</span>
<div class="finished-speaker-grid">
<div class="number">{{ number + 1 }}.</div>
<div class="name">{{ speaker }}</div>
<div class="time">
{{ durationString(speaker) }} ({{ 'Start time' | translate }}: {{ startTimeToString(speaker) }})
</div>
<div class="controls">
<button
mat-icon-button
matTooltip="{{ 'Remove' | translate }}"
*osPerms="'agenda.can_manage_list_of_speakers'"
(click)="onDeleteButton(speaker)"
>
<mat-icon>close</mat-icon>
</button>
</div>
</div>
<div class="finished-suffix">
&nbsp;&nbsp; {{ durationString(speaker) }} ({{ 'Start time' | translate }}:
{{ startTimeToString(speaker) }})
</div>
<button
mat-stroked-button
matTooltip="{{ 'Remove' | translate }}"
*osPerms="'agenda.can_manage_list_of_speakers'"
(click)="onDeleteButton(speaker)"
>
<mat-icon>close</mat-icon>
</button>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
<!-- horizontal separation line -->
<mat-divider *ngIf="finishedSpeakers && finishedSpeakers.length"></mat-divider>
<div *ngIf="finishedSpeakers && finishedSpeakers.length" class="spacer-bottom-40"></div>
<!-- Current Speaker -->
<div class="current-speaker" *ngIf="activeSpeaker">
<mat-icon class="speaking-icon">play_arrow</mat-icon>
<span class="speaking-name">{{ activeSpeaker }}</span>
<span class="prefix">
<mat-icon>mic</mat-icon>
</span>
<button
mat-stroked-button
matTooltip="{{ 'End speech' | translate }}"
*osPerms="'agenda.can_manage_list_of_speakers'"
(click)="onStopButton()"
>
<mat-icon>mic_off</mat-icon>
<span translate>Stop</span>
</button>
<span class="name">{{ activeSpeaker }}</span>
<span class="suffix">
<!-- Stop speaker button -->
<button
mat-icon-button
matTooltip="{{ 'End speech' | translate }}"
*osPerms="'agenda.can_manage_list_of_speakers'"
(click)="onStopButton()"
>
<mat-icon>stop</mat-icon>
</button>
</span>
</div>
<!-- Waiting speakers -->
<div>
<div class="waiting-list" *ngIf="speakers && speakers.length > 0">
<os-sorting-list
[input]="speakers"
[live]="true"
[count]="true"
[enable]="opCanManage()"
(sortEvent)="onSortingChange($event)"
>
<!-- implicit item references into the component using ng-template slot -->
<ng-template let-item>
<span *osPerms="'agenda.can_manage_list_of_speakers'">
<span *ngIf="hasSpokenCount(item)" class="red-warning-text speaker-warning">
{{ hasSpokenCount(item) + 1 }}. <span translate>contribution</span>
</span>
<span *ngIf="item.gender">({{ item.gender | translate }})</span>
<div class="waiting-list" *ngIf="speakers && speakers.length > 0">
<os-sorting-list
[input]="speakers"
[live]="true"
[count]="true"
[enable]="opCanManage()"
(sortEvent)="onSortingChange($event)"
>
<!-- implicit item references into the component using ng-template slot -->
<ng-template let-item>
<span *osPerms="'agenda.can_manage_list_of_speakers'">
<span *ngIf="hasSpokenCount(item)" class="red-warning-text speaker-warning">
{{ hasSpokenCount(item) + 1 }}. <span translate>contribution</span>
</span>
<mat-button-toggle-group *osPerms="'agenda.can_manage_list_of_speakers'">
<mat-button-toggle matTooltip="{{ 'Begin speech' | translate }}" (click)="onStartButton(item)">
<mat-icon>mic</mat-icon>
<span translate>Start</span>
</mat-button-toggle>
<mat-button-toggle matTooltip="{{ 'Mark speaker' | translate }}" (click)="onMarkButton(item)">
<mat-icon>{{ item.marked ? 'star' : 'star_border' }}</mat-icon>
</mat-button-toggle>
<mat-button-toggle matTooltip="{{ 'Remove' | translate }}" (click)="onDeleteButton(item)">
<mat-icon>close</mat-icon>
</mat-button-toggle>
</mat-button-toggle-group>
</ng-template>
</os-sorting-list>
</div>
<span *ngIf="item.gender">({{ item.gender | translate }})</span>
</span>
<!-- Start, start and delete buttons -->
<span *osPerms="'agenda.can_manage_list_of_speakers'">
<!-- start button -->
<button mat-icon-button matTooltip="{{ 'Begin speech' | translate }}" (click)="onStartButton(item)">
<mat-icon>play_arrow</mat-icon>
</button>
<!-- star button -->
<button mat-icon-button matTooltip="{{ 'Mark speaker' | translate }}" (click)="onMarkButton(item)">
<mat-icon>{{ item.marked ? 'star' : 'star_border' }}</mat-icon>
</button>
<!-- delete button -->
<button mat-icon-button matTooltip="{{ 'Remove' | translate }}" (click)="onDeleteButton(item)">
<mat-icon>close</mat-icon>
</button>
</span>
</ng-template>
</os-sorting-list>
</div>
<!-- Search for speakers -->
@ -110,11 +125,11 @@
<!-- Add me and remove me if OP has correct permission -->
<div *osPerms="'agenda.can_be_speaker'" class="add-self-buttons">
<div *ngIf="speakers && !closedList">
<button mat-raised-button (click)="addNewSpeaker()" *ngIf="!isOpInList()">
<button mat-stroked-button (click)="addNewSpeaker()" *ngIf="!isOpInList()">
<mat-icon>add</mat-icon>
<span translate>Add me</span>
</button>
<button mat-raised-button (click)="onDeleteButton()" *ngIf="isOpInList()">
<button mat-stroked-button (click)="onDeleteButton()" *ngIf="isOpInList()">
<mat-icon>remove</mat-icon>
<span translate>Remove me</span>
</button>

View File

@ -1,72 +1,147 @@
@import '~@angular/material/theming';
@mixin os-list-of-speakers-style($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
$contrast: map-get($primary, contrast);
$foreground: map-get($theme, foreground);
.current-speaker {
background-color: mat-color($accent) !important;
> span {
color: mat-color($accent, default-contrast);
}
}
.finished-speaker-grid {
> .number .name .controls {
color: mat-color($foreground, text);
}
> .time {
color: mat-color($foreground, secondary-text);
}
}
}
.title {
margin-left: 25px;
}
.speaker-card {
margin: 0 20px 0 20px;
padding: 0;
.finished-list {
box-shadow: none !important;
margin-bottom: 15px;
.finished-list {
margin-bottom: 15px;
.finished-suffix {
color: slategray;
font-size: 80%;
margin-right: 10px;
}
.mat-list-item {
height: auto;
margin-bottom: 10px;
}
.mat-list-item {
height: auto;
}
.finished-speaker-grid {
display: grid;
width: 100%;
grid-template-areas: 'number name time controls';
grid-gap: 5px;
grid-template-columns: 30px 1fr min-content min-content;
}
button {
margin-left: 10px;
@media only screen and (max-width: 960px) {
.finished-speaker-grid {
grid-template-areas:
'number name controls'
'number time controls';
grid-template-columns: 30px 1fr min-content;
}
}
.current-speaker {
padding: 10px 25px 15px 25px;
display: table;
.speaking-icon {
display: table-cell;
vertical-align: middle;
}
.speaking-name {
display: table-cell;
vertical-align: middle;
font-weight: bold;
padding-left: 10px;
}
button {
display: table-cell;
vertical-align: middle;
margin-left: 10px;
}
.number {
grid-area: number;
margin: 0;
}
.waiting-list {
padding: 10px 25px 0 25px;
width: 75%;
.name {
grid-area: name;
margin: 0;
}
form {
padding: 15px 25px 10px 25px;
width: auto;
.time {
grid-area: time;
margin: 0;
//allows pushing this grid area as small as possible and aligns the end to the same level
white-space: nowrap;
font-size: 80%;
}
.search-users {
display: grid;
.mat-form-field {
width: 100%;
.controls {
grid-area: controls;
margin: 0;
opacity: 0.7;
.mat-icon-button {
height: 20px;
line-height: 1;
.mat-icon {
line-height: 19px;
}
}
}
}
.add-self-buttons {
padding: 20px 0 20px 25px;
.current-speaker {
display: table;
width: -webkit-fill-available;
height: 50px;
margin: 50px 25px 20px 25px;
box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.25);
.prefix {
display: table-cell;
padding: 0 15px;
vertical-align: middle;
.mat-icon {
vertical-align: middle;
}
}
.speaker-warning {
margin-right: 5px;
.name {
display: table-cell;
vertical-align: middle;
font-weight: bold;
padding-left: 10px;
width: 100%;
}
.suffix {
display: table-cell;
vertical-align: middle;
white-space: nowrap;
padding-right: 10px;
}
}
.waiting-list {
padding: 10px 25px 0 25px;
}
form {
padding: 15px 25px 10px 25px;
width: auto;
.search-users {
display: grid;
.mat-form-field {
width: 100%;
}
}
}
.add-self-buttons {
padding: 15px 0 20px 25px;
}
.speaker-warning {
margin-right: 5px;
}

View File

@ -81,7 +81,7 @@
}
.backgroundColorLight {
background-color: mat-color($background, status-bar);
background-color: mat-color($background, hover);
color: mat-color($foreground, text) !important;
}
}

View File

@ -7,10 +7,11 @@
@import './assets/styles/openslides-dark-theme.scss';
@import './assets/styles/openslides-green-theme.scss';
/** Import the component-related stylesheets here */
/** Import the component-related style sheets here */
@import './app/site/site.component.scss-theme.scss';
@import './assets/styles/global-components-style.scss';
@import './app/shared/components/projector-button/projector-button.component.scss';
@import './app/site/agenda/components/list-of-speakers/list-of-speakers.component.scss';
/** fonts */
@import './assets/styles/fonts.scss';
@ -21,6 +22,7 @@
@include os-site-theme($theme);
@include os-components-style($theme);
@include os-projector-button-style($theme);
@include os-list-of-speakers-style($theme);
/** More components are added here */
}
@ -408,6 +410,9 @@ button.mat-menu-item.selected {
.spacer-bottom-20 {
margin-bottom: 20px !important;
}
.spacer-bottom-40 {
margin-bottom: 40px !important;
}
.spacer-left-10 {
margin-left: 10px;
}