Merge pull request #4811 from FinnStutzenstein/recommendationReferencingMotions

Show from recommendation referencing motions
This commit is contained in:
Emanuel Schütze 2019-07-04 12:42:04 +02:00 committed by GitHub
commit 7943d15dae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 105 additions and 5 deletions

View File

@ -458,7 +458,8 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
await this.httpService.delete(url); await this.httpService.delete(url);
} }
/** Returns an observable returning the amendments to a given motion /**
* Returns an observable returning the amendments to a given motion
* *
* @param {number} motionId * @param {number} motionId
* @returns {Observable<ViewMotion[]>} * @returns {Observable<ViewMotion[]>}
@ -473,6 +474,33 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
); );
} }
/**
* Returns an observable for all motions, that referencing the given motion (via id)
* in the recommendation.
*/
public getRecommendationReferencingMotions(motionId: number): Observable<ViewMotion[]> {
return this.getViewModelListObservable().pipe(
map((motions: ViewMotion[]): ViewMotion[] => {
return motions.filter((motion: ViewMotion): boolean => {
if (!motion.recommendationExtension) {
return false;
}
// Check, if this motion has the motionId in it's recommendation
const placeholderRegex = /\[motion:(\d+)\]/g;
let match;
while ((match = placeholderRegex.exec(motion.recommendationExtension))) {
if (parseInt(match[1], 10) === motionId) {
return true;
}
}
return false;
});
})
);
}
/** /**
* Returns the amendments to a given motion * Returns the amendments to a given motion
* *

View File

@ -296,7 +296,7 @@ export class ViewMotion extends BaseViewModelWithAgendaItemAndListOfSpeakers<Mot
} }
/** /**
* @returns the current recommendation extension if the workwlof allows for extenstion fields * @returns the current recommendation extension if the workflow allows for extenstion fields
*/ */
public get recommendationExtension(): string { public get recommendationExtension(): string {
if (this.recommendation && this.recommendation.show_recommendation_extension_field) { if (this.recommendation && this.recommendation.show_recommendation_extension_field) {

View File

@ -329,6 +329,14 @@
</button> </button>
</div> </div>
<!-- recommendation referencing motions -->
<div *ngIf="!editMotion && recommendationReferencingMotions.length > 0">
<h4 translate>Recommendation-referencing motions</h4>
<div *ngFor="let motion of recommendationReferencingMotions">
<a [routerLink]="motion.getDetailStateURL()">{{ motion.identifierOrTitle }}</a>
</div>
</div>
<!-- Category --> <!-- Category -->
<!-- Disabled during "new motion" since changing has no effect --> <!-- Disabled during "new motion" since changing has no effect -->
<div *ngIf="!editMotion && categoryObserver.value.length"> <div *ngIf="!editMotion && categoryObserver.value.length">

View File

@ -371,6 +371,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
*/ */
private navigationSubscription: Subscription; private navigationSubscription: Subscription;
public recommendationReferencingMotions: ViewMotion[] = [];
/** /**
* Constructs the detail view. * Constructs the detail view.
* *
@ -614,6 +616,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
this.amendments = amendments; this.amendments = amendments;
this.recalcUnifiedChanges(); this.recalcUnifiedChanges();
}), }),
this.repo
.getRecommendationReferencingMotions(motionId)
.subscribe(motions => (this.recommendationReferencingMotions = motions)),
this.changeRecoRepo this.changeRecoRepo
.getChangeRecosOfMotionObservable(motionId) .getChangeRecosOfMotionObservable(motionId)
.subscribe((recos: ViewMotionChangeRecommendation[]) => { .subscribe((recos: ViewMotionChangeRecommendation[]) => {

View File

@ -1,4 +1,4 @@
import { ChangeRecoMode, LineNumberingMode } from 'app/site/motions/models/view-motion'; import { ChangeRecoMode, LineNumberingMode, MotionTitleInformation } from 'app/site/motions/models/view-motion';
import { ReferencedMotions } from '../base/base-motion-slide'; import { ReferencedMotions } from '../base/base-motion-slide';
/** /**
@ -66,6 +66,7 @@ export interface MotionSlideData {
recommender?: string; recommender?: string;
recommendation?: string; recommendation?: string;
recommendation_extension?: string; recommendation_extension?: string;
recommendation_referencing_motions?: MotionTitleInformation[];
referenced_motions?: ReferencedMotions; referenced_motions?: ReferencedMotions;
base_motion?: MotionSlideDataBaseMotion; base_motion?: MotionSlideDataBaseMotion;
base_statute?: MotionSlideDataBaseStatute; base_statute?: MotionSlideDataBaseStatute;

View File

@ -11,6 +11,14 @@
<h3>{{ data.data.recommender }}</h3> <h3>{{ data.data.recommender }}</h3>
{{ getRecommendationLabel() }} {{ getRecommendationLabel() }}
</div> </div>
<!-- recommendation referencing motions -->
<div *ngIf="data.data.recommendation_referencing_motions">
<h3 translate>Recommendation-referencing motions</h3>
<div *ngFor="let titleInformation of data.data.recommendation_referencing_motions">
{{ getIdentifierOrTitle(titleInformation) }}
</div>
</div>
</div> </div>
<div [ngStyle]="{width: data.data.show_meta_box ? 'calc(100% - 250px)' : '100%'}"> <div [ngStyle]="{width: data.data.show_meta_box ? 'calc(100% - 250px)' : '100%'}">

View File

@ -4,7 +4,7 @@ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { MotionSlideData, MotionSlideDataAmendment } from './motion-slide-data'; import { MotionSlideData, MotionSlideDataAmendment } from './motion-slide-data';
import { ChangeRecoMode, LineNumberingMode } from 'app/site/motions/models/view-motion'; import { ChangeRecoMode, LineNumberingMode, MotionTitleInformation } from 'app/site/motions/models/view-motion';
import { DiffLinesInParagraph, DiffService, LineRange } from 'app/core/ui-services/diff.service'; import { DiffLinesInParagraph, DiffService, LineRange } from 'app/core/ui-services/diff.service';
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service'; import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change'; import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change';
@ -118,6 +118,10 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
super(translate, motionRepo); super(translate, motionRepo);
} }
public getIdentifierOrTitle(titleInformation: MotionTitleInformation): string {
return this.motionRepo.getIdentifierOrTitle(titleInformation);
}
public getRecommendationLabel(): string { public getRecommendationLabel(): string {
let recommendation = this.translate.instant(this.data.data.recommendation); let recommendation = this.translate.instant(this.data.data.recommendation);
if (this.data.data.recommendation_extension) { if (this.data.data.recommendation_extension) {

View File

@ -1,5 +1,5 @@
import re import re
from typing import Any, Dict, Optional from typing import Any, Dict, List, Optional
from ..users.projector import get_user_name from ..users.projector import get_user_name
from ..utils.projector import ( from ..utils.projector import (
@ -228,6 +228,7 @@ async def motion_slide(
return_value["modified_final_version"] = motion["modified_final_version"] return_value["modified_final_version"] = motion["modified_final_version"]
if show_meta_box: if show_meta_box:
# Add recommendation, if enabled in config (and the motion has one)
if ( if (
not await get_config( not await get_config(
all_data, "motions_disable_recommendation_on_projector" all_data, "motions_disable_recommendation_on_projector"
@ -254,6 +255,7 @@ async def motion_slide(
all_data, "motions_recommendations_by" all_data, "motions_recommendations_by"
) )
# Add submitters
return_value["submitter"] = [ return_value["submitter"] = [
await get_user_name(all_data, submitter["user_id"]) await get_user_name(all_data, submitter["user_id"])
for submitter in sorted( for submitter in sorted(
@ -261,9 +263,50 @@ async def motion_slide(
) )
] ]
# Add recommendation-referencing motions
return_value[
"recommendation_referencing_motions"
] = await get_recommendation_referencing_motions(all_data, motion_id)
return return_value return return_value
async def get_recommendation_referencing_motions(
all_data: AllData, motion_id: int
) -> Optional[List[Dict[str, Any]]]:
"""
Returns all title information for motions, that are referencing
the given motion (by id) in their recommendation. If there are no
motions, None is returned (instead of []).
"""
recommendation_referencing_motions = []
for motion in all_data["motions/motion"].values():
# Motion must have a recommendation and a recommendaiton extension
if not motion["recommendation_id"] or not motion["recommendation_extension"]:
continue
# The recommendation must allow the extension field (there might be left-overs
# in a motions recommendation extension..)
recommendation = await get_state(all_data, motion, "recommendation_id")
if not recommendation["show_recommendation_extension_field"]:
continue
# Find referenced motion ids
referenced_ids = [
int(id)
for id in motion_placeholder_regex.findall(
motion["recommendation_extension"]
)
]
# if one of the referenced ids is the given motion, add the current motion.
if motion_id in referenced_ids:
recommendation_referencing_motions.append(
{"title": motion["title"], "identifier": motion["identifier"]}
)
return recommendation_referencing_motions or None
async def motion_block_slide( async def motion_block_slide(
all_data: AllData, element: Dict[str, Any], projector_id: int all_data: AllData, element: Dict[str, Any], projector_id: int
) -> Dict[str, Any]: ) -> Dict[str, Any]:

View File

@ -297,6 +297,7 @@ async def test_motion_slide(all_data):
"line_length": 90, "line_length": 90,
"line_numbering_mode": "none", "line_numbering_mode": "none",
"preamble": "The assembly may decide:", "preamble": "The assembly may decide:",
"recommendation_referencing_motions": None,
} }
@ -322,6 +323,7 @@ async def test_amendment_slide(all_data):
"line_length": 90, "line_length": 90,
"line_numbering_mode": "none", "line_numbering_mode": "none",
"preamble": "The assembly may decide:", "preamble": "The assembly may decide:",
"recommendation_referencing_motions": None,
} }
@ -347,4 +349,5 @@ async def test_statute_amendment_slide(all_data):
"line_length": 90, "line_length": 90,
"line_numbering_mode": "none", "line_numbering_mode": "none",
"preamble": "The assembly may decide:", "preamble": "The assembly may decide:",
"recommendation_referencing_motions": None,
} }