return measureSelected || overviewSelected;
};
+ getValues = () => {
+ const { domain, selected } = this.props;
+ const measureSelected = domain.measures.find(measure => measure.metric.key === selected);
+ const overviewSelected = domain.name === selected && hasBubbleChart(domain.name);
+ return measureSelected
+ ? [getLocalizedMetricName(measureSelected.metric)]
+ : overviewSelected ? [translate('component_measures.domain_overview')] : [];
+ };
+
renderItemFacetStat = (item /*: MeasureEnhanced */) =>
hasFacetStat(item.metric.key) ? <FacetMeasureValue measure={item} /> : null;
};
render() {
- const { domain, selected } = this.props;
+ const { domain } = this.props;
const helper = `component_measures.domain_facets.${domain.name}.help`;
const translatedHelper = translate(helper);
return (
name={getLocalizedMetricDomain(domain.name)}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.hasFacetSelected(domain, domain.measures, selected) ? 1 : 0}
+ values={this.getValues()}
/>
{this.props.open && (
name="Reliability"
onClick={[Function]}
open={true}
- values={0}
+ values={Array []}
/>
<FacetItemsList>
<FacetItem
name="Reliability"
onClick={[Function]}
open={true}
- values={1}
+ values={
+ Array [
+ "Bugs",
+ ]
+ }
/>
<FacetItemsList>
<FacetItem
return stats ? stats[assignee] : null;
}
+ getValues() {
+ const values = this.props.assignees.map(assignee => {
+ const user = this.props.referencedUsers[assignee];
+ return user ? user.name : assignee;
+ });
+ if (!this.props.assigned) {
+ values.push(translate('unassigned'));
+ }
+ return values;
+ }
+
renderOption = (option /*: { avatar: string, label: string } */) => {
return (
<span>
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.assignees.length + (this.props.assigned ? 0 : 1)}
+ values={this.getValues()}
/>
{this.props.open && this.renderList()}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.authors.length}
+ values={this.props.authors}
/>
{this.props.open && this.renderList()}
handleLeakPeriodClick = () => this.resetTo({ sinceLeakPeriod: true });
+ getValues() {
+ const { createdAfter, createdAt, createdBefore, createdInLast, sinceLeakPeriod } = this.props;
+ const { formatDate } = this.context.intl;
+ const values = [];
+ if (createdAfter) {
+ values.push(formatDate(createdAfter, longFormatterOption));
+ }
+ if (createdAt) {
+ values.push(formatDate(createdAt, longFormatterOption));
+ }
+ if (createdBefore) {
+ values.push(formatDate(createdBefore, longFormatterOption));
+ }
+ if (createdInLast === '1w') {
+ values.push(translate('issues.facet.createdAt.last_week'));
+ }
+ if (createdInLast === '1m') {
+ values.push(translate('issues.facet.createdAt.last_month'));
+ }
+ if (createdInLast === '1y') {
+ values.push(translate('issues.facet.createdAt.last_year'));
+ }
+ if (sinceLeakPeriod) {
+ values.push(translate('issues.leak_period'));
+ }
+ return values;
+ }
+
renderBarChart() {
const { createdBefore, stats } = this.props;
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.hasValue() ? 1 : 0}
+ values={this.getValues()}
/>
{this.props.open && this.renderInner()}
import FacetItemsList from '../../../components/facet/FacetItemsList';
import QualifierIcon from '../../../components/shared/QualifierIcon';
import { translate } from '../../../helpers/l10n';
+import { collapsePath } from '../../../helpers/path';
import { formatFacetStat } from '../utils';
/*:: import type { ReferencedComponent } from '../utils'; */
}
renderName(directory /*: string */) /*: React.Element<*> | string */ {
- // `referencedComponents` are indexed by uuid
- // so we have to browse them all to find a matching one
- const { referencedComponents } = this.props;
- const uuid = Object.keys(referencedComponents).find(
- uuid => referencedComponents[uuid].key === directory
- );
- const name = uuid ? referencedComponents[uuid].name : directory;
return (
<span>
<QualifierIcon className="little-spacer-right" qualifier="DIR" />
- {name}
+ {directory}
</span>
);
}
}
render() {
+ const values = this.props.directories.map(dir => collapsePath(dir));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.directories.length}
+ values={values}
/>
{this.props.open && this.renderList()}
return stats ? stats[file] : null;
}
- renderName(file /*: string */) /*: React.Element<*> | string */ {
+ getFileName(file /*: string */) {
const { referencedComponents } = this.props;
- const name = referencedComponents[file]
- ? collapsePath(referencedComponents[file].path, 15)
- : file;
+ return referencedComponents[file] ? collapsePath(referencedComponents[file].path, 15) : file;
+ }
+
+ renderName(file /*: string */) /*: React.Element<*> | string */ {
+ const name = this.getFileName(file);
return (
<span>
<QualifierIcon className="little-spacer-right" qualifier="FIL" />
}
render() {
+ const values = this.props.files.map(file => this.getFileName(file));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.files.length}
+ values={values}
/>
{this.props.open && this.renderList()}
}
render() {
+ const values = this.props.languages.map(language => this.getLanguageName(language));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.languages.length}
+ values={values}
/>
{this.props.open && this.renderList()}
return stats ? stats[module] : null;
}
- renderName(module /*: string */) /*: React.Element<*> | string */ {
+ getModuleName(module /*: string */) {
const { referencedComponents } = this.props;
- const name = referencedComponents[module] ? referencedComponents[module].name : module;
+ return referencedComponents[module] ? referencedComponents[module].name : module;
+ }
+
+ renderName(module /*: string */) /*: React.Element<*> | string */ {
return (
<span>
<QualifierIcon className="little-spacer-right" qualifier="BRC" />
- {name}
+ {this.getModuleName(module)}
</span>
);
}
}
render() {
+ const values = this.props.modules.map(module => this.getModuleName(module));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.modules.length}
+ values={values}
/>
{this.props.open && this.renderList()}
return stats ? stats[project] : null;
}
+ getProjectName(project /*: string */) {
+ const { referencedComponents } = this.props;
+ return referencedComponents[project] ? referencedComponents[project].name : project;
+ }
+
renderName(project /*: string */) /*: React.Element<*> | string */ {
const { organization, referencedComponents } = this.props;
return referencedComponents[project] ? (
}
render() {
+ const values = this.props.projects.map(project => this.getProjectName(project));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.projects.length}
+ values={values}
/>
{this.props.open && this.renderList()}
render() {
const resolutions = ['', 'FIXED', 'FALSE-POSITIVE', 'WONTFIX', 'REMOVED'];
+ const values = this.props.resolutions.map(resolution => this.getFacetItemName(resolution));
return (
<FacetBox>
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.resolutions.length}
+ values={values}
/>
{this.props.open && <FacetItemsList>{resolutions.map(this.renderItem)}</FacetItemsList>}
}
render() {
+ const values = this.props.rules.map(rule => this.getRuleName(rule));
return (
<FacetBox>
<FacetHeader
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.rules.length}
+ values={values}
/>
{this.props.open && this.renderList()}
render() {
const severities = ['BLOCKER', 'MINOR', 'CRITICAL', 'INFO', 'MAJOR'];
+ const values = this.props.severities.map(severity => translate('severity', severity));
return (
<FacetBox>
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.severities.length}
+ values={values}
/>
{this.props.open && <FacetItemsList>{severities.map(this.renderItem)}</FacetItemsList>}
render() {
const statuses = ['OPEN', 'RESOLVED', 'REOPENED', 'CLOSED', 'CONFIRMED'];
+ const values = this.props.statuses.map(status => translate('issue.status', status));
return (
<FacetBox>
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.statuses.length}
+ values={values}
/>
{this.props.open && <FacetItemsList>{statuses.map(this.renderItem)}</FacetItemsList>}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.tags.length}
+ values={this.props.tags}
/>
{this.props.open && this.renderList()}
render() {
const types = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
+ const values = this.props.types.map(type => translate('issue.type', type));
return (
<FacetBox>
onClear={this.handleClear}
onClick={this.handleHeaderClick}
open={this.props.open}
- values={this.props.types.length}
+ values={values}
/>
{this.props.open && <FacetItemsList>{types.map(this.renderItem)}</FacetItemsList>}
onClear={[Function]}
onClick={[Function]}
open={true}
- values={0}
+ values={Array []}
/>
<FacetItemsList>
<FacetItem
onClear={[Function]}
onClick={[Function]}
open={true}
- values={0}
+ values={Array []}
/>
</FacetBox>
`;
onClear={[Function]}
onClick={[Function]}
open={true}
- values={1}
+ values={
+ Array [
+ "unassigned",
+ ]
+ }
/>
<FacetItemsList>
<FacetItem
onClear={[Function]}
onClick={[Function]}
open={true}
- values={1}
+ values={
+ Array [
+ "name-foo",
+ ]
+ }
/>
<FacetItemsList>
<FacetItem
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// @flow
-/* eslint-disable max-len */
import React from 'react';
import OpenCloseIcon from '../icons-components/OpenCloseIcon';
import HelpIcon from '../icons-components/HelpIcon';
import Tooltip from '../controls/Tooltip';
-import { translate } from '../../helpers/l10n';
+import { translate, translateWithParameters } from '../../helpers/l10n';
/*::
type Props = {|
onClear?: () => void,
onClick?: () => void,
open: boolean,
- values?: number
+ values?: Array<string>
|};
*/
}
renderValueIndicator() {
- if (this.props.open || !this.props.values) {
+ const { values } = this.props;
+ if (this.props.open || !values || !values.length) {
return null;
}
+ const value =
+ values.length === 1 ? values[0] : translateWithParameters('x_selected', values.length);
return (
- <span className="spacer-left badge badge-secondary is-rounded">{this.props.values}</span>
+ <span className="badge badge-secondary is-rounded text-ellipsis" title={value}>
+ {value}
+ </span>
);
}
render() {
- const showClearButton /*: boolean */ = !!this.props.values && this.props.onClear != null;
+ const showClearButton =
+ this.props.values != null && this.props.values.length > 0 && this.props.onClear != null;
return (
- <div>
- {showClearButton && (
- <button
- className="search-navigator-facet-header-button button-small button-red"
- onClick={this.handleClearClick}>
- {translate('clear')}
- </button>
- )}
-
+ <div className="search-navigator-facet-header-wrapper">
{this.props.onClick ? (
<span className="search-navigator-facet-header">
<a href="#" onClick={this.handleClick}>
{this.props.name}
</a>
{this.renderHelper()}
- {this.renderValueIndicator()}
</span>
) : (
<span className="search-navigator-facet-header">
{this.renderHelper()}
</span>
)}
+
+ <span className="search-navigator-facet-header-value spacer-left spacer-right ">
+ {this.renderValueIndicator()}
+ </span>
+
+ {showClearButton && (
+ <button
+ className="search-navigator-facet-header-button button-small button-red"
+ onClick={this.handleClearClick}>
+ {translate('clear')}
+ </button>
+ )}
</div>
);
}
it('should render open facet with value', () => {
expect(
- shallow(<FacetHeader name="foo" onClick={jest.fn()} open={true} values={1} />)
+ shallow(<FacetHeader name="foo" onClick={jest.fn()} open={true} values={['foo']} />)
).toMatchSnapshot();
});
it('should render closed facet with value', () => {
expect(
- shallow(<FacetHeader name="foo" onClick={jest.fn()} open={false} values={1} />)
+ shallow(<FacetHeader name="foo" onClick={jest.fn()} open={false} values={['foo']} />)
).toMatchSnapshot();
});
it('should clear', () => {
const onClear = jest.fn();
const wrapper = shallow(
- <FacetHeader name="foo" onClear={onClear} onClick={jest.fn()} open={false} values={3} />
+ <FacetHeader
+ name="foo"
+ onClear={onClear}
+ onClick={jest.fn()}
+ open={false}
+ values={['foo', 'bar', 'baz']}
+ />
);
expect(wrapper).toMatchSnapshot();
click(wrapper.find('.button-red'));
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should clear 1`] = `
-<div>
- <button
- className="search-navigator-facet-header-button button-small button-red"
- onClick={[Function]}
- >
- clear
- </button>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
/>
foo
</a>
+ </span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ >
<span
- className="spacer-left badge badge-secondary is-rounded"
+ className="badge badge-secondary is-rounded text-ellipsis"
+ title="x_selected.3"
>
- 3
+ x_selected.3
</span>
</span>
+ <button
+ className="search-navigator-facet-header-button button-small button-red"
+ onClick={[Function]}
+ >
+ clear
+ </button>
</div>
`;
exports[`should render closed facet with value 1`] = `
-<div>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
/>
foo
</a>
+ </span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ >
<span
- className="spacer-left badge badge-secondary is-rounded"
+ className="badge badge-secondary is-rounded text-ellipsis"
+ title="foo"
>
- 1
+ foo
</span>
</span>
</div>
`;
exports[`should render closed facet without value 1`] = `
-<div>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
foo
</a>
</span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ />
</div>
`;
exports[`should render open facet with value 1`] = `
-<div>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
foo
</a>
</span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ />
</div>
`;
exports[`should render open facet without value 1`] = `
-<div>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
foo
</a>
</span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ />
</div>
`;
exports[`should render without link 1`] = `
-<div>
+<div
+ className="search-navigator-facet-header-wrapper"
+>
<span
className="search-navigator-facet-header"
>
foo
</span>
+ <span
+ className="search-navigator-facet-header-value spacer-left spacer-right "
+ />
</div>
`;
.search-navigator-facet-header {
display: block;
+ flex-shrink: 0;
padding: 8px 0;
color: @baseFontColor;
font-weight: 600;
+ overflow: hidden;
+ white-space: nowrap;
& > a {
border-bottom: none;
}
}
+.search-navigator-facet-header-value {
+ display: block;
+ padding: 8px 0;
+ overflow: hidden;
+}
+
+.search-navigator-facet-header-value > .badge {
+ display: block;
+}
+
.search-navigator-facet-header-button {
- float: right;
- margin-top: 6px;
+ flex-shrink: 0;
+ margin-left: auto;
+}
+
+.search-navigator-facet-header-wrapper {
+ display: flex;
+ align-items: center;
}
.search-navigator-facet-list {
severity=Severity
shared=Shared
x_show={0} shown
+x_selected={0} selected
x_of_y_shown={0} of {1} shown
size=Size
status=Status