codecharta-visualization 1.87.1 → 1.88.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 (67) hide show
  1. package/app/app.module.ts +18 -8
  2. package/app/codeCharta/codeCharta.component.ts +2 -0
  3. package/app/codeCharta/codeCharta.model.ts +2 -0
  4. package/app/codeCharta/codeCharta.service.spec.ts +41 -50
  5. package/app/codeCharta/codeCharta.service.ts +33 -32
  6. package/app/codeCharta/e2e/url.e2e.ts +1 -1
  7. package/app/codeCharta/state/store/appStatus/appStatus.reducer.ts +3 -1
  8. package/app/codeCharta/state/store/appStatus/appStatus.selector.ts +3 -0
  9. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions.ts +23 -0
  10. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.reducer.ts +15 -0
  11. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector.ts +4 -0
  12. package/app/codeCharta/state/store/state.actions.ts +3 -1
  13. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +6 -8
  14. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +9 -9
  15. package/app/codeCharta/ui/dialog/dialog.addCustomConfigSettings.component.html +2 -2
  16. package/app/codeCharta/ui/dialog/dialog.changelog.component.scss +15 -0
  17. package/app/codeCharta/ui/dialog/dialog.changelog.component.spec.ts +15 -15
  18. package/app/codeCharta/ui/dialog/dialog.changelog.component.ts +2 -1
  19. package/app/codeCharta/ui/dialog/dialog.service.spec.ts +68 -0
  20. package/app/codeCharta/ui/dialog/dialog.service.ts +38 -17
  21. package/app/codeCharta/ui/edgeChooser/edgeChooser.e2e.ts +3 -2
  22. package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -6
  23. package/app/codeCharta/ui/filePanel/filePanel.component.html +24 -106
  24. package/app/codeCharta/ui/filePanel/filePanel.component.scss +12 -57
  25. package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +40 -72
  26. package/app/codeCharta/ui/filePanel/filePanel.component.ts +29 -81
  27. package/app/codeCharta/ui/filePanel/filePanel.module.ts +13 -1
  28. package/app/codeCharta/ui/filePanel/filePanel.po.ts +6 -24
  29. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html +23 -0
  30. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts +18 -0
  31. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +18 -0
  32. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +16 -0
  33. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html +18 -0
  34. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.ts +11 -0
  35. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +7 -5
  36. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.html +1 -1
  37. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.spec.ts +6 -16
  38. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.ts +15 -11
  39. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.html +22 -0
  40. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.scss +31 -0
  41. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +35 -0
  42. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.ts +30 -0
  43. package/app/codeCharta/ui/nodeContextMenu/{markFolderColorPicker/markFolderColorPicker.module.ts → markFolderRow/markFolderRow.module.ts} +4 -5
  44. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +17 -0
  45. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
  46. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.spec.ts +15 -0
  47. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.ts +9 -0
  48. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -15
  49. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +0 -15
  50. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +10 -119
  51. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +40 -134
  52. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -2
  53. package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +1 -1
  54. package/app/codeCharta/ui/toolBar/toolBar.component.html +1 -1
  55. package/app/codeCharta/ui/toolBar/toolBar.component.scss +1 -1
  56. package/app/codeCharta/ui/ui.ts +2 -2
  57. package/app/codeCharta/util/customConfigHelper.spec.ts +155 -60
  58. package/app/codeCharta/util/customConfigHelper.ts +33 -3
  59. package/app/codeCharta/util/dataMocks.ts +4 -2
  60. package/app/codeCharta/util/fileValidator.spec.ts +69 -182
  61. package/app/codeCharta/util/fileValidator.ts +61 -37
  62. package/dist/webpack/bundle.js +852 -485
  63. package/dist/webpack/bundle.js.map +1 -1
  64. package/package.json +1 -1
  65. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +0 -9
  66. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.scss +0 -13
  67. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +0 -10
@@ -0,0 +1,30 @@
1
+ import "./markFolderRow.component.scss"
2
+ import { Component, Inject } from "@angular/core"
3
+ import { Store } from "../../../state/angular-redux/store"
4
+ import { markPackages, unmarkPackage } from "../../../state/store/fileSettings/markedPackages/markedPackages.actions"
5
+ import { Observable } from "rxjs"
6
+ import { MarkFolderItem, markFolderItemsSelector } from "./selectors/markFolderItems.selector"
7
+ import { Node } from "../../../codeCharta.model"
8
+ import { rightClickedNodeSelector } from "./selectors/rightClickedNode.selector"
9
+
10
+ @Component({
11
+ selector: "cc-mark-folder-row",
12
+ template: require("./markFolderRow.component.html")
13
+ })
14
+ export class MarkFolderRowComponent {
15
+ markFolderItems$: Observable<MarkFolderItem[]>
16
+ node$: Observable<Node>
17
+
18
+ constructor(@Inject(Store) private store: Store) {
19
+ this.markFolderItems$ = store.select(markFolderItemsSelector)
20
+ this.node$ = store.select(rightClickedNodeSelector)
21
+ }
22
+
23
+ markFolder(path: string, color: string) {
24
+ this.store.dispatch(markPackages([{ path, color }]))
25
+ }
26
+
27
+ unmarkFolder(path: string) {
28
+ this.store.dispatch(unmarkPackage({ path }))
29
+ }
30
+ }
@@ -1,12 +1,11 @@
1
1
  import { CommonModule } from "@angular/common"
