codecharta-visualization 1.89.0 → 1.90.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 (104) hide show
  1. package/app/app.module.ts +16 -2
  2. package/app/codeCharta/assets/gameObjectsFile.json +75 -0
  3. package/app/codeCharta/codeCharta.model.ts +1 -10
  4. package/app/codeCharta/services/idToBuilding/idToBuilding.service.ts +17 -0
  5. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.spec.ts +14 -23
  6. package/app/codeCharta/state/effects/nodeContextMenu/highlightButtons/highlightButtons.component.ts +7 -5
  7. package/app/codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.component.spec.ts +3 -1
  8. package/app/codeCharta/state/effects/nodeContextMenu/rightClickedCodeMapNode.selector.ts +1 -1
  9. package/app/codeCharta/state/effects/trackEventUsageData/trackEventUsageData.effect.spec.ts +56 -0
  10. package/app/codeCharta/state/effects/trackEventUsageData/trackEventUsageData.effect.ts +49 -0
  11. package/app/codeCharta/state/effects/unfocusNodesOnLoadingMap.effect.ts +2 -1
  12. package/app/codeCharta/state/injector.service.ts +0 -4
  13. package/app/codeCharta/state/selectors/accumulatedData/idToNode.selector.spec.ts +15 -0
  14. package/app/codeCharta/state/selectors/accumulatedData/idToNode.selector.ts +16 -0
  15. package/app/codeCharta/state/selectors/selectedNode.selector.ts +5 -2
  16. package/app/codeCharta/state/state.module.ts +0 -4
  17. package/app/codeCharta/state/store/appSettings/isLoadingMap/isLoadingMap.reducer.ts +1 -5
  18. package/app/codeCharta/state/store/state.actions.ts +0 -2
  19. package/app/codeCharta/state/store/state.reducer.ts +0 -2
  20. package/app/codeCharta/state/store/state.splitter.ts +0 -10
  21. package/app/codeCharta/state/store.service.ts +0 -16
  22. package/app/codeCharta/ui/attributeSideBar/attributeSideBar.component.spec.ts +5 -1
  23. package/app/codeCharta/ui/attributeSideBar/attributeSideBar.component.ts +2 -2
  24. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/attributeSideBarHeaderSection.component.html +0 -1
  25. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/attributeSideBarHeaderSection.component.spec.ts +3 -45
  26. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/attributeSideBarHeaderSection.component.ts +2 -8
  27. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/nodePath/nodePath.component.html +1 -1
  28. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/nodePath/nodePath.component.spec.ts +3 -2
  29. package/app/codeCharta/ui/attributeSideBar/attributeSideBarHeaderSection/nodePath/nodePath.component.ts +2 -2
  30. package/app/codeCharta/ui/attributeSideBar/attributeSideBarSecondaryMetrics/secondaryMetrics.selector.ts +2 -2
  31. package/app/codeCharta/ui/attributeSideBar/metricDeltaSelected/metricDeltaSelected.component.spec.ts +26 -23
  32. package/app/codeCharta/ui/attributeSideBar/metricDeltaSelected/metricDeltaSelected.component.ts +2 -2
  33. package/app/codeCharta/ui/attributeSideBar/util/showAttributeTypeSelector.selector.spec.ts +2 -2
  34. package/app/codeCharta/ui/attributeSideBar/util/showAttributeTypeSelector.selector.ts +2 -2
  35. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.spec.ts +28 -45
  36. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +7 -11
  37. package/app/codeCharta/ui/codeMap/codeMap.preRender.service.ts +4 -46
  38. package/app/codeCharta/ui/codeMap/threeViewer/threeSceneService.spec.ts +26 -19
  39. package/app/codeCharta/ui/codeMap/threeViewer/threeSceneService.ts +13 -25
  40. package/app/codeCharta/ui/codeMap/threeViewer/threeViewer.module.ts +3 -0
  41. package/app/codeCharta/ui/dialog/dialog.globalSettings.component.ts +3 -5
  42. package/app/codeCharta/ui/dialog/dialog.globalSettings.e2e.ts +1 -1
  43. package/app/codeCharta/ui/fileChooser/fileChooser.component.spec.ts +1 -0
  44. package/app/codeCharta/ui/fileChooser/fileChooser.component.ts +6 -1
  45. package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -0
  46. package/app/codeCharta/ui/filePanel/filePanel.component.html +1 -0
  47. package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +7 -0
  48. package/app/codeCharta/ui/filePanel/filePanel.component.ts +1 -2
  49. package/app/codeCharta/ui/filePanel/filePanel.module.ts +2 -0
  50. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +7 -1
  51. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.scss +6 -0
  52. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +2 -1
  53. package/app/codeCharta/ui/filePanel/filePanelFileSelector/removeFileButton/removeFileButton.component.html +3 -0
  54. package/app/codeCharta/ui/filePanel/filePanelFileSelector/removeFileButton/removeFileButton.component.scss +9 -0
  55. package/app/codeCharta/ui/filePanel/filePanelFileSelector/removeFileButton/removeFileButton.component.ts +11 -0
  56. package/app/codeCharta/ui/rangeSlider/rangeSlider.component.ts +9 -33
  57. package/app/codeCharta/util/__snapshots__/usageDataTracker.spec.ts.snap +1 -16
  58. package/app/codeCharta/util/codeMapHelper.ts +3 -2
  59. package/app/codeCharta/util/customConfigHelper.ts +4 -16
  60. package/app/codeCharta/util/dataMocks.ts +0 -8
  61. package/app/codeCharta/util/envDetector.ts +0 -4
  62. package/app/codeCharta/util/gameObjectsParser/__snapshots__/gameObjectsImporter.spec.ts.snap +121 -0
  63. package/app/codeCharta/util/gameObjectsParser/gameObjectsImporter.spec.ts +11 -0
  64. package/app/codeCharta/util/gameObjectsParser/gameObjectsImporter.ts +170 -0
  65. package/app/codeCharta/util/gameObjectsParser/gameObjectsMocks.ts +75 -0
  66. package/app/codeCharta/util/gameObjectsParser/gameObjectsSchema.json +271 -0
  67. package/app/codeCharta/util/gameObjectsParser/gameObjectsValidator.spec.ts +18 -0
  68. package/app/codeCharta/util/gameObjectsParser/gameObjectsValidator.ts +7 -0
  69. package/app/codeCharta/util/nodeDecorator.ts +1 -0
  70. package/app/codeCharta/util/usageDataTracker.spec.ts +36 -76
  71. package/app/codeCharta/util/usageDataTracker.ts +20 -31
  72. package/conf/webpack.config.js +7 -7
  73. package/dist/webpack/bundle.js +871 -1260
  74. package/dist/webpack/bundle.js.map +1 -1
  75. package/package.json +10 -11
  76. package/app/codeCharta/state/selectors/selectedBuilding.selector.ts +0 -8
  77. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.actions.ts +0 -22
  78. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.reducer.spec.ts +0 -33
  79. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.reducer.ts +0 -14
  80. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.selector.ts +0 -3
  81. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.service.spec.ts +0 -40
  82. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.service.ts +0 -23
  83. package/app/codeCharta/state/store/lookUp/idToBuilding/idToBuilding.splitter.ts +0 -6
  84. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.actions.ts +0 -22
  85. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.reducer.spec.ts +0 -39
  86. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.reducer.ts +0 -11
  87. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.selector.ts +0 -4
  88. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.service.spec.ts +0 -57
  89. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.service.ts +0 -23
  90. package/app/codeCharta/state/store/lookUp/idToNode/idToNode.splitter.ts +0 -6
  91. package/app/codeCharta/state/store/lookUp/lookUp.actions.ts +0 -27
  92. package/app/codeCharta/state/store/lookUp/lookUp.reducer.ts +0 -10
  93. package/app/codeCharta/state/store/lookUp/lookUp.selector.ts +0 -3
  94. package/app/codeCharta/state/store/lookUp/lookUp.splitter.ts +0 -19
  95. package/app/codeCharta/ui/removeFileButton/removeFileButton.component.html +0 -5
  96. package/app/codeCharta/ui/removeFileButton/removeFileButton.component.scss +0 -41
  97. package/app/codeCharta/ui/removeFileButton/removeFileButton.component.ts +0 -18
  98. package/app/codeCharta/ui/removeFileButton/removeFileButton.module.ts +0 -7
  99. package/app/codeCharta/util/codeChartaFileStorage.spec.ts +0 -73
  100. package/app/codeCharta/util/codeChartaStorage.ts +0 -62
  101. package/app/codeCharta/util/lazyLoader.spec.ts +0 -33
  102. package/app/codeCharta/util/lazyLoader.ts +0 -50
  103. package/dist/webpack/vendors-node_modules_open_index_js.bundle.js +0 -1036
  104. package/dist/webpack/vendors-node_modules_open_index_js.bundle.js.map +0 -1
