diff options
author | Jay <jeremy.davis@sonarsource.com> | 2023-07-06 17:32:55 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-07-11 20:03:24 +0000 |
commit | 76c1f065c934a9abcba93dedb97fe7b4b8277ec4 (patch) | |
tree | f0e190f826d1736b02b0eba4a2488c0e649614f8 /server/sonar-web/src/main/js/apps/issues/sidebar | |
parent | f062b56fd8656ee6239335a561474e25f73af5f5 (diff) | |
download | sonarqube-76c1f065c934a9abcba93dedb97fe7b4b8277ec4.tar.gz sonarqube-76c1f065c934a9abcba93dedb97fe7b4b8277ec4.zip |
SONAR-19709 Migrate projects facets to the new UI
Diffstat (limited to 'server/sonar-web/src/main/js/apps/issues/sidebar')
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/sidebar/ListStyleFacet.tsx | 44 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap | 22 |
2 files changed, 61 insertions, 5 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ListStyleFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/ListStyleFacet.tsx index dce39a06677..106ea557690 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/ListStyleFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ListStyleFacet.tsx @@ -19,12 +19,13 @@ */ import { FacetBox, FacetItem, FlagMessage, InputSearch } from 'design-system'; -import { sortBy, without } from 'lodash'; +import { max, sortBy, values, without } from 'lodash'; import * as React from 'react'; import ListFooter from '../../../components/controls/ListFooter'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import { queriesEqual } from '../../../helpers/query'; +import { isDefined } from '../../../helpers/types'; import { MetricType } from '../../../types/metrics'; import { Dict, Paging, RawQuery } from '../../../types/types'; import { FacetItemsList } from './FacetItemsList'; @@ -39,6 +40,7 @@ interface SearchResponse<S> { export interface Props<S> { disabled?: boolean; + disableZero?: boolean; facetHeader: string; fetching: boolean; getFacetItemText: (item: string) => string; @@ -54,7 +56,7 @@ export interface Props<S> { onClear?: () => void; onItemClick?: (itemValue: string, multiple: boolean) => void; onSearch: (query: string, page?: number) => Promise<SearchResponse<S>>; - onToggle: (property: string) => void; + onToggle?: (property: string) => void; open: boolean; property: string; query?: RawQuery; @@ -63,6 +65,7 @@ export interface Props<S> { searchPlaceholder: string; showLessAriaLabel?: string; showMoreAriaLabel?: string; + showStatBar?: boolean; stats: Dict<number> | undefined; values: string[]; } @@ -155,7 +158,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { }; handleHeaderClick = () => { - this.props.onToggle(this.props.property); + this.props.onToggle?.(this.props.property); }; handleClear = () => { @@ -241,6 +244,24 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { return stats?.[item]; } + getStatBarPercent = (item: string) => { + const { showStatBar, stats } = this.props; + const { searchResultsCounts } = this.state; + + if (!showStatBar) { + return undefined; + } + + const combined = { ...stats, ...searchResultsCounts }; + + const maxFacetValue = max(values(combined)); + const facetValue = combined?.[item]; + + return isDefined(facetValue) && isDefined(maxFacetValue) && maxFacetValue > 0 + ? facetValue / maxFacetValue + : undefined; + }; + getFacetHeaderId = (property: string) => { return `facet_${property}`; }; @@ -255,6 +276,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { renderList() { const { + disableZero, maxInitialItems, maxItems, property, @@ -293,11 +315,13 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { {limitedList.map((item) => ( <FacetItem active={this.props.values.includes(item)} + disableZero={disableZero} className="it__search-navigator-facet" key={item} name={this.props.renderFacetItem(item)} onClick={this.handleItemClick} stat={formatFacetStat(this.getStat(item)) ?? 0} + statBarPercent={this.getStatBarPercent(item)} tooltip={this.props.getFacetItemText(item)} value={item} /> @@ -313,10 +337,12 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { <FacetItem active className="it__search-navigator-facet" + disableZero={disableZero} key={item} name={this.props.renderFacetItem(item)} onClick={this.handleItemClick} stat={formatFacetStat(this.getStat(item)) ?? 0} + statBarPercent={this.getStatBarPercent(item)} tooltip={this.props.getFacetItemText(item)} value={item} /> @@ -344,6 +370,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { } renderSearch() { + const { minSearchLength } = this.props; return ( <InputSearch className="it__search-box-input sw-mb-4 sw-w-full" @@ -354,6 +381,8 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { value={this.state.query} searchInputAriaLabel={translate('search_verb')} clearIconAriaLabel={translate('clear')} + minLength={minSearchLength} + tooShortText={translateWithParameters('select2.tooShort', minSearchLength)} /> ); } @@ -399,6 +428,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { } renderSearchResult(result: S) { + const { disableZero } = this.props; const key = this.props.getSearchResultKey(result); const active = this.props.values.includes(key); const stat = formatFacetStat(this.getStat(key) ?? this.state.searchResultsCounts[key]) ?? 0; @@ -407,10 +437,12 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { <FacetItem active={active} className="it__search-navigator-facet" + disableZero={disableZero} key={key} name={this.props.renderSearchResult(result, this.state.query)} onClick={this.handleItemClick} stat={stat} + statBarPercent={this.getStatBarPercent(key)} tooltip={this.props.getSearchResultText(result)} value={key} /> @@ -423,6 +455,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { facetHeader, fetching, inner, + minSearchLength, open, property, stats = {}, @@ -436,7 +469,7 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { const loadingResults = query !== '' && searching && (searchResults === undefined || searchResults.length === 0); - const showList = !query || loadingResults; + const showList = query.length < minSearchLength || loadingResults; const nbSelectableItems = Object.keys(stats).length; const nbSelectedItems = values.length; @@ -447,13 +480,14 @@ export class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> { clearIconLabel={translate('clear')} count={nbSelectedItems} countLabel={translateWithParameters('x_selected', nbSelectedItems)} + data-property={property} disabled={disabled} id={this.getFacetHeaderId(property)} inner={inner} loading={fetching} name={facetHeader} onClear={this.handleClear} - onClick={disabled ? undefined : this.handleHeaderClick} + onClick={disabled || !this.props.onToggle ? undefined : this.handleHeaderClick} open={open && !disabled} > {!disabled && ( diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap index 1e996ba29e7..f3f1bf306ff 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap @@ -6,6 +6,7 @@ exports[`should be disabled 1`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" disabled={true} id="facet_foo" loading={false} @@ -21,6 +22,7 @@ exports[`should display all selected items 1`] = ` clearIconLabel="clear" count={3} countLabel="x_selected.3" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -35,10 +37,12 @@ exports[`should display all selected items 1`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="" /> <FacetItemsList @@ -103,6 +107,7 @@ exports[`should render 1`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -117,10 +122,12 @@ exports[`should render 1`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="" /> <FacetItemsList @@ -176,6 +183,7 @@ exports[`should search 1`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -190,10 +198,12 @@ exports[`should search 1`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="query" /> <FacetItemsList @@ -242,6 +252,7 @@ exports[`should search 2`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -256,10 +267,12 @@ exports[`should search 2`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="query" /> <FacetItemsList @@ -318,6 +331,7 @@ exports[`should search 3`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -332,10 +346,12 @@ exports[`should search 3`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="" /> <FacetItemsList @@ -391,6 +407,7 @@ exports[`should search 4`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -405,10 +422,12 @@ exports[`should search 4`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="blabla" /> <div @@ -430,6 +449,7 @@ exports[`should search 5`] = ` clearIconLabel="clear" count={0} countLabel="x_selected.0" + data-property="foo" id="facet_foo" loading={false} name="facet header" @@ -444,10 +464,12 @@ exports[`should search 5`] = ` autoFocus={false} className="it__search-box-input sw-mb-4 sw-w-full" clearIconAriaLabel="clear" + minLength={2} onChange={[Function]} placeholder="search for foo..." searchInputAriaLabel="search_verb" size="auto" + tooShortText="select2.tooShort.2" value="blabla" /> <div |