2
2
  import { NgModule } from "@angular/core"
3
-
4
3
  import { ColorPickerModule } from "../../colorPicker/colorPicker.module"
5
- import { MarkFolderColorPickerComponent } from "./markFolderColorPicker.component"
4
+ import { MarkFolderRowComponent } from "./markFolderRow.component"
6
5
 
7
6
  @NgModule({
8
7
  imports: [CommonModule, ColorPickerModule],
9
- declarations: [MarkFolderColorPickerComponent],
10
- exports: [MarkFolderColorPickerComponent]
8
+ declarations: [MarkFolderRowComponent],
9
+ exports: [MarkFolderRowComponent]
11
10
  })
12
- export class MarkFolderColorPickerModule {}
11
+ export class MarkFolderRowModule {}
@@ -0,0 +1,17 @@
1
+ import { _getMarkFolderItems } from "./markFolderItems.selector"
2
+
3
+ describe("markFolderItemsSelector's _getMarkFolderItems", () => {
4
+ it("should return all colors as unmarked if no node is given", () => {
5
+ expect(_getMarkFolderItems(null, ["#000000", "#ffffff"], [])).toEqual([
6
+ { color: "#000000", isMarked: false },
7
+ { color: "#ffffff", isMarked: false }
8
+ ])
9
+ })
10
+
11
+ it("should recognized a marked folder", () => {
12
+ expect(_getMarkFolderItems({ path: "/root" }, ["#000000", "#ffffff"], [{ color: "#000000", path: "/root" }])).toEqual([
13
+ { color: "#000000", isMarked: true },
14
+ { color: "#ffffff", isMarked: false }
15
+ ])
16
+ })
17
+ })
@@ -0,0 +1,29 @@
1
+ import { MarkedPackage, Node } from "../../../../codeCharta.model"
2
+ import { createSelector } from "../../../../state/angular-redux/createSelector"
3
+ import { mapColorsSelector } from "../../../../state/store/appSettings/mapColors/mapColors.selector"
4
+ import { markedPackagesSelector } from "../../../../state/store/fileSettings/markedPackages/markedPackages.selector"
5
+ import { findIndexOfMarkedPackageOrParent } from "../../../../state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent"
6
+ import { CcState } from "../../../../state/store/store"
7
+ import { rightClickedNodeSelector } from "./rightClickedNode.selector"
8
+
9
+ export type MarkFolderItem = {
10
+ color: string
11
+ isMarked: boolean
12
+ }
13
+
14
+ const markingColorsSelector = createSelector([mapColorsSelector], mapColors => mapColors.markingColors)
15
+
16
+ export const _getMarkFolderItems = (node: Pick<Node, "path">, markingColors: string[], markedPackages: MarkedPackage[]) => {
17
+ if (node === null) return markingColors.map(color => ({ color, isMarked: false }))
18
+
19
+ const nodeIndexWithinMarkedPackages = findIndexOfMarkedPackageOrParent(markedPackages, node.path)
20
+ return markingColors.map(color => ({
21
+ color,
22
+ isMarked: nodeIndexWithinMarkedPackages !== -1 && color === markedPackages[nodeIndexWithinMarkedPackages].color
23
+ }))
24
+ }
25
+
26
+ export const markFolderItemsSelector: (state: CcState) => MarkFolderItem[] = createSelector(
27
+ [rightClickedNodeSelector, markingColorsSelector, markedPackagesSelector],
28
+ _getMarkFolderItems
29
+ )
@@ -0,0 +1,15 @@
1
+ import { CodeMapBuilding } from "../../../codeMap/rendering/codeMapBuilding"
2
+ import { _getNode } from "./rightClickedNode.selector"
3
+
4
+ describe("rightClickedNodeSelector's _getNode", () => {
5
+ it("should return null when no building was right clicked on", () => {
6
+ expect(_getNode(new Map(), null)).toBe(null)
7
+ })
8
+
9
+ it("should return node", () => {
10
+ const node = { id: 1 }
11
+ const codeMapBuilding = { node } as CodeMapBuilding
12
+ const idToBuilding = new Map([[1, codeMapBuilding]])
13
+ expect(_getNode(idToBuilding, { nodeId: 1 })).toBe(node)
14
+ })
15
+ })
@@ -0,0 +1,9 @@
1
+ import { createSelector } from "../../../../state/angular-redux/createSelector"
2
+ import { rightClickedNodeDataSelector } from "../../../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector"
3
+ import { idToBuildingSelector } from "../../../../state/store/lookUp/idToBuilding/idToBuilding.selector"
4
+ import { CodeMapBuilding } from "../../../codeMap/rendering/codeMapBuilding"
5
+
6
+ export const _getNode = (idToBuilding: Map<number, CodeMapBuilding>, rightClickedNodeData: { nodeId: number }) =>
7
+ rightClickedNodeData !== null ? idToBuilding.get(rightClickedNodeData.nodeId).node : null
8
+
9
+ export const rightClickedNodeSelector = createSelector([idToBuildingSelector, rightClickedNodeDataSelector], _getNode)
@@ -1,19 +1,6 @@
1
- <md-card id="codemap-context-menu" ng-show="$ctrl._viewModel.showNodeContextMenu">
1
+ <md-card id="codemap-context-menu" ng-show="$ctrl.rightClickedNodeData !== null">
2
2
  <div ng-if="$ctrl.nodeIsFolder()">
