aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
authorstanislavh <stanislav.honcharov@sonarsource.com>2023-04-18 14:29:18 +0200
committersonartech <sonartech@sonarsource.com>2023-04-25 20:03:00 +0000
commit0776b019cd2e044441a6cc8c0f2fb61405264a19 (patch)
tree8dd464abfa948e2f430ec52317dc971deb818e57 /server/sonar-web/src
parent4df28629b1864e169caa7dec71dbac611c34ac1b (diff)
downloadsonarqube-0776b019cd2e044441a6cc8c0f2fb61405264a19.tar.gz
sonarqube-0776b019cd2e044441a6cc8c0f2fb61405264a19.zip
SONAR-19069 Disable the option to change an issue type in issues list and issue view
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts6
-rw-r--r--server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx28
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx63
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-it.tsx12
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx6
-rw-r--r--server/sonar-web/src/main/js/components/issue/Issue.css4
-rw-r--r--server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx13
-rw-r--r--server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx14
-rw-r--r--server/sonar-web/src/main/js/components/issue/components/IssueType.tsx97
-rw-r--r--server/sonar-web/src/main/js/types/issues.ts1
10 files changed, 18 insertions, 226 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
index 46bedfce13d..73e33083b28 100644
--- a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
@@ -62,8 +62,8 @@ import {
editIssueComment,
getIssueChangelog,
getIssueFlowSnippets,
- searchIssueTags,
searchIssues,
+ searchIssueTags,
setIssueAssignee,
setIssueSeverity,
setIssueTags,
@@ -528,11 +528,11 @@ export default class IssuesServiceMock {
}
handleBulkChangeIssues = (issueKeys: string[], query: RequestData) => {
- //For now we only check for issue type change.
+ //For now we only check for issue severity change.
this.list
.filter((i) => issueKeys.includes(i.issue.key))
.forEach((data) => {
- data.issue.type = query.set_type;
+ data.issue.severity = query.set_severity;
});
return this.reply({});
};
diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
index e90b41b0a4e..d90c6b6f4f8 100644
--- a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
@@ -246,12 +246,6 @@ describe('issues app', () => {
// Check that we bulk change the selected issue
const issueBoxFixThat = within(screen.getByRole('region', { name: 'Fix that' }));
- expect(
- issueBoxFixThat.getByRole('button', {
- name: 'issue.type.type_x_click_to_change.issue.type.CODE_SMELL',
- })
- ).toBeInTheDocument();
-
await user.click(
screen.getByRole('checkbox', { name: 'issues.action_select.label.Fix that' })
);
@@ -261,14 +255,14 @@ describe('issues app', () => {
await user.keyboard('New Comment');
expect(screen.getByRole('button', { name: 'apply' })).toBeDisabled();
- await selectEvent.select(screen.getByRole('combobox', { name: 'issue.set_type' }), [
- 'issue.type.BUG',
+ await selectEvent.select(screen.getByRole('combobox', { name: 'issue.set_severity' }), [
+ 'severity.BLOCKER',
]);
await user.click(screen.getByRole('button', { name: 'apply' }));
expect(
issueBoxFixThat.getByRole('button', {
- name: 'issue.type.type_x_click_to_change.issue.type.BUG',
+ name: 'issue.severity.severity_x_click_to_change.severity.BLOCKER',
})
).toBeInTheDocument();
});
@@ -613,22 +607,6 @@ describe('issues item', () => {
// Get a specific issue list item
const listItem = within(await screen.findByRole('region', { name: 'Fix that' }));
- // Change issue type
- await user.click(
- listItem.getByRole('button', {
- name: `issue.type.type_x_click_to_change.issue.type.CODE_SMELL`,
- })
- );
- expect(listItem.getByText('issue.type.BUG')).toBeInTheDocument();
- expect(listItem.getByText('issue.type.VULNERABILITY')).toBeInTheDocument();
-
- await user.click(listItem.getByText('issue.type.VULNERABILITY'));
- expect(
- listItem.getByRole('button', {
- name: `issue.type.type_x_click_to_change.issue.type.VULNERABILITY`,
- })
- ).toBeInTheDocument();
-
// Change issue severity
expect(listItem.getByText('severity.MAJOR')).toBeInTheDocument();
diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
index 1a31ccfb7ff..fb3e941c7bd 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
@@ -33,14 +33,13 @@ import Select, {
LabelValueSelectOption,
SearchSelect,
} from '../../../components/controls/Select';
-import IssueTypeIcon from '../../../components/icons/IssueTypeIcon';
import SeverityHelper from '../../../components/shared/SeverityHelper';
import { Alert } from '../../../components/ui/Alert';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { SEVERITIES } from '../../../helpers/constants';
import { throwGlobalError } from '../../../helpers/error';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { Component, Dict, Issue, IssueType, Paging } from '../../../types/types';
+import { Component, Dict, Issue, Paging } from '../../../types/types';
import { CurrentUser } from '../../../types/users';
import AssigneeSelect, { AssigneeOption } from './AssigneeSelect';
@@ -67,7 +66,6 @@ interface FormFields {
removeTags?: Array<{ label: string; value: string }>;
severity?: string;
transition?: string;
- type?: string;
}
interface State extends FormFields {
@@ -85,30 +83,10 @@ enum InputField {
assignee = 'assignee',
removeTags = 'removeTags',
severity = 'severity',
- type = 'type',
}
export const MAX_PAGE_SIZE = 500;
-function typeFieldTypeRenderer(option: LabelValueSelectOption) {
- return (
- <div className="display-flex-center">
- <IssueTypeIcon query={option.value} />
- <span className="little-spacer-left">{option.label}</span>
- </div>
- );
-}
-
-function TypeFieldOptionComponent(props: OptionProps<LabelValueSelectOption, false>) {
- return <components.Option {...props}>{typeFieldTypeRenderer(props.data)}</components.Option>;
-}
-
-function TypeFieldSingleValueComponent(props: SingleValueProps<LabelValueSelectOption, false>) {
- return (
- <components.SingleValue {...props}>{typeFieldTypeRenderer(props.data)}</components.SingleValue>
- );
-}
-
function SeverityFieldOptionComponent(props: OptionProps<LabelValueSelectOption, false>) {
return (
<components.Option {...props}>
@@ -218,7 +196,6 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
remove_tags: this.state.removeTags && this.state.removeTags.map((t) => t.value).join(),
sendNotifications: this.state.notifications,
set_severity: this.state.severity,
- set_type: this.state.type,
},
(x) => x !== undefined
);
@@ -258,15 +235,14 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
}
canSubmit = () => {
- const { addTags, assignee, removeTags, severity, transition, type } = this.state;
+ const { addTags, assignee, removeTags, severity, transition } = this.state;
return Boolean(
(addTags && addTags.length > 0) ||
(removeTags && removeTags.length > 0) ||
assignee ||
severity ||
- transition ||
- type
+ transition
);
};
@@ -331,38 +307,6 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
return this.renderField(field, 'issue.assign.formlink', affected, input);
};
- renderTypeField = () => {
- const affected = this.state.issues.filter(hasAction('set_type')).length;
- const field = InputField.type;
-
- if (affected === 0) {
- return null;
- }
-
- const types: IssueType[] = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
- const options: LabelValueSelectOption[] = types.map((type) => ({
- label: translate('issue.type', type),
- value: type,
- }));
-
- const input = (
- <Select
- className="input-super-large"
- inputId={`issues-bulk-change-${field}`}
- isClearable={true}
- isSearchable={false}
- components={{
- Option: TypeFieldOptionComponent,
- SingleValue: TypeFieldSingleValueComponent,
- }}
- onChange={this.handleSelectFieldChange('type')}
- options={options}
- />
- );
-
- return this.renderField(field, 'issue.set_type', affected, input);
- };
-
renderSeverityField = () => {
const affected = this.state.issues.filter(hasAction('set_severity')).length;
const field = InputField.severity;
@@ -519,7 +463,6 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
)}
{this.renderAssigneeField()}
- {this.renderTypeField()}
{this.renderSeverityField()}
{this.renderTagsField(InputField.addTags, 'issue.add_tags', true)}
{this.renderTagsField(InputField.removeTags, 'issue.remove_tags', false)}
diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-it.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-it.tsx
index d629ed13c86..bfa23365190 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-it.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-it.tsx
@@ -25,7 +25,6 @@ import { bulkChangeIssues } from '../../../../api/issues';
import { SEVERITIES } from '../../../../helpers/constants';
import { mockIssue, mockLoggedInUser } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
-import { IssueType } from '../../../../types/issues';
import { Issue } from '../../../../types/types';
import BulkChangeModal, { MAX_PAGE_SIZE } from '../BulkChangeModal';
@@ -57,10 +56,7 @@ it('should display warning when too many issues are passed', async () => {
expect(await screen.findByText('issue_bulk_change.max_issues_reached')).toBeInTheDocument();
});
-it.each([
- ['type', 'set_type'],
- ['severity', 'set_severity'],
-])('should render select for %s', async (_field, action) => {
+it.each([['severity', 'set_severity']])('should render select for %s', async (_field, action) => {
renderBulkChangeModal([mockIssue(false, { actions: [action] })]);
expect(await screen.findByText('issue.' + action)).toBeInTheDocument();
@@ -143,11 +139,6 @@ it('should properly submit', async () => {
'tag2',
]);
- // Select a type
- await selectEvent.select(screen.getByRole('combobox', { name: 'issue.set_type' }), [
- `issue.type.CODE_SMELL`,
- ]);
-
// Select a severity
await selectEvent.select(screen.getByRole('combobox', { name: 'issue.set_severity' }), [
`severity.${SEVERITIES[0]}`,
@@ -175,7 +166,6 @@ it('should properly submit', async () => {
set_severity: 'BLOCKER',
add_tags: 'tag1,tag2',
do_transition: 'Transition2',
- set_type: IssueType.CodeSmell,
sendNotifications: true,
});
});
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx
index 1439f083790..60f2ca41ac2 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx
@@ -145,12 +145,6 @@ it('should be able to interact with issue action', async () => {
const user = userEvent.setup();
renderSourceViewer();
- //Open Issue type
- await user.click(
- await screen.findByRole('button', { name: 'issue.type.type_x_click_to_change.issue.type.BUG' })
- );
- expect(ui.codeSmellTypeButton.get()).toBeInTheDocument();
-
// Open severity
await user.click(
await screen.findByRole('button', {
diff --git a/server/sonar-web/src/main/js/components/issue/Issue.css b/server/sonar-web/src/main/js/components/issue/Issue.css
index 5be5920c71f..a5c12dfd9de 100644
--- a/server/sonar-web/src/main/js/components/issue/Issue.css
+++ b/server/sonar-web/src/main/js/components/issue/Issue.css
@@ -89,6 +89,10 @@
display: flex;
}
+.issue-meta.disabled {
+ color: var(--gray60);
+}
+
.issue-meta + .issue-meta {
margin-left: var(--gridSize);
}
diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx b/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
index 0f6d9799898..8d6b59b8981 100644
--- a/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
+++ b/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
@@ -125,19 +125,6 @@ describe('rendering', () => {
});
describe('updating', () => {
- it('should allow updating the type', async () => {
- const { ui } = getPageObject();
- const issue = mockRawIssue(false, {
- type: IssueType.Bug,
- actions: [IssueActions.SetType],
- });
- issuesHandler.setIssueList([{ issue, snippets: {} }]);
- renderIssue({ issue: mockIssue(false, { ...pick(issue, 'actions', 'key', 'type') }) });
-
- await ui.updateType(IssueType.Bug, IssueType.CodeSmell);
- expect(ui.updateTypeBtn(IssueType.CodeSmell).get()).toBeInTheDocument();
- });
-
it('should allow updating the severity', async () => {
const { ui } = getPageObject();
const issue = mockRawIssue(false, {
diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx
index 1153e95b6c8..fbf9d08f5c4 100644
--- a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx
+++ b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx
@@ -27,13 +27,13 @@ import {
IssueType as IssueTypeEnum,
} from '../../../types/issues';
import { Issue, RawQuery } from '../../../types/types';
+import IssueTypeIcon from '../../icons/IssueTypeIcon';
import { updateIssue } from '../actions';
import IssueAssign from './IssueAssign';
import IssueCommentAction from './IssueCommentAction';
import IssueSeverity from './IssueSeverity';
import IssueTags from './IssueTags';
import IssueTransition from './IssueTransition';
-import IssueType from './IssueType';
interface Props {
issue: Issue;
@@ -98,21 +98,15 @@ export default class IssueActionsBar extends React.PureComponent<Props, State> {
const canAssign = issue.actions.includes(IssueActions.Assign);
const canComment = issue.actions.includes(IssueActions.Comment);
const canSetSeverity = issue.actions.includes(IssueActions.SetSeverity);
- const canSetType = issue.actions.includes(IssueActions.SetType);
const canSetTags = issue.actions.includes(IssueActions.SetTags);
const hasTransitions = issue.transitions.length > 0;
return (
<div className={classNames(className, 'issue-actions')}>
<div className="issue-meta-list">
- <div className="issue-meta">
- <IssueType
- canSetType={canSetType}
- isOpen={this.props.currentPopup === 'set-type' && canSetType}
- issue={issue}
- setIssueProperty={this.setIssueProperty}
- togglePopup={this.props.togglePopup}
- />
+ <div className="issue-meta display-flex-center disabled">
+ <IssueTypeIcon className="little-spacer-right" query={issue.type} />
+ {translate('issue.type', issue.type)}
</div>
<div className="issue-meta">
<IssueSeverity
diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueType.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueType.tsx
deleted file mode 100644
index 048b1d3b4cd..00000000000
--- a/server/sonar-web/src/main/js/components/issue/components/IssueType.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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 { setIssueType } from '../../../api/issues';
-import { colors } from '../../../app/theme';
-import { ButtonLink } from '../../../components/controls/buttons';
-import Toggler from '../../../components/controls/Toggler';
-import DropdownIcon from '../../../components/icons/DropdownIcon';
-import IssueTypeIcon from '../../../components/icons/IssueTypeIcon';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { IssueResponse } from '../../../types/issues';
-import { Issue, RawQuery } from '../../../types/types';
-import SetTypePopup from '../popups/SetTypePopup';
-
-interface Props {
- canSetType: boolean;
- isOpen: boolean;
- issue: Pick<Issue, 'type'>;
- setIssueProperty: (
- property: keyof Issue,
- popup: string,
- apiCall: (query: RawQuery) => Promise<IssueResponse>,
- value: string
- ) => void;
- togglePopup: (popup: string, show?: boolean) => void;
-}
-
-export default class IssueType extends React.PureComponent<Props> {
- toggleSetType = (open?: boolean) => {
- this.props.togglePopup('set-type', open);
- };
-
- setType = (type: string) => {
- this.props.setIssueProperty('type', 'set-type', setIssueType, type);
- };
-
- handleClose = () => {
- this.toggleSetType(false);
- };
-
- render() {
- const { issue } = this.props;
- if (this.props.canSetType) {
- return (
- <div className="dropdown">
- <Toggler
- onRequestClose={this.handleClose}
- open={this.props.isOpen && this.props.canSetType}
- overlay={<SetTypePopup issue={issue} onSelect={this.setType} />}
- >
- <ButtonLink
- aria-label={translateWithParameters(
- 'issue.type.type_x_click_to_change',
- translate('issue.type', issue.type)
- )}
- aria-expanded={this.props.isOpen}
- className="issue-action issue-action-with-options js-issue-set-type"
- onClick={this.toggleSetType}
- >
- <IssueTypeIcon
- className="little-spacer-right"
- fill={colors.baseFontColor}
- query={issue.type}
- />
- {translate('issue.type', issue.type)}
- <DropdownIcon className="little-spacer-left" />
- </ButtonLink>
- </Toggler>
- </div>
- );
- }
-
- return (
- <span>
- <IssueTypeIcon className="little-spacer-right" query={issue.type} />
- {translate('issue.type', issue.type)}
- </span>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/types/issues.ts b/server/sonar-web/src/main/js/types/issues.ts
index 04ec365eaf1..f812988ce80 100644
--- a/server/sonar-web/src/main/js/types/issues.ts
+++ b/server/sonar-web/src/main/js/types/issues.ts
@@ -94,7 +94,6 @@ export enum IssueStatus {
}
export enum IssueActions {
- SetType = 'set_type',
SetTags = 'set_tags',
SetSeverity = 'set_severity',
Comment = 'comment',