UI improvements

- better select field for category and block in motion detail
- improved motion block views
- chips for submitters
- motion detail template
This commit is contained in:
Emanuel Schütze 2019-01-17 14:07:54 +01:00
parent f2b9ba0e52
commit 8536f46d01
16 changed files with 232 additions and 171 deletions

View File

@ -1,4 +1,9 @@
<mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" *ngIf="!vp.isMobile"></mat-toolbar> <mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" *ngIf="!vp.isMobile">
<!-- Nav menu -->
<button mat-icon-button class="on-transition-fade" *ngIf="!multiSelectMode" (click)="clickHamburgerMenu()">
<mat-icon>menu</mat-icon>
</button>
</mat-toolbar>
<mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" class="sticky-toolbar"> <mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" class="sticky-toolbar">
<div class="toolbar-left"> <div class="toolbar-left">
<!-- Nav menu --> <!-- Nav menu -->
@ -63,7 +68,6 @@
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
<!-- Save button --> <!-- Save button -->
<button mat-button *ngIf="editMode" (click)="save()"><strong translate class="upper">Save</strong></button> <button mat-button *ngIf="editMode" (click)="save()"><strong translate class="upper">Save</strong></button>

View File

@ -1,9 +1,6 @@
.list { .list {
width: 100%; width: 100%;
border: solid 1px #ccc;
display: block; display: block;
background: white; // TODO theme
border-radius: 4px;
overflow: hidden; overflow: hidden;
} }
@ -11,7 +8,6 @@
width: 100%; width: 100%;
border-bottom: solid 1px #ccc; border-bottom: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
background: white; // TODO theme
font-size: 14px; font-size: 14px;
} }

View File

