From f3c798e5ec60ba64594a906eaee45d52b7f46f76 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aubert=20Gr=C3=A9goire?= Date: Mon, 6 Mar 2017 14:42:29 +0100 Subject: [PATCH] SONAR-8876 Language facet searchbox on projects page (#1741) --- .../main/js/apps/projects/filters/Filter.js | 13 +++ .../apps/projects/filters/LanguageFilter.js | 10 +++ .../projects/filters/LanguageFilterFooter.js | 84 +++++++++++++++++++ .../less/components/search-navigator.less | 12 ++- 4 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/projects/filters/LanguageFilterFooter.js diff --git a/server/sonar-web/src/main/js/apps/projects/filters/Filter.js b/server/sonar-web/src/main/js/apps/projects/filters/Filter.js index b10b4162d63..53806389065 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/Filter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/Filter.js @@ -33,6 +33,7 @@ export default class Filter extends React.Component { renderName: React.PropTypes.func.isRequired, renderOption: React.PropTypes.func.isRequired, + renderFooter: React.PropTypes.func, getFacetValueForOption: React.PropTypes.func, @@ -130,11 +131,23 @@ export default class Filter extends React.Component { } } + renderFooter () { + if (!this.props.renderFooter) { + return null; + } + return ( +
+ {this.props.renderFooter()} +
+ ); + } + render () { return (
{this.renderHeader()} {this.renderOptions()} + {this.renderFooter()}
); } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilter.js index 4e3e10921f5..0e3d5e51706 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilter.js @@ -21,6 +21,7 @@ import React from 'react'; import sortBy from 'lodash/sortBy'; import FilterContainer from './FilterContainer'; import LanguageFilterOption from './LanguageFilterOption'; +import LanguageFilterFooter from './LanguageFilterFooter'; export default class LanguageFilter extends React.Component { static propTypes = { @@ -39,6 +40,14 @@ export default class LanguageFilter extends React.Component { return sortBy(Object.keys(facet), [option => -facet[option]]); } + renderFooter = () => ( + + ); + getFacetValueForOption = (facet, option) => facet[option]; render () { @@ -48,6 +57,7 @@ export default class LanguageFilter extends React.Component { getOptions={facet => facet ? this.getSortedOptions(facet) : []} renderName={() => 'Languages'} renderOption={this.renderOption} + renderFooter={this.renderFooter} getFacetValueForOption={this.getFacetValueForOption} query={this.props.query} isFavorite={this.props.isFavorite} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilterFooter.js b/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilterFooter.js new file mode 100644 index 00000000000..9db6ebe304f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/LanguageFilterFooter.js @@ -0,0 +1,84 @@ +/* + * 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. + */ +import React from 'react'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router'; +import Select from 'react-select'; +import difference from 'lodash/difference'; +import isNil from 'lodash/isNil'; +import omitBy from 'lodash/omitBy'; +import { getProjectsAppFacetByProperty, getLanguages } from '../../../store/rootReducer'; +import { translate } from '../../../helpers/l10n'; + +class LanguageFilterFooter extends React.Component { + static propTypes = { + property: React.PropTypes.string.isRequired, + query: React.PropTypes.object.isRequired, + isFavorite: React.PropTypes.bool, + organization: React.PropTypes.object, + languages: React.PropTypes.object, + value: React.PropTypes.any, + facet: React.PropTypes.object, + getFilterUrl: React.PropTypes.func.isRequired + } + + handleLanguageChange = ({ value }) => { + const urlOptions = (this.props.value || []).concat(value).join(','); + const path = this.props.getFilterUrl({ [this.props.property]: urlOptions }); + this.props.router.push(path); + } + + getOptions () { + const { languages, facet } = this.props; + let options = Object.keys(languages); + if (facet) { + options = difference(options, Object.keys(facet)); + } + return options.map(key => ({ label: languages[key].name, value: key })); + } + + render () { + return ( +