From 6a2c038752b09413a9c749b3dbfdb408a72def20 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 16 Aug 2018 14:43:06 +0200 Subject: [PATCH] SONAR-6961 load counts for search results (#619) --- .../main/js/apps/issues/components/App.tsx | 7 +- .../js/apps/issues/sidebar/AssigneeFacet.tsx | 13 +- .../js/apps/issues/sidebar/AuthorFacet.tsx | 8 +- .../js/apps/issues/sidebar/DirectoryFacet.tsx | 10 +- .../main/js/apps/issues/sidebar/FileFacet.tsx | 8 +- .../js/apps/issues/sidebar/LanguageFacet.tsx | 10 +- .../issues/sidebar/LanguageFacetFooter.tsx | 69 ------- .../js/apps/issues/sidebar/ModuleFacet.tsx | 10 +- .../js/apps/issues/sidebar/ProjectFacet.tsx | 10 +- .../main/js/apps/issues/sidebar/RuleFacet.tsx | 8 +- .../main/js/apps/issues/sidebar/Sidebar.tsx | 93 ++++----- .../js/apps/issues/sidebar/StandardFacet.tsx | 8 +- .../main/js/apps/issues/sidebar/TagFacet.tsx | 8 +- .../sidebar/__tests__/AssigneeFacet-test.tsx | 1 - .../issues/sidebar/__tests__/Sidebar-test.tsx | 59 +++--- .../__snapshots__/AssigneeFacet-test.tsx.snap | 1 + .../__snapshots__/StandardFacet-test.tsx.snap | 1 + .../src/main/js/apps/issues/utils.ts | 2 +- .../components/controls/MouseOverHandler.tsx | 84 -------- .../__tests__/MouseOverHandler-test.tsx | 88 --------- .../main/js/components/facet/FacetItem.tsx | 10 - .../js/components/facet/ListStyleFacet.css | 39 ---- .../js/components/facet/ListStyleFacet.tsx | 182 ++++++------------ .../facet/__tests__/ListStyleFacet-test.tsx | 37 +--- .../ListStyleFacet-test.tsx.snap | 130 ++++++------- 25 files changed, 265 insertions(+), 631 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.tsx delete mode 100644 server/sonar-web/src/main/js/components/controls/MouseOverHandler.tsx delete mode 100644 server/sonar-web/src/main/js/components/controls/__tests__/MouseOverHandler-test.tsx delete mode 100644 server/sonar-web/src/main/js/components/facet/ListStyleFacet.css diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.tsx b/server/sonar-web/src/main/js/apps/issues/components/App.tsx index 3d26c6b39fc..8e32c0e0691 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/App.tsx @@ -661,7 +661,7 @@ export default class App extends React.PureComponent { }); }; - loadSearchResultCount = (changes: Partial) => { + loadSearchResultCount = (property: string, changes: Partial) => { const { component } = this.props; const { myIssues, query } = this.state; @@ -672,6 +672,7 @@ export default class App extends React.PureComponent { const parameters = { ...getBranchLikeQuery(this.props.branchLike), componentKeys: component && component.key, + facets: mapFacet(property), s: 'FILE_LINE', ...serializeQuery({ ...query, ...changes }), ps: 1, @@ -682,7 +683,9 @@ export default class App extends React.PureComponent { Object.assign(parameters, { assignees: '__me__' }); } - return this.props.fetchIssues(parameters, false).then(reponse => reponse.paging.total); + return this.props + .fetchIssues(parameters, false) + .then(({ facets }) => parseFacets(facets)[property]); }; closeFacet = (property: string) => { diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx index 656f74bc72c..6d5d6a22076 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx @@ -19,8 +19,7 @@ */ import * as React from 'react'; import { omit, sortBy, without } from 'lodash'; -import { searchAssignees, Query, ReferencedUser, SearchedAssignee } from '../utils'; -import { Component } from '../../../app/types'; +import { searchAssignees, Query, ReferencedUser, SearchedAssignee, Facet } from '../utils'; import Avatar from '../../../components/ui/Avatar'; import { translate } from '../../../helpers/l10n'; import { highlightTerm } from '../../../helpers/search'; @@ -29,9 +28,8 @@ import ListStyleFacet from '../../../components/facet/ListStyleFacet'; export interface Props { assigned: boolean; assignees: string[]; - component: Component | undefined; fetching: boolean; - loadSearchResultCount: (changes: Partial) => Promise; + loadSearchResultCount: (property: string, changes: Partial) => Promise; onChange: (changes: Partial) => void; onToggle: (property: string) => void; open: boolean; @@ -77,8 +75,11 @@ export default class AssigneeFacet extends React.PureComponent { } }; - loadSearchResultCount = (assignee: SearchedAssignee) => { - return this.props.loadSearchResultCount({ assigned: undefined, assignees: [assignee.login] }); + loadSearchResultCount = (assignees: SearchedAssignee[]) => { + return this.props.loadSearchResultCount('assignees', { + assigned: undefined, + assignees: assignees.map(assignee => assignee.login) + }); }; getSortedItems = () => { diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.tsx index c1d27df94ad..081a059661d 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { omit } from 'lodash'; -import { Query } from '../utils'; +import { Query, Facet } from '../utils'; import { translate } from '../../../helpers/l10n'; import ListStyleFacet from '../../../components/facet/ListStyleFacet'; import { searchIssueAuthors } from '../../../api/issues'; @@ -29,7 +29,7 @@ import { Component } from '../../../app/types'; interface Props { component: Component | undefined; fetching: boolean; - loadSearchResultCount: (changes: Partial) => Promise; + loadSearchResultCount: (property: string, changes: Partial) => Promise; onChange: (changes: Partial) => void; onToggle: (property: string) => void; open: boolean; @@ -58,8 +58,8 @@ export default class AuthorFacet extends React.PureComponent { }).then(authors => ({ maxResults: authors.length === SEARCH_SIZE, results: authors })); }; - loadSearchResultCount = (author: string) => { - return this.props.loadSearchResultCount({ authors: [author] }); + loadSearchResultCount = (authors: string[]) => { + return this.props.loadSearchResultCount('authors', { authors }); }; renderSearchResult = (author: string, term: string) => { diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx index 56501ced226..f810116174f 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { omit } from 'lodash'; -import { Query } from '../utils'; +import { Query, Facet } from '../utils'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; import { translate } from '../../../helpers/l10n'; import ListStyleFacet from '../../../components/facet/ListStyleFacet'; @@ -31,7 +31,7 @@ interface Props { componentKey: string; fetching: boolean; directories: string[]; - loadSearchResultCount: (changes: Partial) => Promise; + loadSearchResultCount: (property: string, changes: Partial) => Promise; onChange: (changes: Partial) => void; onToggle: (property: string) => void; open: boolean; @@ -62,8 +62,10 @@ export default class DirectoryFacet extends React.PureComponent { }).then(({ components, paging }) => ({ paging, results: components })); }; - loadSearchResultCount = (directory: TreeComponent) => { - return this.props.loadSearchResultCount({ directories: [directory.name] }); + loadSearchResultCount = (directories: TreeComponent[]) => { + return this.props.loadSearchResultCount('directories', { + directories: directories.map(directory => directory.name) + }); }; renderDirectory = (directory: React.ReactNode) => ( diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.tsx index 1c1f2658e94..b04c72cf2af 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { omit } from 'lodash'; -import { Query, ReferencedComponent } from '../utils'; +import { Query, ReferencedComponent, Facet } from '../utils'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; import { translate } from '../../../helpers/l10n'; import { collapsePath } from '../../../helpers/path'; @@ -31,7 +31,7 @@ interface Props { componentKey: string; fetching: boolean; files: string[]; - loadSearchResultCount: (changes: Partial) => Promise; + loadSearchResultCount: (property: string, changes: Partial) => Promise; onChange: (changes: Partial) => void; onToggle: (property: string) => void; open: boolean; @@ -69,8 +69,8 @@ export default class FileFacet extends React.PureComponent { }).then(({ components, paging }) => ({ paging, results: components })); }; - loadSearchResultCount = (file: TreeComponent) => { - return this.props.loadSearchResultCount({ files: [file.id] }); + loadSearchResultCount = (files: TreeComponent[]) => { + return this.props.loadSearchResultCount('files', { files: files.map(file => file.id) }); }; renderFile = (file: React.ReactNode) => ( diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.tsx index bfe9952e7bd..c6e3bef5d38 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { uniqBy, omit } from 'lodash'; import { connect } from 'react-redux'; import ListStyleFacet from '../../../components/facet/ListStyleFacet'; -import { Query, ReferencedLanguage } from '../utils'; +import { Query, ReferencedLanguage, Facet } from '../utils'; import { getLanguages } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; import { highlightTerm } from '../../../helpers/search'; @@ -35,7 +35,7 @@ interface Props { fetching: boolean; installedLanguages: InstalledLanguage[]; languages: string[]; - loadSearchResultCount: (changes: Partial) => Promise; + loadSearchResultCount: (property: string, changes: Partial) => Promise; onChange: (changes: Partial) => void; onToggle: (property: string) => void; open: boolean; @@ -71,8 +71,10 @@ class LanguageFacet extends React.PureComponent { ); }; - loadSearchResultCount = (language: InstalledLanguage) => { - return this.props.loadSearchResultCount({ languages: [language.key] }); + loadSearchResultCount = (languages: InstalledLanguage[]) => { + return this.props.loadSearchResultCount('languages', { + languages: languages.map(language => language.key) + }); }; renderSearchResult = ({ name }: InstalledLanguage, term: string) => { diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.tsx deleted file mode 100644 index ebc49ff62c8..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 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 * as React from 'react'; -import { connect } from 'react-redux'; -import { differenceWith } from 'lodash'; -import Select from '../../../components/controls/Select'; -import { translate } from '../../../helpers/l10n'; -import { getLanguages } from '../../../store/rootReducer'; - -interface Props { - languages: Array<{ key: string; name: string }>; - onSelect: (value: string) => void; - selected: string[]; -} - -class LanguageFacetFooter extends React.PureComponent { - handleChange = (option: { value: string }) => { - this.props.onSelect(option.value); - }; - - render() { - const options = differenceWith( - this.props.languages, - this.props.selected, - (language, key) => language.key === key - ).map(language => ({ label: language.name, value: language.key })); - - if (options.length === 0) { - return null; - } - - return ( -
-