From c234cfe698f215eb8591d9c4583396a7a66d78eb Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Mon, 29 Apr 2019 11:18:40 +0200 Subject: [PATCH] Dynamic a two column layout in motion block slides --- .../motion-block-slide.component.html | 24 +++-- .../motion-block-slide.component.scss | 9 +- .../motion-block-slide.component.ts | 96 +++++++++++++++++-- openslides/motions/projector.py | 7 +- 4 files changed, 113 insertions(+), 23 deletions(-) diff --git a/client/src/app/slides/motions/motion-block/motion-block-slide.component.html b/client/src/app/slides/motions/motion-block/motion-block-slide.component.html index c8c20a481..ef6a614ce 100644 --- a/client/src/app/slides/motions/motion-block/motion-block-slide.component.html +++ b/client/src/app/slides/motions/motion-block/motion-block-slide.component.html @@ -4,14 +4,18 @@

Motion block – {{ data.data.motions.length }} motions

-
-
- {{ getMotionTitle(motion) }} -
-
- - {{ getRecommendationLabel(motion) }} - -
-
+ + + + +
+
+ {{ getMotionTitle(i, j) }} +
+
+ + {{ getRecommendationLabel(i, j) }} + +
+
diff --git a/client/src/app/slides/motions/motion-block/motion-block-slide.component.scss b/client/src/app/slides/motions/motion-block/motion-block-slide.component.scss index df20acc08..bcc603f4c 100644 --- a/client/src/app/slides/motions/motion-block/motion-block-slide.component.scss +++ b/client/src/app/slides/motions/motion-block/motion-block-slide.component.scss @@ -1,4 +1,9 @@ -.blockitem { +table { line-height: 1; - margin-bottom: 10px; + width: 100%; + table-layout: fixed; +} + +td { + min-width: 50%; } diff --git a/client/src/app/slides/motions/motion-block/motion-block-slide.component.ts b/client/src/app/slides/motions/motion-block/motion-block-slide.component.ts index fb2506ec6..c2168abed 100644 --- a/client/src/app/slides/motions/motion-block/motion-block-slide.component.ts +++ b/client/src/app/slides/motions/motion-block/motion-block-slide.component.ts @@ -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) { 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 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 += diff --git a/openslides/motions/projector.py b/openslides/motions/projector.py index 01cb0699d..7625db93e 100644 --- a/openslides/motions/projector.py +++ b/openslides/motions/projector.py @@ -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:] referenced_ids = [ int(id) for id in motion_placeholder_regex.findall(recommendation)