diff options
Diffstat (limited to 'server/sonar-web/src/main/js/app')
51 files changed, 426 insertions, 2839 deletions
diff --git a/server/sonar-web/src/main/js/app/components/AlmSynchronisationWarning.tsx b/server/sonar-web/src/main/js/app/components/AlmSynchronisationWarning.tsx index 9f6259e4a32..ffc9f55bdaf 100644 --- a/server/sonar-web/src/main/js/app/components/AlmSynchronisationWarning.tsx +++ b/server/sonar-web/src/main/js/app/components/AlmSynchronisationWarning.tsx @@ -25,7 +25,6 @@ import { FormattedMessage } from 'react-intl'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { AlmSyncStatus } from '../../types/provisioning'; import { TaskStatuses } from '../../types/tasks'; -import './SystemAnnouncement.css'; interface SynchronisationWarningProps { short?: boolean; diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx index aed1b98b8f6..b96e54a5d4d 100644 --- a/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx +++ b/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx @@ -17,9 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Card, CenteredLayout, Link, SubHeading } from 'design-system/lib'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; -import Link from '../../components/common/Link'; import { translate } from '../../helpers/l10n'; export interface ComponentContainerNotFoundProps { @@ -32,19 +32,15 @@ export default function ComponentContainerNotFound({ const componentType = isPortfolioLike ? 'portfolio' : 'project'; return ( - <> + <CenteredLayout className="sw-flex sw-justify-around" id="bd"> <Helmet defaultTitle={translate('404_not_found')} defer={false} /> - <div className="page-wrapper-simple" id="bd"> - <div className="page-simple" id="nonav"> - <h2 className="big-spacer-bottom"> - {translate('dashboard', componentType, 'not_found')} - </h2> - <p className="spacer-bottom">{translate('dashboard', componentType, 'not_found.2')}</p> - <p> - <Link to="/">{translate('go_back_to_homepage')}</Link> - </p> - </div> - </div> - </> + <Card className="sw-mt-24" id="nonav"> + <SubHeading>{translate('dashboard', componentType, 'not_found')}</SubHeading> + <p className="sw-mb-2">{translate('dashboard', componentType, 'not_found.2')}</p> + <p> + <Link to="/">{translate('go_back_to_homepage')}</Link> + </p> + </Card> + </CenteredLayout> ); } diff --git a/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx b/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx index db9b1473502..ce07d94d59d 100644 --- a/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx +++ b/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx @@ -17,10 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Link } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { useLocation } from 'react-router-dom'; -import Link from '../../components/common/Link'; import { useDocUrl } from '../../helpers/docs'; const PAUSE_REDIRECT = 1; @@ -34,12 +34,12 @@ export default function DocumentationRedirect() { <Helmet> <meta httpEquiv="refresh" content={`${PAUSE_REDIRECT}; url='${url}'`} /> </Helmet> - <div className="global-loading"> - <div className="display-flex-center"> - <i className="spinner global-loading-spinner" /> - <span className="spacer-left global-loading-text">Redirecting...</span> + <div className="sw-flex sw-flex-col sw-items-center sw-gap-4 sw-h-[100vh]"> + <div className="global-loading"> + <i className="global-loading-spinner" /> + <span className="global-loading-text">Redirecting...</span> </div> - <div className="display-flex-justify-content spacer-top large"> + <div> <Link to={url}>Click here if you're not being redirected automatically</Link> </div> </div> diff --git a/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx b/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx index 5adbce4ac73..12c1592adb7 100644 --- a/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx +++ b/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx @@ -20,7 +20,6 @@ import * as React from 'react'; import { useGitHubSyncStatusQuery } from '../../queries/identity-provider/github'; import AlmSynchronisationWarning from './AlmSynchronisationWarning'; -import './SystemAnnouncement.css'; interface Props { short?: boolean; diff --git a/server/sonar-web/src/main/js/app/components/GitLabSynchronisationWarning.tsx b/server/sonar-web/src/main/js/app/components/GitLabSynchronisationWarning.tsx index 39a18f809ad..806882fa76b 100644 --- a/server/sonar-web/src/main/js/app/components/GitLabSynchronisationWarning.tsx +++ b/server/sonar-web/src/main/js/app/components/GitLabSynchronisationWarning.tsx @@ -20,7 +20,6 @@ import * as React from 'react'; import { useGitLabSyncStatusQuery } from '../../queries/identity-provider/gitlab'; import AlmSynchronisationWarning from './AlmSynchronisationWarning'; -import './SystemAnnouncement.css'; interface Props { short?: boolean; diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx index 66951e5aae3..d8aa49d5ce2 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -18,8 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { ThemeProvider } from '@emotion/react'; -import classNames from 'classnames'; -import { lightTheme, ToastMessageContainer } from 'design-system'; +import styled from '@emotion/styled'; +import { lightTheme, themeColor, ToastMessageContainer } from 'design-system'; import * as React from 'react'; import { Outlet, useLocation } from 'react-router-dom'; import A11yProvider from '../../components/a11y/A11yProvider'; @@ -38,30 +38,11 @@ import StartupModal from './StartupModal'; import SystemAnnouncement from './SystemAnnouncement'; import UpdateNotification from './update-notification/UpdateNotification'; -const TEMP_PAGELIST_WITH_NEW_BACKGROUND = [ - '/admin/extension/governance/views_console', - '/admin/extension/license', - '/code', - '/coding_rules', - '/component_measures', - '/dashboard', - '/portfolios', - '/profiles', - '/project/activity', - '/project/admin/extension/governance/console', - '/project/admin/extension/governance/report', - '/project/extension/securityreport/securityreport', - '/project/information', - '/project/issues', - '/projects', - '/quality_gates', - '/security_hotspots', - '/web_api_v2', - '/portfolio', - '/account', -]; - -const TEMP_PAGELIST_WITH_NEW_BACKGROUND_WHITE = [ +/* + * These pages need a white background (aka 'secondary', rather than the default 'primary') + * This should be revisited at some point (why the exception?) + */ +const PAGES_WITH_SECONDARY_BACKGROUND = [ '/tutorials', '/projects/create', '/project/baseline', @@ -101,15 +82,9 @@ export default function GlobalContainer() { <A11yProvider> <A11ySkipLinks /> <div className="global-container"> - <div - className={classNames('page-wrapper', { - 'new-background': TEMP_PAGELIST_WITH_NEW_BACKGROUND.some((element) => - location.pathname.startsWith(element), - ), - 'white-background': TEMP_PAGELIST_WITH_NEW_BACKGROUND_WHITE.includes( - location.pathname, - ), - })} + <GlobalBackground + secondary={PAGES_WITH_SECONDARY_BACKGROUND.includes(location.pathname)} + className="sw-box-border sw-flex-[1_0_auto]" id="container" > <div className="page-container"> @@ -136,7 +111,7 @@ export default function GlobalContainer() { </Workspace> </div> <PromotionNotification /> - </div> + </GlobalBackground> <GlobalFooter /> </div> <StartupModal /> @@ -145,3 +120,8 @@ export default function GlobalContainer() { </ThemeProvider> ); } + +const GlobalBackground = styled.div<{ secondary: boolean }>` + background-color: ${({ secondary }) => + themeColor(secondary ? 'backgroundSecondary' : 'backgroundPrimary')}; +`; diff --git a/server/sonar-web/src/main/js/app/components/LicensePromptModal.tsx b/server/sonar-web/src/main/js/app/components/LicensePromptModal.tsx index 3ed3a5f191e..cee66aca180 100644 --- a/server/sonar-web/src/main/js/app/components/LicensePromptModal.tsx +++ b/server/sonar-web/src/main/js/app/components/LicensePromptModal.tsx @@ -17,11 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { Modal } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import Link from '../../components/common/Link'; -import Modal from '../../components/controls/Modal'; -import { ResetButtonLink } from '../../components/controls/buttons'; import { translate } from '../../helpers/l10n'; interface Props { @@ -29,13 +29,9 @@ interface Props { } export default function LicensePromptModal({ onClose }: Readonly<Props>) { - const header = translate('license.prompt.title'); return ( - <Modal contentLabel={header} onRequestClose={onClose}> - <header className="modal-head"> - <h2>{header}</h2> - </header> - <div className="modal-body"> + <Modal + body={ <FormattedMessage defaultMessage={translate('license.prompt.description')} id="license.prompt.description" @@ -47,10 +43,10 @@ export default function LicensePromptModal({ onClose }: Readonly<Props>) { ), }} /> - </div> - <footer className="modal-foot"> - <ResetButtonLink onClick={onClose}>{translate('cancel')}</ResetButtonLink> - </footer> - </Modal> + } + headerTitle={translate('license.prompt.title')} + onClose={onClose} + secondaryButtonLabel={translate('cancel')} + /> ); } diff --git a/server/sonar-web/src/main/js/app/components/NonAdminPagesContainer.tsx b/server/sonar-web/src/main/js/app/components/NonAdminPagesContainer.tsx index e7dad14f203..6053ebd3de9 100644 --- a/server/sonar-web/src/main/js/app/components/NonAdminPagesContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/NonAdminPagesContainer.tsx @@ -17,9 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CenteredLayout, FlagMessage } from 'design-system'; import * as React from 'react'; import { Outlet } from 'react-router-dom'; -import { Alert } from '../../components/ui/Alert'; import { translate } from '../../helpers/l10n'; import { isApplication } from '../../types/component'; import { ComponentContext } from './componentContext/ComponentContext'; @@ -34,17 +34,18 @@ export default function NonAdminPagesContainer() { */ if (component && isApplication(component.qualifier) && !component.canBrowseAllChildProjects) { return ( - <div className="page page-limited display-flex-justify-center"> - <Alert - className="it__alert-no-access-all-child-project max-width-60 huge-spacer-top" - display="block" - variant="error" - > - <p>{translate('application.cannot_access_all_child_projects1')}</p> - <br /> - <p>{translate('application.cannot_access_all_child_projects2')}</p> - </Alert> - </div> + <CenteredLayout + className="sw-py-8 sw-body-md sw-flex sw-flex-col sw-items-center" + id="code-page" + > + <FlagMessage className="it__alert-no-access-all-child-project sw-mt-10" variant="error"> + <p> + {translate('application.cannot_access_all_child_projects1')} + <br /> + {translate('application.cannot_access_all_child_projects2')} + </p> + </FlagMessage> + </CenteredLayout> ); } diff --git a/server/sonar-web/src/main/js/app/components/PluginRiskConsent.css b/server/sonar-web/src/main/js/app/components/PluginRiskConsent.css deleted file mode 100644 index 142d8bafe5f..00000000000 --- a/server/sonar-web/src/main/js/app/components/PluginRiskConsent.css +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.plugin-risk-consent-page { - padding-top: 10vh; -} - -.plugin-risk-consent-page h1 { - line-height: 1.5; - font-size: 24px; - font-weight: 300; - text-align: center; -} - -.plugin-risk-consent-content { - min-width: 500px; - width: 40%; - margin: 0 auto; -} diff --git a/server/sonar-web/src/main/js/app/components/PluginRiskConsent.tsx b/server/sonar-web/src/main/js/app/components/PluginRiskConsent.tsx index a4f0e5a3a85..8ac5fff5109 100644 --- a/server/sonar-web/src/main/js/app/components/PluginRiskConsent.tsx +++ b/server/sonar-web/src/main/js/app/components/PluginRiskConsent.tsx @@ -17,10 +17,11 @@ * 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, Card, Title } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { setSimpleSettingValue } from '../../api/settings'; -import { Button } from '../../components/controls/buttons'; import { whenLoggedIn } from '../../components/hoc/whenLoggedIn'; import { Router, withRouter } from '../../components/hoc/withRouter'; import { translate } from '../../helpers/l10n'; @@ -30,15 +31,14 @@ import { Permissions } from '../../types/permissions'; import { RiskConsent } from '../../types/plugins'; import { SettingsKey } from '../../types/settings'; import { LoggedInUser } from '../../types/users'; -import './PluginRiskConsent.css'; export interface PluginRiskConsentProps { currentUser: LoggedInUser; router: Router; } -export function PluginRiskConsent(props: PluginRiskConsentProps) { - const { router, currentUser } = props; +export function PluginRiskConsent(props: Readonly<PluginRiskConsentProps>) { + const { currentUser, router } = props; const isAdmin = hasGlobalPermission(currentUser, Permissions.Admin); @@ -67,20 +67,24 @@ export function PluginRiskConsent(props: PluginRiskConsentProps) { }; return ( - <div className="plugin-risk-consent-page"> + <> <Helmet defer={false} title={translate('plugin_risk_consent.page')} /> - <div className="plugin-risk-consent-content boxed-group"> - <div className="boxed-group-inner text-center"> - <h1 className="big-spacer-bottom">{translate('plugin_risk_consent.title')}</h1> - <p className="big big-spacer-bottom">{translate('plugin_risk_consent.description')}</p> - <p className="big huge-spacer-bottom">{translate('plugin_risk_consent.description2')}</p> - <Button className="big-spacer-bottom" onClick={acknowledgeRisk}> - {translate('plugin_risk_consent.action')} - </Button> - </div> - </div> - </div> + <Card + className="sw-body-md sw-min-w-[500px] sw-mx-auto sw-mt-[10vh] sw-w-[40%] sw-text-center" + data-testid="plugin-risk-consent-page" + > + <Title className="sw-mb-4">{translate('plugin_risk_consent.title')}</Title> + + <p className="sw-mb-4">{translate('plugin_risk_consent.description')}</p> + + <p className="sw-mb-6">{translate('plugin_risk_consent.description2')}</p> + + <ButtonPrimary className="sw-my-4" onClick={acknowledgeRisk}> + {translate('plugin_risk_consent.action')} + </ButtonPrimary> + </Card> + </> ); } diff --git a/server/sonar-web/src/main/js/app/components/SonarLintConnection.css b/server/sonar-web/src/main/js/app/components/SonarLintConnection.css deleted file mode 100644 index 26bdc7cde12..00000000000 --- a/server/sonar-web/src/main/js/app/components/SonarLintConnection.css +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.sonarlint-connection-page { - padding-top: 10vh; -} - -.sonarlint-connection-page h1 { - line-height: 1.5; - font-size: 24px; - font-weight: 300; - text-align: center; -} - -.sonarlint-connection-content { - min-width: 600px; - width: 40%; - margin: 0 auto; -} - -.sonarlint-connection-page ol { - list-style: inside decimal; -} - -.sonarlint-connection-page .field-label { - display: inline-block; - width: 150px; - color: var(--secondFontColor); - text-align: start; - flex-shrink: 0; -} - -.sonarlint-connection-page .sonarlint-token-value { - background-color: var(--codeBackground); - border: 1px solid var(--barBorderColor); - padding: calc(var(--gridSize) / 2) var(--gridSize); -} diff --git a/server/sonar-web/src/main/js/app/components/SonarLintConnection.tsx b/server/sonar-web/src/main/js/app/components/SonarLintConnection.tsx index 6b8832dc414..4f8a19c4d40 100644 --- a/server/sonar-web/src/main/js/app/components/SonarLintConnection.tsx +++ b/server/sonar-web/src/main/js/app/components/SonarLintConnection.tsx @@ -17,19 +17,27 @@ * 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, + Card, + CardSeparator, + CheckIcon, + ClipboardButton, + InputField, + Link, + ListItem, + Note, + OrderedList, + Title, +} from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { useSearchParams } from 'react-router-dom'; -import Link from '../../components/common/Link'; -import { Button } from '../../components/controls/buttons'; -import { ClipboardButton } from '../../components/controls/clipboard'; import { whenLoggedIn } from '../../components/hoc/whenLoggedIn'; -import CheckIcon from '../../components/icons/CheckIcon'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { generateSonarLintUserToken, portIsValid, sendUserToken } from '../../helpers/sonarlint'; import { NewUserToken } from '../../types/token'; import { LoggedInUser } from '../../types/users'; -import './SonarLintConnection.css'; enum Status { request, @@ -76,127 +84,98 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { }, [port, ideName, login]); return ( - <div className="sonarlint-connection-page"> - <div className="sonarlint-connection-content boxed-group"> - <div className="boxed-group-inner text-center"> - {status === Status.request && ( - <> - <h1 className="big-spacer-top big-spacer-bottom"> - {translate('sonarlint-connection.request.title')} - </h1> - <img - alt="" - aria-hidden - className="big-spacer-top big-spacer-bottom" - src="/images/SonarLint-connection-request.png" - /> - <p className="big big-spacer-top big-spacer-bottom"> - {translateWithParameters('sonarlint-connection.request.description', ideName)} - </p> - <p className="big huge-spacer-bottom"> - {translate('sonarlint-connection.request.description2')} - </p> - - <Button className="big-spacer-bottom" onClick={authorize}> - <CheckIcon className="spacer-right" /> - {translate('sonarlint-connection.request.action')} - </Button> - </> - )} - - {status === Status.tokenError && ( - <> - <img - alt="" - aria-hidden - className="big-spacer-top big-spacer-bottom padded-top" - src="/images/cross.svg" - /> - <h1 className="big-spacer-bottom"> - {translate('sonarlint-connection.token-error.title')} - </h1> - <p className="big big-spacer-top big-spacer-bottom"> - {translate('sonarlint-connection.token-error.description')} - </p> - <p className="big huge-spacer-bottom"> - <FormattedMessage - id="sonarlint-connection.token-error.description2" - defaultMessage={translate('sonarlint-connection.token-error.description2')} - values={{ - link: ( - <Link to="/account/security"> - {translate('sonarlint-connection.token-error.description2.link')} - </Link> - ), - }} - /> - </p> - </> - )} - - {status === Status.tokenCreated && newToken && ( - <> - <img - alt="" - aria-hidden - className="big-spacer-top big-spacer-bottom padded-top" - src="/images/check.svg" - /> - <h1 className="big-spacer-bottom"> - {translate('sonarlint-connection.connection-error.title')} - </h1> - <p className="big big-spacer-top big-spacer-bottom"> - {translate('sonarlint-connection.connection-error.description')} - </p> - <div className="display-flex-center"> - <span className="field-label"> - {translate('sonarlint-connection.connection-error.token-name')} - </span> - {newToken.name} - </div> - <hr /> - <div className="display-flex-center"> - <span className="field-label"> - {translate('sonarlint-connection.connection-error.token-value')} - </span> - <span className="sonarlint-token-value">{newToken.token}</span> - <ClipboardButton className="big-spacer-left" copyValue={newToken.token} /> - </div> - <div className="big huge-spacer-top"> - <strong>{translate('sonarlint-connection.connection-error.next-steps')}</strong> - </div> - <ol className="big big-spacer-top big-spacer-bottom"> - <li>{translate('sonarlint-connection.connection-error.step1')}</li> - <li>{translate('sonarlint-connection.connection-error.step2')}</li> - </ol> - </> - )} - - {status === Status.tokenSent && newToken && ( - <> - <h1 className="big-spacer-top big-spacer-bottom"> - {translate('sonarlint-connection.success.title')} - </h1> - <img - alt="" - aria-hidden - className="big-spacer-bottom" - src="/images/SonarLint-connection-ok.png" - /> - <p className="big big-spacer-top big-spacer-bottom"> - {translateWithParameters('sonarlint-connection.success.description', newToken.name)} - </p> - <div className="big huge-spacer-top"> - <strong>{translate('sonarlint-connection.success.last-step')}</strong> - </div> - <div className="big big-spacer-top big-spacer-bottom"> - {translate('sonarlint-connection.success.step')} - </div> - </> - )} - </div> - </div> - </div> + <Card className="sw-mt-[10vh] sw-mx-auto sw-w-[650px] sw-text-center"> + {status === Status.request && ( + <> + <Title>{translate('sonarlint-connection.request.title')}</Title> + <img + alt="" + className="sw-my-4" + role="presentation" + src="/images/SonarLint-connection-request.png" + /> + <p className="sw-my-4"> + {translateWithParameters('sonarlint-connection.request.description', ideName)} + </p> + <p className="sw-mb-10">{translate('sonarlint-connection.request.description2')}</p> + + <ButtonPrimary icon={<CheckIcon fill="currentColor" />} onClick={authorize}> + {translate('sonarlint-connection.request.action')} + </ButtonPrimary> + </> + )} + + {status === Status.tokenError && ( + <> + <img alt="" className="sw-my-4 sw-pt-2" role="presentation" src="/images/cross.svg" /> + <Title>{translate('sonarlint-connection.token-error.title')}</Title> + <p className="sw-my-4">{translate('sonarlint-connection.token-error.description')}</p> + <p className="sw-mb-4"> + <FormattedMessage + id="sonarlint-connection.token-error.description2" + defaultMessage={translate('sonarlint-connection.token-error.description2')} + values={{ + link: ( + <Link to="/account/security"> + {translate('sonarlint-connection.token-error.description2.link')} + </Link> + ), + }} + /> + </p> + </> + )} + + {status === Status.tokenCreated && newToken && ( + <> + <img alt="" className="sw-my-4 sw-pt-2" role="presentation" src="/images/check.svg" /> + <Title>{translate('sonarlint-connection.connection-error.title')}</Title> + <p className="sw-my-6"> + {translate('sonarlint-connection.connection-error.description')} + </p> + <div className="sw-flex sw-items-center"> + <Note className="sw-w-abs-150 sw-text-start"> + {translate('sonarlint-connection.connection-error.token-name')} + </Note> + {newToken.name} + </div> + <CardSeparator className="sw-my-3" /> + <div className="sw-flex sw-items-center"> + <Note className="sw-min-w-abs-150 sw-text-start"> + {translate('sonarlint-connection.connection-error.token-value')} + </Note> + <InputField className="sw-cursor-text" disabled size="full" value={newToken.token} /> + <ClipboardButton className="sw-ml-2" copyValue={newToken.token} /> + </div> + <div className="sw-mt-10"> + <strong>{translate('sonarlint-connection.connection-error.next-steps')}</strong> + </div> + <OrderedList className="sw-list-inside sw-mb-4"> + <ListItem>{translate('sonarlint-connection.connection-error.step1')}</ListItem> + <ListItem>{translate('sonarlint-connection.connection-error.step2')}</ListItem> + </OrderedList> + </> + )} + + {status === Status.tokenSent && newToken && ( + <> + <Title>{translate('sonarlint-connection.success.title')}</Title> + <img + alt="" + className="sw-mb-4" + role="presentation" + src="/images/SonarLint-connection-ok.png" + /> + <p className="sw-my-4"> + {translateWithParameters('sonarlint-connection.success.description', newToken.name)} + </p> + <div className="sw-mt-10"> + <strong>{translate('sonarlint-connection.success.last-step')}</strong> + </div> + <div className="sw-my-4">{translate('sonarlint-connection.success.step')}</div> + </> + )} + </Card> ); } diff --git a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.css b/server/sonar-web/src/main/js/app/components/SystemAnnouncement.css deleted file mode 100644 index aec6caf4da1..00000000000 --- a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.system-announcement-wrapper { - min-height: 34px; -} - -.system-announcement-banner { - box-sizing: border-box; - width: 100%; - z-index: var(--globalBannerZIndex); - margin-bottom: 0% !important; -} diff --git a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx b/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx index c80e8c966ad..b64f10b404b 100644 --- a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx +++ b/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx @@ -17,14 +17,13 @@ * 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 styled from '@emotion/styled'; +import { FlagWarningIcon, themeBorder, themeColor } from 'design-system'; import { keyBy, throttle } from 'lodash'; import * as React from 'react'; import { getValues } from '../../api/settings'; -import { Alert } from '../../components/ui/Alert'; import { Feature } from '../../types/features'; import { GlobalSettingKeys, SettingValue } from '../../types/settings'; -import './SystemAnnouncement.css'; import withAvailableFeatures, { WithAvailableFeaturesProps, } from './available-features/withAvailableFeatures'; @@ -78,20 +77,28 @@ export class SystemAnnouncement extends React.PureComponent<WithAvailableFeature const { displayMessage, message } = this.state; return ( - <div className={classNames({ 'system-announcement-wrapper': displayMessage && message })}> - <Alert - className="system-announcement-banner" - title={message} - display="banner" - variant="warning" - aria-live="assertive" - role="alert" - > - {displayMessage && message} - </Alert> - </div> + <StyledBanner + className="sw-py-3 sw-px-4 sw-gap-3" + style={!(displayMessage && message.length > 0) ? { display: 'none' } : {}} + title={message} + aria-live="assertive" + role="alert" + > + <FlagWarningIcon /> + <span>{displayMessage && message}</span> + </StyledBanner> ); } } export default withAvailableFeatures(SystemAnnouncement); + +const StyledBanner = styled.div` + display: flex; + align-items: center; + box-sizing: border-box; + width: 100%; + + background-color: ${themeColor('warningBackground')}; + border-bottom: ${themeBorder('default', 'warningBorder')}; +`; diff --git a/server/sonar-web/src/main/js/app/components/__tests__/NonAdminPagesContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/NonAdminPagesContainer-test.tsx index 20e7da86992..01f497a8d08 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/NonAdminPagesContainer-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/NonAdminPagesContainer-test.tsx @@ -23,8 +23,8 @@ import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { mockComponent } from '../../../helpers/mocks/component'; import { ComponentContextShape, ComponentQualifier } from '../../../types/component'; import { Component } from '../../../types/types'; -import { ComponentContext } from '../componentContext/ComponentContext'; import NonAdminPagesContainer from '../NonAdminPagesContainer'; +import { ComponentContext } from '../componentContext/ComponentContext'; function Child() { return <div>Test Child</div>; @@ -34,7 +34,7 @@ it('should render correctly for an user that does not have access to all childre renderNonAdminPagesContainer( mockComponent({ qualifier: ComponentQualifier.Application, canBrowseAllChildProjects: false }), ); - expect(screen.getByText('application.cannot_access_all_child_projects1')).toBeInTheDocument(); + expect(screen.getByText(/^application.cannot_access_all_child_projects1/)).toBeInTheDocument(); }); it('should render correctly', () => { diff --git a/server/sonar-web/src/main/js/app/components/__tests__/SonarLintConnection-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/SonarLintConnection-test.tsx index bf9552c0d2a..1914cdf185f 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/SonarLintConnection-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/SonarLintConnection-test.tsx @@ -112,7 +112,7 @@ it('should handle connection errors', async () => { ).toBeInTheDocument(); const tokenValue = tokenMock.getLastToken()?.token ?? ''; - expect(await screen.findByText(tokenValue)).toBeInTheDocument(); + expect(await screen.findByRole('textbox')).toHaveValue(tokenValue); }); it('should require authentication if user is not logged in', () => { diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx index 3d036ba3d86..1b79c3fad1c 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx @@ -17,6 +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 { withTheme } from '@emotion/react'; import { QueryClient } from '@tanstack/react-query'; import { Theme } from 'design-system'; @@ -35,30 +36,29 @@ import { AppState } from '../../../types/appstate'; import { ExtensionStartMethod } from '../../../types/extension'; import { Dict, Extension as TypeExtension } from '../../../types/types'; import { CurrentUser, HomePage } from '../../../types/users'; -import * as theme from '../../theme'; import withAppStateContext from '../app-state/withAppStateContext'; import withCurrentUserContext from '../current-user/withCurrentUserContext'; export interface ExtensionProps extends WrappedComponentProps { - theme: Theme; appState: AppState; currentUser: CurrentUser; extension: TypeExtension; location: Location; - options?: Dict<any>; - router: Router; + options?: Dict<unknown>; queryClient: QueryClient; + router: Router; + theme: Theme; updateCurrentUserHomepage: (homepage: HomePage) => void; } interface State { - extensionElement?: React.ReactElement<any>; + extensionElement?: React.ReactElement<unknown>; } class Extension extends React.PureComponent<ExtensionProps, State> { container?: HTMLElement | null; - stop?: Function; state: State = {}; + stop?: Function; componentDidMount() { this.startExtension(); @@ -78,23 +78,22 @@ class Extension extends React.PureComponent<ExtensionProps, State> { } handleStart = (start: ExtensionStartMethod) => { - const { theme: dsTheme, queryClient } = this.props; + const { theme, queryClient } = this.props; + const result = start({ appState: this.props.appState, - el: this.container, + baseUrl: getBaseUrl(), currentUser: this.props.currentUser, + el: this.container, intl: this.props.intl, + l10nBundle: getCurrentL10nBundle(), location: this.props.location, + queryClient, router: this.props.router, theme, - // New theme from design-system, we should drop old theme once the migration to miui is done - dsTheme, - baseUrl: getBaseUrl(), - l10nBundle: getCurrentL10nBundle(), // See SONAR-16207 and core-extension-enterprise-server/src/main/js/portfolios/components/Header.tsx // for more information on why we're passing this as a prop to an extension. updateCurrentUserHomepage: this.props.updateCurrentUserHomepage, - queryClient, ...this.props.options, }); diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.css b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.css deleted file mode 100644 index 187579b9109..00000000000 --- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.css +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.indexation-notification-wrapper { - height: 34px; -} - -.indexation-notification-banner { - width: 100%; - z-index: var(--globalBannerZIndex); - margin-bottom: 0 !important; -} diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx index bfbeafe96eb..665c9f333e9 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx +++ b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx @@ -26,7 +26,6 @@ import { IndexationNotificationType } from '../../../types/indexation'; import { Permissions } from '../../../types/permissions'; import { CurrentUser, isLoggedIn } from '../../../types/users'; import withCurrentUserContext from '../current-user/withCurrentUserContext'; -import './IndexationNotification.css'; import IndexationNotificationHelper from './IndexationNotificationHelper'; import IndexationNotificationRenderer from './IndexationNotificationRenderer'; diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx index bc46d8afb4d..5bb714c9697 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx +++ b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx @@ -19,12 +19,20 @@ */ /* eslint-disable react/no-unused-prop-types */ -import classNames from 'classnames'; +import styled from '@emotion/styled'; +import { + FlagErrorIcon, + FlagSuccessIcon, + FlagWarningIcon, + Link, + Spinner, + ThemeColors, + themeBorder, + themeColor, +} from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; -import DocLink from '../../../components/common/DocLink'; -import Link from '../../../components/common/Link'; -import { Alert, AlertProps } from '../../../components/ui/Alert'; +import DocumentationLink from '../../../components/common/DocumentationLink'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { queryToSearch } from '../../../helpers/urls'; import { IndexationNotificationType } from '../../../types/indexation'; @@ -36,26 +44,41 @@ export interface IndexationNotificationRendererProps { type?: IndexationNotificationType; } -const NOTIFICATION_VARIANTS: { [key in IndexationNotificationType]: AlertProps['variant'] } = { - [IndexationNotificationType.InProgress]: 'warning', - [IndexationNotificationType.InProgressWithFailure]: 'error', - [IndexationNotificationType.Completed]: 'success', - [IndexationNotificationType.CompletedWithFailure]: 'error', +const NOTIFICATION_COLORS: { + [key in IndexationNotificationType]: { background: ThemeColors; border: ThemeColors }; +} = { + [IndexationNotificationType.InProgress]: { + background: 'warningBackground', + border: 'warningBorder', + }, + [IndexationNotificationType.InProgressWithFailure]: { + background: 'errorBackground', + border: 'errorBorder', + }, + [IndexationNotificationType.Completed]: { + background: 'successBackground', + border: 'successBorder', + }, + [IndexationNotificationType.CompletedWithFailure]: { + background: 'errorBackground', + border: 'errorBorder', + }, }; export default function IndexationNotificationRenderer(props: IndexationNotificationRendererProps) { const { completedCount, total, type } = props; return ( - <div className={classNames({ 'indexation-notification-wrapper': type })}> - <Alert - className="indexation-notification-banner" - display="banner" - variant={type ? NOTIFICATION_VARIANTS[type] : 'success'} + <div className={type === undefined ? 'sw-hidden' : ''}> + <StyledBanner + className="sw-body-sm sw-py-3 sw-px-4 sw-gap-4" + type={type ?? IndexationNotificationType.Completed} aria-live="assertive" + role="alert" > {type !== undefined && ( - <div className="display-flex-center"> + <> + {renderIcon(type)} {type === IndexationNotificationType.Completed && renderCompletedBanner()} {type === IndexationNotificationType.CompletedWithFailure && @@ -66,20 +89,34 @@ export default function IndexationNotificationRenderer(props: IndexationNotifica {type === IndexationNotificationType.InProgressWithFailure && renderInProgressWithFailureBanner(completedCount as number, total as number)} - </div> + </> )} - </Alert> + </StyledBanner> </div> ); } +function renderIcon(type: IndexationNotificationType) { + switch (type) { + case IndexationNotificationType.Completed: + return <FlagSuccessIcon />; + case IndexationNotificationType.CompletedWithFailure: + case IndexationNotificationType.InProgressWithFailure: + return <FlagErrorIcon />; + case IndexationNotificationType.InProgress: + return <FlagWarningIcon />; + default: + return null; + } +} + function renderCompletedBanner() { - return <span className="spacer-right">{translate('indexation.completed')}</span>; + return <span>{translate('indexation.completed')}</span>; } function renderCompletedWithFailureBanner() { return ( - <span className="spacer-right"> + <span> <FormattedMessage defaultMessage={translate('indexation.completed_with_error')} id="indexation.completed_with_error" @@ -97,7 +134,7 @@ function renderCompletedWithFailureBanner() { function renderInProgressBanner(completedCount: number, total: number) { return ( <> - <span className="spacer-right"> + <span> <FormattedMessage id="indexation.in_progress" />{' '} <FormattedMessage id="indexation.features_partly_available" @@ -106,9 +143,9 @@ function renderInProgressBanner(completedCount: number, total: number) { }} /> </span> - <i className="spinner spacer-right" /> - <span className="spacer-right"> + <span className="sw-flex sw-items-center"> + <Spinner className="sw-mr-1 -sw-mb-1/2" /> {translateWithParameters( 'indexation.progression', completedCount.toString(), @@ -116,7 +153,7 @@ function renderInProgressBanner(completedCount: number, total: number) { )} </span> - <span className="spacer-right"> + <span> <FormattedMessage id="indexation.admin_link" defaultMessage={translate('indexation.admin_link')} @@ -132,7 +169,7 @@ function renderInProgressBanner(completedCount: number, total: number) { function renderInProgressWithFailureBanner(completedCount: number, total: number) { return ( <> - <span className="spacer-right"> + <span> <FormattedMessage id="indexation.in_progress" />{' '} <FormattedMessage id="indexation.features_partly_available" @@ -141,17 +178,15 @@ function renderInProgressWithFailureBanner(completedCount: number, total: number }} /> </span> - <i className="spinner spacer-right" /> - <span className="spacer-right"> + <span className="sw-flex sw-items-center"> + <Spinner className="sw-mr-1 -sw-mb-1/2" /> <FormattedMessage + tagName="span" id="indexation.progression_with_error" - defaultMessage={translateWithParameters( - 'indexation.progression_with_error', - completedCount.toString(), - total.toString(), - )} values={{ + count: completedCount, + total, link: renderBackgroundTasksPageLink( true, translate('indexation.progression_with_error.link'), @@ -181,8 +216,18 @@ function renderBackgroundTasksPageLink(hasError: boolean, text: string) { function renderIndexationDocPageLink() { return ( - <DocLink to="/instance-administration/reindexing/"> + <DocumentationLink className="sw-whitespace-nowrap" to="/instance-administration/reindexing/"> <FormattedMessage id="indexation.features_partly_available.link" /> - </DocLink> + </DocumentationLink> ); } + +const StyledBanner = styled.div<{ type: IndexationNotificationType }>` + display: flex; + align-items: center; + box-sizing: border-box; + width: 100%; + + background-color: ${({ type }) => themeColor(NOTIFICATION_COLORS[type].background)}; + border-bottom: ${({ type }) => themeBorder('default', NOTIFICATION_COLORS[type].border)}; +`; diff --git a/server/sonar-web/src/main/js/app/components/indexation/PageUnavailableDueToIndexation.tsx b/server/sonar-web/src/main/js/app/components/indexation/PageUnavailableDueToIndexation.tsx index 03444d3b0cc..c31b3f3d2f4 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/PageUnavailableDueToIndexation.tsx +++ b/server/sonar-web/src/main/js/app/components/indexation/PageUnavailableDueToIndexation.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 { FlagMessage, Link } from 'design-system'; +import { CenteredLayout, FlagMessage, Link } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import withIndexationContext, { @@ -37,8 +37,8 @@ export class PageUnavailableDueToIndexation extends React.PureComponent<WithInde render() { return ( - <div className="page-wrapper-simple"> - <FlagMessage className="sw-m-10" variant="info"> + <CenteredLayout className="sw-flex sw-justify-around"> + <FlagMessage className="sw-mt-32" variant="info"> <span className="sw-w-[290px]"> {translate('indexation.page_unavailable.description')} <span className="sw-ml-1"> @@ -58,7 +58,7 @@ export class PageUnavailableDueToIndexation extends React.PureComponent<WithInde </span> </span> </FlagMessage> - </div> + </CenteredLayout> ); } } diff --git a/server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx b/server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx index 71426cd607f..d387a7e3554 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx +++ b/server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx @@ -103,7 +103,7 @@ describe('Completed banner', () => { />, ); - expect(byText('indexation.progression_with_error').get()).toBeInTheDocument(); + expect(byText(/^indexation\.progression_with_error\.link/).get()).toBeInTheDocument(); rerender( <IndexationNotification diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavProjectBindingErrorNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavProjectBindingErrorNotif.tsx index 9514729d9e4..803a51eaddf 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavProjectBindingErrorNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavProjectBindingErrorNotif.tsx @@ -17,11 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import styled from '@emotion/styled'; +import { FlagWarningIcon, Link, themeBorder, themeColor } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { PULL_REQUEST_DECORATION_BINDING_CATEGORY } from '../../../../apps/settings/constants'; -import Link from '../../../../components/common/Link'; -import { Alert } from '../../../../components/ui/Alert'; import { translate } from '../../../../helpers/l10n'; import { getProjectSettingsUrl } from '../../../../helpers/urls'; import { Component } from '../../../../types/types'; @@ -47,12 +47,20 @@ export default function ComponentNavProjectBindingErrorNotif( } return ( - <Alert display="banner" variant="warning"> - <FormattedMessage - defaultMessage={translate('component_navigation.pr_deco.error_detected_X')} - id="component_navigation.pr_deco.error_detected_X" - values={{ action }} - /> - </Alert> + <StyledBanner className="sw-body-sm sw-py-3 sw-px-4 sw-gap-4"> + <FlagWarningIcon /> + <FormattedMessage id="component_navigation.pr_deco.error_detected_X" values={{ action }} /> + </StyledBanner> ); } + +const StyledBanner = styled.div` + display: flex; + align-items: center; + box-sizing: border-box; + width: 100%; + + background-color: ${themeColor('warningBackground')}; + border-top: ${themeBorder('default', 'warningBorder')}; + border-bottom: ${themeBorder('default', 'warningBorder')}; +`; diff --git a/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx index 35ae56d1015..cd423d7a912 100644 --- a/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx +++ b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx @@ -45,19 +45,17 @@ export function PromotionNotification(props: CurrentUserContextInterface) { }; return ( - <div className="toaster display-flex-center big-padded-left big-padded-right"> - <div className="toaster-icon spacer-right"> + <div className="toaster sw-flex sw-items-center sw-px-4"> + <div className="sw-mr-2"> <img alt="SonarQube + SonarLint" height={80} src={`${getBaseUrl()}/images/sq-sl.svg`} /> </div> - <div className="toaster-content flex-1 padded-left padded-right big-padded-top big-padded-bottom"> - <span className="toaster-title text-bold medium"> - {translate('promotion.sonarlint.title')} - </span> - <p className="spacer-top">{translate('promotion.sonarlint.content')}</p> + <div className="toaster-content sw-flex-1 sw-px-2 sw-py-4"> + <span className="sw-body-sm-highlight">{translate('promotion.sonarlint.title')}</span> + <p className="sw-mt-2">{translate('promotion.sonarlint.content')}</p> </div> <div className="toaster-actions spacer-left padded-left display-flex-column display-flex-center"> <a - className="button button-primary big-spacer-bottom" + className="button button-primary sw-mb-4" href="https://www.sonarsource.com/products/sonarlint/?referrer=sonarqube-welcome" rel="noreferrer" onClick={onClick} diff --git a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css deleted file mode 100644 index baff8ae2ecf..00000000000 --- a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.promote-update-notification.dismissable-alert-wrapper { - height: 42px; -} - -.promote-update-notification .dismissable-alert-banner { - margin-bottom: 0 !important; - width: 100%; - z-index: var(--globalBannerZIndex); -} diff --git a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx index 04cc3b0c81a..4ed1ad44c54 100644 --- a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx +++ b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx @@ -17,11 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { Variant } from 'design-system'; +import { Banner, Variant } from 'design-system'; import { groupBy, isEmpty, mapValues } from 'lodash'; import * as React from 'react'; import { getSystemUpgrades } from '../../../api/system'; -import { Alert } from '../../../components/ui/Alert'; import DismissableAlert from '../../../components/ui/DismissableAlert'; import SystemUpgradeButton from '../../../components/upgrade/SystemUpgradeButton'; import { UpdateUseCase, sortUpgrades } from '../../../components/upgrade/utils'; @@ -34,7 +33,6 @@ import { Dict } from '../../../types/types'; import { CurrentUser, isLoggedIn } from '../../../types/users'; import withAppStateContext from '../app-state/withAppStateContext'; import withCurrentUserContext from '../current-user/withCurrentUserContext'; -import './UpdateNotification.css'; const MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION = 6; @@ -223,7 +221,7 @@ export class UpdateNotification extends React.PureComponent<Props, State> { <DismissableAlert alertKey={dismissKey} variant={MAP_VARIANT[useCase]} - className={`promote-update-notification it__upgrade-prompt-${useCase}`} + className={`it__promote-update-notification it__upgrade-prompt-${useCase}`} > {translate('admin_notification.update', useCase)} <SystemUpgradeButton @@ -233,14 +231,14 @@ export class UpdateNotification extends React.PureComponent<Props, State> { /> </DismissableAlert> ) : ( - <Alert variant={MAP_VARIANT[useCase]} className={`it__upgrade-prompt-${useCase}`}> + <Banner variant={MAP_VARIANT[useCase]} className={`it__upgrade-prompt-${useCase}`}> {translate('admin_notification.update', useCase)} <SystemUpgradeButton systemUpgrades={systemUpgrades} updateUseCase={useCase} latestLTS={latestLTS} /> - </Alert> + </Banner> ); } } diff --git a/server/sonar-web/src/main/js/app/styles/GlobalStyles.tsx b/server/sonar-web/src/main/js/app/styles/GlobalStyles.tsx new file mode 100644 index 00000000000..8db4ac406d6 --- /dev/null +++ b/server/sonar-web/src/main/js/app/styles/GlobalStyles.tsx @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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 { Global, css, useTheme } from '@emotion/react'; +import { themeColor } from 'design-system/lib'; +import React from 'react'; +import twDefaultTheme from 'tailwindcss/defaultTheme'; + +export function GlobalStyles() { + const theme = useTheme(); + + return ( + <Global + styles={css` + body { + font-family: Inter, ${twDefaultTheme.fontFamily.sans.join(', ')}; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 400; + + color: ${themeColor('pageContent')({ theme })}; + background-color: ${themeColor('backgroundPrimary')({ theme })}; + } + + a { + outline: none; + text-decoration: none; + color: ${themeColor('pageContent')({ theme })}; + } + + ol, + ul { + padding-left: 0; + list-style: none; + } + `} + /> + ); +} diff --git a/server/sonar-web/src/main/js/app/styles/components/badges.css b/server/sonar-web/src/main/js/app/styles/components/badges.css deleted file mode 100644 index d1e3398155e..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/badges.css +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.badge { - display: inline-block; - padding: 4px; - background-color: var(--barBorderColor); - border-radius: 3px; - font-size: var(--smallFontSize); - font-weight: 600; - color: var(--baseFontColor); - text-transform: uppercase; - white-space: nowrap; - line-height: 8px; -} -.badge:empty { - display: none; -} - -a.badge:hover, -a.badge:focus, -a.badge:active { - text-decoration: underline; -} -a.badge { - border-bottom: none; -} - -.list-group-item-heading > .badge { - float: right; - margin: 3px; -} -.list-group-item-heading > .badge + .badge { - margin-right: 5px; -} - -.badge-info { - background-color: var(--alertBackgroundInfo); - color: var(--alertTextInfo); -} - -.badge-success { - background-color: var(--alertBackgroundSuccess); - color: var(--alertTextSuccess); -} - -.badge-warning { - background-color: var(--alertBackgroundWarning); - color: var(--alertTextWarning); -} - -.badge-error { - background-color: var(--alertBackgroundError); - color: var(--alertTextError); -} - -.counter-badge { - color: var(--badgeBlueColor); - background-color: var(--badgeBlueBackground); - font-size: var(--smallFontSize); - padding: 0.3em 0.8em; - border-radius: 1em; -} - -.counter-badge:empty { - display: none; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/boxed-group.css b/server/sonar-web/src/main/js/app/styles/components/boxed-group.css index 687f776c397..02b5cb0f788 100644 --- a/server/sonar-web/src/main/js/app/styles/components/boxed-group.css +++ b/server/sonar-web/src/main/js/app/styles/components/boxed-group.css @@ -51,26 +51,6 @@ margin: calc(2 * var(--gridSize)) -20px; } -.boxed-group-header { - position: relative; - z-index: 10; - padding: calc(2 * var(--gridSize)) 20px 0; -} - -.boxed-group-header > h2 { - display: inline-block; - vertical-align: middle; - line-height: var(--controlHeight); -} - -.boxed-group-actions { - position: relative; - z-index: 12; - float: right; - margin-top: calc(2 * var(--gridSize)); - margin-right: 20px; -} - .boxed-group-inner { padding: calc(2 * var(--gridSize)) 20px; } @@ -101,15 +81,6 @@ border-color: var(--info400); } -.boxed-group-accordion .boxed-group-header { - cursor: pointer; - padding-bottom: calc(2 * var(--gridSize)); -} - -.boxed-group-accordion.not-clickable .boxed-group-header { - cursor: default; -} - .boxed-group-accordion.not-clickable .boxed-group-accordion-title > svg { display: none; } diff --git a/server/sonar-web/src/main/js/app/styles/components/columns.css b/server/sonar-web/src/main/js/app/styles/components/columns.css deleted file mode 100644 index ed27c68728e..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/columns.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.columns { - margin-left: -10px; - margin-right: -10px; - overflow: hidden; -} - -.columns:before, -.columns:after { - display: table; - content: ''; - line-height: 0; -} - -.columns:after { - clear: both; -} - -.column-half { - float: left; - width: 50%; - padding: 0 10px; - box-sizing: border-box; -} - -.column-half.column-one { - margin: 0 25%; -} - -.flex-columns { - display: flex; -} - -.flex-column + .flex-column { - margin-left: 20px; -} - -.flex-column-full { - width: 100%; -} - -.flex-column-half { - width: 50%; -} - -.flex-column-third { - width: calc(100% / 3); -} diff --git a/server/sonar-web/src/main/js/app/styles/components/component-name.css b/server/sonar-web/src/main/js/app/styles/components/component-name.css deleted file mode 100644 index 78658b1d06b..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/component-name.css +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.component-name { - line-height: 16px; - font-size: var(--smallFontSize); -} - -.component-name:before, -.component-name:after { - display: table; - content: ''; - line-height: 0; -} - -.component-name:after { - clear: both; -} - -.component-name-parent { - float: left; - margin-right: 20px; -} - -.component-name-parent:last-child { - margin-right: 0; -} - -.component-name-path { - float: left; - clear: left; -} - -.component-name-parent + .component-name-path { - margin-top: 4px; -} - -.component-name-favorite { - margin-left: 4px; - padding: 0; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/dropdowns.css b/server/sonar-web/src/main/js/app/styles/components/dropdowns.css deleted file mode 100644 index 0bf8a21f41d..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/dropdowns.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.dropdown { - position: relative; - display: inline-block; - vertical-align: middle; -} - -.dropdown-bottom-hint { - line-height: 16px; - margin-bottom: -5px; - padding: 5px 10px; - border-top: 1px solid var(--barBorderColor); - background-color: var(--barBackgroundColor); - color: var(--secondFontColor); - font-size: 11px; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/global-loading.css b/server/sonar-web/src/main/js/app/styles/components/global-loading.css index 838578b6bdc..5aa658b9656 100644 --- a/server/sonar-web/src/main/js/app/styles/components/global-loading.css +++ b/server/sonar-web/src/main/js/app/styles/components/global-loading.css @@ -21,12 +21,42 @@ width: 300px; margin: 200px auto 0; white-space: nowrap; + font-family: + Inter, + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + 'Helvetica Neue', + Arial, + 'Noto Sans', + sans-serif, + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + 'Noto Color Emoji'; + color: rgb(62, 67, 87); } -.global-loading .global-loading-spinner { +.global-loading-spinner { + display: inline-block; + box-sizing: border-box; vertical-align: middle; width: 80px; height: 80px; + border: 2px solid transparent; + border-radius: 625rem; + 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; + mask: + linear-gradient(white 0 0) padding-box, + linear-gradient(white 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + animation: global-loading-spin 1s infinite linear; } .global-loading-text { @@ -36,3 +66,12 @@ font-size: 36px; font-weight: 300; } + +@keyframes global-loading-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(-360deg); + } +} diff --git a/server/sonar-web/src/main/js/app/styles/components/issues.css b/server/sonar-web/src/main/js/app/styles/components/issues.css deleted file mode 100644 index 0d066e7e6c6..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/issues.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.issue-list { - margin: 10px 0; -} - -.issue-list, -.issue { - max-width: 980px; -} - -.issue-filters-list { - /* - * On Firefox on Windows, the scrollbar hides the sidebar's content. - * Using 'scrollbar-gutter:stable' is a workaround to ensure consistency with other browsers. - * @see https://bugzilla.mozilla.org/show_bug.cgi?id=764076 - * @see https://discuss.sonarsource.com/t/unnecessary-horizontal-scrollbar-on-issues-page/14889/4 - */ - scrollbar-gutter: stable; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/list-groups.css b/server/sonar-web/src/main/js/app/styles/components/list-groups.css deleted file mode 100644 index c6774b23de2..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/list-groups.css +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.list-group { - margin-bottom: 20px; - padding-left: 0; -} - -.list-group-item, -button.list-group-item { - position: relative; - z-index: var(--normalZIndex); - display: block; - margin-bottom: -1px; - padding: 5px 10px; - border: 1px solid transparent; - width: 100%; - box-sizing: border-box; - text-align: left; -} - -.list-group-item.depth-1 { - padding-left: 31px; -} - -.list-group-item.depth-2 { - padding-left: 51px; -} - -.list-group-item.depth-3 { - padding-left: 71px; -} - -.list-group-item:last-child { - margin-bottom: 0; -} - -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: var(--aboveNormalZIndex); - border-color: var(--blue) !important; - background-color: var(--lightBlue); -} - -.list-group-item:hover { - z-index: var(--aboveNormalZIndex); - border-color: var(--blue) !important; -} - -.list-group-item + .list-group-item { - border-top-color: var(--barBorderColor); -} - -a.list-group-item { - color: var(--baseFontColor); - transition: none; -} - -.list-group-item-heading { - margin-top: 5px; - margin-bottom: 5px; - text-overflow: ellipsis; - overflow: hidden; -} - -.list-group-item-heading:after { - content: ''; - display: table; - clear: both; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/menu.css b/server/sonar-web/src/main/js/app/styles/components/menu.css deleted file mode 100644 index 492d6283643..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/menu.css +++ /dev/null @@ -1,188 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.menu { - min-width: 160px; - padding: 5px 0; - list-style: none; - font-size: var(--smallFontSize); - text-align: left; - background-color: #fff; - background-clip: padding-box; -} - -.menu:not(:last-of-type) { - padding-bottom: 12px; -} - -.menu + .menu, -.menu + .menu-header { - border-top: 1px solid var(--barBorderColor); -} - -.menu.is-container { - padding: 5px; -} - -.menu-item, -.menu > li > a, -.menu > li > button, -.menu > li > span { - display: block; - padding: 4px 16px; - line-height: 14px; - clear: both; - font-weight: normal; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.menu > li > a, -.menu > li > button { - color: var(--neutral800); - border-width: 0 0 0 2px; - border-style: solid; - border-color: transparent; - transition: none; -} - -.menu > li > button { - text-align: left; - width: 100%; -} - -.menu > li > a.disabled { - color: var(--disableGrayText) !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -.menu > li > a.text-muted { - color: var(--secondFontColor); -} - -.menu > li > a:hover, -.menu > li > a.hover, -.menu > li > button:hover { - background-color: var(--neutral50); - border-left-color: var(--blacka60); -} - -.menu > li > a.active, -.menu > li > button.active { - background-color: var(--info50); - border-left-color: var(--info500); -} - -.menu > li > a.active:hover, -.menu > li > a.active.hover, -.menu > li > button.active:hover { - background-color: var(--info100); -} - -.menu.menu-vertically-limited { - max-height: 300px; - overflow-y: auto; -} - -.menu .divider { - height: 1px; - margin: 6px 0; - overflow: hidden; - background-color: var(--barBorderColor); -} - -.menu-vertically-limited.with-top-separator { - border-top: 1px solid #e6e6e6; -} - -.menu-vertically-limited.with-bottom-separator { - border-bottom: 1px solid #e6e6e6; -} - -.menu .menu-footer > a > span { - border-bottom: 1px solid var(--gray80); - color: var(--secondFontColor); -} - -.menu .menu-footer-note { - opacity: 0; - transition: opacity 0.3s ease; -} - -.menu .menu-footer.active .menu-footer-note { - opacity: 1; -} - -.menu-search { - position: relative; - padding: var(--gridSize) calc(2 * var(--gridSize)) 0; -} - -.menu-search .search-box, -.menu-search .search-box-input { - max-width: none; - min-width: 240px; -} - -.menu-search ~ .menu > li > a:hover, -.menu-search ~ .menu > li > a:focus { - background-color: transparent; -} - -.menu-search ~ .menu > .active > a, -.menu-search ~ .menu > li > .active, -.menu-search ~ .menu > .active > a:hover, -.menu-search ~ .menu > li > .active:hover, -.menu-search ~ .menu > .active > a:focus, -.menu-search ~ .menu > li > .active:focus { - background-color: var(--barBackgroundColor); -} - -.menu-message { - display: block; - padding: 4px 16px; - line-height: 16px; -} - -.menu-header { - padding: var(--gridSize); - margin: -8px; - font-size: 12px; - color: var(--neutral600); - white-space: nowrap; - line-height: unset; -} - -.menu-header + ul { - padding-top: 8px; -} - -.menu-header.no-margin + ul { - padding-top: 0; -} - -.menu-header.no-margin { - margin: 0; -} - -.divider + .menu-header { - padding-top: calc(var(--gridSize) - 5px); -} diff --git a/server/sonar-web/src/main/js/app/styles/components/page.css b/server/sonar-web/src/main/js/app/styles/components/page.css index 812f7cf6cc9..37962ef9a7c 100644 --- a/server/sonar-web/src/main/js/app/styles/components/page.css +++ b/server/sonar-web/src/main/js/app/styles/components/page.css @@ -61,20 +61,6 @@ flex: 1 0 auto; } -.page-wrapper-simple { - display: flex; - justify-content: center; - align-items: center; - margin: 100px 0; -} - -.page-simple { - width: 400px; - padding: 40px; - border: 1px solid var(--barBorderColor); - background-color: #fff; -} - .page-header { position: relative; margin-bottom: 20px; @@ -91,12 +77,6 @@ clear: both; } -.page-header .spinner { - position: relative; - top: 3px; - margin-left: 8px; -} - .page-title { float: left; margin-bottom: 0; @@ -115,10 +95,6 @@ margin: 3px 0; } -.page-actions .spinner { - top: 0 !important; -} - .page-description { float: left; clear: left; diff --git a/server/sonar-web/src/main/js/app/styles/components/panels.css b/server/sonar-web/src/main/js/app/styles/components/panels.css deleted file mode 100644 index 584d3390d36..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/panels.css +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.panel { - padding: 10px; -} - -.panel:not(:last-child) { - border-bottom: 1px solid var(--barBorderColor); -} - -.panel-vertical { - padding-left: 0; - padding-right: 0; -} - -.panel-white { - border: 1px solid var(--barBorderColor); - background-color: #fff; -} - -.panel-warning { - border: 1px solid var(--alertBorderWarning); - background-color: var(--alertBackgroundWarning); - color: #8a6d3b; -} diff --git a/server/sonar-web/src/main/js/app/styles/components/spinner.css b/server/sonar-web/src/main/js/app/styles/components/spinner.css deleted file mode 100644 index c33b3aa34fa..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/spinner.css +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.spinner { - position: relative; - vertical-align: middle; - width: 16px; - height: 16px; - border: 2px solid var(--info500); - border-radius: 50%; - animation: spin 0.75s infinite linear; -} - -.spinner:before, -.spinner:after { - left: -2px; - top: -2px; - display: none; - position: absolute; - content: ''; - width: inherit; - height: inherit; - border: inherit; - border-radius: inherit; -} - -.spinner, -.spinner:before, -.spinner:after { - display: inline-block; - box-sizing: border-box; - border-color: transparent; - border-top-color: var(--info500); - animation-duration: 1.2s; -} - -.spinner:before { - transform: rotate(120deg); -} - -.spinner:after { - transform: rotate(240deg); -} - -@keyframes spin { - from { - transform: rotate(0deg); - } - - to { - transform: rotate(360deg); - } -} diff --git a/server/sonar-web/src/main/js/app/styles/components/ui.css b/server/sonar-web/src/main/js/app/styles/components/ui.css deleted file mode 100644 index 8ec19539497..00000000000 --- a/server/sonar-web/src/main/js/app/styles/components/ui.css +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.shortcut-button { - display: inline-block; - min-width: 24px; - height: var(--controlHeight); - line-height: 21px; - padding: 0 4px; - box-sizing: border-box; - border: 1px solid #ccc; - border-radius: 3px; - background-image: linear-gradient(to bottom, #f5f5f5, #eee); - box-shadow: - inset 0 1px 0 #fff, - 0 1px 0 #ccc; - color: var(--secondFontColor); - font-size: 11px; - text-align: center; -} - -.shortcut-button-small { - min-width: 16px; - height: 16px; - line-height: 14px; - margin-left: 4px; - margin-right: 4px; -} - -.shortcut-button-tiny { - width: 14px; - min-width: auto; - padding: 0; - height: 14px; - line-height: inherit; - font-size: 6px; -} - -.page-shortcuts-tooltip { - line-height: 12px; -} - -.identity-provider { - display: inline-block; - line-height: 14px; - padding: 2px 5px; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 3px; - box-sizing: border-box; - background-color: var(--darkBlue); - font-size: var(--smallFontSize); - color: #fff; -} - -.analysis-version { - display: inline-block; - vertical-align: middle; - height: 20px; - padding: 0 8px; - background-color: var(--primary400); - border-radius: 2px; - line-height: 20px; - font-size: var(--smallFontSize); - color: var(--white); - white-space: nowrap; - text-align: center; - font-weight: bold; - letter-spacing: 0; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/base.css b/server/sonar-web/src/main/js/app/styles/init/base.css index 41f506c63e7..a7f14eca985 100644 --- a/server/sonar-web/src/main/js/app/styles/init/base.css +++ b/server/sonar-web/src/main/js/app/styles/init/base.css @@ -29,12 +29,12 @@ } *:focus-visible { - outline: 2px dotted var(--primary400); + outline: 2px dotted #297bae; } html, body { - background-color: var(--barBackgroundColor); + background-color: white; } body { diff --git a/server/sonar-web/src/main/js/app/styles/init/forms.css b/server/sonar-web/src/main/js/app/styles/init/forms.css deleted file mode 100644 index 64c35c5b8f8..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/forms.css +++ /dev/null @@ -1,220 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -/* - * Inputs - */ -input[type='text'], -input[type='password'], -input[type='email'], -input[type='search'], -input[type='date'], -input[type='number'], -textarea, -select { - border: 1px solid var(--gray80); - box-sizing: border-box; - border-radius: 2px; - background: #fff; - color: var(--baseFontColor); - transition: border-color 0.2s ease; -} - -input[type='text']:active, -input[type='password']:active, -input[type='email']:active, -input[type='search']:active, -input[type='date']:active, -input[type='number']:active, -textarea:active, -select:active, -input[type='text']:focus, -input[type='password']:focus, -input[type='email']:focus, -input[type='search']:focus, -input[type='date']:focus, -input[type='number']:focus, -textarea:focus, -select:focus { - border-color: var(--blue); - box-shadow: none; - outline: none; -} - -input[type='text']:invalid, -input[type='password']:invalid, -input[type='email']:invalid, -input[type='search']:invalid, -input[type='date']:invalid, -input[type='number']:invalid, -textarea:invalid, -select:invalid { - box-shadow: none; - outline: none; -} - -input::placeholder, -textarea::placeholder { - color: var(--neutral600); - opacity: 0.9; -} - -input[type='text'].is-valid, -input[type='password'].is-valid, -input[type='email'].is-valid, -input[type='search'].is-valid, -input[type='date'].is-valid, -input[type='number'].is-valid, -textarea.is-valid, -select.is-valid { - border-color: var(--green); -} - -input[type='text'].is-invalid, -input[type='password'].is-invalid, -input[type='email'].is-invalid, -input[type='search'].is-invalid, -input[type='date'].is-invalid, -input[type='number'].is-invalid, -textarea.is-invalid, -select.is-invalid { - border-color: var(--red); -} - -input.disabled, -input:disabled, -textarea.disabled, -textarea:disabled, -select.disabled, -select:disabled { - color: var(--disableGrayText) !important; - border-color: var(--disableGrayBorder) !important; - background: var(--disableGrayBg) !important; - cursor: not-allowed !important; - pointer-events: none !important; - box-shadow: none !important; -} - -input[type='text'], -input[type='password'], -input[type='email'], -input[type='search'], -input[type='date'], -input[type='number'] { - height: var(--controlHeight); - padding: 0 6px; -} - -input[type='search'] { - -webkit-appearance: textfield; -} - -input[type='search']::-webkit-search-decoration { - -webkit-appearance: none; -} - -textarea { - padding: 3px; -} - -textarea.width-100 { - max-width: 100%; -} - -textarea.fixed-width { - resize: vertical; -} - -select { - height: var(--controlHeight); - line-height: var(--controlHeight); -} - -.input-tiny { - width: 60px !important; -} - -.input-small { - width: 100px !important; -} - -.input-medium { - width: 150px !important; -} - -.input-large { - width: 200px !important; -} - -.input-super-large { - width: 100% !important; - max-width: 300px; - min-width: 200px; -} - -.input-ghost { - padding: 0 !important; - border: none !important; - background-color: transparent !important; -} - -.input-clear { - background-color: transparent !important; -} - -.input-code { - font-family: var(--sourceCodeFontFamily); - font-size: var(--smallFontSize); -} - -em.mandatory { - color: var(--mandatoryFieldColor); - font-style: italic; -} - -.form-field { - clear: both; - display: block; - padding-bottom: calc(2 * var(--gridSize)); -} - -.form-field label { - display: block; - font-weight: bold; - padding-bottom: calc(var(--gridSize) / 2); -} - -.form-field-description { - line-height: 1.4; - color: var(--secondFontColor); - font-size: var(--smallFontSize); - overflow: hidden; - text-overflow: ellipsis; - margin-top: 2px; -} - -.form-field input[type='text'], -.form-field input[type='email'], -.form-field input[type='password'], -.form-field textarea, -.form-field select, -.form-field .react-select, -.form-field .Select { - width: 250px; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/icons.css b/server/sonar-web/src/main/js/app/styles/init/icons.css deleted file mode 100644 index 2206cde6208..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/icons.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -[class^='icon-'], -[class*=' icon-'] { - line-height: 1; - vertical-align: middle; -} - -a[class^='icon-'], -a[class*=' icon-'] { - border-bottom: none; -} - -/* - * Colors - */ -.icon-gray { - color: #999; -} - -.icon-gray path { - fill: #999; -} - -.icon-color-link { - color: var(--darkBlue); -} - -/* - * Common - */ -.icon-outline { - transition: all 0.2s ease !important; -} - -.icon-outline path { - stroke: var(--secondFontColor); - stroke-width: 1.41421356; - stroke-opacity: 1; - fill-opacity: 0; - vector-effect: non-scaling-stroke; - transition: all 0.2s ease; -} - -.icon-outline.is-filled path { - fill: currentColor; - stroke: currentColor; - fill-opacity: 1; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/links.css b/server/sonar-web/src/main/js/app/styles/init/links.css deleted file mode 100644 index b0e811ec87a..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/links.css +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -a { - border-bottom: 1px solid var(--primarya40); - color: var(--primary); - cursor: pointer; - outline: none; - text-decoration: none; - transition: - border-bottom-color 0.2s ease, - color 0.2s ease; -} - -a:hover, -a:active, -a:focus { - border-bottom-color: var(--primary); -} - -a svg, -a img { - vertical-align: middle; -} - -.link-no-underline { - border-bottom-color: transparent !important; -} - -.link-no-underline:hover { - border-bottom-color: var(--primary) !important; -} - -.link-rating, -.link-rating:hover { - border-bottom: 0 !important; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/lists.css b/server/sonar-web/src/main/js/app/styles/init/lists.css deleted file mode 100644 index 4447df2b394..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/lists.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -ol, -ul { - padding-left: 0; - list-style: none; -} - -.list-styled { - margin-bottom: 10px; - padding-left: 40px; -} - -.list-styled.no-padding { - padding-left: calc(var(--gridSize) * 2); -} - -ul.list-styled { - list-style: disc; -} - -ol.list-styled { - list-style: decimal; -} - -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; -} - -.list-breadcrumbs > li { - display: inline-block; -} - -.list-breadcrumbs > li:not(:first-of-type)::before { - content: '/' / ''; - margin-inline: 3px; -} - -ul.list-inline > li, -div.list-inline > div { - display: inline-block; - vertical-align: top; - padding-right: 5px; - padding-left: 5px; -} - -.list-spaced { - margin-bottom: 10px; - list-style: none; -} - -.list-spaced > li { - margin-top: 10px; -} - -.list-item-checkable-link { - cursor: pointer; -} - -.list-item-checkable-link:focus { - outline: none; -} - -.list-item-checkable-link.disabled { - opacity: 0.7; -} - -.list-item-checkable-link.disabled a::before { - background-color: var(--gray80); - border-color: var(--gray80); -} - -dl { - margin-top: 0; - margin-bottom: 20px; -} - -dt, -dd { - line-height: 1.42857143; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 0; -} 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 d1d01be68f3..df466f2fa8a 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 @@ -34,32 +34,11 @@ th.hide-overflow { overflow: hidden; } -.hidden { - display: none !important; - visibility: hidden !important; -} - -.invisible { - visibility: hidden; -} - .note { color: var(--secondFontColor); font-size: var(--smallFontSize); } -.nudged-up { - margin-top: -1px; -} - -.nudged-down { - margin-top: 1px; -} - -.null-spacer-top { - margin-top: 0 !important; -} - .null-spacer-bottom { margin-bottom: 0 !important; } @@ -84,46 +63,6 @@ th.hide-overflow { margin-top: 8px !important; } -.big-spacer { - margin: 16px !important; -} - -.big-spacer-left { - margin-left: 16px !important; -} - -.big-spacer-right { - margin-right: 16px !important; -} - -.big-spacer-bottom { - margin-bottom: 16px !important; -} - -.big-spacer-top { - margin-top: 16px !important; -} - -.huge-spacer { - margin: 40px !important; -} - -.huge-spacer-bottom { - margin-bottom: 40px !important; -} - -.huge-spacer-top { - margin-top: 40px !important; -} - -.huge-spacer-left { - margin-left: 40px !important; -} - -.huge-spacer-right { - margin-right: 40px !important; -} - .little-spacer { margin: 4px !important; } @@ -148,18 +87,10 @@ th.hide-overflow { padding: var(--gridSize) !important; } -.little-padded { - padding: calc(var(--gridSize) / 2) !important; -} - .big-padded { padding: calc(2 * var(--gridSize)) !important; } -.padded-top { - padding-top: var(--gridSize) !important; -} - .padded-right { padding-right: var(--gridSize) !important; } @@ -172,45 +103,10 @@ th.hide-overflow { padding-left: var(--gridSize) !important; } -.little-padded-top { - padding-top: calc(var(--gridSize) / 2) !important; -} - -.little-padded-right { - padding-right: calc(var(--gridSize) / 2) !important; -} - -.little-padded-bottom { - padding-bottom: calc(var(--gridSize) / 2) !important; -} - -.little-padded-left { - padding-left: calc(var(--gridSize) / 2) !important; -} - -.big-padded-top { - padding-top: calc(2 * var(--gridSize)); -} -.big-padded-bottom { - padding-bottom: calc(2 * var(--gridSize)); -} - .big-padded-right { padding-right: calc(2 * var(--gridSize)); } -.big-padded-left { - padding-left: calc(2 * var(--gridSize)); -} - -.huge-padded-top { - padding-top: 40px; -} - -.huge-padded-bottom { - padding-bottom: 40px; -} - td.little-spacer-left { padding-left: 4px !important; } @@ -235,60 +131,10 @@ td.spacer-top { padding-top: 8px !important; } -td.big-spacer-left, -th.big-spacer-left { - padding-left: 16px !important; -} - -td.big-spacer-right { - padding-right: 16px !important; -} - -td.big-spacer-bottom { - padding-bottom: 16px !important; -} - -td.big-spacer-top { - padding-top: 16px !important; -} - -td.huge-spacer-right, -th.huge-spacer-right { - padding-right: 40px !important; -} - .pull-left { float: left !important; } -.pull-right { - float: right !important; -} - -.borderless { - border: none !important; -} - -.bordered { - border: 1px solid var(--barBorderColor); -} - -.bordered-left { - border-left: 1px solid var(--barBorderColor); -} - -.bordered-right { - border-right: 1px solid var(--barBorderColor); -} - -.bordered-bottom { - border-bottom: 1px solid var(--barBorderColor); -} - -.bordered-top { - border-top: 1px solid var(--barBorderColor); -} - .overflow-hidden { overflow: hidden !important; } @@ -297,78 +143,14 @@ th.huge-spacer-right { overflow-y: auto !important; } -.max-width-100 { - max-width: 100% !important; -} - -.max-width-80 { - max-width: 80% !important; -} - -.max-width-60 { - max-width: 60% !important; -} - .width-100 { width: 100% !important; } -.width-80 { - width: 80% !important; -} - -.width-60 { - width: 60% !important; -} - -.width-55 { - width: 55% !important; -} - -.width-50 { - width: 50% !important; -} - -.width-40 { - width: 40% !important; -} - -.width-30 { - width: 30% !important; -} - -.width-25 { - width: 25% !important; -} - -.width-20 { - width: 20% !important; -} - -.width-15 { - width: 15% !important; -} - -.width-10 { - width: 10% !important; -} - .abs-width-100 { width: 100px !important; } -.abs-width-150 { - width: 150px !important; -} - -.abs-width-240 { - width: 240px !important; -} - -.abs-width-300 { - width: 300px !important; -} - .abs-width-400 { width: 400px !important; } @@ -377,58 +159,6 @@ th.huge-spacer-right { width: 600px !important; } -.abs-width-800 { - width: 800px !important; -} - -.abs-height-50 { - height: 50px !important; -} - -.abs-height-100 { - height: 100% !important; -} - -.max-height-100 { - max-height: 100% !important; -} - -.justify { - margin-bottom: -1em; - text-align: justify; -} - -.justify > .ib { - display: inline-block; -} - -.justify:after { - display: inline-block; - width: 100%; - content: ' '; -} - -.first-letter-uppercase::first-letter { - text-transform: uppercase; -} - -.disabled-pointer-events { - pointer-events: none !important; -} - -.display-block { - display: block !important; -} - -.display-inline-block { - display: inline-block !important; -} - -.display-flex-row { - display: flex !important; - flex-direction: row; -} - .display-flex-column { display: flex !important; flex-direction: column; @@ -439,108 +169,29 @@ th.huge-spacer-right { align-items: center; } -.display-flex-justify-start { - display: flex !important; - justify-content: flex-start !important; -} - .display-flex-justify-center { display: flex !important; justify-content: center; } -.display-flex-justify-end { - display: flex !important; - justify-content: flex-end; -} - -.display-flex-space-around { - display: flex !important; - justify-content: space-around; -} - -.display-flex-space-between { - display: flex !important; - justify-content: space-between; -} - -.display-flex-stretch { - display: flex !important; - align-items: stretch; -} - .display-flex-start { display: flex !important; align-items: flex-start !important; } -.display-flex-end { - display: flex !important; - align-items: flex-end; -} - -.display-flex-wrap { - display: flex !important; - flex-wrap: wrap; -} - -.display-inline-flex-baseline { - display: inline-flex !important; - align-items: baseline; -} - -.display-inline-flex-start { - display: inline-flex !important; - align-items: flex-start; -} - .display-inline-flex-center { display: inline-flex !important; align-items: center; } -.position-absolute { - position: absolute !important; -} - -.position-relative { - position: relative !important; -} - -.rounded { - border-radius: 2px; -} - .flex-1 { flex: 1; } -.flex-1-0-auto { - flex: 1 0 auto; -} - -.flex-0 { - flex: 0 0 auto; -} - .flex-grow { flex-grow: 1; } -.flex-shrink { - flex-shrink: 1; - min-width: 0; -} - -.space-between { - justify-content: space-between !important; -} - -.new-loading { - opacity: 0.5; - transition: opacity 0.5s ease; -} - .slash-separator { margin-left: 5px; margin-right: 5px; @@ -550,99 +201,3 @@ th.huge-spacer-right { content: '/'; color: rgba(68, 68, 68, 0.3); } - -.horizontal-pipe-separator { - display: flex; - align-items: center; - margin-top: calc(4 * var(--gridSize)); - margin-bottom: calc(4 * var(--gridSize)); -} - -.horizontal-pipe-separator > .horizontal-separator { - margin: 0 4px; -} - -.horizontal-separator { - min-width: 16px; - height: 1px; - flex-grow: 1; - background-color: var(--barBorderColor); -} - -.vertical-separator { - width: 1px; - min-height: 16px; - flex-grow: 1; - background-color: var(--barBorderColor); -} - -.vertical-pipe-separator { - display: flex; - flex-direction: column; - margin-left: 60px; - margin-right: 60px; -} - -.vertical-pipe-separator > .vertical-separator { - margin: 4px auto; -} - -.capitalize { - text-transform: capitalize !important; -} - -.cursor-pointer { - cursor: pointer; -} - -.cursor-not-allowed { - cursor: not-allowed !important; -} - -.no-outline, -.no-outline:focus { - outline: none !important; -} - -.bg-danger { - background-color: var(--red); - color: #fff; -} - -.bg-warning { - background-color: var(--alertBackgroundWarning); - color: var(--alertTextWarning); -} - -.bg-info { - background-color: var(--blue); - color: #fff; -} - -.bg-success { - background-color: var(--green); - color: #fff; -} - -.bg-muted { - background-color: var(--barBackgroundColor); - color: inherit; -} - -.muted { - color: var(--neutral600); -} - -.leak-box { - background-color: var(--leakPrimaryColor); - border: 1px solid var(--leakSecondaryColor); - padding: 4px 6px; -} - -.break-word { - word-break: break-word; -} - -.no-margin-bottom { - margin-bottom: 0 !important; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/tables.css b/server/sonar-web/src/main/js/app/styles/init/tables.css deleted file mode 100644 index 8ac6c5d3d6f..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/tables.css +++ /dev/null @@ -1,301 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -table { - border-collapse: collapse; - border-spacing: 0; -} - -table.form td { - padding: 2px 5px; - vertical-align: top; -} - -table.form th { - padding: 2px 5px; - font-weight: 600; -} - -table.form td.keyCell { - width: 1%; - white-space: nowrap; - text-align: right; - font-weight: bold; - vertical-align: top; -} - -table.form td img { - vertical-align: bottom; -} - -table.spaced th { - font-weight: bold; - color: #333; - padding: 4px 5px; -} - -table.spaced td { - padding: 3px 5px; - line-height: 18px; -} - -table.spaced td img { - vertical-align: text-bottom; -} - -table.spacedicon th { - font-weight: bold; - color: #333; - padding: 4px 5px; -} - -table.spacedicon td { - padding: 0 5px; - height: 24px; -} - -.thin { - width: 1%; -} - -.formError { - display: inline-block; - background-color: var(--orange); - color: #000; - padding: 0 5px; -} - -.table > thead > tr > th { - border-top: 0 none; - font-weight: bold; - line-height: 16px; - padding: 4px 5px; - vertical-align: bottom; -} - -.table > tbody > tr > td { - line-height: 16px; - padding: 4px 5px; - vertical-align: top; -} - -.table > tfoot > tr > td { - font-size: 93%; - color: var(--secondFontColor); - padding: 4px 5px; -} - -.table > tfoot > tr > td a { - color: var(--secondFontColor); -} - -.hoverable:hover { - background-color: var(--lightBlue); -} - -.hoverable:hover a { - color: #111; -} - -.odd { - background-color: #fff; -} - -.even { - background-color: #f5f5f5; -} - -.odd.selected, -.even.selected, -.odd.selected a, -.even.selected a, -.even.selected span:not(.rating), -.odd.selected span:not(.rating) { - background-color: #d9edf7; - color: var(--baseFontColor); -} - -.table-cell-doc { - position: absolute; - z-index: var(--aboveNormalZIndex); - right: -8px; -} - -th > .table-cell-doc { - top: 50%; - margin-top: -6px; -} - -td.sep { - width: 10px; -} - -table.matrix tfoot td { - padding: 3px 5px; - line-height: 18px; -} - -table.data, -table.spaced { - width: 100%; -} - -table.data td.small, -table.data th.small { - padding: 0; - white-space: nowrap; -} - -table.data > caption { - padding: 8px 10px; - text-align: center; - font-weight: bold; -} - -table.data > thead > tr > th { - position: relative; - vertical-align: top; - line-height: 18px; - padding: 8px 10px; - border-bottom: 1px solid var(--barBorderColor); - font-weight: 600; -} - -table.data > thead > tr > th > .small { - display: block; - line-height: 1.4; - font-weight: 400; -} - -table.data > tfoot > tr > td { - font-size: 93%; - color: var(--secondFontColor); - padding: 5px; -} - -table.data > tbody > tr > td { - position: relative; - padding: 8px 10px; - line-height: 16px; -} - -table.data > tbody > tr > td.text-middle { - vertical-align: middle; -} - -.data thead tr.total { - background-color: var(--gray94); - font-weight: normal; - border: 1px solid #ddd; -} - -.data thead tr.total th { - font-weight: normal; -} - -.data tr.blank, -.data tr.blank > td, -.data td.blank { - background-color: #fff !important; - line-height: 15px; -} - -.data tr.highlight { - background-color: var(--lightBlue); -} - -.data input, -.data select, -.data button { - vertical-align: middle; -} - -table.data.condensed > tbody > tr > td { - padding-top: 5px; - padding-bottom: 5px; -} - -table.data tr.subheader th { - font-size: var(--smallFontSize); - border-bottom: none; -} - -table.data:not(.boxed-padding) > thead:after { - display: block; - line-height: 5px; - content: '\200C'; -} - -table.data.boxed-padding > thead > tr > th { - padding-top: 24px; -} - -table.data.boxed-padding > thead > tr > th:first-child, -table.data.boxed-padding > tbody > tr > td:first-child, -table.data.boxed-padding > thead > tr > th:last-child, -table.data.boxed-padding > tbody > tr > td:last-child { - width: 20px; - padding: 8px 0; -} - -table.data.no-outer-padding > thead > tr > th:first-child, -table.data.no-outer-padding > tbody > tr > td:first-child { - padding-left: 0; -} - -table.data.no-outer-padding > thead > tr > th:last-child, -table.data.no-outer-padding > tbody > tr > td:last-child { - padding-right: 0; -} - -table.data.boxed-padding > thead + tbody > tr:first-child > td { - padding-top: 16px; -} - -table.data.zebra-hover > tbody > tr:hover { - background-color: var(--rowHoverHighlight) !important; -} - -table.data.zebra > tbody > tr.selected { - background-color: #d9edf7 !important; -} - -table.data.zebra:not(.zebra-inversed) > tbody > tr:nth-child(even) { - background-color: #f5f5f5; -} - -table.data.zebra.zebra-inversed > tbody > tr:nth-child(odd) { - background-color: #f5f5f5; -} - -table#project-history tr > td { - vertical-align: top; -} - -table.fixed { - table-layout: fixed; -} - -table.fixed th.action-small { - width: 30px; -} - -table.fixed th.action { - width: 50px; -} diff --git a/server/sonar-web/src/main/js/app/styles/init/type.css b/server/sonar-web/src/main/js/app/styles/init/type.css deleted file mode 100644 index 1ed45b8b67b..00000000000 --- a/server/sonar-web/src/main/js/app/styles/init/type.css +++ /dev/null @@ -1,304 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -html, -body { - color: var(--baseFontColor); -} - -body { - font-family: var(--baseFontFamily); - font-size: var(--baseFontSize); - line-height: 1.23076923; -} - -h1, -.h1 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: var(--bigFontSize); - font-weight: 400; -} - -h1 img, -.h1 img, -h1 svg, -.h1 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -h2, -.h2 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: 15px; - font-weight: 400; -} - -h2 img, -.h2 img, -h2 svg, -.h2 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -h3, -.h3 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: var(--mediumFontSize); - font-weight: 600; -} - -h3 img, -.h3 img, -h3 svg, -.h3 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -h4, -.h4 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: var(--baseFontSize); - font-weight: 600; -} - -h4 img, -.h4 img, -h4 svg, -.h4 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -h5, -.h5 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: var(--baseFontSize); - font-weight: 600; -} - -h5 img, -.h5 img, -h5 svg, -.h5 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -h6, -.h6 { - line-height: var(--controlHeight); - color: var(--baseFontColor); - font-size: var(--baseFontSize); - font-weight: 600; -} - -h6 img, -.h6 img, -h6 svg, -.h6 svg { - vertical-align: middle; - transform: translateY(-1px); -} - -em { - font-style: italic; -} - -strong { - font-weight: 600; -} - -.underline { - text-decoration: underline; -} - -mark { - background: none; - color: var(--baseFontColor); - font-weight: bold; -} - -blockquote { - border-left: 3px solid var(--barBorderColor); - padding: 0 8px; - line-height: 1.5; -} - -blockquote cite { - line-height: 1.5; - color: var(--secondFontColor); - font-size: var(--smallFontSize); -} - -small, -.small { - font-size: var(--smallFontSize) !important; -} - -.medium { - font-size: var(--mediumFontSize) !important; -} - -.big { - font-size: var(--bigFontSize) !important; -} - -.huge { - font-size: var(--hugeFontSize) !important; -} - -.gigantic { - font-size: var(--giganticFontSize) !important; -} - -.zero-font-size { - font-size: 0 !important; -} - -.text-left { - text-align: left; -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.text-justify { - text-align: justify; -} - -.text-top { - vertical-align: top !important; -} - -.text-middle { - vertical-align: middle !important; -} - -.text-bottom { - vertical-align: bottom !important; -} - -.text-text-top { - vertical-align: text-top !important; -} - -.text-text-bottom { - vertical-align: text-bottom !important; -} - -.text-baseline { - vertical-align: baseline !important; -} - -.text-ellipsis { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.text-limited-small { - display: inline-block; - max-width: 8vw; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.text-limited { - display: inline-block; - max-width: 16vw; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.text-uppercase { - text-transform: uppercase; -} - -.text-lowercase { - text-transform: lowercase; -} - -.text-no-transform { - text-transform: none; -} - -.text-light { - font-weight: 300 !important; -} - -.text-normal { - font-weight: normal !important; -} - -.text-bold { - font-weight: bold !important; -} - -.text-muted { - color: var(--secondFontColor); -} - -.text-muted-2 { - color: var(--gray71); -} - -.text-danger { - color: var(--red) !important; -} - -.text-warning { - color: var(--orange) !important; -} - -.text-info { - color: var(--blue) !important; -} - -.text-success { - color: var(--green) !important; -} - -.monospaced { - line-height: 18px; - font-family: var(--sourceCodeFontFamily); - font-size: var(--smallFontSize); -} - -.new-background { - background-color: #fcfcfd; -} - -.white-background { - background-color: #ffffff; -} diff --git a/server/sonar-web/src/main/js/app/styles/mixins.css b/server/sonar-web/src/main/js/app/styles/mixins.css deleted file mode 100644 index ef4eeb2e0f2..00000000000 --- a/server/sonar-web/src/main/js/app/styles/mixins.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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. - */ -.clearfix:before, -.clearfix:after { - display: table; - content: ''; - line-height: 0; -} - -.clearfix:after { - clear: both; -} diff --git a/server/sonar-web/src/main/js/app/styles/sonar.ts b/server/sonar-web/src/main/js/app/styles/sonar.ts index fcc97c52a3d..aa6fdccd870 100644 --- a/server/sonar-web/src/main/js/app/styles/sonar.ts +++ b/server/sonar-web/src/main/js/app/styles/sonar.ts @@ -23,27 +23,10 @@ import '../../../../../public/fonts/Inter/inter.css'; import '../../../../../public/fonts/Ubuntu/Ubuntu.css'; -import './components/badges.css'; import './components/boxed-group.css'; -import './components/columns.css'; -import './components/component-name.css'; -import './components/dropdowns.css'; import './components/global-loading.css'; -import './components/issues.css'; -import './components/list-groups.css'; -import './components/menu.css'; import './components/page.css'; -import './components/panels.css'; -import './components/spinner.css'; -import './components/ui.css'; import './init/base.css'; -import './init/forms.css'; -import './init/icons.css'; -import './init/links.css'; -import './init/lists.css'; import './init/misc.css'; -import './init/tables.css'; -import './init/type.css'; -import './mixins.css'; import './print.css'; import './style.css'; diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx index b12aae3de32..553ec297a82 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx @@ -101,6 +101,7 @@ import PortfolioPage from '../components/extensions/PortfolioPage'; import PortfoliosPage from '../components/extensions/PortfoliosPage'; import ProjectAdminPageExtension from '../components/extensions/ProjectAdminPageExtension'; import ProjectPageExtension from '../components/extensions/ProjectPageExtension'; +import { GlobalStyles } from '../styles/GlobalStyles'; import exportModulesAsGlobals from './exportModulesAsGlobals'; function renderComponentRoutes() { @@ -272,6 +273,7 @@ export default function startReactApp( <RawIntlProvider value={l10nBundle}> <ThemeProvider theme={lightTheme}> <QueryClientProvider client={queryClient}> + <GlobalStyles /> <GlobalMessagesContainer /> <Helmet titleTemplate={translate('page_title.template.default')} /> <RouterProvider router={router} /> |