codecharta-visualization 1.88.0 → 1.89.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 (124) hide show
  1. package/app/app.module.ts +20 -10
  2. package/app/codeCharta/codeCharta.component.html +0 -2
  3. package/app/codeCharta/codeCharta.model.ts +1 -0
  4. package/app/codeCharta/services/ajs-upgraded-providers.ts +13 -0
  5. package/app/codeCharta/state/angular-redux/effects/createEffect.spec.ts +37 -0
  6. package/app/codeCharta/state/angular-redux/effects/createEffect.ts +25 -0
  7. package/app/codeCharta/state/angular-redux/effects/effects.module.ts +36 -0
  8. package/app/codeCharta/state/angular-redux/ofType.ts +11 -0
  9. package/app/codeCharta/state/angular-redux/state.ts +12 -0
  10. package/app/codeCharta/state/angular-redux/store.ts +1 -1
  11. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/addBlacklistItemsIfNotResultsInEmptyMap.effect.spec.ts +60 -0
  12. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/addBlacklistItemsIfNotResultsInEmptyMap.effect.ts +56 -0
  13. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/resultsInEmptyMap.ts +22 -0
  14. package/app/codeCharta/state/effects/nodeContextMenu/excludeButton/excludeButton.component.html +3 -0
  15. package/app/codeCharta/state/effects/nodeContextMenu/excludeButton/excludeButton.component.ts +26 -0
  16. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.html +13 -0
  17. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.spec.ts +55 -0
  18. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.ts +34 -0
  19. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.module.ts +11 -0
  20. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/focusButtons.component.html +0 -0
  21. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/focusButtons.component.spec.ts +2 -2
  22. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/focusButtons.component.ts +5 -5
  23. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/focusButtons.module.ts +1 -1
  24. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/isNodeFocused.pipe.spec.ts +0 -0
  25. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/focusButtons/isNodeFocused.pipe.ts +2 -2
  26. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.html +6 -0
  27. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.spec.ts +64 -0
  28. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.ts +39 -0
  29. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.module.ts +11 -0
  30. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/markFolderRow.component.html +3 -3
  31. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/markFolderRow.component.scss +0 -0
  32. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +2 -2
  33. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/markFolderRow.component.ts +6 -6
  34. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/markFolderRow.module.ts +1 -1
  35. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +0 -0
  36. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
  37. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/nodeContextMenu.e2e.ts +4 -16
  38. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/nodeContextMenu.po.ts +1 -1
  39. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenu.service.spec.ts +78 -0
  40. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenu.service.ts +72 -0
  41. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/lastPartOfNodePath.pipe.spec.ts +11 -0
  42. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/lastPartOfNodePath.pipe.ts +8 -0
  43. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.html +17 -0
  44. package/app/codeCharta/{ui/nodeContextMenu/nodeContextMenu.component.scss → state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.scss} +6 -11
  45. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.spec.ts +49 -0
  46. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.ts +19 -0
  47. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.module.ts +18 -0
  48. package/app/codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect.spec.ts +32 -0
  49. package/app/codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect.ts +33 -0
  50. package/app/codeCharta/state/effects/nodeContextMenu/rightClickedCodeMapNode.selector.ts +8 -0
  51. package/app/codeCharta/state/effects/unfocusNodesOnLoadingMap.effect.spec.ts +47 -0
  52. package/app/codeCharta/state/effects/unfocusNodesOnLoadingMap.effect.ts +18 -0
  53. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/areAllNecessaryRenderDataAvailable.selector.ts +30 -0
  54. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areDynamicSettingsAvailable.spec.ts +36 -0
  55. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areDynamicSettingsAvailable.ts +10 -0
  56. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areMetricsAvailable.spec.ts +13 -0
  57. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areMetricsAvailable.ts +8 -0
  58. package/app/codeCharta/state/store/appSettings/appSettings.actions.ts +2 -0
  59. package/app/codeCharta/state/store/appSettings/appSettings.reducer.ts +2 -0
  60. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.actions.ts +32 -0
  61. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.reducer.spec.ts +26 -0
  62. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.reducer.ts +12 -0
  63. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.selector.ts +3 -0
  64. package/app/codeCharta/state/store/appSettings/isLoadingMap/isLoadingMap.reducer.spec.ts +14 -3
  65. package/app/codeCharta/state/store/appSettings/isLoadingMap/isLoadingMap.reducer.ts +41 -6
  66. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.actions.ts +33 -2
  67. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.reducer.spec.ts +17 -1
  68. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.reducer.ts +3 -1
  69. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.service.spec.ts +1 -19
  70. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.service.ts +5 -28
  71. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.selector.ts +4 -0
  72. package/app/codeCharta/state/store/lookUp/lookUp.selector.ts +3 -0
  73. package/app/codeCharta/state/store/metricData/nodeMetricData/nodeMetricData.service.ts +0 -4
  74. package/app/codeCharta/state/store/store.ts +5 -1
  75. package/app/codeCharta/state/store.service.spec.ts +20 -7
  76. package/app/codeCharta/state/store.service.ts +3 -36
  77. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.html +3 -1
  78. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.scss +6 -2
  79. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.ts +1 -1
  80. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.module.ts +3 -0
  81. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.po.ts +4 -4
  82. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.html +1 -0
  83. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.scss +26 -0
  84. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.spec.ts +29 -0
  85. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.ts +24 -0
  86. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/aggregationType.pipe.spec.ts +19 -0
  87. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/{aggregationSymbol.pipe.ts → aggregationType.pipe.ts} +4 -4
  88. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.html +4 -12
  89. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.scss +11 -20
  90. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.spec.ts +8 -15
  91. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.module.ts +2 -2
  92. package/app/codeCharta/ui/codeMap/codeMap.preRender.service.spec.ts +1 -9
  93. package/app/codeCharta/ui/codeMap/codeMap.preRender.service.ts +9 -32
  94. package/app/codeCharta/ui/dialogs/dialogs.ts +3 -0
  95. package/app/codeCharta/ui/dialogs/errorDialog/errorDialog.component.html +7 -0
  96. package/app/codeCharta/ui/dialogs/errorDialog/errorDialog.component.ts +9 -0
  97. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +1 -1
  98. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.po.ts +1 -1
  99. package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +2 -2
  100. package/app/codeCharta/ui/ribbonBar/ribbonBar.e2e.ts +3 -3
  101. package/app/codeCharta/ui/searchBar/searchBar.component.html +5 -0
  102. package/app/codeCharta/ui/searchBar/searchBar.component.scss +11 -0
  103. package/app/codeCharta/ui/searchBar/searchBar.component.spec.ts +10 -0
  104. package/app/codeCharta/ui/searchBar/searchBar.component.ts +1 -1
  105. package/app/codeCharta/ui/sortingOption/sortingOption.component.spec.ts +1 -1
  106. package/app/codeCharta/ui/ui.ts +0 -2
  107. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.spec.ts +1 -1
  108. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.ts +14 -7
  109. package/app/codeCharta/util/customConfigBuilder.ts +1 -0
  110. package/app/codeCharta/util/dataMocks.ts +2 -0
  111. package/app/codeCharta/util/reduxHelper.ts +11 -0
  112. package/app/material/material.module.ts +17 -1
  113. package/conf/webpack.loaders.js +4 -1
  114. package/dist/webpack/bundle.js +4582 -950
  115. package/dist/webpack/bundle.js.map +1 -1
  116. package/package.json +2 -2
  117. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/aggregationSymbol.pipe.spec.ts +0 -19
  118. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +0 -29
  119. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.spec.ts +0 -15
  120. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.ts +0 -9
  121. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +0 -45
  122. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +0 -365
  123. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +0 -198
  124. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +0 -15
