Bugfix: better handling of inconsistent states in amendments if the base motion has shrunk
This commit is contained in:
parent
f80ac1d9c5
commit
ac50d6f8dc
@ -336,6 +336,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
const changeRecos = viewMotion.changeRecommendations.filter(changeReco =>
|
||||
changeReco.showInFinalView()
|
||||
);
|
||||
try {
|
||||
return this.getAmendmentParagraphLines(
|
||||
viewMotion,
|
||||
this.motionLineLength,
|
||||
@ -343,6 +344,10 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
changeRecos,
|
||||
false
|
||||
);
|
||||
} catch (e) {
|
||||
// Inconsistency between motion and amendment -> the best we can do is not to fail completely
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@ -810,6 +815,13 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
let paragraph: string;
|
||||
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) {
|
||||
paragraph = baseParagraphs[paraNo];
|
||||
paragraphHasChanges = false;
|
||||
@ -855,6 +867,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
* @param {ViewMotionChangeRecommendation[]} changeRecommendations
|
||||
* @param {boolean} includeUnchanged
|
||||
* @returns {DiffLinesInParagraph}
|
||||
* @throws Error
|
||||
*/
|
||||
public getAmendmentParagraphLines(
|
||||
amendment: ViewMotion,
|
||||
@ -876,7 +889,11 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
return amendmentParagraphs
|
||||
?.map(
|
||||
(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(
|
||||
paraNo,
|
||||
baseParagraphs[paraNo],
|
||||
@ -950,6 +967,12 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
|
||||
if (newText === 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],
|
||||
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 => {
|
||||
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) {
|
||||
return origText;
|
||||
|
@ -2238,7 +2238,8 @@ export class DiffService {
|
||||
// That's a pretty serious inconsistency that should not happen at all,
|
||||
// we're just doing some basic damage control here.
|
||||
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>';
|
||||
}
|
||||
|
||||
@ -2299,7 +2300,7 @@ export class DiffService {
|
||||
// That's a pretty serious inconsistency that should not happen at all,
|
||||
// we're just doing some basic damage control here.
|
||||
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>';
|
||||
}
|
||||
|
||||
|
@ -140,9 +140,14 @@ export class MotionDetailDiffComponent extends BaseViewComponentDirective implem
|
||||
|
||||
let baseText: LineNumberedString;
|
||||
if (this.motion.isParagraphBasedAmendment()) {
|
||||
try {
|
||||
baseText = this.motionRepo
|
||||
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
||||
.join('\n');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
||||
}
|
||||
@ -184,9 +189,14 @@ export class MotionDetailDiffComponent extends BaseViewComponentDirective implem
|
||||
}
|
||||
let baseText: LineNumberedString;
|
||||
if (this.motion.isParagraphBasedAmendment()) {
|
||||
try {
|
||||
baseText = this.motionRepo
|
||||
.getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true)
|
||||
.join('\n');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
baseText = this.lineNumbering.insertLineNumbers(this.motion.text, this.lineLength);
|
||||
}
|
||||
|
@ -769,6 +769,10 @@
|
||||
{{ 'This field is required.' | translate }}
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<!-- Paragraph-based amendments -->
|
||||
@ -900,6 +904,9 @@
|
||||
<i *ngIf="motion.parent">{{ 'No changes at the text.' | translate }}</i>
|
||||
<i *ngIf="!motion.parent">{{ 'The parent motion was deleted.' | translate }}</i>
|
||||
</div>
|
||||
<div class="alert alert-info alert-inconsistency" *ngIf="amendmentErrorMessage">
|
||||
<i [innerHTML]="amendmentErrorMessage"></i>
|
||||
</div>
|
||||
<ng-container *ngIf="motion.parent && !isRecoMode(ChangeRecoMode.Diff) && !isFinalEdit">
|
||||
<div
|
||||
*ngFor="let paragraph of getAmendmentParagraphs(); trackBy: trackByIndex"
|
||||
|
@ -78,6 +78,11 @@ span {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.alert-inconsistency {
|
||||
color: red;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.motion-content {
|
||||
h4 {
|
||||
margin: 10px 10px 15px 0;
|
||||
|
@ -430,6 +430,8 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
|
||||
public recommendationReferencingMotions: ViewMotion[] = [];
|
||||
|
||||
public amendmentErrorMessage: string = null;
|
||||
|
||||
/**
|
||||
* Constructs the detail view.
|
||||
*
|
||||
@ -816,6 +818,7 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
|
||||
if (formMotion.isParagraphBasedAmendment()) {
|
||||
contentPatch.selected_paragraphs = [];
|
||||
contentPatch.broken_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.
|
||||
@ -833,6 +836,18 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
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: [],
|
||||
origin: [''],
|
||||
selected_paragraphs: [],
|
||||
broken_paragraphs: [],
|
||||
statute_amendment: [''], // Internal value for the checkbox, not saved to the model
|
||||
statute_paragraph_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
|
||||
*
|
||||
* @returns {DiffLinesInParagraph[]}
|
||||
* @throws Error
|
||||
*/
|
||||
public getAmendmentParagraphs(): DiffLinesInParagraph[] {
|
||||
try {
|
||||
this.amendmentErrorMessage = null;
|
||||
return this.repo.getAmendmentParagraphLines(
|
||||
this.motion,
|
||||
this.lineLength,
|
||||
@ -1048,6 +1067,9 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
this.changeRecommendations,
|
||||
this.showAmendmentContext
|
||||
);
|
||||
} catch (e) {
|
||||
this.amendmentErrorMessage = e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public getAmendmentParagraphLinesTitle(paragraph: DiffLinesInParagraph): string {
|
||||
@ -1209,6 +1231,7 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
changeRecommendation: null
|
||||
};
|
||||
if (this.motion.isParagraphBasedAmendment()) {
|
||||
try {
|
||||
const lineNumberedParagraphs = this.repo.getAllAmendmentParagraphsWithOriginalLineNumbers(
|
||||
this.motion,
|
||||
this.lineLength,
|
||||
@ -1220,6 +1243,10 @@ export class MotionDetailComponent extends BaseViewComponentDirective implements
|
||||
lineRange,
|
||||
this.lineLength
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
data.changeRecommendation = this.changeRecoRepo.createMotionChangeRecommendationTemplate(
|
||||
this.motion,
|
||||
|
@ -580,6 +580,7 @@ export class MotionPdfService {
|
||||
if (motion.isParagraphBasedAmendment()) {
|
||||
// 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
|
||||
try {
|
||||
const changeRecos = this.changeRecoRepo.getChangeRecoOfMotion(motion.id);
|
||||
const amendmentParas = this.motionRepo.getAmendmentParagraphLines(
|
||||
motion,
|
||||
@ -594,6 +595,9 @@ export class MotionPdfService {
|
||||
motionText += paragraph.text;
|
||||
motionText += `<div class="paragraphcontext">${paragraph.textPost}</div>`;
|
||||
}
|
||||
} catch (e) {
|
||||
motionText += '<em style="color: red; font-weight: bold;">' + e.toString() + '</em>';
|
||||
}
|
||||
} else if (motion.isStatuteAmendment()) {
|
||||
// statute amendments
|
||||
const statutes = this.statuteRepo.getViewModelList();
|
||||
|
Loading…
Reference in New Issue
Block a user