aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorPhilippe Perrin <philippe.perrin@sonarsource.com>2020-02-07 14:45:12 +0100
committerSonarTech <sonartech@sonarsource.com>2020-02-21 20:46:19 +0100
commit92bdc9faf99a89c0c70945198045b1de81db2ed7 (patch)
tree28d31ab41b171eb6d562136d91d716169dc18ec2 /server/sonar-web
parent7421f46c36752c57290af1c53ea2e57e0cfa32fa (diff)
downloadsonarqube-92bdc9faf99a89c0c70945198045b1de81db2ed7.tar.gz
sonarqube-92bdc9faf99a89c0c70945198045b1de81db2ed7.zip
SONAR-12754 Assignee change are made directly from the main screen
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/app/utils/startReactApp.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsApp.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsApp-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/utils-test.ts (renamed from server/sonar-web/src/main/js/apps/securityHotspots/__tests__/utils-test.ts)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/FilterBar.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActions.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActions.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsForm.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsForm.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsFormRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsFormRenderer.tsx)7
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCategory.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotCategory.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.css)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotListItem.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotListItem.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainer.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainerRenderer.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewer.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerRenderer.tsx)14
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTab.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTab.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerTabs.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/EmptyHotspotsPage-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/FilterBar-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActions-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActions-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsForm-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotCategory-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotCategory-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotList-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotList-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotListItem-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotListItem-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerRenderer-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerTabs-test.tsx)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap)10
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap)667
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/Assignee.tsx103
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeRenderer.tsx81
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.css (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.css)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.tsx)133
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelectionRenderer.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelectRenderer.tsx)24
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/Assignee-test.tsx92
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeRenderer-test.tsx85
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelection-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelect-test.tsx)41
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelectionRenderer-test.tsx (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelectRenderer-test.tsx)8
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/Assignee-test.tsx.snap39
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeRenderer-test.tsx.snap135
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelection-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelect-test.tsx.snap)5
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelectionRenderer-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelectRenderer-test.tsx.snap)71
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/styles.css (renamed from server/sonar-web/src/main/js/apps/securityHotspots/styles.css)0
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/utils.ts (renamed from server/sonar-web/src/main/js/apps/securityHotspots/utils.ts)0
69 files changed, 1322 insertions, 195 deletions
diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
index d8fb504f091..a901bca0c2a 100644
--- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
+++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
@@ -183,7 +183,7 @@ function renderComponentRoutes() {
<Route
path="security_hotspots"
component={lazyLoadComponent(() =>
- import('../../apps/securityHotspots/SecurityHotspotsApp')
+ import('../../apps/security-hotspots/SecurityHotspotsApp')
)}
/>
<RouteWithChildRoutes path="project/quality_gate" childRoutes={projectQualityGateRoutes} />
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
index 13e16ce83b8..13e16ce83b8 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsApp.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx
index 898dcbe5074..898dcbe5074 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsApp-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
index 8437fcffb58..8437fcffb58 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsApp-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
index b90229c0aff..b90229c0aff 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap
index 78f624205a3..78f624205a3 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
index 64e20d6e7c9..64e20d6e7c9 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/utils-test.ts
index a837324eba8..a837324eba8 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/utils-test.ts
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/utils-test.ts
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx
index a178c3bbb8b..a178c3bbb8b 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/FilterBar.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
index 67151c4a16c..67151c4a16c 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/FilterBar.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActions.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActions.tsx
index 2018a18feb3..2018a18feb3 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActions.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActions.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsForm.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsForm.tsx
index c5564548006..c5564548006 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsForm.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsForm.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsFormRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsFormRenderer.tsx
index e6a382828db..d8d0ff6ceb0 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotActionsFormRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotActionsFormRenderer.tsx
@@ -30,7 +30,6 @@ import {
HotspotStatus,
HotspotStatusOption
} from '../../../types/security-hotspots';
-import HotspotAssigneeSelect from './HotspotAssigneeSelect';
export interface HotspotActionsFormRendererProps {
comment: string;
@@ -76,12 +75,6 @@ export default function HotspotActionsFormRenderer(props: HotspotActionsFormRend
onClick: props.onSelectOption
})}
</div>
- {selectedOption === HotspotStatusOption.ADDITIONAL_REVIEW && (
- <div className="form-field huge-spacer-left">
- <label>{translate('hotspots.form.assign_to')}</label>
- <HotspotAssigneeSelect onSelect={props.onAssign} />
- </div>
- )}
<div className="display-flex-column big-spacer-bottom">
<label className="little-spacer-bottom">{translate('hotspots.form.comment')}</label>
<textarea
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotCategory.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCategory.tsx
index be732964b3b..be732964b3b 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotCategory.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCategory.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.css b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css
index 242baa85c30..242baa85c30 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.css
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx
index 286e9a30b85..286e9a30b85 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotList.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotListItem.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotListItem.tsx
index 95a9826cc7d..95a9826cc7d 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotListItem.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotListItem.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainer.tsx
index c9afaceffa5..c9afaceffa5 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainer.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainerRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx
index f743bef4d05..f743bef4d05 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainerRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx
index 480b3001dd0..480b3001dd0 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx
index a12ae55ffe6..179f461cda7 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx
@@ -19,11 +19,12 @@
*/
import * as React from 'react';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { translate } from 'sonar-ui-common/helpers/l10n';
import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { isLoggedIn } from '../../../helpers/users';
import { BranchLike } from '../../../types/branch-like';
import { Hotspot } from '../../../types/security-hotspots';
+import Assignee from './assignee/Assignee';
import HotspotActions from './HotspotActions';
import HotspotSnippetContainer from './HotspotSnippetContainer';
import HotspotViewerTabs from './HotspotViewerTabs';
@@ -63,16 +64,7 @@ export function HotspotViewerRenderer(props: HotspotViewerRendererProps) {
<span className="badge little-spacer-left">
{translate('hotspot.status', hotspot.resolution || hotspot.status)}
</span>
- {hotspot.assigneeUser && hotspot.assigneeUser.name && (
- <>
- <span className="huge-spacer-left">{translate('assigned_to')}:</span>
- <strong className="little-spacer-left">
- {hotspot.assigneeUser.active
- ? hotspot.assigneeUser.name
- : translateWithParameters('user.x_deleted', hotspot.assigneeUser.name)}
- </strong>
- </>
- )}
+ <Assignee hotspot={hotspot} onAssigneeChange={props.onUpdateHotspot} />
</div>
<HotspotSnippetContainer branchLike={branchLike} hotspot={hotspot} />
<HotspotViewerTabs hotspot={hotspot} onUpdateHotspot={props.onUpdateHotspot} />
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTab.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTab.tsx
index 07989ed42f7..07989ed42f7 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTab.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTab.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx
index df8afcfff29..df8afcfff29 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerReviewHistoryTabCommentBox.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerTabs.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx
index 961c8829c64..961c8829c64 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotViewerTabs.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/EmptyHotspotsPage-test.tsx
index bbeb14429c5..bbeb14429c5 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/EmptyHotspotsPage-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/FilterBar-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx
index 31dce745ea4..31dce745ea4 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/FilterBar-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActions-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActions-test.tsx
index 1f67a35002f..1f67a35002f 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActions-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActions-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsForm-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsForm-test.tsx
index 11fb8aa26ef..11fb8aa26ef 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsForm-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsForm-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx
index 77dc7596bd0..77dc7596bd0 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotActionsFormRenderer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotCategory-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotCategory-test.tsx
index 99a432c2b5d..99a432c2b5d 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotCategory-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotCategory-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotList-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotList-test.tsx
index caaa7bff5d7..caaa7bff5d7 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotList-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotList-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotListItem-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotListItem-test.tsx
index 3e6467046a5..3e6467046a5 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotListItem-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotListItem-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainer-test.tsx
index 23b4bad0dc9..23b4bad0dc9 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx
index 064ef445734..064ef445734 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSnippetContainerRenderer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx
index 01e8029eee0..01e8029eee0 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx
index 68820dd230e..68820dd230e 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx
index 48e790c2e44..48e790c2e44 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTab-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx
index febd2a6a017..febd2a6a017 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerReviewHistoryTabCommentBox-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerTabs-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx
index 24a09807b6e..24a09807b6e 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotViewerTabs-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap
index b90efd1eb50..b90efd1eb50 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
index 2e6f744c0a7..2e6f744c0a7 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap
index e0d10a202a4..e0d10a202a4 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActions-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap
index 9ad46c82552..9ad46c82552 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsForm-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap
index 3aec0f39980..1f5255ea037 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotActionsFormRenderer-test.tsx.snap
@@ -514,16 +514,6 @@ exports[`should render correctly: user selected 1`] = `
</div>
</div>
<div
- className="form-field huge-spacer-left"
- >
- <label>
- hotspots.form.assign_to
- </label>
- <HotspotAssigneeSelect
- onSelect={[MockFunction]}
- />
- </div>
- <div
className="display-flex-column big-spacer-bottom"
>
<label
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap
index a075d958dfe..a075d958dfe 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotCategory-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
index 07c77d60fa5..07c77d60fa5 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap
index 2bf9b48a976..2bf9b48a976 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotListItem-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap
index 861a5718a00..861a5718a00 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap
index 08bcc2a1b2d..08bcc2a1b2d 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotSnippetContainerRenderer-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
index c9bd0adb0ab..c9bd0adb0ab 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap
index 5feb8354528..6b2e8cf1ad4 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerRenderer-test.tsx.snap
@@ -44,17 +44,108 @@ exports[`should render correctly 1`] = `
>
hotspot.status.FIXED
</span>
- <span
- className="huge-spacer-left"
- >
- assigned_to
- :
- </span>
- <strong
- className="little-spacer-left"
- >
- John Doe
- </strong>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
@@ -307,17 +398,108 @@ exports[`should render correctly: anonymous user 1`] = `
>
hotspot.status.FIXED
</span>
- <span
- className="huge-spacer-left"
- >
- assigned_to
- :
- </span>
- <strong
- className="little-spacer-left"
- >
- John Doe
- </strong>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
@@ -570,6 +752,108 @@ exports[`should render correctly: assignee without name 1`] = `
>
hotspot.status.FIXED
</span>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
+ "active": true,
+ "local": true,
+ "login": "assignee_login",
+ "name": undefined,
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
@@ -822,17 +1106,108 @@ exports[`should render correctly: deleted assignee 1`] = `
>
hotspot.status.FIXED
</span>
- <span
- className="huge-spacer-left"
- >
- assigned_to
- :
- </span>
- <strong
- className="little-spacer-left"
- >
- user.x_deleted.John Doe
- </strong>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
+ "active": false,
+ "local": true,
+ "login": "john.doe",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
@@ -1092,17 +1467,108 @@ exports[`should render correctly: unassigned 1`] = `
>
hotspot.status.FIXED
</span>
- <span
- className="huge-spacer-left"
- >
- assigned_to
- :
- </span>
- <strong
- className="little-spacer-left"
- >
- John Doe
- </strong>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": undefined,
+ "assigneeUser": Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
@@ -1457,17 +1923,108 @@ exports[`should render correctly: user logged in 1`] = `
>
hotspot.status.FIXED
</span>
- <span
- className="huge-spacer-left"
- >
- assigned_to
- :
- </span>
- <strong
- className="little-spacer-left"
- >
- John Doe
- </strong>
+ <Connect(withCurrentUser(Assignee))
+ hotspot={
+ Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ "canChangeStatus": true,
+ "changelog": Array [],
+ "comment": Array [],
+ "component": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "FIL",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "creationDate": "2013-05-13T17:55:41+0200",
+ "key": "01fc972e-2a3c-433e-bcae-0bd7f88f5123",
+ "line": 142,
+ "message": "'3' is a magic number.",
+ "project": Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ },
+ "resolution": "FIXED",
+ "rule": Object {
+ "fixRecommendations": "<p>This a <strong>strong</strong> message about fixing !</p>",
+ "key": "squid:S2077",
+ "name": "That rule",
+ "riskDescription": "<p>This a <strong>strong</strong> message about risk !</p>",
+ "securityCategory": "sql-injection",
+ "vulnerabilityDescription": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
+ "vulnerabilityProbability": "HIGH",
+ },
+ "status": "REVIEWED",
+ "textRange": Object {
+ "endLine": 142,
+ "endOffset": 83,
+ "startLine": 142,
+ "startOffset": 26,
+ },
+ "updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
+ }
+ }
+ onAssigneeChange={[MockFunction]}
+ />
</div>
<HotspotSnippetContainer
hotspot={
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap
index 3aee5ee3160..3aee5ee3160 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTab-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap
index 951a828e1b2..951a828e1b2 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerReviewHistoryTabCommentBox-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap
index 76d3667a4ff..76d3667a4ff 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewerTabs-test.tsx.snap
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/Assignee.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/Assignee.tsx
new file mode 100644
index 00000000000..67afff62765
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/Assignee.tsx
@@ -0,0 +1,103 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { assignSecurityHotspot } from '../../../../api/security-hotspots';
+import { withCurrentUser } from '../../../../components/hoc/withCurrentUser';
+import { isLoggedIn } from '../../../../helpers/users';
+import { Hotspot, HotspotStatus } from '../../../../types/security-hotspots';
+import AssigneeRenderer from './AssigneeRenderer';
+
+interface Props {
+ currentUser: T.CurrentUser;
+ hotspot: Hotspot;
+
+ onAssigneeChange: () => void;
+}
+
+interface State {
+ editing: boolean;
+ loading: boolean;
+}
+
+export class Assignee extends React.PureComponent<Props, State> {
+ mounted = false;
+ state = {
+ editing: false,
+ loading: false
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleEnterEditionMode = () => {
+ this.setState({ editing: true });
+ };
+
+ handleExitEditionMode = () => {
+ this.setState({ editing: false });
+ };
+
+ handleAssign = (newAssignee?: T.UserActive) => {
+ if (newAssignee && newAssignee.login) {
+ this.setState({ loading: true });
+ assignSecurityHotspot(this.props.hotspot.key, {
+ assignee: newAssignee.login
+ })
+ .then(() => {
+ if (this.mounted) {
+ this.setState({ editing: false, loading: false });
+ this.props.onAssigneeChange();
+ }
+ })
+ .catch(() => this.setState({ loading: false }));
+ }
+ };
+
+ render() {
+ const {
+ currentUser,
+ hotspot: { assigneeUser, status }
+ } = this.props;
+ const { editing, loading } = this.state;
+
+ const canEdit = status === HotspotStatus.TO_REVIEW;
+
+ return (
+ <AssigneeRenderer
+ assignee={assigneeUser}
+ canEdit={canEdit}
+ editing={editing}
+ loading={loading}
+ loggedInUser={isLoggedIn(currentUser) ? currentUser : undefined}
+ onAssign={this.handleAssign}
+ onEnterEditionMode={this.handleEnterEditionMode}
+ onExitEditionMode={this.handleExitEditionMode}
+ />
+ );
+ }
+}
+
+export default withCurrentUser(Assignee);
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeRenderer.tsx
new file mode 100644
index 00000000000..8aae0d6d31e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeRenderer.tsx
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { EditButton } from 'sonar-ui-common/components/controls/buttons';
+import EscKeydownHandler from 'sonar-ui-common/components/controls/EscKeydownHandler';
+import OutsideClickHandler from 'sonar-ui-common/components/controls/OutsideClickHandler';
+import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
+import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import AssigneeSelection from './AssigneeSelection';
+
+export interface AssigneeRendererProps {
+ canEdit: boolean;
+ editing: boolean;
+ loading: boolean;
+
+ assignee?: T.UserBase;
+ loggedInUser?: T.LoggedInUser;
+
+ onAssign: (user?: T.UserActive) => void;
+ onEnterEditionMode: () => void;
+ onExitEditionMode: () => void;
+}
+
+export default function AssigneeRenderer(props: AssigneeRendererProps) {
+ const { assignee, canEdit, loggedInUser, editing, loading } = props;
+
+ return (
+ <div className="big-spacer-top display-flex-center">
+ <span>{translate('assignee')}:</span>
+
+ <span className="spacer-left">
+ <DeferredSpinner loading={loading}>
+ {!editing && (
+ <div className="display-flex-center">
+ <strong>
+ {assignee &&
+ (assignee.active
+ ? assignee.name ?? assignee.login
+ : translateWithParameters('user.x_deleted', assignee.name ?? assignee.login))}
+ {!assignee && translate('unassigned')}
+ </strong>
+ {loggedInUser && canEdit && (
+ <EditButton className="spacer-left" onClick={props.onEnterEditionMode} />
+ )}
+ </div>
+ )}
+
+ {loggedInUser && editing && (
+ <EscKeydownHandler onKeydown={props.onExitEditionMode}>
+ <OutsideClickHandler onClickOutside={props.onExitEditionMode}>
+ <AssigneeSelection
+ allowCurrentUserSelection={loggedInUser.login !== assignee?.login}
+ loggedInUser={loggedInUser}
+ onSelect={props.onAssign}
+ />
+ </OutsideClickHandler>
+ </EscKeydownHandler>
+ )}
+ </DeferredSpinner>
+ </span>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.css b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.css
index 7a5c24ebf0e..7a5c24ebf0e 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.css
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.css
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.tsx
index 45f272a4e6d..edabb4a50bf 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelect.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.tsx
@@ -20,11 +20,13 @@
import { debounce } from 'lodash';
import * as React from 'react';
import { KeyCodes } from 'sonar-ui-common/helpers/keycodes';
-import { searchUsers } from '../../../api/users';
-import { isUserActive } from '../../../helpers/users';
-import HotspotAssigneeSelectRenderer from './HotspotAssigneeSelectRenderer';
+import { searchUsers } from '../../../../api/users';
+import { isUserActive } from '../../../../helpers/users';
+import AssigneeSelectionRenderer from './AssigneeSelectionRenderer';
interface Props {
+ allowCurrentUserSelection: boolean;
+ loggedInUser: T.LoggedInUser;
onSelect: (user?: T.UserActive) => void;
}
@@ -33,123 +35,138 @@ interface State {
loading: boolean;
open: boolean;
query?: string;
- suggestedUsers?: T.UserActive[];
+ suggestedUsers: T.UserActive[];
}
-export default class HotspotAssigneeSelect extends React.PureComponent<Props, State> {
- state: State;
+export default class AssigneeSelection extends React.PureComponent<Props, State> {
+ mounted = false;
constructor(props: Props) {
super(props);
+
this.state = {
loading: false,
- open: false
+ open: props.allowCurrentUserSelection,
+ suggestedUsers: props.allowCurrentUserSelection ? [props.loggedInUser] : []
};
+
this.handleSearch = debounce(this.handleSearch, 250);
}
- getCurrentIndex = () => {
- const { highlighted, suggestedUsers } = this.state;
- return highlighted && suggestedUsers
- ? suggestedUsers.findIndex(suggestion => suggestion.login === highlighted.login)
- : -1;
- };
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
handleSearch = (query: string) => {
- if (query.length < 2) {
- this.setState({ open: false, query });
- this.props.onSelect(undefined);
- return Promise.resolve([]);
+ if (this.mounted) {
+ if (query.length < 2) {
+ this.handleNoSearch(query);
+ } else {
+ this.handleActualSearch(query);
+ }
}
-
- this.setState({ loading: true, query });
- return searchUsers({ q: query })
- .then(this.handleSearchResult, () => {})
- .catch(() => this.setState({ loading: false }));
};
- handleSearchResult = ({ users }: { users: T.UserBase[] }) => {
- const activeUsers = users.filter(isUserActive);
- this.setState(({ highlighted }) => {
- if (activeUsers.length === 0) {
- highlighted = undefined;
- } else {
- const findHighlited = activeUsers.find(u => highlighted && u.login === highlighted.login);
- highlighted = findHighlited || activeUsers[0];
- }
+ handleNoSearch = (query: string) => {
+ const { allowCurrentUserSelection, loggedInUser } = this.props;
- return {
- highlighted,
- loading: false,
- open: true,
- suggestedUsers: activeUsers
- };
+ this.setState({
+ loading: false,
+ open: allowCurrentUserSelection,
+ query,
+ suggestedUsers: allowCurrentUserSelection ? [loggedInUser] : []
});
};
+ handleActualSearch = (query: string) => {
+ this.setState({ loading: true, query });
+ searchUsers({ q: query })
+ .then(result => {
+ if (this.mounted) {
+ this.setState({
+ loading: false,
+ query,
+ open: true,
+ suggestedUsers: result.users.filter(isUserActive) as T.UserActive[]
+ });
+ }
+ })
+ .catch(() => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ });
+ };
+
handleKeyDown = (event: React.KeyboardEvent) => {
switch (event.keyCode) {
case KeyCodes.Enter:
event.preventDefault();
- this.handleSelectHighlighted();
+ this.selectHighlighted();
break;
case KeyCodes.UpArrow:
event.preventDefault();
- this.handleHighlightPrevious();
+ this.highlightPrevious();
break;
case KeyCodes.DownArrow:
event.preventDefault();
- this.handleHighlightNext();
+ this.highlightNext();
break;
}
};
+ getCurrentIndex = () => {
+ const { highlighted, suggestedUsers } = this.state;
+
+ return highlighted
+ ? suggestedUsers.findIndex(suggestion => suggestion.login === highlighted.login)
+ : -1;
+ };
+
highlightIndex = (index: number) => {
const { suggestedUsers } = this.state;
- if (suggestedUsers && suggestedUsers.length > 0) {
+
+ if (suggestedUsers.length > 0) {
if (index < 0) {
index = suggestedUsers.length - 1;
} else if (index >= suggestedUsers.length) {
index = 0;
}
- this.setState({
- highlighted: suggestedUsers[index]
- });
+
+ this.setState({ highlighted: suggestedUsers[index] });
}
};
- handleHighlightPrevious = () => {
+ highlightPrevious = () => {
this.highlightIndex(this.getCurrentIndex() - 1);
};
- handleHighlightNext = () => {
+ highlightNext = () => {
this.highlightIndex(this.getCurrentIndex() + 1);
};
- handleSelectHighlighted = () => {
+ selectHighlighted = () => {
const { highlighted } = this.state;
+
if (highlighted !== undefined) {
- this.handleSelect(highlighted);
+ this.props.onSelect(highlighted);
}
};
- handleSelect = (selectedUser: T.UserActive) => {
- this.setState({
- open: false,
- query: selectedUser.name
- });
- this.props.onSelect(selectedUser);
- };
-
render() {
const { highlighted, loading, open, query, suggestedUsers } = this.state;
+
return (
- <HotspotAssigneeSelectRenderer
+ <AssigneeSelectionRenderer
highlighted={highlighted}
loading={loading}
onKeyDown={this.handleKeyDown}
onSearch={this.handleSearch}
- onSelect={this.handleSelect}
+ onSelect={this.props.onSelect}
open={open}
query={query}
suggestedUsers={suggestedUsers}
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelectRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelectionRenderer.tsx
index 2df77348d12..2132adb5998 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotAssigneeSelectRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelectionRenderer.tsx
@@ -24,8 +24,8 @@ import SearchBox from 'sonar-ui-common/components/controls/SearchBox';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { PopupPlacement } from 'sonar-ui-common/components/ui/popups';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import Avatar from '../../../components/ui/Avatar';
-import './HotspotAssigneeSelect.css';
+import Avatar from '../../../../components/ui/Avatar';
+import './AssigneeSelection.css';
export interface HotspotAssigneeSelectRendererProps {
highlighted?: T.UserActive;
@@ -38,19 +38,21 @@ export interface HotspotAssigneeSelectRendererProps {
suggestedUsers?: T.UserActive[];
}
-export default function HotspotAssigneeSelectRenderer(props: HotspotAssigneeSelectRendererProps) {
+export default function AssigneeSelectionRenderer(props: HotspotAssigneeSelectRendererProps) {
const { highlighted, loading, open, query, suggestedUsers } = props;
return (
<>
- <SearchBox
- autoFocus={true}
- onChange={props.onSearch}
- onKeyDown={props.onKeyDown}
- placeholder={translate('hotspots.form.select_user')}
- value={query}
- />
+ <div className="display-flex-center">
+ <SearchBox
+ autoFocus={true}
+ onChange={props.onSearch}
+ onKeyDown={props.onKeyDown}
+ placeholder={translate('hotspots.form.select_user')}
+ value={query}
+ />
- {loading && <DeferredSpinner />}
+ {loading && <DeferredSpinner className="spacer-left" />}
+ </div>
{!loading && open && (
<div className="position-relative">
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/Assignee-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/Assignee-test.tsx
new file mode 100644
index 00000000000..79d58a59563
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/Assignee-test.tsx
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
+import { assignSecurityHotspot } from '../../../../../api/security-hotspots';
+import { mockHotspot } from '../../../../../helpers/mocks/security-hotspots';
+import { mockCurrentUser, mockUser } from '../../../../../helpers/testMocks';
+import { HotspotStatus } from '../../../../../types/security-hotspots';
+import { Assignee } from '../Assignee';
+import AssigneeRenderer from '../AssigneeRenderer';
+
+jest.mock('../../../../../api/security-hotspots', () => ({
+ assignSecurityHotspot: jest.fn()
+}));
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+ expect(
+ shallowRender({ hotspot: mockHotspot({ status: HotspotStatus.TO_REVIEW }) })
+ ).toMatchSnapshot('can edit');
+});
+
+it('should handle edition event correctly', () => {
+ const wrapper = shallowRender();
+
+ wrapper
+ .find(AssigneeRenderer)
+ .props()
+ .onEnterEditionMode();
+ expect(wrapper.state().editing).toBe(true);
+
+ wrapper
+ .find(AssigneeRenderer)
+ .props()
+ .onExitEditionMode();
+ expect(wrapper.state().editing).toBe(false);
+});
+
+it('should handle assign event correctly', async () => {
+ const hotspot = mockHotspot();
+ const onAssigneeChange = jest.fn();
+ const user = mockUser() as T.UserActive;
+
+ const wrapper = shallowRender({ hotspot, onAssigneeChange });
+
+ (assignSecurityHotspot as jest.Mock).mockResolvedValueOnce({});
+ wrapper
+ .find(AssigneeRenderer)
+ .props()
+ .onAssign(user);
+
+ expect(wrapper.state().loading).toBe(true);
+ expect(assignSecurityHotspot).toHaveBeenCalledWith(hotspot.key, { assignee: user.login });
+
+ await waitAndUpdate(wrapper);
+
+ expect(wrapper.state()).toEqual({
+ editing: false,
+ loading: false
+ });
+ expect(onAssigneeChange).toHaveBeenCalled();
+});
+
+function shallowRender(props?: Partial<Assignee['props']>) {
+ return shallow<Assignee>(
+ <Assignee
+ currentUser={mockCurrentUser()}
+ hotspot={mockHotspot()}
+ onAssigneeChange={jest.fn()}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeRenderer-test.tsx
new file mode 100644
index 00000000000..6e618962740
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeRenderer-test.tsx
@@ -0,0 +1,85 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { EditButton } from 'sonar-ui-common/components/controls/buttons';
+import OutsideClickHandler from 'sonar-ui-common/components/controls/OutsideClickHandler';
+import { click } from 'sonar-ui-common/helpers/testUtils';
+import { mockLoggedInUser, mockUser } from '../../../../../helpers/testMocks';
+import AssigneeRenderer, { AssigneeRendererProps } from '../AssigneeRenderer';
+import AssigneeSelection from '../AssigneeSelection';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('not editing');
+ expect(shallowRender({ editing: true })).toMatchSnapshot('editing');
+ expect(shallowRender({ assignee: undefined })).toMatchSnapshot('without current assignee');
+ expect(shallowRender({ assignee: mockUser({ active: true }) })).toMatchSnapshot(
+ 'with active assignee'
+ );
+
+ expect(shallowRender({ loggedInUser: undefined }).find(EditButton).length).toBe(0);
+ expect(shallowRender({ canEdit: false }).find(EditButton).length).toBe(0);
+ expect(
+ shallowRender({ editing: true, assignee: mockUser() })
+ .find(AssigneeSelection)
+ .props().allowCurrentUserSelection
+ ).toBe(true);
+});
+
+it('should propagate calls correctly', () => {
+ const onAssign = jest.fn();
+ const onEnterEditionMode = jest.fn();
+ const onExitEditionMode = jest.fn();
+ const wrapper = shallowRender({ onAssign, onEnterEditionMode, onExitEditionMode });
+
+ click(wrapper.find(EditButton));
+ expect(onEnterEditionMode).toHaveBeenCalled();
+
+ const newAssignee = mockUser({ login: 'toto' });
+ wrapper.setProps({ editing: true });
+ wrapper
+ .find(AssigneeSelection)
+ .props()
+ .onSelect(newAssignee as T.UserActive);
+ expect(onAssign).toHaveBeenCalledWith(newAssignee);
+
+ wrapper
+ .find(OutsideClickHandler)
+ .props()
+ .onClickOutside();
+ expect(onExitEditionMode).toHaveBeenCalled();
+});
+
+function shallowRender(props?: Partial<AssigneeRendererProps>) {
+ return shallow<AssigneeRendererProps>(
+ <AssigneeRenderer
+ assignee={mockLoggedInUser()}
+ canEdit={true}
+ editing={false}
+ loading={false}
+ loggedInUser={mockLoggedInUser()}
+ onAssign={jest.fn()}
+ onEnterEditionMode={jest.fn()}
+ onExitEditionMode={jest.fn()}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelect-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelection-test.tsx
index 7d5797d0be6..630b23cd44a 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelect-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelection-test.tsx
@@ -21,11 +21,11 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyCodes } from 'sonar-ui-common/helpers/keycodes';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { searchUsers } from '../../../../api/users';
-import { mockUser } from '../../../../helpers/testMocks';
-import HotspotAssigneeSelect from '../HotspotAssigneeSelect';
+import { searchUsers } from '../../../../../api/users';
+import { mockLoggedInUser, mockUser } from '../../../../../helpers/testMocks';
+import AssigneeSelection from '../AssigneeSelection';
-jest.mock('../../../../api/users', () => ({
+jest.mock('../../../../../api/users', () => ({
searchUsers: jest.fn().mockResolvedValue([])
}));
@@ -77,6 +77,7 @@ it('should handle search', async () => {
const onSelect = jest.fn();
const wrapper = shallowRender({ onSelect });
+ expect(wrapper.state().suggestedUsers.length).toBe(0);
wrapper.instance().handleSearch('j');
expect(searchUsers).not.toBeCalled();
@@ -88,18 +89,40 @@ it('should handle search', async () => {
await waitAndUpdate(wrapper);
- expect(wrapper.state().highlighted).toBe(users[0]);
expect(wrapper.state().loading).toBe(false);
expect(wrapper.state().open).toBe(true);
expect(wrapper.state().suggestedUsers).toHaveLength(3);
jest.clearAllMocks();
- await wrapper.instance().handleSearch('');
+ wrapper.instance().handleSearch('');
expect(searchUsers).not.toBeCalled();
- expect(onSelect).toBeCalledWith(undefined);
+ expect(wrapper.state().suggestedUsers.length).toBe(0);
});
-function shallowRender(props?: Partial<HotspotAssigneeSelect['props']>) {
- return shallow<HotspotAssigneeSelect>(<HotspotAssigneeSelect onSelect={jest.fn()} {...props} />);
+it('should allow current user selection', async () => {
+ const loggedInUser = mockLoggedInUser();
+ const users = [mockUser({ login: '1' }), mockUser({ login: '2' }), mockUser({ login: '3' })];
+ (searchUsers as jest.Mock).mockResolvedValueOnce({ users });
+
+ const wrapper = shallowRender({ allowCurrentUserSelection: true, loggedInUser });
+ expect(wrapper.state().suggestedUsers[0]).toBe(loggedInUser);
+
+ wrapper.instance().handleSearch('jo');
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().suggestedUsers).toHaveLength(3);
+
+ wrapper.instance().handleSearch('');
+ expect(wrapper.state().suggestedUsers[0]).toBe(loggedInUser);
+});
+
+function shallowRender(props?: Partial<AssigneeSelection['props']>) {
+ return shallow<AssigneeSelection>(
+ <AssigneeSelection
+ allowCurrentUserSelection={false}
+ loggedInUser={mockLoggedInUser()}
+ onSelect={jest.fn()}
+ {...props}
+ />
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelectRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelectionRenderer-test.tsx
index c067c3dcfa0..678af97de90 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotAssigneeSelectRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelectionRenderer-test.tsx
@@ -19,10 +19,10 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { mockUser } from '../../../../helpers/testMocks';
-import HotspotAssigneeSelectRenderer, {
+import { mockUser } from '../../../../../helpers/testMocks';
+import AssigneeSelectionRenderer, {
HotspotAssigneeSelectRendererProps
-} from '../HotspotAssigneeSelectRenderer';
+} from '../AssigneeSelectionRenderer';
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
@@ -58,7 +58,7 @@ it('should call onSelect when clicked', () => {
function shallowRender(props?: Partial<HotspotAssigneeSelectRendererProps>) {
return shallow(
- <HotspotAssigneeSelectRenderer
+ <AssigneeSelectionRenderer
loading={false}
onKeyDown={jest.fn()}
onSearch={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/Assignee-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/Assignee-test.tsx.snap
new file mode 100644
index 00000000000..1cb486f7a56
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/Assignee-test.tsx.snap
@@ -0,0 +1,39 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<AssigneeRenderer
+ assignee={
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ }
+ }
+ canEdit={false}
+ editing={false}
+ loading={false}
+ onAssign={[Function]}
+ onEnterEditionMode={[Function]}
+ onExitEditionMode={[Function]}
+/>
+`;
+
+exports[`should render correctly: can edit 1`] = `
+<AssigneeRenderer
+ assignee={
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ }
+ }
+ canEdit={true}
+ editing={false}
+ loading={false}
+ onAssign={[Function]}
+ onEnterEditionMode={[Function]}
+ onExitEditionMode={[Function]}
+/>
+`;
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeRenderer-test.tsx.snap
new file mode 100644
index 00000000000..2b45d1fb5f4
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeRenderer-test.tsx.snap
@@ -0,0 +1,135 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: editing 1`] = `
+<div
+ className="big-spacer-top display-flex-center"
+>
+ <span>
+ assignee
+ :
+ </span>
+ <span
+ className="spacer-left"
+ >
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <EscKeydownHandler
+ onKeydown={[MockFunction]}
+ >
+ <OutsideClickHandler
+ onClickOutside={[MockFunction]}
+ >
+ <AssigneeSelection
+ allowCurrentUserSelection={false}
+ loggedInUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
+ }
+ }
+ onSelect={[MockFunction]}
+ />
+ </OutsideClickHandler>
+ </EscKeydownHandler>
+ </DeferredSpinner>
+ </span>
+</div>
+`;
+
+exports[`should render correctly: not editing 1`] = `
+<div
+ className="big-spacer-top display-flex-center"
+>
+ <span>
+ assignee
+ :
+ </span>
+ <span
+ className="spacer-left"
+ >
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <div
+ className="display-flex-center"
+ >
+ <strong>
+ user.x_deleted.Skywalker
+ </strong>
+ <EditButton
+ className="spacer-left"
+ onClick={[MockFunction]}
+ />
+ </div>
+ </DeferredSpinner>
+ </span>
+</div>
+`;
+
+exports[`should render correctly: with active assignee 1`] = `
+<div
+ className="big-spacer-top display-flex-center"
+>
+ <span>
+ assignee
+ :
+ </span>
+ <span
+ className="spacer-left"
+ >
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <div
+ className="display-flex-center"
+ >
+ <strong>
+ John Doe
+ </strong>
+ <EditButton
+ className="spacer-left"
+ onClick={[MockFunction]}
+ />
+ </div>
+ </DeferredSpinner>
+ </span>
+</div>
+`;
+
+exports[`should render correctly: without current assignee 1`] = `
+<div
+ className="big-spacer-top display-flex-center"
+>
+ <span>
+ assignee
+ :
+ </span>
+ <span
+ className="spacer-left"
+ >
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <div
+ className="display-flex-center"
+ >
+ <strong>
+ unassigned
+ </strong>
+ <EditButton
+ className="spacer-left"
+ onClick={[MockFunction]}
+ />
+ </div>
+ </DeferredSpinner>
+ </span>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelect-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelection-test.tsx.snap
index 3d3a988ea50..a0b29106d14 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelect-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelection-test.tsx.snap
@@ -1,11 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<HotspotAssigneeSelectRenderer
+<AssigneeSelectionRenderer
loading={false}
onKeyDown={[Function]}
onSearch={[Function]}
- onSelect={[Function]}
+ onSelect={[MockFunction]}
open={false}
+ suggestedUsers={Array []}
/>
`;
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelectRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelectionRenderer-test.tsx.snap
index f86f59f3bdc..93774eb9f81 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotAssigneeSelectRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/__snapshots__/AssigneeSelectionRenderer-test.tsx.snap
@@ -2,37 +2,50 @@
exports[`should render correctly 1`] = `
<Fragment>
- <SearchBox
- autoFocus={true}
- onChange={[MockFunction]}
- onKeyDown={[MockFunction]}
- placeholder="hotspots.form.select_user"
- />
+ <div
+ className="display-flex-center"
+ >
+ <SearchBox
+ autoFocus={true}
+ onChange={[MockFunction]}
+ onKeyDown={[MockFunction]}
+ placeholder="hotspots.form.select_user"
+ />
+ </div>
</Fragment>
`;
exports[`should render correctly: loading 1`] = `
<Fragment>
- <SearchBox
- autoFocus={true}
- onChange={[MockFunction]}
- onKeyDown={[MockFunction]}
- placeholder="hotspots.form.select_user"
- />
- <DeferredSpinner
- timeout={100}
- />
+ <div
+ className="display-flex-center"
+ >
+ <SearchBox
+ autoFocus={true}
+ onChange={[MockFunction]}
+ onKeyDown={[MockFunction]}
+ placeholder="hotspots.form.select_user"
+ />
+ <DeferredSpinner
+ className="spacer-left"
+ timeout={100}
+ />
+ </div>
</Fragment>
`;
exports[`should render correctly: open 1`] = `
<Fragment>
- <SearchBox
- autoFocus={true}
- onChange={[MockFunction]}
- onKeyDown={[MockFunction]}
- placeholder="hotspots.form.select_user"
- />
+ <div
+ className="display-flex-center"
+ >
+ <SearchBox
+ autoFocus={true}
+ onChange={[MockFunction]}
+ onKeyDown={[MockFunction]}
+ placeholder="hotspots.form.select_user"
+ />
+ </div>
<div
className="position-relative"
>
@@ -53,12 +66,16 @@ exports[`should render correctly: open 1`] = `
exports[`should render correctly: open with results 1`] = `
<Fragment>
- <SearchBox
- autoFocus={true}
- onChange={[MockFunction]}
- onKeyDown={[MockFunction]}
- placeholder="hotspots.form.select_user"
- />
+ <div
+ className="display-flex-center"
+ >
+ <SearchBox
+ autoFocus={true}
+ onChange={[MockFunction]}
+ onKeyDown={[MockFunction]}
+ placeholder="hotspots.form.select_user"
+ />
+ </div>
<div
className="position-relative"
>
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/styles.css b/server/sonar-web/src/main/js/apps/security-hotspots/styles.css
index 9a327c158d7..9a327c158d7 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/styles.css
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/styles.css
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/utils.ts b/server/sonar-web/src/main/js/apps/security-hotspots/utils.ts
index cfa1e81f5ed..cfa1e81f5ed 100644
--- a/server/sonar-web/src/main/js/apps/securityHotspots/utils.ts
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/utils.ts