package/app/app.module.ts CHANGED
@@ -19,18 +19,23 @@ import { LegendPanelComponent } from "./codeCharta/ui/legendPanel/legendPanel.co
19
19
  import { LegendPanelModule } from "./codeCharta/ui/legendPanel/legendPanel.module"
20
20
  import { ColorPickerForMapColorModule } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.module"
21
21
  import { ColorPickerForMapColorComponent } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.component"
22
- import { FocusButtonsModule } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module"
23
- import { FocusButtonsComponent } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component"
24
22
  import { FilePanelFileSelectorComponent } from "./codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component"
25
23
  import { FilePanelStateButtonsComponent } from "./codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component"
26
24
  import { FilePanelDeltaSelectorComponent } from "./codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component"
27
- import { MarkFolderRowComponent } from "./codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component"
28
- import { MarkFolderRowModule } from "./codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.module"
25
+ import { EffectsModule } from "./codeCharta/state/angular-redux/effects/effects.module"
26
+ import { UnfocusNodesOnLoadingMapEffect } from "./codeCharta/state/effects/unfocusNodesOnLoadingMap.effect"
27
+ import { AddBlacklistItemsIfNotResultsInEmptyMapEffect } from "./codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/addBlacklistItemsIfNotResultsInEmptyMap.effect"
28
+ import { dialogs } from "./codeCharta/ui/dialogs/dialogs"
29
+ import { threeSceneServiceProvider } from "./codeCharta/services/ajs-upgraded-providers"
30
+ import { NodeContextMenuCardModule } from "./codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.module"
31
+ import { OpenNodeContextMenuEffect } from "./codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect"
32
+ import { InvertAreaOptionComponent } from "./codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component"
29
33
 
