Replace recommendation on client and server for motion slide
This commit is contained in:
parent
4fedae63a8
commit
ed4b1c80f1
41
client/src/app/slides/motions/base/base-motion-slide.ts
Normal file
41
client/src/app/slides/motions/base/base-motion-slide.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { MotionTitleInformation } from '../motion-block/motion-block-slide-data';
|
||||
|
||||
/**
|
||||
* Format for referenced motions: A mapping of motion ids to their title information.
|
||||
*/
|
||||
export interface ReferencedMotions {
|
||||
[id: number]: MotionTitleInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base slide for motions and motion blocks. This Provides the functionality of
|
||||
* replacing referenced motions (format: `[motion:<id>]`) in strings.
|
||||
*/
|
||||
export class BaseMotionSlideComponent<T extends object> extends BaseSlideComponent<T> {
|
||||
public constructor(protected translate: TranslateService, protected motionRepo: MotionRepositoryService) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all motion placeholders with the motion titles or `<unknown motion>` if the
|
||||
* referenced motion doe snot exist.
|
||||
*
|
||||
* @param text the text to replace
|
||||
* @param referencedMotions an object holding the title information for all referenced motions
|
||||
* @returns the new string
|
||||
*/
|
||||
public replaceReferencedMotions(text: string, referencedMotions: ReferencedMotions): string {
|
||||
return text.replace(/\[motion:(\d+)\]/g, (match, id) => {
|
||||
const titleInformation = referencedMotions[id];
|
||||
if (titleInformation) {
|
||||
return this.motionRepo.getIdentifierOrTitle(titleInformation);
|
||||
} else {
|
||||
return this.translate.instant('<unknown motion>');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import { ReferencedMotions } from '../base/base-motion-slide';
|
||||
|
||||
export interface MotionTitleInformation {
|
||||
title: string;
|
||||
identifier?: string;
|
||||
@ -14,5 +16,5 @@ export interface MotionBlockSlideMotionRepresentation extends MotionTitleInforma
|
||||
export interface MotionBlockSlideData {
|
||||
title: string;
|
||||
motions: MotionBlockSlideMotionRepresentation[];
|
||||
referenced_motions: { [id: number]: MotionTitleInformation };
|
||||
referenced_motions: ReferencedMotions;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||
import {
|
||||
MotionBlockSlideData,
|
||||
MotionBlockSlideMotionRepresentation,
|
||||
@ -9,15 +8,16 @@ import {
|
||||
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';
|
||||
import { BaseMotionSlideComponent } from '../base/base-motion-slide';
|
||||
|
||||
@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();
|
||||
export class MotionBlockSlideComponent extends BaseMotionSlideComponent<MotionBlockSlideData> {
|
||||
public constructor(translate: TranslateService, motionRepo: MotionRepositoryService) {
|
||||
super(translate, motionRepo);
|
||||
}
|
||||
|
||||
public getMotionTitle(motion: MotionTitleInformation): string {
|
||||
@ -31,16 +31,8 @@ export class MotionBlockSlideComponent extends BaseSlideComponent<MotionBlockSli
|
||||
public getRecommendationLabel(motion: MotionBlockSlideMotionRepresentation): string {
|
||||
let recommendation = this.translate.instant(motion.recommendation.name);
|
||||
if (motion.recommendation_extension) {
|
||||
const extension = motion.recommendation_extension.replace(/\[motion:(\d+)\]/g, (match, id) => {
|
||||
const titleInformation = this.data.data.referenced_motions[id];
|
||||
if (titleInformation) {
|
||||
return this.motionRepo.getIdentifierOrTitle(titleInformation);
|
||||
} else {
|
||||
return this.translate.instant('<unknown motion>');
|
||||
}
|
||||
});
|
||||
|
||||
recommendation += ' ' + extension;
|
||||
recommendation +=
|
||||
' ' + this.replaceReferencedMotions(motion.recommendation_extension, this.data.data.referenced_motions);
|
||||
}
|
||||
return recommendation;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion';
|
||||
import { MergeAmendment } from '../../../shared/models/motions/workflow-state';
|
||||
import { ReferencedMotions } from '../base/base-motion-slide';
|
||||
|
||||
/**
|
||||
* This interface describes the data returned by the server about an amendment.
|
||||
@ -65,6 +66,7 @@ export interface MotionSlideData {
|
||||
recommender?: string;
|
||||
recommendation?: string;
|
||||
recommendation_extension?: string;
|
||||
referenced_motions?: ReferencedMotions;
|
||||
base_motion?: MotionSlideDataBaseMotion;
|
||||
base_statute?: MotionSlideDataBaseStatute;
|
||||
amendment_paragraphs: string[];
|
||||
|
@ -9,7 +9,7 @@
|
||||
<!-- Recommendation -->
|
||||
<div *ngIf="data.data.recommendation && data.data.recommender">
|
||||
<h3>{{ data.data.recommender }}</h3>
|
||||
{{ data.data.recommendation | translate }} {{ data.data.recommendation_extension }}
|
||||
{{ getRecommendationLabel() }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { MotionSlideData, MotionSlideDataAmendment } from './motion-slide-data';
|
||||
import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion';
|
||||
import { DiffLinesInParagraph, DiffService, LineRange } from '../../../core/ui-services/diff.service';
|
||||
@ -10,13 +11,15 @@ import { ViewUnifiedChange } from '../../../shared/models/motions/view-unified-c
|
||||
import { MotionSlideObjChangeReco } from './motion-slide-obj-change-reco';
|
||||
import { SlideData } from '../../../core/core-services/projector-data.service';
|
||||
import { MotionSlideObjAmendmentParagraph } from './motion-slide-obj-amendment-paragraph';
|
||||
import { BaseMotionSlideComponent } from '../base/base-motion-slide';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
|
||||
@Component({
|
||||
selector: 'os-motion-slide',
|
||||
templateUrl: './motion-slide.component.html',
|
||||
styleUrls: ['./motion-slide.component.scss']
|
||||
})
|
||||
export class MotionSlideComponent extends BaseSlideComponent<MotionSlideData> {
|
||||
export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideData> {
|
||||
/**
|
||||
* Indicates the LineNumberingMode Mode.
|
||||
*/
|
||||
@ -67,11 +70,26 @@ export class MotionSlideComponent extends BaseSlideComponent<MotionSlideData> {
|
||||
}
|
||||
|
||||
public constructor(
|
||||
translate: TranslateService,
|
||||
motionRepo: MotionRepositoryService,
|
||||
private sanitizer: DomSanitizer,
|
||||
private lineNumbering: LinenumberingService,
|
||||
private diff: DiffService
|
||||
) {
|
||||
super();
|
||||
super(translate, motionRepo);
|
||||
}
|
||||
|
||||
public getRecommendationLabel(): string {
|
||||
let recommendation = this.translate.instant(this.data.data.recommendation);
|
||||
if (this.data.data.recommendation_extension) {
|
||||
recommendation +=
|
||||
' ' +
|
||||
this.replaceReferencedMotions(
|
||||
this.data.data.recommendation_extension,
|
||||
this.data.data.referenced_motions
|
||||
);
|
||||
}
|
||||
return recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,8 @@ from ..utils.projector import (
|
||||
)
|
||||
|
||||
|
||||
motion_placeholder_regex = re.compile(r"\[motion:(\d+)\]")
|
||||
|
||||
# Important: All functions have to be prune. This means, that thay can only
|
||||
# access the data, that they get as argument and do not have any
|
||||
# side effects. They are called from an async context. So they have
|
||||
@ -98,6 +100,28 @@ def get_amendment_base_statute(amendment, all_data):
|
||||
return {"title": statute["title"], "text": statute["text"]}
|
||||
|
||||
|
||||
def extend_reference_motion_dict(
|
||||
all_data: AllData,
|
||||
recommendation: 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.
|
||||
"""
|
||||
# Collect all meantioned motions via [motion:<id>]
|
||||
referenced_ids = [
|
||||
int(id) for id in motion_placeholder_regex.findall(recommendation)
|
||||
]
|
||||
for id in referenced_ids:
|
||||
# Put every referenced motion into the referenced_motions dict
|
||||
if id not in referenced_motions and id in all_data["motions/motion"]:
|
||||
referenced_motions[id] = {
|
||||
"title": all_data["motions/motion"][id]["title"],
|
||||
"identifier": all_data["motions/motion"][id]["identifier"],
|
||||
}
|
||||
|
||||
|
||||
def motion_slide(
|
||||
all_data: AllData, element: Dict[str, Any], projector_id: int
|
||||
) -> Dict[str, Any]:
|
||||
@ -189,9 +213,14 @@ def motion_slide(
|
||||
"recommendation_label"
|
||||
]
|
||||
if recommendation_state["show_recommendation_extension_field"]:
|
||||
return_value["recommendation_extension"] = motion[
|
||||
"recommendation_extension"
|
||||
]
|
||||
recommendation_extension = motion["recommendation_extension"]
|
||||
# All title information for referenced motions in the recommendation
|
||||
referenced_motions: Dict[int, Dict[str, str]] = {}
|
||||
extend_reference_motion_dict(
|
||||
all_data, recommendation_extension, referenced_motions
|
||||
)
|
||||
return_value["recommendation_extension"] = recommendation_extension
|
||||
return_value["referenced_motions"] = referenced_motions
|
||||
|
||||
return_value["recommender"] = get_config(
|
||||
all_data, "motions_recommendations_by"
|
||||
@ -228,12 +257,8 @@ def motion_block_slide(
|
||||
# All motions in this motion block
|
||||
motions = []
|
||||
|
||||
# All motions meantioned in recommendations of the above motions.
|
||||
# Only title_informations will be collected. With this, the client can
|
||||
# replace the placeholders in the recommendation correctly
|
||||
# This maps the motion id to the title information
|
||||
# All title information for referenced motions in the recommendation
|
||||
referenced_motions: Dict[int, Dict[str, str]] = {}
|
||||
motion_placeholder_regex = re.compile(r"\[motion:(\d+)\]")
|
||||
|
||||
# Search motions.
|
||||
for motion in all_data["motions/motion"].values():
|
||||
@ -254,26 +279,10 @@ def motion_block_slide(
|
||||
}
|
||||
if recommendation["show_recommendation_extension_field"]:
|
||||
recommendation_extension = motion["recommendation_extension"]
|
||||
|
||||
motion_object["recommendation_extension"] = recommendation_extension
|
||||
# Collect all meantioned motions via [motion:<id>]
|
||||
referenced_ids = [
|
||||
int(id)
|
||||
for id in motion_placeholder_regex.findall(
|
||||
recommendation_extension
|
||||
extend_reference_motion_dict(
|
||||
all_data, recommendation_extension, referenced_motions
|
||||
)
|
||||
]
|
||||
for id in referenced_ids:
|
||||
if (
|
||||
id not in referenced_motions
|
||||
and id in all_data["motions/motion"]
|
||||
):
|
||||
referenced_motions[id] = {
|
||||
"title": all_data["motions/motion"][id]["title"],
|
||||
"identifier": all_data["motions/motion"][id][
|
||||
"identifier"
|
||||
],
|
||||
}
|
||||
motion_object["recommendation_extension"] = recommendation_extension
|
||||
|
||||
motions.append(motion_object)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user