aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/issues
diff options
context:
space:
mode:
authorPascal Mugnier <pascal.mugnier@sonarsource.com>2018-07-30 14:49:25 +0200
committerSonarTech <sonartech@sonarsource.com>2018-08-02 20:21:32 +0200
commitd0242b05cdd2c419055a162d56fc6f95c930cca8 (patch)
tree118c1b5e9430c10018d63a8520cb6dd4aabb69d2 /server/sonar-web/src/main/js/apps/issues
parent2d10f95a8da89ea498eab5a7fe5a38ed9af23849 (diff)
downloadsonarqube-d0242b05cdd2c419055a162d56fc6f95c930cca8.tar.gz
sonarqube-d0242b05cdd2c419055a162d56fc6f95c930cca8.zip
SONAR-9178 Make spinner noticeable on loading projects issues or measure
Diffstat (limited to 'server/sonar-web/src/main/js/apps/issues')
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/App.tsx59
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx18
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap16
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap16
23 files changed, 142 insertions, 29 deletions
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 384faec119a..dd2288d8346 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
@@ -20,7 +20,7 @@
import * as React from 'react';
import Helmet from 'react-helmet';
import * as key from 'keymaster';
-import { keyBy, union, without } from 'lodash';
+import { keyBy, omit, union, without } from 'lodash';
import * as PropTypes from 'prop-types';
import BulkChangeModal from './BulkChangeModal';
import ComponentBreadcrumbs from './ComponentBreadcrumbs';
@@ -75,6 +75,7 @@ import DropdownIcon from '../../../components/icons-components/DropdownIcon';
import { isSonarCloud } from '../../../helpers/system';
import '../../../components/search-navigator.css';
import '../styles.css';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface FetchIssuesPromise {
components: ReferencedComponent[];
@@ -104,6 +105,7 @@ export interface State {
issues: Issue[];
lastChecked?: string;
loading: boolean;
+ loadingFacets: { [key: string]: boolean };
locationsNavigator: boolean;
myIssues: boolean;
openFacets: { [facet: string]: boolean };
@@ -136,6 +138,7 @@ export default class App extends React.PureComponent<Props, State> {
facets: {},
issues: [],
loading: true,
+ loadingFacets: {},
locationsNavigator: false,
myIssues: props.myIssues || areMyIssuesSelected(props.location.query),
openFacets: { severities: true, types: true },
@@ -571,16 +574,21 @@ export default class App extends React.PureComponent<Props, State> {
fetchFacet = (facet: string) => {
const requestOrganizations = facet === 'projects';
+ this.setState(state => ({ loadingFacets: { ...state.loadingFacets, [facet]: true } }));
return this.fetchIssues({ ps: 1, facets: mapFacet(facet) }, false, requestOrganizations).then(
({ facets, ...other }) => {
if (this.mounted) {
this.setState(state => ({
facets: { ...state.facets, ...parseFacets(facets) },
+ loadingFacets: omit(state.loadingFacets, facet),
referencedComponents: {
...state.referencedComponents,
...keyBy(other.components, 'uuid')
},
- referencedLanguages: { ...state.referencedLanguages, ...keyBy(other.languages, 'key') },
+ referencedLanguages: {
+ ...state.referencedLanguages,
+ ...keyBy(other.languages, 'key')
+ },
referencedRules: { ...state.referencedRules, ...keyBy(other.rules, 'key') },
referencedUsers: { ...state.referencedUsers, ...keyBy(other.users, 'login') }
}));
@@ -869,6 +877,7 @@ export default class App extends React.PureComponent<Props, State> {
component={component}
facets={this.state.facets}
loading={this.state.loading}
+ loadingFacets={this.state.loadingFacets}
myIssues={this.state.myIssues}
onFacetToggle={this.handleFacetToggle}
onFilterChange={this.handleFilterChange}
@@ -1004,6 +1013,31 @@ export default class App extends React.PureComponent<Props, State> {
);
}
+ renderPage() {
+ const { openIssue } = this.state;
+ return (
+ <div className="layout-page-main-inner">
+ <DeferredSpinner loading={this.state.loading}>
+ {openIssue ? (
+ <IssuesSourceViewer
+ branchLike={fillBranchLike(openIssue.branch, openIssue.pullRequest)}
+ loadIssues={this.fetchIssuesForComponent}
+ locationsNavigator={this.state.locationsNavigator}
+ onIssueChange={this.handleIssueChange}
+ onIssueSelect={this.openIssue}
+ onLocationSelect={this.selectLocation}
+ openIssue={openIssue}
+ selectedFlowIndex={this.state.selectedFlowIndex}
+ selectedLocationIndex={this.state.selectedLocationIndex}
+ />
+ ) : (
+ this.renderList()
+ )}
+ </DeferredSpinner>
+ </div>
+ );
+ }
+
render() {
const { component } = this.props;
const { openIssue, paging } = this.state;
@@ -1038,7 +1072,6 @@ export default class App extends React.PureComponent<Props, State> {
!this.props.component &&
(!isSonarCloud() || this.props.myIssues)
)}
- loading={this.state.loading}
onReload={this.handleReload}
paging={paging}
selectedIndex={selectedIndex}
@@ -1049,25 +1082,7 @@ export default class App extends React.PureComponent<Props, State> {
</div>
</div>
- <div className="layout-page-main-inner">
- <div>
- {openIssue ? (
- <IssuesSourceViewer
- branchLike={fillBranchLike(openIssue.branch, openIssue.pullRequest)}
- loadIssues={this.fetchIssuesForComponent}
- locationsNavigator={this.state.locationsNavigator}
- onIssueChange={this.handleIssueChange}
- onIssueSelect={this.openIssue}
- onLocationSelect={this.selectLocation}
- openIssue={openIssue}
- selectedFlowIndex={this.state.selectedFlowIndex}
- selectedLocationIndex={this.state.selectedLocationIndex}
- />
- ) : (
- this.renderList()
- )}
- </div>
- </div>
+ {this.renderPage()}
</div>
</div>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx b/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx
index 38e0821b0e9..330409caa95 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx
@@ -21,14 +21,12 @@ import * as React from 'react';
import IssuesCounter from './IssuesCounter';
import ReloadButton from './ReloadButton';
import { HomePageType, Paging } from '../../../app/types';
-import DeferredSpinner from '../../../components/common/DeferredSpinner';
import HomePageSelect from '../../../components/controls/HomePageSelect';
import { translate } from '../../../helpers/l10n';
import { isSonarCloud } from '../../../helpers/system';
interface Props {
canSetHome: boolean;
- loading: boolean;
onReload: () => void;
paging: Paging | undefined;
selectedIndex: number | undefined;
@@ -61,9 +59,7 @@ export default class PageActions extends React.PureComponent<Props> {
{this.renderShortcuts()}
<div className="issues-page-actions">
- <DeferredSpinner className="issues-main-header-spinner" loading={this.props.loading}>
- <ReloadButton onClick={this.props.onReload} />
- </DeferredSpinner>
+ <ReloadButton onClick={this.props.onReload} />
{paging != null && (
<IssuesCounter className="spacer-left" current={selectedIndex} total={paging.total} />
)}
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 7e671e03616..73c22e1498e 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
@@ -28,11 +28,13 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import Avatar from '../../../components/ui/Avatar';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
export interface Props {
assigned: boolean;
assignees: string[];
component: Component | undefined;
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -201,6 +203,7 @@ export default class AssigneeFacet extends React.PureComponent<Props> {
values={this.getValues()}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
{this.props.open && this.renderFooter()}
</FacetBox>
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 9ea5200d8d5..a163c43c363 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
@@ -25,8 +25,10 @@ import FacetHeader from '../../../components/facet/FacetHeader';
import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -107,6 +109,7 @@ export default class AuthorFacet extends React.PureComponent<Props> {
values={this.props.authors}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.tsx
index 7d242ebf048..db6e7f6eff1 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.tsx
@@ -33,6 +33,7 @@ import DateRangeInput from '../../../components/controls/DateRangeInput';
import { isSameDay, parseDate } from '../../../helpers/dates';
import { translate } from '../../../helpers/l10n';
import { formatMeasure } from '../../../helpers/measures';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
component: Component | undefined;
@@ -40,6 +41,7 @@ interface Props {
createdAt: string;
createdBefore: Date | undefined;
createdInLast: string;
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -290,6 +292,7 @@ export default class CreationDateFacet extends React.PureComponent<Props> {
values={this.getValues()}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderInner()}
</FacetBox>
);
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 248418cee17..b2aa50d02f5 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
@@ -27,8 +27,10 @@ import FacetItemsList from '../../../components/facet/FacetItemsList';
import QualifierIcon from '../../../components/icons-components/QualifierIcon';
import { translate } from '../../../helpers/l10n';
import { collapsePath } from '../../../helpers/path';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
directories: string[];
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
@@ -125,6 +127,7 @@ export default class DirectoryFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
</FacetBox>
);
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 28a798a2429..86063f1be60 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
@@ -27,8 +27,10 @@ import FacetItemsList from '../../../components/facet/FacetItemsList';
import QualifierIcon from '../../../components/icons-components/QualifierIcon';
import { translate } from '../../../helpers/l10n';
import { collapsePath } from '../../../helpers/path';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
files: string[];
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
@@ -126,6 +128,7 @@ export default class FileFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
</FacetBox>
);
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 2c63c463044..81585ed2f97 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
@@ -26,8 +26,10 @@ import FacetHeader from '../../../components/facet/FacetHeader';
import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
languages: string[];
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
@@ -130,6 +132,7 @@ export default class LanguageFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
{this.props.open && this.renderFooter()}
</FacetBox>
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.tsx
index faf97f7d5ae..3f4ec1fb9a4 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.tsx
@@ -26,8 +26,10 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import QualifierIcon from '../../../components/icons-components/QualifierIcon';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
modules: string[];
onChange: (changes: Partial<Query>) => void;
@@ -124,6 +126,7 @@ export default class ModuleFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.tsx
index c684af5b1cd..5163f9683f0 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.tsx
@@ -30,10 +30,12 @@ import FacetFooter from '../../../components/facet/FacetFooter';
import Organization from '../../../components/shared/Organization';
import QualifierIcon from '../../../components/icons-components/QualifierIcon';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
component: Component | undefined;
loading?: boolean;
+ fetching: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
open: boolean;
@@ -192,7 +194,7 @@ export default class ProjectFacet extends React.PureComponent<Props> {
open={this.props.open}
values={values}
/>
-
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
{this.props.open && this.renderFooter()}
</FacetBox>
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx
index 1a6163d9124..1ad489a6e29 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx
@@ -25,8 +25,10 @@ import FacetHeader from '../../../components/facet/FacetHeader';
import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -124,6 +126,7 @@ export default class ResolutionFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && <FacetItemsList>{resolutions.map(this.renderItem)}</FacetItemsList>}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.tsx
index e2db449dc3c..46f58bd9e4d 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.tsx
@@ -27,8 +27,10 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import FacetFooter from '../../../components/facet/FacetFooter';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
languages: string[];
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
@@ -144,6 +146,7 @@ export default class RuleFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
{this.props.open && this.renderFooter()}
</FacetBox>
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.tsx
index 5d2e61b5e58..dba8a5366bf 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.tsx
@@ -26,8 +26,10 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import SeverityHelper from '../../../components/shared/SeverityHelper';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -104,6 +106,7 @@ export default class SeverityFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && <FacetItemsList>{severities.map(this.renderItem)}</FacetItemsList>}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
index 906e9245842..ace5779f36b 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
@@ -47,6 +47,7 @@ export interface Props {
component: Component | undefined;
facets: { [facet: string]: Facet };
loading?: boolean;
+ loadingFacets: { [key: string]: boolean };
myIssues: boolean;
onFacetToggle: (property: string) => void;
onFilterChange: (changes: Partial<Query>) => void;
@@ -77,6 +78,7 @@ export default class Sidebar extends React.PureComponent<Props> {
return (
<div className="search-navigator-facets-list">
<TypeFacet
+ fetching={this.props.loadingFacets.types === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -85,6 +87,7 @@ export default class Sidebar extends React.PureComponent<Props> {
types={query.types}
/>
<SeverityFacet
+ fetching={this.props.loadingFacets.severities === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -93,6 +96,7 @@ export default class Sidebar extends React.PureComponent<Props> {
stats={facets.severities}
/>
<ResolutionFacet
+ fetching={this.props.loadingFacets.resolutions === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -102,6 +106,7 @@ export default class Sidebar extends React.PureComponent<Props> {
stats={facets.resolutions}
/>
<StatusFacet
+ fetching={this.props.loadingFacets.statuses === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -115,6 +120,7 @@ export default class Sidebar extends React.PureComponent<Props> {
createdAt={query.createdAt}
createdBefore={query.createdBefore}
createdInLast={query.createdInLast}
+ fetching={this.props.loadingFacets.createdAt === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -123,6 +129,7 @@ export default class Sidebar extends React.PureComponent<Props> {
stats={facets.createdAt}
/>
<LanguageFacet
+ fetching={this.props.loadingFacets.languages === true}
languages={query.languages}
loading={this.props.loading}
onChange={this.props.onFilterChange}
@@ -132,6 +139,7 @@ export default class Sidebar extends React.PureComponent<Props> {
stats={facets.languages}
/>
<RuleFacet
+ fetching={this.props.loadingFacets.rules === true}
languages={query.languages}
loading={this.props.loading}
onChange={this.props.onFilterChange}
@@ -146,6 +154,9 @@ export default class Sidebar extends React.PureComponent<Props> {
cwe={query.cwe}
cweOpen={!!openFacets.cwe}
cweStats={facets.cwe}
+ fetchingCwe={this.props.loadingFacets.cwe === true}
+ fetchingOwaspTop10={this.props.loadingFacets.owaspTop10 === true}
+ fetchingSansTop25={this.props.loadingFacets.sansTop25 === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -159,6 +170,7 @@ export default class Sidebar extends React.PureComponent<Props> {
/>
<TagFacet
component={component}
+ fetching={this.props.loadingFacets.tags === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -170,6 +182,7 @@ export default class Sidebar extends React.PureComponent<Props> {
{displayProjectsFacet && (
<ProjectFacet
component={component}
+ fetching={this.props.loadingFacets.projects === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -182,6 +195,7 @@ export default class Sidebar extends React.PureComponent<Props> {
)}
{displayModulesFacet && (
<ModuleFacet
+ fetching={this.props.loadingFacets.modules === true}
loading={this.props.loading}
modules={query.modules}
onChange={this.props.onFilterChange}
@@ -194,6 +208,7 @@ export default class Sidebar extends React.PureComponent<Props> {
{displayDirectoriesFacet && (
<DirectoryFacet
directories={query.directories}
+ fetching={this.props.loadingFacets.directories === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -204,6 +219,7 @@ export default class Sidebar extends React.PureComponent<Props> {
)}
{displayFilesFacet && (
<FileFacet
+ fetching={this.props.loadingFacets.files === true}
files={query.files}
loading={this.props.loading}
onChange={this.props.onFilterChange}
@@ -218,6 +234,7 @@ export default class Sidebar extends React.PureComponent<Props> {
assigned={query.assigned}
assignees={query.assignees}
component={component}
+ fetching={this.props.loadingFacets.assignees === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
@@ -230,6 +247,7 @@ export default class Sidebar extends React.PureComponent<Props> {
{displayAuthorFacet && (
<AuthorFacet
authors={query.authors}
+ fetching={this.props.loadingFacets.authors === true}
loading={this.props.loading}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
index febd7e1cbdd..9670921d9e1 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
@@ -32,11 +32,15 @@ import {
renderCWECategory,
Standards
} from '../../securityReports/utils';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
export interface Props {
cwe: string[];
cweOpen: boolean;
cweStats: { [x: string]: number } | undefined;
+ fetchingOwaspTop10: boolean;
+ fetchingSansTop25: boolean;
+ fetchingCwe: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -260,6 +264,7 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
renderOwaspTop10Category(this.state.standards, item)
)}
/>
+ <DeferredSpinner loading={this.props.fetchingOwaspTop10} />
{this.props.owaspTop10Open && this.renderOwaspTop10List()}
</FacetBox>
<FacetBox className="is-inner" property="sansTop25">
@@ -271,6 +276,7 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
renderSansTop25Category(this.state.standards, item)
)}
/>
+ <DeferredSpinner loading={this.props.fetchingSansTop25} />
{this.props.sansTop25Open && this.renderSansTop25List()}
</FacetBox>
<FacetBox className="is-inner" property="cwe">
@@ -280,6 +286,7 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
open={this.props.cweOpen}
values={this.props.cwe.map(item => renderCWECategory(this.state.standards, item))}
/>
+ <DeferredSpinner loading={this.props.fetchingCwe} />
{this.props.cweOpen && this.renderCWEList()}
{this.props.cweOpen && this.renderCWESearch()}
</FacetBox>
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.tsx
index dea89105567..1eb4e060fc2 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.tsx
@@ -26,8 +26,10 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import StatusHelper from '../../../components/shared/StatusHelper';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -104,6 +106,7 @@ export default class StatusFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && <FacetItemsList>{statuses.map(this.renderItem)}</FacetItemsList>}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.tsx
index 2db0f5c9118..c4a804d0e69 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.tsx
@@ -30,9 +30,11 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import TagsIcon from '../../../components/icons-components/TagsIcon';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
component: Component | undefined;
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -143,8 +145,8 @@ export default class TagFacet extends React.PureComponent<Props> {
values={this.props.tags}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && this.renderList()}
-
{this.props.open && this.renderFooter()}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx
index 62900a529a3..6246b462078 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.tsx
@@ -26,8 +26,10 @@ import FacetItem from '../../../components/facet/FacetItem';
import FacetItemsList from '../../../components/facet/FacetItemsList';
import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
import { translate } from '../../../helpers/l10n';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface Props {
+ fetching: boolean;
loading?: boolean;
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
@@ -118,6 +120,7 @@ export default class TypeFacet extends React.PureComponent<Props> {
values={values}
/>
+ <DeferredSpinner loading={this.props.fetching} />
{this.props.open && <FacetItemsList>{types.map(this.renderItem)}</FacetItemsList>}
</FacetBox>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx
index efed16ca848..64217b4de0b 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx
@@ -29,6 +29,7 @@ const renderAssigneeFacet = (props?: Partial<Props>) =>
assigned={true}
assignees={[]}
component={undefined}
+ fetching={false}
onChange={jest.fn()}
onToggle={jest.fn()}
open={true}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx
index cbffca5d94c..7b658ae3db0 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx
@@ -29,6 +29,7 @@ const renderSidebar = (props?: Partial<Props>) =>
<Sidebar
component={undefined}
facets={{}}
+ loadingFacets={{}}
myIssues={false}
onFacetToggle={jest.fn()}
onFilterChange={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
index f36d3c29176..815d6b03f93 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
@@ -153,6 +153,9 @@ function shallowRender(props: Partial<Props> = {}) {
cwe={[]}
cweOpen={false}
cweStats={{}}
+ fetchingCwe={false}
+ fetchingOwaspTop10={false}
+ fetchingSansTop25={false}
onChange={jest.fn()}
onToggle={jest.fn()}
open={false}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap
index e28401150f4..406c6d77188 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap
@@ -11,6 +11,10 @@ exports[`should render 1`] = `
open={true}
values={Array []}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={false}
@@ -101,6 +105,10 @@ exports[`should render without stats 1`] = `
open={true}
values={Array []}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
</FacetBox>
`;
@@ -119,6 +127,10 @@ exports[`should select unassigned 1`] = `
]
}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={true}
@@ -201,6 +213,10 @@ exports[`should select user 1`] = `
]
}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={false}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap
index 1982863f389..42bf996ded1 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap
@@ -25,6 +25,10 @@ exports[`should render empty sub-facet 1`] = `
open={true}
values={Array []}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<div
className="search-navigator-facet-empty little-spacer-top"
>
@@ -65,6 +69,10 @@ exports[`should render sub-facets 1`] = `
]
}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={false}
@@ -106,6 +114,10 @@ exports[`should render sub-facets 1`] = `
]
}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={false}
@@ -147,6 +159,10 @@ exports[`should render sub-facets 1`] = `
]
}
/>
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ />
<FacetItemsList>
<FacetItem
active={true}