@@ -9,6 +9,17 @@ | |||
"rules": { | |||
"camelcase": "off", | |||
"promise/no-return-wrap": "warn", | |||
"react/forbid-elements": [ | |||
"warn", | |||
{ | |||
"forbid": [ | |||
{ | |||
"element": "img", | |||
"message": "use <Image> from components/common instead" | |||
} | |||
] | |||
} | |||
], | |||
"react/jsx-curly-brace-presence": "warn", | |||
"testing-library/render-result-naming-convention": "off", | |||
/* Local rules, defined in ./eslint-local-rules/ */ |
@@ -17,6 +17,8 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { LinkStandalone } from '@sonarsource/echoes-react'; | |||
import { | |||
ButtonPrimary, | |||
Card, | |||
@@ -24,7 +26,6 @@ import { | |||
CheckIcon, | |||
ClipboardButton, | |||
InputField, | |||
Link, | |||
ListItem, | |||
Note, | |||
OrderedList, | |||
@@ -33,6 +34,7 @@ import { | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { useSearchParams } from 'react-router-dom'; | |||
import { Image } from '../../components/common/Image'; | |||
import { whenLoggedIn } from '../../components/hoc/whenLoggedIn'; | |||
import { translate, translateWithParameters } from '../../helpers/l10n'; | |||
import { generateSonarLintUserToken, portIsValid, sendUserToken } from '../../helpers/sonarlint'; | |||
@@ -88,10 +90,9 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { | |||
{status === Status.request && ( | |||
<> | |||
<Title>{translate('sonarlint-connection.request.title')}</Title> | |||
<img | |||
alt="" | |||
<Image | |||
alt="sonarlint-connection-request" | |||
className="sw-my-4" | |||
role="presentation" | |||
src="/images/SonarLint-connection-request.png" | |||
/> | |||
<p className="sw-my-4"> | |||
@@ -107,7 +108,7 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { | |||
{status === Status.tokenError && ( | |||
<> | |||
<img alt="" className="sw-my-4 sw-pt-2" role="presentation" src="/images/cross.svg" /> | |||
<Image alt="sonarlint-token-error" className="sw-my-4 sw-pt-2" 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"> | |||
@@ -116,9 +117,9 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { | |||
defaultMessage={translate('sonarlint-connection.token-error.description2')} | |||
values={{ | |||
link: ( | |||
<Link to="/account/security"> | |||
<LinkStandalone to="/account/security"> | |||
{translate('sonarlint-connection.token-error.description2.link')} | |||
</Link> | |||
</LinkStandalone> | |||
), | |||
}} | |||
/> | |||
@@ -128,7 +129,11 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { | |||
{status === Status.tokenCreated && newToken && ( | |||
<> | |||
<img alt="" className="sw-my-4 sw-pt-2" role="presentation" src="/images/check.svg" /> | |||
<Image | |||
alt="sonarlint-connection-error" | |||
className="sw-my-4 sw-pt-2" | |||
src="/images/check.svg" | |||
/> | |||
<Title>{translate('sonarlint-connection.connection-error.title')}</Title> | |||
<p className="sw-my-6"> | |||
{translate('sonarlint-connection.connection-error.description')} | |||
@@ -160,10 +165,9 @@ export function SonarLintConnection({ currentUser }: Readonly<Props>) { | |||
{status === Status.tokenSent && newToken && ( | |||
<> | |||
<Title>{translate('sonarlint-connection.success.title')}</Title> | |||
<img | |||
alt="" | |||
<Image | |||
alt="sonarlint-connection-success" | |||
className="sw-mb-4" | |||
role="presentation" | |||
src="/images/SonarLint-connection-ok.png" | |||
/> | |||
<p className="sw-my-4"> |
@@ -20,9 +20,9 @@ | |||
import { LinkStandalone } from '@sonarsource/echoes-react'; | |||
import React from 'react'; | |||
import { Image } from '../../../../../components/common/Image'; | |||
import { isPullRequest } from '../../../../../helpers/branch-like'; | |||
import { translate, translateWithParameters } from '../../../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../../../helpers/system'; | |||
import { isDefined } from '../../../../../helpers/types'; | |||
import { AlmKeys } from '../../../../../types/alm-settings'; | |||
import { BranchLike } from '../../../../../types/branch-like'; | |||
@@ -70,10 +70,10 @@ export default function PRLink({ | |||
<LinkStandalone | |||
iconLeft={ | |||
almKey !== '' && ( | |||
<img | |||
<Image | |||
alt={almKey} | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/${almKey}.svg`} | |||
src={`/images/alm/${almKey}.svg`} | |||
title={translateWithParameters('branches.see_the_pr_on_x', translate(almKey))} | |||
/> | |||
) |
@@ -17,8 +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 { MainAppBar, SonarQubeLogo } from 'design-system'; | |||
import * as React from 'react'; | |||
import { Image } from '../../../../components/common/Image'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
import { GlobalSettingKeys } from '../../../../types/settings'; | |||
import { AppStateContext } from '../../app-state/AppStateContext'; | |||
@@ -35,7 +37,7 @@ function LogoWithAriaText() { | |||
return ( | |||
<div aria-label={title} role="img"> | |||
{customLogoUrl ? ( | |||
<img alt={title} src={customLogoUrl} width={customLogoWidth} /> | |||
<Image alt={title} src={customLogoUrl} width={customLogoWidth} /> | |||
) : ( | |||
<SonarQubeLogo /> | |||
)} |
@@ -17,12 +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 styled from '@emotion/styled'; | |||
import { ButtonPrimary, ButtonSecondary, themeBorder, themeColor } from 'design-system'; | |||
import * as React from 'react'; | |||
import { dismissNotice } from '../../../api/users'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { NoticeType, isLoggedIn } from '../../../types/users'; | |||
import { CurrentUserContextInterface } from '../current-user/CurrentUserContext'; | |||
import withCurrentUserContext from '../current-user/withCurrentUserContext'; | |||
@@ -47,7 +48,7 @@ export function PromotionNotification(props: CurrentUserContextInterface) { | |||
return ( | |||
<PromotionNotificationWrapper className="it__promotion_notification sw-z-global-popup sw-rounded-1 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`} /> | |||
<Image alt="SonarQube + SonarLint" height={80} src="/images/sq-sl.svg" /> | |||
</div> | |||
<PromotionNotificationContent className="sw-flex-1 sw-px-2 sw-py-4"> | |||
<span className="sw-body-sm-highlight">{translate('promotion.sonarlint.title')}</span> |
@@ -17,11 +17,12 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { getTextColor } from 'design-system'; | |||
import * as React from 'react'; | |||
import { getIdentityProviders } from '../../../api/users'; | |||
import { colors } from '../../../app/theme'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { IdentityProvider } from '../../../types/types'; | |||
import { LoggedInUser } from '../../../types/users'; | |||
@@ -104,11 +105,11 @@ export default class UserExternalIdentity extends React.PureComponent< | |||
color: getTextColor(identityProvider.backgroundColor, colors.secondFontColor), | |||
}} | |||
> | |||
<img | |||
<Image | |||
alt={identityProvider.name} | |||
className="sw-mr-1" | |||
height="14" | |||
src={getBaseUrl() + identityProvider.iconPath} | |||
src={identityProvider.iconPath} | |||
width="14" | |||
/> | |||
{user.externalIdentity} |
@@ -17,22 +17,23 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable react/no-unused-prop-types */ | |||
import { LinkStandalone, Spinner } from '@sonarsource/echoes-react'; | |||
import { | |||
ButtonSecondary, | |||
GreyCard, | |||
HelperHintIcon, | |||
LightPrimary, | |||
Spinner, | |||
StandoutLink, | |||
TextMuted, | |||
Title, | |||
} from 'design-system'; | |||
import * as React from 'react'; | |||
import withAppStateContext from '../../../app/components/app-state/withAppStateContext'; | |||
import { Image } from '../../../components/common/Image'; | |||
import HelpTooltip from '../../../components/controls/HelpTooltip'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { getCreateProjectModeLocation } from '../../../helpers/urls'; | |||
import { AlmKeys } from '../../../types/alm-settings'; | |||
import { AppState } from '../../../types/appstate'; | |||
@@ -79,12 +80,10 @@ function renderAlmOption( | |||
const svgFileNameGrey = `${svgFileName}_grey`; | |||
const icon = ( | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/alm/${ | |||
!disabled && hasConfig ? svgFileName : svgFileNameGrey | |||
}.svg`} | |||
src={`/images/alm/${!disabled && hasConfig ? svgFileName : svgFileNameGrey}.svg`} | |||
/> | |||
); | |||
@@ -92,9 +91,11 @@ function renderAlmOption( | |||
<GreyCard key={alm} className="sw-col-span-4 sw-p-4 sw-flex sw-justify-between sw-items-center"> | |||
<div className="sw-items-center sw-flex sw-py-2"> | |||
{!disabled && hasConfig ? ( | |||
<StandoutLink icon={icon} to={getCreateProjectModeLocation(mode)}> | |||
{translate('onboarding.create_project.import_select_method', alm)} | |||
</StandoutLink> | |||
<LinkStandalone iconLeft={icon} to={getCreateProjectModeLocation(mode)}> | |||
<span className="sw-ml-2"> | |||
{translate('onboarding.create_project.import_select_method', alm)} | |||
</span> | |||
</LinkStandalone> | |||
) : ( | |||
<> | |||
{icon} | |||
@@ -106,7 +107,7 @@ function renderAlmOption( | |||
)} | |||
</div> | |||
<Spinner loading={loadingBindings}> | |||
<Spinner isLoading={loadingBindings}> | |||
{!hasConfig && | |||
(canAdmin ? ( | |||
<ButtonSecondary onClick={() => props.onConfigMode(configMode)}> | |||
@@ -167,9 +168,9 @@ export function CreateProjectModeSelection(props: CreateProjectModeSelectionProp | |||
<div className="sw-grid sw-gap-x-12 sw-gap-y-6 sw-grid-cols-12"> | |||
<GreyCard className="sw-col-span-4 sw-p-4 sw-py-6 sw-flex sw-justify-between sw-items-center"> | |||
<div> | |||
<StandoutLink to={getCreateProjectModeLocation(CreateProjectModes.Manual)}> | |||
<LinkStandalone to={getCreateProjectModeLocation(CreateProjectModes.Manual)}> | |||
{translate('onboarding.create_project.import_select_method.manual')} | |||
</StandoutLink> | |||
</LinkStandalone> | |||
</div> | |||
</GreyCard> | |||
</div> |
@@ -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 { | |||
ActionsDropdown, | |||
Badge, | |||
@@ -33,8 +34,8 @@ import { | |||
} from 'design-system'; | |||
import * as React from 'react'; | |||
import { useState } from 'react'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { translate, translateWithParameters } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { useGroupMembersCountQuery } from '../../../queries/group-memberships'; | |||
import { Group, Provider } from '../../../types/types'; | |||
import DeleteGroupForm from './DeleteGroupForm'; | |||
@@ -69,11 +70,11 @@ export default function ListItem(props: Readonly<ListItemProps>) { | |||
} | |||
return ( | |||
<img | |||
<Image | |||
alt={identityProvider} | |||
className="sw-ml-2 sw-mr-2" | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/${identityProvider}.svg`} | |||
src={`/images/alm/${identityProvider}.svg`} | |||
/> | |||
); | |||
}; |
@@ -17,9 +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 { SubHeading, UnorderedList } from 'design-system'; | |||
import * as React from 'react'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { Edition, EditionKey } from '../../../types/editions'; | |||
interface Props { | |||
@@ -32,11 +33,11 @@ export default function EditionBox({ edition }: Readonly<Props>) { | |||
return ( | |||
<div> | |||
<SubHeading as="h2" id="data-center-edition"> | |||
<img | |||
<Image | |||
alt="SonarQube logo" | |||
className="sw-mr-2" | |||
width={16} | |||
src={`${getBaseUrl()}/images/embed-doc/sq-icon.svg`} | |||
src="/images/embed-doc/sq-icon.svg" | |||
/> | |||
<span>Data Center Edition</span> | |||
</SubHeading> | |||
@@ -56,11 +57,11 @@ export default function EditionBox({ edition }: Readonly<Props>) { | |||
return ( | |||
<div> | |||
<SubHeading as="h2" id="enterprise-edition"> | |||
<img | |||
<Image | |||
alt="SonarQube logo" | |||
className="sw-mr-2" | |||
width={16} | |||
src={`${getBaseUrl()}/images/embed-doc/sq-icon.svg`} | |||
src="/images/embed-doc/sq-icon.svg" | |||
/> | |||
<span>Enterprise Edition</span> | |||
</SubHeading> | |||
@@ -83,11 +84,11 @@ export default function EditionBox({ edition }: Readonly<Props>) { | |||
return ( | |||
<div> | |||
<SubHeading as="h2" id="developer-edition"> | |||
<img | |||
<Image | |||
alt="SonarQube logo" | |||
className="sw-mr-2" | |||
width={16} | |||
src={`${getBaseUrl()}/images/embed-doc/sq-icon.svg`} | |||
src="/images/embed-doc/sq-icon.svg" | |||
/> | |||
<span>Developer Edition</span> | |||
</SubHeading> | |||
@@ -98,28 +99,18 @@ export default function EditionBox({ edition }: Readonly<Props>) { | |||
<UnorderedList className="sw-ml-8" ticks> | |||
<li> | |||
<span>PR / MR decoration & Quality Gate</span> | |||
<img | |||
alt="GitHub" | |||
className="sw-ml-2" | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
width={16} | |||
/> | |||
<img | |||
alt="GitLab" | |||
className="sw-ml-2" | |||
src={`${getBaseUrl()}/images/alm/gitlab.svg`} | |||
width={16} | |||
/> | |||
<img | |||
<Image alt="GitHub" className="sw-ml-2" src="/images/alm/github.svg" width={16} /> | |||
<Image alt="GitLab" className="sw-ml-2" src="/images/alm/gitlab.svg" width={16} /> | |||
<Image | |||
alt="Azure DevOps" | |||
className="sw-ml-2" | |||
src={`${getBaseUrl()}/images/alm/azure.svg`} | |||
src="/images/alm/azure.svg" | |||
width={16} | |||
/> | |||
<img | |||
<Image | |||
alt="Bitbucket" | |||
className="sw-ml-2" | |||
src={`${getBaseUrl()}/images/alm/bitbucket.svg`} | |||
src="/images/alm/bitbucket.svg" | |||
width={16} | |||
/> | |||
</li> |
@@ -17,13 +17,15 @@ | |||
* 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, Note, getTabPanelId } from 'design-system'; | |||
import { Link } from '@sonarsource/echoes-react'; | |||
import { Note, getTabPanelId } from 'design-system'; | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import DocumentationLink from '../../../components/common/DocumentationLink'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { getBranchLikeQuery } from '../../../helpers/branch-like'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { CodeScope, queryToSearch } from '../../../helpers/urls'; | |||
import { Branch } from '../../../types/branch-like'; | |||
import { ComponentQualifier } from '../../../types/component'; | |||
@@ -42,7 +44,10 @@ export default function MeasuresPanelNoNewCode(props: MeasuresPanelNoNewCodeProp | |||
const isApp = component.qualifier === ComponentQualifier.Application; | |||
const hasBadReferenceBranch = | |||
!isApp && !!period && !period.date && period.mode === NewCodeDefinitionType.ReferenceBranch; | |||
!isApp && | |||
!!period && | |||
period.date === '' && | |||
period.mode === NewCodeDefinitionType.ReferenceBranch; | |||
/* | |||
* If the period is "reference branch"-based, and if there's no date, it means | |||
* that we're not lacking a second analysis, but that we'll never have new code because the | |||
@@ -65,11 +70,11 @@ export default function MeasuresPanelNoNewCode(props: MeasuresPanelNoNewCodeProp | |||
id={getTabPanelId(CodeScope.New)} | |||
style={{ height: 500 }} | |||
> | |||
<img | |||
<Image | |||
alt="" /* Make screen readers ignore this image; it's purely eye candy. */ | |||
className="sw-mr-2" | |||
height={52} | |||
src={`${getBaseUrl()}/images/source-code.svg`} | |||
src="/images/source-code.svg" | |||
/> | |||
<Note as="div" className="sw-ml-4 sw-max-w-abs-500"> | |||
<p className="sw-mb-2 sw-mt-4">{translate(badExplanationKey)}</p> |
@@ -17,11 +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 { ButtonPrimary, FlagMessage, Title } from 'design-system'; | |||
import * as React from 'react'; | |||
import GitHubSynchronisationWarning from '../../../../app/components/GitHubSynchronisationWarning'; | |||
import { Image } from '../../../../components/common/Image'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../../helpers/system'; | |||
import { isDefined } from '../../../../helpers/types'; | |||
import { useGithubProvisioningEnabledQuery } from '../../../../queries/identity-provider/github'; | |||
import { isApplication, isPortfolioLike, isProject } from '../../../../types/component'; | |||
import { Component } from '../../../../types/types'; | |||
@@ -69,19 +71,19 @@ export default function PageHeader(props: Props) { | |||
<Title> | |||
{translate('permissions.page')} | |||
{provisionedByGitHub && ( | |||
<img | |||
<Image | |||
alt="github" | |||
className="sw-mx-2 sw-align-baseline" | |||
aria-label={translate('project_permission.github_managed')} | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
src="/images/alm/github.svg" | |||
/> | |||
)} | |||
</Title> | |||
<div> | |||
<p>{description}</p> | |||
{visibilityDescription && <p>{visibilityDescription}</p>} | |||
{isDefined(visibilityDescription) && <p>{visibilityDescription}</p>} | |||
{provisionedByGitHub && ( | |||
<> | |||
<p>{translate('roles.page.description.github')}</p> |
@@ -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 { Spinner } from '@sonarsource/echoes-react'; | |||
import { | |||
BasicSeparator, | |||
@@ -32,6 +33,7 @@ import { | |||
import { isEmpty } from 'lodash'; | |||
import * as React from 'react'; | |||
import { useState } from 'react'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { getBranchLikeQuery } from '../../../helpers/branch-like'; | |||
import { translate, translateWithParameters } from '../../../helpers/l10n'; | |||
import { localizeMetric } from '../../../helpers/measures'; | |||
@@ -103,7 +105,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { | |||
onClick={() => handleSelectType(BadgeType.measure)} | |||
selected={BadgeType.measure === selectedType} | |||
image={ | |||
<img | |||
<Image | |||
alt={translate('overview.badges', BadgeType.measure, 'alt')} | |||
src={getBadgeUrl(BadgeType.measure, fullBadgeOptions, token)} | |||
/> | |||
@@ -115,7 +117,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { | |||
onClick={() => handleSelectType(BadgeType.qualityGate)} | |||
selected={BadgeType.qualityGate === selectedType} | |||
image={ | |||
<img | |||
<Image | |||
alt={translate('overview.badges', BadgeType.qualityGate, 'alt')} | |||
src={getBadgeUrl(BadgeType.qualityGate, fullBadgeOptions, token)} | |||
width="128px" |
@@ -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 { ItemLink } from 'design-system'; | |||
import * as React from 'react'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { queryToSearch } from '../../../helpers/urls'; | |||
import { AlmKeys } from '../../../types/alm-settings'; | |||
@@ -40,12 +41,7 @@ export default function ProjectCreationMenuItem(props: ProjectCreationMenuItemPr | |||
to={{ pathname: '/projects/create', search: queryToSearch({ mode: alm }) }} | |||
> | |||
{alm !== 'manual' && ( | |||
<img | |||
alt={alm} | |||
className="sw-mr-2" | |||
width={16} | |||
src={`${getBaseUrl()}/images/alm/${almIcon}.svg`} | |||
/> | |||
<Image alt={alm} className="sw-mr-2" width={16} src={`/images/alm/${almIcon}.svg`} /> | |||
)} | |||
{translate('my_account.add_project', alm)} | |||
</ItemLink> |
@@ -17,11 +17,12 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { Note } from 'design-system'; | |||
import * as React from 'react'; | |||
import DocumentationLink from '../../../components/common/DocumentationLink'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
export interface EmptyHotspotsPageProps { | |||
filtered: boolean; | |||
@@ -45,13 +46,11 @@ export default function EmptyHotspotsPage(props: EmptyHotspotsPageProps) { | |||
return ( | |||
<div className="sw-items-center sw-justify-center sw-flex-col sw-flex sw-pt-16"> | |||
<img | |||
<Image | |||
alt={translate('hotspots.page')} | |||
className="sw-mt-8" | |||
height={100} | |||
src={`${getBaseUrl()}/images/${ | |||
filtered && !filterByFile ? 'filter-large' : 'hotspot-large' | |||
}.svg`} | |||
src={`/images/${filtered && !filterByFile ? 'filter-large' : 'hotspot-large'}.svg`} | |||
/> | |||
<h1 className="sw-mt-10 sw-body-sm-highlight"> | |||
{translate(`hotspots.${translationRoot}.title`)} |
@@ -17,22 +17,23 @@ | |||
* 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 { Spinner } from '@sonarsource/echoes-react'; | |||
import { | |||
Card, | |||
FlagMessage, | |||
PageContentFontWrapper, | |||
Spinner, | |||
Title, | |||
themeBorder, | |||
themeColor, | |||
} from 'design-system'; | |||
import * as React from 'react'; | |||
import { Helmet } from 'react-helmet-async'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { Location } from '../../../components/hoc/withRouter'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { sanitizeUserInput } from '../../../helpers/sanitize'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { getReturnUrl } from '../../../helpers/urls'; | |||
import { IdentityProvider } from '../../../types/types'; | |||
import LoginForm from './LoginForm'; | |||
@@ -54,17 +55,12 @@ export default function Login(props: Readonly<LoginProps>) { | |||
return ( | |||
<div className="sw-flex sw-flex-col sw-items-center" id="login_form"> | |||
<Helmet defer={false} title={translate('login.page')} /> | |||
<img alt="" className="sw-mt-32" src={`${getBaseUrl()}/images/sonar-logo-horizontal.png`} /> | |||
<Image alt="" className="sw-mt-32" src="/images/sonar-logo-horizontal.png" /> | |||
<Card className="sw-my-14 sw-p-0 sw-w-abs-350"> | |||
<PageContentFontWrapper className="sw-body-md sw-flex sw-flex-col sw-items-center sw-py-8 sw-px-4"> | |||
<img | |||
alt="" | |||
className="sw-mb-6" | |||
src={`${getBaseUrl()}/images/embed-doc/sq-icon.svg`} | |||
width={28} | |||
/> | |||
<Image alt="" className="sw-mb-6" src="/images/embed-doc/sq-icon.svg" width={28} /> | |||
<Title className="sw-mb-6">{translate('login.login_to_sonarqube')}</Title> | |||
<Spinner loading={loading}> | |||
<Spinner isLoading={loading}> | |||
<> | |||
{displayError && ( | |||
<FlagMessage className="sw-mb-6" variant="error"> |
@@ -17,11 +17,14 @@ | |||
* 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, SubTitle, ToggleButton } from 'design-system'; | |||
import { Link } from '@sonarsource/echoes-react'; | |||
import { FlagMessage, SubTitle, ToggleButton } from 'design-system'; | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { Image } from '../../../../components/common/Image'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../../helpers/system'; | |||
import { isDefined } from '../../../../helpers/types'; | |||
import { useGetValuesQuery } from '../../../../queries/settings'; | |||
import { | |||
AlmKeys, | |||
@@ -56,12 +59,7 @@ const tabs = [ | |||
{ | |||
label: ( | |||
<> | |||
<img | |||
alt="github" | |||
className="sw-mr-2" | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
/> | |||
<Image alt="github" className="sw-mr-2" height={16} src="/images/alm/github.svg" /> | |||
{translate('settings.almintegration.tab.github')} | |||
</> | |||
), | |||
@@ -70,12 +68,7 @@ const tabs = [ | |||
{ | |||
label: ( | |||
<> | |||
<img | |||
alt="bitbucket" | |||
className="sw-mr-2" | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/bitbucket.svg`} | |||
/> | |||
<Image alt="bitbucket" className="sw-mr-2" height={16} src="/images/alm/bitbucket.svg" /> | |||
{translate('settings.almintegration.tab.bitbucket')} | |||
</> | |||
), | |||
@@ -84,12 +77,7 @@ const tabs = [ | |||
{ | |||
label: ( | |||
<> | |||
<img | |||
alt="azure" | |||
className="sw-mr-2" | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/azure.svg`} | |||
/> | |||
<Image alt="azure" className="sw-mr-2" height={16} src="/images/alm/azure.svg" /> | |||
{translate('settings.almintegration.tab.azure')} | |||
</> | |||
), | |||
@@ -98,12 +86,7 @@ const tabs = [ | |||
{ | |||
label: ( | |||
<> | |||
<img | |||
alt="gitlab" | |||
className="sw-mr-2" | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/gitlab.svg`} | |||
/> | |||
<Image alt="gitlab" className="sw-mr-2" height={16} src="/images/alm/gitlab.svg" /> | |||
{translate('settings.almintegration.tab.gitlab')} | |||
</> | |||
), | |||
@@ -182,7 +165,7 @@ export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProp | |||
onUpdateDefinitions={props.onUpdateDefinitions} | |||
/> | |||
{definitionKeyForDeletion && ( | |||
{isDefined(definitionKeyForDeletion) && ( | |||
<DeleteModal | |||
id={definitionKeyForDeletion} | |||
onCancel={props.onCancelDelete} |
@@ -17,16 +17,18 @@ | |||
* 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 '@sonarsource/echoes-react'; | |||
import classNames from 'classnames'; | |||
import { FlagMessage, Link, SubTitle, ToggleButton, getTabId, getTabPanelId } from 'design-system'; | |||
import { FlagMessage, SubTitle, ToggleButton, getTabId, getTabPanelId } from 'design-system'; | |||
import * as React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { useSearchParams } from 'react-router-dom'; | |||
import withAvailableFeatures, { | |||
WithAvailableFeaturesProps, | |||
} from '../../../../app/components/available-features/withAvailableFeatures'; | |||
import { Image } from '../../../../components/common/Image'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../../helpers/system'; | |||
import { searchParamsToQuery } from '../../../../helpers/urls'; | |||
import { AlmKeys } from '../../../../types/alm-settings'; | |||
import { Feature } from '../../../../types/features'; | |||
@@ -54,9 +56,7 @@ export const DOCUMENTATION_LINK_SUFFIXES = { | |||
}; | |||
function renderDevOpsIcon(key: string) { | |||
return ( | |||
<img alt={key} className="sw-mr-2" height={16} src={`${getBaseUrl()}/images/alm/${key}.svg`} /> | |||
); | |||
return <Image alt={key} className="sw-mr-2" height={16} src={`/images/alm/${key}.svg`} />; | |||
} | |||
export function Authentication(props: Props & WithAvailableFeaturesProps) { |
@@ -21,8 +21,9 @@ | |||
import { Badge, Note, getTextColor } from 'design-system'; | |||
import * as React from 'react'; | |||
import { colors } from '../../../app/theme'; | |||
import { Image } from '../../../components/common/Image'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { isDefined } from '../../../helpers/types'; | |||
import { IdentityProvider, Provider } from '../../../types/types'; | |||
import { RestUserDetailed } from '../../../types/users'; | |||
@@ -39,7 +40,9 @@ export default function UserListItemIdentity({ identityProvider, user, managePro | |||
<strong className="it__user-name sw-body-sm-highlight">{user.name}</strong> | |||
<Note className="it__user-login">{user.login}</Note> | |||
</div> | |||
{user.email && <div className="it__user-email sw-mt-1">{user.email}</div>} | |||
{isDefined(user.email) && user.email !== '' && ( | |||
<div className="it__user-email sw-mt-1">{user.email}</div> | |||
)} | |||
{!user.local && user.externalProvider !== 'sonarqube' && ( | |||
<ExternalProvider identityProvider={identityProvider} user={user} /> | |||
)} | |||
@@ -68,11 +71,11 @@ export function ExternalProvider({ identityProvider, user }: Omit<Props, 'manage | |||
color: getTextColor(identityProvider.backgroundColor, colors.secondFontColor), | |||
}} | |||
> | |||
<img | |||
<Image | |||
alt={identityProvider.name} | |||
className="sw-mr-1" | |||
height="14" | |||
src={getBaseUrl() + identityProvider.iconPath} | |||
src={identityProvider.iconPath} | |||
width="14" | |||
/> | |||
{user.externalLogin} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* 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 * as React from 'react'; | |||
import { getBaseUrl } from '../../helpers/system'; | |||
export function Image(props: Readonly<JSX.IntrinsicElements['img']>) { | |||
const { alt, src: source, ...rest } = props; | |||
const baseUrl = getBaseUrl(); | |||
let src = source; | |||
if ( | |||
src !== undefined && | |||
!src.startsWith(baseUrl) && | |||
!src.startsWith('http') && | |||
!src.startsWith('data:') | |||
) { | |||
src = `${baseUrl}/${src}`.replace(/(?<!:)\/+/g, '/'); | |||
} | |||
// eslint-disable-next-line react/forbid-elements | |||
return <img alt={alt} src={src} {...rest} />; | |||
} |
@@ -17,11 +17,12 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { ItemDivider, ItemHeader, ItemLink, OpenNewTabIcon } from 'design-system'; | |||
import * as React from 'react'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { getBaseUrl } from '../../helpers/system'; | |||
import { SuggestionLink } from '../../types/types'; | |||
import { Image } from '../common/Image'; | |||
import { DocItemLink } from './DocItemLink'; | |||
import { SuggestionsContext } from './SuggestionsContext'; | |||
@@ -36,12 +37,12 @@ function IconLink({ | |||
}) { | |||
return ( | |||
<ItemLink to={link}> | |||
<img | |||
<Image | |||
alt={text} | |||
aria-hidden | |||
className="sw-mr-2" | |||
height="18" | |||
src={`${getBaseUrl()}/images/${icon}`} | |||
src={`/images/${icon}`} | |||
width="18" | |||
/> | |||
{text} |
@@ -17,13 +17,15 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { Badge, ContentCell, TableRowInteractive, UserGroupIcon } from 'design-system'; | |||
import * as React from 'react'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { isPermissionDefinitionGroup } from '../../helpers/permissions'; | |||
import { getBaseUrl } from '../../helpers/system'; | |||
import { isDefined } from '../../helpers/types'; | |||
import { Permissions } from '../../types/permissions'; | |||
import { PermissionDefinitions, PermissionGroup } from '../../types/types'; | |||
import { Image } from '../common/Image'; | |||
import PermissionCell from './PermissionCell'; | |||
import usePermissionChange from './usePermissionChange'; | |||
@@ -63,12 +65,12 @@ export default function GroupHolder(props: Props) { | |||
<strong>{group.name}</strong> | |||
</div> | |||
{disabled && ( | |||
<img | |||
<Image | |||
alt="github" | |||
className="sw-ml-2" | |||
aria-label={translate('project_permission.github_managed')} | |||
height={16} | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
src="/images/alm/github.svg" | |||
/> | |||
)} | |||
{group.name === ANYONE && ( | |||
@@ -77,7 +79,9 @@ export default function GroupHolder(props: Props) { | |||
</Badge> | |||
)} | |||
</div> | |||
{description && <div className="sw-mt-2 sw-whitespace-normal">{description}</div>} | |||
{isDefined(description) && ( | |||
<div className="sw-mt-2 sw-whitespace-normal">{description}</div> | |||
)} | |||
</div> | |||
</div> | |||
</ContentCell> |
@@ -17,12 +17,14 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { Avatar, ContentCell, Note, TableRowInteractive } from 'design-system'; | |||
import * as React from 'react'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { isPermissionDefinitionGroup } from '../../helpers/permissions'; | |||
import { getBaseUrl } from '../../helpers/system'; | |||
import { isDefined } from '../../helpers/types'; | |||
import { PermissionDefinitions, PermissionUser } from '../../types/types'; | |||
import { Image } from '../common/Image'; | |||
import PermissionCell from './PermissionCell'; | |||
import usePermissionChange from './usePermissionChange'; | |||
@@ -90,16 +92,16 @@ export default function UserHolder(props: Props) { | |||
<Note className="sw-ml-2">{user.login}</Note> | |||
</div> | |||
{disabled && ( | |||
<img | |||
<Image | |||
alt="github" | |||
className="sw-ml-2" | |||
height={16} | |||
aria-label={translate('project_permission.github_managed')} | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
src="/images/alm/github.svg" | |||
/> | |||
)} | |||
</div> | |||
{user.email && ( | |||
{isDefined(user.email) && ( | |||
<div className="sw-mt-2 sw-max-w-100 sw-text-ellipsis sw-whitespace-nowrap sw-overflow-hidden"> | |||
{user.email} | |||
</div> |
@@ -18,15 +18,13 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { LinkHighlight, LinkStandalone, Spinner } from '@sonarsource/echoes-react'; | |||
import { | |||
Breadcrumbs, | |||
FlagMessage, | |||
GreyCard, | |||
HoverLink, | |||
LightLabel, | |||
LightPrimary, | |||
Spinner, | |||
StandoutLink, | |||
SubTitle, | |||
Title, | |||
} from 'design-system'; | |||
@@ -34,13 +32,13 @@ import * as React from 'react'; | |||
import { AnalysisStatus } from '../../apps/overview/components/AnalysisStatus'; | |||
import { isMainBranch } from '../../helpers/branch-like'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { getBaseUrl } from '../../helpers/system'; | |||
import { getProjectTutorialLocation } from '../../helpers/urls'; | |||
import { useBranchesQuery } from '../../queries/branch'; | |||
import { AlmKeys, AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings'; | |||
import { MainBranch } from '../../types/branch-like'; | |||
import { Component } from '../../types/types'; | |||
import { LoggedInUser } from '../../types/users'; | |||
import { Image } from '../common/Image'; | |||
import AzurePipelinesTutorial from './azure-pipelines/AzurePipelinesTutorial'; | |||
import BitbucketPipelinesTutorial from './bitbucket-pipelines/BitbucketPipelinesTutorial'; | |||
import GitHubActionTutorial from './github-action/GitHubActionTutorial'; | |||
@@ -66,9 +64,11 @@ export interface TutorialSelectionRendererProps { | |||
function renderAlm(mode: TutorialModes, project: string, icon?: React.ReactNode) { | |||
return ( | |||
<GreyCard className="sw-col-span-4 sw-p-4"> | |||
<StandoutLink icon={icon} to={getProjectTutorialLocation(project, mode)}> | |||
{translate('onboarding.tutorial.choose_method', mode)} | |||
</StandoutLink> | |||
<LinkStandalone iconLeft={icon} to={getProjectTutorialLocation(project, mode)}> | |||
<span className={icon ? 'sw-ml-2' : ''}> | |||
{translate('onboarding.tutorial.choose_method', mode)} | |||
</span> | |||
</LinkStandalone> | |||
{mode === TutorialModes.Local && ( | |||
<LightLabel as="p" className="sw-mt-3"> | |||
@@ -157,10 +157,10 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
renderAlm( | |||
TutorialModes.Jenkins, | |||
component.key, | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/tutorials/jenkins.svg`} | |||
src="/images/tutorials/jenkins.svg" | |||
/>, | |||
)} | |||
@@ -168,10 +168,10 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
renderAlm( | |||
TutorialModes.GitHubActions, | |||
component.key, | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/tutorials/github-actions.svg`} | |||
src="/images/tutorials/github-actions.svg" | |||
/>, | |||
)} | |||
@@ -179,10 +179,10 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
renderAlm( | |||
TutorialModes.BitbucketPipelines, | |||
component.key, | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/alm/bitbucket.svg`} | |||
src="/images/alm/bitbucket.svg" | |||
/>, | |||
)} | |||
@@ -190,10 +190,10 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
renderAlm( | |||
TutorialModes.GitLabCI, | |||
component.key, | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/alm/gitlab.svg`} | |||
src="/images/alm/gitlab.svg" | |||
/>, | |||
)} | |||
@@ -201,10 +201,10 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
renderAlm( | |||
TutorialModes.AzurePipelines, | |||
component.key, | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-h-4 sw-w-4" | |||
src={`${getBaseUrl()}/images/tutorials/azure-pipelines.svg`} | |||
src="/images/tutorials/azure-pipelines.svg" | |||
/>, | |||
)} | |||
@@ -217,13 +217,19 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
{selectedTutorial && ( | |||
<Breadcrumbs className="sw-mb-3"> | |||
<HoverLink to={getProjectTutorialLocation(component.key)}> | |||
<LinkStandalone | |||
highlight={LinkHighlight.CurrentColor} | |||
to={getProjectTutorialLocation(component.key)} | |||
> | |||
{translate('onboarding.tutorial.breadcrumbs.home')} | |||
</HoverLink> | |||
</LinkStandalone> | |||
<HoverLink to={getProjectTutorialLocation(component.key, selectedTutorial)}> | |||
<LinkStandalone | |||
highlight={LinkHighlight.CurrentColor} | |||
to={getProjectTutorialLocation(component.key, selectedTutorial)} | |||
> | |||
{translate('onboarding.tutorial.breadcrumbs', selectedTutorial)} | |||
</HoverLink> | |||
</LinkStandalone> | |||
</Breadcrumbs> | |||
)} | |||
@@ -17,11 +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 { LinkStandalone } from '@sonarsource/echoes-react'; | |||
import classNames from 'classnames'; | |||
import { Card, LightLabel, StandoutLink } from 'design-system'; | |||
import { Card, LightLabel } from 'design-system'; | |||
import React from 'react'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { Image } from '../../common/Image'; | |||
import { OSs, TutorialModes } from '../types'; | |||
export interface GithubCFamilyExampleRepositoriesProps { | |||
@@ -58,15 +60,15 @@ export default function GithubCFamilyExampleRepositories( | |||
return ( | |||
<Card className={classNames('sw-p-4 sw-bg-inherit', className)}> | |||
<div> | |||
<img | |||
<Image | |||
alt="" // Should be ignored by screen readers | |||
className="sw-mr-2" | |||
height={20} | |||
src={`${getBaseUrl()}/images/alm/github.svg`} | |||
src="/images/alm/github.svg" | |||
/> | |||
<StandoutLink target="_blank" to={link}> | |||
<LinkStandalone target="_blank" to={link}> | |||
sonarsource-cfamily-examples | |||
</StandoutLink> | |||
</LinkStandalone> | |||
</div> | |||
<LightLabel as="p" className="sw-mt-4"> | |||
{translate('onboarding.tutorial.cfamily.examples_repositories_description')} |