diff options
author | Viktor Vorona <viktor.vorona@sonarsource.com> | 2023-08-10 12:25:28 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-08-15 20:02:41 +0000 |
commit | d72f2c84df6986c8a097be153269eae7f5ba0ea5 (patch) | |
tree | e23528873565d9228f481c9a50491fcdc927e906 /server/sonar-web/src/main | |
parent | 4f7c8b3b77dd11e655b20fdf40654881d98176f3 (diff) | |
download | sonarqube-d72f2c84df6986c8a097be153269eae7f5ba0ea5.tar.gz sonarqube-d72f2c84df6986c8a097be153269eae7f5ba0ea5.zip |
SONAR-19465 Remove deferred state from spinner
Diffstat (limited to 'server/sonar-web/src/main')
124 files changed, 530 insertions, 615 deletions
diff --git a/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchShowMore.tsx b/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchShowMore.tsx index ded1f414256..eb63b27a859 100644 --- a/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchShowMore.tsx +++ b/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchShowMore.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import classNames from 'classnames'; -import { DeferredSpinner, ItemButton } from 'design-system'; +import { ItemButton, Spinner } from 'design-system'; import * as React from 'react'; import { translate } from '../../../helpers/l10n'; @@ -61,9 +61,7 @@ export default class GlobalSearchShowMore extends React.PureComponent<Props> { this.handleMouseEnter(qualifier); }} > - <DeferredSpinner loading={loadingMore === qualifier}> - {translate('show_more')} - </DeferredSpinner> + <Spinner loading={loadingMore === qualifier}>{translate('show_more')}</Spinner> </ItemButton> ); } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx index a082485aa65..b76fbe499de 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisStatus.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, FlagMessage, Link } from 'design-system'; +import { FlagMessage, Link, Spinner } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { useBranchWarrningQuery } from '../../../../queries/branch'; @@ -48,7 +48,7 @@ export function AnalysisStatus(props: HeaderMetaProps) { if (isInProgress || isPending) { return ( <div className="sw-flex sw-items-center"> - <DeferredSpinner timeout={0} /> + <Spinner /> <span className="sw-ml-1"> {isInProgress ? translate('project_navigation.analysis_status.in_progress') diff --git a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisWarningsModal.tsx b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisWarningsModal.tsx index 90f7da97609..cd599a72a75 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/AnalysisWarningsModal.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/AnalysisWarningsModal.tsx @@ -17,13 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { - DangerButtonSecondary, - DeferredSpinner, - FlagMessage, - HtmlFormatter, - Modal, -} from 'design-system'; +import { DangerButtonSecondary, FlagMessage, HtmlFormatter, Modal, Spinner } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { sanitizeStringRestricted } from '../../../../helpers/sanitize'; @@ -77,10 +71,7 @@ export function AnalysisWarningsModal(props: Props) { {translate('dismiss_permanently')} </DangerButtonSecondary> - <DeferredSpinner - className="sw-ml-2" - loading={isLoading && variables?.key === key} - /> + <Spinner className="sw-ml-2" loading={isLoading && variables?.key === key} /> </div> )} </div> diff --git a/server/sonar-web/src/main/js/app/styles/init/misc.css b/server/sonar-web/src/main/js/app/styles/init/misc.css index 526a667115d..6ac611f45a6 100644 --- a/server/sonar-web/src/main/js/app/styles/init/misc.css +++ b/server/sonar-web/src/main/js/app/styles/init/misc.css @@ -42,7 +42,7 @@ th.hide-overflow { .a11y-hidden { position: absolute !important; left: -10000px !important; - top: auto !important; + top: 0 !important; width: 1px !important; height: 1px !important; overflow: hidden !important; diff --git a/server/sonar-web/src/main/js/apps/account/__tests__/Account-it.tsx b/server/sonar-web/src/main/js/apps/account/__tests__/Account-it.tsx index 4fbc29fdf32..e050c593a66 100644 --- a/server/sonar-web/src/main/js/apps/account/__tests__/Account-it.tsx +++ b/server/sonar-web/src/main/js/apps/account/__tests__/Account-it.tsx @@ -559,7 +559,7 @@ describe('notifications page', () => { renderAccountApp(mockLoggedInUser(), notificationsPagePath); await user.click( - screen.getByRole('button', { name: 'my_profile.per_project_notifications.add' }) + await screen.findByRole('button', { name: 'my_profile.per_project_notifications.add' }) ); expect(screen.getByLabelText('search.placeholder', { selector: 'input' })).toBeInTheDocument(); await user.keyboard('sonarqube'); diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx index 1321037e356..8e1ba6aaf3e 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx +++ b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx @@ -25,7 +25,7 @@ import { WithNotificationsProps, } from '../../../components/hoc/withNotifications'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import GlobalNotifications from './GlobalNotifications'; import Projects from './Projects'; @@ -47,7 +47,7 @@ export function Notifications(props: WithNotificationsProps) { <div className="account-body account-container"> <Helmet defer={false} title={translate('my_account.notifications')} /> <Alert variant="info">{translate('notification.dispatcher.information')}</Alert> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {notifications && ( <> <GlobalNotifications @@ -66,7 +66,7 @@ export function Notifications(props: WithNotificationsProps) { /> </> )} - </DeferredSpinner> + </Spinner> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/AnalysisWarningsModal.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/AnalysisWarningsModal.tsx index c585b9a8da3..a53b2200515 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/AnalysisWarningsModal.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/AnalysisWarningsModal.tsx @@ -17,13 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { - DangerButtonSecondary, - DeferredSpinner, - FlagMessage, - HtmlFormatter, - Modal, -} from 'design-system'; +import { DangerButtonSecondary, FlagMessage, HtmlFormatter, Modal, Spinner } from 'design-system'; import * as React from 'react'; import { dismissAnalysisWarning, getTask } from '../../../api/ce'; import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext'; @@ -116,7 +110,7 @@ export class AnalysisWarningsModal extends React.PureComponent<Props, State> { const header = translate('warnings'); const body = ( - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {warnings.map(({ dismissable, key, message }) => ( <React.Fragment key={key}> <div className="sw-flex sw-items-center sw-mt-2"> @@ -143,13 +137,13 @@ export class AnalysisWarningsModal extends React.PureComponent<Props, State> { {translate('dismiss_permanently')} </DangerButtonSecondary> - <DeferredSpinner className="sw-ml-2" loading={dismissedWarning === key} /> + <Spinner className="sw-ml-2" loading={dismissedWarning === key} /> </div> )} </div> </React.Fragment> ))} - </DeferredSpinner> + </Spinner> ); return ( diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx index 3d5aa565930..62946b6765e 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx @@ -31,7 +31,7 @@ import withComponentContext from '../../../app/components/componentContext/withC import ListFooter from '../../../components/controls/ListFooter'; import Suggestions from '../../../components/embed-docs-modal/Suggestions'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { toShortISO8601String } from '../../../helpers/dates'; import { translate } from '../../../helpers/l10n'; import { parseAsDate } from '../../../helpers/query'; @@ -218,7 +218,7 @@ export class BackgroundTasksApp extends React.PureComponent<Props, State> { return ( <div className="page page-limited"> <Helmet defer={false} title={translate('background_tasks.page')} /> - <DeferredSpinner loading /> + <Spinner /> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx index d7ea12754eb..d420d15d43b 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx @@ -19,12 +19,12 @@ */ import { Card, - DeferredSpinner, FlagMessage, HelperHintIcon, KeyboardHint, LargeCenteredLayout, LightLabel, + Spinner, } from 'design-system'; import { intersection } from 'lodash'; import * as React from 'react'; @@ -182,7 +182,7 @@ export default function CodeAppRenderer(props: Props) { {(showComponentList || showSearch) && ( <Card className="sw-mt-2"> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {showComponentList && ( <Components baseComponent={baseComponent} @@ -212,7 +212,7 @@ export default function CodeAppRenderer(props: Props) { selected={highlighted} /> )} - </DeferredSpinner> + </Spinner> </Card> )} diff --git a/server/sonar-web/src/main/js/apps/code/components/Search.tsx b/server/sonar-web/src/main/js/apps/code/components/Search.tsx index 3c1323fe81b..f7d8252248a 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Search.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/Search.tsx @@ -23,7 +23,7 @@ import { isEmpty, omit } from 'lodash'; import * as React from 'react'; import { getTree } from '../../../api/components'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { KeyboardKeys } from '../../../helpers/keycodes'; import { translate } from '../../../helpers/l10n'; @@ -176,7 +176,7 @@ class Search extends React.PureComponent<Props, State> { size="large" value={this.state.query} /> - <DeferredSpinner className="sw-ml-2" loading={loading} /> + <Spinner className="sw-ml-2" loading={loading} /> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetails.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetails.tsx index 4b59c2c0b60..27233ef7bba 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetails.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetails.tsx @@ -23,7 +23,7 @@ import { deleteRule, getRuleDetails, updateRule } from '../../../api/rules'; import ConfirmButton from '../../../components/controls/ConfirmButton'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import { Button } from '../../../components/controls/buttons'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Dict, RuleActivation, RuleDetails as TypeRuleDetails } from '../../../types/types'; import { Activation, Query } from '../query'; @@ -163,7 +163,7 @@ export default class RuleDetails extends React.PureComponent<Props, State> { return ( <div className="coding-rule-details"> - <DeferredSpinner loading={this.state.loading}> + <Spinner loading={this.state.loading}> <RuleDetailsMeta canWrite={canWrite} onFilterChange={this.props.onFilterChange} @@ -252,7 +252,7 @@ export default class RuleDetails extends React.PureComponent<Props, State> { {!ruleDetails.isTemplate && ruleDetails.type !== 'SECURITY_HOTSPOT' && ( <RuleDetailsIssues ruleDetails={ruleDetails} /> )} - </DeferredSpinner> + </Spinner> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsCustomRules.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsCustomRules.tsx index cd1d53047d5..de10ac4a3a8 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsCustomRules.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsCustomRules.tsx @@ -24,7 +24,7 @@ import Link from '../../../components/common/Link'; import ConfirmButton from '../../../components/controls/ConfirmButton'; import { Button } from '../../../components/controls/buttons'; import SeverityHelper from '../../../components/shared/SeverityHelper'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getRuleUrl } from '../../../helpers/urls'; import { Rule, RuleDetails } from '../../../types/types'; @@ -164,13 +164,13 @@ export default class RuleDetailsCustomRules extends React.PureComponent<Props, S </CustomRuleButton> )} - <DeferredSpinner className="spacer-left" loading={loading}> + <Spinner className="spacer-left" loading={loading}> {rules.length > 0 && ( <table className="coding-rules-detail-list" id="coding-rules-detail-custom-rules"> <tbody>{sortBy(rules, (rule) => rule.name).map(this.renderRule)}</tbody> </table> )} - </DeferredSpinner> + </Spinner> </div> </div> ); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsIssues.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsIssues.tsx index 344e90a0bec..d57d9a00006 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsIssues.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsIssues.tsx @@ -24,7 +24,7 @@ import withAvailableFeatures, { } from '../../../app/components/available-features/withAvailableFeatures'; import Link from '../../../components/common/Link'; import Tooltip from '../../../components/controls/Tooltip'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import { getIssuesUrl } from '../../../helpers/urls'; @@ -149,7 +149,7 @@ export class RuleDetailsIssues extends React.PureComponent<Props, State> { return ( <div className="js-rule-issues coding-rule-section"> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <h2 className="coding-rules-detail-title"> {translate('coding_rules.issues')} {this.renderTotal()} @@ -171,7 +171,7 @@ export class RuleDetailsIssues extends React.PureComponent<Props, State> { {translate('coding_rules.no_issue_detected_for_projects')} </div> )} - </DeferredSpinner> + </Spinner> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/StandardFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/StandardFacet.tsx index 3b6382f99ea..41495c49953 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/StandardFacet.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/StandardFacet.tsx @@ -28,7 +28,7 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import ListStyleFacet from '../../../components/facet/ListStyleFacet'; import ListStyleFacetFooter from '../../../components/facet/ListStyleFacetFooter'; import MultipleSelectionHint from '../../../components/facet/MultipleSelectionHint'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { highlightTerm } from '../../../helpers/search'; import { @@ -236,7 +236,7 @@ export class StandardFacet extends React.PureComponent<Props, State> { const values = this.props[valuesProp]; if (!stats) { - return <DeferredSpinner className="sw-ml-4" />; + return <Spinner className="sw-ml-4" />; } const categories = sortBy(Object.keys(stats), (key) => -stats[key]); @@ -321,7 +321,7 @@ export class StandardFacet extends React.PureComponent<Props, State> { const values = this.props.sonarsourceSecurity; if (!stats) { - return <DeferredSpinner className="sw-ml-4" />; + return <Spinner className="sw-ml-4" />; } const sortedItems = sortBy( diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx index 33a9263ee3c..1d58466994b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx @@ -20,10 +20,10 @@ import { withTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { - DeferredSpinner, LargeCenteredLayout, Note, PageContentFontWrapper, + Spinner, themeBorder, themeColor, } from 'design-system'; @@ -266,10 +266,7 @@ class ComponentMeasuresApp extends React.PureComponent<Props, State> { <Suggestions suggestions="component_measures" /> <Helmet defer={false} title={translate('layout.measures')} /> <PageContentFontWrapper> - <DeferredSpinner - className="my-10 sw-flex sw-content-center" - loading={this.state.loading} - /> + <Spinner className="my-10 sw-flex sw-content-center" loading={this.state.loading} /> {measures.length > 0 ? ( <div className="sw-grid sw-grid-cols-12 sw-w-full"> diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.tsx index 95a8382f216..4fb34c5cfa3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner } from 'design-system'; +import { Spinner } from 'design-system'; import * as React from 'react'; import { getComponentLeaves } from '../../../api/components'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; @@ -169,7 +169,7 @@ export default class MeasureOverview extends React.PureComponent<Props, State> { /> <div className="sw-p-6"> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> {!loading && this.renderContent(isFileComponent)} </div> </div> diff --git a/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx index 55a12b730d4..c7a681f82f1 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzurePersonalAccessTokenForm.tsx @@ -19,7 +19,7 @@ */ import { ButtonPrimary, - DeferredSpinner, + Spinner, FlagErrorIcon, FlagMessage, FormField, @@ -61,7 +61,7 @@ export default function AzurePersonalAccessTokenForm({ } = usePersonalAccessToken(almSetting, resetPat, onPersonalAccessTokenCreate); if (checkingPat) { - return <DeferredSpinner className="sw-ml-2" loading />; + return <Spinner className="sw-ml-2" loading />; } const isInvalid = (validationFailed && !touched) || (touched && !password); @@ -147,7 +147,7 @@ export default function AzurePersonalAccessTokenForm({ <ButtonPrimary type="submit" disabled={isInvalid || submitting || !touched}> {translate('save')} </ButtonPrimary> - <DeferredSpinner className="sw-ml-2" loading={submitting} /> + <Spinner className="sw-ml-2" loading={submitting} /> </div> </form> ); diff --git a/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx index 9bc4aaa19c8..5d4001510d6 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectAccordion.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { Accordion, DeferredSpinner, FlagMessage, Link, SearchHighlighter } from 'design-system'; +import { Accordion, Spinner, FlagMessage, Link, SearchHighlighter } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import ListFooter from '../../../../components/controls/ListFooter'; @@ -66,9 +66,8 @@ export default function AzureProjectAccordion(props: AzureProjectAccordionProps) > {/* eslint-disable-next-line local-rules/no-conditional-rendering-of-deferredspinner*/} {open && ( - <DeferredSpinner loading={loading}> - {/* The extra loading guard is to prevent the flash of the Alert */} - {!loading && repositories.length === 0 ? ( + <Spinner loading={loading}> + {repositories.length === 0 ? ( <FlagMessage variant="warning"> <span> <FormattedMessage @@ -118,7 +117,7 @@ export default function AzureProjectAccordion(props: AzureProjectAccordionProps) /> </> )} - </DeferredSpinner> + </Spinner> )} </Accordion> ); diff --git a/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx index c775999c4d6..0dfb6b79fd8 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Azure/AzureProjectCreateRenderer.tsx @@ -18,12 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { - DeferredSpinner, FlagMessage, InputSearch, LightPrimary, Link, PageContentFontWrapper, + Spinner, Title, } from 'design-system'; import * as React from 'react'; @@ -94,7 +94,7 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend onChangeConfig={props.onSelectedAlmInstanceChange} /> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> {showUrlError && ( <FlagMessage variant="error" className="sw-mb-2"> @@ -142,7 +142,7 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend size="full" /> </div> - <DeferredSpinner loading={Boolean(searching)}> + <Spinner loading={Boolean(searching)}> <AzureProjectsList loadingRepositories={loadingRepositories} onOpenProject={props.onOpenProject} @@ -152,7 +152,7 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend searchResults={searchResults} searchQuery={searchQuery} /> - </DeferredSpinner> + </Spinner> </> ))} </PageContentFontWrapper> diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx index e703e78bef6..e33feb31caf 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudPersonalAccessTokenForm.tsx @@ -20,13 +20,13 @@ import { ButtonPrimary, - DeferredSpinner, FlagErrorIcon, FlagMessage, FormField, InputField, LightPrimary, Link, + Spinner, } from 'design-system'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -60,7 +60,7 @@ export default function BitbucketCloudPersonalAccessTokenForm({ } = usePersonalAccessToken(almSetting, resetPat, onPersonalAccessTokenCreated); if (checkingPat) { - return <DeferredSpinner className="sw-ml-2" loading />; + return <Spinner className="sw-ml-2" loading />; } const isInvalid = validationFailed && !touched; @@ -179,7 +179,7 @@ export default function BitbucketCloudPersonalAccessTokenForm({ <ButtonPrimary type="submit" disabled={submitButtonDiabled} className="sw-mb-6"> {translate('save')} </ButtonPrimary> - <DeferredSpinner className="sw-ml-2" loading={submitting} /> + <Spinner className="sw-ml-2" loading={submitting} /> </form> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx index 8cd8154af31..0682393082b 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, LightPrimary, Title } from 'design-system'; +import { LightPrimary, Spinner, Title } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { BitbucketCloudRepository } from '../../../../types/alm-integration'; @@ -81,7 +81,7 @@ export default function BitbucketCloudProjectCreateRenderer( onChangeConfig={props.onSelectedAlmInstanceChange} /> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> {!loading && !selectedAlmInstance && ( <WrongBindingCountAlert alm={AlmKeys.BitbucketCloud} canAdmin={!!canAdmin} /> diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx index c42983bb137..9a6654bb0ef 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, LightPrimary, PageContentFontWrapper, Title } from 'design-system'; +import { LightPrimary, PageContentFontWrapper, Spinner, Title } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { @@ -81,7 +81,7 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr onChangeConfig={props.onSelectedAlmInstanceChange} /> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {!loading && !selectedAlmInstance && ( <WrongBindingCountAlert alm={AlmKeys.BitbucketServer} canAdmin={!!canAdmin} /> )} @@ -104,7 +104,7 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr onImportRepository={props.onImportRepository} /> ))} - </DeferredSpinner> + </Spinner> </PageContentFontWrapper> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx index 4afc74f2460..479d75f929a 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, FlagMessage } from 'design-system'; +import { FlagMessage, Spinner } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { BitbucketProject, BitbucketRepository } from '../../../../types/alm-integration'; @@ -50,7 +50,7 @@ export default function BitbucketSearchResults(props: BitbucketSearchResultsProp ); return ( - <DeferredSpinner loading={searching}> + <Spinner loading={searching}> {filteredSearchResults.length > 0 && ( <BitbucketProjectAccordion onImportRepository={props.onImportRepository} @@ -74,6 +74,6 @@ export default function BitbucketSearchResults(props: BitbucketSearchResultsProp /> ); })} - </DeferredSpinner> + </Spinner> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketServerPersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketServerPersonalAccessTokenForm.tsx index 914cee82adc..885f69aa646 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketServerPersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketServerPersonalAccessTokenForm.tsx @@ -20,13 +20,13 @@ import { ButtonPrimary, - DeferredSpinner, FlagErrorIcon, FlagMessage, FormField, InputField, LightPrimary, Link, + Spinner, } from 'design-system'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -58,7 +58,7 @@ export default function BitbucketServerPersonalAccessTokenForm({ } = usePersonalAccessToken(almSetting, resetPat, onPersonalAccessTokenCreated); if (checkingPat) { - return <DeferredSpinner className="sw-ml-2" loading />; + return <Spinner className="sw-ml-2" loading />; } const { url } = almSetting; @@ -143,7 +143,7 @@ export default function BitbucketServerPersonalAccessTokenForm({ <ButtonPrimary type="submit" disabled={submitButtonDiabled} className="sw-mb-6"> {translate('save')} </ButtonPrimary> - <DeferredSpinner className="sw-ml-2" loading={submitting} /> + <Spinner className="sw-ml-2" loading={submitting} /> </form> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx index ad3055c6b7e..1c0dd2de98c 100644 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx @@ -20,10 +20,10 @@ /* eslint-disable react/no-unused-prop-types */ import { ButtonSecondary, - DeferredSpinner, GreyCard, HelperHintIcon, LightPrimary, + Spinner, StandoutLink, TextMuted, Title, @@ -106,7 +106,7 @@ function renderAlmOption( )} </div> - <DeferredSpinner loading={loadingBindings}> + <Spinner loading={loadingBindings}> {!hasConfig && (canAdmin ? ( <ButtonSecondary onClick={() => props.onConfigMode(configMode)}> @@ -117,7 +117,7 @@ function renderAlmOption( <HelperHintIcon aria-label="help-tooltip" /> </HelpTooltip> ))} - </DeferredSpinner> + </Spinner> </GreyCard> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx index 69de3118fd3..97ffd1f2755 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx @@ -21,12 +21,12 @@ import { DarkLabel, - DeferredSpinner, FlagMessage, InputSearch, InputSelect, LightPrimary, Link, + Spinner, Title, } from 'design-system'; import * as React from 'react'; @@ -131,7 +131,7 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe } = props; if (loadingBindings) { - return <DeferredSpinner />; + return <Spinner />; } return ( @@ -172,7 +172,7 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe </FlagMessage> )} - <DeferredSpinner loading={loadingOrganizations && !error}> + <Spinner loading={loadingOrganizations && !error}> {!error && ( <div className="sw-flex sw-flex-col"> <DarkLabel htmlFor="github-choose-organization" className="sw-mb-2"> @@ -215,7 +215,7 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe )} </div> )} - </DeferredSpinner> + </Spinner> {renderRepositoryList(props)} </> diff --git a/server/sonar-web/src/main/js/apps/create/project/Gitlab/GItlabPersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GItlabPersonalAccessTokenForm.tsx index 2b12662b9dd..e2d3115b00c 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Gitlab/GItlabPersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GItlabPersonalAccessTokenForm.tsx @@ -20,13 +20,13 @@ import { ButtonPrimary, - DeferredSpinner, FlagErrorIcon, FlagMessage, FormField, InputField, LightPrimary, Link, + Spinner, } from 'design-system'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -58,7 +58,7 @@ export default function GitlabPersonalAccessTokenForm({ } = usePersonalAccessToken(almSetting, resetPat, onPersonalAccessTokenCreated); if (checkingPat) { - return <DeferredSpinner className="sw-ml-2" loading />; + return <Spinner className="sw-ml-2" loading />; } const isInvalid = validationFailed && !touched; @@ -136,7 +136,7 @@ export default function GitlabPersonalAccessTokenForm({ <ButtonPrimary type="submit" disabled={submitButtonDiabled} className="sw-mb-6"> {translate('save')} </ButtonPrimary> - <DeferredSpinner className="sw-ml-2" loading={submitting} /> + <Spinner className="sw-ml-2" loading={submitting} /> </form> ); } diff --git a/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx index 0b843afff80..655009755db 100644 --- a/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/Gitlab/GitlabProjectCreateRenderer.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, LightPrimary, Title } from 'design-system'; +import { LightPrimary, Spinner, Title } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; import { GitlabProject } from '../../../../types/alm-integration'; @@ -79,7 +79,7 @@ export default function GitlabProjectCreateRenderer(props: GitlabProjectCreateRe onChangeConfig={props.onSelectedAlmInstanceChange} /> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> {!loading && !selectedAlmInstance && ( <WrongBindingCountAlert alm={AlmKeys.GitLab} canAdmin={!!canAdmin} /> diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx index 7970bde1bf1..c9244c31a63 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx @@ -76,9 +76,6 @@ it('should redirect to github authorization page when not already authorized', a await selectEvent.select(ui.instanceSelector.get(), [/conf-github-1/]); expect(window.location.replace).toHaveBeenCalled(); - expect( - screen.getByText('onboarding.create_project.github.choose_organization') - ).toBeInTheDocument(); }); it('should not redirect to github when url is malformated', async () => { diff --git a/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx b/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx index f331941bdc5..003be840a13 100644 --- a/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { ButtonPrimary, DeferredSpinner, Link, Title } from 'design-system'; +import { ButtonPrimary, Link, Spinner, Title } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { Router } from '../../../../components/hoc/withRouter'; @@ -84,7 +84,7 @@ export default function NewCodeDefinitionSelection(props: Props) { type="submit" > {translate('onboarding.create_project.new_code_definition.create_project')} - <DeferredSpinner className="sw-ml-2" loading={submitting} /> + <Spinner className="sw-ml-2" loading={submitting} /> </ButtonPrimary> </div> </div> diff --git a/server/sonar-web/src/main/js/apps/groups/components/DeleteGroupForm.tsx b/server/sonar-web/src/main/js/apps/groups/components/DeleteGroupForm.tsx index fd716931b76..3345f248d98 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/DeleteGroupForm.tsx +++ b/server/sonar-web/src/main/js/apps/groups/components/DeleteGroupForm.tsx @@ -20,9 +20,9 @@ import * as React from 'react'; import { useCallback } from 'react'; import { deleteGroup } from '../../../api/user_groups'; -import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import SimpleModal from '../../../components/controls/SimpleModal'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Group } from '../../../types/types'; @@ -55,7 +55,7 @@ export default function DeleteGroupForm(props: Props) { </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton className="button-red" disabled={submitting}> {translate('delete')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/groups/components/GroupForm.tsx b/server/sonar-web/src/main/js/apps/groups/components/GroupForm.tsx index 958d8537ee7..b13b23bb7f2 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/GroupForm.tsx +++ b/server/sonar-web/src/main/js/apps/groups/components/GroupForm.tsx @@ -20,11 +20,11 @@ import * as React from 'react'; import { useCallback, useEffect, useState } from 'react'; import { createGroup, updateGroup } from '../../../api/user_groups'; -import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import SimpleModal from '../../../components/controls/SimpleModal'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { omitNil } from '../../../helpers/request'; import { Group } from '../../../types/types'; @@ -123,7 +123,7 @@ export default function GroupForm(props: Props) { </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton disabled={submitting}> {create ? translate('create') : translate('update_verb')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/groups/components/ViewMembersModal.tsx b/server/sonar-web/src/main/js/apps/groups/components/ViewMembersModal.tsx index 76d326fad49..664b6e4d79e 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/ViewMembersModal.tsx +++ b/server/sonar-web/src/main/js/apps/groups/components/ViewMembersModal.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner } from 'design-system/lib'; +import { Spinner } from 'design-system/lib'; import * as React from 'react'; import { getUsersInGroup } from '../../../api/user_groups'; import ListFooter from '../../../components/controls/ListFooter'; @@ -85,7 +85,7 @@ export default function ViewMembersModal(props: Props) { value={query} /> <div className="select-list-list-container spacer-top"> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <ul className="menu"> {users.map((user) => ( <li key={user.login} className="display-flex-center"> @@ -104,7 +104,7 @@ export default function ViewMembersModal(props: Props) { </li> ))} </ul> - </DeferredSpinner> + </Spinner> </div> {total !== undefined && ( <ListFooter count={users.length} loadMore={() => setPage((p) => p + 1)} total={total} /> diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx index e191ebc3d8b..b9c4fb78f98 100644 --- a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx @@ -258,11 +258,10 @@ describe('issues app', () => { expect(screen.getByRole('button', { name: 'issues.bulk_change_X_issues.10' })).toHaveFocus(); await user.click(screen.getByRole('checkbox', { name: 'issues.select_all_issues' })); - // Check that we bulk change the selected issue - const issueBoxFixThat = within(screen.getByRole('region', { name: 'Fix that' })); - expect( - issueBoxFixThat.getByLabelText('issue.type.type_x_click_to_change.issue.type.CODE_SMELL') + within(screen.getByRole('region', { name: 'Fix that' })).getByLabelText( + 'issue.type.type_x_click_to_change.issue.type.CODE_SMELL' + ) ).toBeInTheDocument(); await user.click( @@ -280,7 +279,9 @@ describe('issues app', () => { await user.click(screen.getByRole('button', { name: 'apply' })); expect( - issueBoxFixThat.getByLabelText('issue.type.type_x_click_to_change.issue.type.BUG') + await within(screen.getByRole('region', { name: 'Fix that' })).findByLabelText( + 'issue.type.type_x_click_to_change.issue.type.BUG' + ) ).toBeInTheDocument(); }); }); diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx index bbe8bcc8a46..b9ace10c84d 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx @@ -21,7 +21,6 @@ import { ButtonPrimary, Checkbox, - DeferredSpinner, FlagMessage, FormField, HelperHintIcon, @@ -31,6 +30,7 @@ import { LightLabel, Modal, RadioButton, + Spinner, } from 'design-system'; import { pickBy, sortBy } from 'lodash'; import * as React from 'react'; @@ -449,7 +449,7 @@ export class BulkChangeModal extends React.PureComponent<Props, State> { const limitReached = paging && paging.total > MAX_PAGE_SIZE; return ( - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <form id="bulk-change-form" onSubmit={this.handleSubmit}> {limitReached && ( <FlagMessage className="sw-mb-4" variant="warning"> @@ -479,7 +479,7 @@ export class BulkChangeModal extends React.PureComponent<Props, State> { <FlagMessage variant="warning">{translate('issue_bulk_change.no_match')}</FlagMessage> )} </form> - </DeferredSpinner> + </Spinner> ); }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx index a10a9e73540..4c09972fd5a 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx @@ -51,7 +51,7 @@ import withIndexationGuard from '../../../components/hoc/withIndexationGuard'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; import IssueTabViewer from '../../../components/rules/IssueTabViewer'; import '../../../components/search-navigator.css'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { fillBranchLike, getBranchLikeQuery, isSameBranchLike } from '../../../helpers/branch-like'; import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication'; import { parseIssueFromResponse } from '../../../helpers/issues'; @@ -1227,7 +1227,7 @@ export class App extends React.PureComponent<Props, State> { > {this.renderHeader({ openIssue, paging, selectedIndex })} - <DeferredSpinner loading={loadingRule}> + <Spinner loading={loadingRule}> {/* eslint-disable-next-line local-rules/no-conditional-rendering-of-deferredspinner */} {openIssue && openRuleDetails ? ( <IssueTabViewer @@ -1262,7 +1262,7 @@ export class App extends React.PureComponent<Props, State> { className="sw-px-6 sw-pb-6" style={{ marginTop: `-${PSEUDO_SHADOW_HEIGHT}px` }} > - <DeferredSpinner + <Spinner ariaLabel={translate('issues.loading_issues')} className="sw-mt-4" loading={loading} @@ -1291,10 +1291,10 @@ export class App extends React.PureComponent<Props, State> { )} {this.renderList()} - </DeferredSpinner> + </Spinner> </div> )} - </DeferredSpinner> + </Spinner> </div> )} </ScreenPositionHelper> diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx index 8e5e8551a02..018c43287b7 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx @@ -33,7 +33,7 @@ import { issuesByComponentAndLine, } from '../../../components/SourceViewer/helpers/indexing'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { WorkspaceContext } from '../../../components/workspace/context'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { throwGlobalError } from '../../../helpers/error'; @@ -192,7 +192,7 @@ export default class CrossComponentSourceViewer extends React.PureComponent<Prop if (loading) { return ( <div> - <DeferredSpinner ariaLabel={translate('code_viewer.loading')} /> + <Spinner ariaLabel={translate('code_viewer.loading')} /> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/IssueSourceViewerHeader.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/IssueSourceViewerHeader.tsx index 3c29418ac85..a9973b34848 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/IssueSourceViewerHeader.tsx +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/IssueSourceViewerHeader.tsx @@ -23,11 +23,11 @@ import classNames from 'classnames'; import { ChevronRightIcon, CopyIcon, - DeferredSpinner, HoverLink, InteractiveIcon, LightLabel, Link, + Spinner, ThemeProp, UnfoldIcon, themeColor, @@ -156,7 +156,7 @@ function IssueSourceViewerHeader(props: Props & ThemeProp) { </div> )} - <DeferredSpinner className="sw-mr-1" loading={loading} /> + <Spinner className="sw-mr-1" loading={loading} /> {expandable && !loading && ( <div className="sw-ml-4"> diff --git a/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssuesListHeader.tsx b/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssuesListHeader.tsx index bab12fa0923..17c203ef227 100644 --- a/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssuesListHeader.tsx +++ b/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssuesListHeader.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; -import { DeferredSpinner, SubnavigationHeading, themeBorder } from 'design-system'; +import { Spinner, SubnavigationHeading, themeBorder } from 'design-system'; import * as React from 'react'; import { Paging } from '../../../types/types'; import IssuesCounter from '../components/IssuesCounter'; @@ -34,9 +34,9 @@ export default function SubnavigationIssuesListHeader(props: Props) { return ( <StyledHeader> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {paging && <IssuesCounter current={selectedIndex} total={paging.total} />} - </DeferredSpinner> + </Spinner> </StyledHeader> ); } diff --git a/server/sonar-web/src/main/js/apps/marketplace/App.tsx b/server/sonar-web/src/main/js/apps/marketplace/App.tsx index 9b5afe83d71..cd302fabda3 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/App.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/App.tsx @@ -27,7 +27,7 @@ import DocLink from '../../components/common/DocLink'; import Suggestions from '../../components/embed-docs-modal/Suggestions'; import { Location, Router, withRouter } from '../../components/hoc/withRouter'; import { Alert } from '../../components/ui/Alert'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; +import Spinner from '../../components/ui/Spinner'; import { translate } from '../../helpers/l10n'; import { EditionKey } from '../../types/editions'; import { PendingPluginResult, Plugin, RiskConsent } from '../../types/plugins'; @@ -196,7 +196,7 @@ class App extends React.PureComponent<Props, State> { updateCenterActive={this.props.updateCenterActive} updateQuery={this.updateQuery} /> - <DeferredSpinner loading={loadingPlugins}> + <Spinner loading={loadingPlugins}> {filteredPlugins.length === 0 && translate('marketplace.plugin_list.no_plugins', query.filter)} {filteredPlugins.length > 0 && ( @@ -210,7 +210,7 @@ class App extends React.PureComponent<Props, State> { <Footer total={filteredPlugins.length} /> </> )} - </DeferredSpinner> + </Spinner> </main> ); } diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx index 47ede69bd92..b1bec3ff132 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { BasicSeparator, Card, DeferredSpinner, PageTitle } from 'design-system'; +import { BasicSeparator, Card, PageTitle, Spinner } from 'design-system'; import * as React from 'react'; import GraphsHeader from '../../../components/activity-graph/GraphsHeader'; import GraphsHistory from '../../../components/activity-graph/GraphsHistory'; @@ -115,7 +115,7 @@ export function ActivityPanel(props: ActivityPanelProps) { </div> </Card> <Card className="sw-mt-4" data-test="overview__activity-analyses"> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {filteredAnalyses.length === 0 ? ( <p>{translate('no_results')}</p> ) : ( @@ -126,7 +126,7 @@ export function ActivityPanel(props: ActivityPanelProps) { </div> )) )} - </DeferredSpinner> + </Spinner> </Card> </div> ); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanel.tsx index f6cb093a559..63367c2a442 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanel.tsx @@ -21,11 +21,11 @@ import { Card, CoverageIndicator, - DeferredSpinner, DuplicationsIndicator, FlagMessage, LightLabel, PageTitle, + Spinner, ToggleButton, } from 'design-system'; import * as React from 'react'; @@ -128,7 +128,7 @@ export function MeasuresPanel(props: MeasuresPanelProps) { {loading ? ( <div> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> </div> ) : ( <> diff --git a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx index c31b5cc7f42..3df69b32c76 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanel.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { BasicSeparator, Card, DeferredSpinner } from 'design-system'; +import { BasicSeparator, Card, Spinner } from 'design-system'; import { flatMap } from 'lodash'; import * as React from 'react'; import { ComponentQualifier, isApplication } from '../../../types/component'; @@ -82,7 +82,7 @@ export function QualityGatePanel(props: QualityGatePanelProps) { <div> {loading ? ( <div className="sw-p-6"> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> </div> ) : ( <> diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx index 783b6ed1a89..e7addbf5864 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx @@ -49,7 +49,7 @@ export function EmptyOverview(props: EmptyOverviewProps) { .length > 0; if (isLoading) { - return <Spinner />; + return <Spinner loading />; } if (component.qualifier === ComponentQualifier.Application) { @@ -75,7 +75,7 @@ export function EmptyOverview(props: EmptyOverviewProps) { <PageContentFontWrapper> <FlagMessage variant="warning"> {translate('provisioning.permission_synch_in_progress')} - <Spinner className="sw-ml-8 sw-hidden" aria-hidden /> + <Spinner className="sw-ml-8 sw-hidden" aria-hidden loading /> </FlagMessage> </PageContentFontWrapper> </LargeCenteredLayout> diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx index e01f332016f..61389583269 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx @@ -21,12 +21,12 @@ import { BasicSeparator, Card, CoverageIndicator, - DeferredSpinner, DuplicationsIndicator, HelperHintIcon, LargeCenteredLayout, Link, PageTitle, + Spinner, TextMuted, } from 'design-system'; import { uniq } from 'lodash'; @@ -95,7 +95,7 @@ export default function PullRequestOverview(props: Props) { return ( <LargeCenteredLayout> <div className="sw-p-6"> - <DeferredSpinner loading /> + <Spinner loading /> </div> </LargeCenteredLayout> ); diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/DeleteForm.tsx b/server/sonar-web/src/main/js/apps/permission-templates/components/DeleteForm.tsx index fbf1ffe6ca5..c29b65a05a1 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/DeleteForm.tsx +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/DeleteForm.tsx @@ -18,9 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import SimpleModal from '../../../components/controls/SimpleModal'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { PermissionTemplate } from '../../../types/types'; @@ -49,7 +49,7 @@ export default function DeleteForm({ onClose, onSubmit, permissionTemplate: t }: </div> <div className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton className="button-red" disabled={submitting}> {translate('delete')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Form.tsx b/server/sonar-web/src/main/js/apps/permission-templates/components/Form.tsx index c7927d28bb3..6f00ae26000 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Form.tsx +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Form.tsx @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import SimpleModal from '../../../components/controls/SimpleModal'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; interface Props { @@ -141,7 +141,7 @@ export default class Form extends React.PureComponent<Props, State> { </div> <div className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton disabled={submitting} id="permission-template-submit"> {this.props.confirmButtonText} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Header.tsx b/server/sonar-web/src/main/js/apps/permission-templates/components/Header.tsx index 9b19b8dd794..8ba5375730f 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Header.tsx +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Header.tsx @@ -22,7 +22,7 @@ import { createPermissionTemplate } from '../../../api/permissions'; import { Button } from '../../../components/controls/buttons'; import { Router, withRouter } from '../../../components/hoc/withRouter'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { throwGlobalError } from '../../../helpers/error'; import { translate } from '../../../helpers/l10n'; import { useGithubProvisioningEnabledQuery } from '../../../queries/identity-provider'; @@ -62,7 +62,7 @@ function Header(props: Props) { <header className="page-header" id="project-permissions-header"> <h1 className="page-title">{translate('permission_templates.page')}</h1> - <DeferredSpinner loading={!ready} /> + <Spinner loading={!ready} /> <div className="page-actions"> <Button onClick={() => setCreateModal(true)}>{translate('create')}</Button> diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.tsx b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.tsx index b8396164e9a..3625d0be7a5 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.tsx +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import Link from '../../../components/common/Link'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { PermissionTemplate } from '../../../types/types'; import { PERMISSION_TEMPLATES_PATH } from '../utils'; @@ -42,7 +42,7 @@ export default function TemplateHeader(props: Props) { <h1 className="page-title">{template.name}</h1> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> <div className="pull-right"> <ActionsCell diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx b/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx index bc1d118871c..54e8541bc96 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx @@ -19,13 +19,13 @@ */ import * as React from 'react'; import { applyTemplateToProject, getPermissionTemplates } from '../../../../api/permissions'; -import { ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import Select from '../../../../components/controls/Select'; import SimpleModal from '../../../../components/controls/SimpleModal'; +import { ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; import MandatoryFieldMarker from '../../../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; import { PermissionTemplate } from '../../../../types/types'; @@ -147,7 +147,7 @@ export default class ApplyTemplate extends React.PureComponent<Props, State> { </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> {!this.state.done && ( <SubmitButton disabled={submitting || !this.state.permissionTemplate}> {translate('apply')} diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.tsx b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.tsx index 38d5012a19a..0b452177aca 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.tsx +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import GitHubSynchronisationWarning from '../../../../app/components/GitHubSynchronisationWarning'; import { Button } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; +import Spinner from '../../../../components/ui/Spinner'; import { translate } from '../../../../helpers/l10n'; import { getBaseUrl } from '../../../../helpers/system'; import { useGithubProvisioningEnabledQuery } from '../../../../queries/identity-provider'; @@ -81,7 +81,7 @@ export default function PageHeader(props: Props) { )} </h1> - <DeferredSpinner className="spacer-left" loading={loading} /> + <Spinner className="spacer-left" loading={loading} /> {canApplyPermissionTemplate && ( <div className="page-actions"> diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx index 6ea2f6bf60a..b17cd760b54 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx @@ -20,7 +20,7 @@ import styled from '@emotion/styled'; import classNames from 'classnames'; import { isEqual } from 'date-fns'; -import { Badge, DeferredSpinner, LightLabel, themeColor } from 'design-system'; +import { Badge, LightLabel, Spinner, themeColor } from 'design-system'; import * as React from 'react'; import Tooltip from '../../../components/controls/Tooltip'; import DateFormatter from '../../../components/intl/DateFormatter'; @@ -113,7 +113,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro <div> {this.props.initializing ? ( <div className="sw-p-4 sw-body-sm"> - <DeferredSpinner /> + <Spinner /> </div> ) : ( <div className="sw-p-4 sw-body-sm"> @@ -183,7 +183,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro })} {this.props.analysesLoading && ( <li className="sw-text-center"> - <DeferredSpinner /> + <Spinner /> </li> )} </ul> diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx index f4aa054ff89..420f7f75862 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisListRenderer.tsx @@ -25,7 +25,7 @@ import Select from '../../../components/controls/Select'; import Tooltip from '../../../components/controls/Tooltip'; import DateFormatter, { longFormatterOption } from '../../../components/intl/DateFormatter'; import TimeFormatter from '../../../components/intl/TimeFormatter'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { parseDate, toShortISO8601String } from '../../../helpers/dates'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { ParsedAnalysis } from '../../../types/project-activity'; @@ -138,7 +138,7 @@ function BranchAnalysisListRenderer( </div> <div className="branch-analysis-list-wrapper"> <div className="bordered branch-analysis-list" onScroll={props.handleScroll}> - <DeferredSpinner className="big-spacer-top" loading={loading} /> + <Spinner className="big-spacer-top" loading={loading} /> {!loading && !hasFilteredData ? ( <div className="big-spacer-top big-spacer-bottom strong"> diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx index 5d14760a99b..67fe858571a 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx @@ -25,7 +25,7 @@ import { ResetButtonLink, SubmitButton } from '../../../components/controls/butt import NewCodeDefinitionDaysOption from '../../../components/new-code-definition/NewCodeDefinitionDaysOption'; import NewCodeDefinitionPreviousVersionOption from '../../../components/new-code-definition/NewCodeDefinitionPreviousVersionOption'; import NewCodeDefinitionWarning from '../../../components/new-code-definition/NewCodeDefinitionWarning'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { toISO8601WithOffsetString } from '../../../helpers/dates'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getNumberOfDaysDefaultValue } from '../../../helpers/new-code-definition'; @@ -218,7 +218,7 @@ export default class BranchBaselineSettingModal extends React.PureComponent<Prop )} </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={saving} /> + <Spinner className="spacer-right" loading={saving} /> <SubmitButton disabled={!isChanged || saving || !isValid}> {translate('save')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx index 857895cb8dd..ff1aa3a4329 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { listBranchesNewCodePeriod, resetNewCodePeriod } from '../../../api/newCodePeriod'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { isBranch, sortBranches } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { DEFAULT_NEW_CODE_DEFINITION_TYPE } from '../../../helpers/new-code-definition'; @@ -141,7 +141,7 @@ export default class BranchList extends React.PureComponent<Props, State> { } if (loading) { - return <DeferredSpinner />; + return <Spinner />; } return ( diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineApp.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineApp.tsx index 3d73558be4d..620c5d78653 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineApp.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineApp.tsx @@ -29,7 +29,7 @@ import withAvailableFeatures, { import withComponentContext from '../../../app/components/componentContext/withComponentContext'; import Suggestions from '../../../components/embed-docs-modal/Suggestions'; import AlertSuccessIcon from '../../../components/icons/AlertSuccessIcon'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { isBranch, sortBranches } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { @@ -280,7 +280,7 @@ class ProjectBaselineApp extends React.PureComponent<Props, State> { <Helmet defer={false} title={translate('project_baseline.page')} /> <div className="page page-limited"> <AppHeader canAdmin={!!appState.canAdmin} /> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> {!loading && ( <div className="panel-white project-baseline"> diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx index 20756d3f5eb..affb46b2e5f 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx @@ -28,7 +28,7 @@ import NewCodeDefinitionDaysOption from '../../../components/new-code-definition import NewCodeDefinitionPreviousVersionOption from '../../../components/new-code-definition/NewCodeDefinitionPreviousVersionOption'; import NewCodeDefinitionWarning from '../../../components/new-code-definition/NewCodeDefinitionWarning'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { isNewCodeDefinitionCompliant } from '../../../helpers/new-code-definition'; import { Branch } from '../../../types/branch-like'; @@ -196,7 +196,7 @@ export default function ProjectBaselineSelector(props: ProjectBaselineSelectorPr <Alert variant="info" className="spacer-bottom"> {translate('baseline.next_analysis_notice')} </Alert> - <DeferredSpinner className="spacer-right" loading={saving} /> + <Spinner className="spacer-right" loading={saving} /> <SubmitButton disabled={saving || !isValid || !isChanged}>{translate('save')}</SubmitButton> <ResetButtonLink className="spacer-left" onClick={props.onCancel}> {translate('cancel')} diff --git a/server/sonar-web/src/main/js/apps/projectBranches/components/BranchPurgeSetting.tsx b/server/sonar-web/src/main/js/apps/projectBranches/components/BranchPurgeSetting.tsx index d0fd998284e..06e16afec8a 100644 --- a/server/sonar-web/src/main/js/apps/projectBranches/components/BranchPurgeSetting.tsx +++ b/server/sonar-web/src/main/js/apps/projectBranches/components/BranchPurgeSetting.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { useEffect } from 'react'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import Toggle from '../../../components/controls/Toggle'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { isMainBranch } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { useExcludeFromPurgeMutation } from '../../../queries/branch'; @@ -52,7 +52,7 @@ export default function BranchPurgeSetting(props: Props) { <> <Toggle disabled={disabled} onChange={handleOnChange} value={branch.excludedFromPurge} /> <span className="spacer-left"> - <DeferredSpinner loading={isLoading} /> + <Spinner loading={isLoading} /> </span> {isTheMainBranch && ( <HelpTooltip diff --git a/server/sonar-web/src/main/js/apps/projectBranches/components/LifetimeInformationRenderer.tsx b/server/sonar-web/src/main/js/apps/projectBranches/components/LifetimeInformationRenderer.tsx index edb949f5f50..afa5d48ce77 100644 --- a/server/sonar-web/src/main/js/apps/projectBranches/components/LifetimeInformationRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/projectBranches/components/LifetimeInformationRenderer.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import Link from '../../../components/common/Link'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; @@ -34,7 +34,7 @@ function LifetimeInformationRenderer(props: LifetimeInformationRendererProps) { const { branchAndPullRequestLifeTimeInDays, canAdmin, loading } = props; return ( - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {branchAndPullRequestLifeTimeInDays && ( <p className="page-description"> <FormattedMessage @@ -53,7 +53,7 @@ function LifetimeInformationRenderer(props: LifetimeInformationRendererProps) { )} </p> )} - </DeferredSpinner> + </Spinner> ); } diff --git a/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx b/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx index d5ae521d4b8..cb9c461c5c3 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx @@ -21,11 +21,11 @@ import { BasicSeparator, ButtonSecondary, CodeSnippet, - DeferredSpinner, FlagMessage, FormField, IllustratedSelectionCard, InputSelect, + Spinner, SubTitle, ToggleButton, } from 'design-system'; @@ -94,7 +94,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { <SubTitle>{translate('overview.badges.get_badge')}</SubTitle> <p className="big-spacer-bottom">{translate('overview.badges.description', qualifier)}</p> - <DeferredSpinner loading={isLoading || isEmpty(token)}> + <Spinner loading={isLoading || isEmpty(token)}> <div className="sw-flex sw-space-x-4 sw-mb-4"> <IllustratedSelectionCard className="sw-w-abs-300 it__badge-button" @@ -127,7 +127,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { )} /> </div> - </DeferredSpinner> + </Spinner> {BadgeType.measure === selectedType && ( <FormField htmlFor="badge-param-customize" label={translate('overview.badges.metric')}> @@ -162,7 +162,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { </div> </FormField> - <DeferredSpinner className="spacer-top spacer-bottom" loading={isFetchingToken || isRenewing}> + <Spinner className="spacer-top spacer-bottom" loading={isFetchingToken || isRenewing}> {!isLoading && ( <CodeSnippet language="plaintext" @@ -171,7 +171,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { wrap /> )} - </DeferredSpinner> + </Spinner> <FlagMessage className="sw-w-full" variant="warning"> <p> diff --git a/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx b/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx index 760cc32b7d2..837b5ca4149 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx @@ -23,7 +23,7 @@ import { WithNotificationsProps, withNotifications, } from '../../../components/hoc/withNotifications'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { hasMessage, translate, translateWithParameters } from '../../../helpers/l10n'; import { NotificationProjectType } from '../../../types/notifications'; import { Component } from '../../../types/types'; @@ -79,7 +79,7 @@ export function ProjectNotifications(props: WithNotificationsProps & Props) { {translate('notification.dispatcher.information')} </FlagMessage> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <h3 id="notifications-update-title" className="sw-mt-6"> {translate('project_information.project_notifications.title')} </h3> @@ -102,7 +102,7 @@ export function ProjectNotifications(props: WithNotificationsProps & Props) { </li> ))} </ul> - </DeferredSpinner> + </Spinner> </form> ); } diff --git a/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx b/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx index a1ac7d9582e..30823e150ca 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; import SimpleModal from '../../components/controls/SimpleModal'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; +import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../components/ui/Spinner'; import { translate } from '../../helpers/l10n'; interface Props { @@ -104,7 +104,7 @@ export default class CreationModal extends React.PureComponent<Props, State> { </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton disabled={submitting} id="create-link-confirm"> {translate('create')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx index 8da9634a051..e9209cded54 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { createLink, deleteLink, getProjectLinks } from '../../api/projectLinks'; import withComponentContext from '../../app/components/componentContext/withComponentContext'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; +import Spinner from '../../components/ui/Spinner'; import { translate } from '../../helpers/l10n'; import { Component, ProjectLink } from '../../types/types'; import Header from './Header'; @@ -105,9 +105,9 @@ export class ProjectLinksApp extends React.PureComponent<Props, State> { <div className="page page-limited"> <Helmet defer={false} title={translate('project_links.page')} /> <Header onCreate={this.handleCreateLink} /> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> {links && <Table links={links} onDelete={this.handleDeleteLink} />} - </DeferredSpinner> + </Spinner> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx index 8c30d1d2f83..654ef2df955 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx @@ -36,7 +36,7 @@ import ScreenPositionHelper from '../../../components/common/ScreenPositionHelpe import Suggestions from '../../../components/embed-docs-modal/Suggestions'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; import '../../../components/search-navigator.css'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication'; import { translate } from '../../../helpers/l10n'; import { addSideBarClass, removeSideBarClass } from '../../../helpers/pages'; @@ -280,7 +280,7 @@ export class AllProjects extends React.PureComponent<Props, State> { renderMain = () => { if (this.state.loading && this.state.projects === undefined) { - return <DeferredSpinner />; + return <Spinner />; } return ( diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx index 26d929bcc01..64a78adfdd5 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx @@ -21,7 +21,7 @@ import React, { useState } from 'react'; import { getComponentNavigation } from '../../api/navigation'; import { Project } from '../../api/project-management'; import ActionsDropdown, { ActionsDropdownItem } from '../../components/controls/ActionsDropdown'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; +import Spinner from '../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { getComponentPermissionsUrl } from '../../helpers/urls'; import { useGithubProvisioningEnabledQuery } from '../../queries/identity-provider'; @@ -76,7 +76,7 @@ export default function ProjectRowActions({ currentUser, project }: Props) { > {loading ? ( <ActionsDropdownItem> - <DeferredSpinner /> + <Spinner /> </ActionsDropdownItem> ) : ( <> diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx index a0ce8d48ab9..3f4d681d753 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx @@ -24,7 +24,7 @@ import { fetchQualityGates } from '../../../api/quality-gates'; import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; import Suggestions from '../../../components/embed-docs-modal/Suggestions'; import '../../../components/search-navigator.css'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { addSideBarClass, @@ -135,9 +135,9 @@ class App extends React.PureComponent<Props, State> { canCreate={canCreate} refreshQualityGates={this.fetchQualityGates} /> - <DeferredSpinner loading={this.state.loading}> + <Spinner loading={this.state.loading}> <List qualityGates={qualityGates} currentQualityGate={name} /> - </DeferredSpinner> + </Spinner> </div> </div> </nav> diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx index 97f18dc80f0..cf246948bbb 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx @@ -21,7 +21,7 @@ import { clone } from 'lodash'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { fetchQualityGate } from '../../../api/quality-gates'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { addGlobalSuccessMessage } from '../../../helpers/globalMessages'; import { translate } from '../../../helpers/l10n'; import { Condition, QualityGate } from '../../../types/types'; @@ -151,7 +151,7 @@ export default class Details extends React.PureComponent<Props, State> { return ( <main className="layout-page-main"> - <DeferredSpinner loading={loading} timeout={200}> + <Spinner loading={loading}> {qualityGate && ( <> <Helmet defer={false} title={qualityGate.name} /> @@ -171,7 +171,7 @@ export default class Details extends React.PureComponent<Props, State> { /> </> )} - </DeferredSpinner> + </Spinner> </main> ); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx index 3daa2daec75..97dd4a14dee 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx @@ -19,9 +19,9 @@ */ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; -import { Button } from '../../../components/controls/buttons'; import ConfirmModal from '../../../components/controls/ConfirmModal'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { Button } from '../../../components/controls/buttons'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { Group, isUser } from '../../../types/quality-gates'; import { QualityGate } from '../../../types/types'; @@ -54,7 +54,7 @@ export default function QualityGatePermissionsRenderer(props: QualityGatePermiss <h3 className="spacer-bottom">{translate('quality_gates.permissions')}</h3> <p className="spacer-bottom">{translate('quality_gates.permissions.help')}</p> <div> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <ul> {users.map((user) => ( <li key={user.login}> @@ -67,7 +67,7 @@ export default function QualityGatePermissionsRenderer(props: QualityGatePermiss </li> ))} </ul> - </DeferredSpinner> + </Spinner> </div> <Button className="big-spacer-top" onClick={props.onClickAddPermission}> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx index c2e38caeefd..4d0507c2dea 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { ChangelogResponse, getProfileChangelog } from '../../../api/quality-profiles'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { parseDate, toISO8601WithOffsetString } from '../../../helpers/dates'; import { translate } from '../../../helpers/l10n'; import { withQualityProfilesContext } from '../qualityProfilesContext'; @@ -147,7 +147,7 @@ class ChangelogContainer extends React.PureComponent<Props, State> { onDateRangeChange={this.handleDateRangeChange} onReset={this.handleReset} /> - <DeferredSpinner loading={this.state.loading} className="spacer-left" /> + <Spinner loading={this.state.loading} className="spacer-left" /> </div> {this.state.events != null && this.state.events.length === 0 && <ChangelogEmpty />} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResultActivation.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResultActivation.tsx index 333e6aeff30..94fbb4e4053 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResultActivation.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResultActivation.tsx @@ -20,9 +20,9 @@ import * as React from 'react'; import { Profile } from '../../../api/quality-profiles'; import { getRuleDetails } from '../../../api/rules'; -import { Button } from '../../../components/controls/buttons'; import Tooltip from '../../../components/controls/Tooltip'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import { Button } from '../../../components/controls/buttons'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { RuleDetails } from '../../../types/types'; import ActivationFormModal from '../../coding-rules/components/ActivationFormModal'; @@ -78,7 +78,7 @@ export default class ComparisonResultActivation extends React.PureComponent<Prop const { profile } = this.props; return ( - <DeferredSpinner loading={this.state.state === 'opening'}> + <Spinner loading={this.state.state === 'opening'}> <Tooltip placement="bottom" overlay={translateWithParameters( @@ -107,7 +107,7 @@ export default class ComparisonResultActivation extends React.PureComponent<Prop rule={this.state.rule} /> )} - </DeferredSpinner> + </Spinner> ); } } diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx index 8253691a9fb..d0c74ef0f43 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx @@ -21,12 +21,12 @@ import { withTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { - DeferredSpinner, LAYOUT_FOOTER_HEIGHT, LAYOUT_GLOBAL_NAV_HEIGHT, LAYOUT_PROJECT_NAV_HEIGHT, LargeCenteredLayout, PageContentFontWrapper, + Spinner, themeBorder, themeColor, } from 'design-system'; @@ -159,13 +159,13 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe }px`, }} > - <DeferredSpinner className="sw-mt-3" loading={loading}> - <HotspotFilterByStatus - filters={filters} - isStaticListOfHotspots={isStaticListOfHotspots} - onChangeFilters={onChangeFilters} - onShowAllHotspots={onShowAllHotspots} - /> + <HotspotFilterByStatus + filters={filters} + isStaticListOfHotspots={isStaticListOfHotspots} + onChangeFilters={onChangeFilters} + onShowAllHotspots={onShowAllHotspots} + /> + <Spinner className="sw-mt-3" loading={loading}> {hotspots.length > 0 && selectedHotspot && ( <> {filterByCategory || filterByCWE || filterByFile ? ( @@ -200,7 +200,7 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe )} </> )} - </DeferredSpinner> + </Spinner> </StyledSidebarContent> </StyledSidebar> diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotOpenInIdeButton.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotOpenInIdeButton.tsx index 3d879f6ef32..5229e07481e 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotOpenInIdeButton.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotOpenInIdeButton.tsx @@ -25,7 +25,7 @@ import { PopupPlacement, } from 'design-system'; import * as React from 'react'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { addGlobalErrorMessage, addGlobalSuccessMessage } from '../../../helpers/globalMessages'; import { translate } from '../../../helpers/l10n'; import { openHotspot, probeSonarLintServers } from '../../../helpers/sonarlint'; @@ -122,7 +122,7 @@ export default class HotspotOpenInIdeButton extends React.PureComponent<Props, S > <ButtonSecondary onClick={this.handleOnClick}> {translate('hotspots.open_in_ide.open')} - <DeferredSpinner loading={loading} className="sw-ml-4" /> + <Spinner loading={loading} className="sw-ml-4" /> </ButtonSecondary> </DropdownToggler> </div> diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSidebarHeader.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSidebarHeader.tsx index 56d26d44309..c1751a3a336 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSidebarHeader.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSidebarHeader.tsx @@ -35,7 +35,7 @@ import withCurrentUserContext from '../../../app/components/current-user/withCur import HelpTooltip from '../../../components/controls/HelpTooltip'; import Tooltip from '../../../components/controls/Tooltip'; import Measure from '../../../components/measure/Measure'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { PopupPlacement } from '../../../components/ui/popups'; import { isBranch } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; @@ -76,7 +76,7 @@ function HotspotSidebarHeader(props: SecurityHotspotsAppRendererProps) { return ( <div className="sw-flex sw-h-6 sw-items-center sw-px-4 sw-py-4"> - <DeferredSpinner loading={loadingMeasure}> + <Spinner loading={loadingMeasure}> {hotspotsReviewedMeasure !== undefined && ( <CoverageIndicator value={hotspotsReviewedMeasure} /> )} @@ -91,85 +91,85 @@ function HotspotSidebarHeader(props: SecurityHotspotsAppRendererProps) { metricType={MetricType.Percent} value={hotspotsReviewedMeasure} /> - - <span className="sw-body-sm sw-ml-1"> - {translate('metric.security_hotspots_reviewed.name')} - </span> - - <HelpTooltip className="sw-ml-1" overlay={translate('hotspots.reviewed.tooltip')}> - <HelperHintIcon aria-label="help-tooltip" /> - </HelpTooltip> - - {!isStaticListOfHotspots && (isBranch(branchLike) || userLoggedIn || isFiltered) && ( - <div className="sw-flex sw-flex-grow sw-justify-end"> - <Dropdown - allowResizing - closeOnClick={false} - id="filter-hotspots-menu" - isPortal - overlay={ - <> - <ItemHeader>{translate('hotspot.filters.title')}</ItemHeader> - - {isBranch(branchLike) && ( + </Spinner> + + <span className="sw-body-sm sw-ml-1"> + {translate('metric.security_hotspots_reviewed.name')} + </span> + + <HelpTooltip className="sw-ml-1" overlay={translate('hotspots.reviewed.tooltip')}> + <HelperHintIcon aria-label="help-tooltip" /> + </HelpTooltip> + + {!isStaticListOfHotspots && (isBranch(branchLike) || userLoggedIn || isFiltered) && ( + <div className="sw-flex sw-flex-grow sw-justify-end"> + <Dropdown + allowResizing + closeOnClick={false} + id="filter-hotspots-menu" + isPortal + overlay={ + <> + <ItemHeader>{translate('hotspot.filters.title')}</ItemHeader> + + {isBranch(branchLike) && ( + <ItemCheckbox + checked={Boolean(filters.inNewCodePeriod)} + onCheck={(inNewCodePeriod: boolean) => + props.onChangeFilters({ inNewCodePeriod }) + } + > + <span className="sw-mx-2"> + {translate('hotspot.filters.period.since_leak_period')} + </span> + </ItemCheckbox> + )} + + {userLoggedIn && ( + <Tooltip + classNameSpace={component?.needIssueSync ? 'tooltip' : 'sw-hidden'} + overlay={<HotspotDisabledFilterTooltip />} + placement="right" + > <ItemCheckbox - checked={Boolean(filters.inNewCodePeriod)} - onCheck={(inNewCodePeriod: boolean) => - props.onChangeFilters({ inNewCodePeriod }) - } + checked={Boolean(filters.assignedToMe)} + disabled={component?.needIssueSync} + onCheck={(assignedToMe: boolean) => props.onChangeFilters({ assignedToMe })} > <span className="sw-mx-2"> - {translate('hotspot.filters.period.since_leak_period')} + {translate('hotspot.filters.assignee.assigned_to_me')} </span> </ItemCheckbox> - )} - - {userLoggedIn && ( - <Tooltip - classNameSpace={component?.needIssueSync ? 'tooltip' : 'sw-hidden'} - overlay={<HotspotDisabledFilterTooltip />} - placement="right" - > - <ItemCheckbox - checked={Boolean(filters.assignedToMe)} - disabled={component?.needIssueSync} - onCheck={(assignedToMe: boolean) => props.onChangeFilters({ assignedToMe })} - > - <span className="sw-mx-2"> - {translate('hotspot.filters.assignee.assigned_to_me')} - </span> - </ItemCheckbox> - </Tooltip> - )} - - {isFiltered && <ItemDivider />} - - {isFiltered && ( - <ItemDangerButton - onClick={() => - props.onChangeFilters({ - assignedToMe: false, - inNewCodePeriod: false, - }) - } - > - {translate('hotspot.filters.clear')} - </ItemDangerButton> - )} - </> - } - placement={PopupPlacement.BottomRight} + </Tooltip> + )} + + {isFiltered && <ItemDivider />} + + {isFiltered && ( + <ItemDangerButton + onClick={() => + props.onChangeFilters({ + assignedToMe: false, + inNewCodePeriod: false, + }) + } + > + {translate('hotspot.filters.clear')} + </ItemDangerButton> + )} + </> + } + placement={PopupPlacement.BottomRight} + > + <DiscreetInteractiveIcon + Icon={FilterIcon} + aria-label={translate('hotspot.filters.title')} > - <DiscreetInteractiveIcon - Icon={FilterIcon} - aria-label={translate('hotspot.filters.title')} - > - {isFiltered ? filtersCount : null} - </DiscreetInteractiveIcon> - </Dropdown> - </div> - )} - </DeferredSpinner> + {isFiltered ? filtersCount : null} + </DiscreetInteractiveIcon> + </Dropdown> + </div> + )} </div> ); } diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx index 48433425bde..92abb4afe39 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotSnippetContainerRenderer.tsx @@ -21,7 +21,7 @@ import { withTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { themeBorder, themeColor } from 'design-system'; import * as React from 'react'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { BranchLike } from '../../../types/branch-like'; import { Hotspot } from '../../../types/security-hotspots'; @@ -155,7 +155,7 @@ export default function HotspotSnippetContainerRenderer( <SourceFileWrapper className="sw-box-border sw-w-full sw-rounded-1" ref={scrollableRef}> <HotspotSnippetHeader hotspot={hotspot} component={component} branchLike={branchLike} /> - <DeferredSpinner className="big-spacer" loading={loading} /> + <Spinner className="big-spacer" loading={loading} /> {!loading && sourceLines.length > 0 && ( <SnippetViewer diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx index 8aedbfe45d0..4edfc35fe77 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { fillBranchLike } from '../../../helpers/branch-like'; import { Standards } from '../../../types/security'; import { Hotspot, HotspotStatusOption } from '../../../types/security-hotspots'; @@ -70,7 +70,7 @@ export function HotspotViewerRenderer(props: HotspotViewerRendererProps) { return ( <> - <DeferredSpinner className="sw-ml-4 sw-mt-4" loading={loading} /> + <Spinner className="sw-ml-4 sw-mt-4" loading={loading} /> {showStatusUpdateSuccessModal && ( <StatusUpdateSuccessModal diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Login.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Login.tsx index abc039a5585..8af2013638a 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Login.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/Login.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { Location } from '../../../components/hoc/withRouter'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { sanitizeUserInput } from '../../../helpers/sanitize'; import { getReturnUrl } from '../../../helpers/urls'; @@ -50,7 +50,7 @@ export default function Login(props: LoginProps) { </h1> <Helmet defer={false} title={translate('login.page')} /> {loading ? ( - <DeferredSpinner loading={loading} timeout={0} /> + <Spinner loading={loading} /> ) : ( <> {displayError && ( diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx index 962ac29d111..e1da85d5982 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import Link from '../../../components/common/Link'; import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import './LoginForm.css'; @@ -121,7 +121,7 @@ export default class LoginForm extends React.PureComponent<Props, State> { <div> <div className="text-right overflow-hidden"> - <DeferredSpinner className="spacer-right" loading={this.state.loading} /> + <Spinner className="spacer-right" loading={this.state.loading} /> <SubmitButton disabled={this.state.loading}> {translate('sessions.log_in')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.tsx index 77b64a6bd90..47dd8d91b1a 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.tsx @@ -22,9 +22,9 @@ import { sendTestEmail } from '../../../api/settings'; import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext'; import { SubmitButton } from '../../../components/controls/buttons'; import { Alert } from '../../../components/ui/Alert'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { parseError } from '../../../helpers/request'; import { LoggedInUser } from '../../../types/users'; @@ -168,7 +168,7 @@ export class EmailForm extends React.PureComponent<Props, State> { <SubmitButton disabled={loading}> {translate('email_configuration.test.send')} </SubmitButton> - {loading && <DeferredSpinner className="spacer-left" />} + {loading && <Spinner className="spacer-left" />} </form> </div> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx b/server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx index b6495cbc1f7..b1047cec1f2 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx @@ -26,7 +26,7 @@ import AlertSuccessIcon from '../../../components/icons/AlertSuccessIcon'; import NewCodeDefinitionDaysOption from '../../../components/new-code-definition/NewCodeDefinitionDaysOption'; import NewCodeDefinitionPreviousVersionOption from '../../../components/new-code-definition/NewCodeDefinitionPreviousVersionOption'; import NewCodeDefinitionWarning from '../../../components/new-code-definition/NewCodeDefinitionWarning'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { getNumberOfDaysDefaultValue, @@ -198,7 +198,7 @@ export default class NewCodePeriod extends React.PureComponent<{}, State> { </div> <div className="settings-definition-right"> - <DeferredSpinner loading={loading} timeout={500}> + <Spinner loading={loading}> <form onSubmit={this.onSubmit}> <NewCodeDefinitionPreviousVersionOption isDefault @@ -225,7 +225,7 @@ export default class NewCodePeriod extends React.PureComponent<{}, State> { <p className="spacer-bottom"> {translate('baseline.next_analysis_notice')} </p> - <DeferredSpinner className="spacer-right" loading={saving} /> + <Spinner className="spacer-right" loading={saving} /> <SubmitButton disabled={saving || !isValid}> {translate('save')} </SubmitButton> @@ -243,7 +243,7 @@ export default class NewCodePeriod extends React.PureComponent<{}, State> { </div> )} </form> - </DeferredSpinner> + </Spinner> </div> </div> </li> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx index 5e95c87d2c3..2f2f67442e4 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import Modal from '../../../../components/controls/Modal'; import { ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; +import Spinner from '../../../../components/ui/Spinner'; import { translate } from '../../../../helpers/l10n'; import { AlmBindingDefinition, @@ -134,7 +134,7 @@ export default class AlmBindingDefinitionFormRenderer extends React.PureComponen <div className="modal-foot"> <SubmitButton disabled={!canSubmit || submitting}> {translate('settings.almintegration.form.save')} - <DeferredSpinner className="spacer-left" loading={submitting} /> + <Spinner className="spacer-left" loading={submitting} /> </SubmitButton> <ResetButtonLink onClick={this.props.onCancel}>{translate('cancel')}</ResetButtonLink> </div> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx index 2d22762356f..5096a11a8fc 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx @@ -23,7 +23,7 @@ import Link from '../../../../components/common/Link'; import { getTabId, getTabPanelId } from '../../../../components/controls/BoxedTabs'; import { Button } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; +import Spinner from '../../../../components/ui/Spinner'; import { translate } from '../../../../helpers/l10n'; import { AlmBindingDefinition, @@ -85,7 +85,7 @@ export default function AlmTabRenderer(props: AlmTabRendererProps) { aria-labelledby={getTabId(almTab)} > <div className="big-padded"> - <DeferredSpinner loading={loadingAlmDefinitions}> + <Spinner loading={loadingAlmDefinitions}> {definitions.length === 0 && ( <p className="spacer-top">{translate('settings.almintegration.empty', almTab)}</p> )} @@ -122,7 +122,7 @@ export default function AlmTabRenderer(props: AlmTabRendererProps) { afterSubmit={props.afterSubmit} /> )} - </DeferredSpinner> + </Spinner> </div> {AUTHENTICATION_AVAILABLE_PLATFORMS.includes(almTab) && ( <Alert variant="info" className="spacer"> diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx index 4c1a3081db6..45370d10734 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx @@ -24,7 +24,7 @@ import DocLink from '../../../../components/common/DocLink'; import Modal from '../../../../components/controls/Modal'; import { ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; +import Spinner from '../../../../components/ui/Spinner'; import { translate } from '../../../../helpers/l10n'; import { useSaveValuesMutation } from '../../../../queries/settings'; import { Dict } from '../../../../types/types'; @@ -101,10 +101,7 @@ export default function ConfigurationForm(props: Props) { <h2>{headerLabel}</h2> </div> <div className="modal-body modal-container"> - <DeferredSpinner - loading={loading} - ariaLabel={translate('settings.authentication.form.loading')} - > + <Spinner loading={loading} ariaLabel={translate('settings.authentication.form.loading')}> <Alert variant={hasLegacyConfiguration ? 'warning' : 'info'}> <FormattedMessage id={`settings.authentication.${ @@ -145,13 +142,13 @@ export default function ConfigurationForm(props: Props) { </div> ); })} - </DeferredSpinner> + </Spinner> </div> <div className="modal-foot"> <SubmitButton disabled={!canBeSave}> {translate('settings.almintegration.form.save')} - <DeferredSpinner className="spacer-left" loading={loading} /> + <Spinner className="spacer-left" loading={loading} /> </SubmitButton> <ResetButtonLink onClick={props.onClose}>{translate('cancel')}</ResetButtonLink> </div> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx index 2c0c4823033..fbcb8704810 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx @@ -24,9 +24,9 @@ import { Button, SubmitButton } from '../../../../components/controls/buttons'; import AlmSettingsInstanceSelector from '../../../../components/devops-platform/AlmSettingsInstanceSelector'; import AlertSuccessIcon from '../../../../components/icons/AlertSuccessIcon'; import { Alert } from '../../../../components/ui/Alert'; -import DeferredSpinner from '../../../../components/ui/DeferredSpinner'; import MandatoryFieldMarker from '../../../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../../../components/ui/MandatoryFieldsExplanation'; +import Spinner from '../../../../components/ui/Spinner'; import { translate } from '../../../../helpers/l10n'; import { getGlobalSettingsUrl } from '../../../../helpers/urls'; import { @@ -72,7 +72,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe } = props; if (loading) { - return <DeferredSpinner />; + return <Spinner />; } if (instances.length < 1) { @@ -154,7 +154,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe {isChanged && ( <SubmitButton className="spacer-right button-success" disabled={updating || !isValid}> <span data-test="project-settings__alm-save">{translate('save')}</span> - <DeferredSpinner className="spacer-left" loading={updating} /> + <Spinner className="spacer-left" loading={updating} /> </SubmitButton> )} {!updating && successfullyUpdated && ( @@ -171,7 +171,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe {!isChanged && ( <Button onClick={props.onCheckConfiguration} disabled={checkingConfiguration}> {translate('settings.pr_decoration.binding.check_configuration')} - <DeferredSpinner className="spacer-left" loading={checkingConfiguration} /> + <Spinner className="spacer-left" loading={checkingConfiguration} /> </Button> )} </> diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx index 6b56a14c61b..5c9502161a9 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx +++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { checkSecretKey, generateSecretKey } from '../../../api/settings'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import EncryptionForm from './EncryptionForm'; import GenerateSecretKeyForm from './GenerateSecretKeyForm'; @@ -74,7 +74,7 @@ export default class EncryptionApp extends React.PureComponent<{}, State> { <Helmet defer={false} title={translate('property.category.security.encryption')} /> <header className="page-header"> <h1 className="page-title">{translate('property.category.security.encryption')}</h1> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> </header> {!loading && !secretKeyAvailable && ( diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx index 2498c8f417a..c2ba4907837 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx @@ -23,7 +23,7 @@ import { encryptValue } from '../../../api/settings'; import DocLink from '../../../components/common/DocLink'; import { SubmitButton } from '../../../components/controls/buttons'; import { ClipboardButton } from '../../../components/controls/clipboard'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; interface Props { @@ -101,7 +101,7 @@ export default class EncryptionForm extends React.PureComponent<Props, State> { <SubmitButton disabled={encrypting || generating}> {translate('encryption.encrypt')} </SubmitButton> - <DeferredSpinner className="spacer-left" loading={encrypting} /> + <Spinner className="spacer-left" loading={encrypting} /> </div> </form> @@ -143,7 +143,7 @@ export default class EncryptionForm extends React.PureComponent<Props, State> { <SubmitButton disabled={generating || encrypting}> {translate('encryption.generate_new_secret_key')}{' '} </SubmitButton> - <DeferredSpinner className="spacer-left" loading={generating} /> + <Spinner className="spacer-left" loading={generating} /> </form> </div> ); diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx index 6ef0b5d576c..8d478192490 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx @@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl'; import DocLink from '../../../components/common/DocLink'; import { SubmitButton } from '../../../components/controls/buttons'; import { ClipboardButton } from '../../../components/controls/clipboard'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; interface Props { @@ -125,7 +125,7 @@ export default class GenerateSecretKeyForm extends React.PureComponent<Props, St <SubmitButton disabled={submitting}> {translate('encryption.generate_secret_key')} </SubmitButton> - <DeferredSpinner className="spacer-left" loading={submitting} /> + <Spinner className="spacer-left" loading={submitting} /> </form> )} </div> diff --git a/server/sonar-web/src/main/js/apps/users/UsersApp.tsx b/server/sonar-web/src/main/js/apps/users/UsersApp.tsx index 7ba7969debb..91d942a6325 100644 --- a/server/sonar-web/src/main/js/apps/users/UsersApp.tsx +++ b/server/sonar-web/src/main/js/apps/users/UsersApp.tsx @@ -29,7 +29,7 @@ import SearchBox from '../../components/controls/SearchBox'; import Select, { LabelValueSelectOption } from '../../components/controls/Select'; import Suggestions from '../../components/embed-docs-modal/Suggestions'; import { Provider, useManageProvider } from '../../components/hooks/useManageProvider'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; +import Spinner from '../../components/ui/Spinner'; import { now, toISO8601WithOffsetString } from '../../helpers/dates'; import { translate } from '../../helpers/l10n'; import { useUsersQueries } from '../../queries/users'; @@ -141,13 +141,13 @@ export default function UsersApp() { /> </div> </div> - <DeferredSpinner loading={isLoading}> + <Spinner loading={isLoading}> <UsersList identityProviders={identityProviders} users={users} manageProvider={manageProvider} /> - </DeferredSpinner> + </Spinner> <ListFooter count={users.length} diff --git a/server/sonar-web/src/main/js/apps/users/components/TokensForm.tsx b/server/sonar-web/src/main/js/apps/users/components/TokensForm.tsx index 3fb253cb56d..079006f6469 100644 --- a/server/sonar-web/src/main/js/apps/users/components/TokensForm.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/TokensForm.tsx @@ -24,7 +24,7 @@ import { generateToken, getTokens } from '../../../api/user-tokens'; import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext'; import Select, { LabelValueSelectOption } from '../../../components/controls/Select'; import { SubmitButton } from '../../../components/controls/buttons'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate } from '../../../helpers/l10n'; import { EXPIRATION_OPTIONS, @@ -405,9 +405,9 @@ export class TokensForm extends React.PureComponent<Props, State> { </tr> </thead> <tbody> - <DeferredSpinner customSpinner={customSpinner} loading={loading && tokens.length <= 0}> + <Spinner customSpinner={customSpinner} loading={loading && tokens.length <= 0}> {this.renderItems()} - </DeferredSpinner> + </Spinner> </tbody> </table> </> diff --git a/server/sonar-web/src/main/js/apps/users/components/TokensFormItem.tsx b/server/sonar-web/src/main/js/apps/users/components/TokensFormItem.tsx index 2a8980b81e2..8e05a173ed8 100644 --- a/server/sonar-web/src/main/js/apps/users/components/TokensFormItem.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/TokensFormItem.tsx @@ -26,7 +26,7 @@ import { Button } from '../../../components/controls/buttons'; import WarningIcon from '../../../components/icons/WarningIcon'; import DateFormatter from '../../../components/intl/DateFormatter'; import DateFromNow from '../../../components/intl/DateFromNow'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { UserToken } from '../../../types/token'; @@ -117,9 +117,9 @@ export default class TokensFormItem extends React.PureComponent<Props, State> { onClick={this.handleRevoke} aria-label={translateWithParameters('users.tokens.remove_label', token.name)} > - <DeferredSpinner className="little-spacer-right" loading={loading}> + <Spinner className="little-spacer-right" loading={loading}> {translate('remove')} - </DeferredSpinner> + </Spinner> </Button> )} {!token.isExpired && deleteConfirmation === 'modal' && ( @@ -159,7 +159,7 @@ export default class TokensFormItem extends React.PureComponent<Props, State> { } onClick={this.handleClick} > - <DeferredSpinner className="little-spacer-right" loading={loading} /> + <Spinner className="little-spacer-right" loading={loading} /> {showConfirmation ? translate('users.tokens.sure') : translate('users.tokens.revoke')} </Button> )} diff --git a/server/sonar-web/src/main/js/apps/web-api-v2/WebApiApp.tsx b/server/sonar-web/src/main/js/apps/web-api-v2/WebApiApp.tsx index 4147cca391a..cce9a665dd3 100644 --- a/server/sonar-web/src/main/js/apps/web-api-v2/WebApiApp.tsx +++ b/server/sonar-web/src/main/js/apps/web-api-v2/WebApiApp.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; -import { DeferredSpinner, LargeCenteredLayout, PageContentFontWrapper, Title } from 'design-system'; +import { LargeCenteredLayout, PageContentFontWrapper, Spinner, Title } from 'design-system'; import { omit } from 'lodash'; import React, { useMemo } from 'react'; import { Helmet } from 'react-helmet-async'; @@ -57,7 +57,7 @@ export default function WebApiApp() { <LargeCenteredLayout> <PageContentFontWrapper className="sw-body-sm"> <Helmet defer={false} title={translate('api_documentation.page')} /> - <DeferredSpinner loading={isLoading}> + <Spinner loading={isLoading}> {data && ( <div className="sw-w-full sw-flex"> <NavContainer aria-label={translate('api_documentation.page')} className="sw--mx-2"> @@ -76,7 +76,7 @@ export default function WebApiApp() { className="sw-relative sw-ml-12 sw-flex-1 sw-overflow-y-auto sw-py-6" style={{ height: 'calc(100vh - 160px)' }} > - <DeferredSpinner loading={isLoading}> + <Spinner loading={isLoading}> {!activeData && ( <> <Title>{translate('about')}</Title> @@ -91,11 +91,11 @@ export default function WebApiApp() { method={activeData.method} /> )} - </DeferredSpinner> + </Spinner> </main> </div> )} - </DeferredSpinner> + </Spinner> </PageContentFontWrapper> </LargeCenteredLayout> ); diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/DeleteWebhookForm.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/DeleteWebhookForm.tsx index 238ec10c8b9..2ad2f5e195a 100644 --- a/server/sonar-web/src/main/js/apps/webhooks/components/DeleteWebhookForm.tsx +++ b/server/sonar-web/src/main/js/apps/webhooks/components/DeleteWebhookForm.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import SimpleModal from '../../../components/controls/SimpleModal'; import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { WebhookResponse } from '../../../types/webhook'; @@ -46,7 +46,7 @@ export default function DeleteWebhookForm({ onClose, onSubmit, webhook }: Props) </div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton className="button-red" disabled={submitting}> {translate('delete')} </SubmitButton> diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx index e3c3dd82e32..26b461327c4 100644 --- a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx +++ b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx @@ -23,7 +23,7 @@ import { searchDeliveries } from '../../../api/webhooks'; import ListFooter from '../../../components/controls/ListFooter'; import Modal from '../../../components/controls/Modal'; import { ResetButtonLink } from '../../../components/controls/buttons'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Paging } from '../../../types/types'; import { WebhookDelivery, WebhookResponse } from '../../../types/webhook'; @@ -87,7 +87,7 @@ export default function DeliveriesForm({ onClose, webhook }: Props) { <DeliveryAccordion delivery={delivery} key={delivery.id} /> ))} <div className="text-center"> - <DeferredSpinner loading={loading} /> + <Spinner loading={loading} /> </div> {paging !== undefined && ( <ListFooter diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx index cd184e8f9a5..35ee6b3628b 100644 --- a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx +++ b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import CodeSnippet from '../../../components/common/CodeSnippet'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; +import Spinner from '../../../components/ui/Spinner'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import { WebhookDelivery } from '../../../types/webhook'; @@ -48,9 +48,9 @@ export default function DeliveryItem({ className, delivery, loading, payload }: )} </p> <p className="spacer-bottom">{translate('webhooks.delivery.payload')}</p> - <DeferredSpinner className="spacer-left spacer-top" loading={loading}> + <Spinner className="spacer-left spacer-top" loading={loading}> {payload && <CodeSnippet noCopy snippet={formatPayload(payload)} />} - </DeferredSpinner> + </Spinner> </div> ); } diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx index 9f53f638091..0f965bccc3e 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { ButtonSecondary, DeferredSpinner, LightLabel, SonarCodeColorizer } from 'design-system'; +import { ButtonSecondary, LightLabel, SonarCodeColorizer, Spinner } from 'design-system'; import * as React from 'react'; import { decorateWithUnderlineFlags } from '../../helpers/code-viewer'; import { translate } from '../../helpers/l10n'; @@ -287,7 +287,7 @@ export default class SourceViewerCode extends React.PureComponent<Props, State> <div className="sw-flex sw-justify-center sw-p-6"> {loadingSourcesBefore ? ( <div className="sw-flex sw-items-center"> - <DeferredSpinner loading /> + <Spinner loading /> <LightLabel className="sw-ml-2"> {translate('source_viewer.loading_more_code')} </LightLabel> @@ -326,7 +326,7 @@ export default class SourceViewerCode extends React.PureComponent<Props, State> <div className="sw-flex sw-justify-center sw-p-6"> {loadingSourcesAfter ? ( <div className="sw-flex sw-items-center"> - <DeferredSpinner loading /> + <Spinner loading /> <LightLabel className="sw-ml-2"> {translate('source_viewer.loading_more_code')} </LightLabel> diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx index fe17ca2251c..1bc44e8fea6 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { DeferredSpinner, LightLabel } from 'design-system'; +import { LightLabel, Spinner } from 'design-system'; import { isEqual, uniqBy } from 'lodash'; import * as React from 'react'; import { translate, translateWithParameters } from '../../helpers/l10n'; @@ -73,7 +73,7 @@ export default class GraphsHistory extends React.PureComponent<Props, State> { return ( <div className="sw-flex sw-justify-center sw-flex-col sw-items-stretch sw-grow"> <div className="sw-text-center"> - <DeferredSpinner ariaLabel={translate('loading')} loading={loading} /> + <Spinner ariaLabel={translate('loading')} loading={loading} /> </div> </div> ); diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/ActivityGraph-it.tsx b/server/sonar-web/src/main/js/components/activity-graph/__tests__/ActivityGraph-it.tsx index 8f1d75b645d..a75b385edc1 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/ActivityGraph-it.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/ActivityGraph-it.tsx @@ -42,7 +42,7 @@ const START_DATE = '2016-01-01T00:00:00+0200'; describe('rendering', () => { it('should render correctly when loading', async () => { renderActivityGraph({ loading: true }); - expect(await screen.findByLabelText('loading')).toBeInTheDocument(); + expect(await screen.findByText('loading')).toBeInTheDocument(); }); it('should show the correct legend items', async () => { diff --git a/server/sonar-web/src/main/js/components/controls/Checkbox.tsx b/server/sonar-web/src/main/js/components/controls/Checkbox.tsx index e105d7274a0..63bdcef3cfe 100644 --- a/server/sonar-web/src/main/js/components/controls/Checkbox.tsx +++ b/server/sonar-web/src/main/js/components/controls/Checkbox.tsx @@ -22,7 +22,7 @@ import classNames from 'classnames'; import * as React from 'react'; -import DeferredSpinner from '../ui/DeferredSpinner'; +import Spinner from '../ui/Spinner'; import './Checkbox.css'; interface Props { @@ -77,16 +77,16 @@ export default class Checkbox extends React.PureComponent<Props> { title={title} > {right && children} - <DeferredSpinner loading={Boolean(loading)}> + <Spinner loading={Boolean(loading)}> <i className={className} /> - </DeferredSpinner> + </Spinner> {!right && children} </a> ); } if (loading) { - return <DeferredSpinner ariaLabel={label} />; + return <Spinner ariaLabel={label} />; } return ( diff --git a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx index 19dcca49810..4705effa339 100644 --- a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx +++ b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx @@ -19,11 +19,11 @@ */ import * as React from 'react'; import { translate } from '../../helpers/l10n'; -import DeferredSpinner from '../ui/DeferredSpinner'; -import { ResetButtonLink, SubmitButton } from './buttons'; +import Spinner from '../ui/Spinner'; import ClickEventBoundary from './ClickEventBoundary'; import { ModalProps } from './Modal'; import SimpleModal, { ChildrenProps } from './SimpleModal'; +import { ResetButtonLink, SubmitButton } from './buttons'; export interface ConfirmModalProps<T> extends ModalProps { cancelButtonText?: string; @@ -88,7 +88,7 @@ export default class ConfirmModal<T = string> extends React.PureComponent<Props< </header> <div className="modal-body">{children}</div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> + <Spinner className="spacer-right" loading={submitting} /> <SubmitButton autoFocus className={isDestructive ? 'button-red' : undefined} diff --git a/server/sonar-web/src/main/js/components/controls/ListFooter.tsx b/server/sonar-web/src/main/js/components/controls/ListFooter.tsx index 4c8ca653971..55a42841659 100644 --- a/server/sonar-web/src/main/js/components/controls/ListFooter.tsx +++ b/server/sonar-web/src/main/js/components/controls/ListFooter.tsx @@ -19,12 +19,12 @@ */ import styled from '@emotion/styled'; import classNames from 'classnames'; -import { ButtonSecondary, DeferredSpinner, themeColor } from 'design-system'; +import { ButtonSecondary, Spinner, themeColor } from 'design-system'; import * as React from 'react'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { formatMeasure } from '../../helpers/measures'; import { MetricType } from '../../types/metrics'; -import LegacySpinner from '../ui/DeferredSpinner'; +import LegacySpinner from '../ui/Spinner'; import { Button } from './buttons'; export interface ListFooterProps { @@ -123,7 +123,7 @@ export default function ListFooter(props: ListFooterProps) { {button} {/* eslint-disable local-rules/no-conditional-rendering-of-deferredspinner */} {useMIUIButtons ? ( - <DeferredSpinner loading={loading} className="sw-ml-2" /> + <Spinner loading={loading} className="sw-ml-2" /> ) : ( <LegacySpinner loading={loading} className="sw-ml-2" /> )} diff --git a/server/sonar-web/src/main/js/components/controls/SearchBox.css b/server/sonar-web/src/main/js/components/controls/SearchBox.css index 30c190d12da..ad0ad0d9fa8 100644 --- a/server/sonar-web/src/main/js/components/controls/SearchBox.css +++ b/server/sonar-web/src/main/js/components/controls/SearchBox.css @@ -81,7 +81,7 @@ transition: color 0.3s ease; } -.search-box > .deferred-spinner { +.search-box > .spinner { position: absolute; top: 4px; left: 5px; diff --git a/server/sonar-web/src/main/js/components/controls/SearchBox.tsx b/server/sonar-web/src/main/js/components/controls/SearchBox.tsx index 3c5b8430a61..4ae74ff0009 100644 --- a/server/sonar-web/src/main/js/components/controls/SearchBox.tsx +++ b/server/sonar-web/src/main/js/components/controls/SearchBox.tsx @@ -23,7 +23,7 @@ import * as React from 'react'; import { KeyboardKeys } from '../../helpers/keycodes'; import { translate, translateWithParameters } from '../../helpers/l10n'; import SearchIcon from '../icons/SearchIcon'; -import DeferredSpinner from '../ui/DeferredSpinner'; +import Spinner from '../ui/Spinner'; import { ClearButton } from './buttons'; import './SearchBox.css'; @@ -158,9 +158,9 @@ export default class SearchBox extends React.PureComponent<Props, State> { value={value} /> - <DeferredSpinner loading={loading !== undefined ? loading : false}> + <Spinner loading={loading !== undefined ? loading : false}> <SearchIcon className="search-box-magnifier" /> - </DeferredSpinner> + </Spinner> {value && ( <ClearButton diff --git a/server/sonar-web/src/main/js/components/controls/Select.tsx b/server/sonar-web/src/main/js/components/controls/Select.tsx index 3d35a3d6806..898b6f2d33c 100644 --- a/server/sonar-web/src/main/js/components/controls/Select.tsx +++ b/server/sonar-web/src/main/js/components/controls/Select.tsx @@ -82,9 +82,7 @@ export function loadingIndicator< IsMulti extends boolean = boolean, Group extends GroupBase<Option> = GroupBase<Option> >({ innerProps }: LoadingIndicatorProps<Option, IsMulti, Group>) { - return ( - <i className={classNames('deferred-spinner spacer-left spacer-right', innerProps.className)} /> - ); + return <i className={classNames('spinner spacer-left spacer-right', innerProps.className)} />; } export function multiValueRemove< diff --git a/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx b/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx index 3a745ddae1e..0cf5c2657f4 100644 --- a/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx +++ b/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx @@ -21,7 +21,7 @@ import classNames from 'classnames'; import { uniqueId } from 'lodash'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; -import DeferredSpinner from '../ui/DeferredSpinner'; +import Spinner from '../ui/Spinner'; import Checkbox from './Checkbox'; import { SelectListFilter } from './SelectList'; import SelectListListElement from './SelectListListElement'; @@ -94,7 +94,7 @@ export default class SelectListListContainer extends React.PureComponent<Props, > <span className="big-spacer-left"> {translate('bulk_change')} - <DeferredSpinner className="spacer-left" loading={this.state.loading} timeout={10} /> + <Spinner className="spacer-left" loading={this.state.loading} /> </span> </Checkbox> </li> diff --git a/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx b/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx index 0babe37d055..a88956818dd 100644 --- a/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx +++ b/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx @@ -20,10 +20,10 @@ import { FormikValues } from 'formik'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; -import DeferredSpinner from '../ui/DeferredSpinner'; -import { ResetButtonLink, SubmitButton } from './buttons'; +import Spinner from '../ui/Spinner'; import Modal, { ModalProps } from './Modal'; import ValidationForm, { ChildrenProps } from './ValidationForm'; +import { ResetButtonLink, SubmitButton } from './buttons'; interface Props<V> extends ModalProps { children: (props: ChildrenProps<V>) => React.ReactNode; @@ -65,7 +65,7 @@ export default class ValidationModal<V extends FormikValues> extends React.PureC <div className="modal-body">{this.props.children(props)}</div> <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={props.isSubmitting} /> + <Spinner className="spacer-right" loading={props.isSubmitting} /> <SubmitButton className={this.props.isDestructive ? 'button-red' : undefined} disabled={props.isSubmitting || !props.isValid || !props.dirty} diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/Checkbox-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/Checkbox-test.tsx index 51c6f35ad58..6603a1deff1 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/Checkbox-test.tsx +++ b/server/sonar-web/src/main/js/components/controls/__tests__/Checkbox-test.tsx @@ -52,11 +52,8 @@ describe.each([ }); it('should render loading state', () => { - jest.useFakeTimers(); renderCheckbox({ label: 'me', children, loading: true }); - jest.runAllTimers(); - expect(screen.getByTestId('deferred-spinner')).toMatchSnapshot(); - jest.useRealTimers(); + expect(screen.getByTestId('spinner')).toMatchSnapshot(); }); }); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/ListFooter-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/ListFooter-test.tsx index c40b9543625..709658d78f9 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/ListFooter-test.tsx +++ b/server/sonar-web/src/main/js/components/controls/__tests__/ListFooter-test.tsx @@ -86,7 +86,7 @@ describe('ListFooter using MIUI buttons', () => { describe('rendering', () => { it('should render correctly when loading', async () => { renderListFooter({ loading: true }); - expect(await screen.findByLabelText('loading')).toBeInTheDocument(); + expect(await screen.findByText('loading')).toBeInTheDocument(); }); it('should not render if there are neither loadmore nor reload props', () => { diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Checkbox-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Checkbox-test.tsx.snap index ae3c407b7bd..ccceff9af23 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Checkbox-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Checkbox-test.tsx.snap @@ -3,8 +3,8 @@ exports[`Checkbox with children should render loading state 1`] = ` <i aria-live="polite" - class="deferred-spinner is-loading" - data-testid="deferred-spinner" + class="spinner is-loading" + data-testid="spinner" > <span class="a11y-hidden" @@ -17,8 +17,8 @@ exports[`Checkbox with children should render loading state 1`] = ` exports[`Checkbox with no children should render loading state 1`] = ` <i aria-live="polite" - class="deferred-spinner is-loading" - data-testid="deferred-spinner" + class="spinner is-loading" + data-testid="spinner" > <span class="a11y-hidden" @@ -44,8 +44,8 @@ exports[`should render the checkbox on the right 1`] = ` > <i aria-live="polite" - class="deferred-spinner a11y-hidden" - data-testid="deferred-spinner" + class="spinner a11y-hidden" + data-testid="spinner" /> </div> <i diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ConfirmModal-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ConfirmModal-test.tsx.snap index f1367ae048a..ea4ee4afd8c 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ConfirmModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ConfirmModal-test.tsx.snap @@ -4,7 +4,7 @@ exports[`should confirm and close after confirm 1`] = ` <footer className="modal-foot" > - <DeferredSpinner + <Spinner className="spacer-right" loading={true} /> @@ -59,7 +59,7 @@ exports[`should render correctly 2`] = ` <footer className="modal-foot" > - <DeferredSpinner + <Spinner className="spacer-right" loading={false} /> diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap index 95e8fea7598..ce284960f01 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap @@ -16,13 +16,13 @@ exports[`renders 1`] = ` type="search" value="foo" /> - <DeferredSpinner + <Spinner loading={false} > <SearchIcon className="search-box-magnifier" /> - </DeferredSpinner> + </Spinner> <ClearButton aria-label="clear" className="button-tiny search-box-clear" diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Select-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Select-test.tsx.snap index 49cb58d74e3..0136a28365e 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Select-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Select-test.tsx.snap @@ -93,7 +93,7 @@ exports[`Select should render dropdownIndicator correctly 1`] = `<Styled(span) / exports[`Select should render loadingIndicator correctly 1`] = ` <i - className="deferred-spinner spacer-left spacer-right additional-class" + className="spinner spacer-left spacer-right additional-class" /> `; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SelectListListContainer-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SelectListListContainer-test.tsx.snap index 450d9144161..ecbe4c96647 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SelectListListContainer-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SelectListListContainer-test.tsx.snap @@ -18,10 +18,9 @@ exports[`should render correctly 1`] = ` className="big-spacer-left" > bulk_change - <DeferredSpinner + <Spinner className="spacer-left" loading={false} - timeout={10} /> </span> </Checkbox> diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap index bf6335287a5..ee17dc8e5ce 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap @@ -92,7 +92,7 @@ exports[`should render correctly 2`] = ` <footer className="modal-foot" > - <DeferredSpinner + <Spinner className="spacer-right" loading={false} /> diff --git a/server/sonar-web/src/main/js/components/facet/FacetHeader.tsx b/server/sonar-web/src/main/js/components/facet/FacetHeader.tsx index 1339669273c..e741e3084ee 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetHeader.tsx +++ b/server/sonar-web/src/main/js/components/facet/FacetHeader.tsx @@ -22,9 +22,9 @@ import * as React from 'react'; import HelpTooltip from '../../components/controls/HelpTooltip'; import { Button, ButtonLink } from '../../components/controls/buttons'; import OpenCloseIcon from '../../components/icons/OpenCloseIcon'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; import { translate, translateWithParameters } from '../../helpers/l10n'; import Tooltip from '../controls/Tooltip'; +import Spinner from '../ui/Spinner'; interface Props { children?: React.ReactNode; @@ -118,7 +118,7 @@ export default class FacetHeader extends React.PureComponent<Props> { {fetching && ( <span className="little-spacer-right"> - <DeferredSpinner /> + <Spinner /> </span> )} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/EditTokenModal.tsx b/server/sonar-web/src/main/js/components/tutorials/components/EditTokenModal.tsx index e1d62e9745d..466d63dc05d 100644 --- a/server/sonar-web/src/main/js/components/tutorials/components/EditTokenModal.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/components/EditTokenModal.tsx @@ -20,7 +20,6 @@ import { ButtonSecondary, ClipboardIconButton, - DeferredSpinner, DestructiveIcon, FlagMessage, InputField, @@ -28,6 +27,7 @@ import { LabelValueSelectOption, Link, Modal, + Spinner, TrashIcon, } from 'design-system'; import * as React from 'react'; @@ -205,7 +205,7 @@ export default class EditTokenModal extends React.PureComponent<Props, State> { ) : ( <> <div className="sw-flex sw-pt-4"> - <DeferredSpinner loading={loading}> + <Spinner loading={loading}> <div className="sw-flex-col sw-mr-2"> <label className="sw-block" htmlFor="token-name"> {translate('onboarding.token.name.label')} @@ -243,7 +243,7 @@ export default class EditTokenModal extends React.PureComponent<Props, State> { </ButtonSecondary> </div> </div> - </DeferredSpinner> + </Spinner> </div> {type === TokenType.Project && <ProjectTokenScopeInfo />} </> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/TokenStep.tsx b/server/sonar-web/src/main/js/components/tutorials/other/TokenStep.tsx index 6766b7bc279..1e0a5e4ffa6 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/TokenStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/TokenStep.tsx @@ -20,7 +20,6 @@ import { ButtonPrimary, ButtonSecondary, - DeferredSpinner, DestructiveIcon, FlagMessage, FlagSuccessIcon, @@ -32,6 +31,7 @@ import { Link, Note, RadioButton, + Spinner, TrashIcon, } from 'design-system'; import * as React from 'react'; @@ -266,7 +266,7 @@ export default class TokenStep extends React.PureComponent<Props, State> { <ButtonSecondary type="submit" disabled={!tokenName || loading} - icon={<DeferredSpinner className="sw-mr-1" loading={loading} />} + icon={<Spinner className="sw-mr-1" loading={loading} />} > {translate('onboarding.token.generate')} </ButtonSecondary> @@ -345,14 +345,14 @@ export default class TokenStep extends React.PureComponent<Props, State> { <strong className="sw-font-semibold">{token}</strong> </span> - <DeferredSpinner className="sw-ml-3 sw-my-2" loading={loading}> + <Spinner className="sw-ml-3 sw-my-2" loading={loading}> <DestructiveIcon className="sw-ml-1" Icon={TrashIcon} aria-label={translate('onboarding.token.delete')} onClick={this.handleTokenRevoke} /> - </DeferredSpinner> + </Spinner> </form> ) : ( <div> diff --git a/server/sonar-web/src/main/js/components/ui/Alert.tsx b/server/sonar-web/src/main/js/components/ui/Alert.tsx index 88f91e671fa..eb18521582f 100644 --- a/server/sonar-web/src/main/js/components/ui/Alert.tsx +++ b/server/sonar-web/src/main/js/components/ui/Alert.tsx @@ -27,7 +27,7 @@ import AlertErrorIcon from '../icons/AlertErrorIcon'; import AlertSuccessIcon from '../icons/AlertSuccessIcon'; import AlertWarnIcon from '../icons/AlertWarnIcon'; import InfoIcon from '../icons/InfoIcon'; -import DeferredSpinner from './DeferredSpinner'; +import Spinner from './Spinner'; type AlertDisplay = 'banner' | 'inline' | 'block'; export type AlertVariant = 'error' | 'warning' | 'success' | 'info' | 'loading'; @@ -140,7 +140,7 @@ function getAlertVariantInfo(variant: AlertVariant) { backGroundColor: colors.alertBackgroundInfo, }, loading: { - icon: <DeferredSpinner timeout={0} />, + icon: <Spinner />, color: colors.alertTextInfo, borderColor: colors.alertBorderInfo, backGroundColor: colors.alertBackgroundInfo, diff --git a/server/sonar-web/src/main/js/components/ui/DeferredSpinner.tsx b/server/sonar-web/src/main/js/components/ui/DeferredSpinner.tsx deleted file mode 100644 index e619906e2ff..00000000000 --- a/server/sonar-web/src/main/js/components/ui/DeferredSpinner.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 classNames from 'classnames'; -import * as React from 'react'; -import { translate } from '../../helpers/l10n'; -import './DeferredSpinner.css'; - -interface Props { - ariaLabel?: string; - children?: React.ReactNode; - className?: string; - customSpinner?: JSX.Element; - loading?: boolean; - timeout?: number; -} - -interface State { - showSpinner: boolean; -} - -const DEFAULT_TIMEOUT = 100; - -/** - * Recommendation: do not render this component conditionally based on any loading state: - * // Don't do this: - * {loading && <DeferredSpinner />} - * Instead, pass the loading state as a prop: - * // Do this: - * <DeferredSpinner loading={loading} /> - */ -export default class DeferredSpinner extends React.PureComponent<Props, State> { - timer?: number; - - state: State = { showSpinner: false }; - - componentDidMount() { - if (this.props.loading == null || this.props.loading === true) { - this.startTimer(); - } - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.loading === false && this.props.loading === true) { - this.stopTimer(); - this.startTimer(); - } - if (prevProps.loading === true && this.props.loading === false) { - this.stopTimer(); - this.setState({ showSpinner: false }); - } - } - - componentWillUnmount() { - this.stopTimer(); - } - - startTimer = () => { - this.timer = window.setTimeout( - () => this.setState({ showSpinner: true }), - this.props.timeout || DEFAULT_TIMEOUT - ); - }; - - stopTimer = () => { - window.clearTimeout(this.timer); - }; - - render() { - const { ariaLabel = translate('loading'), children, className, customSpinner } = this.props; - const { showSpinner } = this.state; - - if (customSpinner) { - return showSpinner ? customSpinner : children; - } - - return ( - <> - <div className="sw-overflow-hidden"> - <i - aria-live="polite" - data-testid="deferred-spinner" - className={classNames('deferred-spinner', className, { - 'a11y-hidden': !showSpinner, - 'is-loading': showSpinner, - })} - > - {showSpinner && <span className="a11y-hidden">{ariaLabel}</span>} - </i> - </div> - {!showSpinner && children} - </> - ); - } -} diff --git a/server/sonar-web/src/main/js/components/ui/DeferredSpinner.css b/server/sonar-web/src/main/js/components/ui/Spinner.css index dc25eecba4d..3d185b62d82 100644 --- a/server/sonar-web/src/main/js/components/ui/DeferredSpinner.css +++ b/server/sonar-web/src/main/js/components/ui/Spinner.css @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -.deferred-spinner { +.spinner { position: relative; vertical-align: middle; width: 16px; @@ -27,8 +27,8 @@ animation: spin 0.75s infinite linear; } -.deferred-spinner:before, -.deferred-spinner:after { +.spinner:before, +.spinner:after { left: -2px; top: -2px; display: none; @@ -40,9 +40,9 @@ border-radius: inherit; } -.deferred-spinner, -.deferred-spinner:before, -.deferred-spinner:after { +.spinner, +.spinner:before, +.spinner:after { display: inline-block; box-sizing: border-box; border-color: transparent; @@ -50,15 +50,15 @@ animation-duration: 1.2s; } -.deferred-spinner:before { +.spinner:before { transform: rotate(120deg); } -.deferred-spinner:after { +.spinner:after { transform: rotate(240deg); } -.deferred-spinner-placeholder { +.spinner-placeholder { position: relative; display: inline-block; vertical-align: middle; diff --git a/server/sonar-web/src/main/js/components/ui/Spinner.tsx b/server/sonar-web/src/main/js/components/ui/Spinner.tsx new file mode 100644 index 00000000000..8224074cb8e --- /dev/null +++ b/server/sonar-web/src/main/js/components/ui/Spinner.tsx @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 classNames from 'classnames'; +import * as React from 'react'; +import { translate } from '../../helpers/l10n'; +import './Spinner.css'; + +interface Props { + ariaLabel?: string; + children?: React.ReactNode; + className?: string; + customSpinner?: JSX.Element; + loading?: boolean; +} + +export default function Spinner(props: Props) { + const { + ariaLabel = translate('loading'), + children, + className, + customSpinner, + loading = true, + } = props; + + if (customSpinner) { + return <>{loading ? customSpinner : children}</>; + } + + return ( + <> + <div className="sw-overflow-hidden"> + <i + aria-live="polite" + data-testid="spinner" + className={classNames('spinner', className, { + 'a11y-hidden': !loading, + 'is-loading': loading, + })} + > + {loading && <span className="a11y-hidden">{ariaLabel}</span>} + </i> + </div> + {!loading && children} + </> + ); +} diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx b/server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx deleted file mode 100644 index 0237097d9ac..00000000000 --- a/server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 { render, screen } from '@testing-library/react'; -import * as React from 'react'; -import DeferredSpinner from '../DeferredSpinner'; - -beforeEach(() => { - jest.useFakeTimers(); -}); - -afterEach(() => { - jest.runOnlyPendingTimers(); - jest.useRealTimers(); -}); - -it('renders children before timeout', () => { - renderDeferredSpinner({ children: <a href="#">foo</a> }); - expect(screen.getByRole('link')).toBeInTheDocument(); - jest.runAllTimers(); - expect(screen.queryByRole('link')).not.toBeInTheDocument(); -}); - -it('renders spinner after timeout', () => { - renderDeferredSpinner(); - expect(screen.queryByText('loading')).not.toBeInTheDocument(); - jest.runAllTimers(); - expect(screen.getByText('loading')).toBeInTheDocument(); -}); - -it('allows setting a custom class name', () => { - renderDeferredSpinner({ className: 'foo' }); - jest.runAllTimers(); - expect(screen.getByTestId('deferred-spinner')).toHaveClass('foo'); -}); - -it('can be controlled by the loading prop', () => { - const { rerender } = renderDeferredSpinner({ loading: true }); - jest.runAllTimers(); - expect(screen.getByText('loading')).toBeInTheDocument(); - - rerender(prepareDeferredSpinner({ loading: false })); - expect(screen.queryByText('loading')).not.toBeInTheDocument(); -}); - -function renderDeferredSpinner(props: Partial<DeferredSpinner['props']> = {}) { - // We don't use our renderComponent() helper here, as we have some tests that - // require changes in props. - return render(prepareDeferredSpinner(props)); -} - -function prepareDeferredSpinner(props: Partial<DeferredSpinner['props']> = {}) { - return <DeferredSpinner ariaLabel="loading" {...props} />; -} diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/Spinner-test.tsx b/server/sonar-web/src/main/js/components/ui/__tests__/Spinner-test.tsx new file mode 100644 index 00000000000..fbc8dbda7e7 --- /dev/null +++ b/server/sonar-web/src/main/js/components/ui/__tests__/Spinner-test.tsx @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 { render, screen } from '@testing-library/react'; +import * as React from 'react'; +import Spinner from '../Spinner'; + +it('can be controlled by the loading prop', () => { + const { rerender } = renderSpinner({ loading: true }); + expect(screen.getByText('loading')).toBeInTheDocument(); + + rerender(prepareSpinner({ loading: false })); + expect(screen.queryByText('loading')).not.toBeInTheDocument(); +}); + +function renderSpinner(props: Partial<Parameters<typeof Spinner>[0]> = {}) { + // We don't use our renderComponent() helper here, as we have some tests that + // require changes in props. + return render(prepareSpinner(props)); +} + +function prepareSpinner(props: Partial<Parameters<typeof Spinner>[0]> = {}) { + return <Spinner ariaLabel="loading" {...props} />; +} diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspaceRuleDetails.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspaceRuleDetails.tsx index 3d21f1f48f5..8ade13db05c 100644 --- a/server/sonar-web/src/main/js/components/workspace/WorkspaceRuleDetails.tsx +++ b/server/sonar-web/src/main/js/components/workspace/WorkspaceRuleDetails.tsx @@ -23,8 +23,8 @@ import { getRuleDetails, getRulesApp } from '../../api/rules'; import RuleDetailsDescription from '../../apps/coding-rules/components/RuleDetailsDescription'; import RuleDetailsMeta from '../../apps/coding-rules/components/RuleDetailsMeta'; import '../../apps/coding-rules/styles.css'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; import { Dict, RuleDetails } from '../../types/types'; +import Spinner from '../ui/Spinner'; interface Props { onLoad: (details: { name: string }) => void; @@ -81,7 +81,7 @@ export default class WorkspaceRuleDetails extends React.PureComponent<Props, Sta render() { return ( - <DeferredSpinner loading={this.state.loading}> + <Spinner loading={this.state.loading}> {this.state.ruleDetails && ( <> <RuleDetailsMeta @@ -99,7 +99,7 @@ export default class WorkspaceRuleDetails extends React.PureComponent<Props, Sta /> </> )} - </DeferredSpinner> + </Spinner> ); } } diff --git a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceRuleDetails-test.tsx.snap b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceRuleDetails-test.tsx.snap index 08866c568d3..3e8578a0921 100644 --- a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceRuleDetails-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceRuleDetails-test.tsx.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render 1`] = ` -<DeferredSpinner +<Spinner loading={true} /> `; exports[`should render 2`] = ` -<DeferredSpinner +<Spinner loading={false} > <RuleDetailsMeta @@ -41,5 +41,5 @@ exports[`should render 2`] = ` } } /> -</DeferredSpinner> +</Spinner> `; diff --git a/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx b/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx index 5a47af23c3e..ad497152d76 100644 --- a/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx +++ b/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx @@ -23,7 +23,7 @@ import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup'; import { omit } from 'lodash'; import * as React from 'react'; import { HelmetProvider } from 'react-helmet-async'; -import { IntlProvider } from 'react-intl'; +import { IntlProvider, ReactIntlErrorCode } from 'react-intl'; import { MemoryRouter, Outlet, Route, Routes, parsePath } from 'react-router-dom'; import AdminContext from '../app/components/AdminContext'; import GlobalMessagesContainer from '../app/components/GlobalMessagesContainer'; @@ -100,7 +100,7 @@ export function renderComponent( const queryClient = new QueryClient(); return ( - <IntlProvider defaultLocale="en" locale="en"> + <IntlWrapper> <QueryClientProvider client={queryClient}> <HelmetProvider> <AvailableFeaturesContext.Provider value={featureList}> @@ -114,7 +114,7 @@ export function renderComponent( </AvailableFeaturesContext.Provider> </HelmetProvider> </QueryClientProvider> - </IntlProvider> + </IntlWrapper> ); } @@ -194,7 +194,7 @@ function renderRoutedApp( return render( <HelmetProvider context={{}}> - <IntlProvider defaultLocale="en" locale="en"> + <IntlWrapper> <MetricsContext.Provider value={metrics}> <LanguagesContext.Provider value={languages}> <AvailableFeaturesContext.Provider value={featureList}> @@ -216,7 +216,7 @@ function renderRoutedApp( </AvailableFeaturesContext.Provider> </LanguagesContext.Provider> </MetricsContext.Provider> - </IntlProvider> + </IntlWrapper> </HelmetProvider> ); } @@ -259,3 +259,28 @@ Example: ? within(target).getByText(text, { selector }) : screen.getByText(text, { selector }); } + +export function IntlWrapper({ + children, + messages = {}, +}: { + children: React.ReactNode; + messages?: Record<string, string>; +}) { + return ( + <IntlProvider + defaultLocale="en" + locale="en" + messages={messages} + onError={(e) => { + // ignore missing translations, there are none! + if (e.code !== ReactIntlErrorCode.MISSING_TRANSLATION) { + // eslint-disable-next-line no-console + console.error(e); + } + }} + > + {children} + </IntlProvider> + ); +} |