codecharta-visualization 1.87.1 → 1.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/app/app.module.ts +18 -8
  2. package/app/codeCharta/codeCharta.component.ts +2 -0
  3. package/app/codeCharta/codeCharta.model.ts +2 -0
  4. package/app/codeCharta/codeCharta.service.spec.ts +41 -50
  5. package/app/codeCharta/codeCharta.service.ts +33 -32
  6. package/app/codeCharta/e2e/url.e2e.ts +1 -1
  7. package/app/codeCharta/state/store/appStatus/appStatus.reducer.ts +3 -1
  8. package/app/codeCharta/state/store/appStatus/appStatus.selector.ts +3 -0
  9. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions.ts +23 -0
  10. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.reducer.ts +15 -0
  11. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector.ts +4 -0
  12. package/app/codeCharta/state/store/state.actions.ts +3 -1
  13. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +6 -8
  14. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +9 -9
  15. package/app/codeCharta/ui/dialog/dialog.addCustomConfigSettings.component.html +2 -2
  16. package/app/codeCharta/ui/dialog/dialog.changelog.component.scss +15 -0
  17. package/app/codeCharta/ui/dialog/dialog.changelog.component.spec.ts +15 -15
  18. package/app/codeCharta/ui/dialog/dialog.changelog.component.ts +2 -1
  19. package/app/codeCharta/ui/dialog/dialog.service.spec.ts +68 -0
  20. package/app/codeCharta/ui/dialog/dialog.service.ts +38 -17
  21. package/app/codeCharta/ui/edgeChooser/edgeChooser.e2e.ts +3 -2
  22. package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -6
  23. package/app/codeCharta/ui/filePanel/filePanel.component.html +24 -106
  24. package/app/codeCharta/ui/filePanel/filePanel.component.scss +12 -57
  25. package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +40 -72
  26. package/app/codeCharta/ui/filePanel/filePanel.component.ts +29 -81
  27. package/app/codeCharta/ui/filePanel/filePanel.module.ts +13 -1
  28. package/app/codeCharta/ui/filePanel/filePanel.po.ts +6 -24
  29. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html +23 -0
  30. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts +18 -0
  31. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +18 -0
  32. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +16 -0
  33. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html +18 -0
  34. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.ts +11 -0
  35. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +7 -5
  36. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.html +1 -1
  37. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.spec.ts +6 -16
  38. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.ts +15 -11
  39. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.html +22 -0
  40. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.scss +31 -0
  41. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +35 -0
  42. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.ts +30 -0
  43. package/app/codeCharta/ui/nodeContextMenu/{markFolderColorPicker/markFolderColorPicker.module.ts → markFolderRow/markFolderRow.module.ts} +4 -5
  44. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +17 -0
  45. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
  46. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.spec.ts +15 -0
  47. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.ts +9 -0
  48. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -15
  49. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +0 -15
  50. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +10 -119
  51. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +40 -134
  52. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -2
  53. package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +1 -1
  54. package/app/codeCharta/ui/toolBar/toolBar.component.html +1 -1
  55. package/app/codeCharta/ui/toolBar/toolBar.component.scss +1 -1
  56. package/app/codeCharta/ui/ui.ts +2 -2
  57. package/app/codeCharta/util/customConfigHelper.spec.ts +155 -60
  58. package/app/codeCharta/util/customConfigHelper.ts +33 -3
  59. package/app/codeCharta/util/dataMocks.ts +4 -2
  60. package/app/codeCharta/util/fileValidator.spec.ts +69 -182
  61. package/app/codeCharta/util/fileValidator.ts +61 -37
  62. package/dist/webpack/bundle.js +852 -485
  63. package/dist/webpack/bundle.js.map +1 -1
  64. package/package.json +1 -1
  65. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +0 -9
  66. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.scss +0 -13
  67. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +0 -10
package/app/app.module.ts CHANGED
@@ -4,7 +4,8 @@ import { Inject, NgModule } from "@angular/core"
4
4
  import { BrowserModule } from "@angular/platform-browser"
5
5
  import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"
6
6
  import { UpgradeModule } from "@angular/upgrade/static"
7
-
7
+ import { FormsModule } from "@angular/forms"
8
+ import { MaterialModule } from "./material/material.module"
8
9
  import { MapTreeViewModule } from "./codeCharta/ui/mapTreeView/mapTreeView.module"
9
10
  import { MapTreeViewComponent } from "./codeCharta/ui/mapTreeView/mapTreeView.component"
10
11
  import { MatchingFilesCounterComponent } from "./codeCharta/ui/matchingFilesCounter/matchingFilesCounter.component"
