codecharta-visualization 1.86.0 → 1.87.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.
- package/Dockerfile +1 -1
- package/app/app.module.ts +6 -2
- package/app/codeCharta/codeCharta.model.ts +1 -1
- package/app/codeCharta/state/store/dynamicSettings/dynamicSettings.splitter.ts +2 -2
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/currentFocused.selector.ts +8 -0
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions.ts +27 -7
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.spec.ts +27 -11
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.ts +11 -5
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector.ts +4 -0
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.spec.ts +2 -2
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.ts +1 -1
- package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.actions.ts +9 -10
- package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.spec.ts +37 -7
- package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.ts +7 -3
- package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.spec.ts +39 -0
- package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.ts +19 -0
- package/app/codeCharta/state/store/state.splitter.spec.ts +4 -4
- package/app/codeCharta/state/store.service.spec.ts +3 -3
- package/app/codeCharta/state/store.service.ts +5 -0
- package/app/codeCharta/ui/artificialIntelligence/__snapshots__/artificialIntelligence.component.spec.ts.snap +13 -16
- package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.html +4 -4
- package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.scss +0 -4
- package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.spec.ts +82 -52
- package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.ts +41 -101
- package/app/codeCharta/ui/codeMap/codeMap.actions.service.ts +1 -40
- package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +10 -16
- package/app/codeCharta/ui/colorPicker/colorPicker.component.html +16 -7
- package/app/codeCharta/ui/colorPicker/colorPicker.component.spec.ts +55 -16
- package/app/codeCharta/ui/colorPicker/colorPicker.component.ts +32 -1
- package/app/codeCharta/ui/colorPicker/colorPicker.module.ts +3 -1
- package/app/codeCharta/ui/customConfigs/customConfigs.component.html +21 -3
- package/app/codeCharta/ui/customConfigs/customConfigs.component.scss +1 -0
- package/app/codeCharta/ui/customConfigs/customConfigs.component.spec.ts +123 -2
- package/app/codeCharta/ui/customConfigs/customConfigs.component.ts +56 -2
- package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.html +21 -13
- package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.spec.ts +11 -24
- package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.ts +1 -40
- package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.module.ts +1 -2
- package/app/codeCharta/ui/legendPanel/legendMarkedPackages/legendMarkedPackages.component.ts +2 -2
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.html +24 -0
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.spec.ts +55 -0
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.ts +38 -0
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module.ts +13 -0
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.spec.ts +31 -0
- package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.ts +25 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +8 -4
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +1 -21
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module.ts +1 -2
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -12
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +3 -1
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +28 -125
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +29 -55
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -0
- package/app/codeCharta/ui/ui.ts +0 -2
- package/app/codeCharta/util/algorithm/streetLayout/strip/strip.ts +2 -2
- package/app/codeCharta/util/algorithm/streetLayout/treeMap.ts +1 -1
- package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.spec.ts +1 -1
- package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.spec.ts +2 -2
- package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.ts +1 -1
- package/app/codeCharta/util/customConfigBuilder.ts +1 -1
- package/app/codeCharta/util/dataMocks.ts +2 -2
- package/app/codeCharta/util/fileExtensionCalculator.ts +1 -1
- package/dist/webpack/bundle.js +963 -934
- package/dist/webpack/bundle.js.map +1 -1
- package/package.json +6 -5
- package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.splitter.ts +0 -8
- package/app/codeCharta/ui/codeMap/codeMap.actions.service.spec.ts +0 -147
- package/app/codeCharta/ui/unfocusButton/unfocusButton.component.html +0 -15
- package/app/codeCharta/ui/unfocusButton/unfocusButton.component.scss +0 -5
- package/app/codeCharta/ui/unfocusButton/unfocusButton.component.spec.ts +0 -106
- package/app/codeCharta/ui/unfocusButton/unfocusButton.component.ts +0 -62
- package/app/codeCharta/ui/unfocusButton/unfocusButton.module.ts +0 -7
|
@@ -1,32 +1,71 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Component } from "@angular/core"
|
|
2
2
|
import { TestBed } from "@angular/core/testing"
|
|
3
|
-
import { render, screen } from "@testing-library/angular"
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/angular"
|
|
4
4
|
|
|
5
|
-
import { ColorPickerComponent } from "./colorPicker.component"
|
|
6
5
|
import { ColorPickerModule } from "./colorPicker.module"
|
|
7
6
|
|
|
8
7
|
describe("colorPicker", () => {
|
|
9
|
-
|
|
8
|
+
@Component({
|
|
9
|
+
selector: "test-color-picker",
|
|
10
|
+
template: `
|
|
11
|
+
<cc-color-picker
|
|
12
|
+
[hexColor]="hexColor"
|
|
13
|
+
(onColorChange)="hexColor = $event"
|
|
14
|
+
[triggerTemplate]="colorPickerTriggerTemplate"
|
|
15
|
+
></cc-color-picker>
|
|
16
|
+
<ng-template #colorPickerTriggerTemplate let-isOpen="isOpen" let-isHovered="isHovered">
|
|
17
|
+
<div>isOpen: {{ isOpen }}</div>
|
|
18
|
+
<div>isHovered: {{ isHovered }}</div>
|
|
19
|
+
<div>color: {{ hexColor }}</div>
|
|
20
|
+
</ng-template>
|
|
21
|
+
`
|
|
22
|
+
})
|
|
23
|
+
class TestColorPicker {
|
|
24
|
+
hexColor = "#ffffff"
|
|
25
|
+
}
|
|
10
26
|
|
|
11
27
|
beforeEach(() => {
|
|
12
|
-
handleColorChange.mockReset()
|
|
13
28
|
TestBed.configureTestingModule({
|
|
14
29
|
imports: [ColorPickerModule]
|
|
15
30
|
})
|
|
16
31
|
})
|
|
17
32
|
|
|
18
|
-
it("should let a user change a color", async () => {
|
|
19
|
-
await render(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
it("should let a user change a color within a menu", async () => {
|
|
34
|
+
const { container } = await render(TestColorPicker)
|
|
35
|
+
|
|
36
|
+
expectColorPickerInDom(false)
|
|
37
|
+
expect(screen.queryByText("isOpen: false")).toBeTruthy()
|
|
38
|
+
expect(screen.queryByText("color: #ffffff")).toBeTruthy()
|
|
39
|
+
|
|
40
|
+
fireEvent.click(container.querySelector("cc-color-picker"))
|
|
41
|
+
expectColorPickerInDom(true)
|
|
42
|
+
expect(screen.queryByText("isOpen: true")).toBeTruthy()
|
|
26
43
|
|
|
27
|
-
const colorPicker = screen.getByRole("colorpicker")
|
|
28
44
|
// @ts-ignore
|
|
29
|
-
ng.probe(
|
|
30
|
-
expect(
|
|
45
|
+
ng.probe(screen.queryByRole("colorpicker")).componentInstance.onChangeComplete.emit({ $event: {}, color: { hex: "#000000" } })
|
|
46
|
+
expect(await screen.findByText("color: #000000")).toBeTruthy()
|
|
47
|
+
|
|
48
|
+
fireEvent.click(document)
|
|
49
|
+
await waitFor(() => expectColorPickerInDom(false))
|
|
50
|
+
expect(screen.queryByText("isOpen: false")).toBeTruthy()
|
|
31
51
|
})
|
|
52
|
+
|
|
53
|
+
it("should pass `isHovered` into template", async () => {
|
|
54
|
+
const { container } = await render(TestColorPicker)
|
|
55
|
+
const colorPicker = container.querySelector("cc-color-picker")
|
|
56
|
+
|
|
57
|
+
expect(screen.queryByText("isHovered: false")).toBeTruthy()
|
|
58
|
+
|
|
59
|
+
fireEvent.mouseEnter(colorPicker)
|
|
60
|
+
expect(screen.queryByText("isHovered: true")).toBeTruthy()
|
|
61
|
+
|
|
62
|
+
fireEvent.mouseLeave(colorPicker)
|
|
63
|
+
expect(screen.queryByText("isHovered: false")).toBeTruthy()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
function expectColorPickerInDom(isOpen: boolean) {
|
|
67
|
+
const colorPickerElement = screen.queryByRole("colorpicker")
|
|
68
|
+
if (isOpen) expect(colorPickerElement).not.toBe(null)
|
|
69
|
+
else expect(colorPickerElement).toBe(null)
|
|
70
|
+
}
|
|
32
71
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output } from "@angular/core"
|
|
1
|
+
import { Component, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from "@angular/core"
|
|
2
|
+
import { MatMenuTrigger, MenuPositionX } from "@angular/material/menu"
|
|
2
3
|
|
|
3
4
|
@Component({
|
|
4
5
|
selector: "cc-color-picker",
|
|
@@ -6,10 +7,40 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"
|
|
|
6
7
|
})
|
|
7
8
|
export class ColorPickerComponent {
|
|
8
9
|
@Input() hexColor: string
|
|
10
|
+
@Input() openXPosition: MenuPositionX = "after"
|
|
11
|
+
@Input() triggerTemplate: TemplateRef<unknown>
|
|
9
12
|
|
|
10
13
|
@Output() onColorChange = new EventEmitter<string>()
|
|
11
14
|
|
|
15
|
+
@ViewChild("colorPickerMenuTrigger") colorPickerMenuTrigger: MatMenuTrigger
|
|
16
|
+
|
|
17
|
+
isHovered = false
|
|
18
|
+
|
|
19
|
+
private isClickInside = false
|
|
20
|
+
|
|
12
21
|
handleChangeComplete(hexColor: string) {
|
|
13
22
|
this.onColorChange.emit(hexColor)
|
|
14
23
|
}
|
|
24
|
+
|
|
25
|
+
@HostListener("mouseenter") onMouseEnter() {
|
|
26
|
+
this.isHovered = true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@HostListener("mouseleave") onMouseLeave() {
|
|
30
|
+
this.isHovered = false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@HostListener("click") onClick() {
|
|
34
|
+
this.isClickInside = true
|
|
35
|
+
this.colorPickerMenuTrigger.openMenu()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@HostListener("document:click")
|
|
39
|
+
handleDocumentClick() {
|
|
40
|
+
if (!this.isClickInside && this.colorPickerMenuTrigger.menuOpen) {
|
|
41
|
+
this.colorPickerMenuTrigger.closeMenu()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.isClickInside = false
|
|
45
|
+
}
|
|
15
46
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { CommonModule } from "@angular/common"
|
|
2
2
|
import { NgModule } from "@angular/core"
|
|
3
3
|
import { ColorChromeModule } from "ngx-color/chrome"
|
|
4
|
+
|
|
5
|
+
import { MaterialModule } from "../../../material/material.module"
|
|
4
6
|
import { ColorPickerComponent } from "./colorPicker.component"
|
|
5
7
|
|
|
6
8
|
@NgModule({
|
|
7
|
-
imports: [CommonModule, ColorChromeModule],
|
|
9
|
+
imports: [CommonModule, ColorChromeModule, MaterialModule],
|
|
8
10
|
declarations: [ColorPickerComponent],
|
|
9
11
|
exports: [ColorPickerComponent]
|
|
10
12
|
})
|
|
@@ -34,8 +34,17 @@
|
|
|
34
34
|
<md-button disabled>It is time to add your first CustomConfig.</md-button>
|
|
35
35
|
</md-menu-item>
|
|
36
36
|
|
|
37
|
-
<md-menu-item
|
|
38
|
-
|
|
37
|
+
<md-menu-item
|
|
38
|
+
class="custom-configs-item"
|
|
39
|
+
ng-repeat="customConfigItemGroup in $ctrl._viewModel.dropDownCustomConfigItemGroups |
|
|
40
|
+
limitTo: $ctrl._viewModel.visibleEntries"
|
|
41
|
+
>
|
|
42
|
+
<md-button
|
|
43
|
+
class="button-hovering"
|
|
44
|
+
ng-click="collapsed=!collapsed"
|
|
45
|
+
ng-style="!customConfigItemGroup.hasApplicableItems && { color: 'rgba(0,0,0,0.3)' }"
|
|
46
|
+
md-prevent-menu-close="md-prevent-menu-close"
|
|
47
|
+
>
|
|
39
48
|
<span class="collapse-trigger">
|
|
40
49
|
Custom Configs in <strong>{{ customConfigItemGroup.mapSelectionMode | lowercase }}</strong> mode for
|
|
41
50
|
<strong>{{ customConfigItemGroup.mapNames }}</strong>
|
|
@@ -64,7 +73,8 @@
|
|
|
64
73
|
</md-button>
|
|
65
74
|
|
|
66
75
|
<md-button
|
|
67
|
-
ng-click="$ctrl.removeCustomConfig(customConfig.id)"
|
|
76
|
+
ng-click="$ctrl.removeCustomConfig(customConfig.id, $index, $parent.$index)"
|
|
77
|
+
md-prevent-menu-close="md-prevent-menu-close"
|
|
68
78
|
class="action-button remove button-hovering"
|
|
69
79
|
title="Remove Custom Config"
|
|
70
80
|
>
|
|
@@ -73,6 +83,14 @@
|
|
|
73
83
|
</div>
|
|
74
84
|
</div>
|
|
75
85
|
</md-menu-item>
|
|
86
|
+
<button
|
|
87
|
+
ng-show="$ctrl._viewModel.showNonApplicableButton"
|
|
88
|
+
ng-click="$ctrl.toggleNonApplicableItems();"
|
|
89
|
+
md-prevent-menu-close="md-prevent-menu-close"
|
|
90
|
+
>
|
|
91
|
+
{{ $ctrl.isExpanded() ? "Hide non-applicable CustomConfigs" : "Show non-applicable CustomConfigs" }}
|
|
92
|
+
<i ng-class="$ctrl.isExpanded() ? 'fa fa-angle-up' : 'fa fa-angle-down'"></i>
|
|
93
|
+
</button>
|
|
76
94
|
</md-menu-content>
|
|
77
95
|
</md-menu>
|
|
78
96
|
|
|
@@ -13,6 +13,7 @@ import { CustomConfigHelper } from "../../util/customConfigHelper"
|
|
|
13
13
|
import { setState } from "../../state/store/state.actions"
|
|
14
14
|
import { CustomConfig, ExportCustomConfig } from "../../model/customConfig/customConfig.api.model"
|
|
15
15
|
import { ThreeCameraService } from "../codeMap/threeViewer/threeCameraService"
|
|
16
|
+
import { klona } from "klona"
|
|
16
17
|
|
|
17
18
|
describe("CustomConfigsController", () => {
|
|
18
19
|
let customConfigsController: CustomConfigsController
|
|
@@ -133,12 +134,60 @@ describe("CustomConfigsController", () => {
|
|
|
133
134
|
|
|
134
135
|
describe("removeCustomConfig", () => {
|
|
135
136
|
it("should call deleteCustomConfig", () => {
|
|
137
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(klona(CUSTOM_CONFIG_ITEM_GROUPS))
|
|
138
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
139
|
+
customConfigsController.initView()
|
|
140
|
+
CustomConfigHelper.deleteCustomConfig = jest.fn()
|
|
141
|
+
const configIdToRemove = "SINGLEfileASampleMap View #1"
|
|
142
|
+
|
|
143
|
+
customConfigsController.removeCustomConfig(configIdToRemove, 0, 0)
|
|
144
|
+
|
|
145
|
+
expect(CustomConfigHelper.deleteCustomConfig).toHaveBeenCalledWith(configIdToRemove)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it("should delete element from customConfigItemGroup in dropDownCustomConfigItemGroups when removing a custom config", () => {
|
|
149
|
+
const testDropDownConfigItemGroup = [klona(CUSTOM_CONFIG_ITEM_GROUPS.get("fileAfileBSINGLE"))]
|
|
150
|
+
const configIdToRemove = "SINGLEfileASampleMap View #1"
|
|
151
|
+
|
|
152
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(testDropDownConfigItemGroup)
|
|
153
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
154
|
+
customConfigsController.initView()
|
|
155
|
+
CustomConfigHelper.deleteCustomConfig = jest.fn()
|
|
156
|
+
|
|
157
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(1)
|
|
158
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups[0].customConfigItems).toHaveLength(2)
|
|
159
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
160
|
+
|
|
161
|
+
customConfigsController.removeCustomConfig(configIdToRemove, 0, 0)
|
|
162
|
+
|
|
163
|
+
expect(CustomConfigHelper.deleteCustomConfig).toHaveBeenCalledWith(configIdToRemove)
|
|
164
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(1)
|
|
165
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups[0].customConfigItems).toHaveLength(1)
|
|
166
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it("should delete element from dropDownCustomConfigItemGroups when removing a custom config", () => {
|
|
170
|
+
const testDropDownConfigItemGroup = [klona(CUSTOM_CONFIG_ITEM_GROUPS.get("fileAfileBMultiple"))]
|
|
171
|
+
testDropDownConfigItemGroup[0].customConfigItems.pop()
|
|
172
|
+
const configIdToRemove = "MULTIPLEfileESampleMap View #1"
|
|
173
|
+
|
|
174
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue([testDropDownConfigItemGroup])
|
|
175
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(testDropDownConfigItemGroup)
|
|
176
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
177
|
+
customConfigsController.initView()
|
|
136
178
|
CustomConfigHelper.deleteCustomConfig = jest.fn()
|
|
137
179
|
|
|
138
|
-
|
|
139
|
-
customConfigsController.
|
|
180
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(1)
|
|
181
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups[0].customConfigItems).toHaveLength(1)
|
|
182
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
183
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeFalsy()
|
|
184
|
+
|
|
185
|
+
customConfigsController.removeCustomConfig(configIdToRemove, 0, 0)
|
|
140
186
|
|
|
141
187
|
expect(CustomConfigHelper.deleteCustomConfig).toHaveBeenCalledWith(configIdToRemove)
|
|
188
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(0)
|
|
189
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(0)
|
|
190
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeFalsy()
|
|
142
191
|
})
|
|
143
192
|
})
|
|
144
193
|
|
|
@@ -214,4 +263,76 @@ describe("CustomConfigsController", () => {
|
|
|
214
263
|
expect(customConfigsController["_viewModel"].hasDownloadableConfigs).toBe(true)
|
|
215
264
|
})
|
|
216
265
|
})
|
|
266
|
+
|
|
267
|
+
describe("collapse and expand non applicable custom configs", () => {
|
|
268
|
+
it("should not show configs that are not applicable by default", () => {
|
|
269
|
+
const testConfigItemGroups = [[...CUSTOM_CONFIG_ITEM_GROUPS][0], [...CUSTOM_CONFIG_ITEM_GROUPS][2]]
|
|
270
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(testConfigItemGroups)
|
|
271
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
272
|
+
|
|
273
|
+
customConfigsController.initView()
|
|
274
|
+
|
|
275
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(2)
|
|
276
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(0)
|
|
277
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it("should show all configs that are applicable by default", () => {
|
|
281
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(CUSTOM_CONFIG_ITEM_GROUPS)
|
|
282
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
283
|
+
|
|
284
|
+
customConfigsController.initView()
|
|
285
|
+
|
|
286
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(3)
|
|
287
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
288
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it("should hide expand button when only applicable custom configs are loaded", () => {
|
|
292
|
+
const testConfigItemGroup = [CUSTOM_CONFIG_ITEM_GROUPS.get("fileAfileBMultiple")]
|
|
293
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(testConfigItemGroup)
|
|
294
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
295
|
+
|
|
296
|
+
customConfigsController.initView()
|
|
297
|
+
|
|
298
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(1)
|
|
299
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
300
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeFalsy()
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it("should show all custom configs when 'show non-applicable CustomConfigs' button is clicked", () => {
|
|
304
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(CUSTOM_CONFIG_ITEM_GROUPS)
|
|
305
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
306
|
+
|
|
307
|
+
customConfigsController.initView()
|
|
308
|
+
|
|
309
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(3)
|
|
310
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
311
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
312
|
+
|
|
313
|
+
customConfigsController.toggleNonApplicableItems()
|
|
314
|
+
|
|
315
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(3)
|
|
316
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(3)
|
|
317
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it("should hide all configs that are not applicable when 'show non-applicable CustomConfigs' button is clicked", () => {
|
|
321
|
+
CustomConfigHelper.getCustomConfigItemGroups = jest.fn().mockReturnValue(CUSTOM_CONFIG_ITEM_GROUPS)
|
|
322
|
+
CustomConfigHelper.getCustomConfigs = jest.fn().mockReturnValue(new Map())
|
|
323
|
+
|
|
324
|
+
customConfigsController.initView()
|
|
325
|
+
|
|
326
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(3)
|
|
327
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
328
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
329
|
+
|
|
330
|
+
customConfigsController.toggleNonApplicableItems()
|
|
331
|
+
customConfigsController.toggleNonApplicableItems()
|
|
332
|
+
|
|
333
|
+
expect(customConfigsController["_viewModel"].dropDownCustomConfigItemGroups).toHaveLength(3)
|
|
334
|
+
expect(customConfigsController["_viewModel"].visibleEntries).toBe(1)
|
|
335
|
+
expect(customConfigsController["_viewModel"].showNonApplicableButton).toBeTruthy()
|
|
336
|
+
})
|
|
337
|
+
})
|
|
217
338
|
})
|
|
@@ -29,13 +29,19 @@ export class CustomConfigsController implements FilesSelectionSubscriber {
|
|
|
29
29
|
private _viewModel: {
|
|
30
30
|
dropDownCustomConfigItemGroups: CustomConfigItemGroup[]
|
|
31
31
|
hasDownloadableConfigs: boolean
|
|
32
|
+
showNonApplicableButton: boolean
|
|
33
|
+
visibleEntries: number
|
|
32
34
|
} = {
|
|
33
35
|
dropDownCustomConfigItemGroups: [],
|
|
34
|
-
hasDownloadableConfigs: false
|
|
36
|
+
hasDownloadableConfigs: false,
|
|
37
|
+
showNonApplicableButton: false,
|
|
38
|
+
visibleEntries: 0
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
private customConfigFileStateConnector: CustomConfigFileStateConnector
|
|
38
42
|
private downloadableConfigs: Map<string, ExportCustomConfig> = new Map()
|
|
43
|
+
private previousEntries
|
|
44
|
+
private applicableEntries = 0
|
|
39
45
|
|
|
40
46
|
constructor(
|
|
41
47
|
private $rootScope: IRootScopeService,
|
|
@@ -57,6 +63,7 @@ export class CustomConfigsController implements FilesSelectionSubscriber {
|
|
|
57
63
|
initView() {
|
|
58
64
|
this.loadCustomConfigs()
|
|
59
65
|
this.preloadDownloadableConfigs()
|
|
66
|
+
this.initVisibleEntries()
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
loadCustomConfigs() {
|
|
@@ -74,8 +81,41 @@ export class CustomConfigsController implements FilesSelectionSubscriber {
|
|
|
74
81
|
CustomConfigHelper.applyCustomConfig(configId, this.storeService, this.threeCameraService, this.threeOrbitControlsService)
|
|
75
82
|
}
|
|
76
83
|
|
|
77
|
-
removeCustomConfig(configId) {
|
|
84
|
+
removeCustomConfig(configId, customConfigItemIndex, dropDownCustomConfigItemGroupIndex) {
|
|
85
|
+
const { dropDownCustomConfigItemGroups } = this._viewModel
|
|
86
|
+
|
|
78
87
|
CustomConfigHelper.deleteCustomConfig(configId)
|
|
88
|
+
dropDownCustomConfigItemGroups[dropDownCustomConfigItemGroupIndex].customConfigItems.splice(customConfigItemIndex, 1)
|
|
89
|
+
|
|
90
|
+
if (dropDownCustomConfigItemGroups[dropDownCustomConfigItemGroupIndex].customConfigItems.length === 0) {
|
|
91
|
+
if (dropDownCustomConfigItemGroups[dropDownCustomConfigItemGroupIndex].hasApplicableItems) {
|
|
92
|
+
this.applicableEntries--
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
dropDownCustomConfigItemGroups.splice(dropDownCustomConfigItemGroupIndex, 1)
|
|
96
|
+
this._viewModel.visibleEntries--
|
|
97
|
+
this.previousEntries--
|
|
98
|
+
this.updateButtonVisibility()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private initVisibleEntries() {
|
|
103
|
+
this.applicableEntries = 0
|
|
104
|
+
while (this._viewModel.dropDownCustomConfigItemGroups[this.applicableEntries]?.hasApplicableItems) {
|
|
105
|
+
this.applicableEntries++
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this._viewModel.visibleEntries = this.applicableEntries
|
|
109
|
+
this.updateButtonVisibility()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
toggleNonApplicableItems() {
|
|
113
|
+
if (!this.isExpanded()) {
|
|
114
|
+
this.previousEntries = this._viewModel.visibleEntries
|
|
115
|
+
this._viewModel.visibleEntries = this._viewModel.dropDownCustomConfigItemGroups.length
|
|
116
|
+
} else {
|
|
117
|
+
this._viewModel.visibleEntries = this.previousEntries
|
|
118
|
+
}
|
|
79
119
|
}
|
|
80
120
|
|
|
81
121
|
downloadPreloadedCustomConfigs() {
|
|
@@ -109,6 +149,20 @@ export class CustomConfigsController implements FilesSelectionSubscriber {
|
|
|
109
149
|
}
|
|
110
150
|
return false
|
|
111
151
|
}
|
|
152
|
+
|
|
153
|
+
private isExpanded(): boolean {
|
|
154
|
+
return this._viewModel.visibleEntries === this._viewModel.dropDownCustomConfigItemGroups.length
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private updateButtonVisibility() {
|
|
158
|
+
if (this._viewModel.dropDownCustomConfigItemGroups.length === 0) {
|
|
159
|
+
this._viewModel.showNonApplicableButton = false
|
|
160
|
+
} else if (this.applicableEntries < this._viewModel.dropDownCustomConfigItemGroups.length) {
|
|
161
|
+
this._viewModel.showNonApplicableButton = true
|
|
162
|
+
} else {
|
|
163
|
+
this._viewModel.showNonApplicableButton = false
|
|
164
|
+
}
|
|
165
|
+
}
|
|
112
166
|
}
|
|
113
167
|
|
|
114
168
|
export const customConfigsComponent = {
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
<
|
|
1
|
+
<cc-color-picker
|
|
2
|
+
[hexColor]="hexColor"
|
|
3
|
+
(onColorChange)="handleColorChange($event)"
|
|
4
|
+
[openXPosition]="'before'"
|
|
5
|
+
[triggerTemplate]="colorPickerTriggerTemplate"
|
|
6
|
+
></cc-color-picker>
|
|
2
7
|
|
|
3
|
-
<
|
|
4
|
-
<div class="cc-color-
|
|
5
|
-
<
|
|
6
|
-
|
|
8
|
+
<ng-template #colorPickerTriggerTemplate let-isOpen="isOpen" let-isHovered="isHovered">
|
|
9
|
+
<div class="cc-labelled-color-picker-container">
|
|
10
|
+
<div class="cc-color-swatch-container">
|
|
11
|
+
<span class="cc-color-swatch" [style.background-color]="hexColor"></span>
|
|
12
|
+
<span
|
|
13
|
+
class="cc-color-brush fa fa-paint-brush"
|
|
14
|
+
[style.color]="hexColor | readableColorForBackground"
|
|
15
|
+
[style.opacity]="isHovered || isOpen ? '1' : '0'"
|
|
16
|
+
>
|
|
17
|
+
</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div>
|
|
20
|
+
<span *ngFor="let label of labels"> {{ label }} <br *ngIf="!last" /></span>
|
|
21
|
+
</div>
|
|
7
22
|
</div>
|
|
8
|
-
|
|
9
|
-
<span *ngFor="let label of labels"> {{ label }} <br *ngIf="!last" /></span>
|
|
10
|
-
</div>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
<mat-menu #menu="matMenu" xPosition="before" [hasBackdrop]="false" class="cc-color-picker-menu">
|
|
14
|
-
<cc-color-picker [hexColor]="hexColor" (onColorChange)="handleColorChange($event)"></cc-color-picker>
|
|
15
|
-
</mat-menu>
|
|
23
|
+
</ng-template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from "@angular/core"
|
|
2
2
|
import { TestBed } from "@angular/core/testing"
|
|
3
|
-
import { render, fireEvent, screen, waitForElementToBeRemoved
|
|
3
|
+
import { render, fireEvent, screen, waitForElementToBeRemoved } from "@testing-library/angular"
|
|
4
4
|
|
|
5
5
|
import { LabelledColorPickerComponent } from "./labelledColorPicker.component"
|
|
6
6
|
import { LabelledColorPickerModule } from "./labelledColorPicker.module"
|
|
@@ -15,7 +15,7 @@ describe("labelledColorPicker", () => {
|
|
|
15
15
|
})
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
it("should
|
|
18
|
+
it("should display label and handle brush visibility", async () => {
|
|
19
19
|
const { container } = await render(LabelledColorPickerComponent, {
|
|
20
20
|
excludeComponentDeclaration: true,
|
|
21
21
|
componentProperties: {
|
|
@@ -24,41 +24,28 @@ describe("labelledColorPicker", () => {
|
|
|
24
24
|
onColorChange: { emit: handleColorChange } as unknown as EventEmitter<string>
|
|
25
25
|
}
|
|
26
26
|
})
|
|
27
|
+
const colorPickerTrigger = container.querySelector("cc-color-picker")
|
|
27
28
|
|
|
28
29
|
expect(container.textContent).toMatch("pretty color")
|
|
29
30
|
|
|
30
|
-
fireEvent.
|
|
31
|
-
|
|
31
|
+
fireEvent.mouseEnter(colorPickerTrigger)
|
|
32
|
+
expectBrushVisibility(container, true)
|
|
33
|
+
|
|
34
|
+
fireEvent.click(colorPickerTrigger)
|
|
35
|
+
const colorPicker = screen.getByRole("colorpicker")
|
|
32
36
|
expectBrushVisibility(container, true)
|
|
33
37
|
|
|
34
38
|
// @ts-ignore
|
|
35
39
|
ng.probe(colorPicker).componentInstance.onChangeComplete.emit({ $event: {}, color: { hex: "#ffffff" } })
|
|
36
40
|
expect(handleColorChange).toHaveBeenCalledWith("#ffffff")
|
|
37
41
|
|
|
38
|
-
fireEvent.
|
|
42
|
+
fireEvent.mouseLeave(colorPickerTrigger)
|
|
43
|
+
expectBrushVisibility(container, true) // still true as color picker is still open
|
|
39
44
|
|
|
45
|
+
fireEvent.click(document)
|
|
40
46
|
await waitForElementToBeRemoved(screen.getByRole("colorpicker"))
|
|
41
47
|
expectBrushVisibility(container, false)
|
|
42
48
|
})
|
|
43
|
-
|
|
44
|
-
it("should add/remove brush on mouseenter/mouseleave", async () => {
|
|
45
|
-
const { container } = await render(LabelledColorPickerComponent, {
|
|
46
|
-
excludeComponentDeclaration: true,
|
|
47
|
-
componentProperties: {
|
|
48
|
-
hexColor: "#000000",
|
|
49
|
-
labels: ["pretty color"],
|
|
50
|
-
onColorChange: { emit: handleColorChange } as unknown as EventEmitter<string>
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
expectBrushVisibility(container, false)
|
|
55
|
-
|
|
56
|
-
fireEvent.mouseEnter(container)
|
|
57
|
-
expectBrushVisibility(container, true)
|
|
58
|
-
|
|
59
|
-
fireEvent.mouseLeave(container)
|
|
60
|
-
expectBrushVisibility(container, false)
|
|
61
|
-
})
|
|
62
49
|
})
|
|
63
50
|
|
|
64
51
|
function expectBrushVisibility(container: Element, isVisible: boolean) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import "./labelledColorPicker.component.scss"
|
|
2
|
-
import { Component,
|
|
3
|
-
import { MatMenuTrigger } from "@angular/material/menu"
|
|
2
|
+
import { Component, EventEmitter, Input, Output } from "@angular/core"
|
|
4
3
|
|
|
5
4
|
@Component({
|
|
6
5
|
selector: "cc-labelled-color-picker",
|
|
@@ -12,44 +11,6 @@ export class LabelledColorPickerComponent {
|
|
|
12
11
|
|
|
13
12
|
@Output() onColorChange = new EventEmitter<string>()
|
|
14
13
|
|
|
15
|
-
@ViewChild("colorPickerMenuTrigger") colorPickerMenuTrigger: MatMenuTrigger
|
|
16
|
-
@ViewChild("brush") brush: ElementRef
|
|
17
|
-
|
|
18
|
-
private isClickInside = false
|
|
19
|
-
|
|
20
|
-
@HostListener("mouseenter") onMouseEnter() {
|
|
21
|
-
this.brush.nativeElement.style.opacity = "1"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@HostListener("mouseleave") onMouseLeave() {
|
|
25
|
-
if (!this.colorPickerMenuTrigger.menuOpen) this.brush.nativeElement.style.opacity = "0"
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
@HostListener("click")
|
|
29
|
-
onClick() {
|
|
30
|
-
this.isClickInside = true
|
|
31
|
-
|
|
32
|
-
const menuOpenedSubscription = this.colorPickerMenuTrigger.menuOpened.subscribe(() => {
|
|
33
|
-
this.brush.nativeElement.style.opacity = "1"
|
|
34
|
-
menuOpenedSubscription.unsubscribe()
|
|
35
|
-
})
|
|
36
|
-
const menuClosedSubscription = this.colorPickerMenuTrigger.menuClosed.subscribe(() => {
|
|
37
|
-
this.brush.nativeElement.style.opacity = "0"
|
|
38
|
-
menuClosedSubscription.unsubscribe()
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
this.colorPickerMenuTrigger.openMenu()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@HostListener("document:click")
|
|
45
|
-
handleDocumentClick() {
|
|
46
|
-
if (!this.isClickInside && this.colorPickerMenuTrigger && this.colorPickerMenuTrigger.menuOpen) {
|
|
47
|
-
this.colorPickerMenuTrigger.closeMenu()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.isClickInside = false
|
|
51
|
-
}
|
|
52
|
-
|
|
53
14
|
handleColorChange(hexColor: string) {
|
|
54
15
|
this.onColorChange.emit(hexColor)
|
|
55
16
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { CommonModule } from "@angular/common"
|
|
2
2
|
import { NgModule } from "@angular/core"
|
|
3
3
|
|
|
4
|
-
import { MaterialModule } from "../../../material/material.module"
|
|
5
4
|
import { ColorPickerModule } from "../colorPicker/colorPicker.module"
|
|
6
5
|
import { LabelledColorPickerComponent } from "./labelledColorPicker.component"
|
|
7
6
|
import { ReadableColorForBackgroundPipe } from "./readableColorForBackground.pipe"
|
|
8
7
|
|
|
9
8
|
@NgModule({
|
|
10
|
-
imports: [CommonModule, ColorPickerModule
|
|
9
|
+
imports: [CommonModule, ColorPickerModule],
|
|
11
10
|
declarations: [LabelledColorPickerComponent, ReadableColorForBackgroundPipe],
|
|
12
11
|
exports: [LabelledColorPickerComponent]
|
|
13
12
|
})
|
package/app/codeCharta/ui/legendPanel/legendMarkedPackages/legendMarkedPackages.component.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { KeyValue } from "@angular/common"
|
|
|
5
5
|
|
|
6
6
|
import { Store } from "../../../state/angular-redux/store"
|
|
7
7
|
import { legendMarkedPackagesSelector, MarkedPackagesMap } from "./legendMarkedPackages.selector"
|
|
8
|
-
import {
|
|
8
|
+
import { markPackages } from "../../../state/store/fileSettings/markedPackages/markedPackages.actions"
|
|
9
9
|
|
|
10
10
|
type MarkedPackagesMapKeyValue = KeyValue<keyof MarkedPackagesMap, MarkedPackagesMap[keyof MarkedPackagesMap]>
|
|
11
11
|
|
|
@@ -24,7 +24,7 @@ export class LegendMarkedPackagesComponent {
|
|
|
24
24
|
|
|
25
25
|
handleColorChange(newHexColor: string, paths: string[]) {
|
|
26
26
|
this.store.dispatch(
|
|
27
|
-
|
|
27
|
+
markPackages(
|
|
28
28
|
paths.map(path => ({
|
|
29
29
|
color: newHexColor,
|
|
30
30
|
path
|
|
@@ -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>
|