codecharta-visualization 1.86.0 → 1.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/Dockerfile +1 -1
  2. package/app/app.module.ts +6 -2
  3. package/app/codeCharta/codeCharta.model.ts +1 -1
  4. package/app/codeCharta/state/store/dynamicSettings/dynamicSettings.splitter.ts +2 -2
  5. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/currentFocused.selector.ts +8 -0
  6. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions.ts +27 -7
  7. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.spec.ts +27 -11
  8. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.ts +11 -5
  9. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector.ts +4 -0
  10. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.spec.ts +2 -2
  11. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.ts +1 -1
  12. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.actions.ts +9 -10
  13. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.spec.ts +37 -7
  14. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.ts +7 -3
  15. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.spec.ts +39 -0
  16. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.ts +19 -0
  17. package/app/codeCharta/state/store/state.splitter.spec.ts +4 -4
  18. package/app/codeCharta/state/store.service.spec.ts +3 -3
  19. package/app/codeCharta/state/store.service.ts +5 -0
  20. package/app/codeCharta/ui/artificialIntelligence/__snapshots__/artificialIntelligence.component.spec.ts.snap +13 -16
  21. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.html +4 -4
  22. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.scss +0 -4
  23. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.spec.ts +82 -52
  24. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.ts +41 -101
  25. package/app/codeCharta/ui/codeMap/codeMap.actions.service.ts +1 -40
  26. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +10 -16
  27. package/app/codeCharta/ui/colorPicker/colorPicker.component.html +16 -7
  28. package/app/codeCharta/ui/colorPicker/colorPicker.component.spec.ts +55 -16
  29. package/app/codeCharta/ui/colorPicker/colorPicker.component.ts +32 -1
  30. package/app/codeCharta/ui/colorPicker/colorPicker.module.ts +3 -1
  31. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +21 -3
  32. package/app/codeCharta/ui/customConfigs/customConfigs.component.scss +1 -0
  33. package/app/codeCharta/ui/customConfigs/customConfigs.component.spec.ts +123 -2
  34. package/app/codeCharta/ui/customConfigs/customConfigs.component.ts +56 -2
  35. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.html +21 -13
  36. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.spec.ts +11 -24
  37. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.ts +1 -40
  38. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.module.ts +1 -2
  39. package/app/codeCharta/ui/legendPanel/legendMarkedPackages/legendMarkedPackages.component.ts +2 -2
  40. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.html +24 -0
  41. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.spec.ts +55 -0
  42. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.ts +38 -0
  43. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module.ts +13 -0
  44. package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.spec.ts +31 -0
  45. package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.ts +25 -0
  46. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +8 -4
  47. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +1 -21
  48. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module.ts +1 -2
  49. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -12
  50. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +3 -1
  51. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +28 -125
  52. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +29 -55
  53. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -0
  54. package/app/codeCharta/ui/ui.ts +0 -2
  55. package/app/codeCharta/util/algorithm/streetLayout/strip/strip.ts +2 -2
  56. package/app/codeCharta/util/algorithm/streetLayout/treeMap.ts +1 -1
  57. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.spec.ts +1 -1
  58. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.spec.ts +2 -2
  59. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.ts +1 -1
  60. package/app/codeCharta/util/customConfigBuilder.ts +1 -1
  61. package/app/codeCharta/util/dataMocks.ts +2 -2
  62. package/app/codeCharta/util/fileExtensionCalculator.ts +1 -1
  63. package/dist/webpack/bundle.js +963 -934
  64. package/dist/webpack/bundle.js.map +1 -1
  65. package/package.json +6 -5
  66. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.splitter.ts +0 -8
  67. package/app/codeCharta/ui/codeMap/codeMap.actions.service.spec.ts +0 -147
  68. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.html +0 -15
  69. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.scss +0 -5
  70. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.spec.ts +0 -106
  71. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.ts +0 -62
  72. package/app/codeCharta/ui/unfocusButton/unfocusButton.module.ts +0 -7
package/Dockerfile CHANGED
@@ -1,3 +1,3 @@
1
- FROM nginx:1.21.4-alpine
1
+ FROM nginx:1.21.5-alpine
2
2
 
3
3
  COPY ./dist/webpack /usr/share/nginx/html
package/app/app.module.ts CHANGED
@@ -20,6 +20,8 @@ import { ColorPickerForMapColorModule } from "./codeCharta/ui/colorPickerForMapC
20
20
  import { ColorPickerForMapColorComponent } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.component"
21
21
  import { MarkFolderColorPickerModule } from "./codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module"
