From ac50d6f8dccc5b502c7b7a3a106ef5935184494f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Ho=CC=88=C3=9Fl?= Date: Sun, 28 Feb 2021 18:38:51 +0100 Subject: [PATCH] Bugfix: better handling of inconsistent states in amendments if the base motion has shrunk --- .../motions/motion-repository.service.ts | 42 ++++++++++--- .../src/app/core/ui-services/diff.service.ts | 5 +- .../motion-detail-diff.component.ts | 22 +++++-- .../motion-detail.component.html | 7 +++ .../motion-detail.component.scss | 5 ++ .../motion-detail/motion-detail.component.ts | 63 +++++++++++++------ .../motions/services/motion-pdf.service.ts | 30 +++++---- 7 files changed, 127 insertions(+), 47 deletions(-) diff --git a/client/src/app/core/repositories/motions/motion-repository.service.ts b/client/src/app/core/repositories/motions/motion-repository.service.ts index 610785404..2730d5f7a 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -336,13 +336,18 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo const changeRecos = viewMotion.changeRecommendations.filter(changeReco => changeReco.showInFinalView() ); - return this.getAmendmentParagraphLines( - viewMotion, - this.motionLineLength, - ChangeRecoMode.Changed, - changeRecos, - false - ); + try { + return this.getAmendmentParagraphLines( + viewMotion, + this.motionLineLength, + ChangeRecoMode.Changed, + 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 '' + msg + ''; + } + 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; diff --git a/client/src/app/core/ui-services/diff.service.ts b/client/src/app/core/ui-services/diff.service.ts index 429a671e2..fcac55fcd 100644 --- a/client/src/app/core/ui-services/diff.service.ts +++ b/client/src/app/core/ui-services/diff.service.ts @@ -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 '' + msg + ''; } @@ -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 '' + msg + ''; } diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.ts index 0fd73e919..3b2484211 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail-diff/motion-detail-diff.component.ts @@ -140,9 +140,14 @@ export class MotionDetailDiffComponent extends BaseViewComponentDirective implem let baseText: LineNumberedString; if (this.motion.isParagraphBasedAmendment()) { - baseText = this.motionRepo - .getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true) - .join('\n'); + 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()) { - baseText = this.motionRepo - .getAllAmendmentParagraphsWithOriginalLineNumbers(this.motion, this.lineLength, true) - .join('\n'); + 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); } diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html index 8dbac8f8d..173448648 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html @@ -769,6 +769,10 @@ {{ 'This field is required.' | translate }} +
+ {{ 'This paragraph does not exist in the main motion anymore:' | translate }} +
+
@@ -900,6 +904,9 @@ {{ 'No changes at the text.' | translate }} {{ 'The parent motion was deleted.' | translate }} +
+ +
'; - motionText += `
${paragraph.textPre}
`; - motionText += paragraph.text; - motionText += `
${paragraph.textPost}
`; + try { + const changeRecos = this.changeRecoRepo.getChangeRecoOfMotion(motion.id); + const amendmentParas = this.motionRepo.getAmendmentParagraphLines( + motion, + lineLength, + crMode, + changeRecos, + false + ); + for (const paragraph of amendmentParas) { + motionText += '

' + this.motionRepo.getAmendmentParagraphLinesTitle(paragraph) + '

'; + motionText += `
${paragraph.textPre}
`; + motionText += paragraph.text; + motionText += `
${paragraph.textPost}
`; + } + } catch (e) { + motionText += '' + e.toString() + ''; } } else if (motion.isStatuteAmendment()) { // statute amendments