codecharta-visualization 1.86.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 (217) hide show
  1. package/Dockerfile +1 -1
  2. package/app/app.module.ts +30 -6
  3. package/app/codeCharta/codeCharta.component.html +0 -2
  4. package/app/codeCharta/codeCharta.component.ts +2 -0
  5. package/app/codeCharta/codeCharta.model.ts +8 -5
  6. package/app/codeCharta/codeCharta.service.spec.ts +41 -50
  7. package/app/codeCharta/codeCharta.service.ts +33 -32
  8. package/app/codeCharta/e2e/url.e2e.ts +1 -1
  9. package/app/codeCharta/services/ajs-upgraded-providers.ts +13 -0
  10. package/app/codeCharta/state/angular-redux/effects/createEffect.spec.ts +37 -0
  11. package/app/codeCharta/state/angular-redux/effects/createEffect.ts +25 -0
  12. package/app/codeCharta/state/angular-redux/effects/effects.module.ts +36 -0
  13. package/app/codeCharta/state/angular-redux/ofType.ts +11 -0
  14. package/app/codeCharta/state/angular-redux/state.ts +12 -0
  15. package/app/codeCharta/state/angular-redux/store.ts +1 -1
  16. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/addBlacklistItemsIfNotResultsInEmptyMap.effect.spec.ts +60 -0
  17. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/addBlacklistItemsIfNotResultsInEmptyMap.effect.ts +56 -0
  18. package/app/codeCharta/state/effects/addBlacklistItemsIfNotResultsInEmptyMap/resultsInEmptyMap.ts +22 -0
  19. package/app/codeCharta/state/effects/nodeContextMenu/excludeButton/excludeButton.component.html +3 -0
  20. package/app/codeCharta/state/effects/nodeContextMenu/excludeButton/excludeButton.component.ts +26 -0
  21. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.html +13 -0
  22. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.spec.ts +55 -0
  23. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.component.ts +34 -0
  24. package/app/codeCharta/state/effects/nodeContextMenu/flattenButtons/flattenButtons.module.ts +11 -0
  25. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/focusButtons.component.html +24 -0
  26. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/focusButtons.component.spec.ts +55 -0
  27. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/focusButtons.component.ts +38 -0
  28. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/focusButtons.module.ts +13 -0
  29. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/isNodeFocused.pipe.spec.ts +31 -0
  30. package/app/codeCharta/state/effects/nodeContextMenu/focusButtons/isNodeFocused.pipe.ts +25 -0
  31. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.html +6 -0
  32. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.spec.ts +64 -0
  33. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.ts +39 -0
  34. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.module.ts +11 -0
  35. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/markFolderRow.component.html +22 -0
  36. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/markFolderRow.component.scss +31 -0
  37. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +35 -0
  38. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/markFolderRow.component.ts +30 -0
  39. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/markFolderRow.module.ts +11 -0
  40. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +17 -0
  41. package/app/codeCharta/state/effects/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
  42. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/nodeContextMenu.e2e.ts +4 -16
  43. package/app/codeCharta/{ui → state/effects}/nodeContextMenu/nodeContextMenu.po.ts +1 -1
  44. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenu.service.spec.ts +78 -0
  45. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenu.service.ts +72 -0
  46. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/lastPartOfNodePath.pipe.spec.ts +11 -0
  47. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/lastPartOfNodePath.pipe.ts +8 -0
  48. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.html +17 -0
  49. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.scss +34 -0
  50. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.spec.ts +49 -0
  51. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.ts +19 -0
  52. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.module.ts +18 -0
  53. package/app/codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect.spec.ts +32 -0
  54. package/app/codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect.ts +33 -0
  55. package/app/codeCharta/state/effects/nodeContextMenu/rightClickedCodeMapNode.selector.ts +8 -0
  56. package/app/codeCharta/state/effects/unfocusNodesOnLoadingMap.effect.spec.ts +47 -0
  57. package/app/codeCharta/state/effects/unfocusNodesOnLoadingMap.effect.ts +18 -0
  58. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/areAllNecessaryRenderDataAvailable.selector.ts +30 -0
  59. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areDynamicSettingsAvailable.spec.ts +36 -0
  60. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areDynamicSettingsAvailable.ts +10 -0
  61. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areMetricsAvailable.spec.ts +13 -0
  62. package/app/codeCharta/state/selectors/allNecessaryRenderDataAvailable/utils/areMetricsAvailable.ts +8 -0
  63. package/app/codeCharta/state/store/appSettings/appSettings.actions.ts +2 -0
  64. package/app/codeCharta/state/store/appSettings/appSettings.reducer.ts +2 -0
  65. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.actions.ts +32 -0
  66. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.reducer.spec.ts +26 -0
  67. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.reducer.ts +12 -0
  68. package/app/codeCharta/state/store/appSettings/invertArea/invertArea.selector.ts +3 -0
  69. package/app/codeCharta/state/store/appSettings/isLoadingMap/isLoadingMap.reducer.spec.ts +14 -3
  70. package/app/codeCharta/state/store/appSettings/isLoadingMap/isLoadingMap.reducer.ts +41 -6
  71. package/app/codeCharta/state/store/appStatus/appStatus.reducer.ts +3 -1
  72. package/app/codeCharta/state/store/appStatus/appStatus.selector.ts +3 -0
  73. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions.ts +23 -0
  74. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.reducer.ts +15 -0
  75. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector.ts +4 -0
  76. package/app/codeCharta/state/store/dynamicSettings/dynamicSettings.splitter.ts +2 -2
  77. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/currentFocused.selector.ts +8 -0
  78. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions.ts +27 -7
  79. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.spec.ts +27 -11
  80. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.ts +11 -5
  81. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector.ts +4 -0
  82. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.spec.ts +2 -2
  83. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.ts +1 -1
  84. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.actions.ts +33 -2
  85. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.reducer.spec.ts +17 -1
  86. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.reducer.ts +3 -1
  87. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.service.spec.ts +1 -19
  88. package/app/codeCharta/state/store/fileSettings/blacklist/blacklist.service.ts +5 -28
  89. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.actions.ts +9 -10
  90. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.spec.ts +37 -7
  91. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.ts +7 -3
  92. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.spec.ts +39 -0
  93. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.ts +19 -0
  94. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.selector.ts +4 -0
  95. package/app/codeCharta/state/store/lookUp/lookUp.selector.ts +3 -0
  96. package/app/codeCharta/state/store/metricData/nodeMetricData/nodeMetricData.service.ts +0 -4
  97. package/app/codeCharta/state/store/state.actions.ts +3 -1
  98. package/app/codeCharta/state/store/state.splitter.spec.ts +4 -4
  99. package/app/codeCharta/state/store/store.ts +5 -1
  100. package/app/codeCharta/state/store.service.spec.ts +21 -8
  101. package/app/codeCharta/state/store.service.ts +3 -31
  102. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.html +3 -1
  103. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.scss +6 -2
  104. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.component.ts +1 -1
  105. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.module.ts +3 -0
  106. package/app/codeCharta/ui/areaSettingsPanel/areaSettingsPanel.po.ts +4 -4
  107. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.html +1 -0
  108. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.scss +26 -0
  109. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.spec.ts +29 -0
  110. package/app/codeCharta/ui/areaSettingsPanel/invertAreaOption/invertAreaOption.component.ts +24 -0
  111. package/app/codeCharta/ui/artificialIntelligence/__snapshots__/artificialIntelligence.component.spec.ts.snap +13 -16
  112. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.html +4 -4
  113. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.scss +0 -4
  114. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.spec.ts +82 -52
  115. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.ts +41 -101
  116. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/aggregationType.pipe.spec.ts +19 -0
  117. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/{aggregationSymbol.pipe.ts → aggregationType.pipe.ts} +4 -4
  118. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.html +4 -12
  119. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.scss +11 -20
  120. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.component.spec.ts +8 -15
  121. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/attributeTypeSelector.module.ts +2 -2
  122. package/app/codeCharta/ui/codeMap/__snapshots__/codeMap.arrow.service.spec.ts.snap +2 -2
  123. package/app/codeCharta/ui/codeMap/codeMap.actions.service.ts +1 -40
  124. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +8 -16
  125. package/app/codeCharta/ui/codeMap/codeMap.preRender.service.spec.ts +1 -9
  126. package/app/codeCharta/ui/codeMap/codeMap.preRender.service.ts +9 -32
  127. package/app/codeCharta/ui/codeMap/rendering/codeMapMesh.ts +1 -0
  128. package/app/codeCharta/ui/colorPicker/colorPicker.component.html +16 -7
  129. package/app/codeCharta/ui/colorPicker/colorPicker.component.spec.ts +55 -16
  130. package/app/codeCharta/ui/colorPicker/colorPicker.component.ts +32 -1
  131. package/app/codeCharta/ui/colorPicker/colorPicker.module.ts +3 -1
  132. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +29 -11
  133. package/app/codeCharta/ui/customConfigs/customConfigs.component.scss +1 -0
  134. package/app/codeCharta/ui/customConfigs/customConfigs.component.spec.ts +123 -2
  135. package/app/codeCharta/ui/customConfigs/customConfigs.component.ts +56 -2
  136. package/app/codeCharta/ui/dialog/dialog.addCustomConfigSettings.component.html +2 -2
  137. package/app/codeCharta/ui/dialog/dialog.changelog.component.html +1 -1
  138. package/app/codeCharta/ui/dialog/dialog.changelog.component.scss +15 -0
  139. package/app/codeCharta/ui/dialog/dialog.changelog.component.spec.ts +15 -15
  140. package/app/codeCharta/ui/dialog/dialog.changelog.component.ts +2 -1
  141. package/app/codeCharta/ui/dialog/dialog.globalSettings.e2e.ts +1 -1
  142. package/app/codeCharta/ui/dialog/dialog.globalSettings.po.ts +1 -1
  143. package/app/codeCharta/ui/dialog/dialog.service.spec.ts +68 -0
  144. package/app/codeCharta/ui/dialog/dialog.service.ts +38 -17
  145. package/app/codeCharta/ui/dialogs/dialogs.ts +3 -0
  146. package/app/codeCharta/ui/dialogs/errorDialog/errorDialog.component.html +7 -0
  147. package/app/codeCharta/ui/dialogs/errorDialog/errorDialog.component.ts +9 -0
  148. package/app/codeCharta/ui/edgeChooser/edgeChooser.e2e.ts +3 -2
  149. package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -6
  150. package/app/codeCharta/ui/filePanel/filePanel.component.html +24 -106
  151. package/app/codeCharta/ui/filePanel/filePanel.component.scss +12 -57
  152. package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +40 -72
  153. package/app/codeCharta/ui/filePanel/filePanel.component.ts +29 -81
  154. package/app/codeCharta/ui/filePanel/filePanel.module.ts +13 -1
  155. package/app/codeCharta/ui/filePanel/filePanel.po.ts +6 -24
  156. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html +23 -0
  157. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts +18 -0
  158. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +18 -0
  159. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +16 -0
  160. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html +18 -0
  161. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.ts +11 -0
  162. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.html +21 -13
  163. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.spec.ts +11 -24
  164. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.ts +1 -40
  165. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.module.ts +1 -2
  166. package/app/codeCharta/ui/legendPanel/legendMarkedPackages/legendMarkedPackages.component.ts +2 -2
  167. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +8 -6
  168. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.po.ts +1 -1
  169. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.html +1 -1
  170. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.spec.ts +6 -16
  171. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.ts +15 -11
  172. package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +3 -3
  173. package/app/codeCharta/ui/ribbonBar/ribbonBar.e2e.ts +3 -3
  174. package/app/codeCharta/ui/searchBar/searchBar.component.html +5 -0
  175. package/app/codeCharta/ui/searchBar/searchBar.component.scss +11 -0
  176. package/app/codeCharta/ui/searchBar/searchBar.component.spec.ts +10 -0
  177. package/app/codeCharta/ui/searchBar/searchBar.component.ts +1 -1
  178. package/app/codeCharta/ui/sortingOption/sortingOption.component.spec.ts +1 -1
  179. package/app/codeCharta/ui/toolBar/toolBar.component.html +1 -1
  180. package/app/codeCharta/ui/toolBar/toolBar.component.scss +1 -1
  181. package/app/codeCharta/ui/ui.ts +2 -6
  182. package/app/codeCharta/util/algorithm/streetLayout/strip/strip.ts +2 -2
  183. package/app/codeCharta/util/algorithm/streetLayout/treeMap.ts +1 -1
  184. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.spec.ts +2 -2
  185. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.ts +14 -7
  186. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.spec.ts +2 -2
  187. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.ts +1 -1
  188. package/app/codeCharta/util/customConfigBuilder.ts +2 -1
  189. package/app/codeCharta/util/customConfigHelper.spec.ts +155 -60
  190. package/app/codeCharta/util/customConfigHelper.ts +33 -3
  191. package/app/codeCharta/util/dataMocks.ts +8 -4
  192. package/app/codeCharta/util/fileExtensionCalculator.ts +1 -1
  193. package/app/codeCharta/util/fileValidator.spec.ts +69 -182
  194. package/app/codeCharta/util/fileValidator.ts +61 -37
  195. package/app/codeCharta/util/reduxHelper.ts +11 -0
  196. package/app/material/material.module.ts +17 -1
  197. package/conf/webpack.loaders.js +4 -1
  198. package/dist/webpack/bundle.js +5925 -1896
  199. package/dist/webpack/bundle.js.map +1 -1
  200. package/package.json +7 -6
  201. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.splitter.ts +0 -8
  202. package/app/codeCharta/ui/attributeSideBar/attributeTypeSelector/aggregationSymbol.pipe.spec.ts +0 -19
  203. package/app/codeCharta/ui/codeMap/codeMap.actions.service.spec.ts +0 -147
  204. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +0 -5
  205. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.scss +0 -13
  206. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +0 -30
  207. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module.ts +0 -13
  208. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +0 -68
  209. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +0 -52
  210. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +0 -571
  211. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +0 -318
  212. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +0 -13
  213. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.html +0 -15
  214. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.scss +0 -5
  215. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.spec.ts +0 -106
  216. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.ts +0 -62
  217. package/app/codeCharta/ui/unfocusButton/unfocusButton.module.ts +0 -7