22
22
  import { MarkFolderColorPickerComponent } from "./codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component"
23
+ import { FocusButtonsModule } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module"
24
+ import { FocusButtonsComponent } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component"
23
25
 
24
26
  @NgModule({
25
27
  imports: [
@@ -31,7 +33,8 @@ import { MarkFolderColorPickerComponent } from "./codeCharta/ui/nodeContextMenu/
31
33
  Export3DMapButtonModule,
32
34
  LegendPanelModule,
33
35
  ColorPickerForMapColorModule,
34
- MarkFolderColorPickerModule
36
+ MarkFolderColorPickerModule,
37
+ FocusButtonsModule
35
38
  ],
36
39
  declarations: [],
37
40
  entryComponents: [
@@ -42,7 +45,8 @@ import { MarkFolderColorPickerComponent } from "./codeCharta/ui/nodeContextMenu/
42
45
  LegendPanelComponent,
43
46
  LabelledColorPickerComponent,
44
47
  ColorPickerForMapColorComponent,
45
- MarkFolderColorPickerComponent
48
+ MarkFolderColorPickerComponent,
49
+ FocusButtonsComponent
46
50
  ]
47
51
  })
48
52
  export class AppModule {
@@ -119,7 +119,7 @@ export interface DynamicSettings {
119
119
  colorMetric: string
120
120
  distributionMetric: string
121
121
  edgeMetric: string
122
- focusedNodePath: string
122
+ focusedNodePath: string[]
123
123
  searchPattern: string
124
124
  margin: number
125
125
  colorRange: ColorRange
@@ -7,11 +7,11 @@ import { splitEdgeMetricAction } from "./edgeMetric/edgeMetric.splitter"
7
7
  import { splitColorRangeAction } from "./colorRange/colorRange.splitter"
8
8
  import { splitMarginAction } from "./margin/margin.splitter"
9
9
  import { splitSearchPatternAction } from "./searchPattern/searchPattern.splitter"
10
- import { splitFocusedNodePathAction } from "./focusedNodePath/focusedNodePath.splitter"
11
10
  import { splitHeightMetricAction } from "./heightMetric/heightMetric.splitter"
12
11
  import { splitDistributionMetricAction } from "./distributionMetric/distributionMetric.splitter"
13
12
  import { splitColorMetricAction } from "./colorMetric/colorMetric.splitter"
14
13
  import { splitAreaMetricAction } from "./areaMetric/areaMetric.splitter"
14
+ import { setAllFocusedNodes } from "./focusedNodePath/focusedNodePath.actions"
15
15
 
16
16
  export function splitDynamicSettingsActions(payload: RecursivePartial<DynamicSettings>) {
17
17
  const actions: CCAction[] = []
@@ -45,7 +45,7 @@ export function splitDynamicSettingsActions(payload: RecursivePartial<DynamicSet
45
45
  }
46
46
 
47
47
  if (payload.focusedNodePath !== undefined) {
48
- actions.push(splitFocusedNodePathAction(payload.focusedNodePath))
48
+ actions.push(setAllFocusedNodes(payload.focusedNodePath))
49
49
  }
50
50
 
51
51
  if (payload.heightMetric !== undefined) {
@@ -0,0 +1,8 @@
1
+ import { createSelector } from "../../../angular-redux/createSelector"
2
+ import { CcState } from "../../store"
3
+ import { focusedNodePathSelector } from "./focusedNodePath.selector"
4
+
5
+ export const currentFocusedNodePathSelector: (state: CcState) => string | undefined = createSelector(
6
+ [focusedNodePathSelector],
7
+ focusedNodePath => focusedNodePath[0]
8
+ )
@@ -2,7 +2,9 @@ import { CCAction } from "../../../../codeCharta.model"
2
2
 
3
3
  export enum FocusedNodePathActions {
4
4
  FOCUS_NODE = "FOCUS_NODE",
5
- UNFOCUS_NODE = "UNFOCUS_NODE"
5
+ UNFOCUS_NODE = "UNFOCUS_NODE",
6
+ UNFOCUS_ALL_NODES = "UNFOCUS_ALL_NODES",
7
+ SET_ALL_FOCUSED_NODES = "SET_ALL_FOCUSED_NODES"
6
8
  }
7
9
 
8
10
  export interface FocusNodeAction extends CCAction {
@@ -12,12 +14,19 @@ export interface FocusNodeAction extends CCAction {
12
14
 
13
15
  export interface UnfocusNodeAction extends CCAction {
14
16
  type: FocusedNodePathActions.UNFOCUS_NODE
15
- payload: string
16
17
  }
17
18
 
18
- export type FocusedNodePathAction = FocusNodeAction | UnfocusNodeAction
19
+ export interface UnfocusAllNodesAction extends CCAction {
20
+ type: FocusedNodePathActions.UNFOCUS_ALL_NODES
21
+ }
22
+ export interface SetAllFocusedNodesAction extends CCAction {
23
+ type: FocusedNodePathActions.SET_ALL_FOCUSED_NODES
24
+ payload: string[]
25
+ }
26
+
27
+ export type FocusedNodePathAction = FocusNodeAction | UnfocusNodeAction | UnfocusAllNodesAction | SetAllFocusedNodesAction
19
28
 
20
- export function focusNode(focusedNodePath: string = defaultFocusedNodePath): FocusNodeAction {
29
+ export function focusNode(focusedNodePath: string): FocusNodeAction {
21
30
  return {
22
31
  type: FocusedNodePathActions.FOCUS_NODE,
23
32
  payload: focusedNodePath
@@ -26,9 +35,20 @@ export function focusNode(focusedNodePath: string = defaultFocusedNodePath): Foc
26
35
 
27
36
  export function unfocusNode(): UnfocusNodeAction {
28
37
  return {
29
- type: FocusedNodePathActions.UNFOCUS_NODE,
30
- payload: ""
38
+ type: FocusedNodePathActions.UNFOCUS_NODE
39
+ }
40
+ }
41
+
42
+ export function unfocusAllNodes(): UnfocusAllNodesAction {
43
+ return {
44
+ type: FocusedNodePathActions.UNFOCUS_ALL_NODES
45
+ }
46
+ }
47
+ export function setAllFocusedNodes(focusedNodePaths: string[]): SetAllFocusedNodesAction {
48
+ return {
49
+ type: FocusedNodePathActions.SET_ALL_FOCUSED_NODES,
50
+ payload: focusedNodePaths
31
51
  }
32
52
  }
33
53
 
34
- export const defaultFocusedNodePath = ""
54
+ export const defaultFocusedNodePath: string[] = []
@@ -1,40 +1,56 @@
1
1
  import { focusedNodePath } from "./focusedNodePath.reducer"
2
- import { FocusedNodePathAction, focusNode, unfocusNode } from "./focusedNodePath.actions"
2
+ import { FocusedNodePathAction, focusNode, setAllFocusedNodes, unfocusAllNodes, unfocusNode } from "./focusedNodePath.actions"
3
3
 
4
4
  describe("focusedNodePath", () => {
5
5
  describe("Default State", () => {
6
6
  it("should initialize the default state", () => {
7
7
  const result = focusedNodePath(undefined, {} as FocusedNodePathAction)
8
8
 
9
- expect(result).toEqual("")
9
+ expect(result).toEqual([])
10
10
  })
11
11
  })
12
12
 
13
13
  describe("Action: FOCUS_NODE", () => {
14
14
  it("should set new focusedNodePath", () => {
15
- const result = focusedNodePath("", focusNode("some/path/*.ts"))
15
+ const result = focusedNodePath([], focusNode("some/path/*.ts"))
16
16
 
17
- expect(result).toEqual("some/path/*.ts")
17
+ expect(result).toEqual(["some/path/*.ts"])
18
18
  })
19
19
 
20
- it("should set default focusedNodePath", () => {
21
- const result = focusedNodePath("some/path/*.ts", focusNode())
20
+ it("should add focusedNodePath", () => {
21
+ const result = focusedNodePath(["some/path/*.ts"], focusNode("foo.ts"))
22
22
 
23
- expect(result).toEqual("")
23
+ expect(result).toEqual(["foo.ts", "some/path/*.ts"])
24
24
  })
25
25
 
26
26
  it("should not allow to focus root folder", () => {
27
- const result = focusedNodePath("/root", focusNode())
27
+ const result = focusedNodePath([], focusNode("/root"))
28
28
 
29
- expect(result).toEqual("")
29
+ expect(result).toEqual([])
30
30
  })
31
31
  })
32
32
 
33
33
  describe("Action: UNFOCUS_NODE", () => {
34
34
  it("should remove focusedNodePath", () => {
35
- const result = focusedNodePath("some/path/*.ts", unfocusNode())
35
+ const result = focusedNodePath(["some/path/*.ts", "foo.ts"], unfocusNode())
36
36
 
37
- expect(result).toEqual("")
37
+ expect(result).toEqual(["foo.ts"])
38
+ })
39
+ })
40
+
41
+ describe("Action: UNFOCUS_ALL_NODES", () => {
42
+ it("should remove all focusedNodePaths", () => {
43
+ const result = focusedNodePath(["some/path/*.ts", "foo.ts"], unfocusAllNodes())
44
+
45
+ expect(result).toEqual([])
46
+ })
47
+ })
48
+
49
+ describe("Action: SET_ALL_FOCUSED_NODES", () => {
50
+ it("should set all focusedNodePaths", () => {
51
+ const result = focusedNodePath([], setAllFocusedNodes(["some/path/*.ts", "foo.ts"]))
52
+
53
+ expect(result).toEqual(["some/path/*.ts", "foo.ts"])
38
54
  })
39
55
  })
40
56
  })
@@ -1,12 +1,18 @@
1
- import { FocusedNodePathAction, FocusedNodePathActions, focusNode } from "./focusedNodePath.actions"
1
+ import { defaultFocusedNodePath, FocusedNodePathAction, FocusedNodePathActions } from "./focusedNodePath.actions"
2
2
  import { CodeChartaService } from "../../../../codeCharta.service"
3
3
 
4
- export function focusedNodePath(state = focusNode().payload, action: FocusedNodePathAction) {
4
+ export function focusedNodePath(state = defaultFocusedNodePath, action: FocusedNodePathAction) {
5
5
  switch (action.type) {
6
- case FocusedNodePathActions.FOCUS_NODE:
7
- return action.payload === CodeChartaService.ROOT_PATH ? state : action.payload
6
+ case FocusedNodePathActions.FOCUS_NODE: {
7
+ if (action.payload === CodeChartaService.ROOT_PATH) return state
8
+ return [action.payload, ...state]
9
+ }
8
10
  case FocusedNodePathActions.UNFOCUS_NODE:
9
- return action.payload
11
+ return state.slice(1)
12
+ case FocusedNodePathActions.UNFOCUS_ALL_NODES:
13
+ return []
14
+ case FocusedNodePathActions.SET_ALL_FOCUSED_NODES:
15
+ return [...action.payload]
10
16
  default:
11
17
  return state
12
18
  }
@@ -0,0 +1,4 @@
1
+ import { createSelector } from "../../../angular-redux/store"
2
+ import { dynamicSettingsSelector } from "../dynamicSettings.selector"
3
+
4
+ export const focusedNodePathSelector = createSelector([dynamicSettingsSelector], dynamicSettings => dynamicSettings.focusedNodePath)
@@ -57,7 +57,7 @@ describe("FocusedNodePathService", () => {
57
57
 
58
58
  focusedNodePathService.onStoreChanged(FocusedNodePathActions.FOCUS_NODE)
59
59
 
60
- expect($rootScope.$broadcast).toHaveBeenCalledWith("focus-node", { focusedNodePath: "some/path/*.ts" })
60
+ expect($rootScope.$broadcast).toHaveBeenCalledWith("focus-node", { focusedNodePath: ["some/path/*.ts"] })
61
61
  })
62
62
 
63
63
  it("should notify all subscribers with the new focusedNodePath value", () => {
@@ -85,7 +85,7 @@ describe("FocusedNodePathService", () => {
85
85
 
86
86
  focusedNodePathService.onFilesSelectionChanged()
87
87
 
88
- expect(storeService.getState().dynamicSettings.focusedNodePath).toEqual("")
88
+ expect(storeService.getState().dynamicSettings.focusedNodePath).toEqual([])
89
89
  })
90
90
  })
91
91
  })
@@ -43,7 +43,7 @@ export class FocusedNodePathService implements StoreSubscriber, FilesSelectionSu
43
43
  return this.storeService.getState().dynamicSettings.focusedNodePath
44
44
  }
45
45
 
46
- private notifyFocus(newState: string) {
46
+ private notifyFocus(newState: string[]) {
47
47
  this.$rootScope.$broadcast(FocusedNodePathService.FOCUS_NODE_EVENT, { focusedNodePath: newState })
48
48
  }
49
49
 
@@ -1,14 +1,13 @@
1
- import { CCAction, MarkedPackage } from "../../../../codeCharta.model"
1
+ import { CCAction, CodeMapNode, MarkedPackage } from "../../../../codeCharta.model"
2
2
 
3
3
  export enum MarkedPackagesActions {
4
4
  SET_MARKED_PACKAGES = "SET_MARKED_PACKAGES",
5
- CALCULATE_MARKED_PACKAGES_FOR_PATHS = "CALCULATE_MARKED_PACKAGES",
6
5
  MARK_PACKAGE = "MARK_PACKAGE",
7
6
  UNMARK_PACKAGE = "UNMARK_PACKAGE"
8
7
  }
9
8
 
10
- export interface CalculateMarkedPackagesAction extends CCAction {
11
- type: MarkedPackagesActions.CALCULATE_MARKED_PACKAGES_FOR_PATHS
9
+ export interface MarkPackagesAction extends CCAction {
10
+ type: MarkedPackagesActions.MARK_PACKAGE
12
11
  payload: MarkedPackage[]
13
12
  }
14
13
 
@@ -19,14 +18,14 @@ export interface SetMarkedPackagesAction extends CCAction {
19
18
 
20
19
  export interface UnmarkPackageAction extends CCAction {
21
20
  type: MarkedPackagesActions.UNMARK_PACKAGE
22
- payload: number
21
+ payload: CodeMapNode["path"]
23
22
  }
24
23
 
25
- export type MarkedPackagesAction = SetMarkedPackagesAction | UnmarkPackageAction | CalculateMarkedPackagesAction
24
+ export type MarkedPackagesAction = SetMarkedPackagesAction | UnmarkPackageAction | MarkPackagesAction
26
25
 
27
- export function calculateMarkedPackages(packagesToBeMarked: MarkedPackage[]): CalculateMarkedPackagesAction {
26
+ export function markPackages(packagesToBeMarked: MarkedPackage[]): MarkPackagesAction {
28
27
  return {
29
- type: MarkedPackagesActions.CALCULATE_MARKED_PACKAGES_FOR_PATHS,
28
+ type: MarkedPackagesActions.MARK_PACKAGE,
30
29
  payload: packagesToBeMarked
31
30
  }
32
31
  }
@@ -38,10 +37,10 @@ export function setMarkedPackages(markedPackages: MarkedPackage[] = defaultMarke
38
37
  }
39
38
  }
40
39
 
41
- export function unmarkPackage(index: number): UnmarkPackageAction {
40
+ export function unmarkPackage(node: Pick<CodeMapNode, "path">): UnmarkPackageAction {
42
41
  return {
43
42
  type: MarkedPackagesActions.UNMARK_PACKAGE,
44
- payload: index
43
+ payload: node.path
45
44
  }
46
45
  }
47
46
 
@@ -1,5 +1,5 @@
1
1
  import { markedPackages } from "./markedPackages.reducer"
2
- import { MarkedPackagesAction, setMarkedPackages, calculateMarkedPackages, unmarkPackage } from "./markedPackages.actions"
2
+ import { MarkedPackagesAction, setMarkedPackages, markPackages, unmarkPackage } from "./markedPackages.actions"
3
3
  import { MARKED_PACKAGES } from "../../../../util/dataMocks"
4
4
 
5
5
  describe("markedPackages", () => {
@@ -26,17 +26,47 @@ describe("markedPackages", () => {
26
26
  })
27
27
 
28
28
  describe("Action: UNMARK_PACKAGE", () => {
29
- it("should remove a marked package from array", () => {
30
- const result = markedPackages([MARKED_PACKAGES[0]], unmarkPackage(0))
31
-
29
+ it("should remove a marked package", () => {
30
+ const result = markedPackages([{ path: "/root", color: "#000000" }], unmarkPackage({ path: "/root" }))
32
31
  expect(result).toEqual([])
33
32
  })
33
+
34
+ it("should remove nothing, if a parent of a marked node is unmarked", () => {
35
+ const result = markedPackages([{ path: "/root/child", color: "#000000" }], unmarkPackage({ path: "/root" }))
36
+ expect(result).toEqual([{ path: "/root/child", color: "#000000" }])
37
+ })
34
38
  })
35
39
 
36
- describe("Action: CALCULATE_MARKED_PACKAGES", () => {
37
- it("should add all packages", () => {
38
- const result = markedPackages([MARKED_PACKAGES[0]], calculateMarkedPackages(MARKED_PACKAGES.slice(1)))
40
+ describe("Action: MARK_PACKAGES", () => {
41
+ it("should add a package", () => {
42
+ const result = markedPackages([MARKED_PACKAGES[0]], markPackages(MARKED_PACKAGES.slice(1)))
39
43
  expect(result).toEqual(MARKED_PACKAGES)
40
44
  })
45
+
46
+ it("should remove the children of a marked package if children marked color is the same", () => {
47
+ const result = markedPackages([{ path: "/root/child", color: "#000000" }], markPackages([{ path: "/root", color: "#000000" }]))
48
+ expect(result.length).toBe(1)
49
+ expect(result[0]).toEqual({ path: "/root", color: "#000000" })
50
+ })
51
+
52
+ it("should not remove the children of a marked package if color is different", () => {
53
+ const result = markedPackages([{ path: "/root/child", color: "#000000" }], markPackages([{ path: "/root", color: "#ffffff" }]))
54
+ expect(result.length).toBe(2)
55
+ expect(result[0]).toEqual({ path: "/root/child", color: "#000000" })
56
+ expect(result[1]).toEqual({ path: "/root", color: "#ffffff" })
57
+ })
58
+
59
+ it("should replace package if it was already marked", () => {
60
+ const result = markedPackages(
61
+ [
62
+ { path: "/root", color: "#ffffff" },
63
+ { path: "/root/child", color: "#000000" }
64
+ ],
65
+ markPackages([{ path: "/root", color: "#333333" }])
66
+ )
67
+ expect(result.length).toBe(2)
68
+ expect(result[0]).toEqual({ path: "/root", color: "#333333" })
69
+ expect(result[1]).toEqual({ path: "/root/child", color: "#000000" })
70
+ })
41
71
  })
42
72
  })
@@ -1,14 +1,18 @@
1
1
  import { MarkedPackagesAction, MarkedPackagesActions, setMarkedPackages } from "./markedPackages.actions"
2
2
  import { removeEntryAtIndexFromArray } from "../../../../util/reduxHelper"
3
3
  import { addMarkedPackage } from "./util/addMarkedPackage"
4
+ import { findIndexOfMarkedPackageOrParent } from "./util/findIndexOfMarkedPackageOrParent"
4
5
 
5
6
  export function markedPackages(state = setMarkedPackages().payload, action: MarkedPackagesAction) {
6
7
  switch (action.type) {
7
8
  case MarkedPackagesActions.SET_MARKED_PACKAGES:
8
9
  return action.payload
9
- case MarkedPackagesActions.UNMARK_PACKAGE:
10
- return removeEntryAtIndexFromArray(state, action.payload)
11
- case MarkedPackagesActions.CALCULATE_MARKED_PACKAGES_FOR_PATHS: {
10
+ case MarkedPackagesActions.UNMARK_PACKAGE: {
11
+ const indexOfPackageToBeUnmarked = findIndexOfMarkedPackageOrParent(state, action.payload)
12
+ if (indexOfPackageToBeUnmarked !== -1) return removeEntryAtIndexFromArray(state, indexOfPackageToBeUnmarked)
13
+ return state
14
+ }
15
+ case MarkedPackagesActions.MARK_PACKAGE: {
12
16
  const markedPackagesMap = new Map(state.map(entry => [entry.path, entry]))
13
17
 
14
18
  for (const markedPackage of action.payload) {
@@ -0,0 +1,39 @@
1
+ import { findIndexOfMarkedPackageOrParent } from "./findIndexOfMarkedPackageOrParent"
2
+
3
+ describe("findIndexOfMarkedPackageOrParent", () => {
4
+ it("should return -1 if given path is neither marked nor a child of a marked package", () => {
5
+ expect(
6
+ findIndexOfMarkedPackageOrParent(
7
+ [
8
+ { path: "/root/child/grandchild", color: "#ffffff" },
9
+ { path: "/root/child", color: "#000000" }
10
+ ],
11
+ "/root/wolf"
12
+ )
13
+ ).toBe(-1)
14
+ })
15
+
16
+ it("should find exact package even if a children was marked previously", () => {
17
+ expect(
18
+ findIndexOfMarkedPackageOrParent(
19
+ [
20
+ { path: "/root/child/grandchild", color: "#ffffff" },
21
+ { path: "/root/child", color: "#000000" }
22
+ ],
23
+ "/root/child"
24
+ )
25
+ ).toBe(1)
26
+ })
27
+
28
+ it("should find closest parent if given path is not marked", () => {
29
+ expect(
30
+ findIndexOfMarkedPackageOrParent(
31
+ [
32
+ { path: "/root/child", color: "#000000" },
33
+ { path: "/root/child/grandchild", color: "#ffffff" }
34
+ ],
35
+ "/root/child/grandchild/grandgrandchild"
36
+ )
37
+ ).toBe(1)
38
+ })
39
+ })
@@ -0,0 +1,19 @@
1
+ import { MarkedPackage } from "../../../../../codeCharta.model"
2
+
3
+ /** @return index of exact match if there is an exact match. Otherwise return index of parent or -1 */
4
+ export const findIndexOfMarkedPackageOrParent = (markedPackages: MarkedPackage[], nodePath: string) => {
5
+ const indexOfNodePath = markedPackages.findIndex(mp => mp.path === nodePath)
6
+ if (indexOfNodePath !== -1) return indexOfNodePath
7
+
8
+ let indexOfNearestParent = -1
9
+ for (let loopIndex = 0; loopIndex < markedPackages.length; loopIndex++) {
10
+ const markedPackage = markedPackages[loopIndex]
11
+ if (
12
+ nodePath.startsWith(markedPackage.path) &&
13
+ (indexOfNearestParent === -1 || markedPackages[indexOfNearestParent].path.length < markedPackage.path.length)
14
+ )
15
+ indexOfNearestParent = loopIndex
16
+ }
17
+
18
+ return indexOfNearestParent
19
+ }
@@ -40,7 +40,7 @@ describe("state.splitter", () => {
40
40
  it("should return 1 FOCUS_NODE action", () => {
41
41
  const partialState: RecursivePartial<State> = {
42
42
  dynamicSettings: {
43
- focusedNodePath: "/some/path"
43
+ focusedNodePath: ["/some/path"]
44
44
  }
45
45
  }
46
46
 
@@ -48,7 +48,7 @@ describe("state.splitter", () => {
48
48
 
49
49
  expect(result.length).toEqual(1)
50
50
 
51
- expect(result[0].type).toEqual(FocusedNodePathActions.FOCUS_NODE)
51
+ expect(result[0].type).toEqual(FocusedNodePathActions.SET_ALL_FOCUSED_NODES)
52
52
  })
53
53
 
54
54
  it("should return 3 atomic actions from different parts of the state", () => {
@@ -80,13 +80,13 @@ describe("state.splitter", () => {
80
80
  describe("setDynamicSettings", () => {
81
81
  it("should return 1 FOCUS_NODE action", () => {
82
82
  const partialDynamicSettings: RecursivePartial<DynamicSettings> = {
83
- focusedNodePath: "/some/path"
83
+ focusedNodePath: ["/some/path"]
84
84
  }
85
85
 
86
86
  const result: CCAction[] = splitStateActions(setDynamicSettings(partialDynamicSettings))
87
87
 
88
88
  expect(result.length).toEqual(1)
89
- expect(result[0].type).toEqual(FocusedNodePathActions.FOCUS_NODE)
89
+ expect(result[0].type).toEqual(FocusedNodePathActions.SET_ALL_FOCUSED_NODES)
90
90
  expect(result[0].payload).toEqual(partialDynamicSettings.focusedNodePath)
91
91
  })
92
92
  })
@@ -10,7 +10,7 @@ import { setDynamicSettings } from "./store/dynamicSettings/dynamicSettings.acti
10
10
  import { setMargin } from "./store/dynamicSettings/margin/margin.actions"
11
11
  import { setCamera } from "./store/appSettings/camera/camera.actions"
12
12
  import { setIsLoadingMap } from "./store/appSettings/isLoadingMap/isLoadingMap.actions"
13
- import { setIsLoadingFile } from "./store/appSettings/isLoadingFile/isLoadingFile.actions"
13
+ import { toggleSortingOrderAscending } from "./store/appSettings/sortingOrderAscending/sortingOrderAscending.actions"
14
14
 
15
15
  describe("StoreService", () => {
16
16
  let storeService: StoreService
@@ -118,9 +118,9 @@ describe("StoreService", () => {
118
118
  expect(storeService.getState().appSettings.isLoadingMap).toBeFalsy()
119
119
  })
120
120
 
121
- it("should show not the loading-gif when an action is triggered, that changes the loading-gif state", () => {
121
+ it("should show not the loading-gif when an action is triggered, that doesn't change the loading-gif state", () => {
122
122
  storeService.dispatch(setIsLoadingMap(false))
123
- storeService.dispatch(setIsLoadingFile(false))
123
+ storeService.dispatch(toggleSortingOrderAscending())
124
124
 
125
125
  expect(storeService.getState().appSettings.isLoadingMap).toBeFalsy()
126
126
  })
@@ -14,6 +14,7 @@ import { ExperimentalFeaturesEnabledActions } from "./store/appSettings/enableEx
14
14
  import { Store } from "./store/store"
15
15
  import { ScreenshotToClipboardEnabledActions } from "./store/appSettings/enableClipboard/screenshotToClipboardEnabled.actions"
16
16
  import { HoveredBuildingPathActions } from "./store/appStatus/hoveredBuildingPath/hoveredBuildingPath.actions"
17
+ import { unfocusAllNodes } from "./store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
17
18
 
18
19
  export interface StoreSubscriber {
19
20
  onStoreChanged(actionType: string)
@@ -65,6 +66,10 @@ export class StoreService {
65
66
  this.dispatch(setIsLoadingMap(true))
66
67
  }
67
68
 
69
+ if (isActionOfType(action.type, IsLoadingFileActions)) {
70
+ this.dispatch(unfocusAllNodes())
71
+ }
72
+
68
73
  for (const atomicAction of splitStateActions(action)) {
69
74
  this.originalDispatch(atomicAction)
70
75
  if (!options.silent) {
@@ -9,38 +9,26 @@ Object {
9
9
  }
10
10
  `;
11
11
 
12
- exports[`ArtificialIntelligenceController on files selection changed should clear and calculate risk profile for Java map 1`] = `
13
- Object {
14
- "highRisk": 37,
15
- "lowRisk": 46,
16
- "moderateRisk": 17,
17
- "veryHighRisk": 0,
18
- }
19
- `;
20
-
21
- exports[`ArtificialIntelligenceController on files selection changed should create custom config suggestions sorted by outlierCustomConfigId 1`] = `
12
+ exports[`ArtificialIntelligenceController on files selection changed should calculate suspicious metrics sorted by isOutlier 1`] = `
22
13
  Array [
23
14
  Object {
24
15
  "from": 365,
25
- "generalCustomConfigId": "mocked",
16
+ "isOutlier": true,
26
17
  "max": 0,
27
18
  "metric": "loc",
28
19
  "min": 0,
29
- "outlierCustomConfigId": "mocked",
30
20
  "to": 554,
31
21
  },
32
22
  Object {
33
23
  "from": 29,
34
- "generalCustomConfigId": "mocked",
24
+ "isOutlier": true,
35
25
  "max": 0,
36
26
  "metric": "functions",
37
27
  "min": 0,
38
- "outlierCustomConfigId": "mocked",
39
28
  "to": 44,
40
29
  },
41
30
  Object {
42
31
  "from": 48,
43
- "generalCustomConfigId": "mocked",
44
32
  "max": 0,
45
33
  "metric": "mcc",
46
34
  "min": 0,
@@ -49,8 +37,17 @@ Array [
49
37
  ]
50
38
  `;
51
39
 
52
- exports[`ArtificialIntelligenceController on files selection changed should create custom config suggestions sorted by outlierCustomConfigId 2`] = `
40
+ exports[`ArtificialIntelligenceController on files selection changed should calculate suspicious metrics sorted by isOutlier 2`] = `
53
41
  Array [
54
42
  "rloc (real lines of code)",
55
43
  ]
56
44
  `;
45
+
46
+ exports[`ArtificialIntelligenceController on files selection changed should clear and calculate risk profile for Java map 1`] = `
47
+ Object {
48
+ "highRisk": 37,
49
+ "lowRisk": 46,
50
+ "moderateRisk": 17,
51
+ "veryHighRisk": 0,
52
+ }
53
+ `;
@@ -43,8 +43,8 @@
43
43
  <ul class="suspicious-metrics">
44
44
  <li class="suspicious-metric" ng-repeat="item in $ctrl._viewModel.suspiciousMetricSuggestionLinks">
45
45
  <md-button
46
- class="metric-button {{ item.outlierCustomConfigId.length > 0 ? 'high-risk' : '' }}"
47
- ng-click="$ctrl.applyCustomConfig(item.generalCustomConfigId)"
46
+ class="metric-button"
47
+ ng-click="$ctrl.applySuspiciousMetric(item, false)"
48
48
  title="Apply Map Configuration to show files with suspicious metric {{
49
49
  item.metric
50
50
  }} and high risk or very high risk depending on selection"
@@ -54,8 +54,8 @@
54
54
 
55
55
  <md-button
56
56
  class="risk-button"
57
- ng-click="$ctrl.applyCustomConfig(item.outlierCustomConfigId)"
58
- ng-show="item.outlierCustomConfigId.length > 0"
57
+ ng-click="$ctrl.applySuspiciousMetric(item, true)"
58
+ ng-show="item.isOutlier"
59
59
  title="Show very high risk files"
60
60
  >
61
61
  <i class="fa fa-exclamation-triangle"></i>
@@ -68,10 +68,6 @@
68
68
  padding: 0 12px;
69
69
  text-transform: none;
70
70
  margin: 0;
71
-
72
- &.high-risk {
73
- border-radius: 5px 0 0 5px;
74
- }
75
71
  }
76
72
 
77
73
  .risk-button {