diff options
author | stanislavh <stanislav.honcharov@sonarsource.com> | 2023-04-18 14:29:18 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-04-25 20:03:00 +0000 |
commit | 0776b019cd2e044441a6cc8c0f2fb61405264a19 (patch) | |
tree | 8dd464abfa948e2f430ec52317dc971deb818e57 /server/sonar-web/src | |
parent | 4df28629b1864e169caa7dec71dbac611c34ac1b (diff) | |
download | sonarqube-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')
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', |