From 6a8ae93bef4946b74d8f73d3dd1c8635f08c924e Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Tue, 9 Jan 2024 10:57:38 +0100 Subject: [PATCH 1/4] Apply number of labels of custom config correctly #3339 --- .../renderCodeMap.effect.spec.ts | 10 +-- .../renderCodeMap.effect.ts | 7 +- .../updateVisibleTopLabels.effect.spec.ts | 82 +++++++++++++++++++ .../updateVisibleTopLabels.effect.ts | 22 +++-- .../heightSettingsPanel.component.html | 4 +- 5 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts diff --git a/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.spec.ts b/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.spec.ts index cc8206a10f..888c0dcfc3 100644 --- a/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.spec.ts +++ b/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.spec.ts @@ -1,13 +1,11 @@ import { TestBed } from "@angular/core/testing" import { Subject } from "rxjs" -import { Vector3 } from "three" import { CodeMapRenderService } from "../../../ui/codeMap/codeMap.render.service" import { ThreeRendererService } from "../../../ui/codeMap/threeViewer/threeRenderer.service" import { UploadFilesService } from "../../../ui/toolBar/uploadFilesButton/uploadFiles.service" import { wait } from "../../../util/testUtils/wait" import { accumulatedDataSelector } from "../../selectors/accumulatedData/accumulatedData.selector" import { setInvertArea } from "../../store/appSettings/invertArea/invertArea.actions" -import { setScaling } from "../../store/appSettings/scaling/scaling.actions" import { maxFPS, RenderCodeMapEffect } from "./renderCodeMap.effect" import { provideMockActions } from "@ngrx/effects/testing" import { Action } from "@ngrx/store" @@ -46,7 +44,7 @@ describe("renderCodeMapEffect", () => { actions$.complete() }) - it("should render throttled after actions requiring rerender, but not scale map", async () => { + it("should render throttled after actions requiring rerender and scale map", async () => { actions$.next(setInvertArea({ value: true })) actions$.next(setInvertArea({ value: true })) expect(codeMapRenderService.render).toHaveBeenCalledTimes(0) @@ -55,12 +53,6 @@ describe("renderCodeMapEffect", () => { await wait(maxFPS) expect(codeMapRenderService.render).toHaveBeenCalledTimes(1) expect(threeRendererService.render).toHaveBeenCalledTimes(1) - expect(codeMapRenderService.scaleMap).not.toHaveBeenCalled() - }) - - it("should scale map when scaling changes", async () => { - actions$.next(setScaling({ value: new Vector3(1, 1, 1) })) - await wait(maxFPS) expect(codeMapRenderService.scaleMap).toHaveBeenCalledTimes(1) }) diff --git a/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.ts b/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.ts index 9fc5e3e40d..e635aa4b1a 100644 --- a/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.ts +++ b/visualization/app/codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect.ts @@ -7,7 +7,6 @@ import { CodeMapRenderService } from "../../../ui/codeMap/codeMap.render.service import { ThreeRendererService } from "../../../ui/codeMap/threeViewer/threeRenderer.service" import { UploadFilesService } from "../../../ui/toolBar/uploadFilesButton/uploadFiles.service" import { accumulatedDataSelector } from "../../selectors/accumulatedData/accumulatedData.selector" -import { setScaling } from "../../store/appSettings/scaling/scaling.actions" import { actionsRequiringRerender } from "./actionsRequiringRerender" import { setIsLoadingFile } from "../../store/appSettings/isLoadingFile/isLoadingFile.actions" import { setIsLoadingMap } from "../../store/appSettings/isLoadingMap/isLoadingMap.actions" @@ -31,12 +30,10 @@ export class RenderCodeMapEffect { combineLatest([this.store.select(accumulatedDataSelector), this.actionsRequiringRender$]).pipe( filter(([accumulatedData]) => Boolean(accumulatedData.unifiedMapNode)), throttleTime(maxFPS, asyncScheduler, { leading: false, trailing: true }), - tap(([accumulatedData, action]) => { + tap(([accumulatedData]) => { this.codeMapRenderService.render(accumulatedData.unifiedMapNode) + this.codeMapRenderService.scaleMap() this.threeRendererService.render() - if (action.type === setScaling.type) { - this.codeMapRenderService.scaleMap() - } }), share() ), diff --git a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts new file mode 100644 index 0000000000..bdfa2879e0 --- /dev/null +++ b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts @@ -0,0 +1,82 @@ +import { MockStore, provideMockStore } from "@ngrx/store/testing" +import { UpdateVisibleTopLabelsEffect } from "./updateVisibleTopLabels.effect" +import { CcState } from "app/codeCharta/codeCharta.model" +import { TestBed } from "@angular/core/testing" +import { EffectsModule } from "@ngrx/effects" +import { State, StoreModule } from "@ngrx/store" +import { appReducers, setStateMiddleware } from "../../store/state.manager" +import { visibleFileStatesSelector } from "../../selectors/visibleFileStates.selector" +import { codeMapNodesSelector } from "../../selectors/accumulatedData/codeMapNodes.selector" +import { getLastAction } from "../../../../codeCharta/util/testUtils/store.utils" +import { setAmountOfTopLabels } from "../../store/appSettings/amountOfTopLabels/amountOfTopLabels.actions" + +describe("updateVisibleTopLabelsEffect", () => { + let store: MockStore + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + EffectsModule.forRoot([UpdateVisibleTopLabelsEffect]), + StoreModule.forRoot(appReducers, { metaReducers: [setStateMiddleware] }) + ], + providers: [ + provideMockStore({ + selectors: [ + { + selector: visibleFileStatesSelector, + value: {} + }, + { + selector: codeMapNodesSelector, + value: {} + } + ] + }), + { + provide: State, + useValue: { + getValue: () => ({ appSettings: { amountOfTopLabels: 5 } }) + } + } + ] + }) + store = TestBed.inject(MockStore) + }) + + it("should set amount of top labels to current app-settings when visible file-states are unchanged", async () => { + const visibleFileStates = {} + const codeMapNodes = {} + + store.overrideSelector(visibleFileStatesSelector, visibleFileStates as ReturnType) + store.overrideSelector(codeMapNodesSelector, codeMapNodes as ReturnType) + store.refreshState() + + expect(await getLastAction(store)).toEqual(setAmountOfTopLabels({ value: 5 })) + }) + + it("should calculate the amount of top labels when visible-file-states are changed", async () => { + const visibleFileStates = [ + { + file: { + fileMeta: { + fileName: "sample1.cc.json" + } + } + } + ] + const codeMapNodes = [ + { + name: "sample1.ts" + }, + { + name: "sample2.ts" + } + ] + + store.overrideSelector(visibleFileStatesSelector, visibleFileStates as ReturnType) + store.overrideSelector(codeMapNodesSelector, codeMapNodes as ReturnType) + store.refreshState() + + expect(await getLastAction(store)).toEqual(setAmountOfTopLabels({ value: 1 })) + }) +}) diff --git a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts index 7cc0b0a750..c8dac76a7e 100644 --- a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts +++ b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts @@ -1,23 +1,31 @@ import { Injectable } from "@angular/core" import { createEffect } from "@ngrx/effects" -import { map, withLatestFrom } from "rxjs" +import { combineLatest, map, pairwise } from "rxjs" import { visibleFileStatesSelector } from "../../selectors/visibleFileStates.selector" import { codeMapNodesSelector } from "../../selectors/accumulatedData/codeMapNodes.selector" import { setAmountOfTopLabels } from "../../store/appSettings/amountOfTopLabels/amountOfTopLabels.actions" import { getNumberOfTopLabels } from "./getNumberOfTopLabels" -import { Store } from "@ngrx/store" +import { State, Store } from "@ngrx/store" import { CcState } from "../../../codeCharta.model" @Injectable() export class UpdateVisibleTopLabelsEffect { - constructor(private store: Store) {} + constructor(private store: Store, private state: State) {} updateVisibleTopLabels$ = createEffect(() => - this.store.select(visibleFileStatesSelector).pipe( - withLatestFrom(this.store.select(codeMapNodesSelector)), - map(([, codeMapNodes]) => { - return setAmountOfTopLabels({ value: getNumberOfTopLabels(codeMapNodes) }) + combineLatest([ + this.store.select(visibleFileStatesSelector).pipe(pairwise()), + this.store.select(codeMapNodesSelector).pipe(pairwise()) + ]).pipe( + map(([[previousVisibleFileStates, currentVisibleFileStates], [, currentCodeMapNodes]]) => { + const state = this.state.getValue() + const isVisibleFileStatesUnchanged = JSON.stringify(previousVisibleFileStates) === JSON.stringify(currentVisibleFileStates) + const amountOfTopLabels = isVisibleFileStatesUnchanged + ? state.appSettings.amountOfTopLabels + : getNumberOfTopLabels(currentCodeMapNodes) + + return setAmountOfTopLabels({ value: amountOfTopLabels }) }) ) ) diff --git a/visualization/app/codeCharta/ui/ribbonBar/heightSettingsPanel/heightSettingsPanel.component.html b/visualization/app/codeCharta/ui/ribbonBar/heightSettingsPanel/heightSettingsPanel.component.html index 80d467b728..a67de9ad00 100644 --- a/visualization/app/codeCharta/ui/ribbonBar/heightSettingsPanel/heightSettingsPanel.component.html +++ b/visualization/app/codeCharta/ui/ribbonBar/heightSettingsPanel/heightSettingsPanel.component.html @@ -25,8 +25,8 @@ class="cc-height-settings-panel-row" title="Height" label="Height" - [step]="0.1" - [min]="0.1" + [step]="1" + [min]="1" [max]="5" [value]="(scaling$ | async).y" [onChange]="applyDebouncedScalingY" From f3a857d1c1926d76b6aae426e3319bbafd0b238b Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Tue, 9 Jan 2024 11:31:09 +0100 Subject: [PATCH 2/4] Trigger computation of top labels only on file changes #3339 --- .../updateVisibleTopLabels.effect.spec.ts | 24 ++++++++----------- .../updateVisibleTopLabels.effect.ts | 20 +++++++--------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts index bdfa2879e0..88085d00d1 100644 --- a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts +++ b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.spec.ts @@ -24,11 +24,18 @@ describe("updateVisibleTopLabelsEffect", () => { selectors: [ { selector: visibleFileStatesSelector, - value: {} + value: [] }, { selector: codeMapNodesSelector, - value: {} + value: [ + { + name: "sample1.ts" + }, + { + name: "sample2.ts" + } + ] } ] }), @@ -44,11 +51,9 @@ describe("updateVisibleTopLabelsEffect", () => { }) it("should set amount of top labels to current app-settings when visible file-states are unchanged", async () => { - const visibleFileStates = {} - const codeMapNodes = {} + const visibleFileStates = [] store.overrideSelector(visibleFileStatesSelector, visibleFileStates as ReturnType) - store.overrideSelector(codeMapNodesSelector, codeMapNodes as ReturnType) store.refreshState() expect(await getLastAction(store)).toEqual(setAmountOfTopLabels({ value: 5 })) @@ -64,17 +69,8 @@ describe("updateVisibleTopLabelsEffect", () => { } } ] - const codeMapNodes = [ - { - name: "sample1.ts" - }, - { - name: "sample2.ts" - } - ] store.overrideSelector(visibleFileStatesSelector, visibleFileStates as ReturnType) - store.overrideSelector(codeMapNodesSelector, codeMapNodes as ReturnType) store.refreshState() expect(await getLastAction(store)).toEqual(setAmountOfTopLabels({ value: 1 })) diff --git a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts index c8dac76a7e..0b388c0691 100644 --- a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts +++ b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core" import { createEffect } from "@ngrx/effects" -import { combineLatest, map, pairwise } from "rxjs" +import { map, pairwise, withLatestFrom } from "rxjs" import { visibleFileStatesSelector } from "../../selectors/visibleFileStates.selector" import { codeMapNodesSelector } from "../../selectors/accumulatedData/codeMapNodes.selector" import { setAmountOfTopLabels } from "../../store/appSettings/amountOfTopLabels/amountOfTopLabels.actions" @@ -14,16 +14,14 @@ export class UpdateVisibleTopLabelsEffect { constructor(private store: Store, private state: State) {} updateVisibleTopLabels$ = createEffect(() => - combineLatest([ - this.store.select(visibleFileStatesSelector).pipe(pairwise()), - this.store.select(codeMapNodesSelector).pipe(pairwise()) - ]).pipe( - map(([[previousVisibleFileStates, currentVisibleFileStates], [, currentCodeMapNodes]]) => { - const state = this.state.getValue() - const isVisibleFileStatesUnchanged = JSON.stringify(previousVisibleFileStates) === JSON.stringify(currentVisibleFileStates) - const amountOfTopLabels = isVisibleFileStatesUnchanged - ? state.appSettings.amountOfTopLabels - : getNumberOfTopLabels(currentCodeMapNodes) + this.store.select(visibleFileStatesSelector).pipe( + pairwise(), + withLatestFrom(this.store.select(codeMapNodesSelector)), + map(([[previousVisibleFileStates, currentVisibleFileStates], codeMapNodes]) => { + const isUnchanged = JSON.stringify(previousVisibleFileStates) === JSON.stringify(currentVisibleFileStates) + const amountOfTopLabels = isUnchanged + ? this.state.getValue().appSettings.amountOfTopLabels + : getNumberOfTopLabels(codeMapNodes) return setAmountOfTopLabels({ value: amountOfTopLabels }) }) From 06fc9a087feaa7e29c7db74c09e9094a3216e2f5 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Tue, 9 Jan 2024 11:35:31 +0100 Subject: [PATCH 3/4] Update changelog #3339 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c903378066..b639b2fc0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/) ### Fixed 🐞 +- Fix saving the number of top-labels in custom configs [#3461](https://github.com/MaibornWolff/codecharta/pull/3461) - Fix parsers crashing after printing output to stdout [#3442](https://github.com/MaibornWolff/codecharta/pull/3442) - Fix removal of nodes with identical names in `modify` [#3446](https://github.com/MaibornWolff/codecharta/pull/3446) - Fix the highlighting of very high risk metrics to highlight only matching files [#3454](https://github.com/MaibornWolff/codecharta/pull/3454) From c947f7c06fce855072b3d0b9631c8d0ee3b1796c Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Tue, 9 Jan 2024 15:44:31 +0100 Subject: [PATCH 4/4] Compare entries with stable stringify #3339 --- .../updateVisibleTopLabels.effect.ts | 7 ++++--- visualization/package-lock.json | 6 ++++-- visualization/package.json | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts index 0b388c0691..68d2e08be9 100644 --- a/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts +++ b/visualization/app/codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect.ts @@ -1,12 +1,13 @@ +import stringify from "safe-stable-stringify" import { Injectable } from "@angular/core" +import { State, Store } from "@ngrx/store" import { createEffect } from "@ngrx/effects" - import { map, pairwise, withLatestFrom } from "rxjs" + import { visibleFileStatesSelector } from "../../selectors/visibleFileStates.selector" import { codeMapNodesSelector } from "../../selectors/accumulatedData/codeMapNodes.selector" import { setAmountOfTopLabels } from "../../store/appSettings/amountOfTopLabels/amountOfTopLabels.actions" import { getNumberOfTopLabels } from "./getNumberOfTopLabels" -import { State, Store } from "@ngrx/store" import { CcState } from "../../../codeCharta.model" @Injectable() @@ -18,7 +19,7 @@ export class UpdateVisibleTopLabelsEffect { pairwise(), withLatestFrom(this.store.select(codeMapNodesSelector)), map(([[previousVisibleFileStates, currentVisibleFileStates], codeMapNodes]) => { - const isUnchanged = JSON.stringify(previousVisibleFileStates) === JSON.stringify(currentVisibleFileStates) + const isUnchanged = stringify(previousVisibleFileStates) === stringify(currentVisibleFileStates) const amountOfTopLabels = isUnchanged ? this.state.getValue().appSettings.amountOfTopLabels : getNumberOfTopLabels(codeMapNodes) diff --git a/visualization/package-lock.json b/visualization/package-lock.json index fb9ea9d219..652dca03af 100644 --- a/visualization/package-lock.json +++ b/visualization/package-lock.json @@ -34,6 +34,7 @@ "pako": "^2.0.4", "percent-round": "^2.2.1", "rxjs": "^7.5.1", + "safe-stable-stringify": "^2.4.3", "shelljs": "^0.8.4", "three": "^0.126.1", "three-orbit-controls": "^82.1.0", @@ -18150,8 +18151,9 @@ } }, "node_modules/safe-stable-stringify": { - "version": "2.4.2", - "license": "MIT", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "engines": { "node": ">=10" } diff --git a/visualization/package.json b/visualization/package.json index 6302785a15..20687b2f5e 100644 --- a/visualization/package.json +++ b/visualization/package.json @@ -88,6 +88,7 @@ "pako": "^2.0.4", "percent-round": "^2.2.1", "rxjs": "^7.5.1", + "safe-stable-stringify": "^2.4.3", "shelljs": "^0.8.4", "three": "^0.126.1", "three-orbit-controls": "^82.1.0",