@@ -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 {}
@@ -0,0 +1,24 @@
1
+ <ng-container *ngIf="currentFocusedNodePath$ | async | isNodeFocused: codeMapNode; let isNodeFocused">
2
+ <ng-container *ngIf="!isNodeFocused.isNodeFocused">
3
+ <button mat-button (click)="handleFocusNodeClicked()" id="focus-button" title="Only show selected nodes with children-nodes">
4
+ <i class="fa fa-bullseye"></i> FOCUS
5
+ </button>
6
+ </ng-container>
7
+
8
+ <ng-container *ngIf="isNodeFocused.isNodeFocused || isNodeFocused.isParentFocused">
9
+ <button mat-button aria-label="Remove Focus from node" (click)="handleUnfocusNodeClicked()" title="Show previous focused node">
10
+ <i class="fa fa-bullseye"></i>
11
+ {{ isNodeFocused.isParentFocused ? "UNFOCUS PARENT" : "UNFOCUS" }}
12
+ </button>
13
+ <button
14
+ mat-button
15
+ *ngIf="hasPreviousFocusedNodePath$ | async"
16
+ aria-label="Remove Focus from all nodes"
17
+ (click)="handleUnfocusAllNodesClicked()"
18
+ title="Show complete map"
19
+ >
20
+ <i class="fa fa-bullseye"></i>
21
+ UNFOCUS ALL
22
+ </button>
23
+ </ng-container>
24
+ </ng-container>
@@ -0,0 +1,55 @@
1
+ import { render } from "@testing-library/angular"
2
+ import { TestBed } from "@angular/core/testing"
3
+
4
+ import { FocusButtonsComponent } from "./focusButtons.component"
5
+ import { FocusButtonsModule } from "./focusButtons.module"
6
+ import { focusedNodePathSelector } from "../../../store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
7
+
8
+ jest.mock("../../../store/dynamicSettings/focusedNodePath/focusedNodePath.selector", () => ({
9
+ focusedNodePathSelector: jest.fn()
10
+ }))
11
+ const mockedFocusedNodePathSelector = focusedNodePathSelector as jest.Mock
12
+
13
+ describe("focusButton", () => {
14
+ beforeEach(() => {
15
+ TestBed.configureTestingModule({
16
+ imports: [FocusButtonsModule]
17
+ })
18
+ })
19
+ it("should render only 'focus' button if neither node nor one of its parents is focused", async () => {
20
+ const { container } = await render(FocusButtonsComponent, {
21
+ excludeComponentDeclaration: true,
22
+ componentProperties: { codeMapNode: { path: "/root/foo" } }
23
+ })
24
+
25
+ const buttons = container.querySelectorAll("button")
26
+ expect(buttons.length).toBe(1)
27
+ expect(buttons[0].textContent).toMatch(" FOCUS ")
28
+ })
29
+
30
+ it("should render 'focus' and 'unfocus parent' buttons if a parent is focused", async () => {
31
+ mockedFocusedNodePathSelector.mockImplementation(() => ["/root/foo"])
32
+ const { container } = await render(FocusButtonsComponent, {
33
+ excludeComponentDeclaration: true,
34
+ componentProperties: { codeMapNode: { path: "/root/foo/bar" } }
35
+ })
36
+
37
+ const buttons = container.querySelectorAll("button")
38
+ expect(buttons.length).toBe(2)
39
+ expect(buttons[0].textContent).toMatch(" FOCUS ")
40
+ expect(buttons[1].textContent).toMatch("UNFOCUS PARENT")
41
+ })
42
+
43
+ it("should render 'unfocus' and 'unfocus all' buttons if node is focused and there was node focused before", async () => {
44
+ mockedFocusedNodePathSelector.mockImplementation(() => ["/root/foo", "/root/bar"])
45
+ const { container } = await render(FocusButtonsComponent, {
46
+ excludeComponentDeclaration: true,
47
+ componentProperties: { codeMapNode: { path: "/root/foo" } }
48
+ })
49
+
50
+ const buttons = container.querySelectorAll("button")
51
+ expect(buttons.length).toBe(2)
52
+ expect(buttons[0].textContent).toMatch("UNFOCUS")
53
+ expect(buttons[1].textContent).toMatch("UNFOCUS ALL")
54
+ })
55
+ })
@@ -0,0 +1,38 @@
1
+ import { Component, Inject, Input } from "@angular/core"
2
+ import { Observable, map } from "rxjs"
3
+
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
+
10
+ @Component({
11
+ selector: "cc-focus-buttons",
12
+ template: require("./focusButtons.component.html")
13
+ })
14
+ export class FocusButtonsComponent {
15
+ @Input() codeMapNode: Pick<CodeMapNode, "path">
16
+
17
+ currentFocusedNodePath$: Observable<string | undefined>
18
+ hasPreviousFocusedNodePath$: Observable<boolean>
19
+
20
+ constructor(@Inject(Store) private store: Store) {
21
+ this.currentFocusedNodePath$ = this.store.select(currentFocusedNodePathSelector)
22
+ this.hasPreviousFocusedNodePath$ = this.store
23
+ .select(focusedNodePathSelector)
24
+ .pipe(map(focusedNodePaths => focusedNodePaths.length > 1))
25
+ }
26
+
27
+ handleFocusNodeClicked() {
28
+ this.store.dispatch(focusNode(this.codeMapNode.path))
29
+ }
30
+
31
+ handleUnfocusNodeClicked() {
32
+ this.store.dispatch(unfocusNode())
33
+ }
34
+
35
+ handleUnfocusAllNodesClicked() {
36
+ this.store.dispatch(unfocusAllNodes())
37
+ }
38
+ }
@@ -0,0 +1,13 @@
1
+ import { CommonModule } from "@angular/common"
2
+ import { NgModule } from "@angular/core"
3
+
4
+ import { MaterialModule } from "../../../../../material/material.module"
5
+ import { FocusButtonsComponent } from "./focusButtons.component"
6
+ import { IsNodeFocusedPipe } from "./isNodeFocused.pipe"
7
+
8
+ @NgModule({
9
+ imports: [CommonModule, MaterialModule],
10
+ declarations: [FocusButtonsComponent, IsNodeFocusedPipe],
11
+ exports: [FocusButtonsComponent]
12
+ })
13
+ export class FocusButtonsModule {}
@@ -0,0 +1,31 @@
1
+ import { IsNodeFocusedPipe } from "./isNodeFocused.pipe"
2
+
3
+ describe("isNodeFocused pipe", () => {
4
+ it("should return not focused if there is no focused node path", () => {
5
+ expect(new IsNodeFocusedPipe().transform(undefined, { path: "/root" })).toEqual({
6
+ isNodeFocused: false,
7
+ isParentFocused: false
8
+ })
9
+ })
10
+
11
+ it("should return not focused if focused node path isn't given node nor a parent", () => {
12
+ expect(new IsNodeFocusedPipe().transform("root/foo", { path: "/root/bar" })).toEqual({
13
+ isNodeFocused: false,
14
+ isParentFocused: false
15
+ })
16
+ })
17
+
18
+ it("should mark node as focused", () => {
19
+ expect(new IsNodeFocusedPipe().transform("/root/foo", { path: "/root/foo" })).toEqual({
20
+ isNodeFocused: true,
21
+ isParentFocused: false
22
+ })
23
+ })
24
+
25
+ it("should mark parent as focused", () => {
26
+ expect(new IsNodeFocusedPipe().transform("/root/foo", { path: "/root/foo/bar" })).toEqual({
27
+ isNodeFocused: false,
28
+ isParentFocused: true
29
+ })
30
+ })
31
+ })
@@ -0,0 +1,25 @@
1
+ import { Pipe, PipeTransform } from "@angular/core"
2
+
3
+ import { CodeMapNode } from "../../../../codeCharta.model"
4
+
5
+ type IsNodeFocusedType = {
6
+ isNodeFocused: boolean
7
+ isParentFocused: boolean
8
+ }
9
+
10
+ @Pipe({ name: "isNodeFocused" })
11
+ export class IsNodeFocusedPipe implements PipeTransform {
12
+ transform(focusedNodePath: string | undefined, node: Pick<CodeMapNode, "path">): IsNodeFocusedType {
13
+ if (!focusedNodePath || !node)
14
+ return {
15
+ isNodeFocused: false,
16
+ isParentFocused: false
17
+ }
18
+
19
+ const isNodeFocused = focusedNodePath === node.path
20
+ return {
21
+ isNodeFocused,
22
+ isParentFocused: !isNodeFocused && node.path.startsWith(focusedNodePath)
23
+ }
24
+ }
25
+ }
@@ -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>
@@ -0,0 +1,64 @@
1
+ import { render, screen } from "@testing-library/angular"
2
+ import { TestBed } from "@angular/core/testing"
3
+ import userEvent from "@testing-library/user-event"
4
+ import { HighlightButtonsModule } from "./highlightButtons.module"
5
+ import { ThreeSceneServiceToken } from "../../../../services/ajs-upgraded-providers"
6
+ import { HighlightButtonsComponent } from "./highlightButtons.component"
7
+ import { VALID_FILE_NODE_WITH_ID as codeMapNode } from "../../../../util/dataMocks"
8
+ import { State } from "../../../angular-redux/state"
9
+ import { CodeMapNode } from "../../../../codeCharta.model"
10
+
11
+ describe("flattenButtonsComponent", () => {
12
+ let threeSceneService
13
+ let state
14
+
15
+ beforeEach(() => {
16
+ threeSceneService = createMockedThreeSceneService()
17
+ state = createMockedState()
18
+ TestBed.configureTestingModule({
19
+ imports: [HighlightButtonsModule],
20
+ providers: [
21
+ { provide: ThreeSceneServiceToken, useValue: threeSceneService },
22
+ { provide: State, useValue: state }
23
+ ]
24
+ })
25
+ })
26
+
27
+ it("should let a user permanently highlight and remove permanently highlight of a node", async () => {
28
+ state.getValue().lookUp.idToBuilding.set(codeMapNode.id, { id: codeMapNode.id, node: codeMapNode })
29
+
30
+ const { rerender } = await render(HighlightButtonsComponent, {
31
+ excludeComponentDeclaration: true,
32
+ componentProperties: { codeMapNode }
33
+ })
34
+
35
+ expect(screen.queryByText("REMOVE HIGHLIGHT")).toBe(null)
36
+ userEvent.click(screen.getByText("KEEP HIGHLIGHT"))
37
+
38
+ rerender({ codeMapNode: null })
39
+ rerender({ codeMapNode })
40
+
41
+ expect(screen.queryByText("KEEP HIGHLIGHT")).toBe(null)
42
+ userEvent.click(screen.getByText("REMOVE HIGHLIGHT"))
43
+
44
+ rerender({ codeMapNode: null })
45
+ rerender({ codeMapNode })
46
+
47
+ expect(screen.queryByText("REMOVE HIGHLIGHT")).toBe(null)
48
+ expect(screen.queryByText("KEEP HIGHLIGHT")).not.toBe(null)
49
+ })
50
+
51
+ function createMockedThreeSceneService() {
52
+ const highlighted = new Map()
53
+ return {
54
+ addNodeAndChildrenToConstantHighlight: (node: CodeMapNode) => highlighted.set(node.id, node),
55
+ removeNodeAndChildrenFromConstantHighlight: (node: CodeMapNode) => highlighted.delete(node.id),
56
+ getConstantHighlight: () => highlighted
57
+ }
58
+ }
59
+
60
+ function createMockedState() {
61
+ const idToBuilding = new Map()
62
+ return { getValue: () => ({ lookUp: { idToBuilding } }) }
63
+ }
64
+ })
@@ -0,0 +1,39 @@
1
+ import { Component, Inject, Input, OnChanges, SimpleChanges } from "@angular/core"
2
+ import { CodeMapNode } from "../../../../codeCharta.model"
3
+ import { ThreeSceneServiceToken } from "../../../../services/ajs-upgraded-providers"
4
+ import { State } from "../../../angular-redux/state"
5
+ import { ThreeSceneService } from "../../../../ui/codeMap/threeViewer/threeSceneService"
6
+
7
+ @Component({
8
+ selector: "cc-highlight-buttons",
9
+ template: require("./highlightButtons.component.html")
10
+ })
11
+ export class HighlightButtonsComponent implements OnChanges {
12
+ @Input() codeMapNode: CodeMapNode
13
+
14
+ isHighlighted: boolean
15
+
16
+ constructor(@Inject(ThreeSceneServiceToken) private threeSceneService: ThreeSceneService, @Inject(State) private state: State) {}
17
+
18
+ ngOnChanges(changes: SimpleChanges): void {
19
+ if (changes.codeMapNode) this.isHighlighted = this.calculateIsHighlighted()
20
+ }
21
+
22
+ addNodeToConstantHighlight() {
23
+ this.threeSceneService.addNodeAndChildrenToConstantHighlight(this.codeMapNode)
24
+ }
25
+
26
+ removeNodeFromConstantHighlight() {
27
+ this.threeSceneService.removeNodeAndChildrenFromConstantHighlight(this.codeMapNode)
28
+ }
29
+
30
+ private calculateIsHighlighted() {
31
+ if (!this.codeMapNode) return false
32
+
33
+ const { lookUp } = this.state.getValue()
34
+ const codeMapBuilding = lookUp.idToBuilding.get(this.codeMapNode.id)
35
+ if (!codeMapBuilding) return false
36
+
37
+ return this.threeSceneService.getConstantHighlight().has(codeMapBuilding.id)
38
+ }
39
+ }
@@ -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 { HighlightButtonsComponent } from "./highlightButtons.component"
5
+
6
+ @NgModule({
7
+ imports: [CommonModule, MaterialModule],
8
+ declarations: [HighlightButtonsComponent],
9
+ exports: [HighlightButtonsComponent]
10
+ })
11
+ export class HighlightButtonsModule {}
@@ -0,0 +1,22 @@
1
+ <div class="row" *ngIf="codeMapNode$ | async as codeMapNode">
2
+ <ng-container *ngFor="let markFolderItem of markFolderItems$ | async">
3
+ <button
4
+ [style.background-color]="markFolderItem.color"
5
+ (click)="markFolderItem.isMarked ? unmarkFolder(codeMapNode.path) : markFolder(codeMapNode.path, markFolderItem.color)"
6
+ class="colorButton"
7
+ title="Colorize folder"
8
+ >
9
+ <i class="fa fa-times" *ngIf="markFolderItem.isMarked"></i>
10
+ </button>
11
+ </ng-container>
12
+
13
+ <cc-color-picker
14
+ [hexColor]="'#ff0000'"
15
+ (onColorChange)="markFolder(codeMapNode.path, $event)"
16
+ [triggerTemplate]="colorPickerTriggerTemplate"
17
+ ></cc-color-picker>
18
+ </div>
19
+
20
+ <ng-template #colorPickerTriggerTemplate>
21
+ <div class="cc-color-picker-trigger fa fa-paint-brush"></div>
22
+ </ng-template>
@@ -0,0 +1,31 @@
1
+ cc-mark-folder-row {
2
+ .row {
3
+ display: flex;
4
+ }
5
+
6
+ :hover {
7
+ cursor: pointer;
8
+ }
9
+
10
+ .colorButton {
11
+ width: 32px;
12
+ height: 32px;
13
+
14
+ i {
15
+ font-size: 25px;
16
+ display: block;
17
+ color: red;
18
+ text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
19
+ }
20
+ }
21
+
22
+ cc-color-picker {
23
+ width: 32px;
24
+ height: 32px;
25
+
26
+ .cc-color-picker-trigger {
27
+ font-size: 25px;
28
+ margin-top: 8px;
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,35 @@
1
+ import { TestBed } from "@angular/core/testing"
2
+ import { fireEvent, render } from "@testing-library/angular"
3
+ import { MarkFolderRowComponent } from "./markFolderRow.component"
4
+ import { MarkFolderRowModule } from "./markFolderRow.module"
5
+
6
+ jest.mock("../rightClickedCodeMapNode.selector", () => ({
7
+ rightClickedCodeMapNodeSelector: () => ({ path: "/root" })
8
+ }))
9
+
10
+ describe("markFolderRow component", () => {
11
+ beforeEach(() => {
12
+ TestBed.configureTestingModule({
13
+ imports: [MarkFolderRowModule]
14
+ })
15
+ })
16
+
17
+ it("should let a user mark and unmark a node", async () => {
18
+ const { container } = await render(MarkFolderRowComponent, { excludeComponentDeclaration: true })
19
+
20
+ expect(container.querySelectorAll("button").length).toBe(5)
21
+ expect(container.querySelectorAll("cc-color-picker").length).toBe(1)
22
+ expect(container.querySelectorAll(".fa-times").length).toBe(0)
23
+
24
+ fireEvent.click(getFirstColorButton(container))
25
+ expect(container.querySelectorAll(".fa-times").length).toBe(1)
26
+ expect(getFirstColorButton(container).querySelector(".fa-times")).not.toBe(null)
27
+
28
+ fireEvent.click(getFirstColorButton(container))
29
+ expect(container.querySelectorAll(".fa-times").length).toBe(0)
30
+
31
+ function getFirstColorButton(container: Element) {
32
+ return container.querySelectorAll("button[title='Colorize folder']")[0]
33
+ }
34
+ })
35
+ })