3
- <div layout="row" layout-align="center center">
4
- <md-button
5
- ng-repeat="color in $ctrl._viewModel.markingColors track by $index"
6
- ng-style="{ 'background-color': '{{ color }}' }"
7
- ng-disabled="primary === color && !isPrimary"
8
- ng-click="$ctrl.clickColor(color)"
9
- class="colorButton"
10
- title="Colorize folder"
11
- >
12
- <i class="fa fa-times" ng-if="$ctrl.isNodeOrParentMarked(color)"></i>
13
- </md-button>
14
-
15
- <cc-mark-folder-color-picker [mark-folder]="$ctrl.markFolder"></cc-mark-folder-color-picker>
16
- </div>
3
+ <cc-mark-folder-row></cc-mark-folder-row>
17
4
  <md-divider></md-divider>
18
5
  </div>
19
6
 
@@ -36,19 +36,4 @@ node-context-menu-component {
36
36
  margin-bottom: 0;
37
37
  }
38
38
  }
39
-
40
- .colorButton {
41
- width: 32px !important;
42
- height: 32px !important;
43
- min-width: 32px !important;
44
- min-height: 32px !important;
45
-
46
- i {
47
- font-size: 25px;
48
- margin-left: 0;
49
- margin-top: 3px;
50
- color: red;
51
- text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
52
- }
53
- }
54
39
  }
@@ -9,13 +9,11 @@ import {
9
9
  CONSTANT_HIGHLIGHT,
10
10
  TEST_DELTA_MAP_A,
11
11
  VALID_FILE_NODE_WITH_ID,
12
- VALID_NODE_WITH_PATH,
13
- withMockedEventMethods
12
+ VALID_NODE_WITH_PATH
14
13
  } from "../../util/dataMocks"
15
14
  import { CodeMapPreRenderService } from "../codeMap/codeMap.preRender.service"
16
15
  import { StoreService } from "../../state/store.service"
17
- import { setMarkedPackages } from "../../state/store/fileSettings/markedPackages/markedPackages.actions"
18
- import { BlacklistType, MarkedPackage, NodeType } from "../../codeCharta.model"
16
+ import { BlacklistType, NodeType } from "../../codeCharta.model"
19
17
  import { addBlacklistItem } from "../../state/store/fileSettings/blacklist/blacklist.actions"
20
18
  import { NodeDecorator } from "../../util/nodeDecorator"
21
19
  import { ThreeSceneService } from "../codeMap/threeViewer/threeSceneService"
@@ -92,38 +90,6 @@ describe("nodeContextMenuController", () => {
92
90
  })()
93
91
  }
94
92
 
