From 3acf8e51e635be1e900d7d9cd23007f34ae96d8d Mon Sep 17 00:00:00 2001 From: stanislavh Date: Thu, 31 Oct 2024 09:40:03 +0100 Subject: SONAR-23300 Add popover to temporal issue filters --- .../apps/issues/sidebar/QGMetricsMismatchHelp.tsx | 49 ++++++++++++++ .../apps/issues/sidebar/SoftwareQualityFacet.tsx | 2 + .../src/main/js/apps/issues/sidebar/TypeFacet.tsx | 2 + .../apps/issues/sidebar/__tests__/Sidebar-it.tsx | 16 ++++- .../main/js/components/facets/SeverityFacet.tsx | 43 +++++++----- .../js/components/facets/StandardSeverityFacet.tsx | 2 + .../main/js/design-system/components/FacetBox.tsx | 78 +++++++++++----------- 7 files changed, 135 insertions(+), 57 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/issues/sidebar/QGMetricsMismatchHelp.tsx (limited to 'server/sonar-web') diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/QGMetricsMismatchHelp.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/QGMetricsMismatchHelp.tsx new file mode 100644 index 00000000000..f2e99fd3c77 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/QGMetricsMismatchHelp.tsx @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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 { Button, ButtonVariety, IconQuestionMark, Popover } from '@sonarsource/echoes-react'; +import { useIntl } from 'react-intl'; +import DocumentationLink from '../../../components/common/DocumentationLink'; +import { DocLink } from '../../../helpers/doc-links'; +import { useStandardExperienceMode } from '../../../queries/settings'; + +export default function QGMetricsMismatchHelp() { + const intl = useIntl(); + const { data: isStandardMode } = useStandardExperienceMode(); + return ( + + {intl.formatMessage({ id: 'issues.qg_mismatch.link' })} + + } + > + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/SoftwareQualityFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/SoftwareQualityFacet.tsx index 34a1edbf186..310729c94c9 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/SoftwareQualityFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/SoftwareQualityFacet.tsx @@ -20,6 +20,7 @@ import { SOFTWARE_QUALITIES } from '../../../helpers/constants'; import { SoftwareQuality } from '../../../types/clean-code-taxonomy'; +import QGMetricsMismatchHelp from './QGMetricsMismatchHelp'; import { CommonProps, SimpleListStyleFacet } from './SimpleListStyleFacet'; interface Props extends CommonProps { @@ -35,6 +36,7 @@ export function SoftwareQualityFacet(props: Props) { itemNamePrefix="software_quality" listItems={SOFTWARE_QUALITIES} selectedItems={qualities} + help={Boolean(props.secondLine) && } {...rest} /> ); diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx index a96858bd4bc..a0ed6e04035 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx @@ -28,6 +28,7 @@ import { Dict } from '../../../types/types'; import { Query, formatFacetStat } from '../utils'; import { FacetItemsList } from './FacetItemsList'; import { MultipleSelectionHint } from './MultipleSelectionHint'; +import QGMetricsMismatchHelp from './QGMetricsMismatchHelp'; interface Props { fetching: boolean; @@ -128,6 +129,7 @@ export class TypeFacet extends React.PureComponent { onClear={this.handleClear} onClick={this.handleHeaderClick} open={open} + help={Boolean(secondLine) && } secondLine={secondLine} > diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx index 57d9bd85aa2..730b7b8f42d 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx @@ -19,6 +19,7 @@ */ import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { ComponentQualifier } from '~sonar-aligned/types/component'; import SettingsServiceMock from '../../../../api/mocks/SettingsServiceMock'; import { mockComponent } from '../../../../helpers/mocks/component'; @@ -78,7 +79,8 @@ describe('MQR mode', () => { ]); }); - it('should show show mqr filters if they exist in query', async () => { + it('should show standard filters if they exist in query', async () => { + const user = userEvent.setup(); let component = renderSidebar({ query: mockQuery({ types: [IssueType.CodeSmell] }), }); @@ -93,6 +95,11 @@ describe('MQR mode', () => { .byText('issues.facet.second_line.mode.standard') .get(), ).toBeInTheDocument(); + // help icon + expect(byRole('button', { name: 'help' }).get()).toBeInTheDocument(); + await user.click(byRole('button', { name: 'help' }).get()); + expect(screen.getByText('issues.qg_mismatch.title')).toBeInTheDocument(); + expect( screen.queryByRole('button', { name: 'issues.facet.severities' }), ).not.toBeInTheDocument(); @@ -237,6 +244,7 @@ describe('Standard mode', () => { }); it('should show show mqr filters if they exist in query', async () => { + const user = userEvent.setup(); let component = renderSidebar({ query: mockQuery({ impactSeverities: [SoftwareImpactSeverity.Blocker] }), }); @@ -251,6 +259,12 @@ describe('Standard mode', () => { .byText('issues.facet.second_line.mode.mqr') .get(), ).toBeInTheDocument(); + + // help icon + expect(byRole('button', { name: 'help' }).get()).toBeInTheDocument(); + await user.click(byRole('button', { name: 'help' }).get()); + expect(screen.getByText('issues.qg_mismatch.title')).toBeInTheDocument(); + expect( screen.queryByRole('button', { name: 'issues.facet.impactSoftwareQualities' }), ).not.toBeInTheDocument(); diff --git a/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx b/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx index 1ec8d6223e3..23784daa404 100644 --- a/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx +++ b/server/sonar-web/src/main/js/components/facets/SeverityFacet.tsx @@ -22,6 +22,7 @@ import { Popover } from '@sonarsource/echoes-react'; import * as React from 'react'; import { useIntl } from 'react-intl'; import { BareButton, HelperHintIcon } from '~design-system'; +import QGMetricsMismatchHelp from '../../apps/issues/sidebar/QGMetricsMismatchHelp'; import { IMPACT_SEVERITIES } from '../../helpers/constants'; import { DocLink } from '../../helpers/doc-links'; import { translate } from '../../helpers/l10n'; @@ -54,24 +55,30 @@ export default function SeverityFacet(props: Readonly) { renderName={renderName} renderTextName={renderTextName} help={ - -

{intl.formatMessage({ id: 'severity_impact.help.line1' })}

-

{intl.formatMessage({ id: 'severity_impact.help.line2' })}

- - } - footer={ - - {intl.formatMessage({ id: 'learn_more' })} - - } - > - - - -
+ props.secondLine ? ( + + ) : ( + +

{intl.formatMessage({ id: 'severity_impact.help.line1' })}

+

+ {intl.formatMessage({ id: 'severity_impact.help.line2' })} +

+ + } + footer={ + + {intl.formatMessage({ id: 'learn_more' })} + + } + > + + + +
+ ) } /> ); diff --git a/server/sonar-web/src/main/js/components/facets/StandardSeverityFacet.tsx b/server/sonar-web/src/main/js/components/facets/StandardSeverityFacet.tsx index b667875a350..ce8801954ea 100644 --- a/server/sonar-web/src/main/js/components/facets/StandardSeverityFacet.tsx +++ b/server/sonar-web/src/main/js/components/facets/StandardSeverityFacet.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; +import QGMetricsMismatchHelp from '../../apps/issues/sidebar/QGMetricsMismatchHelp'; import { SEVERITIES } from '../../helpers/constants'; import { translate } from '../../helpers/l10n'; import SoftwareImpactSeverityIcon from '../icon-mappers/SoftwareImpactSeverityIcon'; @@ -45,6 +46,7 @@ export default function StandardSeverityFacet( return ( } options={SEVERITIES} property="severities" renderName={renderName} diff --git a/server/sonar-web/src/main/js/design-system/components/FacetBox.tsx b/server/sonar-web/src/main/js/design-system/components/FacetBox.tsx index bac0c8b20db..c93ac18933f 100644 --- a/server/sonar-web/src/main/js/design-system/components/FacetBox.tsx +++ b/server/sonar-web/src/main/js/design-system/components/FacetBox.tsx @@ -94,45 +94,47 @@ export function FacetBox(props: FacetBoxProps) { inner={inner} >
- - { - if (!disabled) { - onClick?.(!open); - } - }} - > - {expandable && } - - {disabled ? ( - - - {name} - - - ) : ( -
- {name} - {secondLine !== undefined && ( - - {secondLine} - - )} -
- )} -
+
+ + { + if (!disabled) { + onClick?.(!open); + } + }} + > + {expandable && } + + {disabled ? ( + + + {name} + + + ) : ( +
+ {name} + {secondLine !== undefined && ( + + {secondLine} + + )} +
+ )} +
+
{help && {help}} - +
{} -- cgit v1.2.3