Skip to content

Commit

Permalink
Feature/1066/display tooltip description in frontend (#3162)
Browse files Browse the repository at this point in the history
* chore(deps): update dependency @types/node to v18

* chore(deps): update dependency @types/node to v18

* Migrate to nodev18

* Add: attributeDescriptor TEST to multiple Files (Still one compile error) #1066

* Add: missing reducer statement - no compile error anymore#1066

* Refactor: rename "Size" metric in legendPanel to "Area"#1066

the word "Size" is quite unusual at this position because in the code and in the ribbonbar the word "Area" is used

* Refactor: some consoleprints and delete unused variables and methods"#1066

* Refactor: delete "test" node in attributeDescriptors layout#1066

* Add: entry for download feature #1066

* Refactor: move getDescription function to legendMetrics #1066

* Add: implementation for merged attributeDescriptors.merger #1066

* Add: attributeDescriptor to attributeDescriptors settings #1066

* Add: if condition to show description in legend block for every metric type #1066

* Refactor: methods and settings layout to fit new cc.json format #1066

* Fix: test errors #1066

* Add: title for legend blocks in legend #1066

* Fix: remove title from color picker #1066

* Add: case for existing title and missing description #1066

* Refactor: text in legendBlock to be uniform #1066

* Refactor: metricTitles cases to fit to new attribute descriptors #1066

* Fix: failing tests #1066

* Fix: format tests #1066

* Fix: test coverage #1066

* Fix: test coverage error #1066

* Update webpack and tapable

* Fix: test coverage error second try #1066

* Refactor: metric name to key #1066

* Fix: refactoring erros #1066

* Chore: Merge main

* Chore: Update puppeteer to see if that fixes the pipeline

* Chore: remove now unused method from puppeteer helper

* Test: change jest testTimeout to 80s #1066

* Fix: PR comments #1066

* Revert "Test: change jest testTimeout to 80s #1066"

This reverts commit 48f45f8.
I reverted this commit, because it's not the suitable branch for it.

* Fix: test error #1066

* TEST Refactor: change "testTimeout": 800000 #2326

* TEST Refactor: waitForFileChooser({ timeout: 800_000 #2326

* TEST Refactor: don't runInBand #2326

* fix: downgrade puppeteer 19 -> 16 again

* Revert "TEST Refactor: waitForFileChooser({ timeout: 800_000 #2326"

This reverts commit 8ce820e.

* Revert "TEST Refactor: don't runInBand #2326"

This reverts commit baf77cf.

* Revert "TEST Refactor: change "testTimeout": 800000 #2326"

This reverts commit 0f5e5d5.

* fix: upgrade puppeteer one last time 16 -> 17

* Add: Test for attributeDescriptors.reducer #2326

* Add changelog entry #2326

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: luig59 <luig59@mi.fu-berlin.de>
Co-authored-by: MW-Friedrich <108457762+MW-Friedrich@users.noreply.github.com>
  • Loading branch information
4 people committed Dec 9, 2022
1 parent c3c2268 commit 9740b92
Show file tree
Hide file tree
Showing 41 changed files with 483 additions and 88 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/)

### Chore 👨‍💻 👩‍💻

- Metric titles in the legend are read from cc.json now [#3162](https://github.com/MaibornWolff/codecharta/pull/3162)
- Add attribute descriptors to SoureCodeParser [#3166](https://github.com/MaibornWolff/codecharta/pull/3166)

## [1.112.1] - 2022-12-01
Expand Down
12 changes: 11 additions & 1 deletion visualization/app/codeCharta/codeCharta.api.model.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Vector3 } from "three"
import { AttributeTypes, AttributeTypeValue, CodeMapNode, Edge, MarkedPackage, RecursivePartial, Settings } from "./codeCharta.model"
import {
AttributeDescriptors,
AttributeTypes,
AttributeTypeValue,
CodeMapNode,
Edge,
MarkedPackage,
RecursivePartial,
Settings
} from "./codeCharta.model"

export interface ExportCCFile {
projectName: string
apiVersion: string
fileChecksum: string
nodes: CodeMapNode[]
attributeTypes?: AttributeTypes | OldAttributeTypes
attributeDescriptors?: AttributeDescriptors
edges?: Edge[]
markedPackages?: MarkedPackage[]
blacklist?: ExportBlacklistItem[]
Expand Down
13 changes: 13 additions & 0 deletions visualization/app/codeCharta/codeCharta.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export interface Settings {

export interface FileSettings {
attributeTypes: AttributeTypes
attributeDescriptors: AttributeDescriptors
blacklist: Array<BlacklistItem>
edges: Edge[]
markedPackages: MarkedPackage[]
Expand Down Expand Up @@ -186,6 +187,18 @@ export interface AttributeTypes {
edges?: { [key: string]: AttributeTypeValue }
}

export interface AttributeDescriptors {
[key: string]: AttributeDescriptor
}

export interface AttributeDescriptor {
title: string
description: string
hintLowValue: string
hintHighValue: string
link: string
}

export enum AttributeTypeValue {
absolute = "absolute",
relative = "relative"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe("loadFileService", () => {
settings: {
fileSettings: {
attributeTypes: { nodes: {}, edges: {} },
attributeDescriptors: {},
blacklist: [],
edges: [],
markedPackages: []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ describe("UpdateFileSettingsEffect", () => {
edges: [],
markedPackages: [],
blacklist: [],
attributeTypes: {}
attributeTypes: {},
attributeDescriptors: {}
}
})
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, Inject } from "@angular/core"
import { Inject, Injectable } from "@angular/core"
import { filter, map } from "rxjs"
import { getVisibleFiles, isPartialState } from "../../../model/files/files.helper"
import { isActionOfType } from "../../../util/reduxHelper"
Expand All @@ -12,6 +12,7 @@ import { getMergedAttributeTypes } from "./utils/attributeTypes.merger"
import { getMergedBlacklist } from "./utils/blacklist.merger"
import { getMergedEdges } from "./utils/edges.merger"
import { getMergedMarkedPackages } from "./utils/markedPackages.merger"
import { getMergedAttributeDescriptors } from "./utils/attributeDescriptors.merger"

@Injectable()
export class UpdateFileSettingsEffect {
Expand All @@ -25,12 +26,16 @@ export class UpdateFileSettingsEffect {
const visibleFiles = getVisibleFiles(state.files)
const withUpdatedPath = isPartialState(state.files)
const allAttributeTypes = visibleFileStatesSelector(state).map(({ file }) => file.settings.fileSettings.attributeTypes)
const allAttributeDescriptors = visibleFileStatesSelector(state).map(
({ file }) => file.settings.fileSettings.attributeDescriptors
)
return setState({
fileSettings: {
edges: getMergedEdges(visibleFiles, withUpdatedPath),
markedPackages: getMergedMarkedPackages(visibleFiles, withUpdatedPath),
blacklist: getMergedBlacklist(visibleFiles, withUpdatedPath),
attributeTypes: getMergedAttributeTypes(allAttributeTypes)
attributeTypes: getMergedAttributeTypes(allAttributeTypes),
attributeDescriptors: getMergedAttributeDescriptors(allAttributeDescriptors)
}
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { AttributeDescriptors } from "../../../../codeCharta.model"
import { getMergedAttributeDescriptors } from "./attributeDescriptors.merger"

describe("AttributeDescriptorsMerger", () => {
describe("getMergedAttributeDescriptors", () => {
let attributes1: AttributeDescriptors
let attributes2: AttributeDescriptors
let attributes3: AttributeDescriptors

beforeEach(() => {
attributes1 = {}

attributes2 = {
rloc: {
title: "rloc2",
description: "",
hintLowValue: "",
hintHighValue: "",
link: "https://www.npmjs.com/package/metric-gardener"
}
}

attributes3 = {
rloc: {
title: "rloc3",
description: "DescriptionRloc3",
hintLowValue: "",
hintHighValue: "",
link: "https://www.npmjs.com/package/metric-gardener"
},
comment_lines: {
title: "Comment Lines",
description: "Number of lines containing either comment or commented-out code",
hintLowValue: "",
hintHighValue: "",
link: "https://www.npmjs.com/package/metric-gardener"
}
}
})

it("should merge attributeDescriptors if one file does not contain any attributeDescriptors", () => {
const attributeDescriptors = getMergedAttributeDescriptors([attributes1, attributes2])

expect(attributeDescriptors).toEqual(attributes2)
})

it("should merge attributeDescriptors. If they share the same key, simply take the first attributeDescriptor", () => {
const attributeDescriptors = getMergedAttributeDescriptors([attributes2, attributes3])

const expected = {
rloc: {
title: "rloc2",
description: "",
hintLowValue: "",
hintHighValue: "",
link: "https://www.npmjs.com/package/metric-gardener"
},
comment_lines: {
title: "Comment Lines",
description: "Number of lines containing either comment or commented-out code",
hintLowValue: "",
hintHighValue: "",
link: "https://www.npmjs.com/package/metric-gardener"
}
}

expect(attributeDescriptors).toEqual(expected)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { AttributeDescriptors } from "../../../../codeCharta.model"

export function getMergedAttributeDescriptors(allAttributeDescriptors: AttributeDescriptors[]): AttributeDescriptors {
const uniqueAttributeDescriptors = {}

for (const attributeDescriptors of allAttributeDescriptors) {
for (const attributeDescriptorKey of Object.keys(attributeDescriptors)) {
if (!uniqueAttributeDescriptors[attributeDescriptorKey]) {
uniqueAttributeDescriptors[attributeDescriptorKey] = attributeDescriptors[attributeDescriptorKey]
}
}
}

return uniqueAttributeDescriptors
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { AttributeDescriptors, CCAction } from "../../../../codeCharta.model"

export enum AttributeDescriptorsActions {
SET_ATTRIBUTE_DESCRIPTORS = "SET_ATTRIBUTE_DESCRIPTORS"
}

export interface SetAttributeDescriptorsAction extends CCAction {
type: AttributeDescriptorsActions.SET_ATTRIBUTE_DESCRIPTORS
payload: AttributeDescriptors
}

export type AttributeDescriptorsAction = SetAttributeDescriptorsAction

export function setAttributeDescriptors(
attributeDescriptors: AttributeDescriptors = defaultAttributeDescriptors
): SetAttributeDescriptorsAction {
return {
type: AttributeDescriptorsActions.SET_ATTRIBUTE_DESCRIPTORS,
payload: attributeDescriptors
}
}

export const defaultAttributeDescriptors: AttributeDescriptors = {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { attributeDescriptors } from "./attributeDescriptors.reducer"
import { STATE } from "../../../../util/dataMocks"
import { AttributeDescriptors } from "../../../../codeCharta.model"
import { AttributeDescriptorsAction, setAttributeDescriptors } from "./attributeDescriptors.action"

describe("attributeDescriptors", () => {
const defaultValue: AttributeDescriptors = {}

describe("Default State", () => {
it("should initialize the default state", () => {
const result = attributeDescriptors(undefined, {} as AttributeDescriptorsAction)

expect(result).toEqual(defaultValue)
})
})

describe("Action: SET_ATTRIBUTE_DESCRIPTORS", () => {
it("should set new attributeDescriptors", () => {
const result = attributeDescriptors(defaultValue, setAttributeDescriptors(STATE.fileSettings.attributeDescriptors))

expect(result).toEqual(STATE.fileSettings.attributeDescriptors)
})

it("should set default attributeDescriptors", () => {
const result = attributeDescriptors(STATE.fileSettings.attributeDescriptors, setAttributeDescriptors())

expect(result).toEqual(defaultValue)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { AttributeDescriptorsAction, AttributeDescriptorsActions, setAttributeDescriptors } from "./attributeDescriptors.action"

export function attributeDescriptors(state = setAttributeDescriptors().payload, action: AttributeDescriptorsAction) {
if (action.type === AttributeDescriptorsActions.SET_ATTRIBUTE_DESCRIPTORS) {
return action.payload
}
return state
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { CcState } from "../../store"

export const attributeDescriptorsSelector = (state: CcState) => state.fileSettings.attributeDescriptors
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CCAction, FileSettings, RecursivePartial } from "../../../codeCharta.model"

import { defaultAttributeTypes } from "./attributeTypes/attributeTypes.actions"
import { defaultAttributeDescriptors } from "./attributeDescriptors/attributeDescriptors.action"
import { defaultBlacklist } from "./blacklist/blacklist.actions"
import { defaultEdges } from "./edges/edges.actions"
import { defaultMarkedPackages } from "./markedPackages/markedPackages.actions"
Expand All @@ -25,6 +26,7 @@ export function setFileSettings(fileSettings: RecursivePartial<FileSettings> = d

export const defaultFileSettings: FileSettings = {
attributeTypes: defaultAttributeTypes,
attributeDescriptors: defaultAttributeDescriptors,
blacklist: defaultBlacklist,
edges: defaultEdges,
markedPackages: defaultMarkedPackages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { edges } from "./edges/edges.reducer"
import { attributeTypes } from "./attributeTypes/attributeTypes.reducer"
import { blacklist } from "./blacklist/blacklist.reducer"
import { combineReducers } from "redux"
import { attributeDescriptors } from "./attributeDescriptors/attributeDescriptors.reducer"

const fileSettings = combineReducers({
markedPackages,
edges,
attributeTypes,
attributeDescriptors,
blacklist
})

Expand Down
1 change: 1 addition & 0 deletions visualization/app/codeCharta/state/store/state.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function isSetStateAction(action: Action): action is SetStateAction {

const objectWithDynamicKeysInStore = new Set([
"fileSettings.attributeTypes",
"fileSettings.attributeDescriptors",
"fileSettings.blacklist",
"fileSettings.edges",
"fileSettings.markedPackages",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</span>
</div>
<div class="cc-labelled-color-picker-label">
<span *ngFor="let label of labels" [title]="label"> {{ label }} <br *ngIf="!last" /></span>
<span *ngFor="let label of labels"> {{ label }} <br *ngIf="!last" /></span>
</div>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
<div *ngIf="legendMetric.description" class="legend-block">
{{ metricFor }} metric (<span class="bold">{{ legendMetric.metricName }}</span
>: {{ legendMetric.description }})
</div>
<div *ngIf="!legendMetric.description" class="legend-block">
{{ metricFor }} metric: <span class="bold">{{ legendMetric.metricName }}</span>
</div>
<ng-container *ngIf="legendMetric.title; then titleExists; else onlyShowName" class="legend-block"></ng-container>
<ng-template #titleExists>
<ng-container *ngIf="legendMetric.description; then showTitleAndDescription; else showTitle"></ng-container>
</ng-template>

<ng-template #showTitleAndDescription>
<div title="{{ legendMetric.key + ': ' + legendMetric.description }}">
{{ metricFor }} metric: <span class="bold">{{ legendMetric.title }}</span> ({{ legendMetric.key }})
</div>
</ng-template>
<ng-template #showTitle>
<div title="{{ legendMetric.key }}">
{{ metricFor }} metric: <span class="bold">{{ legendMetric.title }}</span> ({{ legendMetric.key }})
</div>
</ng-template>
<ng-template #onlyShowName>
<div title="{{ legendMetric.key }}">
{{ metricFor }} metric: <span class="bold">{{ legendMetric.key }}</span>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<div class="block-wrapper" [class.visible]="isLegendVisible" [class.isAttributeSideBarVisible]="isAttributeSideBarVisibleService.isOpen">
<div *ngIf="!(isDeltaState$ | async)">
<cc-legend-block [metricFor]="'Size'" [legendMetric]="areaMetric$ | async"></cc-legend-block>
<cc-legend-block [metricFor]="'Area'" [legendMetric]="areaMetric$ | async"></cc-legend-block>
<cc-legend-block [metricFor]="'Height'" [legendMetric]="heightMetric$ | async"></cc-legend-block>
<cc-legend-block *ngIf="edgeMetric$ | async; let edgeMetric" [metricFor]="'Edge'" [legendMetric]="edgeMetric"></cc-legend-block>

<hr />
<cc-legend-block [metricFor]="'Color'" [legendMetric]="colorMetric$ | async"></cc-legend-block>
<cc-color-picker-for-map-color [mapColorFor]="'positive'"></cc-color-picker-for-map-color>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ describe("LegendPanelController", () => {
expect(areDeltaEntriesShown).toBe(false)

const metricDescriptions = container.querySelectorAll("cc-legend-block")
expect(metricDescriptions[0].textContent).toMatch("Size metric (loc: lines of code)")
expect(metricDescriptions[1].textContent).toMatch("Height metric (mcc: cyclomatic complexity)")
expect(metricDescriptions[2].textContent).toMatch("Color metric (rloc: real lines of code)")
expect(metricDescriptions[0].textContent).toMatch("Area metric: Lines of Code (loc)")
expect(metricDescriptions[1].textContent).toMatch("Height metric: Cyclomatic Complexity (mcc)")
expect(metricDescriptions[2].textContent).toMatch("Color metric: Real Lines of Code (rloc)")
})

it("should display legend for delta mode", async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createSelector } from "../../../state/angular-redux/createSelector"
import { areaMetricSelector } from "../../../state/store/dynamicSettings/areaMetric/areaMetric.selector"
import { attributeDescriptorsSelector } from "../../../state/store/fileSettings/attributeDescriptors/attributesDescriptors.selector"
import { CcState } from "../../../state/store/store"
import { metricDescriptions } from "../../../util/metric/metricDescriptions"
import { LegendMetric } from "./legendMetric"
import { getLegendMetric, LegendMetric } from "./legendMetric"

export const legendAreaMetricSelector: (state: CcState) => LegendMetric = createSelector([areaMetricSelector], areaMetric => ({
metricName: areaMetric,
description: metricDescriptions.get(areaMetric)
}))
export const legendAreaMetricSelector: (state: CcState) => LegendMetric = createSelector(
[areaMetricSelector, attributeDescriptorsSelector],
(areaMetric, attributeDescriptors) => getLegendMetric(areaMetric, attributeDescriptors)
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createSelector } from "../../../state/angular-redux/createSelector"
import { colorMetricSelector } from "../../../state/store/dynamicSettings/colorMetric/colorMetric.selector"
import { CcState } from "../../../state/store/store"
import { metricDescriptions } from "../../../util/metric/metricDescriptions"
import { LegendMetric } from "./legendMetric"
import { getLegendMetric, LegendMetric } from "./legendMetric"
import { attributeDescriptorsSelector } from "../../../state/store/fileSettings/attributeDescriptors/attributesDescriptors.selector"

export const legendColorMetricSelector: (state: CcState) => LegendMetric = createSelector([colorMetricSelector], colorMetric => ({
metricName: colorMetric,
description: metricDescriptions.get(colorMetric)
}))
export const legendColorMetricSelector: (state: CcState) => LegendMetric = createSelector(
[colorMetricSelector, attributeDescriptorsSelector],
(colorMetric, attributeDescriptors) => getLegendMetric(colorMetric, attributeDescriptors)
)

0 comments on commit 9740b92

Please sign in to comment.