95
- describe("constructor", () => {
96
- it("should subscribe to 'show-node-context-menu' events", () => {
97
- NodeContextMenuController.subscribeToShowNodeContextMenu = jest.fn()
98
-
99
- rebuildController()
100
-
101
- expect(NodeContextMenuController.subscribeToShowNodeContextMenu).toHaveBeenCalledWith($rootScope, nodeContextMenuController)
102
- })
103
-
104
- it("should broadcast 'show-node-context-menu' when 'show' method is called", () => {
105
- withMockedEventMethods($rootScope)
106
- NodeContextMenuController.broadcastShowEvent($rootScope, "somepath", "sometype", 42, 24)
107
-
108
- expect($rootScope.$broadcast).toHaveBeenCalledWith("show-node-context-menu", {
109
- path: "somepath",
110
- type: "sometype",
111
- x: 42,
112
- y: 24
113
- })
114
- })
115
-
116
- it("should subscribe to 'on-building-right-clicked' events", () => {
117
- const documentAddEventListenerSpy = jest.spyOn(document, "addEventListener")
118
- rebuildController()
119
-
120
- expect(documentAddEventListenerSpy).toHaveBeenCalledWith(
121
- "building-right-clicked",
122
- nodeContextMenuController.onBuildingRightClicked
123
- )
124
- })
125
- })
126
-
127
93
  describe("onShowNodeContextMenu", () => {
128
94
  let mockedWheelTargetElement
129
95
  beforeEach(() => {
@@ -137,10 +103,9 @@ describe("nodeContextMenuController", () => {
137
103
  })
138
104
 
139
105
  it("should set the correct building after some timeout", () => {
140
- nodeContextMenuController.onShowNodeContextMenu("/root", NodeType.FOLDER, 42, 24)
106
+ nodeContextMenuController.showNodeContextMenu("/root", NodeType.FOLDER, 42, 24)
141
107
 
142
108
  expect(nodeContextMenuController["_viewModel"].codeMapNode).toEqual(TEST_DELTA_MAP_A.map)
143
- expect(nodeContextMenuController["_viewModel"].showNodeContextMenu).toBe(true)
144
109
  expect(nodeContextMenuController.calculatePosition).toHaveBeenCalledWith(42, 24)
145
110
  expect(nodeContextMenuController.setPosition).toHaveBeenCalledTimes(1)
146
111
  expect(nodeContextMenuController.setPosition).toBeCalledWith(1, 2)
@@ -153,14 +118,14 @@ describe("nodeContextMenuController", () => {
153
118
  })
154
119
 
155
120
  it("should not shorten the path if it has no sub paths", () => {
156
- nodeContextMenuController.onShowNodeContextMenu("/root", NodeType.FOLDER, 42, 24)
121
+ nodeContextMenuController.showNodeContextMenu("/root", NodeType.FOLDER, 42, 24)
157
122
 
158
123
  expect(nodeContextMenuController["_viewModel"].nodePath).toEqual(TEST_DELTA_MAP_A.map.path)
159
124
  expect(nodeContextMenuController["_viewModel"].lastPartOfNodePath).toBe(TEST_DELTA_MAP_A.map.path)
160
125
  })
161
126
 
162
127
  it("should set the complete and shortened node path", () => {
163
- nodeContextMenuController.onShowNodeContextMenu("/root/big leaf", NodeType.FILE, 521, 588)
128
+ nodeContextMenuController.showNodeContextMenu("/root/big leaf", NodeType.FILE, 521, 588)
164
129
  const nodePath = TEST_DELTA_MAP_A.map.children[0].path
165
130
 
166
131
  expect(nodeContextMenuController["_viewModel"].nodePath).toEqual(nodePath)
@@ -170,7 +135,7 @@ describe("nodeContextMenuController", () => {
170
135
  it("should remove all listener on hide", () => {
171
136
  const documentRemoveEventListenerSpy = jest.spyOn(document.body, "removeEventListener")
172
137
 
173
- nodeContextMenuController.onHideNodeContextMenu()
138
+ nodeContextMenuController.hideNodeContextMenu()
174
139
 
175
140
  expect(documentRemoveEventListenerSpy).toHaveBeenCalledWith(
176
141
  "click",
@@ -293,80 +258,6 @@ describe("nodeContextMenuController", () => {
293
258
  })
294
259
  })
295
260
 
296
- describe("clickColor", () => {
297
- it("should call unmarkFolder, if current folder is marked with color ", () => {
298
- nodeContextMenuController.isNodeOrParentMarked = jest.fn().mockReturnValue(true)
299
- nodeContextMenuController.unmarkFolder = jest.fn()
300
-
301
- nodeContextMenuController.clickColor("color")
302
-
303
- expect(nodeContextMenuController.isNodeOrParentMarked).toHaveBeenCalledWith("color")
304
- expect(nodeContextMenuController.unmarkFolder).toHaveBeenCalled()
305
- })
306
-
307
- it("should call markFolder, if current folder is not marked with color ", () => {
308
- nodeContextMenuController.isNodeOrParentMarked = jest.fn().mockReturnValue(false)
309
- nodeContextMenuController.markFolder = jest.fn()
310
-
311
- nodeContextMenuController.clickColor("color")
312
-
313
- expect(nodeContextMenuController.isNodeOrParentMarked).toHaveBeenCalledWith("color")
314
- expect(nodeContextMenuController.markFolder).toHaveBeenCalled()
315
- })
316
- })
317
-
318
- describe("currentFolderIsMarkedWithColor", () => {
319
- it("should return false, if color is undefined", () => {
320
- const result = nodeContextMenuController.isNodeOrParentMarked()
321
-
322
- expect(result).toBeFalsy()
323
- })
324
-
325
- it("should return false, if color is null", () => {
326
- const result = nodeContextMenuController.isNodeOrParentMarked(null)
327
-
328
- expect(result).toBeFalsy()
329
- })
330
-
331
- it("should return false, if _viewModel.contextMenuBuilding is undefined", () => {
332
- nodeContextMenuController["_viewModel"].codeMapNode = undefined
333
-
334
- const result = nodeContextMenuController.isNodeOrParentMarked("color")
335
-
336
- expect(result).toBeFalsy()
337
- })
338
-
339
- it("should return false, if _viewModel.contextMenuBuilding is null", () => {
340
- nodeContextMenuController["_viewModel"].codeMapNode = null
341
-
342
- const result = nodeContextMenuController.isNodeOrParentMarked("color")
343
-
344
- expect(result).toBeFalsy()
345
- })
346
-
347
- it("should return true, if package is marked and matches the color", () => {
348
- const markedPackages: MarkedPackage[] = [{ path: "/root", color: "color" }]
349
- storeService.dispatch(setMarkedPackages(markedPackages))
350
-
351
- nodeContextMenuController["_viewModel"].codeMapNode = VALID_NODE_WITH_PATH
352
-
353
- const result = nodeContextMenuController.isNodeOrParentMarked("color")
354
-
355
- expect(result).toBeTruthy()
356
- })
357
-
358
- it("should return false, if package is not marked and doesn't match the color of parent folder", () => {
359
- const markedPackages: MarkedPackage[] = [{ path: "/root", color: "color" }]
360
- storeService.dispatch(setMarkedPackages(markedPackages))
361
-
362
- nodeContextMenuController["_viewModel"].codeMapNode = VALID_NODE_WITH_PATH
363
-
364
- const result = nodeContextMenuController.isNodeOrParentMarked("another color")
365
-
366
- expect(result).toBeFalsy()
367
- })
368
- })
369
-
370
261
  describe("excludeNode", () => {
371
262
  beforeEach(() => {
372
263
  nodeContextMenuController["_viewModel"].codeMapNode = VALID_NODE_WITH_PATH.children[1]
@@ -442,9 +333,9 @@ describe("nodeContextMenuController", () => {
442
333
 
443
334
  describe("onBodyLeftClickHideNodeContextMenu", () => {
444
335
  it("should not hide if a click on color-picker tricker occurs", () => {
445
- const broadcastHideEventSpy = jest.spyOn(NodeContextMenuController, "broadcastHideEvent")
336
+ const broadcastHideEventSpy = jest.spyOn(nodeContextMenuController, "hideNodeContextMenu")
446
337
  const mockedMouseEvent: any = {
447
- composedPath: () => [{ nodeName: "CC-MARK-FOLDER-COLOR-PICKER" }]
338
+ composedPath: () => [{ nodeName: "CC-COLOR-PICKER" }]
448
339
  }
449
340
  nodeContextMenuController.onBodyLeftClickHideNodeContextMenu(mockedMouseEvent)
450
341
 
@@ -452,7 +343,7 @@ describe("nodeContextMenuController", () => {
452
343
  })
453
344
 
454
345
  it("should not hide if a click within color-picker occurs", () => {
455
- const broadcastHideEventSpy = jest.spyOn(NodeContextMenuController, "broadcastHideEvent")
346
+ const broadcastHideEventSpy = jest.spyOn(nodeContextMenuController, "hideNodeContextMenu")
456
347
  const mockedMouseEvent: any = {
457
348
  composedPath: () => [{ nodeName: "COLOR-CHROME" }]
458
349
  }
@@ -462,7 +353,7 @@ describe("nodeContextMenuController", () => {
462
353
  })
463
354
 
464
355
  it("should hide if clicked somewhere but not within the color-picker", () => {
465
- const broadcastHideEventSpy = jest.spyOn(NodeContextMenuController, "broadcastHideEvent")
356
+ const broadcastHideEventSpy = jest.spyOn(nodeContextMenuController, "hideNodeContextMenu")
466
357
  const mockedMouseEvent: any = {
467
358
  composedPath: () => [{ nodeName: "DIV" }]
468
359
  }
@@ -1,47 +1,35 @@
1
1
  import "./nodeContextMenu.component.scss"
2
2
  import angular, { IRootScopeService } from "angular"
3
- import { BlacklistItem, BlacklistType, CodeMapNode, MapColors, NodeType } from "../../codeCharta.model"
3
+ import { BlacklistItem, BlacklistType, CodeMapNode, NodeType } from "../../codeCharta.model"
4
4
  import { CodeMapPreRenderService } from "../codeMap/codeMap.preRender.service"
5
5
  import { StoreService } from "../../state/store.service"
6
6
  import { addBlacklistItem, removeBlacklistItem } from "../../state/store/fileSettings/blacklist/blacklist.actions"
7
7
  import { CodeMapBuilding } from "../codeMap/rendering/codeMapBuilding"
8
- import { MapColorsService, MapColorsSubscriber } from "../../state/store/appSettings/mapColors/mapColors.service"
9
- import { getCodeMapNodeFromPath } from "../../util/codeMapHelper"
8
+ import { getCodeMapNodeFromPath, isLeaf } from "../../util/codeMapHelper"
10
9
  import { ThreeSceneService } from "../codeMap/threeViewer/threeSceneService"
11
10
  import { DialogService } from "../dialog/dialog.service"
12
11
  import { BlacklistService } from "../../state/store/fileSettings/blacklist/blacklist.service"
13
12
  import { ERROR_MESSAGES } from "../../util/fileValidator"
14
- import type { BUILDING_RIGHT_CLICKED_EVENT_TYPE } from "../../../../src/globals"
15
- import { findIndexOfMarkedPackageOrParent } from "../../state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent"
16
- import { markPackages, unmarkPackage } from "../../state/store/fileSettings/markedPackages/markedPackages.actions"
13
+ import { Store } from "../../state/store/store"
14
+ import { rightClickedNodeDataSelector } from "../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector"
15
+ import {
16
+ RightClickedNodeData,
17
+ setRightClickedNodeData
18
+ } from "../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions"
17
19
 
18
20
  export enum ClickType {
19
21
  RightClick = 2
20
22
  }
21
23
 
22
- export interface ShowNodeContextMenuSubscriber {
23
- onShowNodeContextMenu(path: string, type: string, x: number, y: number)
24
- }
25
-
26
- export interface HideNodeContextMenuSubscriber {
27
- onHideNodeContextMenu()
28
- }
29
-
30
- export class NodeContextMenuController implements ShowNodeContextMenuSubscriber, HideNodeContextMenuSubscriber, MapColorsSubscriber {
31
- private static SHOW_NODE_CONTEXT_MENU_EVENT = "show-node-context-menu"
32
- private static HIDE_NODE_CONTEXT_MENU_EVENT = "hide-node-context-menu"
33
- private static instance: NodeContextMenuController
24
+ export class NodeContextMenuController {
25
+ private rightClickedNodeData: RightClickedNodeData
34
26
 
35
27
  private _viewModel: {
36
28
  codeMapNode: CodeMapNode
37
- showNodeContextMenu: boolean
38
- markingColors: string[]
39
29
  nodePath: string
40
30
  lastPartOfNodePath: string
41
31
  } = {
42
32
  codeMapNode: null,
43
- showNodeContextMenu: false,
44
- markingColors: null,
45
33
  nodePath: "",
46
34
  lastPartOfNodePath: ""
47
35
  }
@@ -57,35 +45,38 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
57
45
  private blacklistService: BlacklistService
58
46
  ) {
59
47
  "ngInject"
60
- NodeContextMenuController.instance = this
61
- MapColorsService.subscribe(this.$rootScope, this)
62
- document.addEventListener("building-right-clicked", this.onBuildingRightClicked)
63
- NodeContextMenuController.subscribeToShowNodeContextMenu(this.$rootScope, this)
64
- NodeContextMenuController.subscribeToHideNodeContextMenu(this.$rootScope, this)
65
- }
66
-
67
- onMapColorsChanged(mapColors: MapColors) {
68
- this._viewModel.markingColors = mapColors.markingColors
69
- }
70
-
71
- onBuildingRightClicked = ({ detail: { building, x, y } }: CustomEvent<BUILDING_RIGHT_CLICKED_EVENT_TYPE>) => {
72
- const nodeType = building.node.isLeaf ? NodeType.FILE : NodeType.FOLDER
73
- this.onShowNodeContextMenu(building.node.path, nodeType, x, y)
48
+ Store.store.subscribe(() => {
49
+ const state = Store.store.getState()
50
+ const rightClickedNodeData = rightClickedNodeDataSelector(state)
51
+ if (this.rightClickedNodeData === rightClickedNodeData) return
52
+
53
+ this.rightClickedNodeData = rightClickedNodeData
54
+ if (rightClickedNodeData === null) {
55
+ this.hideNodeContextMenu()
56
+ } else {
57
+ const rightClickedNode = state.lookUp.idToNode.get(rightClickedNodeData.nodeId)
58
+ const nodeType = isLeaf(rightClickedNode) ? NodeType.FILE : NodeType.FOLDER
59
+ this.showNodeContextMenu(
60
+ rightClickedNode.path,
61
+ nodeType,
62
+ rightClickedNodeData.xPositionOfRightClickEvent,
63
+ rightClickedNodeData.yPositionOfRightClickEvent
64
+ )
65
+ }
66
+ })
74
67
  }
75
68
 
76
- onShowNodeContextMenu(path: string, nodeType: string, mouseX: number, mouseY: number) {
69
+ showNodeContextMenu(path: string, nodeType: string, mouseX: number, mouseY: number) {
77
70
  this._viewModel.codeMapNode = getCodeMapNodeFromPath(path, nodeType, this.codeMapPreRenderService.getRenderMap())
78
71
  this._viewModel.nodePath = path
79
72
  this._viewModel.lastPartOfNodePath = `${path.lastIndexOf("/") === 0 ? "" : "..."}${path.slice(path.lastIndexOf("/"))}`
80
73
 
81
- this._viewModel.showNodeContextMenu = true
82
-
83
74
  const { x, y } = this.calculatePosition(mouseX, mouseY)
84
75
  this.setPosition(x, y)
85
76
 
86
77
  // Add event listeners, so that opened node context menu can be closed again later
87
78
  // when clicking (left or right button) or using the mouse wheel on the body element.
88
- document.body.addEventListener("click", this.onBodyLeftClickHideNodeContextMenu, true)
79
+ document.body.addEventListener("click", this.onBodyLeftClickHideNodeContextMenu, false)
89
80
  document.body.addEventListener("mousedown", this.onBodyRightClickHideNodeContextMenu, true)
90
81
  document.getElementById("codeMap").addEventListener("wheel", this.onMapWheelHideNodeContextMenu, true)
91
82
  }
@@ -94,7 +85,7 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
94
85
  if (this.isEventFromColorPicker(mouseEvent)) return
95
86
 
96
87
  // Just close node context menu, if you click anywhere on the map.
97
- this.hideContextMenu()
88
+ this.hideNodeContextMenu()
98
89
  }
99
90
 
100
91
  onBodyRightClickHideNodeContextMenu = event => {
@@ -102,23 +93,19 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
102
93
  // Otherwise, if mouseup would be used and you would move the map with keeping the right button pressed,
103
94
  // the menu would not be closed.
104
95
  if (event.button === ClickType.RightClick) {
105
- this.hideContextMenu()
96
+ this.hideNodeContextMenu()
106
97
  }
107
98
  }
108
99
 
109
100
  onMapWheelHideNodeContextMenu = () => {
110
101
  // If you zoom in and out the map, the node context menu should be closed.
111
- this.hideContextMenu()
102
+ this.hideNodeContextMenu()
112
103
  }
113
104
 
114
- hideContextMenu = () => {
115
- NodeContextMenuController.broadcastHideEvent(this.$rootScope)
116
- }
117
-
118
- onHideNodeContextMenu() {
119
- this._viewModel.showNodeContextMenu = false
105
+ hideNodeContextMenu = () => {
106
+ this.storeService.dispatch(setRightClickedNodeData(null))
120
107
 
121
- // remove event listeners registered in onShowNodeContextMenu
108
+ // remove event listeners registered in showNodeContextMenu
122
109
  document.body.removeEventListener("click", this.onBodyLeftClickHideNodeContextMenu, true)
123
110
  document.body.removeEventListener("mousedown", this.onBodyRightClickHideNodeContextMenu, true)
124
111
  document.getElementById("codeMap").removeEventListener("wheel", this.onMapWheelHideNodeContextMenu, true)
@@ -161,35 +148,12 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
161
148
 
162
149
  addNodeToConstantHighlight() {
163
150
  this.threeSceneService.addNodeAndChildrenToConstantHighlight(this._viewModel.codeMapNode)
164
- this.onHideNodeContextMenu()
151
+ this.hideNodeContextMenu()
165
152
  }
166
153
 
167
154
  removeNodeFromConstantHighlight() {
168
155
  this.threeSceneService.removeNodeAndChildrenFromConstantHighlight(this._viewModel.codeMapNode)
169
- this.onHideNodeContextMenu()
170
- }
171
-
172
- clickColor(color: string) {
173
- if (this.isNodeOrParentMarked(color)) {
174
- this.unmarkFolder()
175
- } else {
176
- this.markFolder(color)
177
- }
178
- }
179
-
180
- markFolder = (color: string) => {
181
- this.storeService.dispatch(
182
- markPackages([
183
- {
184
- path: this._viewModel.codeMapNode.path,
185
- color
186
- }
187
- ])
188
- )
189
- }
190
-
191
- unmarkFolder() {
192
- this.storeService.dispatch(unmarkPackage(this._viewModel.codeMapNode))
156
+ this.hideNodeContextMenu()
193
157
  }
194
158
 
195
159
  calculatePosition(mouseX: number, mouseY: number) {
@@ -206,39 +170,9 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
206
170
  angular.element(this.$element[0].children[0]).css("left", `${x}px`)
207
171
  }
208
172
 
209
- isNodeOrParentMarked(color?: string) {
210
- if (!color || !this._viewModel.codeMapNode) {
211
- return false
212
- }
213
-
214
- if (this.isNodeMarked()) {
215
- return this.packageMatchesColor(color)
216
- }
217
- return this.packageMatchesColorOfParentMP(color)
218
- }
219
-
220
173
  private isEventFromColorPicker(mouseEvent: MouseEvent) {
221
174
  const elements = mouseEvent.composedPath() as Node[]
222
- return elements.some(element => element?.nodeName === "CC-MARK-FOLDER-COLOR-PICKER" || element?.nodeName === "COLOR-CHROME")
223
- }
224
-
225
- private isNodeMarked() {
226
- return this.storeService.getState().fileSettings.markedPackages.some(mp => mp.path === this._viewModel.codeMapNode.path)
227
- }
228
-
229
- private packageMatchesColor(color: string) {
230
- return this.storeService
231
- .getState()
232
- .fileSettings.markedPackages.some(mp => mp.path === this._viewModel.codeMapNode.path && mp.color === color)
233
- }
234
-
235
- private packageMatchesColorOfParentMP(color: string) {
236
- const { markedPackages } = this.storeService.getState().fileSettings
237
- const index = findIndexOfMarkedPackageOrParent(markedPackages, this._viewModel.codeMapNode.path)
238
- if (index === -1) {
239
- return false
240
- }
241
- return this.storeService.getState().fileSettings.markedPackages[index].color === color
175
+ return elements.some(element => element?.nodeName === "CC-COLOR-PICKER" || element?.nodeName === "COLOR-CHROME")
242
176
  }
243
177
 
244
178
  isNodeConstantlyHighlighted() {
@@ -255,34 +189,6 @@ export class NodeContextMenuController implements ShowNodeContextMenuSubscriber,
255
189
  nodeIsFolder() {
256
190
  return this._viewModel.codeMapNode?.children?.length > 0
257
191
  }
258
-
259
- static broadcastShowEvent($rootScope, path: string, type: string, x, y) {
260
- const rootScope = $rootScope || NodeContextMenuController.instance.$rootScope
261
- rootScope.$broadcast(NodeContextMenuController.SHOW_NODE_CONTEXT_MENU_EVENT, {
262
- path,
263
- type,
264
- x,
265
- y
266
- })
267
- }
268
-
269
- static broadcastHideEvent($rootScope?: IRootScopeService) {
270
- const rootScope = $rootScope || NodeContextMenuController.instance.$rootScope
271
- rootScope.$broadcast(NodeContextMenuController.HIDE_NODE_CONTEXT_MENU_EVENT)
272
- }
273
-
274
- static subscribeToShowNodeContextMenu($rootScope: IRootScopeService, subscriber: ShowNodeContextMenuSubscriber) {
275
- $rootScope.$on(NodeContextMenuController.SHOW_NODE_CONTEXT_MENU_EVENT, (_event, data) => {
276
- subscriber.onShowNodeContextMenu(data.path, data.type, data.x, data.y)
277
- })
278
- }
279
-
280
- static subscribeToHideNodeContextMenu($rootScope: IRootScopeService, subscriber: HideNodeContextMenuSubscriber) {
281
- const rootScope = $rootScope || NodeContextMenuController.instance.$rootScope
282
- rootScope.$on(NodeContextMenuController.HIDE_NODE_CONTEXT_MENU_EVENT, () => {
283
- subscriber.onHideNodeContextMenu()
284
- })
285
- }
286
192
  }
287
193
 
288
194
  export const nodeContextMenuComponent = {
@@ -5,11 +5,11 @@ import angular from "angular"
5
5
  import { downgradeComponent } from "@angular/upgrade/static"
6
6
 
7
7
  import { nodeContextMenuComponent } from "./nodeContextMenu.component"
8
- import { MarkFolderColorPickerComponent } from "./markFolderColorPicker/markFolderColorPicker.component"
9
8
  import { FocusButtonsComponent } from "./focusButtons/focusButtons.component"
9
+ import { MarkFolderRowComponent } from "./markFolderRow/markFolderRow.component"
10
10
 
11
11
  angular
12
12
  .module("app.codeCharta.ui.nodeContextMenu", ["app.codeCharta.state", "app.codeCharta.ui"])
13
13
  .component(nodeContextMenuComponent.selector, nodeContextMenuComponent)
14
- .directive("ccMarkFolderColorPicker", downgradeComponent({ component: MarkFolderColorPickerComponent }))
14
+ .directive("ccMarkFolderRow", downgradeComponent({ component: MarkFolderRowComponent }))
15
15
  .directive("ccFocusButtons", downgradeComponent({ component: FocusButtonsComponent }))
@@ -14,7 +14,7 @@
14
14
  <div class="section-header">
15
15
  <custom-configs-component></custom-configs-component>
16
16
  </div>
17
- <span class="section-title no-hover">Map Configurations</span>
17
+ <span class="section-title no-hover">Custom Views</span>
18
18
  </div>
19
19
  </md-card>
20
20