diff options
author | Stas Vilchik <stas-vilchik@users.noreply.github.com> | 2017-04-28 09:19:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-28 09:19:35 +0200 |
commit | c370fe8bd92bc9904cb07b96b562d83c719f1364 (patch) | |
tree | 1efac0d544fdfc6f918dbc1ad166b9bb0ac127b9 /server/sonar-web/src/main/js/apps/issues | |
parent | fd760e08dc881fbff44f480f6512b4bb1df0989e (diff) | |
download | sonarqube-c370fe8bd92bc9904cb07b96b562d83c719f1364.tar.gz sonarqube-c370fe8bd92bc9904cb07b96b562d83c719f1364.zip |
apply feedback on issues page (part 2) (#1991)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/issues')
8 files changed, 137 insertions, 61 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.js b/server/sonar-web/src/main/js/apps/issues/components/App.js index 8d71be0d1ff..7dc673d80dd 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/App.js +++ b/server/sonar-web/src/main/js/apps/issues/components/App.js @@ -433,9 +433,6 @@ export default class App extends React.PureComponent { ): Promise<Array<Issue>> => { const { issues, openIssue, paging } = this.state; - /* eslint-disable no-console */ - console.log(`loadin issues from line ${from} to line ${to}`); - if (!openIssue || !paging) { return Promise.reject(); } diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js index 057eb7e7cd4..8ec80944e7c 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js +++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js @@ -160,16 +160,20 @@ export default class BulkChangeModal extends React.PureComponent { handleSubmit = (e: Event) => { e.preventDefault(); - const query = pickBy({ - assign: this.state.assignee, - set_type: this.state.type, - set_severity: this.state.severity, - add_tags: this.state.addTags && this.state.addTags.join(), - remove_tags: this.state.removeTags && this.state.removeTags.join(), - do_transition: this.state.transition, - comment: this.state.comment, - sendNotifications: this.state.notifications - }); + const query = pickBy( + { + assign: this.state.assignee, + set_type: this.state.type, + set_severity: this.state.severity, + add_tags: this.state.addTags && this.state.addTags.join(), + remove_tags: this.state.removeTags && this.state.removeTags.join(), + do_transition: this.state.transition, + comment: this.state.comment, + sendNotifications: this.state.notifications + }, + // remove null, but keep empty string + x => x != null + ); const issueKeys = this.state.issues.map(issue => issue.key); this.setState({ submitting: true }); diff --git a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js index 0fd09abce63..fafa016098a 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js +++ b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js @@ -47,7 +47,7 @@ export default class ComponentBreadcrumbs extends React.PureComponent { <Organization linkClassName="link-no-underline" organizationKey={issue.organization} />} {displayProject && - <span> + <span title={issue.projectName}> <Link to={getProjectUrl(issue.project)} className="link-no-underline"> {limitComponentName(issue.projectName)} </Link> @@ -56,7 +56,7 @@ export default class ComponentBreadcrumbs extends React.PureComponent { {displaySubProject && issue.subProject != null && - <span> + <span title={issue.subProjectName}> <Link to={getProjectUrl(issue.subProject)} className="link-no-underline"> {limitComponentName(issue.subProjectName)} </Link> @@ -64,7 +64,9 @@ export default class ComponentBreadcrumbs extends React.PureComponent { </span>} <Link to={getProjectUrl(issue.component)} className="link-no-underline"> - {collapsePath(issue.componentLongName)} + <span title={issue.componentLongName}> + {collapsePath(issue.componentLongName)} + </span> </Link> </div> ); diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js index 0c6814735e1..019bf77961d 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js @@ -30,7 +30,7 @@ type Props = { const IssuesCounter = (props: Props) => ( <span> <strong> - {props.current != null && <span>{props.current + 1} / </span>} + {props.current != null && <span>{formatMeasure(props.current + 1, 'INT')} / </span>} {formatMeasure(props.total, 'INT')} </strong> {' '} diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesContainer-test.js b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesContainer-test.js new file mode 100644 index 00000000000..31230e72610 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesContainer-test.js @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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. + */ +// @flow +import React from 'react'; +import { shallow } from 'enzyme'; +import IssuesCounter from '../IssuesCounter'; + +it('formats numbers', () => { + expect(shallow(<IssuesCounter current={1234} total={987654321} />)).toMatchSnapshot(); +}); + +it('does not show current', () => { + expect(shallow(<IssuesCounter current={null} total={987654321} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesContainer-test.js.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesContainer-test.js.snap new file mode 100644 index 00000000000..0af64820202 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesContainer-test.js.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`does not show current 1`] = ` +<span> + <strong> + 987,654,321 + </strong> + + issues.issues +</span> +`; + +exports[`formats numbers 1`] = ` +<span> + <strong> + <span> + 1,235 + / + </span> + 987,654,321 + </strong> + + issues.issues +</span> +`; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js index 56e1328bc4f..a1ec652908d 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js @@ -19,11 +19,11 @@ */ // @flow import React from 'react'; -import classNames from 'classnames'; import moment from 'moment'; import { max } from 'lodash'; import FacetBox from './components/FacetBox'; import FacetHeader from './components/FacetHeader'; +import FacetItem from './components/FacetItem'; import { BarChart } from '../../../components/charts/bar-chart'; import DateInput from '../../../components/controls/DateInput'; import { translate } from '../../../helpers/l10n'; @@ -55,6 +55,13 @@ export default class CreationDateFacet extends React.PureComponent { property = 'createdAt'; + hasValue = (): boolean => + this.props.createdAfter.length > 0 || + this.props.createdAt.length > 0 || + this.props.createdBefore.length > 0 || + this.props.createdInLast.length > 0 || + this.props.sinceLeakPeriod; + handleHeaderClick = () => { this.props.onToggle(this.property); }; @@ -93,15 +100,11 @@ export default class CreationDateFacet extends React.PureComponent { }); }; - handlePeriodClick = (period?: string) => (e: Event & { target: HTMLElement }) => { - e.preventDefault(); - e.target.blur; + handlePeriodClick = (period: string) => { this.resetTo({ createdInLast: period }); }; - handleLeakPeriodClick = () => (e: Event & { target: HTMLElement }) => { - e.preventDefault(); - e.target.blur; + handleLeakPeriodClick = () => { this.resetTo({ sinceLeakPeriod: true }); }; @@ -200,39 +203,51 @@ export default class CreationDateFacet extends React.PureComponent { renderPrefefinedPeriods() { const { component, createdInLast, sinceLeakPeriod } = this.props; return ( - <div className="spacer-top"> - <span className="spacer-right">{translate('issues.facet.createdAt.or')}</span> - <a className="spacer-right" href="#" onClick={this.handlePeriodClick()}> - {translate('issues.facet.createdAt.all')} - </a> + <div className="spacer-top issues-predefined-periods"> + <FacetItem + active={!this.hasValue()} + facetMode="" + name={translate('issues.facet.createdAt.all')} + onClick={this.handlePeriodClick} + stat={null} + value="" + /> {component == null && - <a - className={classNames('spacer-right', { 'active-link': createdInLast === '1w' })} - href="#" - onClick={this.handlePeriodClick('1w')}> - {translate('issues.facet.createdAt.last_week')} - </a>} + <FacetItem + active={createdInLast === '1w'} + facetMode="" + name={translate('issues.facet.createdAt.last_week')} + onClick={this.handlePeriodClick} + stat={null} + value="1w" + />} {component == null && - <a - className={classNames('spacer-right', { 'active-link': createdInLast === '1m' })} - href="#" - onClick={this.handlePeriodClick('1m')}> - {translate('issues.facet.createdAt.last_month')} - </a>} + <FacetItem + active={createdInLast === '1m'} + facetMode="" + name={translate('issues.facet.createdAt.last_month')} + onClick={this.handlePeriodClick} + stat={null} + value="1m" + />} {component == null && - <a - className={classNames('spacer-right', { 'active-link': createdInLast === '1y' })} - href="#" - onClick={this.handlePeriodClick('1y')}> - {translate('issues.facet.createdAt.last_year')} - </a>} + <FacetItem + active={createdInLast === '1y'} + facetMode="" + name={translate('issues.facet.createdAt.last_year')} + onClick={this.handlePeriodClick} + stat={null} + value="1y" + />} {component != null && - <a - className={classNames('spacer-right', { 'active-link': sinceLeakPeriod })} - href="#" - onClick={this.handleLeakPeriodClick()}> - {translate('issues.leak_period')} - </a>} + <FacetItem + active={sinceLeakPeriod} + facetMode="" + name={translate('issues.leak_period')} + onClick={this.handleLeakPeriodClick} + stat={null} + value="" + />} </div> ); } @@ -249,13 +264,6 @@ export default class CreationDateFacet extends React.PureComponent { } render() { - const hasValue = - this.props.createdAfter.length > 0 || - this.props.createdAt.length > 0 || - this.props.createdBefore.length > 0 || - this.props.createdInLast.length > 0 || - this.props.sinceLeakPeriod; - return ( <FacetBox property={this.property}> <FacetHeader @@ -263,7 +271,7 @@ export default class CreationDateFacet extends React.PureComponent { onClear={this.handleClear} onClick={this.handleHeaderClick} open={this.props.open} - values={hasValue ? 1 : 0} + values={this.hasValue() ? 1 : 0} /> {this.props.open && this.renderInner()} diff --git a/server/sonar-web/src/main/js/apps/issues/styles.css b/server/sonar-web/src/main/js/apps/issues/styles.css index 63e28fcf51d..63867881965 100644 --- a/server/sonar-web/src/main/js/apps/issues/styles.css +++ b/server/sonar-web/src/main/js/apps/issues/styles.css @@ -216,3 +216,12 @@ .issues-workspace-list-component + .issues-workspace-list-item { margin-top: 0; } + +.issues-predefined-periods { + display: flex; +} + +.issues-predefined-periods .search-navigator-facet { + width: auto; + margin-right: 4px; +}
\ No newline at end of file |