Merge pull request #4380 from FinnStutzenstein/motionBlockSlide

Motion block slide
This commit is contained in:
Emanuel Schütze 2019-02-21 15:23:42 +01:00 committed by GitHub
commit c0cd3bc252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 267 additions and 88 deletions

View File

@ -3,7 +3,7 @@
[ngClass]="isProjected() ? 'projector-active' : 'projector-inactive'"> [ngClass]="isProjected() ? 'projector-active' : 'projector-inactive'">
<mat-icon>videocam</mat-icon> <mat-icon>videocam</mat-icon>
</button> </button>
<button type="button" *ngIf="menuItem" mat-menu-item (click)="onClick($event)" <button type="button" *ngIf="menuItem" mat-menu-item (click)="onClick()"
[ngClass]="isProjected() ? 'projector-active' : 'projector-inactive'"> [ngClass]="isProjected() ? 'projector-active' : 'projector-inactive'">
<mat-icon>videocam</mat-icon> <mat-icon>videocam</mat-icon>
<span translate>Project</span> <span translate>Project</span>

View File

@ -63,8 +63,10 @@ export class ProjectorButtonComponent implements OnInit {
* *
* @param event the click event * @param event the click event
*/ */
public onClick(event: Event): void { public onClick(event?: Event): void {
event.stopPropagation(); if (event) {
event.stopPropagation();
}
if (this.object) { if (this.object) {
this.projectionDialogService.openProjectDialogFor(this.object); this.projectionDialogService.openProjectDialogFor(this.object);
} }

View File

@ -21,7 +21,7 @@
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
margin-bottom: 20px; margin-bottom: 20px;
z-index: 1; z-index: 9;
.projector-logo-main { .projector-logo-main {
height: 50px; height: 50px;
@ -59,7 +59,7 @@
width: 100%; width: 100%;
height: 35px; height: 35px;
bottom: 0; bottom: 0;
z-index: 1; z-index: 9;
.footertext { .footertext {
font-size: 16px; font-size: 16px;

View File

@ -104,10 +104,8 @@
<span translate>List of speakers</span> <span translate>List of speakers</span>
</button> </button>
<button mat-menu-item *osPerms="'core.can_manage_projector'"> <os-projector-button *ngIf="block" [object]="block" [menuItem]="true"></os-projector-button>
<mat-icon>videocam</mat-icon>
<span translate>Project</span>
</button>
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']"> <div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
<button mat-menu-item (click)="toggleEditMode()"> <button mat-menu-item (click)="toggleEditMode()">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>

View File

@ -52,6 +52,14 @@
<!-- Table --> <!-- Table -->
<mat-card class="os-card"> <mat-card class="os-card">
<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>
<!-- Projector column -->
<ng-container matColumnDef="projector">
<mat-header-cell *matHeaderCellDef mat-sort-header>Projector</mat-header-cell>
<mat-cell *matCellDef="let block">
<os-projector-button [object]="block"></os-projector-button>
</mat-cell>
</ng-container>
<!-- title column --> <!-- title column -->
<ng-container matColumnDef="title"> <ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef mat-sort-header> <span translate>Title</span> </mat-header-cell> <mat-header-cell *matHeaderCellDef mat-sort-header> <span translate>Title</span> </mat-header-cell>

View File

@ -122,7 +122,11 @@ 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', 'menu']; let columns = ['title', 'amount', 'menu'];
if (this.operator.hasPerms('core.can_manage_projector')) {
columns = ['projector'].concat(columns);
}
return columns;
} }
/** /**

View File

@ -41,7 +41,7 @@ import { LinenumberingService } from 'app/core/ui-services/linenumbering.service
import { Tag } from 'app/shared/models/core/tag'; import { Tag } from 'app/shared/models/core/tag';
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service'; import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
import { ViewMotionBlock } from '../../models/view-motion-block'; import { ViewMotionBlock } from '../../models/view-motion-block';
import { ViewWorkflow } from '../../models/view-workflow'; import { ViewWorkflow, StateCssClassMapping } from '../../models/view-workflow';
import { ViewUser } from 'app/site/users/models/view-user'; import { ViewUser } from 'app/site/users/models/view-user';
import { ViewCategory } from '../../models/view-category'; import { ViewCategory } from '../../models/view-category';
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
@ -1280,17 +1280,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
return ''; return '';
} }
switch (this.motion.state.css_class) { return StateCssClassMapping[this.motion.state.css_class] || '';
case 'success':
return 'green';
case 'danger':
return 'red';
case 'default':
return 'grey';
case 'primary':
return 'lightblue';
default:
return '';
}
} }
} }

View File

@ -41,7 +41,7 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion, Motio
/** /**
* Columns to display in table when desktop view is available * Columns to display in table when desktop view is available
*/ */
public displayedColumnsDesktop: string[] = ['identifier', 'title', 'state', 'speakers']; public displayedColumnsDesktop: string[] = ['identifier', 'title', 'state'];
/** /**
* Columns to display in table when mobile view is available * Columns to display in table when mobile view is available
@ -237,6 +237,9 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion, Motio
if (this.isMultiSelect) { if (this.isMultiSelect) {
columns = ['selector'].concat(columns); columns = ['selector'].concat(columns);
} }
if (this.operator.hasPerms('agenda.can_see')) {
columns = columns.concat(['speakers']);
}
return columns; return columns;
} }

View File

@ -82,6 +82,15 @@ export class ViewMotionBlock extends BaseAgendaViewModel implements Searchable {
}; };
public getSlide(): ProjectorElementBuildDeskriptor { public getSlide(): ProjectorElementBuildDeskriptor {
throw new Error('todo'); return {
getBasicProjectorElement: options => ({
name: MotionBlock.COLLECTIONSTRING,
id: this.id,
getIdentifiers: () => ['name', 'id']
}),
slideOptions: [],
projectionDefaultName: 'motionBlocks',
getDialogTitle: () => this.getTitle()
};
} }
} }

View File

@ -2,6 +2,13 @@ import { Workflow } from 'app/shared/models/motions/workflow';
import { WorkflowState } from 'app/shared/models/motions/workflow-state'; import { WorkflowState } from 'app/shared/models/motions/workflow-state';
import { BaseViewModel } from '../../base/base-view-model'; import { BaseViewModel } from '../../base/base-view-model';
export const StateCssClassMapping = {
success: 'green',
danger: 'red',
default: 'grey',
primary: 'lightblue'
};
/** /**
* class for the ViewWorkflow. * class for the ViewWorkflow.
* @ignore * @ignore

View File

@ -15,6 +15,11 @@ export const allSlidesDynamicConfiguration: (SlideDynamicConfiguration & Slide)[
scaleable: true, scaleable: true,
scrollable: true scrollable: true
}, },
{
slide: 'motions/motion-block',
scaleable: true,
scrollable: true
},
{ {
slide: 'users/user', slide: 'users/user',
scaleable: true, scaleable: true,

View File

@ -19,11 +19,19 @@ export const allSlides: SlideManifest[] = [
{ {
slide: 'motions/motion', slide: 'motions/motion',
path: 'motions/motion', path: 'motions/motion',
loadChildren: './slides/motions/motion/motions-motion-slide.module#MotionsMotionSlideModule', loadChildren: './slides/motions/motion/motion-slide.module#MotionSlideModule',
verboseName: 'Motion', verboseName: 'Motion',
elementIdentifiers: ['name', 'id'], elementIdentifiers: ['name', 'id'],
canBeMappedToModel: true canBeMappedToModel: true
}, },
{
slide: 'motions/motion-block',
path: 'motions/motion-block',
loadChildren: './slides/motions/motion-block/motion-block-slide.module#MotionBlockSlideModule',
verboseName: 'Motion block',
elementIdentifiers: ['name', 'id'],
canBeMappedToModel: true
},
{ {
slide: 'users/user', slide: 'users/user',
path: 'users/user', path: 'users/user',

View File

@ -0,0 +1,14 @@
export interface MotionBlockSlideMotionRepresentation {
title: string;
identifier?: string;
recommendation?: {
name: string;
css_class: string;
};
recommendation_extension?: string;
}
export interface MotionBlockSlideData {
title: string;
motions: MotionBlockSlideMotionRepresentation[];
}

View File

@ -0,0 +1,17 @@
<div *ngIf="data">
<div class="slidetitle">
<h1>{{ data.data.title }}</h1>
<h2><span translate>Motion block</span> {{ data.data.motions.length }} <span translate>motions</span></h2>
</div>
<div *ngFor="let motion of data.data.motions">
<div class="ellipsis-overflow">
{{ motion.identifier }}: {{ motion.title }}
</div>
<div class="white ellipsis-overflow">
<mat-basic-chip *ngIf="motion.recommendation" disableRipple [ngClass]="getStateCssColor(motion)">
{{ getRecommendationLabel(motion) }}
</mat-basic-chip>
</div>
</div>
</div>

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MotionBlockSlideComponent } from './motion-block-slide.component';
import { E2EImportsModule } from '../../../../e2e-imports.module';
describe('MotionBlockSlideComponent', () => {
let component: MotionBlockSlideComponent;
let fixture: ComponentFixture<MotionBlockSlideComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [E2EImportsModule],
declarations: [MotionBlockSlideComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MotionBlockSlideComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,35 @@
import { Component } from '@angular/core';
import { BaseSlideComponent } from 'app/slides/base-slide-component';
import { MotionBlockSlideData, MotionBlockSlideMotionRepresentation } from './motion-block-slide-data';
import { Motion } from 'app/shared/models/motions/motion';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { StateCssClassMapping } from 'app/site/motions/models/view-workflow';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'os-motion-block-slide',
templateUrl: './motion-block-slide.component.html',
styleUrls: ['./motion-block-slide.component.scss']
})
export class MotionBlockSlideComponent extends BaseSlideComponent<MotionBlockSlideData> {
public constructor(private motionRepo: MotionRepositoryService, private translate: TranslateService) {
super();
}
public getMotionTitle(motion: Partial<Motion>): string {
return this.motionRepo.getAgendaTitle(motion);
}
public getStateCssColor(motion: MotionBlockSlideMotionRepresentation): string {
return StateCssClassMapping[motion.recommendation.css_class] || '';
}
public getRecommendationLabel(motion: MotionBlockSlideMotionRepresentation): string {
let recommendation = this.translate.instant(motion.recommendation.name);
if (motion.recommendation_extension) {
recommendation += ' ' + this.motionRepo.solveExtensionPlaceHolder(motion.recommendation_extension);
}
return recommendation;
}
}

View File

@ -0,0 +1,13 @@
import { MotionBlockSlideModule } from './motion-block-slide.module';
describe('MotionBlockSlideModule', () => {
let motionBlockSlideModule: MotionBlockSlideModule;
beforeEach(() => {
motionBlockSlideModule = new MotionBlockSlideModule();
});
it('should create an instance', () => {
expect(motionBlockSlideModule).toBeTruthy();
});
});

View File

@ -0,0 +1,7 @@
import { NgModule } from '@angular/core';
import { makeSlideModule } from 'app/slides/base-slide-module';
import { MotionBlockSlideComponent } from './motion-block-slide.component';
@NgModule(makeSlideModule(MotionBlockSlideComponent))
export class MotionBlockSlideModule {}

View File

@ -5,7 +5,7 @@ import { MergeAmendment } from '../../../shared/models/motions/workflow-state';
* This interface describes the data returned by the server about an amendment. * This interface describes the data returned by the server about an amendment.
* This object is used if actually the motion is shown and the amendment is shown in the context of the motion. * This object is used if actually the motion is shown and the amendment is shown in the context of the motion.
*/ */
export interface MotionsMotionSlideDataAmendment { export interface MotionSlideDataAmendment {
id: number; id: number;
title: string; title: string;
amendment_paragraphs: string[]; amendment_paragraphs: string[];
@ -16,7 +16,7 @@ export interface MotionsMotionSlideDataAmendment {
* This interface describes the data returned by the server about a motion that is changed by an amendment. * This interface describes the data returned by the server about a motion that is changed by an amendment.
* It only contains the data necessary for rendering the amendment's diff. * It only contains the data necessary for rendering the amendment's diff.
*/ */
export interface MotionsMotionSlideDataBaseMotion { export interface MotionSlideDataBaseMotion {
identifier: string; identifier: string;
title: string; title: string;
text: string; text: string;
@ -26,7 +26,7 @@ export interface MotionsMotionSlideDataBaseMotion {
* This interface describes the data returned by the server about a statute paragraph that is changed by an amendment. * This interface describes the data returned by the server about a statute paragraph that is changed by an amendment.
* It only contains the data necessary for rendering the amendment's diff. * It only contains the data necessary for rendering the amendment's diff.
*/ */
export interface MotionsMotionSlideDataBaseStatute { export interface MotionSlideDataBaseStatute {
title: string; title: string;
text: string; text: string;
} }
@ -34,7 +34,7 @@ export interface MotionsMotionSlideDataBaseStatute {
/** /**
* This interface describes the data returned by the server about a change recommendation. * This interface describes the data returned by the server about a change recommendation.
*/ */
export interface MotionsMotionSlideDataChangeReco { export interface MotionSlideDataChangeReco {
creation_time: string; creation_time: string;
id: number; id: number;
internal: boolean; internal: boolean;
@ -53,7 +53,7 @@ export interface MotionsMotionSlideDataChangeReco {
* This interface describes either an motion (with all amendments and change recommendations enbedded) * This interface describes either an motion (with all amendments and change recommendations enbedded)
* or an amendment (with the bas motion embedded). * or an amendment (with the bas motion embedded).
*/ */
export interface MotionsMotionSlideData { export interface MotionSlideData {
identifier: string; identifier: string;
title: string; title: string;
preamble: string; preamble: string;
@ -65,11 +65,11 @@ export interface MotionsMotionSlideData {
recommender?: string; recommender?: string;
recommendation?: string; recommendation?: string;
recommendation_extension?: string; recommendation_extension?: string;
base_motion?: MotionsMotionSlideDataBaseMotion; base_motion?: MotionSlideDataBaseMotion;
base_statute?: MotionsMotionSlideDataBaseStatute; base_statute?: MotionSlideDataBaseStatute;
amendment_paragraphs: string[]; amendment_paragraphs: string[];
change_recommendations: MotionsMotionSlideDataChangeReco[]; change_recommendations: MotionSlideDataChangeReco[];
amendments: MotionsMotionSlideDataAmendment[]; amendments: MotionSlideDataAmendment[];
modified_final_version?: string; modified_final_version?: string;
line_length: number; line_length: number;
line_numbering_mode: LineNumberingMode; line_numbering_mode: LineNumberingMode;

View File

@ -1,5 +1,5 @@
import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change'; import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change';
import { MotionsMotionSlideDataAmendment } from './motions-motion-slide-data'; import { MotionSlideDataAmendment } from './motion-slide-data';
import { MergeAmendment } from '../../../shared/models/motions/workflow-state'; import { MergeAmendment } from '../../../shared/models/motions/workflow-state';
import { LineRange } from '../../../core/ui-services/diff.service'; import { LineRange } from '../../../core/ui-services/diff.service';
@ -7,13 +7,13 @@ import { LineRange } from '../../../core/ui-services/diff.service';
* This class adds methods to the MotionsMotionSlideDataChangeReco data object * This class adds methods to the MotionsMotionSlideDataChangeReco data object
* necessary for use it as a UnifiedChange in the Diff-Functions * necessary for use it as a UnifiedChange in the Diff-Functions
*/ */
export class MotionsMotionSlideObjAmendmentParagraph implements ViewUnifiedChange { export class MotionSlideObjAmendmentParagraph implements ViewUnifiedChange {
public id: number; public id: number;
public type: number; public type: number;
public merge_amendment_into_final: MergeAmendment; public merge_amendment_into_final: MergeAmendment;
public constructor( public constructor(
data: MotionsMotionSlideDataAmendment, data: MotionSlideDataAmendment,
private paragraphNo: number, private paragraphNo: number,
private newText: string, private newText: string,
private lineRange: LineRange private lineRange: LineRange

View File

@ -1,11 +1,11 @@
import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change'; import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change';
import { MotionsMotionSlideDataChangeReco } from './motions-motion-slide-data'; import { MotionSlideDataChangeReco } from './motion-slide-data';
/** /**
* This class adds methods to the MotionsMotionSlideDataChangeReco data object * This class adds methods to the MotionsMotionSlideDataChangeReco data object
* necessary for use it as a UnifiedChange in the Diff-Functions * necessary for use it as a UnifiedChange in the Diff-Functions
*/ */
export class MotionsMotionSlideObjChangeReco implements MotionsMotionSlideDataChangeReco, ViewUnifiedChange { export class MotionSlideObjChangeReco implements MotionSlideDataChangeReco, ViewUnifiedChange {
public creation_time: string; public creation_time: string;
public id: number; public id: number;
public internal: boolean; public internal: boolean;
@ -17,7 +17,7 @@ export class MotionsMotionSlideObjChangeReco implements MotionsMotionSlideDataCh
public text: string; public text: string;
public type: number; public type: number;
public constructor(data: MotionsMotionSlideDataChangeReco) { public constructor(data: MotionSlideDataChangeReco) {
Object.assign(this, data); Object.assign(this, data);
} }

View File

@ -1,21 +1,21 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MotionsMotionSlideComponent } from './motions-motion-slide.component'; import { MotionSlideComponent } from './motion-slide.component';
import { E2EImportsModule } from '../../../../e2e-imports.module'; import { E2EImportsModule } from '../../../../e2e-imports.module';
describe('MotionsMotionSlideComponent', () => { describe('MotionsMotionSlideComponent', () => {
let component: MotionsMotionSlideComponent; let component: MotionSlideComponent;
let fixture: ComponentFixture<MotionsMotionSlideComponent>; let fixture: ComponentFixture<MotionSlideComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule],
declarations: [MotionsMotionSlideComponent] declarations: [MotionSlideComponent]
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(MotionsMotionSlideComponent); fixture = TestBed.createComponent(MotionSlideComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -2,21 +2,21 @@ import { Component, Input } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { BaseSlideComponent } from 'app/slides/base-slide-component'; import { BaseSlideComponent } from 'app/slides/base-slide-component';
import { MotionsMotionSlideData, MotionsMotionSlideDataAmendment } from './motions-motion-slide-data'; import { MotionSlideData, MotionSlideDataAmendment } from './motion-slide-data';
import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion'; import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion';
import { DiffLinesInParagraph, DiffService, LineRange } from '../../../core/ui-services/diff.service'; import { DiffLinesInParagraph, DiffService, LineRange } from '../../../core/ui-services/diff.service';
import { LinenumberingService } from '../../../core/ui-services/linenumbering.service'; import { LinenumberingService } from '../../../core/ui-services/linenumbering.service';
import { ViewUnifiedChange } from '../../../shared/models/motions/view-unified-change'; import { ViewUnifiedChange } from '../../../shared/models/motions/view-unified-change';
import { MotionsMotionSlideObjChangeReco } from './motions-motion-slide-obj-change-reco'; import { MotionSlideObjChangeReco } from './motion-slide-obj-change-reco';
import { SlideData } from '../../../site/projector/services/projector-data.service'; import { SlideData } from '../../../site/projector/services/projector-data.service';
import { MotionsMotionSlideObjAmendmentParagraph } from './motions-motion-slide-obj-amendment-paragraph'; import { MotionSlideObjAmendmentParagraph } from './motion-slide-obj-amendment-paragraph';
@Component({ @Component({
selector: 'os-motions-motion-slide', selector: 'os-motion-slide',
templateUrl: './motions-motion-slide.component.html', templateUrl: './motion-slide.component.html',
styleUrls: ['./motions-motion-slide.component.scss'] styleUrls: ['./motion-slide.component.scss']
}) })
export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotionSlideData> { export class MotionSlideComponent extends BaseSlideComponent<MotionSlideData> {
/** /**
* Indicates the LineNumberingMode Mode. * Indicates the LineNumberingMode Mode.
*/ */
@ -48,10 +48,10 @@ export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotio
*/ */
public allChangingObjects: ViewUnifiedChange[]; public allChangingObjects: ViewUnifiedChange[];
private _data: SlideData<MotionsMotionSlideData>; private _data: SlideData<MotionSlideData>;
@Input() @Input()
public set data(value: SlideData<MotionsMotionSlideData>) { public set data(value: SlideData<MotionSlideData>) {
this._data = value; this._data = value;
this.lnMode = value.data.line_numbering_mode; this.lnMode = value.data.line_numbering_mode;
this.lineLength = value.data.line_length; this.lineLength = value.data.line_length;
@ -62,7 +62,7 @@ export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotio
this.recalcUnifiedChanges(); this.recalcUnifiedChanges();
} }
public get data(): SlideData<MotionsMotionSlideData> { public get data(): SlideData<MotionSlideData> {
return this._data; return this._data;
} }
@ -77,19 +77,17 @@ export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotio
/** /**
* Returns all paragraphs that are affected by the given amendment as unified change objects. * Returns all paragraphs that are affected by the given amendment as unified change objects.
* *
* @param {MotionsMotionSlideDataAmendment} amendment * @param {MotionSlideDataAmendment} amendment
* @returns {MotionsMotionSlideObjAmendmentParagraph[]} * @returns {MotionSlideObjAmendmentParagraph[]}
*/ */
public getAmendmentAmendedParagraphs( public getAmendmentAmendedParagraphs(amendment: MotionSlideDataAmendment): MotionSlideObjAmendmentParagraph[] {
amendment: MotionsMotionSlideDataAmendment
): MotionsMotionSlideObjAmendmentParagraph[] {
let baseHtml = this.data.data.text; let baseHtml = this.data.data.text;
baseHtml = this.lineNumbering.insertLineNumbers(baseHtml, this.lineLength); baseHtml = this.lineNumbering.insertLineNumbers(baseHtml, this.lineLength);
const baseParagraphs = this.lineNumbering.splitToParagraphs(baseHtml); const baseParagraphs = this.lineNumbering.splitToParagraphs(baseHtml);
return amendment.amendment_paragraphs return amendment.amendment_paragraphs
.map( .map(
(newText: string, paraNo: number): MotionsMotionSlideObjAmendmentParagraph => { (newText: string, paraNo: number): MotionSlideObjAmendmentParagraph => {
if (newText === null) { if (newText === null) {
return null; return null;
} }
@ -114,10 +112,10 @@ export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotio
this.diff.extractRangeByLineNumbers(newTextLines, affectedLines.from, affectedLines.to) this.diff.extractRangeByLineNumbers(newTextLines, affectedLines.from, affectedLines.to)
); );
return new MotionsMotionSlideObjAmendmentParagraph(amendment, paraNo, newTextLines, affectedLines); return new MotionSlideObjAmendmentParagraph(amendment, paraNo, newTextLines, affectedLines);
} }
) )
.filter((para: MotionsMotionSlideObjAmendmentParagraph) => para !== null); .filter((para: MotionSlideObjAmendmentParagraph) => para !== null);
} }
/** /**
@ -129,7 +127,7 @@ export class MotionsMotionSlideComponent extends BaseSlideComponent<MotionsMotio
if (this.data.data.change_recommendations) { if (this.data.data.change_recommendations) {
this.data.data.change_recommendations.forEach(change => { this.data.data.change_recommendations.forEach(change => {
this.allChangingObjects.push(new MotionsMotionSlideObjChangeReco(change)); this.allChangingObjects.push(new MotionSlideObjChangeReco(change));
}); });
} }
if (this.data.data.amendments) { if (this.data.data.amendments) {

View File

@ -0,0 +1,13 @@
import { MotionSlideModule } from './motion-slide.module';
describe('MotionSlideModule', () => {
let motionSlideModule: MotionSlideModule;
beforeEach(() => {
motionSlideModule = new MotionSlideModule();
});
it('should create an instance', () => {
expect(motionSlideModule).toBeTruthy();
});
});

View File

@ -0,0 +1,7 @@
import { NgModule } from '@angular/core';
import { MotionSlideComponent } from './motion-slide.component';
import { makeSlideModule } from 'app/slides/base-slide-module';
@NgModule(makeSlideModule(MotionSlideComponent))
export class MotionSlideModule {}

View File

@ -1,13 +0,0 @@
import { MotionsMotionSlideModule } from './motions-motion-slide.module';
describe('MotionsMotionSlideModule', () => {
let motionsMotionSlideModule: MotionsMotionSlideModule;
beforeEach(() => {
motionsMotionSlideModule = new MotionsMotionSlideModule();
});
it('should create an instance', () => {
expect(motionsMotionSlideModule).toBeTruthy();
});
});

View File

@ -1,7 +0,0 @@
import { NgModule } from '@angular/core';
import { MotionsMotionSlideComponent } from './motions-motion-slide.component';
import { makeSlideModule } from 'app/slides/base-slide-module';
@NgModule(makeSlideModule(MotionsMotionSlideComponent))
export class MotionsMotionSlideModule {}

View File

@ -617,7 +617,7 @@ button.mat-menu-item.selected {
margin-bottom: 40px; margin-bottom: 40px;
h1 { h1 {
font-size: 2em; font-size: 1.8em;
line-height: 1.1em; line-height: 1.1em;
margin-bottom: 0; margin-bottom: 0;
padding-bottom: 0; padding-bottom: 0;

View File

@ -206,9 +206,45 @@ def motion_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
def motion_block_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]: def motion_block_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
""" """
Motion slide. Motion block slide.
""" """
return {"error": "TODO"} motion_block_id = element.get("id")
if motion_block_id is None:
raise ProjectorElementException("id is required for motion block slide")
try:
motion_block = all_data["motions/motion-block"][motion_block_id]
except KeyError:
raise ProjectorElementException(
f"motion block with id {motion_block_id} does not exist"
)
motions = []
for motion in all_data["motions/motion"].values():
if motion["motion_block_id"] == motion_block_id:
motion_object = {
"title": motion["title"],
"identifier": motion["identifier"],
}
recommendation_id = motion["recommendation_id"]
if recommendation_id is not None:
recommendation = get_state(
all_data, motion, motion["recommendation_id"]
)
motion_object["recommendation"] = {
"name": recommendation["recommendation_label"],
"css_class": recommendation["css_class"],
}
if recommendation["show_recommendation_extension_field"]:
motion_object["recommendation_extension"] = motion[
"recommendation_extension"
]
motions.append(motion_object)
return {"title": motion_block["title"], "motions": motions}
def register_projector_slides() -> None: def register_projector_slides() -> None: