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.
- package/app/app.module.ts +18 -8
- package/app/codeCharta/codeCharta.component.ts +2 -0
- package/app/codeCharta/codeCharta.model.ts +2 -0
- package/app/codeCharta/codeCharta.service.spec.ts +41 -50
- package/app/codeCharta/codeCharta.service.ts +33 -32
- package/app/codeCharta/e2e/url.e2e.ts +1 -1
- package/app/codeCharta/state/store/appStatus/appStatus.reducer.ts +3 -1
- package/app/codeCharta/state/store/appStatus/appStatus.selector.ts +3 -0
- package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions.ts +23 -0
- package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.reducer.ts +15 -0
- package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector.ts +4 -0
- package/app/codeCharta/state/store/state.actions.ts +3 -1
- package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +6 -8
- package/app/codeCharta/ui/customConfigs/customConfigs.component.html +9 -9
- package/app/codeCharta/ui/dialog/dialog.addCustomConfigSettings.component.html +2 -2
- package/app/codeCharta/ui/dialog/dialog.changelog.component.scss +15 -0
- package/app/codeCharta/ui/dialog/dialog.changelog.component.spec.ts +15 -15
- package/app/codeCharta/ui/dialog/dialog.changelog.component.ts +2 -1
- package/app/codeCharta/ui/dialog/dialog.service.spec.ts +68 -0
- package/app/codeCharta/ui/dialog/dialog.service.ts +38 -17
- package/app/codeCharta/ui/edgeChooser/edgeChooser.e2e.ts +3 -2
- package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -6
- package/app/codeCharta/ui/filePanel/filePanel.component.html +24 -106
- package/app/codeCharta/ui/filePanel/filePanel.component.scss +12 -57
- package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +40 -72
- package/app/codeCharta/ui/filePanel/filePanel.component.ts +29 -81
- package/app/codeCharta/ui/filePanel/filePanel.module.ts +13 -1
- package/app/codeCharta/ui/filePanel/filePanel.po.ts +6 -24
- package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html +23 -0
- package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts +18 -0
- package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +18 -0
- package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +16 -0
- package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html +18 -0
- package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.ts +11 -0
- package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +7 -5
- package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.html +1 -1
- package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.spec.ts +6 -16
- package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.ts +15 -11
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.html +22 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.scss +31 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +35 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.ts +30 -0
- package/app/codeCharta/ui/nodeContextMenu/{markFolderColorPicker/markFolderColorPicker.module.ts → markFolderRow/markFolderRow.module.ts} +4 -5
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +17 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.spec.ts +15 -0
- package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.ts +9 -0
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -15
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +0 -15
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +10 -119
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +40 -134
- package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -2
- package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +1 -1
- package/app/codeCharta/ui/toolBar/toolBar.component.html +1 -1
- package/app/codeCharta/ui/toolBar/toolBar.component.scss +1 -1
- package/app/codeCharta/ui/ui.ts +2 -2
- package/app/codeCharta/util/customConfigHelper.spec.ts +155 -60
- package/app/codeCharta/util/customConfigHelper.ts +33 -3
- package/app/codeCharta/util/dataMocks.ts +4 -2
- package/app/codeCharta/util/fileValidator.spec.ts +69 -182
- package/app/codeCharta/util/fileValidator.ts +61 -37
- package/dist/webpack/bundle.js +852 -485
- package/dist/webpack/bundle.js.map +1 -1
- package/package.json +1 -1
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +0 -9
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.scss +0 -13
- package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +0 -10
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import "./filePanel.component.scss"
|
|
2
2
|
import { IRootScopeService } from "angular"
|
|
3
3
|
import { StoreService } from "../../state/store.service"
|
|
4
|
-
import { removeFile, setDeltaByNames, setMultipleByNames
|
|
4
|
+
import { removeFile, setDeltaByNames, setMultipleByNames } from "../../state/store/files/files.actions"
|
|
5
5
|
import { FilesSelectionSubscriber, FilesService } from "../../state/store/files/files.service"
|
|
6
|
-
import {
|
|
7
|
-
fileStatesAvailable,
|
|
8
|
-
getFileNameOf,
|
|
9
|
-
getVisibleFileStates,
|
|
10
|
-
isDeltaState,
|
|
11
|
-
isPartialState,
|
|
12
|
-
isSingleState
|
|
13
|
-
} from "../../model/files/files.helper"
|
|
6
|
+
import { fileStatesAvailable, getFileNameOf, getVisibleFileStates, isDeltaState, isPartialState } from "../../model/files/files.helper"
|
|
14
7
|
import { FileSelectionState, FileState } from "../../model/files/files"
|
|
15
8
|
import { CodeChartaService } from "../../codeCharta.service"
|
|
16
9
|
import { removeRecentFile } from "../../state/store/dynamicSettings/recentFiles/recentFiles.actions"
|
|
10
|
+
import { MapColorsService, MapColorsSubscriber } from "../../state/store/appSettings/mapColors/mapColors.service"
|
|
11
|
+
import { MapColors } from "../../codeCharta.model"
|
|
17
12
|
|
|
18
13
|
interface SelectedFileNames {
|
|
19
|
-
single: string
|
|
20
14
|
delta: {
|
|
21
15
|
reference: string
|
|
22
16
|
comparison: string
|
|
@@ -24,34 +18,29 @@ interface SelectedFileNames {
|
|
|
24
18
|
partial: string[]
|
|
25
19
|
}
|
|
26
20
|
|
|
27
|
-
export class FilePanelController implements FilesSelectionSubscriber {
|
|
21
|
+
export class FilePanelController implements FilesSelectionSubscriber, MapColorsSubscriber {
|
|
28
22
|
private lastRenderState: FileSelectionState
|
|
29
23
|
|
|
30
24
|
private _viewModel: {
|
|
31
|
-
isSingleState: boolean
|
|
32
25
|
isPartialState: boolean
|
|
33
26
|
isDeltaState: boolean
|
|
34
27
|
files: FileState[]
|
|
35
28
|
renderState: FileSelectionState
|
|
36
29
|
selectedFileNames: SelectedFileNames
|
|
37
|
-
pictogramFirstFileColor: string
|
|
38
30
|
pictogramUpperColor: string
|
|
39
31
|
pictogramLowerColor: string
|
|
40
32
|
} = {
|
|
41
|
-
isSingleState: null,
|
|
42
33
|
isPartialState: null,
|
|
43
34
|
isDeltaState: null,
|
|
44
35
|
files: null,
|
|
45
36
|
renderState: null,
|
|
46
37
|
selectedFileNames: {
|
|
47
|
-
single: null,
|
|
48
38
|
delta: {
|
|
49
39
|
reference: null,
|
|
50
40
|
comparison: null
|
|
51
41
|
},
|
|
52
42
|
partial: []
|
|
53
43
|
},
|
|
54
|
-
pictogramFirstFileColor: null,
|
|
55
44
|
pictogramUpperColor: null,
|
|
56
45
|
pictogramLowerColor: null
|
|
57
46
|
}
|
|
@@ -59,41 +48,25 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
59
48
|
constructor(private $rootScope: IRootScopeService, private storeService: StoreService) {
|
|
60
49
|
"ngInject"
|
|
61
50
|
FilesService.subscribe(this.$rootScope, this)
|
|
51
|
+
MapColorsService.subscribe(this.$rootScope, this)
|
|
62
52
|
}
|
|
63
53
|
|
|
64
|
-
|
|
54
|
+
onMapColorsChanged(mapColors: MapColors) {
|
|
55
|
+
this._viewModel.pictogramUpperColor = mapColors.positiveDelta
|
|
56
|
+
this._viewModel.pictogramLowerColor = mapColors.negativeDelta
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
onRemoveFile(filename, $event): void {
|
|
65
60
|
this.storeService.dispatch(removeFile(filename))
|
|
66
61
|
this.storeService.dispatch(removeRecentFile(filename))
|
|
67
62
|
|
|
68
63
|
const files = this.storeService.getState().files
|
|
69
|
-
|
|
70
|
-
this.singleStateFileRemove(files)
|
|
71
|
-
} else {
|
|
72
|
-
this.partialStateFileRemove(files)
|
|
73
|
-
}
|
|
64
|
+
this.partialStateFileRemove(files)
|
|
74
65
|
|
|
75
66
|
$event.stopPropagation()
|
|
76
67
|
$event.preventDefault()
|
|
77
68
|
}
|
|
78
69
|
|
|
79
|
-
singleStateFileRemove(files: FileState[]) {
|
|
80
|
-
if (!isSingleState(files)) {
|
|
81
|
-
this.selectRemainingFile(files)
|
|
82
|
-
} else {
|
|
83
|
-
this.keepSelection()
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private keepSelection() {
|
|
88
|
-
const selectedFile = this.storeService.getState().files.find(fileState => fileState.selectedAs === FileSelectionState.Single)
|
|
89
|
-
this.onSingleFileChange(getFileNameOf(selectedFile))
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private selectRemainingFile(files: FileState[]) {
|
|
93
|
-
const remainingFile = files[files.length - 1]
|
|
94
|
-
this.onSingleFileChange(getFileNameOf(remainingFile))
|
|
95
|
-
}
|
|
96
|
-
|
|
97
70
|
private partialStateFileRemove(files: FileState[]) {
|
|
98
71
|
const selectedFiles = files.filter(x => x.selectedAs === FileSelectionState.Partial).map(fileState => getFileNameOf(fileState))
|
|
99
72
|
|
|
@@ -106,31 +79,20 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
106
79
|
|
|
107
80
|
onFilesSelectionChanged(files: FileState[]) {
|
|
108
81
|
this._viewModel.files = files
|
|
109
|
-
this._viewModel.isSingleState = isSingleState(files)
|
|
110
82
|
this._viewModel.isPartialState = isPartialState(files)
|
|
111
83
|
this._viewModel.isDeltaState = isDeltaState(files)
|
|
112
|
-
this.setPictogramColor()
|
|
113
84
|
this.updateSelectedFileNamesInViewModel()
|
|
114
85
|
this.lastRenderState = this._viewModel.renderState
|
|
115
86
|
}
|
|
116
87
|
|
|
117
|
-
onPartialSelectionClosed() {
|
|
88
|
+
onPartialSelectionClosed = () => {
|
|
118
89
|
this.updateSelectedFileNamesInViewModel()
|
|
119
90
|
}
|
|
120
91
|
|
|
121
|
-
private setPictogramColor() {
|
|
122
|
-
this._viewModel.pictogramFirstFileColor = "#808080"
|
|
123
|
-
this._viewModel.pictogramUpperColor = this.storeService.getState().appSettings.mapColors.positiveDelta
|
|
124
|
-
this._viewModel.pictogramLowerColor = this.storeService.getState().appSettings.mapColors.negativeDelta
|
|
125
|
-
}
|
|
126
|
-
|
|
127
92
|
private updateSelectedFileNamesInViewModel() {
|
|
128
93
|
const visibleFileStates = getVisibleFileStates(this._viewModel.files)
|
|
129
94
|
|
|
130
|
-
if (this._viewModel.
|
|
131
|
-
this._viewModel.renderState = FileSelectionState.Single
|
|
132
|
-
this._viewModel.selectedFileNames.single = visibleFileStates[0].file.fileMeta.fileName
|
|
133
|
-
} else if (this._viewModel.isDeltaState) {
|
|
95
|
+
if (this._viewModel.isDeltaState) {
|
|
134
96
|
this._viewModel.renderState = FileSelectionState.Comparison
|
|
135
97
|
|
|
136
98
|
let reference = visibleFileStates[0].file.fileMeta.fileName
|
|
@@ -148,26 +110,24 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
148
110
|
}
|
|
149
111
|
}
|
|
150
112
|
|
|
151
|
-
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
onDeltaReferenceFileChange(referenceFileName: string) {
|
|
158
|
-
const rootName = this._viewModel.files.find(x => x.file.fileMeta.fileName === referenceFileName).file.map.name
|
|
113
|
+
onDeltaReferenceFileChange = (referenceFileName: string) => {
|
|
114
|
+
const rootFile = this._viewModel.files.find(x => x.file.fileMeta.fileName === referenceFileName)
|
|
115
|
+
if (!rootFile) {
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
const rootName = rootFile.file.map.name
|
|
159
119
|
CodeChartaService.updateRootData(rootName)
|
|
160
120
|
this.storeService.dispatch(setDeltaByNames(referenceFileName, this._viewModel.selectedFileNames.delta.comparison))
|
|
161
121
|
}
|
|
162
122
|
|
|
163
|
-
onDeltaComparisonFileChange(comparisonFileName: string) {
|
|
123
|
+
onDeltaComparisonFileChange = (comparisonFileName: string) => {
|
|
164
124
|
const referenceFileName = this._viewModel.selectedFileNames.delta.reference
|
|
165
125
|
const rootName = this._viewModel.files.find(x => x.file.fileMeta.fileName === referenceFileName).file.map.name
|
|
166
126
|
CodeChartaService.updateRootData(rootName)
|
|
167
127
|
this.storeService.dispatch(setDeltaByNames(referenceFileName, comparisonFileName))
|
|
168
128
|
}
|
|
169
129
|
|
|
170
|
-
onPartialFilesChange(partialFileNames: string[]) {
|
|
130
|
+
onPartialFilesChange = (partialFileNames: string[]) => {
|
|
171
131
|
if (partialFileNames.length > 0) {
|
|
172
132
|
this.storeService.dispatch(setMultipleByNames(partialFileNames))
|
|
173
133
|
} else {
|
|
@@ -175,26 +135,17 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
175
135
|
}
|
|
176
136
|
}
|
|
177
137
|
|
|
178
|
-
|
|
179
|
-
this._viewModel.selectedFileNames.single = this.getLastVisibleFileName()
|
|
180
|
-
this.onSingleFileChange(this._viewModel.selectedFileNames.single)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
onPartialStateSelected() {
|
|
184
|
-
this.selectRecentPartialFiles()
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
onDeltaStateSelected() {
|
|
138
|
+
onDeltaStateSelected = () => {
|
|
188
139
|
this._viewModel.selectedFileNames.delta.reference = this.getLastVisibleFileName()
|
|
189
140
|
this.onDeltaComparisonFileChange(null)
|
|
190
141
|
}
|
|
191
142
|
|
|
192
|
-
selectAllPartialFiles() {
|
|
143
|
+
selectAllPartialFiles = () => {
|
|
193
144
|
const allFileNames = this._viewModel.files.map(x => x.file.fileMeta.fileName)
|
|
194
145
|
this.onPartialFilesChange(allFileNames)
|
|
195
146
|
}
|
|
196
147
|
|
|
197
|
-
selectRecentPartialFiles() {
|
|
148
|
+
selectRecentPartialFiles = () => {
|
|
198
149
|
const recentFileNames = this.storeService.getState().dynamicSettings.recentFiles
|
|
199
150
|
if (recentFileNames.length > 0) {
|
|
200
151
|
this.onPartialFilesChange(recentFileNames)
|
|
@@ -203,11 +154,11 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
203
154
|
}
|
|
204
155
|
}
|
|
205
156
|
|
|
206
|
-
selectZeroPartialFiles() {
|
|
157
|
+
selectZeroPartialFiles = () => {
|
|
207
158
|
this.onPartialFilesChange([])
|
|
208
159
|
}
|
|
209
160
|
|
|
210
|
-
invertPartialFileSelection() {
|
|
161
|
+
invertPartialFileSelection = () => {
|
|
211
162
|
const invertedFileNames: string[] = []
|
|
212
163
|
const partialFileNames = new Set(this._viewModel.selectedFileNames.partial)
|
|
213
164
|
|
|
@@ -225,9 +176,6 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
225
176
|
}
|
|
226
177
|
|
|
227
178
|
private getLastVisibleFileName() {
|
|
228
|
-
if (this.lastRenderState === FileSelectionState.Single) {
|
|
229
|
-
return this._viewModel.selectedFileNames.single
|
|
230
|
-
}
|
|
231
179
|
if (this.lastRenderState === FileSelectionState.Partial) {
|
|
232
180
|
const visibleFileStates = getVisibleFileStates(this._viewModel.files)
|
|
233
181
|
if (fileStatesAvailable(this._viewModel.files)) {
|
|
@@ -242,7 +190,7 @@ export class FilePanelController implements FilesSelectionSubscriber {
|
|
|
242
190
|
}
|
|
243
191
|
|
|
244
192
|
export const filePanelComponent = {
|
|
245
|
-
selector: "
|
|
193
|
+
selector: "ccFilePanel",
|
|
246
194
|
template: require("./filePanel.component.html"),
|
|
247
195
|
controller: FilePanelController
|
|
248
196
|
}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import angular from "angular"
|
|
2
|
+
|
|
2
3
|
import "../../state/state.module"
|
|
4
|
+
|
|
3
5
|
import "../dialog/dialog.module"
|
|
6
|
+
|
|
4
7
|
import { filePanelComponent } from "./filePanel.component"
|
|
8
|
+
import { downgradeComponent } from "@angular/upgrade/static"
|
|
9
|
+
import { FilePanelFileSelectorComponent } from "./filePanelFileSelector/filePanelFileSelector.component"
|
|
10
|
+
import { FilePanelStateButtonsComponent } from "./filePanelStateButtons/filePanelStateButtons.component"
|
|
11
|
+
import { FilePanelDeltaSelectorComponent } from "./filePanelDeltaSelector/filePanelDeltaSelector.component"
|
|
5
12
|
|
|
6
|
-
angular
|
|
13
|
+
angular
|
|
14
|
+
.module("app.codeCharta.ui.filePanel", ["app.codeCharta.state"])
|
|
15
|
+
.component(filePanelComponent.selector, filePanelComponent)
|
|
16
|
+
.directive("ccFilePanelFileSelector", downgradeComponent({ component: FilePanelFileSelectorComponent }))
|
|
17
|
+
.directive("ccFilePanelStateButtons", downgradeComponent({ component: FilePanelStateButtonsComponent }))
|
|
18
|
+
.directive("ccFilePanelDeltaSelector", downgradeComponent({ component: FilePanelDeltaSelectorComponent }))
|
|
@@ -2,32 +2,14 @@ import { clickButtonOnPageElement } from "../../../puppeteer.helper"
|
|
|
2
2
|
|
|
3
3
|
export class FilePanelPageObject {
|
|
4
4
|
async getSelectedName() {
|
|
5
|
-
await page.waitForSelector("file-panel
|
|
6
|
-
return page.$eval("file-panel
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async getSelectedChangedName(oldName: string) {
|
|
10
|
-
await page.waitForSelector("file-panel-component md-select .md-text")
|
|
11
|
-
await this.waitUntilNameChange(oldName)
|
|
12
|
-
return page.$eval("file-panel-component md-select .md-text", element => element["innerText"])
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
private async waitUntilNameChange(oldName: string) {
|
|
16
|
-
await page.waitForFunction(
|
|
17
|
-
names => {
|
|
18
|
-
return document.querySelector(`file-panel-component md-select .md-text md-truncate`).textContent !== names
|
|
19
|
-
},
|
|
20
|
-
{},
|
|
21
|
-
oldName
|
|
22
|
-
)
|
|
5
|
+
await page.waitForSelector("cc-file-panel cc-file-panel-file-selector .mat-select-value-text span")
|
|
6
|
+
return page.$eval("cc-file-panel cc-file-panel-file-selector .mat-select-value-text span", element => element["innerText"])
|
|
23
7
|
}
|
|
24
8
|
|
|
25
9
|
async getAllNames() {
|
|
26
|
-
await clickButtonOnPageElement("file-panel-
|
|
27
|
-
await page.waitForSelector(".
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return content.split("\n")
|
|
10
|
+
await clickButtonOnPageElement("cc-file-panel cc-file-panel-file-selector mat-select")
|
|
11
|
+
await page.waitForSelector(".mat-select-panel")
|
|
12
|
+
const content = await page.$$eval(".mat-select-panel .mat-option-text", element => element.map(item => item["innerText"]))
|
|
13
|
+
return content
|
|
32
14
|
}
|
|
33
15
|
}
|
package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<mat-select
|
|
2
|
+
class="delta-select"
|
|
3
|
+
placeholder="select reference file"
|
|
4
|
+
[(ngModel)]="selectedDeltaReferenceFile"
|
|
5
|
+
(selectionChange)="handleDeltaReferenceFileChange(selectedDeltaReferenceFile)"
|
|
6
|
+
>
|
|
7
|
+
<mat-option *ngFor="let file of files" [value]="file.file.fileMeta.fileName">
|
|
8
|
+
{{ file.file.fileMeta.fileName }}
|
|
9
|
+
</mat-option>
|
|
10
|
+
</mat-select>
|
|
11
|
+
|
|
12
|
+
<div class="pictogram" [style.background]="'linear-gradient(' + pictogramUpperColor + ' 50%, ' + pictogramLowerColor + ' 50%)'"></div>
|
|
13
|
+
|
|
14
|
+
<mat-select
|
|
15
|
+
class="delta-select"
|
|
16
|
+
placeholder="select comparison file"
|
|
17
|
+
[(ngModel)]="selectedDeltaComparisonFile"
|
|
18
|
+
(selectionChange)="handleDeltaComparisonFileChange(selectedDeltaComparisonFile)"
|
|
19
|
+
>
|
|
20
|
+
<mat-option *ngFor="let file of files" [value]="file.file.fileMeta.fileName">
|
|
21
|
+
{{ file.file.fileMeta.fileName }}
|
|
22
|
+
</mat-option>
|
|
23
|
+
</mat-select>
|
package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core"
|
|
2
|
+
import { FileState } from "../../../model/files/files"
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: "cc-file-panel-delta-selector",
|
|
6
|
+
template: require("./filePanelDeltaSelector.component.html")
|
|
7
|
+
})
|
|
8
|
+
export class FilePanelDeltaSelectorComponent {
|
|
9
|
+
@Input() files: FileState[]
|
|
10
|
+
@Input() pictogramFirstColor: string
|
|
11
|
+
@Input() pictogramUpperColor: string
|
|
12
|
+
@Input() pictogramLowerColor: string
|
|
13
|
+
@Input() handleDeltaReferenceFileChange: (referenceFileName: string) => void
|
|
14
|
+
@Input() handleDeltaComparisonFileChange: (comparisonFileName: string) => void
|
|
15
|
+
|
|
16
|
+
selectedDeltaReferenceFile: string
|
|
17
|
+
selectedDeltaComparisonFile: string
|
|
18
|
+
}
|
package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<mat-select
|
|
2
|
+
class="standard-select"
|
|
3
|
+
[(ngModel)]="selectedFileNames"
|
|
4
|
+
(selectionChange)="handleSelectedFilesChanged(selectedFileNames)"
|
|
5
|
+
name="recentFiles"
|
|
6
|
+
[placeholder]="selectedFileNames"
|
|
7
|
+
multiple
|
|
8
|
+
(closed)="handleOnSelectionClosed()"
|
|
9
|
+
>
|
|
10
|
+
<div class="actions">
|
|
11
|
+
<button mat-button (click)="handleSelectAllPartialFiles()">All</button>
|
|
12
|
+
<button mat-button (click)="handleSelectZeroPartialFiles()">None</button>
|
|
13
|
+
<button mat-button (click)="handleInvertSelectedPartialFiles()">Invert</button>
|
|
14
|
+
</div>
|
|
15
|
+
<mat-option *ngFor="let file of files" [value]="file.file.fileMeta.fileName">
|
|
16
|
+
{{ file.file.fileMeta.fileName }}
|
|
17
|
+
</mat-option>
|
|
18
|
+
</mat-select>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core"
|
|
2
|
+
import { FileState } from "../../../model/files/files"
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: "cc-file-panel-file-selector",
|
|
6
|
+
template: require("./filePanelFileSelector.component.html")
|
|
7
|
+
})
|
|
8
|
+
export class FilePanelFileSelectorComponent {
|
|
9
|
+
@Input() files: FileState[]
|
|
10
|
+
@Input() selectedFileNames: string[]
|
|
11
|
+
@Input() handleSelectedFilesChanged: (selectedFileNames: string[]) => void
|
|
12
|
+
@Input() handleSelectAllPartialFiles: () => void
|
|
13
|
+
@Input() handleSelectZeroPartialFiles: () => void
|
|
14
|
+
@Input() handleInvertSelectedPartialFiles: () => void
|
|
15
|
+
@Input() handleOnSelectionClosed: () => void
|
|
16
|
+
}
|
package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<div class="mode-chooser">
|
|
2
|
+
<button
|
|
3
|
+
mat-button
|
|
4
|
+
class="state-selector-button mode-selector left"
|
|
5
|
+
(click)="handleStandardButtonClicked()"
|
|
6
|
+
[class.current]="!isDeltaState"
|
|
7
|
+
>
|
|
8
|
+
<span class="text">Standard</span>
|
|
9
|
+
</button>
|
|
10
|
+
<button
|
|
11
|
+
mat-button
|
|
12
|
+
class="state-selector-button mode-selector right"
|
|
13
|
+
(click)="handleDeltaButtonClicked()"
|
|
14
|
+
[class.current]="isDeltaState"
|
|
15
|
+
>
|
|
16
|
+
<span class="text">Delta</span>
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core"
|
|
2
|
+
|
|
3
|
+
@Component({
|
|
4
|
+
selector: "cc-file-panel-state-buttons",
|
|
5
|
+
template: require("./filePanelStateButtons.component.html")
|
|
6
|
+
})
|
|
7
|
+
export class FilePanelStateButtonsComponent {
|
|
8
|
+
@Input() isDeltaState: boolean
|
|
9
|
+
@Input() handleStandardButtonClicked: () => void
|
|
10
|
+
@Input() handleDeltaButtonClicked: () => void
|
|
11
|
+
}
|
|
@@ -18,10 +18,11 @@ describe("MapTreeViewLevel", () => {
|
|
|
18
18
|
|
|
19
19
|
describe("Blacklist", () => {
|
|
20
20
|
it("excluding a building should exclude it from the tree-view as well", async () => {
|
|
21
|
-
const filePath = "/root/ParentLeaf/smallLeaf.html"
|
|
21
|
+
const filePath = "/root/sample1.cc.json/ParentLeaf/smallLeaf.html"
|
|
22
22
|
|
|
23
23
|
await searchPanelModeSelector.toggleTreeView()
|
|
24
|
-
await mapTreeViewLevel.openFolder("/root/
|
|
24
|
+
await mapTreeViewLevel.openFolder("/root/sample1.cc.json")
|
|
25
|
+
await mapTreeViewLevel.openFolder("/root/sample1.cc.json/ParentLeaf")
|
|
25
26
|
await mapTreeViewLevel.openContextMenu(filePath)
|
|
26
27
|
await nodeContextMenu.exclude()
|
|
27
28
|
|
|
@@ -31,12 +32,13 @@ describe("MapTreeViewLevel", () => {
|
|
|
31
32
|
|
|
32
33
|
describe("NodeContextMenu", () => {
|
|
33
34
|
it("NodeContextMenu path should remain marked when hovering over another mapTreeView Element", async () => {
|
|
34
|
-
const filePath = "/root/ParentLeaf/smallLeaf.html"
|
|
35
|
+
const filePath = "/root/sample1.cc.json/ParentLeaf/smallLeaf.html"
|
|
35
36
|
|
|
36
37
|
await searchPanelModeSelector.toggleTreeView()
|
|
37
|
-
await mapTreeViewLevel.openFolder("/root/
|
|
38
|
+
await mapTreeViewLevel.openFolder("/root/sample1.cc.json")
|
|
39
|
+
await mapTreeViewLevel.openFolder("/root/sample1.cc.json/ParentLeaf")
|
|
38
40
|
await mapTreeViewLevel.openContextMenu(filePath)
|
|
39
|
-
await mapTreeViewLevel.hoverNode("/root/sample1OnlyLeaf.scss")
|
|
41
|
+
await mapTreeViewLevel.hoverNode("/root/sample1.cc.json/sample1OnlyLeaf.scss")
|
|
40
42
|
|
|
41
43
|
expect(await mapTreeViewLevel.isNodeMarked(filePath)).toBeTruthy()
|
|
42
44
|
})
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
id="{{ node.path }}"
|
|
4
4
|
class="tree-element-label-{{ depth }} tree-element-label"
|
|
5
5
|
[class.hovered]="(hoveredBuildingPath$ | async) === node.path"
|
|
6
|
-
[class.marked]="
|
|
6
|
+
[class.marked]="(rightClickedNodeData$ | async)?.nodeId === node.id"
|
|
7
7
|
(mouseenter)="onMouseEnter()"
|
|
8
8
|
(mouseleave)="onMouseLeave()"
|
|
9
9
|
(click)="toggleOpen()"
|
|
@@ -4,17 +4,10 @@ import userEvent from "@testing-library/user-event"
|
|
|
4
4
|
|
|
5
5
|
import { searchedNodePathsSelector } from "../../../state/selectors/searchedNodes/searchedNodePaths.selector"
|
|
6
6
|
import { Store } from "../../../state/store/store"
|
|
7
|
-
import { NodeContextMenuController } from "../../nodeContextMenu/nodeContextMenu.component"
|
|
8
7
|
import { MapTreeViewModule } from "../mapTreeView.module"
|
|
9
8
|
import { MapTreeViewLevelComponent } from "./mapTreeViewLevel.component"
|
|
10
9
|
import { rootNode } from "./mocks"
|
|
11
10
|
|
|
12
|
-
jest.mock("../../nodeContextMenu/nodeContextMenu.component", () => ({
|
|
13
|
-
NodeContextMenuController: {
|
|
14
|
-
subscribeToHideNodeContextMenu: () => {},
|
|
15
|
-
broadcastShowEvent: jest.fn()
|
|
16
|
-
}
|
|
17
|
-
}))
|
|
18
11
|
jest.mock("../../../state/selectors/searchedNodes/searchedNodePaths.selector", () => ({
|
|
19
12
|
searchedNodePathsSelector: jest.fn(
|
|
20
13
|
jest.requireActual("../../../state/selectors/searchedNodes/searchedNodePaths.selector").searchedNodePathsSelector
|
|
@@ -76,21 +69,18 @@ describe("mapTreeViewLevel", () => {
|
|
|
76
69
|
expect(firstLevelFolder.querySelector("cc-map-tree-view-item-option-buttons")).toBeTruthy()
|
|
77
70
|
})
|
|
78
71
|
|
|
79
|
-
it("should
|
|
80
|
-
const nodeContextMenuSpy = jest.spyOn(NodeContextMenuController, "broadcastShowEvent")
|
|
81
|
-
|
|
72
|
+
it("should show option button on hover and be marked after context menu was opened", async () => {
|
|
82
73
|
const { container } = await render(MapTreeViewLevelComponent, { componentProperties, excludeComponentDeclaration: true })
|
|
74
|
+
|
|
83
75
|
const firstLevelFolder = container.querySelector("#\\/root\\/ParentLeaf")
|
|
76
|
+
let optionsButton = firstLevelFolder.querySelector("cc-map-tree-view-item-option-buttons")
|
|
77
|
+
expect(optionsButton).toBe(null)
|
|
84
78
|
|
|
85
79
|
userEvent.hover(firstLevelFolder)
|
|
86
|
-
|
|
80
|
+
optionsButton = firstLevelFolder.querySelector("cc-map-tree-view-item-option-buttons")
|
|
81
|
+
expect(optionsButton).not.toBe(null)
|
|
87
82
|
fireEvent.click(optionsButton.querySelector("[title='Open Node-Context-Menu']"))
|
|
88
83
|
|
|
89
|
-
expect(nodeContextMenuSpy).toHaveBeenCalled()
|
|
90
|
-
const argumentsToNodeContextMenu = nodeContextMenuSpy.mock.calls[0]
|
|
91
|
-
expect(argumentsToNodeContextMenu[1]).toBe("/root/ParentLeaf")
|
|
92
|
-
expect(argumentsToNodeContextMenu[2]).toBe("Folder")
|
|
93
|
-
|
|
94
84
|
const isMarked = container.querySelector("#\\/root\\/ParentLeaf.marked")
|
|
95
85
|
expect(isMarked).toBeTruthy()
|
|
96
86
|
})
|
|
@@ -5,7 +5,11 @@ import { Store } from "../../../state/angular-redux/store"
|
|
|
5
5
|
import { CodeMapNode } from "../../../codeCharta.model"
|
|
6
6
|
import { hoveredBuildingPathSelector } from "../../../state/store/appStatus/hoveredBuildingPath/hoveredBuildingPath.selector"
|
|
7
7
|
import { setHoveredBuildingPath } from "../../../state/store/appStatus/hoveredBuildingPath/hoveredBuildingPath.actions"
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
RightClickedNodeData,
|
|
10
|
+
setRightClickedNodeData
|
|
11
|
+
} from "../../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions"
|
|
12
|
+
import { rightClickedNodeDataSelector } from "../../../state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector"
|
|
9
13
|
|
|
10
14
|
@Component({
|
|
11
15
|
selector: "cc-map-tree-view-level",
|
|
@@ -16,14 +20,13 @@ export class MapTreeViewLevelComponent implements OnInit {
|
|
|
16
20
|
@Input() depth: number
|
|
17
21
|
|
|
18
22
|
hoveredBuildingPath$: Observable<string | null>
|
|
23
|
+
rightClickedNodeData$: Observable<RightClickedNodeData>
|
|
19
24
|
|
|
20
25
|
isOpen = false
|
|
21
|
-
isContextMenuOpenForNode = false
|
|
22
26
|
|
|
23
27
|
constructor(@Inject(Store) private store: Store) {
|
|
24
28
|
this.hoveredBuildingPath$ = this.store.select(hoveredBuildingPathSelector)
|
|
25
|
-
|
|
26
|
-
NodeContextMenuController.subscribeToHideNodeContextMenu(undefined, this)
|
|
29
|
+
this.rightClickedNodeData$ = this.store.select(rightClickedNodeDataSelector)
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
ngOnInit(): void {
|
|
@@ -33,10 +36,6 @@ export class MapTreeViewLevelComponent implements OnInit {
|
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
onHideNodeContextMenu() {
|
|
37
|
-
this.isContextMenuOpenForNode = false
|
|
38
|
-
}
|
|
39
|
-
|
|
40
39
|
onMouseEnter() {
|
|
41
40
|
this.store.dispatch(setHoveredBuildingPath(this.node.path))
|
|
42
41
|
}
|
|
@@ -49,8 +48,13 @@ export class MapTreeViewLevelComponent implements OnInit {
|
|
|
49
48
|
$event.stopPropagation()
|
|
50
49
|
$event.preventDefault()
|
|
51
50
|
|
|
52
|
-
this.
|
|
53
|
-
|
|
51
|
+
this.store.dispatch(
|
|
52
|
+
setRightClickedNodeData({
|
|
53
|
+
nodeId: this.node.id,
|
|
54
|
+
xPositionOfRightClickEvent: $event.clientX,
|
|
55
|
+
yPositionOfRightClickEvent: $event.clientY
|
|
56
|
+
})
|
|
57
|
+
)
|
|
54
58
|
|
|
55
59
|
document.querySelector(".tree-element-0").addEventListener("scroll", this.scrollFunction)
|
|
56
60
|
}
|
|
@@ -60,7 +64,7 @@ export class MapTreeViewLevelComponent implements OnInit {
|
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
private scrollFunction = () => {
|
|
63
|
-
|
|
67
|
+
this.store.dispatch(setRightClickedNodeData(null))
|
|
64
68
|
document.querySelector(".tree-element-0").removeEventListener("scroll", this.scrollFunction)
|
|
65
69
|
}
|
|
66
70
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<div class="row" *ngIf="node$ | async as node">
|
|
2
|
+
<ng-container *ngFor="let markFolderItem of markFolderItems$ | async">
|
|
3
|
+
<button
|
|
4
|
+
[style.background-color]="markFolderItem.color"
|
|
5
|
+
(click)="markFolderItem.isMarked ? unmarkFolder(node.path) : markFolder(node.path, markFolderItem.color)"
|
|
6
|
+
class="colorButton"
|
|
7
|
+
title="Colorize folder"
|
|
8
|
+
>
|
|
9
|
+
<i class="fa fa-times" *ngIf="markFolderItem.isMarked"></i>
|
|
10
|
+
</button>
|
|
11
|
+
</ng-container>
|
|
12
|
+
|
|
13
|
+
<cc-color-picker
|
|
14
|
+
[hexColor]="'#ff0000'"
|
|
15
|
+
(onColorChange)="markFolder(node.path, $event)"
|
|
16
|
+
[triggerTemplate]="colorPickerTriggerTemplate"
|
|
17
|
+
></cc-color-picker>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<ng-template #colorPickerTriggerTemplate>
|
|
21
|
+
<div class="cc-color-picker-trigger fa fa-paint-brush"></div>
|
|
22
|
+
</ng-template>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
cc-mark-folder-row {
|
|
2
|
+
.row {
|
|
3
|
+
display: flex;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
:hover {
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.colorButton {
|
|
11
|
+
width: 32px;
|
|
12
|
+
height: 32px;
|
|
13
|
+
|
|
14
|
+
i {
|
|
15
|
+
font-size: 25px;
|
|
16
|
+
display: block;
|
|
17
|
+
color: red;
|
|
18
|
+
text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
cc-color-picker {
|
|
23
|
+
width: 32px;
|
|
24
|
+
height: 32px;
|
|
25
|
+
|
|
26
|
+
.cc-color-picker-trigger {
|
|
27
|
+
font-size: 25px;
|
|
28
|
+
margin-top: 8px;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TestBed } from "@angular/core/testing"
|
|
2
|
+
import { fireEvent, render } from "@testing-library/angular"
|
|
3
|
+
import { MarkFolderRowComponent } from "./markFolderRow.component"
|
|
4
|
+
import { MarkFolderRowModule } from "./markFolderRow.module"
|
|
5
|
+
|
|
6
|
+
jest.mock("./selectors/rightClickedNode.selector", () => ({
|
|
7
|
+
rightClickedNodeSelector: () => ({ path: "/root" })
|
|
8
|
+
}))
|
|
9
|
+
|
|
10
|
+
describe("markFolderRow component", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
TestBed.configureTestingModule({
|
|
13
|
+
imports: [MarkFolderRowModule]
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it("should let a user mark and unmark a node", async () => {
|
|
18
|
+
const { container } = await render(MarkFolderRowComponent, { excludeComponentDeclaration: true })
|
|
19
|
+
|
|
20
|
+
expect(container.querySelectorAll("button").length).toBe(5)
|
|
21
|
+
expect(container.querySelectorAll("cc-color-picker").length).toBe(1)
|
|
22
|
+
expect(container.querySelectorAll(".fa-times").length).toBe(0)
|
|
23
|
+
|
|
24
|
+
fireEvent.click(getFirstColorButton(container))
|
|
25
|
+
expect(container.querySelectorAll(".fa-times").length).toBe(1)
|
|
26
|
+
expect(getFirstColorButton(container).querySelector(".fa-times")).not.toBe(null)
|
|
27
|
+
|
|
28
|
+
fireEvent.click(getFirstColorButton(container))
|
|
29
|
+
expect(container.querySelectorAll(".fa-times").length).toBe(0)
|
|
30
|
+
|
|
31
|
+
function getFirstColorButton(container: Element) {
|
|
32
|
+
return container.querySelectorAll("button[title='Colorize folder']")[0]
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
})
|