30
34
  @NgModule({
31
35
  imports: [
32
36
  BrowserModule,
33
37
  UpgradeModule,
38
+ EffectsModule.forRoot([UnfocusNodesOnLoadingMapEffect, AddBlacklistItemsIfNotResultsInEmptyMapEffect, OpenNodeContextMenuEffect]),
34
39
  MapTreeViewModule,
35
40
  MatchingFilesCounterModule,
36
41
  AttributeSideBarModule,
@@ -39,10 +44,16 @@ import { MarkFolderRowModule } from "./codeCharta/ui/nodeContextMenu/markFolderR
39
44
  Export3DMapButtonModule,
40
45
  LegendPanelModule,
41
46
  ColorPickerForMapColorModule,
42
- FocusButtonsModule,
43
- MarkFolderRowModule
47
+ NodeContextMenuCardModule
48
+ ],
49
+ providers: [threeSceneServiceProvider],
50
+ declarations: [
51
+ FilePanelFileSelectorComponent,
52
+ FilePanelStateButtonsComponent,
53
+ FilePanelDeltaSelectorComponent,
54
+ InvertAreaOptionComponent,
55
+ ...dialogs
44
56
  ],
45
- declarations: [FilePanelFileSelectorComponent, FilePanelStateButtonsComponent, FilePanelDeltaSelectorComponent],
46
57
  entryComponents: [
47
58
  MapTreeViewComponent,
48
59
  MatchingFilesCounterComponent,
@@ -51,12 +62,11 @@ import { MarkFolderRowModule } from "./codeCharta/ui/nodeContextMenu/markFolderR
51
62
  LegendPanelComponent,
52
63
  LabelledColorPickerComponent,
53
64
  ColorPickerForMapColorComponent,
54
- FocusButtonsComponent,
55
65
  FilePanelFileSelectorComponent,
56
66
  FilePanelStateButtonsComponent,
57
67
  FilePanelDeltaSelectorComponent,
58
- FocusButtonsComponent,
59
- MarkFolderRowComponent
68
+ InvertAreaOptionComponent,
69
+ ...dialogs
60
70
  ]
61
71
  })