@@ -18,10 +19,13 @@ import { LegendPanelComponent } from "./codeCharta/ui/legendPanel/legendPanel.co
18
19
  import { LegendPanelModule } from "./codeCharta/ui/legendPanel/legendPanel.module"
19
20
  import { ColorPickerForMapColorModule } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.module"
20
21
  import { ColorPickerForMapColorComponent } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.component"
21
- import { MarkFolderColorPickerModule } from "./codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module"
22
- import { MarkFolderColorPickerComponent } from "./codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component"
23
22
  import { FocusButtonsModule } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module"
24
23
  import { FocusButtonsComponent } from "./codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component"
24
+ import { FilePanelFileSelectorComponent } from "./codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component"
25
+ import { FilePanelStateButtonsComponent } from "./codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component"
26
+ 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
29
 
26
30
  @NgModule({
27
31
  imports: [
@@ -30,13 +34,15 @@ import { FocusButtonsComponent } from "./codeCharta/ui/nodeContextMenu/focusButt
30
34
  MapTreeViewModule,
31
35
  MatchingFilesCounterModule,
32
36
  AttributeSideBarModule,
37
+ MaterialModule,
38
+ FormsModule,
33
39
  Export3DMapButtonModule,
34
40
  LegendPanelModule,
35
41
  ColorPickerForMapColorModule,
36
- MarkFolderColorPickerModule,
37
- FocusButtonsModule
42
+ FocusButtonsModule,
43
+ MarkFolderRowModule
38
44
  ],
39
- declarations: [],
45
+ declarations: [FilePanelFileSelectorComponent, FilePanelStateButtonsComponent, FilePanelDeltaSelectorComponent],
40
46
  entryComponents: [
41
47
  MapTreeViewComponent,
42
48
  MatchingFilesCounterComponent,
@@ -45,8 +51,12 @@ import { FocusButtonsComponent } from "./codeCharta/ui/nodeContextMenu/focusButt
45
51
  LegendPanelComponent,
46
52
  LabelledColorPickerComponent,
47
53
  ColorPickerForMapColorComponent,
48
- MarkFolderColorPickerComponent,
49
- FocusButtonsComponent
54
+ FocusButtonsComponent,
55
+ FilePanelFileSelectorComponent,
56
+ FilePanelStateButtonsComponent,
57
+ FilePanelDeltaSelectorComponent,
58
+ FocusButtonsComponent,
59
+ MarkFolderRowComponent
50
60
  ]
51
61
  })
