From d72f2c84df6986c8a097be153269eae7f5ba0ea5 Mon Sep 17 00:00:00 2001 From: Viktor Vorona Date: Thu, 10 Aug 2023 12:25:28 +0200 Subject: [PATCH] SONAR-19465 Remove deferred state from spinner --- .../design-system/src/components/FacetBox.tsx | 4 +- .../{DeferredSpinner.tsx => Spinner.tsx} | 99 ++++-------- .../__tests__/ColorsLegend-test.tsx | 4 +- .../__tests__/DeferredSpinner-test.tsx | 74 --------- .../components/__tests__/FacetBox-test.tsx | 4 +- .../components/__tests__/Spinner-test.tsx} | 49 ++---- .../src/components/__tests__/Tags-test.tsx | 5 +- .../design-system/src/components/index.ts | 2 +- .../src/components/input/Checkbox.tsx | 9 +- .../src/components/input/InputSearch.tsx | 6 +- .../input/__tests__/InputSearch-test.tsx | 4 +- .../src/components/modal/ModalFooter.tsx | 4 +- .../modal/__tests__/ModalFooter-test.tsx | 4 +- .../__snapshots__/ModalFooter-test.tsx.snap | 84 ++++++++++ ...ional-rendering-of-deferredspinner-test.js | 8 +- ...onditional-rendering-of-deferredspinner.js | 4 +- .../global-search/GlobalSearchShowMore.tsx | 6 +- .../nav/component/AnalysisStatus.tsx | 4 +- .../nav/component/AnalysisWarningsModal.tsx | 13 +- .../src/main/js/app/styles/init/misc.css | 2 +- .../js/apps/account/__tests__/Account-it.tsx | 2 +- .../account/notifications/Notifications.tsx | 6 +- .../components/AnalysisWarningsModal.tsx | 14 +- .../components/BackgroundTasksApp.tsx | 4 +- .../apps/code/components/CodeAppRenderer.tsx | 6 +- .../main/js/apps/code/components/Search.tsx | 4 +- .../coding-rules/components/RuleDetails.tsx | 6 +- .../components/RuleDetailsCustomRules.tsx | 6 +- .../components/RuleDetailsIssues.tsx | 6 +- .../coding-rules/components/StandardFacet.tsx | 6 +- .../components/ComponentMeasuresApp.tsx | 7 +- .../components/MeasureOverview.tsx | 4 +- .../Azure/AzurePersonalAccessTokenForm.tsx | 6 +- .../project/Azure/AzureProjectAccordion.tsx | 9 +- .../Azure/AzureProjectCreateRenderer.tsx | 8 +- .../BitbucketCloudPersonalAccessTokenForm.tsx | 6 +- .../BitbucketCloudProjectCreateRender.tsx | 4 +- .../BitbucketProjectCreateRenderer.tsx | 6 +- .../BitbucketSearchResults.tsx | 6 +- ...BitbucketServerPersonalAccessTokenForm.tsx | 6 +- .../project/CreateProjectModeSelection.tsx | 6 +- .../Github/GitHubProjectCreateRenderer.tsx | 8 +- .../Gitlab/GItlabPersonalAccessTokenForm.tsx | 6 +- .../Gitlab/GitlabProjectCreateRenderer.tsx | 4 +- .../create/project/__tests__/GitHub-it.tsx | 3 - .../components/NewCodeDefinitionSelection.tsx | 4 +- .../groups/components/DeleteGroupForm.tsx | 6 +- .../js/apps/groups/components/GroupForm.tsx | 6 +- .../groups/components/ViewMembersModal.tsx | 6 +- .../js/apps/issues/__tests__/IssuesApp-it.tsx | 11 +- .../issues/components/BulkChangeModal.tsx | 6 +- .../js/apps/issues/components/IssuesApp.tsx | 10 +- .../CrossComponentSourceViewer.tsx | 4 +- .../IssueSourceViewerHeader.tsx | 4 +- .../SubnavigationIssuesListHeader.tsx | 6 +- .../src/main/js/apps/marketplace/App.tsx | 6 +- .../apps/overview/branches/ActivityPanel.tsx | 6 +- .../apps/overview/branches/MeasuresPanel.tsx | 4 +- .../overview/branches/QualityGatePanel.tsx | 4 +- .../overview/components/EmptyOverview.tsx | 4 +- .../pullRequests/PullRequestOverview.tsx | 4 +- .../components/DeleteForm.tsx | 6 +- .../permission-templates/components/Form.tsx | 6 +- .../components/Header.tsx | 4 +- .../components/TemplateHeader.tsx | 4 +- .../project/components/ApplyTemplate.tsx | 6 +- .../project/components/PageHeader.tsx | 4 +- .../ProjectActivityAnalysesList.tsx | 6 +- .../components/BranchAnalysisListRenderer.tsx | 4 +- .../components/BranchBaselineSettingModal.tsx | 4 +- .../projectBaseline/components/BranchList.tsx | 4 +- .../components/ProjectBaselineApp.tsx | 4 +- .../components/ProjectBaselineSelector.tsx | 4 +- .../components/BranchPurgeSetting.tsx | 4 +- .../LifetimeInformationRenderer.tsx | 6 +- .../badges/ProjectBadges.tsx | 10 +- .../notifications/ProjectNotifications.tsx | 6 +- .../js/apps/projectLinks/CreationModal.tsx | 6 +- .../js/apps/projectLinks/ProjectLinksApp.tsx | 6 +- .../apps/projects/components/AllProjects.tsx | 4 +- .../projectsManagement/ProjectRowActions.tsx | 4 +- .../js/apps/quality-gates/components/App.tsx | 6 +- .../apps/quality-gates/components/Details.tsx | 6 +- .../QualityGatePermissionsRenderer.tsx | 8 +- .../changelog/ChangelogContainer.tsx | 4 +- .../compare/ComparisonResultActivation.tsx | 8 +- .../SecurityHotspotsAppRenderer.tsx | 18 +-- .../components/HotspotOpenInIdeButton.tsx | 4 +- .../components/HotspotSidebarHeader.tsx | 150 +++++++++--------- .../HotspotSnippetContainerRenderer.tsx | 4 +- .../components/HotspotViewerRenderer.tsx | 4 +- .../js/apps/sessions/components/Login.tsx | 4 +- .../js/apps/sessions/components/LoginForm.tsx | 4 +- .../js/apps/settings/components/EmailForm.tsx | 4 +- .../settings/components/NewCodePeriod.tsx | 8 +- .../AlmBindingDefinitionFormRenderer.tsx | 4 +- .../almIntegration/AlmTabRenderer.tsx | 6 +- .../authentication/ConfigurationForm.tsx | 11 +- .../PRDecorationBindingRenderer.tsx | 8 +- .../settings/encryption/EncryptionApp.tsx | 4 +- .../settings/encryption/EncryptionForm.tsx | 6 +- .../encryption/GenerateSecretKeyForm.tsx | 4 +- .../src/main/js/apps/users/UsersApp.tsx | 6 +- .../js/apps/users/components/TokensForm.tsx | 6 +- .../apps/users/components/TokensFormItem.tsx | 8 +- .../src/main/js/apps/web-api-v2/WebApiApp.tsx | 10 +- .../webhooks/components/DeleteWebhookForm.tsx | 4 +- .../webhooks/components/DeliveriesForm.tsx | 4 +- .../apps/webhooks/components/DeliveryItem.tsx | 6 +- .../SourceViewer/SourceViewerCode.tsx | 6 +- .../activity-graph/GraphsHistory.tsx | 4 +- .../__tests__/ActivityGraph-it.tsx | 2 +- .../main/js/components/controls/Checkbox.tsx | 8 +- .../js/components/controls/ConfirmModal.tsx | 6 +- .../js/components/controls/ListFooter.tsx | 6 +- .../main/js/components/controls/SearchBox.css | 2 +- .../main/js/components/controls/SearchBox.tsx | 6 +- .../main/js/components/controls/Select.tsx | 4 +- .../controls/SelectListListContainer.tsx | 4 +- .../components/controls/ValidationModal.tsx | 6 +- .../controls/__tests__/Checkbox-test.tsx | 5 +- .../controls/__tests__/ListFooter-test.tsx | 2 +- .../__snapshots__/Checkbox-test.tsx.snap | 12 +- .../__snapshots__/ConfirmModal-test.tsx.snap | 4 +- .../__snapshots__/SearchBox-test.tsx.snap | 4 +- .../__snapshots__/Select-test.tsx.snap | 2 +- .../SelectListListContainer-test.tsx.snap | 3 +- .../ValidationModal-test.tsx.snap | 2 +- .../main/js/components/facet/FacetHeader.tsx | 4 +- .../tutorials/components/EditTokenModal.tsx | 6 +- .../components/tutorials/other/TokenStep.tsx | 8 +- .../src/main/js/components/ui/Alert.tsx | 4 +- .../main/js/components/ui/DeferredSpinner.tsx | 111 ------------- .../ui/{DeferredSpinner.css => Spinner.css} | 18 +-- .../src/main/js/components/ui/Spinner.tsx | 63 ++++++++ .../components/ui/__tests__/Spinner-test.tsx | 40 +++++ .../workspace/WorkspaceRuleDetails.tsx | 6 +- .../WorkspaceRuleDetails-test.tsx.snap | 6 +- .../main/js/helpers/testReactTestingUtils.tsx | 35 +++- 139 files changed, 687 insertions(+), 752 deletions(-) rename server/sonar-web/design-system/src/components/{DeferredSpinner.tsx => Spinner.tsx} (52%) delete mode 100644 server/sonar-web/design-system/src/components/__tests__/DeferredSpinner-test.tsx rename server/sonar-web/{src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx => design-system/src/components/__tests__/Spinner-test.tsx} (50%) delete mode 100644 server/sonar-web/src/main/js/components/ui/DeferredSpinner.tsx rename server/sonar-web/src/main/js/components/ui/{DeferredSpinner.css => Spinner.css} (87%) create mode 100644 server/sonar-web/src/main/js/components/ui/Spinner.tsx create mode 100644 server/sonar-web/src/main/js/components/ui/__tests__/Spinner-test.tsx diff --git a/server/sonar-web/design-system/src/components/FacetBox.tsx b/server/sonar-web/design-system/src/components/FacetBox.tsx index 0366e6fe69e..5736f58d0e1 100644 --- a/server/sonar-web/design-system/src/components/FacetBox.tsx +++ b/server/sonar-web/design-system/src/components/FacetBox.tsx @@ -25,8 +25,8 @@ import * as React from 'react'; import tw from 'twin.macro'; import { themeColor } from '../helpers'; import { Badge } from './Badge'; -import { DeferredSpinner } from './DeferredSpinner'; import { DestructiveIcon } from './InteractiveIcon'; +import { Spinner } from './Spinner'; import Tooltip from './Tooltip'; import { BareButton } from './buttons'; import { OpenCloseIndicator } from './icons'; @@ -103,7 +103,7 @@ export function FacetBox(props: FacetBoxProps) { {name} - {} + {} {counter > 0 && ( diff --git a/server/sonar-web/design-system/src/components/DeferredSpinner.tsx b/server/sonar-web/design-system/src/components/Spinner.tsx similarity index 52% rename from server/sonar-web/design-system/src/components/DeferredSpinner.tsx rename to server/sonar-web/design-system/src/components/Spinner.tsx index ad03b0fdf59..aa5db5e1415 100644 --- a/server/sonar-web/design-system/src/components/DeferredSpinner.tsx +++ b/server/sonar-web/design-system/src/components/Spinner.tsx @@ -19,81 +19,49 @@ */ import { keyframes } from '@emotion/react'; import styled from '@emotion/styled'; -import React, { DetailedHTMLProps, HTMLAttributes } from 'react'; +import classNames from 'classnames'; +import * as React from 'react'; import { useIntl } from 'react-intl'; import tw from 'twin.macro'; import { themeColor } from '../helpers/theme'; interface Props { ariaLabel?: string; - children?: React.ReactNode; className?: string; customSpinner?: JSX.Element; loading?: boolean; placeholder?: boolean; - timeout?: number; } -interface State { - showSpinner: boolean; -} - -const DEFAULT_TIMEOUT = 100; - -export class DeferredSpinner extends React.PureComponent { - timer?: number; - static displayName = 'DeferredSpinner'; - state: State = { showSpinner: false }; - - componentDidMount() { - if (this.props.loading == null || this.props.loading) { - 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(); +export function Spinner(props: React.PropsWithChildren) { + const intl = useIntl(); + const { + customSpinner, + className, + children, + placeholder, + ariaLabel = intl.formatMessage({ id: 'loading' }), + loading = true, + } = props; + + if (customSpinner) { + return <>{loading ? customSpinner : children}; } - startTimer = () => { - this.timer = window.setTimeout(() => { - this.setState({ showSpinner: true }); - }, this.props.timeout ?? DEFAULT_TIMEOUT); - }; - - stopTimer = () => { - window.clearTimeout(this.timer); - }; - - render() { - const { showSpinner } = this.state; - const { customSpinner, className, children, placeholder, ariaLabel } = this.props; - if (showSpinner) { - if (customSpinner) { - return customSpinner; - } - // Overwrite aria-label only if defined - return ; - } - if (children) { - return children; - } - if (placeholder) { - return ; - } - return null; - } + return ( + <> +
+ + {loading && {ariaLabel}} + +
+ {!loading && (children ?? (placeholder && ) ?? null)} + + ); } const spinAnimation = keyframes` @@ -106,7 +74,6 @@ const spinAnimation = keyframes` } `; -/* Exported to allow styles to be overridden */ export const StyledSpinner = styled.div` border: 2px solid transparent; background: linear-gradient(0deg, ${themeColor('primary')} 50%, transparent 50% 100%) border-box, @@ -122,14 +89,6 @@ export const StyledSpinner = styled.div` ${tw`sw-rounded-pill`} `; -export function Spinner(props: DetailedHTMLProps, HTMLDivElement>) { - const intl = useIntl(); - - return ( - - ); -} - const Placeholder = styled.div` position: relative; visibility: hidden; diff --git a/server/sonar-web/design-system/src/components/__tests__/ColorsLegend-test.tsx b/server/sonar-web/design-system/src/components/__tests__/ColorsLegend-test.tsx index cb70e5fe760..ca4b3a4e332 100644 --- a/server/sonar-web/design-system/src/components/__tests__/ColorsLegend-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/ColorsLegend-test.tsx @@ -19,7 +19,7 @@ */ import { screen } from '@testing-library/react'; -import { render } from '../../helpers/testUtils'; +import { renderWithContext } from '../../helpers/testUtils'; import { FCProps } from '../../types/misc'; import { ColorsLegend } from '../ColorsLegend'; @@ -53,5 +53,5 @@ it('should react when a rating is clicked', () => { }); function renderColorLegend(props: Partial> = {}) { - return render(); + return renderWithContext(); } diff --git a/server/sonar-web/design-system/src/components/__tests__/DeferredSpinner-test.tsx b/server/sonar-web/design-system/src/components/__tests__/DeferredSpinner-test.tsx deleted file mode 100644 index d8dd6ab7bf0..00000000000 --- a/server/sonar-web/design-system/src/components/__tests__/DeferredSpinner-test.tsx +++ /dev/null @@ -1,74 +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 { IntlWrapper } from '../../helpers/testUtils'; -import { DeferredSpinner } from '../DeferredSpinner'; - -beforeEach(() => { - jest.useFakeTimers(); -}); - -afterEach(() => { - jest.runOnlyPendingTimers(); - jest.useRealTimers(); -}); - -it('renders children before timeout', () => { - renderDeferredSpinner({ children: foo }); - expect(screen.getByRole('link')).toBeInTheDocument(); - jest.runAllTimers(); - expect(screen.queryByRole('link')).not.toBeInTheDocument(); -}); - -it('renders spinner after timeout', () => { - renderDeferredSpinner(); - expect(screen.queryByLabelText('loading')).not.toBeInTheDocument(); - jest.runAllTimers(); - expect(screen.getByLabelText('loading')).toBeInTheDocument(); -}); - -it('allows setting a custom class name', () => { - renderDeferredSpinner({ className: 'foo' }); - jest.runAllTimers(); - expect(screen.getByLabelText('loading')).toHaveClass('foo'); -}); - -it('can be controlled by the loading prop', () => { - const { rerender } = renderDeferredSpinner({ loading: true }); - jest.runAllTimers(); - expect(screen.getByLabelText('loading')).toBeInTheDocument(); - - rerender(prepareDeferredSpinner({ loading: false })); - expect(screen.queryByLabelText('loading')).not.toBeInTheDocument(); -}); - -function renderDeferredSpinner(props: Partial = {}) { - // 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 = {}) { - return ( - - - - ); -} diff --git a/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx b/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx index 434a6147e5c..a7146855abf 100644 --- a/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx @@ -20,7 +20,7 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { render } from '../../helpers/testUtils'; +import { renderWithContext } from '../../helpers/testUtils'; import { FacetBox, FacetBoxProps } from '../FacetBox'; it('should render an empty disabled facet box', async () => { @@ -68,7 +68,7 @@ it('should render an inner expanded facet box with count', async () => { }); function renderComponent({ children, ...props }: Partial = {}) { - return render( + return renderWithContext( {children} diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx b/server/sonar-web/design-system/src/components/__tests__/Spinner-test.tsx similarity index 50% rename from server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx rename to server/sonar-web/design-system/src/components/__tests__/Spinner-test.tsx index 0237097d9ac..b92b41ab489 100644 --- a/server/sonar-web/src/main/js/components/ui/__tests__/DeferredSpinner-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/Spinner-test.tsx @@ -18,53 +18,32 @@ * 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: foo }); - 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(); -}); +import { IntlWrapper } from '../../helpers/testUtils'; +import { Spinner } from '../Spinner'; it('allows setting a custom class name', () => { - renderDeferredSpinner({ className: 'foo' }); - jest.runAllTimers(); - expect(screen.getByTestId('deferred-spinner')).toHaveClass('foo'); + renderSpinner({ className: 'foo' }); + expect(screen.getByRole('status')).toHaveClass('foo'); }); it('can be controlled by the loading prop', () => { - const { rerender } = renderDeferredSpinner({ loading: true }); - jest.runAllTimers(); + const { rerender } = renderSpinner({ loading: true }); expect(screen.getByText('loading')).toBeInTheDocument(); - rerender(prepareDeferredSpinner({ loading: false })); + rerender(prepareSpinner({ loading: false })); expect(screen.queryByText('loading')).not.toBeInTheDocument(); }); -function renderDeferredSpinner(props: Partial = {}) { +function renderSpinner(props: Partial[0]> = {}) { // We don't use our renderComponent() helper here, as we have some tests that // require changes in props. - return render(prepareDeferredSpinner(props)); + return render(prepareSpinner(props)); } -function prepareDeferredSpinner(props: Partial = {}) { - return ; +function prepareSpinner(props: Partial[0]> = {}) { + return ( + + + + ); } diff --git a/server/sonar-web/design-system/src/components/__tests__/Tags-test.tsx b/server/sonar-web/design-system/src/components/__tests__/Tags-test.tsx index 7192c8d91e0..2974d489803 100644 --- a/server/sonar-web/design-system/src/components/__tests__/Tags-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/Tags-test.tsx @@ -20,9 +20,10 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { useState } from 'react'; +import { renderWithContext } from '../../helpers/testUtils'; import { FCProps } from '../../types/misc'; import { Tags } from '../Tags'; import { TagsSelector } from '../TagsSelector'; @@ -75,7 +76,7 @@ it('should allow editing tags', async () => { }); function renderTags(overrides: Partial> = {}) { - render(); + renderWithContext(); } function Wrapper(overrides: Partial> = {}) { diff --git a/server/sonar-web/design-system/src/components/index.ts b/server/sonar-web/design-system/src/components/index.ts index 484ae86999d..bc774d6885a 100644 --- a/server/sonar-web/design-system/src/components/index.ts +++ b/server/sonar-web/design-system/src/components/index.ts @@ -31,7 +31,6 @@ export * from './CodeSnippet'; export * from './CodeSyntaxHighlighter'; export * from './ColorsLegend'; export * from './CoverageIndicator'; -export { DeferredSpinner, Spinner } from './DeferredSpinner'; export { ActionsDropdown, Dropdown } from './Dropdown'; export * from './DropdownMenu'; export { DropdownToggler } from './DropdownToggler'; @@ -69,6 +68,7 @@ export * from './Separator'; export * from './SizeIndicator'; export * from './SonarCodeColorizer'; export * from './SonarQubeLogo'; +export { Spinner } from './Spinner'; export * from './Table'; export * from './Tags'; export * from './TagsSelector'; diff --git a/server/sonar-web/design-system/src/components/input/Checkbox.tsx b/server/sonar-web/design-system/src/components/input/Checkbox.tsx index 707cae6aa65..9266b88cd60 100644 --- a/server/sonar-web/design-system/src/components/input/Checkbox.tsx +++ b/server/sonar-web/design-system/src/components/input/Checkbox.tsx @@ -19,10 +19,10 @@ */ import styled from '@emotion/styled'; +import { Spinner } from 'design-system/src/components/Spinner'; import React from 'react'; import tw from 'twin.macro'; import { themeBorder, themeColor, themeContrast } from '../../helpers/theme'; -import { DeferredSpinner } from '../DeferredSpinner'; import { CheckIcon } from '../icons/CheckIcon'; import { CustomIcon } from '../icons/Icon'; @@ -76,11 +76,12 @@ export function Checkbox({ onFocus={onFocus} type="checkbox" /> - + {!loading && ( - + )} + {!right && children} ); @@ -99,7 +100,7 @@ function CheckboxIcon({ checked, thirdState }: CheckIconProps) { ); } else if (checked) { - return ; + return ; } return null; } diff --git a/server/sonar-web/design-system/src/components/input/InputSearch.tsx b/server/sonar-web/design-system/src/components/input/InputSearch.tsx index cb3eed1cbeb..b4f72d2f8de 100644 --- a/server/sonar-web/design-system/src/components/input/InputSearch.tsx +++ b/server/sonar-web/design-system/src/components/input/InputSearch.tsx @@ -28,8 +28,8 @@ import { Key } from '../../helpers/keyboard'; import { themeBorder, themeColor, themeContrast } from '../../helpers/theme'; import { isDefined } from '../../helpers/types'; import { InputSizeKeys } from '../../types/theme'; -import { DeferredSpinner, StyledSpinner } from '../DeferredSpinner'; import { InteractiveIcon } from '../InteractiveIcon'; +import { Spinner, StyledSpinner } from '../Spinner'; import { CloseIcon } from '../icons/CloseIcon'; import { SearchIcon } from '../icons/SearchIcon'; @@ -160,9 +160,9 @@ export function InputSearch({ value={value} /> )} - + - + {value && ( { }); function setupWithProps(props: Partial> = {}) { - return render( + return renderWithContext( - + {primaryButton} {secondaryButton} diff --git a/server/sonar-web/design-system/src/components/modal/__tests__/ModalFooter-test.tsx b/server/sonar-web/design-system/src/components/modal/__tests__/ModalFooter-test.tsx index ab2c19c133d..e9d1256828f 100644 --- a/server/sonar-web/design-system/src/components/modal/__tests__/ModalFooter-test.tsx +++ b/server/sonar-web/design-system/src/components/modal/__tests__/ModalFooter-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { render } from '../../../helpers/testUtils'; +import { renderWithContext } from '../../../helpers/testUtils'; import { FCProps } from '../../../types/misc'; import { ModalFooter } from '../ModalFooter'; @@ -52,5 +52,5 @@ it('should render with primary and secondary buttons', () => { }); function setupWithProps(props: Partial> = {}) { - return render(} {...props} />); + return renderWithContext(} {...props} />); } diff --git a/server/sonar-web/design-system/src/components/modal/__tests__/__snapshots__/ModalFooter-test.tsx.snap b/server/sonar-web/design-system/src/components/modal/__tests__/__snapshots__/ModalFooter-test.tsx.snap index ace0eba51cf..13e1e90ab13 100644 --- a/server/sonar-web/design-system/src/components/modal/__tests__/__snapshots__/ModalFooter-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/modal/__tests__/__snapshots__/ModalFooter-test.tsx.snap @@ -1,6 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render with primary and secondary buttons 1`] = ` +@keyframes animation-0 { + from { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(-360deg); + -moz-transform: rotate(-360deg); + -ms-transform: rotate(-360deg); + transform: rotate(-360deg); + } +} + .emotion-0 { display: -webkit-box; display: -webkit-flex; @@ -17,10 +33,36 @@ exports[`should render with primary and secondary buttons 1`] = ` gap: 0.75rem; } +.emotion-2 { + border: 2px solid transparent; + background: linear-gradient(0deg, rgb(93,108,208) 50%, transparent 50% 100%) border-box,linear-gradient(90deg, rgb(93,108,208) 25%, transparent 75% 100%) border-box; + -webkit-mask: linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0); + mask: linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + -webkit-mask-composite: exclude; + mask-composite: exclude; + -webkit-animation: animation-0 1s infinite linear; + animation: animation-0 1s infinite linear; + height: 1rem; + width: 1rem; + display: inline-block; + box-sizing: border-box; + border-radius: 625rem; +} +
+
+
+
); 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 { return (
- +

{translate('coding_rules.issues')} {this.renderTotal()} @@ -171,7 +171,7 @@ export class RuleDetailsIssues extends React.PureComponent { {translate('coding_rules.no_issue_detected_for_projects')}

)} - +
); } 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 { const values = this.props[valuesProp]; if (!stats) { - return ; + return ; } const categories = sortBy(Object.keys(stats), (key) => -stats[key]); @@ -321,7 +321,7 @@ export class StandardFacet extends React.PureComponent { const values = this.props.sonarsourceSecurity; if (!stats) { - return ; + return ; } 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 { - + {measures.length > 0 ? (
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 { />
- + {!loading && this.renderContent(isFileComponent)}
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 ; + return ; } const isInvalid = (validationFailed && !touched) || (touched && !password); @@ -147,7 +147,7 @@ export default function AzurePersonalAccessTokenForm({ {translate('save')} - +
); 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 && ( - - {/* The extra loading guard is to prevent the flash of the Alert */} - {!loading && repositories.length === 0 ? ( + + {repositories.length === 0 ? ( )} - +
)} ); 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} /> - + {showUrlError && ( @@ -142,7 +142,7 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend size="full" /> - + - + ))} 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 ; + return ; } const isInvalid = validationFailed && !touched; @@ -179,7 +179,7 @@ export default function BitbucketCloudPersonalAccessTokenForm({ {translate('save')} - + ); } 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} /> - + {!loading && !selectedAlmInstance && ( 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} /> - + {!loading && !selectedAlmInstance && ( )} @@ -104,7 +104,7 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr onImportRepository={props.onImportRepository} /> ))} - + ); } 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 ( - + {filteredSearchResults.length > 0 && ( ); })} - + ); } 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 ; + return ; } const { url } = almSetting; @@ -143,7 +143,7 @@ export default function BitbucketServerPersonalAccessTokenForm({ {translate('save')} - + ); } 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( )} - + {!hasConfig && (canAdmin ? ( props.onConfigMode(configMode)}> @@ -117,7 +117,7 @@ function renderAlmOption( ))} - + ); } 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 ; + return ; } return ( @@ -172,7 +172,7 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe )} - + {!error && (
@@ -215,7 +215,7 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe )}
)} -
+
{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 ; + return ; } const isInvalid = validationFailed && !touched; @@ -136,7 +136,7 @@ export default function GitlabPersonalAccessTokenForm({ {translate('save')} - + ); } 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} /> - + {!loading && !selectedAlmInstance && ( 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')} - + 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) {