62
72
  export class AppModule {
@@ -22,6 +22,4 @@
22
22
  </h2>
23
23
  </div>
24
24
  </div>
25
-
26
- <node-context-menu-component></node-context-menu-component>
27
25
  </div>
@@ -136,6 +136,7 @@ export interface AppSettings {
136
136
  cameraTarget: Vector3
137
137
  hideFlatBuildings: boolean
138
138
  invertHeight: boolean
139
+ invertArea: boolean
139
140
  dynamicMargin: boolean
140
141
  isWhiteBackground: boolean
141
142
  mapColors: MapColors
@@ -0,0 +1,13 @@
1
+ import { InjectionToken, Injector } from "@angular/core"
2
+
3
+ export const ThreeSceneServiceToken = new InjectionToken("ThreeSceneService")
4
+
5
+ export function ThreeSceneServiceFactory(injector: Injector) {
6
+ return injector.get("threeSceneService")
7
+ }
8
+
9
+ export const threeSceneServiceProvider = {
10
+ provide: ThreeSceneServiceToken,
11
+ useFactory: ThreeSceneServiceFactory,
12
+ deps: ["$injector"]
13
+ }
@@ -0,0 +1,37 @@
1
+ import { mocked } from "ts-jest/utils"
2
+ import { Subject } from "rxjs"
3
+ import { Store } from "../../store/store"
4
+ import { createEffect } from "./createEffect"
5
+
6
+ jest.mock("../../store/store", () => ({
7
+ Store: {}
8
+ }))
9
+ const MockedStore = mocked(Store)
10
+
11
+ describe("createEffect", () => {
12
+ let source
13
+
14
+ beforeEach(() => {
15
+ source = new Subject()
16
+ MockedStore.dispatch = jest.fn()
17
+ })
18
+
19
+ afterEach(() => {
20
+ source.complete()
21
+ })
22
+
23
+ it("should observe and dispatch each received value", () => {
24
+ createEffect(() => source)
25
+ source.next({ type: "some-action-type" })
26
+ source.next({ type: "some-other-action-type" })
27
+ expect(MockedStore.dispatch).toHaveBeenCalledTimes(2)
28
+ expect(MockedStore.dispatch.mock.calls[0][0]).toEqual({ type: "some-action-type" })
29
+ expect(MockedStore.dispatch.mock.calls[1][0]).toEqual({ type: "some-other-action-type" })
30
+ })
31
+
32
+ it("should not dispatch if dispatch is set to false", () => {
33
+ createEffect(() => source, { dispatch: false })
34
+ source.next({ type: "some-action-type" })
35
+ expect(MockedStore.dispatch).not.toHaveBeenCalled()
36
+ })
37
+ })
@@ -0,0 +1,25 @@
1
+ import { Action } from "redux"
2
+ import { Observable } from "rxjs"
3
+ import { Store } from "../../store/store"
4
+
5
+ type DontDispatchConfig = { dispatch: false }
6
+ type DispatchConfig = { dispatch?: true }
7
+ type Config = DispatchConfig | DontDispatchConfig
8
+
9
+ /** Simple placeholder for NgRx's createEffect. The goal is to provide the
10
+ * same api as NgRx, so that we can switch to NgRx in the long run.
11
+ * Please note that its functionality is very minimal so far.
12
+ */
13
+ export function createEffect(source: () => Observable<unknown>, config?: Config) {
14
+ source().subscribe(output => {
15
+ if (config?.dispatch === false) return
16
+
17
+ if (!isAction(output)) throw new Error("output must be an action")
18
+
19
+ Store.dispatch(output)
20
+ })
21
+ }
22
+
23
+ function isAction(something: unknown): something is Action {
24
+ return something && Object.prototype.hasOwnProperty.call(something, "type")
25
+ }
@@ -0,0 +1,36 @@
1
+ import { APP_INITIALIZER, Inject, InjectionToken, ModuleWithProviders, NgModule, Optional, SkipSelf } from "@angular/core"
2
+ import { Action } from "redux"
3
+ import { Observable, Subject } from "rxjs"
4
+
5
+ export type Actions = Observable<Action>
6
+ export const ActionsToken = new InjectionToken<Actions>("Actions")
7
+
8
+ /** Simple placeholder for NgRx's EffectsModule. The goal is to provide the
9
+ * same api as NgRx, so that we can switch to NgRx in the long run.
10
+ */
11
+ @NgModule({})
12
+ export class EffectsModule {
13
+ static actions$ = new Subject<Action>()
14
+
15
+ constructor(@Optional() @SkipSelf() @Inject(EffectsModule) parentModule?: EffectsModule) {
16
+ if (parentModule) throw new Error("EffectsModule is already loaded. Import it in the AppModule only")
17
+ }
18
+
19
+ static forRoot(effects = []): ModuleWithProviders<EffectsModule> {
20
+ return {
21
+ ngModule: EffectsModule,
22
+ providers: [
23
+ { provide: ActionsToken, useValue: EffectsModule.actions$ },
24
+ effects,
25
+ {
26
+ provide: APP_INITIALIZER,
27
+ deps: effects,
28
+ useFactory: () => () => {
29
+ // initialized effects"
30
+ },
31
+ multi: true
32
+ }
33
+ ]
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,11 @@
1
+ import { Action } from "redux"
2
+ import { filter, map, Observable } from "rxjs"
3
+
4
+ export function ofType<T extends Action>(type: string) {
5
+ return function (source: Observable<Action>) {
6
+ return source.pipe(
7
+ filter(action => action.type === type),
8
+ map(action => action as T)
9
+ )
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ import { Injectable } from "@angular/core"
2
+
3
+ import { Store as PlainStore } from "../store/store"
4
+
5
+ @Injectable({
6
+ providedIn: "root"
7
+ })
8
+ export class State {
9
+ getValue() {
10
+ return PlainStore.store.getState()
11
+ }
12
+ }
@@ -28,7 +28,7 @@ export class Store {
28
28
  }
29
29
 
30
30
  dispatch(action: CCAction) {
31
- PlainStore.store.dispatch(action)
31
+ PlainStore.dispatch(action)
32
32
  }
33
33
  }
34
34
 
@@ -0,0 +1,60 @@
1
+ import { ApplicationInitStatus } from "@angular/core"
2
+ import { TestBed } from "@angular/core/testing"
3
+ import { MatDialog } from "@angular/material/dialog"
4
+ import { Action } from "redux"
5
+ import { Subject } from "rxjs"
6
+ import { BlacklistType } from "../../../codeCharta.model"
7
+ import { FILE_STATES_JAVA } from "../../../util/dataMocks"
8
+
9
+ import { EffectsModule } from "../../angular-redux/effects/effects.module"
10
+ import { setFiles } from "../../store/files/files.actions"
11
+ import { addBlacklistItems, addBlacklistItemsIfNotResultsInEmptyMap } from "../../store/fileSettings/blacklist/blacklist.actions"
12
+ import { Store } from "../../store/store"
13
+ import { AddBlacklistItemsIfNotResultsInEmptyMapEffect } from "./addBlacklistItemsIfNotResultsInEmptyMap.effect"
14
+
15
+ describe("AddBlacklistItemsIfNotResultsInEmptyMapEffect", () => {
16
+ const mockedDialog = { open: jest.fn() }
17
+ let storeDispatchSpy
18
+
19
+ beforeEach(async () => {
20
+ Store["initialize"]()
21
+ storeDispatchSpy = jest.spyOn(Store, "dispatch")
22
+ mockedDialog.open = jest.fn()
23
+
24
+ EffectsModule.actions$ = new Subject<Action>()
25
+ TestBed.configureTestingModule({
26
+ imports: [EffectsModule.forRoot([AddBlacklistItemsIfNotResultsInEmptyMapEffect])],
27
+ providers: [{ provide: MatDialog, useValue: mockedDialog }]
28
+ })
29
+ await TestBed.inject(ApplicationInitStatus).donePromise
30
+ })
31
+
32
+ afterEach(() => {
33
+ EffectsModule.actions$.complete()
34
+ })
35
+
36
+ it("should ignore a not relevant action", () => {
37
+ EffectsModule.actions$.next({ type: "whatever" })
38
+ expect(storeDispatchSpy).not.toHaveBeenCalled()
39
+ expect(mockedDialog.open).not.toHaveBeenCalled()
40
+ })
41
+
42
+ it("should not blacklist items if it would lead to an empty map but show error dialog", () => {
43
+ EffectsModule.actions$.next(addBlacklistItemsIfNotResultsInEmptyMap([{ type: BlacklistType.exclude, path: "foo/bar" }]))
44
+ expect(storeDispatchSpy).not.toHaveBeenCalledWith(addBlacklistItems([{ type: BlacklistType.exclude, path: "foo/bar" }]))
45
+ expect(mockedDialog.open).toHaveBeenCalledTimes(1)
46
+ })
47
+
48
+ it("should blacklist items if it doesn't lead to an empty map", () => {
49
+ Store.dispatch(setFiles(FILE_STATES_JAVA))
50
+
51
+ EffectsModule.actions$.next(
52
+ addBlacklistItemsIfNotResultsInEmptyMap([{ type: BlacklistType.exclude, path: "/root/src/main/file1.java" }])
53
+ )
54
+
55
+ expect(storeDispatchSpy).toHaveBeenCalledWith(
56
+ addBlacklistItems([{ type: BlacklistType.exclude, path: "/root/src/main/file1.java" }])
57
+ )
58
+ expect(mockedDialog.open).not.toHaveBeenCalled()
59
+ })
60
+ })
@@ -0,0 +1,56 @@
1
+ import { Inject, Injectable } from "@angular/core"
2
+ import { Actions, ActionsToken } from "../../angular-redux/effects/effects.module"
3
+ import { MatDialog } from "@angular/material/dialog"
4
+ import { createEffect } from "../../angular-redux/effects/createEffect"
5
+ import { filter, map, tap, withLatestFrom } from "rxjs"
6
+ import {
7
+ addBlacklistItems,
8
+ AddBlacklistItemsIfNotResultsInEmptyMapAction,
9
+ BlacklistActions
10
+ } from "../../store/fileSettings/blacklist/blacklist.actions"
11
+ import { visibleFileStatesSelector } from "../../selectors/visibleFileStates.selector"
12
+ import { blacklistSelector } from "../../store/fileSettings/blacklist/blacklist.selector"
13
+ import { Store } from "../../angular-redux/store"
14
+ import { resultsInEmptyMap } from "./resultsInEmptyMap"
15
+ import { ErrorDialogComponent } from "../../../ui/dialogs/errorDialog/errorDialog.component"
16
+ import { ofType } from "../../angular-redux/ofType"
17
+
18
+ @Injectable()
19
+ export class AddBlacklistItemsIfNotResultsInEmptyMapEffect {
20
+ constructor(
21
+ @Inject(ActionsToken) private actions$: Actions,
22
+ @Inject(Store) private store: Store,
23
+ @Inject(MatDialog) private dialog: MatDialog
24
+ ) {}
25
+
26
+ private visibleFiles$ = this.store.select(visibleFileStatesSelector)
27
+ private blacklist$ = this.store.select(blacklistSelector)
28
+ private doBlacklistItemsResultInEmptyMap$ = this.actions$.pipe(
29
+ ofType<AddBlacklistItemsIfNotResultsInEmptyMapAction>(BlacklistActions.ADD_BLACKLIST_ITEMS_IF_NOT_RESULTS_IN_EMPTY_MAP),
30
+ withLatestFrom(this.visibleFiles$, this.blacklist$),
31
+ map(([addBlacklistItemsIfNotResultsInEmptyMapAction, visibleFiles, blacklist]) => ({
32
+ items: addBlacklistItemsIfNotResultsInEmptyMapAction.payload,
33
+ resultsInEmptyMap: resultsInEmptyMap(visibleFiles, blacklist, addBlacklistItemsIfNotResultsInEmptyMapAction.payload)
34
+ }))
35
+ )
36
+
37
+ showErrorDialogIfBlacklistItemsResultInEmptyMap$ = createEffect(
38
+ () =>
39
+ this.doBlacklistItemsResultInEmptyMap$.pipe(
40
+ filter(event => event.resultsInEmptyMap),
41
+ tap(() => {
42
+ this.dialog.open(ErrorDialogComponent, {
43
+ data: { title: "Blacklist Error", message: "Excluding all buildings is not possible." }
44
+ })
45
+ })
46
+ ),
47
+ { dispatch: false }
48
+ )
49
+
50
+ addBlacklistItems$ = createEffect(() =>
51
+ this.doBlacklistItemsResultInEmptyMap$.pipe(
52
+ filter(event => !event.resultsInEmptyMap),
53
+ map(event => addBlacklistItems(event.items))
54
+ )
55
+ )
56
+ }
@@ -0,0 +1,22 @@
1
+ import { hierarchy, HierarchyNode } from "d3-hierarchy"
2
+ import { BlacklistItem, BlacklistType, CCFile, CodeMapNode } from "../../../codeCharta.model"
3
+ import { FileState } from "../../../model/files/files"
4
+ import { isLeaf, isPathBlacklisted } from "../../../util/codeMapHelper"
5
+
6
+ export const resultsInEmptyMap = (
7
+ visibleFiles: FileState[],
8
+ currentBlacklist: BlacklistItem[],
9
+ itemsToBeBlackListened: BlacklistItem[]
10
+ ) => {
11
+ const newBlacklist = [...currentBlacklist, ...itemsToBeBlackListened]
12
+ for (const { file } of visibleFiles) if (!resultsInEmptyFile(file, newBlacklist)) return false
13
+ return true
14
+ }
15
+
16
+ const resultsInEmptyFile = (file: CCFile, blacklist: BlacklistItem[]) => {
17
+ for (const node of hierarchy(file.map)) if (isNodeIncluded(node, blacklist)) return false
18
+ return true
19
+ }
20
+
21
+ const isNodeIncluded = (node: HierarchyNode<CodeMapNode>, blacklist: Array<BlacklistItem>) =>
22
+ isLeaf(node) && node.data.path && !isPathBlacklisted(node.data.path, blacklist, BlacklistType.exclude)
@@ -0,0 +1,3 @@
1
+ <button mat-button (click)="excludeNode()" id="exclude-button" title="Exclude node and children-nodes and reorder the CodeMap">
2
+ <i class="fa fa-ban"></i> EXCLUDE
3
+ </button>
@@ -0,0 +1,26 @@
1
+ import { Component, Inject, Input } from "@angular/core"
2
+ import { BlacklistType, CodeMapNode } from "../../../../codeCharta.model"
3
+ import { Store } from "../../../angular-redux/store"
4
+ import { addBlacklistItemsIfNotResultsInEmptyMap } from "../../../store/fileSettings/blacklist/blacklist.actions"
5
+
6
+ @Component({
7
+ selector: "cc-exclude-button",
8
+ template: require("./excludeButton.component.html")
9
+ })
10
+ export class ExcludeButtonComponent {
11
+ @Input() codeMapNode: Pick<CodeMapNode, "path" | "type">
12
+
13
+ constructor(@Inject(Store) private store: Store) {}
14
+
15
+ excludeNode() {
16
+ this.store.dispatch(
17
+ addBlacklistItemsIfNotResultsInEmptyMap([
18
+ {
19
+ path: this.codeMapNode.path,
20
+ type: BlacklistType.exclude,
21
+ nodeType: this.codeMapNode.type
22
+ }
23
+ ])
24
+ )
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ <button
2
+ mat-button
3
+ *ngIf="!codeMapNode?.isFlattened"
4
+ (click)="flattenNode()"
5
+ title="Flatten node and children-nodes, but keep an empty space"
6
+ >
7
+ <img alt="flattenIcon" class="png-icon" src="../../../../../assets/flatten.png" />
8
+ FLATTEN
9
+ </button>
10
+ <button mat-button *ngIf="codeMapNode?.isFlattened" (click)="unFlattenNode()" title="Show node and children-nodes">
11
+ <img alt="flattenIcon" class="png-icon" src="../../../../../assets/flatten.png" />
12
+ SHOW
13
+ </button>
@@ -0,0 +1,55 @@
1
+ import { render, screen } from "@testing-library/angular"
2
+ import { TestBed } from "@angular/core/testing"
3
+ import { FlattenButtonsComponent } from "./flattenButtons.component"
4
+ import { FlattenButtonsModule } from "./flattenButtons.module"
5
+ import { BlacklistType, NodeType } from "../../../../codeCharta.model"
6
+ import userEvent from "@testing-library/user-event"
7
+ import { Store } from "../../../store/store"
8
+
9
+ describe("flattenButtonsComponent", () => {
10
+ beforeEach(() => {
11
+ Store["initialize"]()
12
+ TestBed.configureTestingModule({
13
+ imports: [FlattenButtonsModule]
14
+ })
15
+ })
16
+
17
+ it("should show flatten button for a not flattened node", async () => {
18
+ await render(FlattenButtonsComponent, {
19
+ excludeComponentDeclaration: true,
20
+ componentProperties: { codeMapNode: { path: "/root/foo.ts", type: NodeType.FILE, isFlattened: false } }
21
+ })
22
+
23
+ expect(screen.queryByText("SHOW")).toBe(null)
24
+ expect(screen.queryByText("FLATTEN")).not.toBe(null)
25
+
26
+ userEvent.click(screen.queryByText("FLATTEN"))
27
+ expect(Store.store.getState().fileSettings.blacklist).toContainEqual({
28
+ nodeType: NodeType.FILE,
29
+ path: "/root/foo.ts",
30
+ type: BlacklistType.flatten
31
+ })
32
+ })
33
+
34
+ it("should show un-flatten button for a flattened node", async () => {
35
+ Store.store.getState().fileSettings.blacklist.push({
36
+ nodeType: NodeType.FILE,
37
+ path: "/root/foo.ts",
38
+ type: BlacklistType.flatten
39
+ })
40
+ await render(FlattenButtonsComponent, {
41
+ excludeComponentDeclaration: true,
42
+ componentProperties: { codeMapNode: { path: "/root/foo.ts", type: NodeType.FILE, isFlattened: true } }
43
+ })
44
+
45
+ expect(screen.queryByText("FLATTEN")).toBe(null)
46
+ expect(screen.queryByText("SHOW")).not.toBe(null)
47
+
48
+ userEvent.click(screen.queryByText("SHOW"))
49
+ expect(Store.store.getState().fileSettings.blacklist).not.toContainEqual({
50
+ nodeType: NodeType.FILE,
51
+ path: "/root/foo.ts",
52
+ type: BlacklistType.flatten
53
+ })
54
+ })
55
+ })
@@ -0,0 +1,34 @@
1
+ import { Component, Inject, Input } from "@angular/core"
2
+ import { BlacklistType, CodeMapNode } from "../../../../codeCharta.model"
3
+ import { Store } from "../../../angular-redux/store"
4
+ import { addBlacklistItem, removeBlacklistItem } from "../../../store/fileSettings/blacklist/blacklist.actions"
5
+
6
+ @Component({
7
+ selector: "cc-flatten-buttons",
8
+ template: require("./flattenButtons.component.html")
9
+ })
10
+ export class FlattenButtonsComponent {
11
+ @Input() codeMapNode: Pick<CodeMapNode, "path" | "type" | "isFlattened">
12
+
13
+ constructor(@Inject(Store) private store: Store) {}
14
+
15
+ flattenNode() {
16
+ this.store.dispatch(
17
+ addBlacklistItem({
18
+ path: this.codeMapNode.path,
19
+ type: BlacklistType.flatten,
20
+ nodeType: this.codeMapNode.type
21
+ })
22
+ )
23
+ }
24
+
25
+ unFlattenNode() {
26
+ this.store.dispatch(
27
+ removeBlacklistItem({
28
+ path: this.codeMapNode.path,
29
+ type: BlacklistType.flatten,
30
+ nodeType: this.codeMapNode.type
31
+ })
32
+ )
33
+ }
34
+ }
@@ -0,0 +1,11 @@
1
+ import { CommonModule } from "@angular/common"
2
+ import { NgModule } from "@angular/core"
3
+ import { MaterialModule } from "../../../../../material/material.module"
4
+ import { FlattenButtonsComponent } from "./flattenButtons.component"
5
+
6
+ @NgModule({
7
+ imports: [CommonModule, MaterialModule],
8
+ declarations: [FlattenButtonsComponent],
9
+ exports: [FlattenButtonsComponent]
10
+ })
11
+ export class FlattenButtonsModule {}
@@ -3,9 +3,9 @@ import { TestBed } from "@angular/core/testing"
3
3
 
4
4
  import { FocusButtonsComponent } from "./focusButtons.component"
5
5
  import { FocusButtonsModule } from "./focusButtons.module"
6
- import { focusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
6
+ import { focusedNodePathSelector } from "../../../store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
7
7
 
8
- jest.mock("../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector", () => ({
8
+ jest.mock("../../../store/dynamicSettings/focusedNodePath/focusedNodePath.selector", () => ({
9
9
  focusedNodePathSelector: jest.fn()
10
10
  }))
11
11
  const mockedFocusedNodePathSelector = focusedNodePathSelector as jest.Mock
@@ -1,11 +1,11 @@
1
1
  import { Component, Inject, Input } from "@angular/core"
2
2
  import { Observable, map } from "rxjs"
3
3
 
4
- import { CodeMapNode } from "../../../codeCharta.model"
5
- import { Store } from "../../../state/angular-redux/store"
6
- import { currentFocusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/currentFocused.selector"
7
- import { focusNode, unfocusAllNodes, unfocusNode } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
8
- import { focusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
4
+ import { CodeMapNode } from "../../../../codeCharta.model"
5
+ import { Store } from "../../../angular-redux/store"
6
+ import { currentFocusedNodePathSelector } from "../../../store/dynamicSettings/focusedNodePath/currentFocused.selector"
7
+ import { focusNode, unfocusAllNodes, unfocusNode } from "../../../store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
8
+ import { focusedNodePathSelector } from "../../../store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
9
9
 
10
10
  @Component({
11
11
  selector: "cc-focus-buttons",
@@ -1,7 +1,7 @@
1
1
  import { CommonModule } from "@angular/common"
2
2
  import { NgModule } from "@angular/core"
3
3
 
4
- import { MaterialModule } from "../../../../material/material.module"
4
+ import { MaterialModule } from "../../../../../material/material.module"
5
5
  import { FocusButtonsComponent } from "./focusButtons.component"
6
6
  import { IsNodeFocusedPipe } from "./isNodeFocused.pipe"
7
7
 
@@ -1,6 +1,6 @@
1
1
  import { Pipe, PipeTransform } from "@angular/core"
2
2
 
3
- import { CodeMapNode } from "../../../codeCharta.model"
3
+ import { CodeMapNode } from "../../../../codeCharta.model"
4
4
 
5
5
  type IsNodeFocusedType = {
6
6
  isNodeFocused: boolean
@@ -10,7 +10,7 @@ type IsNodeFocusedType = {
10
10
  @Pipe({ name: "isNodeFocused" })
11
11
  export class IsNodeFocusedPipe implements PipeTransform {
12
12
  transform(focusedNodePath: string | undefined, node: Pick<CodeMapNode, "path">): IsNodeFocusedType {
13
- if (!focusedNodePath)
13
+ if (!focusedNodePath || !node)
14
14
  return {
15
15
  isNodeFocused: false,
16
16
  isParentFocused: false
@@ -0,0 +1,6 @@
1
+ <button mat-button *ngIf="!isHighlighted" title="Highlight node constantly" (click)="addNodeToConstantHighlight()">
2
+ <i class="fa fa-cubes"></i> KEEP HIGHLIGHT
3
+ </button>
4
+ <button mat-button *ngIf="isHighlighted" title="Remove constant highlight" (click)="removeNodeFromConstantHighlight()">
5
+ <i class="fa fa-cubes"></i> REMOVE HIGHLIGHT
6
+ </button>