@@ -0,0 +1,271 @@
1
+ {
2
+ "$id": "http://example.com/example.json",
3
+ "$schema": "http://json-schema.org/draft-07/schema",
4
+ "default": {},
5
+ "description": "This is the JSON Schema for the GameObjectsPositions structure",
6
+ "examples": [
7
+ {
8
+ "gameObjectPositions": [
9
+ {
10
+ "name": "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.HelloWorldTest",
11
+ "position": {
12
+ "x": 69.0,
13
+ "y": 18.5,
14
+ "z": 228.5
15
+ },
16
+ "scale": {
17
+ "x": 9.0,
18
+ "y": 5.0,
19
+ "z": 9.0
20
+ }
21
+ },
22
+ {
23
+ "name": "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.TryCatchFinallyTest",
24
+ "position": {
25
+ "x": 66.0,
26
+ "y": 22.5,
27
+ "z": 177.5
28
+ },
29
+ "scale": {
30
+ "x": 1.0,
31
+ "y": 13.0,
32
+ "z": 1.0
33
+ }
34
+ }
35
+ ],
36
+ "cycles": [
37
+ {
38
+ "from": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParser",
39
+ "to": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParserParameter"
40
+ }
41
+ ]
42
+ }
43
+ ],
44
+ "required": ["gameObjectPositions"],
45
+ "title": "The root schema",
46
+ "type": "object",
47
+ "properties": {
48
+ "gameObjectPositions": {
49
+ "$id": "#/properties/gameObjectPositions",
50
+ "type": "array",
51
+ "title": "The gameObjectPositions schema",
52
+ "description": "Defines the position and scale of GameObjects",
53
+ "default": [],
54
+ "examples": [
55
+ [
56
+ {
57
+ "name": "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.HelloWorldTest",
58
+ "position": {
59
+ "x": 69.0,
60
+ "y": 18.5,
61
+ "z": 228.5
62
+ },
63
+ "scale": {
64
+ "x": 9.0,
65
+ "y": 5.0,
66
+ "z": 9.0
67
+ }
68
+ },
69
+ {
70
+ "name": "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.SwitchCaseTest",
71
+ "position": {
72
+ "x": 65.0,
73
+ "y": 22.0,
74
+ "z": 181.0
75
+ },
76
+ "scale": {
77
+ "x": 2.0,
78
+ "y": 12.0,
79
+ "z": 2.0
80
+ }
81
+ }
82
+ ]
83
+ ],
84
+ "additionalItems": true,
85
+ "items": {
86
+ "$id": "#/properties/gameObjectPositions/items",
87
+ "anyOf": [
88
+ {
89
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0",
90
+ "type": "object",
91
+ "title": "The first anyOf schema",
92
+ "description": "Defines the properties of a GameObject",
93
+ "default": {},
94
+ "examples": [
95
+ {
96
+ "name": "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.HelloWorldTest",
97
+ "position": {
98
+ "x": 69.0,
99
+ "y": 18.5,
100
+ "z": 228.5
101
+ },
102
+ "scale": {
103
+ "x": 9.0,
104
+ "y": 5.0,
105
+ "z": 9.0
106
+ }
107
+ }
108
+ ],
109
+ "required": ["name", "position", "scale"],
110
+ "properties": {
111
+ "name": {
112
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/name",
113
+ "type": "string",
114
+ "title": "The name schema",
115
+ "description": "An explanation about the purpose of this instance.",
116
+ "default": "",
117
+ "examples": [
118
+ "root.analysis.import.SourceCodeParser.src.test.kotlin.de.maibornwolff.codecharta.importer.sourcecodeparser.oop.core.extract.HelloWorldTest"
119
+ ]
120
+ },
121
+ "position": {
122
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/position",
123
+ "type": "object",
124
+ "title": "The position schema",
125
+ "description": "The position in absolute values",
126
+ "default": {},
127
+ "examples": [
128
+ {
129
+ "x": 69.0,
130
+ "y": 18.5,
131
+ "z": 228.5
132
+ }
133
+ ],
134
+ "required": ["x", "y", "z"],
135
+ "properties": {
136
+ "x": {
137
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/position/properties/x",
138
+ "type": "number",
139
+ "title": "The x schema",
140
+ "description": "x position",
141
+ "default": 0.0,
142
+ "examples": [69.0]
143
+ },
144
+ "y": {
145
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/position/properties/y",
146
+ "type": "number",
147
+ "title": "The y schema",
148
+ "description": "y position",
149
+ "default": 0.0,
150
+ "examples": [18.5]
151
+ },
152
+ "z": {
153
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/position/properties/z",
154
+ "type": "number",
155
+ "title": "The z schema",
156
+ "description": "z position",
157
+ "default": 0.0,
158
+ "examples": [228.5]
159
+ }
160
+ },
161
+ "additionalProperties": true
162
+ },
163
+ "scale": {
164
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/scale",
165
+ "type": "object",
166
+ "title": "The scale schema",
167
+ "description": "The scale of GameObjects",
168
+ "default": {},
169
+ "examples": [
170
+ {
171
+ "x": 9.0,
172
+ "y": 5.0,
173
+ "z": 9.0
174
+ }
175
+ ],
176
+ "required": ["x", "y", "z"],
177
+ "properties": {
178
+ "x": {
179
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/scale/properties/x",
180
+ "type": "number",
181
+ "title": "The x schema",
182
+ "description": "x scale",
183
+ "default": 0.0,
184
+ "examples": [9.0]
185
+ },
186
+ "y": {
187
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/scale/properties/y",
188
+ "type": "number",
189
+ "title": "The y schema",
190
+ "description": "y scale",
191
+ "default": 0.0,
192
+ "examples": [5.0]
193
+ },
194
+ "z": {
195
+ "$id": "#/properties/gameObjectPositions/items/anyOf/0/properties/scale/properties/z",
196
+ "type": "number",
197
+ "title": "The z schema",
198
+ "description": "z scale",
199
+ "default": 0.0,
200
+ "examples": [9.0]
201
+ }
202
+ },
203
+ "additionalProperties": true
204
+ }
205
+ },
206
+ "additionalProperties": true
207
+ }
208
+ ]
209
+ }
210
+ },
211
+ "cycles": {
212
+ "$id": "#/properties/cycles",
213
+ "type": "array",
214
+ "title": "The cycles schema",
215
+ "description": "Defines the cycles between GameObjects",
216
+ "default": [],
217
+ "examples": [
218
+ [
219
+ {
220
+ "from": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParser",
221
+ "to": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParserParameter"
222
+ }
223
+ ]
224
+ ],
225
+ "additionalItems": true,
226
+ "items": {
227
+ "$id": "#/properties/cycles/items",
228
+ "anyOf": [
229
+ {
230
+ "$id": "#/properties/cycles/items/anyOf/0",
231
+ "type": "object",
232
+ "title": "The first anyOf schema",
233
+ "description": "A cycle between two GameObjects",
234
+ "default": {},
235
+ "examples": [
236
+ {
237
+ "from": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParser",
238
+ "to": "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParserParameter"
239
+ }
240
+ ],
241
+ "required": ["from", "to"],
242
+ "properties": {
243
+ "from": {
244
+ "$id": "#/properties/cycles/items/anyOf/0/properties/from",
245
+ "type": "string",
246
+ "title": "The from schema",
247
+ "description": "from GameObject",
248
+ "default": "",
249
+ "examples": [
250
+ "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParser"
251
+ ]
252
+ },
253
+ "to": {
254
+ "$id": "#/properties/cycles/items/anyOf/0/properties/to",
255
+ "type": "string",
256
+ "title": "The to schema",
257
+ "description": "to GameObject",
258
+ "default": "",
259
+ "examples": [
260
+ "root.analysis.import.SCMLogParser.src.main.java.de.maibornwolff.codecharta.importer.scmlogparser.SCMLogParserParameter"
261
+ ]
262
+ }
263
+ },
264
+ "additionalProperties": true
265
+ }
266
+ ]
267
+ }
268
+ }
269
+ },
270
+ "additionalProperties": true
271
+ }
@@ -0,0 +1,18 @@
1
+ import { validateGameObjects } from "./gameObjectsValidator"
2
+ import { clone } from "../clone"
3
+ import { TEST_GAMEOBJECTS_FILE } from "./gameObjectsMocks"
4
+
5
+ describe("GameObjectsValidator", () => {
6
+ it("should check if gameObjects File structure is valid", function () {
7
+ const gameObjectsFile = clone(TEST_GAMEOBJECTS_FILE)
8
+
9
+ expect(validateGameObjects(JSON.stringify(gameObjectsFile))).toBeTruthy()
10
+
11
+ // @ts-ignore
12
+ gameObjectsFile.gameObjectPositions[0].position.x = false
13
+ // @ts-ignore
14
+ gameObjectsFile.gameObjectPositions[0].scale = {}
15
+
16
+ expect(validateGameObjects(JSON.stringify(gameObjectsFile))).toBeFalsy()
17
+ })
18
+ })
@@ -0,0 +1,7 @@
1
+ import Ajv from "ajv"
2
+ import gameObjectsSchema from "./gameObjectsSchema.json"
3
+
4
+ export function validateGameObjects(jsonContent: string) {
5
+ const ajv = new Ajv({ allErrors: true })
6
+ return ajv.validate(gameObjectsSchema, JSON.parse(jsonContent))
7
+ }
@@ -177,6 +177,7 @@ function mergeFolderChain(data: CodeMapNode) {
177
177
  // Nodes with only one child which also have children are merged into one node
178
178
  // e.g. a /folder which includes anotherFolder that includes other files or folders
179
179
  // will be merged to a node with path /folder/anotherFolder and children are set accordingly
180
+ if (data.children?.length === 1 && data.children[0]?.fixedPosition) return
180
181
 
181
182
  if (data.children?.length === 1 && data.children[0].children?.length > 0) {
182
183
  const [child] = data.children
@@ -1,15 +1,10 @@
1
- import { BlacklistItem, CCFile, CodeMapNode, NodeType, State } from "../codeCharta.model"
2
- import { trackEventUsageData, trackMapMetaData } from "./usageDataTracker"
3
- import * as EnvironmentDetector from "./envDetector"
1
+ import { CCFile, CodeMapNode, NodeType, State } from "../codeCharta.model"
2
+ import { trackEventUsageData, TRACKING_DATA_LOCAL_STORAGE_ELEMENT, trackMapMetaData } from "./usageDataTracker"
4
3
  import * as FilesHelper from "../model/files/files.helper"
5
4
  import { FileState } from "../model/files/files"
6
5
  import { APIVersions } from "../codeCharta.api.model"
7
- import { CodeChartaStorage } from "./codeChartaStorage"
8
6
  import { HeightMetricActions } from "../state/store/dynamicSettings/heightMetric/heightMetric.actions"
9
- import { BlacklistActions } from "../state/store/fileSettings/blacklist/blacklist.actions"
10
- import { FocusedNodePathActions } from "../state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
11
7
  import { klona } from "klona"
12
- jest.mock("./codeChartaStorage")
13
8
 
14
9
  describe("UsageDataTracker", () => {
15
10
  // provide some default state properties
@@ -25,9 +20,8 @@ describe("UsageDataTracker", () => {
25
20
  } as State
26
21
 
27
22
  let singleFileState: FileState
28
- beforeEach(() => {
29
- jest.resetAllMocks()
30
23
 
24
+ beforeEach(() => {
31
25
  singleFileState = {
32
26
  file: {
33
27
  fileMeta: {
@@ -41,66 +35,53 @@ describe("UsageDataTracker", () => {
41
35
  })
42
36
 
43
37
  function mockTrackingToBeAllowed() {
44
- jest.spyOn(EnvironmentDetector, "isStandalone").mockReturnValue(true)
45
38
  jest.spyOn(FilesHelper, "isSingleState").mockReturnValue(true)
46
39
  jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([singleFileState])
47
40
  }
48
41
 
49
42
  describe("trackMetaUsageData", () => {
50
- const setItemMock = jest.fn()
51
- CodeChartaStorage.prototype.setItem = setItemMock
52
-
53
- afterAll(() => {
54
- jest.resetAllMocks()
55
- jest.unmock("./codeChartaStorage")
43
+ beforeEach(() => {
44
+ jest.spyOn(window.localStorage.__proto__, "setItem")
45
+ window.localStorage.__proto__.setItem = jest.fn()
56
46
  })
57
-
58
- it("should not track in web version, in multi/delta mode or for more than one uploaded file", () => {
59
- jest.spyOn(EnvironmentDetector, "isStandalone").mockReturnValue(false)
60
- jest.spyOn(FilesHelper, "isSingleState").mockReturnValue(true)
61
- jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([{} as FileState])
62
-
63
- trackMapMetaData(stateStub)
64
-
65
- jest.spyOn(EnvironmentDetector, "isStandalone").mockReturnValue(true)
47
+ it("should not track in multi/delta mode or for more than one uploaded file", () => {
66
48
  jest.spyOn(FilesHelper, "isSingleState").mockReturnValue(false)
67
49
  jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([{} as FileState])
68
50
 
69
- trackMapMetaData(stateStub)
51
+ trackMapMetaData(stateStub.files)
70
52
 
71
- jest.spyOn(EnvironmentDetector, "isStandalone").mockReturnValue(true)
72
53
  jest.spyOn(FilesHelper, "isSingleState").mockReturnValue(true)
73
54
  jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([{} as FileState, {} as FileState])
74
55
 
75
- trackMapMetaData(stateStub)
56
+ trackMapMetaData(stateStub.files)
76
57
 
77
- expect(setItemMock).not.toHaveBeenCalled()
58
+ expect(localStorage.setItem).not.toHaveBeenCalled()
78
59
  })
79
60
 
80
61
  it("should not track maps from old API versions", () => {
81
62
  singleFileState.file.fileMeta.apiVersion = APIVersions.ZERO_POINT_ONE
82
63
  mockTrackingToBeAllowed()
83
- trackMapMetaData(stateStub)
64
+ trackMapMetaData(stateStub.files)
84
65
 
85
66
  singleFileState.file.fileMeta.apiVersion = "0.9"
86
- trackMapMetaData(stateStub)
67
+ trackMapMetaData(stateStub.files)
87
68
 
88
- expect(setItemMock).not.toHaveBeenCalled()
69
+ expect(localStorage.setItem).not.toHaveBeenCalled()
89
70
  })
90
71
 
91
72
  it("should track from API version 1.0", () => {
92
73
  singleFileState.file.map = { path: "/root" } as CodeMapNode
93
74
 
94
75
  mockTrackingToBeAllowed()
95
- trackMapMetaData(stateStub)
76
+ trackMapMetaData(stateStub.files)
96
77
 
97
78
  singleFileState.file.fileMeta.apiVersion = "1.0"
98
- trackMapMetaData(stateStub)
79
+ trackMapMetaData(stateStub.files)
99
80
 
100
81
  singleFileState.file.fileMeta.apiVersion = "2.0"
101
- trackMapMetaData(stateStub)
82
+ trackMapMetaData(stateStub.files)
102
83
 
103
- expect(setItemMock).toHaveBeenCalledTimes(3)
84
+ expect(localStorage.setItem).toHaveBeenCalledTimes(3)
104
85
  })
105
86
 
106
87
  it("should track files with multiple programming languages properly", () => {
@@ -121,71 +102,50 @@ describe("UsageDataTracker", () => {
121
102
  mockTrackingToBeAllowed()
122
103
  jest.spyOn(Date, "now").mockReturnValue(1_612_369_999_999)
123
104
 
124
- const expectSetItemSnapshot = (CodeChartaStorage.prototype.setItem = jest.fn().mockImplementation((_, value) => {
105
+ jest.spyOn(window.localStorage.__proto__, "setItem")
106
+ window.localStorage.__proto__.setItem = jest.fn().mockImplementation((_, value) => {
125
107
  expect(value).toMatchSnapshot()
126
- }))
108
+ })
127
109
 
128
- trackMapMetaData(stateStub)
110
+ trackMapMetaData(stateStub.files)
129
111
 
130
- expect(expectSetItemSnapshot).toHaveBeenCalledTimes(1)
112
+ expect(localStorage.setItem).toHaveBeenCalledTimes(1)
131
113
  }
132
114
  })
133
115
 
134
116
  describe("trackEventUsageData", () => {
135
- afterAll(() => {
136
- jest.resetAllMocks()
137
- jest.unmock("./codeChartaStorage")
138
- })
139
-
140
- let getItemMock
141
- let expectSetItemSnapshot
142
-
143
117
  beforeEach(() => {
144
- jest.spyOn(EnvironmentDetector, "isStandalone").mockReturnValue(true)
118
+ jest.restoreAllMocks()
119
+
145
120
  jest.spyOn(FilesHelper, "isSingleState").mockReturnValue(true)
146
121
  jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([singleFileState])
147
122
  jest.spyOn(Date, "now").mockReturnValue(1_612_428_357_566)
148
123
 
149
- getItemMock = CodeChartaStorage.prototype.getItem = jest.fn().mockReturnValue("some-already-tracked-events-from-file-storage")
150
- expectSetItemSnapshot = CodeChartaStorage.prototype.setItem = jest.fn().mockImplementation((_, value) => {
124
+ jest.spyOn(window.localStorage.__proto__, "getItem")
125
+ jest.spyOn(window.localStorage.__proto__, "setItem")
126
+ window.localStorage.__proto__.getItem = jest.fn().mockReturnValue("some-already-tracked-events-from-file-storage")
127
+ window.localStorage.__proto__.setItem = jest.fn().mockImplementation((_, value) => {
151
128
  expect(value).toMatchSnapshot()
152
129
  })
153
130
  })
154
131
 
155
132
  function expectEventHasBeenTracked() {
156
133
  expect(FilesHelper.getVisibleFileStates).toHaveBeenCalledTimes(3)
157
- expect(getItemMock).toHaveBeenCalledWith("usageData/invalid-md5-sample-checksum-events")
158
- expect(expectSetItemSnapshot).toHaveBeenCalledTimes(1)
134
+ expect(localStorage.getItem).toHaveBeenCalledWith(`${TRACKING_DATA_LOCAL_STORAGE_ELEMENT}/invalid-md5-sample-checksum-events`)
135
+ expect(localStorage.setItem).toHaveBeenCalledTimes(1)
159
136
  }
160
137
 
161
- it("should not track on not allowed events", () => {
162
- trackEventUsageData("EVENT_ACTION_WHICH_SHOULD_NOT_BE_TRACKED", stateStub)
138
+ it("should not track when tracking is not allowed", () => {
139
+ jest.spyOn(FilesHelper, "getVisibleFileStates").mockReturnValue([singleFileState, singleFileState])
140
+
141
+ trackEventUsageData(HeightMetricActions.SET_HEIGHT_METRIC, stateStub.files, "newHeightMetricValue")
163
142
 
164
143
  // A second call would indicate that the tracking has not been cancelled as expected
165
144
  expect(FilesHelper.getVisibleFileStates).toHaveBeenCalledTimes(1)
166
145
  })
167
146
 
168
- it("should track setting changed event", () => {
169
- trackEventUsageData(HeightMetricActions.SET_HEIGHT_METRIC, stateStub, "newHeightMetricValue")
170
- expectEventHasBeenTracked()
171
- })
172
-
173
- it("should track setting changed event for resetting the blacklist", () => {
174
- trackEventUsageData(BlacklistActions.SET_BLACKLIST, stateStub, [])
175
- expectEventHasBeenTracked()
176
- })
177
-
178
- it("should track node interaction blacklist event", () => {
179
- trackEventUsageData(BlacklistActions.ADD_BLACKLIST_ITEM, stateStub, {
180
- path: "test",
181
- attributes: {},
182
- type: "exclude"
183
- } as BlacklistItem)
184
- expectEventHasBeenTracked()
185
- })
186
-
187
- it("should track node interaction focus event", () => {
188
- trackEventUsageData(FocusedNodePathActions.FOCUS_NODE, stateStub, "focusedPathPayload")
147
+ it("should track an event", () => {
148
+ trackEventUsageData(HeightMetricActions.SET_HEIGHT_METRIC, stateStub.files, "newHeightMetricValue")
189
149
  expectEventHasBeenTracked()
190
150
  })
191
151
  })
@@ -1,9 +1,7 @@
1
1
  "use strict"
2
2
 
3
3
  import { getVisibleFileStates, isSingleState } from "../model/files/files.helper"
4
- import { CodeChartaStorage } from "./codeChartaStorage"
5
- import { CodeMapNode, NodeType, State } from "../codeCharta.model"
6
- import { isStandalone } from "./envDetector"
4
+ import { CodeMapNode, NodeType } from "../codeCharta.model"
7
5
  import { isActionOfType } from "./reduxHelper"
8
6
  import { AreaMetricActions } from "../state/store/dynamicSettings/areaMetric/areaMetric.actions"
9
7
  import { HeightMetricActions } from "../state/store/dynamicSettings/heightMetric/heightMetric.actions"
@@ -15,8 +13,8 @@ import { APIVersions } from "../codeCharta.api.model"
15
13
  import { getAsApiVersion } from "./fileValidator"
16
14
  import { hierarchy } from "d3-hierarchy"
17
15
  import { getMedian, pushSorted } from "./nodeDecorator"
18
- import { RangeSliderController } from "../ui/rangeSlider/rangeSlider.component"
19
16
  import { ColorRangeActions } from "../state/store/dynamicSettings/colorRange/colorRange.actions"
17
+ import { FileState } from "../model/files/files"
20
18
 
21
19
  interface MetaDataTrackingItem {
22
20
  mapId: string
@@ -56,10 +54,12 @@ interface MetricStatistics {
56
54
  metricValues: number[]
57
55
  }
58
56
 
59
- function isTrackingAllowed(state: State) {
60
- const singleFileStates = getVisibleFileStates(state.files)
57
+ export const TRACKING_DATA_LOCAL_STORAGE_ELEMENT = "CodeCharta::usageData"
61
58
 
62
- if (!isStandalone() || !isSingleState(state.files) || singleFileStates.length > 1) {
59
+ function isTrackingAllowed(files: FileState[]) {
60
+ const singleFileStates = getVisibleFileStates(files)
61
+
62
+ if (!isSingleState(files) || singleFileStates.length > 1) {
63
63
  return false
64
64
  }
65
65
 
@@ -72,12 +72,12 @@ function isTrackingAllowed(state: State) {
72
72
  )
73
73
  }
74
74
 
75
- export function trackMapMetaData(state: State) {
76
- if (!isTrackingAllowed(state)) {
75
+ export function trackMapMetaData(files: FileState[]) {
76
+ if (!isTrackingAllowed(files)) {
77
77
  return
78
78
  }
79
79
 
80
- const singleFileStates = getVisibleFileStates(state.files)
80
+ const singleFileStates = getVisibleFileStates(files)
81
81
  const fileNodes: CodeMapNode[] = getFileNodes(singleFileStates[0].file.map)
82
82
  const fileMeta = singleFileStates[0].file.fileMeta
83
83
 
@@ -90,12 +90,11 @@ export function trackMapMetaData(state: State) {
90
90
  repoCreationDate: fileMeta.repoCreationDate
91
91
  }
92
92
 
93
- const fileStorage = new CodeChartaStorage()
94
93
  // Make sure that only files within usageData can be read
95
94
  const fileChecksum = trackingDataItem.mapId.replace(/\//g, "")
96
95
 
97
96
  try {
98
- fileStorage.setItem(`usageData/${fileChecksum}-meta`, JSON.stringify(trackingDataItem))
97
+ localStorage.setItem(`${TRACKING_DATA_LOCAL_STORAGE_ELEMENT}/${fileChecksum}-meta`, JSON.stringify(trackingDataItem))
99
98
  } catch {
100
99
  // ignore it
101
100
  }
@@ -269,21 +268,10 @@ interface EventTrackingItem {
269
268
  payload: SettingChangedEventPayload | NodeInteractionEventPayload
270
269
  }
271
270
 
272
- export function trackEventUsageData(actionType: string, state: State, payload?: any) {
273
- if (
274
- !isTrackingAllowed(state) ||
275
- (!isActionOfType(actionType, AreaMetricActions) &&
276
- !isActionOfType(actionType, HeightMetricActions) &&
277
- !isActionOfType(actionType, ColorMetricActions) &&
278
- !isActionOfType(actionType, ColorRangeActions) &&
279
- !isActionOfType(actionType, BlacklistActions) &&
280
- !isActionOfType(actionType, FocusedNodePathActions) &&
281
- ![RangeSliderController.COLOR_RANGE_FROM_UPDATED, RangeSliderController.COLOR_RANGE_TO_UPDATED].includes(actionType))
282
- ) {
283
- return
284
- }
271
+ export function trackEventUsageData(actionType: string, files: FileState[], payload?: any) {
272
+ if (!isTrackingAllowed(files)) return
285
273
 
286
- const singleFileStates = getVisibleFileStates(state.files)
274
+ const singleFileStates = getVisibleFileStates(files)
287
275
  const fileMeta = singleFileStates[0].file.fileMeta
288
276
 
289
277
  const eventTrackingItem = buildEventTrackingItem(fileMeta.fileChecksum, actionType, payload)
@@ -292,13 +280,11 @@ export function trackEventUsageData(actionType: string, state: State, payload?:
292
280
  }
293
281
 
294
282
  // Make sure that only files within usageData can be read
295
- const fileChecksum = getVisibleFileStates(state.files)[0].file.fileMeta.fileChecksum.replace(/\//g, "")
296
-
297
- const fileStorage = new CodeChartaStorage()
283
+ const fileChecksum = getVisibleFileStates(files)[0].file.fileMeta.fileChecksum.replace(/\//g, "")
298
284
 
299
285
  let appendedEvents = ""
300
286
  try {
301
- appendedEvents = fileStorage.getItem(`usageData/${fileChecksum}-events`)
287
+ appendedEvents = localStorage.getItem(`${TRACKING_DATA_LOCAL_STORAGE_ELEMENT}/${fileChecksum}-events`)
302
288
  } catch {
303
289
  // ignore, it no events item exists
304
290
  }
@@ -307,7 +293,10 @@ export function trackEventUsageData(actionType: string, state: State, payload?:
307
293
  if (appendedEvents.length > 0) {
308
294
  appendedEvents += "\n"
309
295
  }
310
- fileStorage.setItem(`usageData/${fileChecksum}-events`, appendedEvents + JSON.stringify(eventTrackingItem))
296
+ localStorage.setItem(
297
+ `${TRACKING_DATA_LOCAL_STORAGE_ELEMENT}/${fileChecksum}-events`,
298
+ appendedEvents + JSON.stringify(eventTrackingItem)
299
+ )
311
300
  } catch {
312
301
  // ignore tracking errors
313
302
  }
@@ -8,18 +8,22 @@ const dist = path.resolve(__dirname, "../dist/webpack")
8
8
  module.exports = env => {
9
9
  return {
10
10
  mode: "development",
11
- target: JSON.parse(env.STANDALONE) ? "node" : "web",
11
+ target: "web",
12
12
  entry: "./app/app.module.ts",
13
13
  output: {
14
14
  filename: "bundle.js",
15
15
  path: dist
16
16
  },
17
17
  devServer: {
18
- contentBase: dist,
18
+ static: {
19
+ directory: dist
20
+ },
19
21
  compress: true, // enable gzip compression
20
22
  hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
21
23
  port: 3000,
22
- clientLogLevel: "error",
24
+ client: {
25
+ logging: "error"
26
+ },
23
27
  open: true
24
28
  },
25
29
  module: require("./webpack.loaders.js"),
@@ -30,7 +34,6 @@ module.exports = env => {
30
34
  favicon: "./app/assets/icon.ico"
31
35
  }),
32
36
  new DefinePlugin({
33
- "process.env.STANDALONE": JSON.stringify(env.STANDALONE),
34
37
  "process.env.DEV": JSON.stringify(env.DEV)
35
38
  }),
36
39
  new NodePolyfillPlugin()
@@ -38,9 +41,6 @@ module.exports = env => {
38
41
  devtool: "source-map",
39
42
  resolve: {
40
43
  extensions: [".ts", ".tsx", ".js"]
41
- },
42
- externals: {
43
- child_process: "require('child_process')"
44
44
  }
45
45
  }
46
46
  }