Merge pull request #4573 from CatoTH/OS3-multi-paragraph-amendments
Creating multi-paragraph amendments
This commit is contained in:
commit
58b5ec3f5e
@ -120,6 +120,7 @@ _('Amendments');
|
||||
_('Activate statute amendments');
|
||||
_('Activate amendments');
|
||||
_('Show amendments together with motions');
|
||||
_('Amendments can change multiple paragraphs');
|
||||
_('Prefix for the identifier for amendments');
|
||||
_('The title of the motion is always applied.');
|
||||
_('How to create new amendments');
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
@ -14,7 +15,7 @@ import { DataStoreService } from '../../core-services/data-store.service';
|
||||
import { DiffLinesInParagraph, DiffService, LineRange, ModificationType } from '../../ui-services/diff.service';
|
||||
import { HttpService } from 'app/core/core-services/http.service';
|
||||
import { Item } from 'app/shared/models/agenda/item';
|
||||
import { LinenumberingService } from '../../ui-services/linenumbering.service';
|
||||
import { LinenumberingService, LineNumberRange } from '../../ui-services/linenumbering.service';
|
||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||
import { Motion } from 'app/shared/models/motions/motion';
|
||||
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||
@ -45,6 +46,36 @@ import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
|
||||
type SortProperty = 'callListWeight' | 'identifier';
|
||||
|
||||
/**
|
||||
* Describes the single paragraphs from the base motion.
|
||||
*/
|
||||
export interface ParagraphToChoose {
|
||||
/**
|
||||
* The paragraph number.
|
||||
*/
|
||||
paragraphNo: number;
|
||||
|
||||
/**
|
||||
* The raw HTML of this paragraph.
|
||||
*/
|
||||
rawHtml: string;
|
||||
|
||||
/**
|
||||
* The HTML of this paragraph, wrapped in a `SafeHtml`-object.
|
||||
*/
|
||||
safeHtml: SafeHtml;
|
||||
|
||||
/**
|
||||
* The first line number
|
||||
*/
|
||||
lineFrom: number;
|
||||
|
||||
/**
|
||||
* The last line number
|
||||
*/
|
||||
lineTo: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository Services for motions (and potentially categories)
|
||||
*
|
||||
@ -74,6 +105,7 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
* @param mapperService Maps collection strings to classes
|
||||
* @param dataSend sending changed objects
|
||||
* @param httpService OpenSlides own Http service
|
||||
* @param sanitizer DOM Sanitizer
|
||||
* @param lineNumbering Line numbering for motion text
|
||||
* @param diff Display changes in motion text as diff.
|
||||
* @param personalNoteService service fo personal notes
|
||||
@ -87,6 +119,7 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
translate: TranslateService,
|
||||
config: ConfigService,
|
||||
private httpService: HttpService,
|
||||
private readonly sanitizer: DomSanitizer,
|
||||
private readonly lineNumbering: LinenumberingService,
|
||||
private readonly diff: DiffService,
|
||||
private treeService: TreeService,
|
||||
@ -637,6 +670,25 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
return this.lineNumbering.splitToParagraphs(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data structure used for creating and editing amendments
|
||||
*
|
||||
* @param {ViewMotion} motion
|
||||
* @param {number} lineLength
|
||||
*/
|
||||
public getParagraphsToChoose(motion: ViewMotion, lineLength: number): ParagraphToChoose[] {
|
||||
return this.getTextParagraphs(motion, true, lineLength).map((paragraph: string, index: number) => {
|
||||
const affected: LineNumberRange = this.lineNumbering.getLineNumberRange(paragraph);
|
||||
return {
|
||||
paragraphNo: index,
|
||||
safeHtml: this.sanitizer.bypassSecurityTrustHtml(paragraph),
|
||||
rawHtml: this.lineNumbering.stripLineNumbers(paragraph),
|
||||
lineFrom: affected.from,
|
||||
lineTo: affected.to
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all paragraphs that are affected by the given amendment in diff-format
|
||||
*
|
||||
|
@ -21,7 +21,7 @@ interface BreakablePoint {
|
||||
/**
|
||||
* An object specifying a range of line numbers.
|
||||
*/
|
||||
interface LineNumberRange {
|
||||
export interface LineNumberRange {
|
||||
/**
|
||||
* The first line number to be included.
|
||||
*/
|
||||
|
@ -17,18 +17,24 @@
|
||||
|
||||
<form [formGroup]="contentForm" (ngSubmit)="saveAmendment()" class="on-transition-fade">
|
||||
<mat-horizontal-stepper #matStepper linear>
|
||||
<mat-step [completed]="contentForm.value.selectedParagraph">
|
||||
<ng-template matStepLabel>{{ 'Select paragraph' | translate }}</ng-template>
|
||||
<mat-step [completed]="contentForm.value.selectedParagraphs.length > 0">
|
||||
<ng-template matStepLabel>{{ 'Select paragraphs' | translate }}</ng-template>
|
||||
<div>
|
||||
<section
|
||||
*ngFor="let paragraph of paragraphs"
|
||||
class="paragraph-row"
|
||||
[class.active]="contentForm.value.selectedParagraph === paragraph.paragraphNo"
|
||||
(click)="selectParagraph(paragraph)"
|
||||
[class.active]="isParagraphSelected(paragraph)"
|
||||
(click)="onParagraphClicked(paragraph)"
|
||||
>
|
||||
<mat-radio-button
|
||||
<mat-checkbox
|
||||
*ngIf="multipleParagraphsAllowed"
|
||||
class="paragraph-select"
|
||||
[checked]="contentForm.value.selectedParagraph === paragraph.paragraphNo"
|
||||
[checked]="isParagraphSelected(paragraph)"
|
||||
></mat-checkbox>
|
||||
<mat-radio-button
|
||||
*ngIf="!multipleParagraphsAllowed"
|
||||
class="paragraph-select"
|
||||
[checked]="isParagraphSelected(paragraph)"
|
||||
></mat-radio-button>
|
||||
<div class="paragraph-text motion-text" [innerHTML]="paragraph.safeHtml"></div>
|
||||
</section>
|
||||
@ -37,28 +43,33 @@
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'Change paragraph' | translate }}</ng-template>
|
||||
|
||||
<h3><span translate>Amendment text</span> <span>*</span></h3>
|
||||
|
||||
<!-- Text -->
|
||||
<h3
|
||||
[ngClass]="
|
||||
contentForm.get('text').invalid &&
|
||||
(contentForm.get('text').dirty || contentForm.get('text').touched)
|
||||
? 'red-warning-text'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
<span translate>Amendment text</span> <span>*</span>
|
||||
</h3>
|
||||
<editor formControlName="text" [init]="tinyMceSettings" required></editor>
|
||||
<div
|
||||
*ngIf="
|
||||
contentForm.get('text').invalid &&
|
||||
(contentForm.get('text').dirty || contentForm.get('text').touched)
|
||||
"
|
||||
class="red-warning-text"
|
||||
translate
|
||||
>
|
||||
This field is required.
|
||||
</div>
|
||||
<section *ngFor="let paragraph of contentForm.value.selectedParagraphs">
|
||||
<h4 [class.red-warning-text]="contentForm.get('text_' + paragraph.paragraphNo).invalid && (
|
||||
contentForm.get('text_' + paragraph.paragraphNo).dirty ||
|
||||
contentForm.get('text_' + paragraph.paragraphNo).touched
|
||||
)"
|
||||
>
|
||||
<span *ngIf="paragraph.lineFrom >= paragraph.lineTo - 1" class="line-number">
|
||||
{{ 'Line' | translate }} {{ paragraph.lineFrom }}</span> <span>*</span>
|
||||
<span *ngIf="paragraph.lineFrom < paragraph.lineTo - 1" class="line-number">
|
||||
{{ 'Line' | translate }} {{ paragraph.lineFrom }}
|
||||
- {{ paragraph.lineTo - 1 }}</span> <span>*</span>
|
||||
</h4>
|
||||
<editor [formControlName]="'text_' + paragraph.paragraphNo" [init]="tinyMceSettings" required></editor>
|
||||
<div
|
||||
*ngIf="contentForm.get('text_' + paragraph.paragraphNo).invalid && (
|
||||
contentForm.get('text_' + paragraph.paragraphNo).dirty ||
|
||||
contentForm.get('text_' + paragraph.paragraphNo).touched
|
||||
)"
|
||||
class="red-warning-text"
|
||||
translate
|
||||
>
|
||||
This field is required.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Reason -->
|
||||
<h3
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -9,30 +9,9 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { CreateMotion } from 'app/site/motions/models/create-motion';
|
||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { MotionRepositoryService, ParagraphToChoose } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { ViewMotion } from 'app/site/motions/models/view-motion';
|
||||
|
||||
/**
|
||||
* Describes the single paragraphs from the base motion.
|
||||
*/
|
||||
interface ParagraphToChoose {
|
||||
/**
|
||||
* The paragraph number.
|
||||
*/
|
||||
paragraphNo: number;
|
||||
|
||||
/**
|
||||
* The raw HTML of this paragraph.
|
||||
*/
|
||||
rawHtml: string;
|
||||
|
||||
/**
|
||||
* The HTML of this paragraph, wrapped in a `SafeHtml`-object.
|
||||
*/
|
||||
safeHtml: SafeHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* The wizard used to create a new amendment based on a motion.
|
||||
*/
|
||||
@ -67,6 +46,11 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
*/
|
||||
public reasonRequired: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if an amendment can change multiple paragraphs or only one
|
||||
*/
|
||||
public multipleParagraphsAllowed: boolean;
|
||||
|
||||
/**
|
||||
* Constructs this component.
|
||||
*
|
||||
@ -77,8 +61,6 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
* @param {MotionRepositoryService} repo Motion Repository
|
||||
* @param {ActivatedRoute} route The activated route
|
||||
* @param {Router} router The router
|
||||
* @param {DomSanitizer} sanitizer The DOM Sanitizing library
|
||||
* @param {LinenumberingService} lineNumbering The line numbering service
|
||||
* @param {MatSnackBar} matSnackBar Material Design SnackBar
|
||||
*/
|
||||
public constructor(
|
||||
@ -89,8 +71,6 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
private repo: MotionRepositoryService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private sanitizer: DomSanitizer,
|
||||
private lineNumbering: LinenumberingService,
|
||||
matSnackBar: MatSnackBar
|
||||
) {
|
||||
super(titleService, translate, matSnackBar);
|
||||
@ -104,6 +84,10 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
this.configService.get<boolean>('motions_reason_required').subscribe(required => {
|
||||
this.reasonRequired = required;
|
||||
});
|
||||
|
||||
this.configService.get<boolean>('motions_amendments_multiple_paragraphs').subscribe(allowed => {
|
||||
this.multipleParagraphsAllowed = allowed;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,16 +98,7 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
this.route.params.subscribe(params => {
|
||||
this.repo.getViewModelObservable(params.id).subscribe(newViewMotion => {
|
||||
this.motion = newViewMotion;
|
||||
|
||||
this.paragraphs = this.repo
|
||||
.getTextParagraphs(this.motion, true, this.lineLength)
|
||||
.map((paragraph: string, index: number) => {
|
||||
return {
|
||||
paragraphNo: index,
|
||||
safeHtml: this.sanitizer.bypassSecurityTrustHtml(paragraph),
|
||||
rawHtml: this.lineNumbering.stripLineNumbers(paragraph)
|
||||
};
|
||||
});
|
||||
this.paragraphs = this.repo.getParagraphsToChoose(newViewMotion, this.lineLength);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -133,22 +108,85 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
*/
|
||||
public createForm(): void {
|
||||
this.contentForm = this.formBuilder.group({
|
||||
selectedParagraph: [null, Validators.required],
|
||||
text: ['', Validators.required],
|
||||
selectedParagraphs: [[], Validators.required],
|
||||
reason: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
public isParagraphSelected(paragraph: ParagraphToChoose): boolean {
|
||||
return !!this.contentForm.value.selectedParagraphs.find(para => para.paragraphNo === paragraph.paragraphNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the template when a paragraph is clicked in single paragraph mode.
|
||||
* Behaves like a radio-button
|
||||
*
|
||||
* @param {ParagraphToChoose} paragraph
|
||||
*/
|
||||
public setParagraph(paragraph: ParagraphToChoose): void {
|
||||
this.contentForm.value.selectedParagraphs.forEach(para => {
|
||||
this.contentForm.removeControl('text_' + para.paragraphNo);
|
||||
});
|
||||
this.contentForm.addControl(
|
||||
'text_' + paragraph.paragraphNo,
|
||||
new FormControl(paragraph.rawHtml, Validators.required)
|
||||
);
|
||||
this.contentForm.patchValue({
|
||||
selectedParagraphs: [paragraph]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the template when a paragraph is clicked in multiple paragraph mode.
|
||||
* Behaves like a checkbox
|
||||
*
|
||||
* @param {ParagraphToChoose} paragraph
|
||||
*/
|
||||
public toggleParagraph(paragraph: ParagraphToChoose): void {
|
||||
let newParagraphs: ParagraphToChoose[];
|
||||
const oldSelected: ParagraphToChoose[] = this.contentForm.value.selectedParagraphs;
|
||||
if (this.isParagraphSelected(paragraph)) {
|
||||
newParagraphs = oldSelected.filter(para => para.paragraphNo !== paragraph.paragraphNo);
|
||||
this.contentForm.patchValue({
|
||||
selectedParagraphs: newParagraphs
|
||||
});
|
||||
this.contentForm.removeControl('text_' + paragraph.paragraphNo);
|
||||
} else {
|
||||
newParagraphs = Object.assign([], oldSelected);
|
||||
newParagraphs.push(paragraph);
|
||||
newParagraphs.sort(
|
||||
(para1: ParagraphToChoose, para2: ParagraphToChoose): number => {
|
||||
if (para1.paragraphNo < para2.paragraphNo) {
|
||||
return -1;
|
||||
} else if (para1.paragraphNo > para2.paragraphNo) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.contentForm.addControl(
|
||||
'text_' + paragraph.paragraphNo,
|
||||
new FormControl(paragraph.rawHtml, Validators.required)
|
||||
);
|
||||
this.contentForm.patchValue({
|
||||
selectedParagraphs: newParagraphs
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the template when a paragraph is clicked.
|
||||
*
|
||||
* @param {ParagraphToChoose} paragraph
|
||||
*/
|
||||
public selectParagraph(paragraph: ParagraphToChoose): void {
|
||||
this.contentForm.patchValue({
|
||||
selectedParagraph: paragraph.paragraphNo,
|
||||
text: paragraph.rawHtml
|
||||
});
|
||||
public onParagraphClicked(paragraph: ParagraphToChoose): void {
|
||||
if (this.multipleParagraphsAllowed) {
|
||||
this.toggleParagraph(paragraph);
|
||||
} else {
|
||||
this.setParagraph(paragraph);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,10 +195,12 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async saveAmendment(): Promise<void> {
|
||||
let text = '';
|
||||
const amendedParagraphs = this.paragraphs.map(
|
||||
(paragraph: ParagraphToChoose, index: number): string => {
|
||||
if (index === this.contentForm.value.selectedParagraph) {
|
||||
return this.contentForm.value.text;
|
||||
if (this.contentForm.value.selectedParagraphs.find(para => para.paragraphNo === index)) {
|
||||
text = this.contentForm.value['text_' + index];
|
||||
return this.contentForm.value['text_' + index];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -169,6 +209,7 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
|
||||
const newMotionValues = {
|
||||
...this.contentForm.value,
|
||||
title: this.translate.instant('Amendment to') + ' ' + this.motion.identifier,
|
||||
text: text, // Workaround as 'text' is required from the backend
|
||||
parent_id: this.motion.id,
|
||||
category_id: this.motion.category_id,
|
||||
motion_block_id: this.motion.motion_block_id,
|
||||
|
@ -623,17 +623,43 @@
|
||||
[innerHTML]="getFormattedStatuteAmendment()"
|
||||
></div>
|
||||
|
||||
<!-- The HTML Editor -->
|
||||
<editor formControlName="text" [init]="tinyMceSettings" *ngIf="motion && editMotion" required></editor>
|
||||
<div
|
||||
*ngIf="
|
||||
<!-- The HTML Editor for motions and traditional amendments -->
|
||||
<ng-container *ngIf="motion && editMotion && !motion.isParagraphBasedAmendment()">
|
||||
<editor formControlName="text" [init]="tinyMceSettings" required></editor>
|
||||
<div
|
||||
*ngIf="
|
||||
contentForm.get('text').invalid && (contentForm.get('text').dirty || contentForm.get('text').touched)
|
||||
"
|
||||
class="red-warning-text"
|
||||
translate
|
||||
>
|
||||
This field is required.
|
||||
</div>
|
||||
class="red-warning-text"
|
||||
translate
|
||||
>
|
||||
This field is required.
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- The HTML Editor for paragraph-based amendments -->
|
||||
<ng-container *ngIf="motion && editMotion && motion.isParagraphBasedAmendment()">
|
||||
<section *ngFor="let paragraph of contentForm.value.selected_paragraphs">
|
||||
<h4>
|
||||
<span *ngIf="paragraph.lineFrom >= paragraph.lineTo - 1" class="line-number">
|
||||
{{ 'Line' | translate }} {{ paragraph.lineFrom }}</span>
|
||||
<span *ngIf="paragraph.lineFrom < paragraph.lineTo - 1" class="line-number">
|
||||
{{ 'Line' | translate }} {{ paragraph.lineFrom }} - {{ paragraph.lineTo - 1 }}</span>
|
||||
<span>*</span>
|
||||
</h4>
|
||||
<editor [formControlName]="'text_' + paragraph.paragraphNo" [init]="tinyMceSettings" required></editor>
|
||||
<div
|
||||
*ngIf="contentForm.get('text_' + paragraph.paragraphNo).invalid && (
|
||||
contentForm.get('text_' + paragraph.paragraphNo).dirty ||
|
||||
contentForm.get('text_' + paragraph.paragraphNo).touched
|
||||
)"
|
||||
class="red-warning-text"
|
||||
translate
|
||||
>
|
||||
This field is required.
|
||||
</div>
|
||||
</section>
|
||||
</ng-container>
|
||||
|
||||
<!-- Paragraph-based amendments -->
|
||||
<ng-container *ngIf="!editMotion && motion.isParagraphBasedAmendment()">
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
MotionChangeRecommendationComponent
|
||||
} from '../motion-change-recommendation/motion-change-recommendation.component';
|
||||
import { MotionPdfExportService } from 'app/site/motions/services/motion-pdf-export.service';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { MotionRepositoryService, ParagraphToChoose } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { NotifyService } from 'app/core/core-services/notify.service';
|
||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
import { PersonalNoteService } from 'app/core/ui-services/personal-note.service';
|
||||
@ -645,11 +645,28 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
});
|
||||
|
||||
if (formMotion.isParagraphBasedAmendment()) {
|
||||
contentPatch.text = formMotion.amendment_paragraphs.find(
|
||||
(para: string): boolean => {
|
||||
return para !== null;
|
||||
}
|
||||
);
|
||||
contentPatch.selected_paragraphs = [];
|
||||
const parentMotion = this.repo.getViewModel(formMotion.parent_id);
|
||||
// Hint: lineLength is sometimes not loaded yet when this form is initialized;
|
||||
// This doesn't hurt as long as patchForm is called when editing mode is started, i.e., later.
|
||||
if (parentMotion && this.lineLength) {
|
||||
const paragraphsToChoose = this.repo.getParagraphsToChoose(parentMotion, this.lineLength);
|
||||
|
||||
paragraphsToChoose.forEach(
|
||||
(paragraph: ParagraphToChoose, paragraphNo: number): void => {
|
||||
if (formMotion.amendment_paragraphs[paragraphNo]) {
|
||||
this.contentForm.addControl(
|
||||
'text_' + paragraphNo,
|
||||
new FormControl('', Validators.required)
|
||||
);
|
||||
|
||||
contentPatch.selected_paragraphs.push(paragraph);
|
||||
contentPatch.text = formMotion.amendment_paragraphs[paragraphNo]; // Workaround as 'text' is required from the backend
|
||||
contentPatch['text_' + paragraphNo] = formMotion.amendment_paragraphs[paragraphNo];
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const statuteAmendmentFieldName = 'statute_amendment';
|
||||
@ -681,6 +698,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
supporters_id: [[]],
|
||||
workflow_id: [],
|
||||
origin: [''],
|
||||
selected_paragraphs: [],
|
||||
statute_amendment: [''], // Internal value for the checkbox, not saved to the model
|
||||
statute_paragraph_id: [''],
|
||||
motion_block_id: [], // TODO: Can be removed if this is not required
|
||||
@ -733,11 +751,11 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
const motion = new ctor();
|
||||
if (this.motion.isParagraphBasedAmendment()) {
|
||||
motion.amendment_paragraphs = this.motion.amendment_paragraphs.map(
|
||||
(paragraph: string): string => {
|
||||
(paragraph: string, paragraphNo: number): string => {
|
||||
if (paragraph === null) {
|
||||
return null;
|
||||
} else {
|
||||
return motionValues.text;
|
||||
return motionValues['text_' + paragraphNo];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
File diff suppressed because one or more lines are too long
@ -1708,8 +1708,8 @@ msgstr "Redner/in auswählen oder suchen ..."
|
||||
msgid "Select or search new submitter ..."
|
||||
msgstr "Antragsteller/in auswählen oder suchen ..."
|
||||
|
||||
msgid "Select paragraph"
|
||||
msgstr "Absatz auswählen"
|
||||
msgid "Select paragraphs"
|
||||
msgstr "Absätze auswählen"
|
||||
|
||||
msgid "Selected values"
|
||||
msgstr "Ausgewählte Werte"
|
||||
@ -1786,6 +1786,9 @@ msgstr "Änderungsantrag im Hauptantrag anzeigen"
|
||||
msgid "Show amendments together with motions"
|
||||
msgstr "Änderungsanträge zusätzlich in der Hauptantragsübersicht anzeigen"
|
||||
|
||||
msgid "Amendments can change multiple paragraphs"
|
||||
msgstr "Änderungsanträge können mehrere Absätze ändern"
|
||||
|
||||
msgid "Show clock"
|
||||
msgstr "Uhr anzeigen"
|
||||
|
||||
|
@ -1651,7 +1651,7 @@ msgstr ""
|
||||
msgid "Select or search new submitter ..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Select paragraph"
|
||||
msgid "Select paragraphs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Selected values"
|
||||
@ -1726,7 +1726,10 @@ msgstr ""
|
||||
msgid "Show amendment in parent motoin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show amendments together with motions"
|
||||
msgid "Amendments can change multiple paragraphs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Restrict amendments to only one paragraph"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show clock"
|
||||
|
@ -261,6 +261,16 @@ def get_config_variables():
|
||||
subgroup="Amendments",
|
||||
)
|
||||
|
||||
yield ConfigVariable(
|
||||
name="motions_amendments_multiple_paragraphs",
|
||||
default_value=False,
|
||||
input_type="boolean",
|
||||
label="Amendments can change multiple paragraphs",
|
||||
weight=343,
|
||||
group="Motions",
|
||||
subgroup="Amendments",
|
||||
)
|
||||
|
||||
# Supporters
|
||||
|
||||
yield ConfigVariable(
|
||||
|
Loading…
Reference in New Issue
Block a user