Merge pull request #4648 from FinnStutzenstein/motionBlockSlideTwoColumns

Dynamic a two column layout in motion block slides
This commit is contained in:
Emanuel Schütze 2019-04-30 16:38:58 +02:00 committed by GitHub
commit 9f5226c1d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 23 deletions

View File

@ -4,14 +4,18 @@
<h2><span translate>Motion block</span> {{ data.data.motions.length }} <span translate>motions</span></h2>
</div>
<div *ngFor="let motion of data.data.motions" class="blockitem">
<div class="ellipsis-overflow">
{{ getMotionTitle(motion) }}
</div>
<div class="white ellipsis-overflow">
<mat-basic-chip *ngIf="motion.recommendation" disableRipple [ngClass]="getStateCssColor(motion)" class="block-recommendation">
{{ getRecommendationLabel(motion) }}
</mat-basic-chip>
</div>
</div>
<table>
<tr *ngFor="let i of rowsArray">
<td *ngFor="let j of columnsArray">
<div class="ellipsis-overflow">
{{ getMotionTitle(i, j) }}
</div>
<div class="white"><!-- ellipsis-overflow?? -->
<mat-basic-chip *ngIf="hasRecommendation(i, j)" disableRipple [ngClass]="getStateCssColor(i, j)" class="block-recommendation">
{{ getRecommendationLabel(i, j) }}
</mat-basic-chip>
</div>
</td>
</tr>
</table>
</div>

View File

@ -1,4 +1,9 @@
.blockitem {
table {
line-height: 1;
margin-bottom: 10px;
width: 100%;
table-layout: fixed;
}
td {
min-width: 50%;
}

View File

@ -5,9 +5,14 @@ import { TranslateService } from '@ngx-translate/core';
import { MotionBlockSlideData, MotionBlockSlideMotionRepresentation } from './motion-block-slide-data';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { StateCssClassMapping } from 'app/site/motions/models/view-workflow';
import { BaseMotionSlideComponent, MotionTitleInformation } from '../base/base-motion-slide';
import { BaseMotionSlideComponent } from '../base/base-motion-slide';
import { SlideData } from 'app/core/core-services/projector-data.service';
/**
* The row threshold to switch from one to a two column layout
*/
const TWO_COLUMNS_THRESHOLD = 8;
@Component({
selector: 'os-motion-block-slide',
templateUrl: './motion-block-slide.component.html',
@ -28,7 +33,10 @@ export class MotionBlockSlideComponent extends BaseMotionSlideComponent<MotionBl
public set data(data: SlideData<MotionBlockSlideData>) {
if (data && data.data.motions) {
data.data.motions = data.data.motions.sort((a, b) =>
this.languageCollator.compare(this.getMotionIdentifier(a), this.getMotionIdentifier(b))
this.languageCollator.compare(
this.motionRepo.getIdentifierOrTitle(a),
this.motionRepo.getIdentifierOrTitle(b)
)
);
}
this._data = data;
@ -38,30 +46,100 @@ export class MotionBlockSlideComponent extends BaseMotionSlideComponent<MotionBl
return this._data;
}
/**
* @returns the amount of motions in this block
*/
public get motionsAmount(): number {
if (this.data && this.data.data.motions) {
return this.data.data.motions.length;
} else {
return 0;
}
}
/**
* @returns the amount of rows to display.
*/
public get rows(): number {
let rows = this.motionsAmount;
if (this.motionsAmount > TWO_COLUMNS_THRESHOLD) {
rows = Math.ceil(rows / 2);
}
return rows;
}
/**
* @returns an aray with [1, ..., this.rows]
*/
public get rowsArray(): number[] {
const indices = [];
const rows = this.rows;
for (let i = 0; i < rows; i++) {
indices.push(i);
}
return indices;
}
/**
* @returns [0] or [0, 1] if one or two columns are used
*/
public get columnsArray(): number[] {
if (this.motionsAmount > TWO_COLUMNS_THRESHOLD) {
return [0, 1];
} else {
return [0];
}
}
public constructor(translate: TranslateService, motionRepo: MotionRepositoryService) {
super(translate, motionRepo);
this.languageCollator = new Intl.Collator(this.translate.currentLang);
}
/**
* Get the motion for the cell given by i and j
*
* @param i the row
* @param j the column
*/
private getMotion(i: number, j: number): MotionBlockSlideMotionRepresentation {
const index = i + this.rows * j;
return this.data.data.motions[index];
}
/**
* @returns the title of the given motion.
*/
public getMotionTitle(motion: MotionTitleInformation): string {
return this.motionRepo.getTitle(motion);
public getMotionTitle(i: number, j: number): string {
return this.motionRepo.getTitle(this.getMotion(i, j));
}
/**
* @returns the identifier (of title if identifier not availabe) of the given motion.
*/
public getMotionIdentifier(motion: MotionTitleInformation): string {
return this.motionRepo.getIdentifierOrTitle(motion);
public getMotionIdentifier(i: number, j: number): string {
return this.motionRepo.getIdentifierOrTitle(this.getMotion(i, j));
}
public getStateCssColor(motion: MotionBlockSlideMotionRepresentation): string {
return StateCssClassMapping[motion.recommendation.css_class] || '';
/**
* @returns true if the motion in cell i and j has a recommendation
*/
public hasRecommendation(i: number, j: number): boolean {
return !!this.getMotion(i, j).recommendation;
}
public getRecommendationLabel(motion: MotionBlockSlideMotionRepresentation): string {
/**
* @returns the css color for the state of the motion in cell i and j
*/
public getStateCssColor(i: number, j: number): string {
return StateCssClassMapping[this.getMotion(i, j).recommendation.css_class] || '';
}
/**
* @returns the recommendation label for motion in cell i and j
*/
public getRecommendationLabel(i: number, j: number): string {
const motion = this.getMotion(i, j);
let recommendation = this.translate.instant(motion.recommendation.name);
if (motion.recommendation_extension) {
recommendation +=

View File

@ -1,5 +1,5 @@
import re
from typing import Any, Dict
from typing import Any, Dict, Optional
from ..users.projector import get_user_name
from ..utils.projector import (
@ -121,13 +121,16 @@ async def get_amendment_base_statute(amendment, all_data):
async def extend_reference_motion_dict(
all_data: AllData,
recommendation: str,
recommendation: Optional[str],
referenced_motions: Dict[int, Dict[str, str]],
) -> None:
"""
Extends a dict of motion ids mapped to their title information.
The client can replace the placeholders in the recommendation correctly.
"""
if recommendation is None:
return
# Collect all meantioned motions via [motion:<id>]
referenced_ids = [
int(id) for id in motion_placeholder_regex.findall(recommendation)