52
62
  export class AppModule {
@@ -76,6 +76,8 @@ export class CodeChartaController {
76
76
  this.codeChartaService.loadFiles(values)
77
77
  }
78
78
 
79
+ // TODO: Please make sure that this function works fine on Github pages with
80
+ // the updated file selection (no more single mode!)
79
81
  private setRenderStateFromUrl() {
80
82
  const renderState = this.urlUtils.getParameterByName("mode")
81
83
  const files = getCCFiles(this.storeService.getState().files)
@@ -5,6 +5,7 @@ import { CodeMapBuilding } from "./ui/codeMap/rendering/codeMapBuilding"
5
5
  import { FileState } from "./model/files/files"
6
6
  import { CustomConfig } from "./model/customConfig/customConfig.api.model"
7
7
  import Rectangle from "./util/algorithm/streetLayout/rectangle"
8
+ import { RightClickedNodeData } from "./state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions"
8
9
 
9
10
  export interface NameDataPair {
10
11
  fileName: string
@@ -404,6 +405,7 @@ export interface LookUp {
404
405
  export interface AppStatus {
405
406
  hoveredBuildingPath: string | null
406
407
  selectedBuildingId: number | null
408
+ rightClickedNodeData: RightClickedNodeData
407
409
  }
408
410
 
409
411
  export enum PanelSelection {
@@ -6,9 +6,9 @@ import { BlacklistType, CCFile, NodeMetricData, NodeType } from "./codeCharta.mo
6
6
  import { StoreService } from "./state/store.service"
7
7
  import { removeFile, resetFiles } from "./state/store/files/files.actions"
8
8
  import { ExportBlacklistType, ExportCCFile } from "./codeCharta.api.model"
9
- import { getCCFiles, isSingleState } from "./model/files/files.helper"
9
+ import { getCCFiles, isPartialState } from "./model/files/files.helper"
10
10
  import { DialogService } from "./ui/dialog/dialog.service"
11
- import { CCValidationResult, ERROR_MESSAGES } from "./util/fileValidator"
11
+ import { CCFileValidationResult, ERROR_MESSAGES } from "./util/fileValidator"
12
12
  import packageJson from "../../package.json"
13
13
  import { clone } from "./util/clone"
14
14
  import { nodeMetricDataSelector } from "./state/selectors/accumulatedData/metricData/nodeMetricData.selector"
@@ -53,8 +53,7 @@ describe("codeChartaService", () => {
53
53
 
54
54
  function withMockedDialogService() {
55
55
  dialogService = codeChartaService["dialogService"] = jest.fn().mockReturnValue({
56
- showValidationErrorDialog: jest.fn(),
57
- showValidationWarningDialog: jest.fn()
56
+ showValidationDialog: jest.fn()
58
57
  })()
59
58
  }
60
59
 
@@ -137,7 +136,7 @@ describe("codeChartaService", () => {
137
136
  ])
138
137
 
139
138
  expect(getCCFiles(storeService.getState().files)[0]).toEqual(expected)
140
- expect(isSingleState(storeService.getState().files)).toBeTruthy()
139
+ expect(isPartialState(storeService.getState().files)).toBeTruthy()
141
140
  })
142
141
 
143
142
  it("should load a valid file and update root data", async () => {
@@ -150,9 +149,8 @@ describe("codeChartaService", () => {
150
149
  ])
151
150
 
152
151
  expect(getCCFiles(storeService.getState().files)[0]).toEqual(expected)
153
- expect(isSingleState(storeService.getState().files)).toBeTruthy()
154
- expect(dialogService.showValidationWarningDialog).not.toHaveBeenCalled()
155
- expect(dialogService.showValidationErrorDialog).not.toHaveBeenCalled()
152
+ expect(isPartialState(storeService.getState().files)).toBeTruthy()
153
+ expect(dialogService.showValidationDialog).not.toHaveBeenCalled()
156
154
 
157
155
  expect(CodeChartaService.ROOT_NAME).toEqual(expected.map.name)
158
156
  expect(CodeChartaService.ROOT_PATH).toEqual(`/${expected.map.name}`)
@@ -253,7 +251,7 @@ describe("codeChartaService", () => {
253
251
  await codeChartaService.loadFiles([{ fileName: "SecondFile", content: valid2ndFileContent, fileSize: 42 }])
254
252
 
255
253
  expect(storeService.getState().files[0].selectedAs).toEqual("None")
256
- expect(storeService.getState().files[1].selectedAs).toEqual("Single")
254
+ expect(storeService.getState().files[1].selectedAs).toEqual("Partial")
257
255
  })
258
256
 
259
257
  it("should load the default scenario after loading a valid file", async () => {
@@ -287,41 +285,50 @@ describe("codeChartaService", () => {
287
285
  })
288
286
 
289
287
  it("should show error on invalid file", async () => {
290
- const expectedError: CCValidationResult = {
291
- error: [ERROR_MESSAGES.fileIsInvalid],
292
- warning: []
293
- }
288
+ const expectedError: CCFileValidationResult[] = [
289
+ {
290
+ fileName,
291
+ errors: [ERROR_MESSAGES.fileIsInvalid],
292
+ warnings: []
293
+ }
294
+ ]
294
295
 
295
296
  await codeChartaService.loadFiles([{ fileName, content: null, fileSize: 0 }])
296
297
 
297
298
  expect(storeService.getState().files).toHaveLength(0)
298
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledWith(expectedError)
299
+ expect(dialogService.showValidationDialog).toHaveBeenCalledWith(expectedError)
299
300
  })
300
301
 
301
302
  it("should show error on a random string", async () => {
302
- const expectedError: CCValidationResult = {
303
- error: [ERROR_MESSAGES.apiVersionIsInvalid],
304
- warning: []
305
- }
303
+ const expectedError: CCFileValidationResult[] = [
304
+ {
305
+ fileName,
306
+ errors: [ERROR_MESSAGES.apiVersionIsInvalid],
307
+ warnings: []
308
+ }
309
+ ]
306
310
 
307
311
  await codeChartaService.loadFiles([{ fileName, fileSize: 42, content: "string" as unknown as ExportCCFile }])
308
312
 
309
313
  expect(storeService.getState().files).toHaveLength(0)
310
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledWith(expectedError)
314
+ expect(dialogService.showValidationDialog).toHaveBeenCalledWith(expectedError)
311
315
  })
312
316
 
313
317
  it("should show error if a file is missing a required property", async () => {
314
- const expectedError: CCValidationResult = {
315
- error: ["Required error: should have required property 'projectName'"],
316
- warning: []
317
- }
318
+ const expectedError: CCFileValidationResult[] = [
319
+ {
320
+ fileName,
321
+ errors: ["Required error: should have required property 'projectName'"],
322
+ warnings: []
323
+ }
324
+ ]
318
325
 
319
326
  const invalidFileContent = validFileContent
320
327
  delete invalidFileContent.projectName
321
328
  await codeChartaService.loadFiles([{ fileName, fileSize: 42, content: invalidFileContent }])
322
329
 
323
330
  expect(storeService.getState().files).toHaveLength(0)
324
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledWith(expectedError)
331
+ expect(dialogService.showValidationDialog).toHaveBeenCalledWith(expectedError)
325
332
  })
326
333
 
327
334
  it("should convert old blacklist type", async () => {
@@ -339,46 +346,30 @@ describe("codeChartaService", () => {
339
346
  expect(getCCFiles(storeService.getState().files)[0].settings.fileSettings.blacklist).toEqual(blacklist)
340
347
  })
341
348
 
342
- it("should break the loop after the first invalid file was validated", async () => {
343
- const expectedError: CCValidationResult = {
344
- error: ["Required error: should have required property 'projectName'"],
345
- warning: []
346
- }
347
-
348
- const invalidFileContent = validFileContent
349
- delete invalidFileContent.projectName
350
-
351
- await codeChartaService.loadFiles([
352
- { fileName, content: invalidFileContent, fileSize: 42 },
353
- { fileName, content: invalidFileContent, fileSize: 42 }
354
- ])
355
-
356
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledTimes(1)
357
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledWith(expectedError)
358
- })
359
-
360
349
  it("should not show a validation error if filenames are duplicated when their path is different", async () => {
361
350
  validFileContent.nodes[0].children[0].name = "duplicate"
362
351
  validFileContent.nodes[0].children[1].children[0].name = "duplicate"
363
352
 
364
353
  await codeChartaService.loadFiles([{ fileName, content: validFileContent, fileSize: 42 }])
365
354
 
366
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledTimes(0)
355
+ expect(dialogService.showValidationDialog).toHaveBeenCalledTimes(0)
367
356
  expect(storeService.getState().files).toHaveLength(1)
368
357
  })
369
358
 
370
359
  it("should show a validation error if two files in a folder have the same name", async () => {
371
360
  validFileContent.nodes[0].children[1].children[0].name = "duplicate"
372
361
  validFileContent.nodes[0].children[1].children[1].name = "duplicate"
373
- const expectedError: CCValidationResult = {
374
- error: [`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of File with path: /root/Parent Leaf/duplicate`],
375
- warning: []
376
- }
362
+ const expectedError: CCFileValidationResult[] = [
363
+ {
364
+ fileName,
365
+ errors: [`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of File with path: /root/Parent Leaf/duplicate`],
366
+ warnings: []
367
+ }
368
+ ]
377
369
 
378
370
  await codeChartaService.loadFiles([{ fileName, content: validFileContent, fileSize: 42 }])
379
371
 
380
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledTimes(1)
381
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledWith(expectedError)
372
+ expect(dialogService.showValidationDialog).toHaveBeenCalledWith(expectedError)
382
373
  })
383
374
 
384
375
  it("should not show a validation error if two files in a folder have the same name but different type", async () => {
@@ -389,7 +380,7 @@ describe("codeChartaService", () => {
389
380
 
390
381
  await codeChartaService.loadFiles([{ fileName, content: validFileContent, fileSize: 42 }])
391
382
 
392
- expect(dialogService.showValidationErrorDialog).toHaveBeenCalledTimes(0)
383
+ expect(dialogService.showValidationDialog).toHaveBeenCalledTimes(0)
393
384
  expect(storeService.getState().files).toHaveLength(1)
394
385
  })
395
386
 
@@ -1,7 +1,7 @@
1
- import { validate } from "./util/fileValidator"
1
+ import { CCFileValidationResult, checkErrors, checkWarnings } from "./util/fileValidator"
2
2
  import { NodeDecorator } from "./util/nodeDecorator"
3
3
  import { StoreService } from "./state/store.service"
4
- import { setFiles, setSingleByName } from "./state/store/files/files.actions"
4
+ import { setFiles, setMultipleByNames } from "./state/store/files/files.actions"
5
5
  import { DialogService } from "./ui/dialog/dialog.service"
6
6
  import { setState } from "./state/store/state.actions"
7
7
  import { ScenarioHelper } from "./util/scenarioHelper"
@@ -25,41 +25,46 @@ export class CodeChartaService {
25
25
 
26
26
  async loadFiles(nameDataPairs: NameDataPair[]) {
27
27
  this.fileStates = this.storeService.getState().files
28
- for (const nameDataPair of nameDataPairs) {
29
- try {
30
- validate(nameDataPair)
31
- this.addFile(nameDataPair)
32
- } catch (error) {
33
- if (error.error.length > 0) {
34
- this.fileStates = []
35
- this.recentFiles = []
36
- this.storeService.dispatch(setIsLoadingFile(false))
37
- await this.dialogService.showValidationErrorDialog(error)
38
- break
39
- }
40
-
41
- if (error.warning.length > 0) {
42
- this.addFile(nameDataPair)
43
- this.addRecentFile(nameDataPair.fileName)
44
- this.storeService.dispatch(setIsLoadingFile(false))
45
- await this.dialogService.showValidationWarningDialog(error)
46
- }
47
- }
48
- }
28
+ const fileValidationResults: CCFileValidationResult[] = []
29
+
30
+ this.getValidationResults(nameDataPairs, fileValidationResults)
31
+
32
+ this.storeService.dispatch(setIsLoadingFile(false))
49
33
 
50
- if (this.fileStates.length > 0) {
34
+ if (fileValidationResults.length > 0) await this.dialogService.showValidationDialog(fileValidationResults)
35
+
36
+ if (this.recentFiles.length > 0) {
51
37
  this.storeService.dispatch(setRecentFiles(this.recentFiles))
52
38
  this.storeService.dispatch(setFiles(this.fileStates))
53
39
 
54
- this.fileStates = []
55
- this.recentFiles = []
56
-
57
40
  const recentFile = this.storeService.getState().dynamicSettings.recentFiles[0]
58
41
  const rootName = this.storeService.getState().files.find(f => f.file.fileMeta.fileName === recentFile).file.map.name
59
- this.storeService.dispatch(setSingleByName(recentFile))
42
+ this.storeService.dispatch(setMultipleByNames(this.recentFiles))
60
43
 
61
44
  CodeChartaService.updateRootData(rootName)
62
45
  this.setDefaultScenario()
46
+
47
+ this.fileStates = []
48
+ this.recentFiles = []
49
+ }
50
+ }
51
+
52
+ private getValidationResults(nameDataPairs: NameDataPair[], fileValidationResults: CCFileValidationResult[]) {
53
+ for (const nameDataPair of nameDataPairs) {
54
+ const fileValidationResult: CCFileValidationResult = {
55
+ fileName: nameDataPair?.fileName,
56
+ errors: [],
57
+ warnings: []
58
+ }
59
+ fileValidationResult.errors.push(...checkErrors(nameDataPair?.content))
60
+
61
+ if (fileValidationResult.errors.length === 0) {
62
+ fileValidationResult.warnings.push(...checkWarnings(nameDataPair?.content))
63
+ this.addFile(nameDataPair)
64
+ }
65
+
66
+ if (fileValidationResult.errors.length > 0 || fileValidationResult.warnings.length > 0)
67
+ fileValidationResults.push(fileValidationResult)
63
68
  }
64
69
  }
65
70
 
@@ -129,8 +134,4 @@ export class CodeChartaService {
129
134
  CodeChartaService.ROOT_NAME = rootName
130
135
  CodeChartaService.ROOT_PATH = `/${CodeChartaService.ROOT_NAME}`
131
136
  }
132
-
133
- private addRecentFile(fileName: string) {
134
- this.recentFiles.push(fileName)
135
- }
136
137
  }
@@ -63,7 +63,7 @@ describe("codecharta", () => {
63
63
  it("should throw errors when file parameters in url are invalid and load sample data instead", async () => {
64
64
  await goto(`${CC_URL}?file=invalid234`)
65
65
  await handleErrorDialog()
66
- await checkSelectedFileName("sample1.cc.json")
66
+ await checkSelectedFileName("sample1.cc.json, sample2.cc.json")
67
67
  await checkAllFileNames(["sample1.cc.json", "sample2.cc.json"])
68
68
  })
69
69
  })
@@ -1,11 +1,13 @@
1
1
  import { combineReducers } from "redux"
2
2
 
3
3
  import { hoveredBuildingPath } from "./hoveredBuildingPath/hoveredBuildingPath.reducer"
4
+ import { rightClickedNodeData } from "./rightClickedNodeData/rightClickedNodeData.reducer"
4
5
  import { selectedBuildingId } from "./selectedBuildingId/selectedBuildingId.reducer"
5
6
 
6
7
  const appStatus = combineReducers({
7
8
  hoveredBuildingPath,
8
- selectedBuildingId
9
+ selectedBuildingId,
10
+ rightClickedNodeData
9
11
  })
10
12
 
11
13
  export default appStatus
@@ -0,0 +1,3 @@
1
+ import { CcState } from "../store"
2
+
3
+ export const appStatusSelector = (state: CcState) => state.appStatus
@@ -0,0 +1,23 @@
1
+ import { Action } from "redux"
2
+
3
+ export enum RightClickedNodeDataActions {
4
+ SET_RIGHT_CLICKED_NODE_DATA = "SET_RIGHT_CLICKED_NODE_DATA"
5
+ }
6
+
7
+ export type RightClickedNodeData = {
8
+ nodeId: number
9
+ xPositionOfRightClickEvent: number
10
+ yPositionOfRightClickEvent: number
11
+ } | null
12
+
13
+ export interface SetRightClickedNodeDataAction extends Action {
14
+ type: RightClickedNodeDataActions.SET_RIGHT_CLICKED_NODE_DATA
15
+ payload: RightClickedNodeData
16
+ }
17
+
18
+ export const defaultRightClickedNodeData: RightClickedNodeData = null
19
+
20
+ export const setRightClickedNodeData = (payload: RightClickedNodeData): SetRightClickedNodeDataAction => ({
21
+ type: RightClickedNodeDataActions.SET_RIGHT_CLICKED_NODE_DATA,
22
+ payload
23
+ })
@@ -0,0 +1,15 @@
1
+ import {
2
+ defaultRightClickedNodeData,
3
+ RightClickedNodeData,
4
+ RightClickedNodeDataActions,
5
+ SetRightClickedNodeDataAction
6
+ } from "./rightClickedNodeData.actions"
7
+
8
+ export const rightClickedNodeData = (state: RightClickedNodeData = defaultRightClickedNodeData, action: SetRightClickedNodeDataAction) => {
9
+ switch (action.type) {
10
+ case RightClickedNodeDataActions.SET_RIGHT_CLICKED_NODE_DATA:
11
+ return action.payload
12
+ default:
13
+ return state
14
+ }
15
+ }
@@ -0,0 +1,4 @@
1
+ import { createSelector } from "../../../angular-redux/createSelector"
2
+ import { appStatusSelector } from "../appStatus.selector"
3
+
4
+ export const rightClickedNodeDataSelector = createSelector([appStatusSelector], appStatus => appStatus.rightClickedNodeData)
@@ -8,6 +8,7 @@ import { defaultTreeMapSettings } from "./treeMap/treeMap.actions"
8
8
  import { defaultFiles } from "./files/files.actions"
9
9
  import { defaultHoveredBuildingPath } from "./appStatus/hoveredBuildingPath/hoveredBuildingPath.actions"
10
10
  import { defaultSelectedBuildingId } from "./appStatus/selectedBuildingId/selectedBuildingId.actions"
11
+ import { defaultRightClickedNodeData } from "./appStatus/rightClickedNodeData/rightClickedNodeData.actions"
11
12
 
12
13
  export enum StateActions {
13
14
  SET_STATE = "SET_STATE"
@@ -36,6 +37,7 @@ export const defaultState: State = {
36
37
  files: defaultFiles,
37
38
  appStatus: {
38
39
  hoveredBuildingPath: defaultHoveredBuildingPath,
39
- selectedBuildingId: defaultSelectedBuildingId
40
+ selectedBuildingId: defaultSelectedBuildingId,
41
+ rightClickedNodeData: defaultRightClickedNodeData
40
42
  }
41
43
  }
@@ -18,7 +18,7 @@ import { CodeMapPreRenderService } from "./codeMap.preRender.service"
18
18
  import { ThreeViewerService } from "./threeViewer/threeViewerService"
19
19
  import { setHoveredBuildingPath } from "../../state/store/appStatus/hoveredBuildingPath/hoveredBuildingPath.actions"
20
20
  import { hoveredBuildingPathSelector } from "../../state/store/appStatus/hoveredBuildingPath/hoveredBuildingPath.selector"
21
- import type { BUILDING_RIGHT_CLICKED_EVENT_TYPE } from "../../../../src/globals"
21
+ import { setRightClickedNodeData } from "../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions"
22
22
 
23
23
  interface Coordinates {
24
24
  x: number
@@ -355,13 +355,11 @@ export class CodeMapMouseEventService implements ViewCubeEventPropagationSubscri
355
355
  // Check if mouse moved to prevent the node context menu to show up
356
356
  // after moving the map, when the cursor ends on a building.
357
357
  if (building && !this.hasMouseMovedMoreThanThreePixels(this.mouseOnLastClick)) {
358
- document.dispatchEvent(
359
- new CustomEvent<BUILDING_RIGHT_CLICKED_EVENT_TYPE>("building-right-clicked", {
360
- detail: {
361
- building,
362
- x: this.mouse.x,
363
- y: this.mouse.y
364
- }
358
+ this.storeService.dispatch(
359
+ setRightClickedNodeData({
360
+ nodeId: building.node.id,
361
+ xPositionOfRightClickEvent: this.mouse.x,
362
+ yPositionOfRightClickEvent: this.mouse.y
365
363
  })
366
364
  )
367
365
  }
@@ -1,17 +1,17 @@
1
1
  <div class="custom-configs">
2
2
  <md-menu class="custom-configs-component">
3
- <md-button class="custom-configs-button" ng-click="$ctrl.initView(); $mdMenu.open($event);" title="Open your saved Custom Configs">
3
+ <md-button class="custom-configs-button" ng-click="$ctrl.initView(); $mdMenu.open($event);" title="Open your saved Custom Views">
4
4
  <i class="fa fa-cogs"></i>
5
5
  </md-button>
6
6
 
7
7
  <md-menu-content class="custom-configs-drop-down" width="7">
8
8
  <md-menu-item class="custom-configs-item">
9
- <md-button class="custom-configs-dialog-name" ng-disabled="true">Custom Configs</md-button>
9
+ <md-button class="custom-configs-dialog-name" ng-disabled="true">Custom Views</md-button>
10
10
 
11
11
  <md-button
12
12
  class="action-button"
13
13
  onclick="document.getElementById('input-file-id').click()"
14
- title="Upload Custom Configs (.cc.config.json file)."
14
+ title="Upload Custom View (.cc.config.json file)."
15
15
  >
16
16
  <i class="fa fa-folder-open" aria-hidden="true"></i>
17
17
  </md-button>
@@ -19,11 +19,11 @@
19
19
  ng-click="$ctrl.downloadPreloadedCustomConfigs()"
20
20
  ng-disabled="!$ctrl._viewModel.hasDownloadableConfigs"
21
21
  class="action-button"
22
- title="Download Custom Configs related to currently uploaded maps, if any."
22
+ title="Download Custom View related to currently uploaded maps, if any."
23
23
  >
24
24
  <i class="fa fa-download" aria-hidden="true"></i>
25
25
  </md-button>
26
- <md-button ng-click="$ctrl.showAddCustomConfigSettings()" class="action-button" title="Create new Custom Config">
26
+ <md-button ng-click="$ctrl.showAddCustomConfigSettings()" class="action-button" title="Create new Custom View">
27
27
  <i class="fa fa-plus" aria-hidden="true"></i>
28
28
  </md-button>
29
29
  </md-menu-item>
@@ -31,7 +31,7 @@
31
31
  <md-divider></md-divider>
32
32
 
33
33
  <md-menu-item ng-if="!$ctrl._viewModel.dropDownCustomConfigItemGroups.length" class="custom-configs-item">
34
- <md-button disabled>It is time to add your first CustomConfig.</md-button>
34
+ <md-button disabled>It is time to add your first Custom View.</md-button>
35
35
  </md-menu-item>
36
36
 
37
37
  <md-menu-item
@@ -46,7 +46,7 @@
46
46
  md-prevent-menu-close="md-prevent-menu-close"
47
47
  >
48
48
  <span class="collapse-trigger">
49
- Custom Configs in <strong>{{ customConfigItemGroup.mapSelectionMode | lowercase }}</strong> mode for
49
+ Custom View(s) in <strong>{{ customConfigItemGroup.mapSelectionMode | lowercase }}</strong> mode for
50
50
  <strong>{{ customConfigItemGroup.mapNames }}</strong>
51
51
  </span>
52
52
  <i ng-show="!collapsed" class="collapse-icon fa fa-arrow-down"></i>
@@ -88,7 +88,7 @@
88
88
  ng-click="$ctrl.toggleNonApplicableItems();"
89
89
  md-prevent-menu-close="md-prevent-menu-close"
90
90
  >
91
- {{ $ctrl.isExpanded() ? "Hide non-applicable CustomConfigs" : "Show non-applicable CustomConfigs" }}
91
+ {{ $ctrl.isExpanded() ? "Hide non-applicable Custom Views" : "Show non-applicable Custom Views" }}
92
92
  <i ng-class="$ctrl.isExpanded() ? 'fa fa-angle-up' : 'fa fa-angle-down'"></i>
93
93
  </button>
94
94
  </md-menu-content>
@@ -98,7 +98,7 @@
98
98
  <md-button
99
99
  class="custom-configs-button plus"
100
100
  ng-click="$ctrl.showAddCustomConfigSettings();"
101
- title="Quick save current view as a Custom Config"
101
+ title="Quick save current view as a Custom View"
102
102
  >
103
103
  <i class="fa fa-plus"></i>
104
104
  </md-button>
@@ -1,7 +1,7 @@
1
1
  <md-dialog class="custom-config-dialog">
2
2
  <md-toolbar>
3
3
  <div class="md-toolbar-tools">
4
- <h2>Add Custom Config</h2>
4
+ <h2>Add Custom View</h2>
5
5
  </div>
6
6
  </md-toolbar>
7
7
 
@@ -34,7 +34,7 @@
34
34
  <md-button
35
35
  ng-click="$ctrl.showPurgeConfirmDialog()"
36
36
  class="md-warn"
37
- title="Download old unused Configs as a backup file and then delete them in the browser."
37
+ title="Download old unused Custom Views as a backup file and then delete them in the browser."
38
38
  >Download & Purge ...</md-button
39
39
  >
40
40
  </span>
@@ -0,0 +1,15 @@
1
+ img[alt$="xs"] {
2
+ height: 32px;
3
+ }
4
+ img[alt$="s"] {
5
+ height: 64px;
6
+ }
7
+ img[alt$="m"] {
8
+ height: 256px;
9
+ }
10
+ img[alt$="l"] {
11
+ height: 350px;
12
+ }
13
+ img[alt$="xl"] {
14
+ height: 512px;
15
+ }
@@ -33,11 +33,11 @@ describe("DialogChangelogController", () => {
33
33
  expect(dialogChangelogController["_viewModel"].changes).not.toBeNull()
34
34
  expect(dialogChangelogController["_viewModel"].changes[added]).toBeUndefined()
35
35
  expect(dialogChangelogController["_viewModel"].changes[fixed]).toBe(
36
- '<li>3 (<a href="">#3</a>)</li>\n' + '<li>4 (<a href="">#4</a>)</li>\n' + '<li>5 (<a href="">#5</a>)</li>'
36
+ '<li>3 (<a href="">#3</a>)</li><br>\n' + '<li>4 (<a href="">#4</a>)</li><br>\n' + '<li>5 (<a href="">#5</a>)</li><br>'
37
37
  )
38
38
  expect(dialogChangelogController["_viewModel"].changes[removed]).toBeUndefined()
39
39
  expect(dialogChangelogController["_viewModel"].changes[changed]).toBeUndefined()
40
- expect(dialogChangelogController["_viewModel"].changes[chore]).toBe('<li>6 (<a href="">#6</a>)</li>')
40
+ expect(dialogChangelogController["_viewModel"].changes[chore]).toBe('<li>6 (<a href="">#6</a>)</li><br>')
41
41
  })
42
42
 
43
43
  it("should extract the changes from changelog for 2 versions", () => {
@@ -47,24 +47,24 @@ describe("DialogChangelogController", () => {
47
47
 
48
48
  expect(dialogChangelogController["_viewModel"].changes).not.toBeNull()
49
49
  expect(dialogChangelogController["_viewModel"].changes[added]).toBe(
50
- '<li>7 (<a href="">#7</a>)</li>\n' + '<li>8 (<a href="">#8</a>)</li>'
50
+ '<li>7 (<a href="">#7</a>)</li><br>\n' + '<li>8 (<a href="">#8</a>)</li><br>'
51
51
  )
52
52
  expect(dialogChangelogController["_viewModel"].changes[fixed]).toBe(
53
- '<li>3 (<a href="">#3</a>)</li>\n' + '<li>4 (<a href="">#4</a>)</li>\n' + '<li>5 (<a href="">#5</a>)</li>'
53
+ '<li>3 (<a href="">#3</a>)</li><br>\n' + '<li>4 (<a href="">#4</a>)</li><br>\n' + '<li>5 (<a href="">#5</a>)</li><br>'
54
54
  )
55
- expect(dialogChangelogController["_viewModel"].changes[chore]).toBe('<li>6 (<a href="">#6</a>)</li>')
55
+ expect(dialogChangelogController["_viewModel"].changes[chore]).toBe('<li>6 (<a href="">#6</a>)</li><br>')
56
56
  // Expect nested list to be correctly parsed
57
57
  expect(dialogChangelogController["_viewModel"].changes[changed]).toBe(
58
- "<li>\n" +
59
- '<p>9 (<a href="">#9</a>)</p>\n' +
60
- "</li>\n" +
61
- "<li>\n" +
62
- '<p>10 (<a href="">#10</a>)</p>\n' +
63
- "<ul>\n" +
64
- "<li>10.1</li>\n" +
65
- "<li>10.2</li>\n" +
66
- "</ul>\n" +
67
- "</li>"
58
+ "<li><br>\n" +
59
+ '<p>9 (<a href="">#9</a>)</p><br>\n' +
60
+ "</li><br>\n" +
61
+ "<li><br>\n" +
62
+ '<p>10 (<a href="">#10</a>)</p><br>\n' +
63
+ "<ul><br>\n" +
64
+ "<li>10.1</li><br>\n" +
65
+ "<li>10.2</li><br>\n" +
66
+ "</ul><br>\n" +
67
+ "</li><br>"
68
68
  )
69
69
  expect(dialogChangelogController["_viewModel"].changes[removed]).toBeUndefined()
70
70
  })