Merge pull request #5920 from CatoTH/bugfix/inconsistency-amendment-paragraphs
Bugfix: better handling of inconsistent states in amendments if the b…
This commit is contained in:
commit
291402e159
@ -336,6 +336,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
const changeRecos = viewMotion.changeRecommendations.filter(changeReco =>
|
const changeRecos = viewMotion.changeRecommendations.filter(changeReco =>
|
||||||
changeReco.showInFinalView()
|
changeReco.showInFinalView()
|
||||||
);
|
);
|
||||||
|
try {
|
||||||
return this.getAmendmentParagraphLines(
|
return this.getAmendmentParagraphLines(
|
||||||
viewMotion,
|
viewMotion,
|
||||||
this.motionLineLength,
|
this.motionLineLength,
|
||||||
@ -343,6 +344,10 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
changeRecos,
|
changeRecos,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// Inconsistency between motion and amendment -> the best we can do is not to fail completely
|
||||||
|
return [];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -810,6 +815,13 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
let paragraph: string;
|
let paragraph: string;
|
||||||
let paragraphHasChanges;
|
let paragraphHasChanges;
|
||||||
|
|
||||||
|
if (baseParagraphs[paraNo] === undefined) {
|
||||||
|
const msg =
|
||||||
|
'Inconsistent data. An amendment is probably referring to a non-existant line number. ' +
|
||||||
|
'You can back up its content when editing it and delete it afterwards.';
|
||||||
|
return '<em style="color: red; font-weight: bold;">' + msg + '</em>';
|
||||||
|
}
|
||||||
|
|
||||||
if (newText === null) {
|
if (newText === null) {
|
||||||
paragraph = baseParagraphs[paraNo];
|
paragraph = baseParagraphs[paraNo];
|
||||||
paragraphHasChanges = false;
|
paragraphHasChanges = false;
|
||||||
@ -855,6 +867,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
* @param {ViewMotionChangeRecommendation[]} changeRecommendations
|
* @param {ViewMotionChangeRecommendation[]} changeRecommendations
|
||||||
* @param {boolean} includeUnchanged
|
* @param {boolean} includeUnchanged
|
||||||
* @returns {DiffLinesInParagraph}
|
* @returns {DiffLinesInParagraph}
|
||||||
|
* @throws Error
|
||||||
*/
|
*/
|
||||||
public getAmendmentParagraphLines(
|
public getAmendmentParagraphLines(
|
||||||
amendment: ViewMotion,
|
amendment: ViewMotion,
|
||||||
@ -876,7 +889,11 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
return amendmentParagraphs
|
return amendmentParagraphs
|
||||||
?.map(
|
?.map(
|
||||||
(newText: string, paraNo: number): DiffLinesInParagraph => {
|
(newText: string, paraNo: number): DiffLinesInParagraph => {
|
||||||
if (newText !== null) {
|
if (baseParagraphs[paraNo] === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
'Inconsistent data. An amendment is probably referring to a non-existant line number.'
|
||||||
|
);
|
||||||
|
} else if (newText !== null) {
|
||||||
return this.diff.getAmendmentParagraphsLines(
|
return this.diff.getAmendmentParagraphsLines(
|
||||||
paraNo,
|
paraNo,
|
||||||
baseParagraphs[paraNo],
|
baseParagraphs[paraNo],
|
||||||
@ -950,6 +967,12 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
if (newText === null) {
|
if (newText === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (baseParagraphs[paraNo] === undefined) {
|
||||||
|
console.error(
|
||||||
|
'Inconsistent data. An amendment is probably referring to a non-existant line number.'
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const origText = baseParagraphs[paraNo],
|
const origText = baseParagraphs[paraNo],
|
||||||
diff = this.diff.diff(origText, newText),
|
diff = this.diff.diff(origText, newText),
|
||||||
@ -990,6 +1013,9 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
|||||||
|
|
||||||
return (amendment.amendment_paragraphs || []).map((newText: string, paraNo: number): string => {
|
return (amendment.amendment_paragraphs || []).map((newText: string, paraNo: number): string => {
|
||||||
const origText = baseParagraphs[paraNo];
|
const origText = baseParagraphs[paraNo];
|
||||||
|
if (origText === undefined) {
|
||||||
|
throw new Error('Inconsistent data. An amendment is probably referring to a non-existant line number.');
|
||||||
|
}
|
||||||
|
|
||||||
if (newText === null) {
|
if (newText === null) {
|
||||||
return origText;
|
return origText;
|
||||||
|
@ -2238,7 +2238,8 @@ export class DiffService {
|
|||||||
// That's a pretty serious inconsistency that should not happen at all,
|
// That's a pretty serious inconsistency that should not happen at all,
|
||||||
// we're just doing some basic damage control here.
|
// we're just doing some basic damage control here.
|
||||||
const msg =
|
const msg =
|
||||||
'Inconsistent data. A change recommendation is probably referring to a non-existant line number.';
|
'Inconsistent data. A change recommendation or amendment is probably referring to a non-existant line number. ' +
|
||||||
|
'If it is an amendment, you can back up its content when editing it and delete it afterwards';
|
||||||
return '<em style="color: red; font-weight: bold;">' + msg + '</em>';
|
return '<em style="color: red; font-weight: bold;">' + msg + '</em>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2299,7 +2300,7 @@ export class DiffService {
|
|||||||
// That's a pretty serious inconsistency that should not happen at all,
|
// That's a pretty serious inconsistency that should not happen at all,
|
||||||
// we're just doing some basic damage control here.
|
// we're just doing some basic damage control here.
|
||||||
const msg =
|
const msg =
|
||||||
'Inconsistent data. A change recommendation is probably referring to a non-existant line number.';
|
'Inconsistent data. A change recommendation or amendment is probably referring to a non-existant line number.';
|
||||||
return '<em style="color: red; font-weight: bold;">' + msg + '</em>';
|
return '<em style="color: red; font-weight: bold;">' + msg + '</em>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +140,14 @@ export class MotionDetailDiffComponent extends BaseViewComponentDirective implem
|
|||||||
|
|
||||||
let baseText: LineNumberedString;
|
let baseText: LineNumberedString;
|
||||||
if (this.motion.isParagraphBasedAmendment()) {
|
if (this.motion.isParagraphBasedAmendment()) {
|
||||||
|
try {
|
||||||
baseText = this.motionRepo
|
baseText = this.motionRepo
|
||||||
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
||||||
}
|
}
|
||||||
@ -184,9 +189,14 @@ export class MotionDetailDiffComponent extends BaseViewComponentDirective implem
|
|||||||
}
|
}
|
||||||
let baseText: LineNumberedString;
|
let baseText: LineNumberedString;
|
||||||
if (this.motion.isParagraphBasedAmendment()) {
|
if (this.motion.isParagraphBasedAmendment()) {
|
||||||
|
try {
|
||||||
baseText = this.motionRepo
|
baseText = this.motionRepo
|
||||||
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
||||||
}
|
}
|
||||||
|
@ -769,6 +769,10 @@
|
|||||||
{{ 'This field is required.' | translate }}
|
{{ 'This field is required.' | translate }}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section *ngFor="let paragraph of contentForm.value.broken_paragraphs">
|
||||||
|
<em class="red-warning-text">{{ 'This paragraph does not exist in the main motion anymore:' | translate }}</em>
|
||||||
|
<div class="motion-text" [innerHTML]="paragraph | trust: 'html'"></div>
|
||||||
|
</section>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Paragraph-based amendments -->
|
<!-- Paragraph-based amendments -->
|
||||||
@ -900,6 +904,9 @@
|
|||||||
<i *ngIf="motion.parent">{{ 'No changes at the text.' | translate }}</i>
|
<i *ngIf="motion.parent">{{ 'No changes at the text.' | translate }}</i>
|
||||||
<i *ngIf="!motion.parent">{{ 'The parent motion was deleted.' | translate }}</i>
|
<i *ngIf="!motion.parent">{{ 'The parent motion was deleted.' | translate }}</i>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="alert alert-info alert-inconsistency" *ngIf="amendmentErrorMessage">
|
||||||
|
<i [innerHTML]="amendmentErrorMessage"></i>
|
||||||
|
</div>
|
||||||
<ng-container *ngIf="motion.parent && !isRecoMode(ChangeRecoMode.Diff) && !isFinalEdit">
|
<ng-container *ngIf="motion.parent && !isRecoMode(ChangeRecoMode.Diff) && !isFinalEdit">
|
||||||
<div
|
<div
|
||||||
*ngFor="let paragraph of getAmendmentParagraphs(); trackBy: trackByIndex"
|
*ngFor="let paragraph of getAmendmentParagraphs(); trackBy: trackByIndex"
|
||||||
|
@ -78,6 +78,11 @@ span {
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert-inconsistency {
|
||||||
|
color: red;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.motion-content {
|
.motion-content {
|
||||||
h4 {
|
h4 {
|
||||||
margin: 10px 10px 15px 0;
|
margin: 10px 10px 15px 0;
|
||||||
|
@ -430,6 +430,8 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
|
|
||||||
public recommendationReferencingMotions: ViewMotion[] = [];
|
public recommendationReferencingMotions: ViewMotion[] = [];
|
||||||
|
|
||||||
|
public amendmentErrorMessage: string = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the detail view.
|
* Constructs the detail view.
|
||||||
*
|
*
|
||||||
@ -816,6 +818,7 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
|
|
||||||
if (formMotion.isParagraphBasedAmendment()) {
|
if (formMotion.isParagraphBasedAmendment()) {
|
||||||
contentPatch.selected_paragraphs = [];
|
contentPatch.selected_paragraphs = [];
|
||||||
|
contentPatch.broken_paragraphs = [];
|
||||||
const parentMotion = this.repo.getViewModel(formMotion.parent_id);
|
const parentMotion = this.repo.getViewModel(formMotion.parent_id);
|
||||||
// Hint: lineLength is sometimes not loaded yet when this form is initialized;
|
// 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.
|
// This doesn't hurt as long as patchForm is called when editing mode is started, i.e., later.
|
||||||
@ -833,6 +836,18 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
contentPatch['text_' + paragraphNo] = formMotion.amendment_paragraphs[paragraphNo];
|
contentPatch['text_' + paragraphNo] = formMotion.amendment_paragraphs[paragraphNo];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If the motion has been shortened after the amendment has been created, we will show the paragraphs
|
||||||
|
// of the amendment as read-only
|
||||||
|
for (
|
||||||
|
let paragraphNo = paragraphsToChoose.length;
|
||||||
|
paragraphNo < formMotion.amendment_paragraphs.length;
|
||||||
|
paragraphNo++
|
||||||
|
) {
|
||||||
|
if (formMotion.amendment_paragraphs[paragraphNo] !== null) {
|
||||||
|
contentPatch.broken_paragraphs.push(formMotion.amendment_paragraphs[paragraphNo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,6 +882,7 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
tags_id: [],
|
tags_id: [],
|
||||||
origin: [''],
|
origin: [''],
|
||||||
selected_paragraphs: [],
|
selected_paragraphs: [],
|
||||||
|
broken_paragraphs: [],
|
||||||
statute_amendment: [''], // Internal value for the checkbox, not saved to the model
|
statute_amendment: [''], // Internal value for the checkbox, not saved to the model
|
||||||
statute_paragraph_id: [''],
|
statute_paragraph_id: [''],
|
||||||
motion_block_id: [],
|
motion_block_id: [],
|
||||||
@ -1039,8 +1055,11 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
* TODO: Cleanup: repo function could be injected part of the model, to have easier access
|
* TODO: Cleanup: repo function could be injected part of the model, to have easier access
|
||||||
*
|
*
|
||||||
* @returns {DiffLinesInParagraph[]}
|
* @returns {DiffLinesInParagraph[]}
|
||||||
|
* @throws Error
|
||||||
*/
|
*/
|
||||||
public getAmendmentParagraphs(): DiffLinesInParagraph[] {
|
public getAmendmentParagraphs(): DiffLinesInParagraph[] {
|
||||||
|
try {
|
||||||
|
this.amendmentErrorMessage = null;
|
||||||
return this.repo.getAmendmentParagraphLines(
|
return this.repo.getAmendmentParagraphLines(
|
||||||
this.motion,
|
this.motion,
|
||||||
this.lineLength,
|
this.lineLength,
|
||||||
@ -1048,6 +1067,9 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
this.changeRecommendations,
|
this.changeRecommendations,
|
||||||
this.showAmendmentContext
|
this.showAmendmentContext
|
||||||
);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
this.amendmentErrorMessage = e.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAmendmentParagraphLinesTitle(paragraph: DiffLinesInParagraph): string {
|
public getAmendmentParagraphLinesTitle(paragraph: DiffLinesInParagraph): string {
|
||||||
@ -1209,6 +1231,7 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
changeRecommendation: null
|
changeRecommendation: null
|
||||||
};
|
};
|
||||||
if (this.motion.isParagraphBasedAmendment()) {
|
if (this.motion.isParagraphBasedAmendment()) {
|
||||||
|
try {
|
||||||
const lineNumberedParagraphs = this.repo.getAllAmendmentParagraphsWithOriginalLineNumbers(
|
const lineNumberedParagraphs = this.repo.getAllAmendmentParagraphsWithOriginalLineNumbers(
|
||||||
this.motion,
|
this.motion,
|
||||||
this.lineLength,
|
this.lineLength,
|
||||||
@ -1220,6 +1243,10 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
|||||||
lineRange,
|
lineRange,
|
||||||
this.lineLength
|
this.lineLength
|
||||||
);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data.changeRecommendation = this.changeRecoRepo.createMotionChangeRecommendationTemplate(
|
data.changeRecommendation = this.changeRecoRepo.createMotionChangeRecommendationTemplate(
|
||||||
this.motion,
|
this.motion,
|
||||||
|
@ -580,6 +580,7 @@ export class MotionPdfService {
|
|||||||
if (motion.isParagraphBasedAmendment()) {
|
if (motion.isParagraphBasedAmendment()) {
|
||||||
// this is logically redundant with the formation of amendments in the motion-detail html.
|
// this is logically redundant with the formation of amendments in the motion-detail html.
|
||||||
// Should be refactored in a way that a service returns the correct html for both cases
|
// Should be refactored in a way that a service returns the correct html for both cases
|
||||||
|
try {
|
||||||
const changeRecos = this.changeRecoRepo.getChangeRecoOfMotion(motion.id);
|
const changeRecos = this.changeRecoRepo.getChangeRecoOfMotion(motion.id);
|
||||||
const amendmentParas = this.motionRepo.getAmendmentParagraphLines(
|
const amendmentParas = this.motionRepo.getAmendmentParagraphLines(
|
||||||
motion,
|
motion,
|
||||||
@ -594,6 +595,9 @@ export class MotionPdfService {
|
|||||||
motionText += paragraph.text;
|
motionText += paragraph.text;
|
||||||
motionText += `<div class="paragraphcontext">${paragraph.textPost}</div>`;
|
motionText += `<div class="paragraphcontext">${paragraph.textPost}</div>`;
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
motionText += '<em style="color: red; font-weight: bold;">' + e.toString() + '</em>';
|
||||||
|
}
|
||||||
} else if (motion.isStatuteAmendment()) {
|
} else if (motion.isStatuteAmendment()) {
|
||||||
// statute amendments
|
// statute amendments
|
||||||
const statutes = this.statuteRepo.getViewModelList();
|
const statutes = this.statuteRepo.getViewModelList();
|
||||||
|
Loading…
Reference in New Issue
Block a user