@ -51,8 +51,6 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
* @param vp determine the viewport * @param vp determine the viewport
* @param durationService Converts numbers to readable duration strings * @param durationService Converts numbers to readable duration strings
* @param csvExport Handles the exporting into csv * @param csvExport Handles the exporting into csv
* @param repo the agenda repository
* @param promptService
* @param filterService: service for filtering data * @param filterService: service for filtering data
*/ */
public constructor( public constructor(

View File

@ -42,7 +42,7 @@
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>
<mat-accordion class="os-card"> <mat-accordion class="os-form-card">
<mat-expansion-panel *ngFor="let category of categories" (opened)="openId = category.id" (closed)="panelClosed(category)" <mat-expansion-panel *ngFor="let category of categories" (opened)="openId = category.id" (closed)="panelClosed(category)"
[expanded]="openId === category.id" multiple="false"> [expanded]="openId === category.id" multiple="false">

View File

@ -6,41 +6,40 @@
</h4> </h4>
<div *ngIf="!isEditMode"> <div *ngIf="!isEditMode">
<mat-chip-list *ngFor="let submitter of motion.submitters"> <mat-chip-list *ngFor="let submitter of motion.submitters" class="user">
<mat-chip>{{ submitter.full_name }}</mat-chip> <mat-chip>{{ submitter.full_name }}</mat-chip>
</mat-chip-list> </mat-chip-list>
</div> </div>
<div *ngIf="isEditMode">
<mat-card>
<form *ngIf="users && users.value.length > 0" [formGroup]="addSubmitterForm">
<os-search-value-selector
class="search-users"
ngDefaultControl
[form]="addSubmitterForm"
[formControl]="addSubmitterForm.get('userId')"
[multiple]="false"
listname="{{ 'Select or search new submitter ...' | translate }}"
[InputListValues]="users"
></os-search-value-selector>
</form>
<os-sorting-list <div *ngIf="isEditMode">
class="testclass" <os-sorting-list
[input]="editSubmitterObservable" [input]="editSubmitterObservable"
[live]="true" [live]="true"
[count]="true" [count]="false"
(sortEvent)="onSortingChange($event)" (sortEvent)="onSortingChange($event)"
> >
<!-- implicit user references into the component using ng-template slot --> <!-- implicit user references into the component using ng-template slot -->
<ng-template let-user> <ng-template let-user>
<button type="button" mat-icon-button matTooltip="{{ 'Remove' | translate }}" (click)="onRemove(user)"> <button type="button" mat-icon-button matTooltip="{{ 'Remove' | translate }}" (click)="onRemove(user)">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</ng-template> </ng-template>
</os-sorting-list> </os-sorting-list>
<mat-card-actions>
<button type="button" mat-button (click)="onSave()"><span translate>Save</span></button> <form *ngIf="users && users.value.length > 0" [formGroup]="addSubmitterForm">
<button type="button" mat-button (click)="onCancel()"><span translate>Cancel</span></button> <os-search-value-selector
</mat-card-actions> class="search-users"
</mat-card> ngDefaultControl
[form]="addSubmitterForm"
[formControl]="addSubmitterForm.get('userId')"
[multiple]="false"
listname="{{ 'Select or search new submitter ...' | translate }}"
[InputListValues]="users"
></os-search-value-selector>
</form>
<p>
<button type="button" mat-button (click)="onSave()"><span translate>Save</span></button>
<button type="button" mat-button (click)="onCancel()"><span translate>Cancel</span></button>
</p>
</div> </div>

View File

@ -1,34 +1,4 @@
<ng-container *ngIf="vp.isMobile ; then mobileView; else desktopView"></ng-container> <div>
<ng-template #title>
<ng-content select=".meta-text-block-title"></ng-content>
</ng-template>
<ng-template #content>
<ng-content select=".meta-text-block-content"></ng-content>
</ng-template>
<ng-template #actionRow>
<ng-content select=".meta-text-block-action-row"></ng-content>
</ng-template>
<ng-template #mobileView>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<mat-icon>{{ icon }}</mat-icon>
<ng-container *ngTemplateOutlet="title"></ng-container>
</mat-panel-title>
</mat-expansion-panel-header>
<ng-container *ngTemplateOutlet="content"></ng-container>
<mat-action-row *ngIf="showActionRow">
<ng-container *ngTemplateOutlet="actionRow"></ng-container>
</mat-action-row>
</mat-expansion-panel>
</ng-template>
<ng-template #desktopView>
<mat-card class="meta-text-block"> <mat-card class="meta-text-block">
<mat-card-header> <mat-card-header>
<mat-card-title> <mat-card-title>
@ -47,4 +17,14 @@
<ng-container *ngTemplateOutlet="content"></ng-container> <ng-container *ngTemplateOutlet="content"></ng-container>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div>
<ng-template #title>
<ng-content select=".meta-text-block-title"></ng-content>
</ng-template>
<ng-template #content>
<ng-content select=".meta-text-block-content"></ng-content>
</ng-template>
<ng-template #actionRow>
<ng-content select=".meta-text-block-action-row"></ng-content>
</ng-template> </ng-template>

View File

@ -1,6 +1,6 @@
.meta-text-block { .meta-text-block {
padding: 0px; padding: 0px;
margin: 20px 10px 20px 0; margin: 20px 0;
min-width: 200px; min-width: 200px;
mat-card-header { mat-card-header {

View File

@ -1,14 +1,10 @@
<os-head-bar <os-head-bar>
mainButtonIcon="edit"
[nav]="false"
[mainButton]="true"
[editMode]="editBlock"
(mainEvent)="toggleEditMode()"
(saveEvent)="saveBlock()"
>
<!-- Title --> <!-- Title -->
<div class="title-slot"> <div class="title-slot">
<h2 *ngIf="block && !editBlock">{{ 'Motion block' | translate }} {{ block.id }}</h2> <h2 *ngIf="block && !editBlock">{{ block.title }}</h2>
<form [formGroup]="blockEditForm" (ngSubmit)="saveBlock()" (keydown)="onKeyDown($event)" *ngIf="editBlock"> <form [formGroup]="blockEditForm" (ngSubmit)="saveBlock()" (keydown)="onKeyDown($event)" *ngIf="editBlock">
<mat-form-field> <mat-form-field>
@ -24,21 +20,23 @@
</form> </form>
</div> </div>
<!-- Menu --> <!-- Menu -->
<div class="menu-slot"> <div class="menu-slot">
<button type="button" mat-icon-button [matMenuTriggerFor]="motionBlockMenu"> <button type="button" mat-icon-button [matMenuTriggerFor]="motionBlockMenu">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
</div> </div>
<!-- Save button -->
<div *ngIf="editBlock" class="extra-controls-slot on-transition-fade">
<button mat-button (click)="saveBlock()"><strong translate class="upper">Save</strong></button>
</div>
</os-head-bar> </os-head-bar>
<!-- Title --> <mat-card>
<div *ngIf="block" class="block-title on-transition-fade">
<h2 *ngIf="!editBlock">{{ block.title }}</h2>
<h2 *ngIf="editBlock">{{ blockEditForm.get('title').value }}</h2>
</div>
<mat-card class="block-card">
<button mat-raised-button color="primary" (click)="onFollowRecButton()" [disabled]="isFollowingProhibited()"> <button mat-raised-button color="primary" (click)="onFollowRecButton()" [disabled]="isFollowingProhibited()">
<mat-icon>done_all</mat-icon> <mat-icon>done_all</mat-icon>
<span translate>Follow recommendations for all motions</span> <span translate>Follow recommendations for all motions</span>
@ -115,8 +113,14 @@
<mat-icon>videocam</mat-icon> <mat-icon>videocam</mat-icon>
<span translate>Project</span> <span translate>Project</span>
</button> </button>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<button mat-menu-item (click)="toggleEditMode()">
<mat-icon>edit</mat-icon>
<span translate>Edit title</span>
</button>
<button mat-menu-item class="red-warning-text" (click)="onDeleteBlockButton()"> <button mat-menu-item class="red-warning-text" (click)="onDeleteBlockButton()">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
<span translate>Delete</span> <span translate>Delete</span>

View File

@ -5,7 +5,7 @@
<!-- Creating a new motion block --> <!-- Creating a new motion block -->
<mat-card class="os-card" *ngIf="blockToCreate"> <mat-card class="os-card" *ngIf="blockToCreate">
<mat-card-title translate>Create new motion block</mat-card-title> <mat-card-title translate>New motion block</mat-card-title>
<mat-card-content> <mat-card-content>
<form [formGroup]="createBlockForm" <form [formGroup]="createBlockForm"
(keydown)="onKeyDown($event)"> (keydown)="onKeyDown($event)">
@ -60,19 +60,39 @@
<table class="os-headed-listview-table on-transition-fade" mat-table [dataSource]="dataSource" matSort> <table class="os-headed-listview-table on-transition-fade" mat-table [dataSource]="dataSource" matSort>
<!-- title column --> <!-- title column -->
<ng-container matColumnDef="title"> <ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef mat-sort-header> <span translate>Name</span> </mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header> <span translate>Title</span> </mat-header-cell>
<mat-cell *matCellDef="let block"> {{ block.title }} </mat-cell> <mat-cell *matCellDef="let block" (click)="openItem(block)"> {{ block.title }} </mat-cell>
</ng-container> </ng-container>
<!-- amount column --> <!-- amount column -->
<ng-container matColumnDef="amount"> <ng-container matColumnDef="amount">
<mat-header-cell *matHeaderCellDef> <span translate>Motions</span> </mat-header-cell> <mat-header-cell *matHeaderCellDef> <span translate>Motions</span> </mat-header-cell>
<mat-cell *matCellDef="let block"> <mat-cell *matCellDef="let block" (click)="openItem(block)">
<span class="os-amount-chip">{{ getMotionAmount(block.motionBlock) }}</span> <span class="os-amount-chip">{{ getMotionAmount(block.motionBlock) }}</span>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<!-- menu -->
<ng-container matColumnDef="menu">
<mat-header-cell *matHeaderCellDef>Menu</mat-header-cell>
<mat-cell *matCellDef="let block">
<button mat-icon-button [matMenuTriggerFor]="singleItemMenu" [matMenuTriggerData]="{ item: block }">
<mat-icon>more_vert</mat-icon>
</button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="getColumnDefinition()"></mat-header-row> <mat-header-row *matHeaderRowDef="getColumnDefinition()"></mat-header-row>
<mat-row (click)="onSelectRow(row)" *matRowDef="let row; columns: getColumnDefinition()"> </mat-row> <mat-row *matRowDef="let row; columns: getColumnDefinition()"> </mat-row>
</table> </table>
</mat-card> </mat-card>
<mat-menu #singleItemMenu="matMenu">
<ng-template matMenuContent let-item="item">
<!-- Delete Button -->
<button mat-menu-item class="red-warning-text" (click)="onDelete(item)">
<mat-icon>delete</mat-icon>
<span translate>Delete</span>
</button>
</ng-template>
</mat-menu>

View File

@ -1,11 +1,20 @@
.os-headed-listview-table { .os-headed-listview-table {
// Title // Title
.mat-column-title { .mat-column-title {
flex: 3 0 0; flex: 9 0 0;
} }
// Amount // Amount
.mat-column-amount { .mat-column-amount {
flex: 1 0 0; flex: 1 0 60px;
}
// Menu
.mat-column-menu {
flex: 0 0 40px;
} }
} }
::ng-deep .mat-form-field {
width: 50%;
}

View File

@ -14,6 +14,7 @@ import { DataStoreService } from 'app/core/services/data-store.service';
import { MotionBlockRepositoryService } from '../../services/motion-block-repository.service'; import { MotionBlockRepositoryService } from '../../services/motion-block-repository.service';
import { ViewMotionBlock } from '../../models/view-motion-block'; import { ViewMotionBlock } from '../../models/view-motion-block';
import { AgendaRepositoryService } from 'app/site/agenda/services/agenda-repository.service'; import { AgendaRepositoryService } from 'app/site/agenda/services/agenda-repository.service';
import { PromptService } from '../../../../core/services/prompt.service';
/** /**
* Table for the motion blocks * Table for the motion blocks
@ -53,7 +54,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
* Constructor for the motion block list view * Constructor for the motion block list view
* *
* @param titleService sets the title * @param titleService sets the title
* @param translate translations * @param translate translpations
* @param matSnackBar display errors in the snack bar * @param matSnackBar display errors in the snack bar
* @param router routing to children * @param router routing to children
* @param route determine the local route * @param route determine the local route
@ -61,6 +62,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
* @param agendaRepo the agenda repository service * @param agendaRepo the agenda repository service
* @param DS the dataStore * @param DS the dataStore
* @param formBuilder creates forms * @param formBuilder creates forms
* @param promptService the delete prompt
*/ */
public constructor( public constructor(
titleService: Title, titleService: Title,
@ -71,7 +73,8 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
private repo: MotionBlockRepositoryService, private repo: MotionBlockRepositoryService,
private agendaRepo: AgendaRepositoryService, private agendaRepo: AgendaRepositoryService,
private DS: DataStoreService, private DS: DataStoreService,
private formBuilder: FormBuilder private formBuilder: FormBuilder,
private promptService: PromptService
) { ) {
super(titleService, translate, matSnackBar); super(titleService, translate, matSnackBar);
@ -98,6 +101,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
}); });
this.repo.getViewModelListObservable().subscribe(newMotionblocks => { this.repo.getViewModelListObservable().subscribe(newMotionblocks => {
newMotionblocks.sort((a, b) => (a > b ? 1 : -1));
this.dataSource.data = newMotionblocks; this.dataSource.data = newMotionblocks;
}); });
@ -110,7 +114,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
* @returns an array of strings building the column definition * @returns an array of strings building the column definition
*/ */
public getColumnDefinition(): string[] { public getColumnDefinition(): string[] {
return ['title', 'amount']; return ['title', 'amount', 'menu'];
} }
/** /**
@ -118,7 +122,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
* *
* @param block the given motion block * @param block the given motion block
*/ */
public onSelectRow(block: ViewMotionBlock): void { public openItem(block: ViewMotionBlock): void {
this.router.navigate([`${block.id}`], { relativeTo: this.route }); this.router.navigate([`${block.id}`], { relativeTo: this.route });
} }
@ -132,6 +136,18 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
return this.repo.getMotionAmountByBlock(motionBlock); return this.repo.getMotionAmountByBlock(motionBlock);
} }
/**
* Click handler to delete motion blocks
*
* @param motionBlock the block to delete
*/
public async onDelete(motionBlock: ViewMotionBlock): Promise<void> {
const content = this.translate.instant('Are you sure you want to delete this motion block?');
if (await this.promptService.open(motionBlock.title, content)) {
await this.repo.delete(motionBlock);
}
}
/** /**
* Helper function reset the form and set the default values * Helper function reset the form and set the default values
*/ */

View File

@ -60,23 +60,23 @@
<mat-menu #motionExtraMenu="matMenu"> <mat-menu #motionExtraMenu="matMenu">
<div *ngIf="motion"> <div *ngIf="motion">
<!-- PDF -->
<button mat-menu-item <button mat-menu-item
(click)="onDownloadPdf()"> (click)="onDownloadPdf()">
<mat-icon>picture_as_pdf</mat-icon> <mat-icon>picture_as_pdf</mat-icon>
<span translate>PDF</span> <span translate>PDF</span>
</button> </button>
<!-- List of speakers -->
<button mat-menu-item [routerLink]="getSpeakerLink()"> <button mat-menu-item [routerLink]="getSpeakerLink()">
<mat-icon>mic</mat-icon> <mat-icon>mic</mat-icon>
<span translate>List of speakers</span> <span translate>List of speakers</span>
</button> </button>
<!-- Project -->
<button mat-menu-item> <button mat-menu-item>
<!-- possible icons: screen_share, cast, videocam -->
<mat-icon>videocam</mat-icon> <mat-icon>videocam</mat-icon>
<span translate>Project</span> <span translate>Project</span>
</button> </button>
<!-- New amendment -->
<button <button
mat-menu-item mat-menu-item
(click)="createAmendment()" (click)="createAmendment()"
@ -85,7 +85,7 @@
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
<span translate>New amendment</span> <span translate>New amendment</span>
</button> </button>
<!-- Show entire motion text -->
<button <button
mat-menu-item mat-menu-item
(click)="showAmendmentContext = !showAmendmentContext" (click)="showAmendmentContext = !showAmendmentContext"
@ -97,6 +97,7 @@
<mat-divider></mat-divider> <mat-divider></mat-divider>
<!-- Delete -->
<button mat-menu-item class="red-warning-text" (click)="deleteMotionButton()"> <button mat-menu-item class="red-warning-text" (click)="deleteMotionButton()">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
<span translate>Delete</span> <span translate>Delete</span>
@ -105,59 +106,50 @@
</mat-menu> </mat-menu>
</os-head-bar> </os-head-bar>
<!-- Title --> <div class="content-container">
<div class="title-left on-transition-fade" *ngIf="motion && !editMotion"> <!-- Title -->
<div class="title-line"> <div class="title on-transition-fade" *ngIf="motion && !editMotion">
<h1> <div class="title-line">
{{ motion.title }} <h1>
</h1> {{ motion.title }}
<button mat-icon-button color="primary" (click)="toggleFavorite()"> </h1>
<mat-icon>{{ motion.star ? 'star' : 'star_border' }}</mat-icon> <button mat-icon-button color="primary" (click)="toggleFavorite()">
</button> <mat-icon>{{ motion.star ? 'star' : 'star_border' }}</mat-icon>
</button>
</div>
<span class="main-nav-color title-font"><span translate>Sequential number</span>&nbsp;{{ motion.id }}</span>
</div> </div>
<span class="main-nav-color title-font"><span translate>Sequential number</span>&nbsp;{{ motion.id }}</span>
<ng-container *ngIf="vp.isMobile; then mobileView; else desktopView"></ng-container>
</div> </div>
<ng-container *ngIf="vp.isMobile; then mobileView; else desktopView"></ng-container>
<ng-template #mobileView> <ng-template #mobileView>
<mat-accordion multi="true" class="on-transition-fade">
<!-- MetaInfo Panel-->
<mat-expansion-panel #metaInfoPanel [expanded]="true" class="meta-info-block meta-info-panel">
<mat-expansion-panel-header>
<mat-panel-title>
<mat-icon>info</mat-icon>
<span translate>Meta information</span>
</mat-panel-title>
</mat-expansion-panel-header>
<!-- Meta info --> <!-- Meta info -->
<div class="expansion-panel-custom-body"> <div class="hspacing">
<ng-container *ngTemplateOutlet="metaInfoTemplate"></ng-container> <ng-container *ngTemplateOutlet="metaInfoTemplate"></ng-container>
</div> </div>
</mat-expansion-panel>
<!-- Content --> <mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
<mat-expansion-panel #contentPanel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<mat-icon>format_align_left</mat-icon>
<span translate>Content</span>
</mat-panel-title>
</mat-expansion-panel-header>
<div class="expansion-panel-custom-body"> <!-- Content -->
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container> <div class="hspacing">
</div> <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
</mat-expansion-panel> </div>
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments> <mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
<button mat-button *ngIf="canShowLog" (click)="motionLogExpanded =!motionLogExpanded"> <!-- Comments -->
<span translate>Show motion log</span> <os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
</button>
<os-motion-log *ngIf="motionLogExpanded" [motion]="motion"></os-motion-log> <!-- Personal note -->
</mat-accordion> <os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
<!-- Motoin log -->
<button mat-button *ngIf="canShowLog" (click)="motionLogExpanded =!motionLogExpanded">
<span translate>Show motion log</span>
</button>
<os-motion-log *ngIf="motionLogExpanded" [motion]="motion"></os-motion-log>
</ng-template> </ng-template>
<ng-template #desktopView> <ng-template #desktopView>
@ -287,7 +279,7 @@
<!-- Category --> <!-- Category -->
<!-- Disabled during "new motion" since changing has no effect --> <!-- Disabled during "new motion" since changing has no effect -->
<div *ngIf="!editMotion"> <div *ngIf="!editMotion && categoryObserver.value.length > 0">
<h4 translate>Category</h4> <h4 translate>Category</h4>
<mat-menu #categoryMenu="matMenu"> <mat-menu #categoryMenu="matMenu">
<button <button
@ -295,27 +287,26 @@
*ngFor="let category of categoryObserver.value" *ngFor="let category of categoryObserver.value"
(click)="setCategory(category.id)" (click)="setCategory(category.id)"
> >
<mat-icon *ngIf="motion.category_id === category.id">check</mat-icon>
{{ category }} {{ category }}
</button> </button>
<button mat-menu-item (click)="setCategory(null)">---</button>
</mat-menu> </mat-menu>
<mat-basic-chip [matMenuTriggerFor]="categoryMenu" class="grey"> <mat-basic-chip [matMenuTriggerFor]="categoryMenu" class="grey">
{{ motion.category ? motion.category : ('not set' | translate) }} {{ motion.category ? motion.category : '' }}
</mat-basic-chip> </mat-basic-chip>
</div> </div>
<!-- Block --> <!-- Block -->
<div *ngIf="!editMotion"> <div *ngIf="!editMotion && blockObserver.value.length > 0">
<h4 translate>Motion block</h4> <h4 translate>Motion block</h4>
<mat-menu #blockMenu="matMenu"> <mat-menu #blockMenu="matMenu">
<button mat-menu-item *ngFor="let block of blockObserver.value" (click)="setBlock(block.id)"> <button mat-menu-item *ngFor="let block of blockObserver.value" (click)="setBlock(block.id)">
<mat-icon *ngIf="motion.motion_block_id === block.id">check</mat-icon>
{{ block }} {{ block }}
</button> </button>
<button mat-menu-item (click)="setBlock(null)">---</button>
</mat-menu> </mat-menu>
<mat-basic-chip [matMenuTriggerFor]="blockMenu" class="grey"> <mat-basic-chip [matMenuTriggerFor]="blockMenu" class="grey">
{{ motion.motion_block ? motion.motion_block : ('not set' | translate) }} {{ motion.motion_block ? motion.motion_block : '' }}
</mat-basic-chip> </mat-basic-chip>
</div> </div>
@ -326,7 +317,7 @@
</div> </div>
<!-- motion polls --> <!-- motion polls -->
<div *ngIf="!editMotion"> <div *ngIf="!editMotion" class="spacer-top-20 spacer-bottom-20">
<os-motion-poll *ngFor="let poll of motion.motion.polls; let i = index" [rawPoll]="poll" [pollIndex]="i"> <os-motion-poll *ngFor="let poll of motion.motion.polls; let i = index" [rawPoll]="poll" [pollIndex]="i">
</os-motion-poll> </os-motion-poll>
<div class="create-poll-button" *ngIf="perms.isAllowed('createpoll', motion)"> <div class="create-poll-button" *ngIf="perms.isAllowed('createpoll', motion)">

View File

@ -107,7 +107,6 @@ span {
.desktop-left { .desktop-left {
width: 30%; width: 30%;
float: left; float: left;
padding-left: 65px;
padding-right: 25px; padding-right: 25px;
} }

View File

@ -923,7 +923,11 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
* @param id Motion category id * @param id Motion category id
*/ */
public setCategory(id: number): void { public setCategory(id: number): void {
this.repo.setCatetory(this.motion, id); if (id === this.motion.category_id) {
this.repo.setCatetory(this.motion, null);
} else {
this.repo.setCatetory(this.motion, id);
}
} }
/** /**
@ -932,7 +936,11 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
* @param id Motion block id * @param id Motion block id
*/ */
public setBlock(id: number): void { public setBlock(id: number): void {
this.repo.setBlock(this.motion, id); if (id === this.motion.motion_block_id) {
this.repo.setBlock(this.motion, null);
} else {
this.repo.setBlock(this.motion, id);
}
} }
/** /**

View File

@ -114,12 +114,10 @@ export class SiteComponent extends BaseComponent implements OnInit {
} }
/** /**
* Closes the sidenav in mobile view * Closes the sidenav
*/ */
public toggleSideNav(): void { public toggleSideNav(): void {
if (this.vp.isMobile) { this.sideNav.toggle();
this.sideNav.toggle();
}
} }
/** /**

View File

@ -318,6 +318,13 @@ mat-panel-title mat-icon {
margin: 8px 8px 8px 0; margin: 8px 8px 8px 0;
} }
.mat-chip-list.user .mat-chip {
border-radius: 16px !important;
padding: 15px !important;
border: solid 1px lightgray;
background: #fff;
}
// to display quantities. Use in span or div // to display quantities. Use in span or div
.os-amount-chip { .os-amount-chip {
border-radius: 50%; border-radius: 50%;
@ -338,6 +345,10 @@ button.mat-menu-item.selected {
font-weight: bold !important; font-weight: bold !important;
} }
.mat-menu-item .mat-icon {
margin-right: 8px !important;
}
.meta-text-block .mat-icon-button { .meta-text-block .mat-icon-button {
margin-top: -12px !important; margin-top: -12px !important;
} }
@ -347,13 +358,16 @@ button.mat-menu-item.selected {
/** helper classes for margin/padding */ /** helper classes for margin/padding */
.spacer-top-10 { .spacer-top-10 {
margin-top: 10px; margin-top: 10px !important;
} }
.spacer-top-20 { .spacer-top-20 {
margin-top: 20px; margin-top: 20px !important;
}
.spacer-bottom-10 {
margin-bottom: 10px !important;
} }
.spacer-bottom-20 { .spacer-bottom-20 {
margin-bottom: 20px; margin-bottom: 20px !important;
} }
.button24 { .button24 {
background-color: white; background-color: white;
@ -378,8 +392,7 @@ button.mat-menu-item.selected {
line-height: 24px; line-height: 24px;
} }
} }
.title-left { .title {
padding-left: 65px;
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
} }
@ -387,6 +400,32 @@ button.mat-menu-item.selected {
padding-right: 20px; padding-right: 20px;
} }
.content-container {
margin: 0 65px;
}
/** media queries */
/* medium */
@media only screen and (min-width: 500px) and (max-width: 960px) {
.content-container {
margin: 0 25px;
}
.content-container h1 {
font-size: 30px
}
}
/* small */
@media only screen and (max-width: 500px) {
.content-container {
margin: 0 15px;
}
.content-container h1 {
font-size: 30px
}
}
/** more helper classes **/ /** more helper classes **/
.center { .center {
text-align: center; text-align: center;