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 ea7a69b79..206d96f50 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -324,7 +324,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo type: 'custom', ownKey: 'diffLines', get: (motion: Motion, viewMotion: ViewMotion) => { - if (viewMotion.parent) { + if (viewMotion.parent && viewMotion.isParagraphBasedAmendment()) { const changeRecos = viewMotion.changeRecommendations.filter(changeReco => changeReco.showInFinalView() ); @@ -335,6 +335,8 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo changeRecos, false ); + } else { + return []; } }, getCacheObjectToCheck: (viewMotion: ViewMotion) => viewMotion.parent @@ -835,7 +837,9 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo } /** - * Returns all paragraph lines that are affected by the given amendment in diff-format, including context + * Returns all paragraph lines that are affected by the given amendment in diff-format, including context. + * + * Should only be called for paragraph-based amendments. * * @param {ViewMotion} amendment * @param {number} lineLength diff --git a/client/src/app/core/ui-services/linenumbering.service.ts b/client/src/app/core/ui-services/linenumbering.service.ts index 04768861a..0e0f68ee3 100644 --- a/client/src/app/core/ui-services/linenumbering.service.ts +++ b/client/src/app/core/ui-services/linenumbering.service.ts @@ -377,22 +377,27 @@ export class LinenumberingService { * @returns {LineNumberRange} */ public getLineNumberRange(html: string): LineNumberRange { - const fragment = this.htmlToFragment(html); - const range = { - from: null, - to: null - }; - const lineNumbers = fragment.querySelectorAll('.os-line-number'); - for (let i = 0; i < lineNumbers.length; i++) { - const node = lineNumbers.item(i); - const number = parseInt(node.getAttribute('data-line-number'), 10); - if (range.from === null || number < range.from) { - range.from = number; - } - if (range.to === null || number + 1 > range.to) { - range.to = number + 1; + const cacheKey = this.djb2hash(html); + let range = this.lineNumberCache.get(cacheKey); + if (!range) { + const fragment = this.htmlToFragment(html); + range = { + from: null, + to: null + }; + const lineNumbers = fragment.querySelectorAll('.os-line-number'); + for (let i = 0; i < lineNumbers.length; i++) { + const node = lineNumbers.item(i); + const number = parseInt(node.getAttribute('data-line-number'), 10); + if (range.from === null || number < range.from) { + range.from = number; + } + if (range.to === null || number + 1 > range.to) { + range.to = number + 1; + } } } + this.lineNumberCache.put(cacheKey, range); return range; } @@ -482,10 +487,17 @@ export class LinenumberingService { * @return {string[]} */ public splitToParagraphs(html: string): string[] { - const fragment = this.htmlToFragment(html); - return this.splitNodeToParagraphs(fragment).map((node: Element): string => { - return node.outerHTML; - }); + const cacheKey = this.djb2hash(html); + let cachedParagraphs = this.lineNumberCache.get(cacheKey); + if (!cachedParagraphs) { + const fragment = this.htmlToFragment(html); + cachedParagraphs = this.splitNodeToParagraphs(fragment).map((node: Element): string => { + return node.outerHTML; + }); + + this.lineNumberCache.put(cacheKey, cachedParagraphs); + } + return cachedParagraphs; } /** diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts index 8cf8d31c9..f92737a1b 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts @@ -322,11 +322,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, */ public showAmendmentContext = false; - /** - * Sets the current amendment text mode from the settings - */ - private amendmentTextMode: string; - /** * Show all amendments in the text, not only the ones with the apropriate state */ @@ -540,9 +535,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, this.configService .get('motions_show_sequential_numbers') .subscribe(shown => (this.showSequential = shown)); - this.configService - .get('motions_amendments_text_mode') - .subscribe(amendmentTextMode => (this.amendmentTextMode = amendmentTextMode)); // Update statute paragraphs this.statuteRepo.getViewModelListObservable().subscribe(newViewStatuteParagraphs => { @@ -649,17 +641,19 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, }); } if (this.amendments) { - this.amendments.forEach((amendment: ViewMotion): void => { - const toApplyChanges = (this.amendmentChangeRecos[amendment.id] || []).filter( - // The rejected change recommendations for amendments should not be considered - change => change.showInFinalView() - ); - this.repo - .getAmendmentAmendedParagraphs(amendment, this.lineLength, toApplyChanges) - .forEach((change: ViewUnifiedChange): void => { - this.allChangingObjects.push(change); - }); - }); + this.amendments + .filter(amendment => amendment.isParagraphBasedAmendment()) + .forEach((amendment: ViewMotion): void => { + const toApplyChanges = (this.amendmentChangeRecos[amendment.id] || []).filter( + // The rejected change recommendations for amendments should not be considered + change => change.showInFinalView() + ); + this.repo + .getAmendmentAmendedParagraphs(amendment, this.lineLength, toApplyChanges) + .forEach((change: ViewUnifiedChange): void => { + this.allChangingObjects.push(change); + }); + }); } this.allChangingObjects.sort((a: ViewUnifiedChange, b: ViewUnifiedChange) => { if (a.getLineFrom() < b.getLineFrom()) { @@ -750,7 +744,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, tags_id: parentMotion.tags_id }); - if (this.amendmentTextMode === 'fulltext') { + const amendmentTextMode = this.configService.instant('motions_amendments_text_mode'); + if (amendmentTextMode === 'fulltext') { defaultMotion.text = parentMotion.text; this.contentForm.patchValue({ text: defaultMotion.text }); } @@ -1219,7 +1214,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, * Goes to the amendment creation wizard. Executed via click. */ public createAmendment(): void { - if (this.amendmentTextMode === 'paragraph') { + const amendmentTextMode = this.configService.instant('motions_amendments_text_mode'); + if (amendmentTextMode === 'paragraph') { this.router.navigate(['./create-amendment'], { relativeTo: this.route }); } else { this.router.navigate(['./motions/new-amendment'], { @@ -1551,6 +1547,16 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, * a change reco. The autoupdate has to come "after" this routine */ return ChangeRecoMode.Original; + } else if ( + mode === ChangeRecoMode.Diff && + !this.changeRecommendations?.length && + this.motion?.isParagraphBasedAmendment() + ) { + /** + * The Diff view for paragraph-based amendments is only relevant for change recommendations; + * the regular amendment changes are shown in the "original" view. + */ + return ChangeRecoMode.Original; } return mode; }