From 3f570b118fa9a68469a34bb98f25367050f21025 Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Mon, 7 Aug 2023 17:34:23 +0200 Subject: [PATCH] SONAR-20086 Migrate new code period setup page --- .../src/components/SelectionCard.tsx | 6 +- .../src/components/input/InputField.tsx | 6 + .../design-system/src/theme/light.ts | 1 + .../apps/create/project/CreateProjectPage.tsx | 120 ++++------------- .../create/project/__tests__/Manual-it.tsx | 28 +--- .../components/NewCodeDefinitionSelection.tsx | 94 ++++++++++++++ .../BaselineSettingReferenceBranch.tsx | 7 +- .../components/BranchBaselineSettingModal.tsx | 2 +- .../components/ProjectBaselineSelector.tsx | 2 +- .../__tests__/ProjectBaselineApp-it.tsx | 2 +- .../components/__tests__/NewCodePeriod-it.tsx | 12 +- .../GlobalNewCodeDefinitionDescription.tsx | 59 ++++----- .../NewCodeDefinitionDaysOption.tsx | 53 ++++---- ...NewCodeDefinitionPreviousVersionOption.tsx | 11 +- .../NewCodeDefinitionSelector.tsx | 122 ++++++++++-------- .../resources/org/sonar/l10n/core.properties | 7 +- 16 files changed, 281 insertions(+), 251 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx diff --git a/server/sonar-web/design-system/src/components/SelectionCard.tsx b/server/sonar-web/design-system/src/components/SelectionCard.tsx index 9f14e1df853..088432fc90b 100644 --- a/server/sonar-web/design-system/src/components/SelectionCard.tsx +++ b/server/sonar-web/design-system/src/components/SelectionCard.tsx @@ -70,9 +70,10 @@ export function SelectionCard(props: SelectionCardProps) { }, className )} - onClick={isActionable && !disabled ? onClick : undefined} + onClick={isActionable && !disabled && !selected ? onClick : undefined} role={isActionable ? 'radio' : 'presentation'} tabIndex={disabled ? -1 : 0} + type="button" > {isActionable && ( @@ -110,6 +111,7 @@ const StyledButton = styled.button` background-color: ${themeColor('backgroundSecondary')}; border: ${themeBorder('default', 'selectionCardBorder')}; + color: inherit; &:focus { outline: none; @@ -139,6 +141,7 @@ const StyledButton = styled.button` ${tw`sw-cursor-not-allowed`} background-color: ${themeColor('selectionCardDisabled')}; + color: ${themeColor('selectionCardDisabledText')}; border: ${themeBorder('default', 'selectionCardBorderDisabled')}; } `; @@ -170,6 +173,7 @@ const StyledLabel = styled.label` ${tw`sw-body-sm-highlight`} color: ${themeColor('selectionCardHeader')}; + cursor: inherit; .disabled & { color: ${themeContrast('selectionCardDisabled')}; diff --git a/server/sonar-web/design-system/src/components/input/InputField.tsx b/server/sonar-web/design-system/src/components/input/InputField.tsx index ec3ddad5a4f..781c5243751 100644 --- a/server/sonar-web/design-system/src/components/input/InputField.tsx +++ b/server/sonar-web/design-system/src/components/input/InputField.tsx @@ -134,6 +134,12 @@ const StyledInput = styled.input` ${baseStyle} ${tw`sw-h-control`} } + + input[type='number']& { + ${getInputVariant} + ${baseStyle} + ${tw`sw-h-control`} + } `; const StyledTextArea = styled.textarea` diff --git a/server/sonar-web/design-system/src/theme/light.ts b/server/sonar-web/design-system/src/theme/light.ts index b9176bdac41..a8eaa23912e 100644 --- a/server/sonar-web/design-system/src/theme/light.ts +++ b/server/sonar-web/design-system/src/theme/light.ts @@ -505,6 +505,7 @@ export const lightTheme = { // selection card selectionCardHeader: secondary.darker, selectionCardDisabled: secondary.light, + selectionCardDisabledText: secondary.dark, selectionCardBorder: COLORS.blueGrey[100], selectionCardBorderHover: COLORS.indigo[200], selectionCardBorderSelected: primary.light, diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx index 51c69701112..664bc914ae6 100644 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx @@ -21,25 +21,17 @@ import classNames from 'classnames'; import { LargeCenteredLayout } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; -import { FormattedMessage } from 'react-intl'; import { getAlmSettings } from '../../../api/alm-settings'; import withAppStateContext from '../../../app/components/app-state/withAppStateContext'; import withAvailableFeatures, { WithAvailableFeaturesProps, } from '../../../app/components/available-features/withAvailableFeatures'; import A11ySkipTarget from '../../../components/a11y/A11ySkipTarget'; -import DocLink from '../../../components/common/DocLink'; -import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; -import NewCodeDefinitionSelector from '../../../components/new-code-definition/NewCodeDefinitionSelector'; -import DeferredSpinner from '../../../components/ui/DeferredSpinner'; -import { addGlobalSuccessMessage } from '../../../helpers/globalMessages'; import { translate } from '../../../helpers/l10n'; -import { getProjectUrl } from '../../../helpers/urls'; import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; import { AppState } from '../../../types/appstate'; import { Feature } from '../../../types/features'; -import { NewCodeDefinitiondWithCompliance } from '../../../types/new-code-definition'; import AlmBindingDefinitionForm from '../../settings/components/almIntegration/AlmBindingDefinitionForm'; import AzureProjectCreate from './Azure/AzureProjectCreate'; import BitbucketCloudProjectCreate from './BitbucketCloud/BitbucketCloudProjectCreate'; @@ -47,7 +39,7 @@ import BitbucketProjectCreate from './BitbucketServer/BitbucketProjectCreate'; import CreateProjectModeSelection from './CreateProjectModeSelection'; import GitHubProjectCreate from './Github/GitHubProjectCreate'; import GitlabProjectCreate from './Gitlab/GitlabProjectCreate'; -import CreateProjectPageHeader from './components/CreateProjectPageHeader'; +import NewCodeDefinitionSelection from './components/NewCodeDefinitionSelection'; import ManualProjectCreate from './manual/ManualProjectCreate'; import './style.css'; import { CreateProjectApiCallback, CreateProjectModes } from './types'; @@ -65,10 +57,7 @@ interface State { githubSettings: AlmSettingsInstance[]; gitlabSettings: AlmSettingsInstance[]; loading: boolean; - isProjectSetupDone: boolean; creatingAlmDefinition?: AlmKeys; - selectedNcd: NewCodeDefinitiondWithCompliance | null; - submitting: boolean; } const PROJECT_MODE_FOR_ALM_KEY = { @@ -90,13 +79,12 @@ export class CreateProjectPage extends React.PureComponent { + location.query.setncd = undefined; + router.replace(location); + }, 0); + } + } + fetchAlmBindings = () => { this.setState({ loading: true }); return getAlmSettings() @@ -138,22 +138,12 @@ export class CreateProjectPage extends React.PureComponent { - const { selectedNcd } = this.state; - if (this.createProjectFnRef && selectedNcd) { - this.setState({ submitting: true }); - - const { project } = await this.createProjectFnRef(selectedNcd.type, selectedNcd.value); - this.props.router.push(getProjectUrl(project.key)); - - addGlobalSuccessMessage(translate('onboarding.create_project.success')); - this.setState({ submitting: false }); - } - }; - handleProjectSetupDone = (createProject: CreateProjectApiCallback) => { + const { location, router } = this.props; this.createProjectFnRef = createProject; - this.setState({ isProjectSetupDone: true }); + + location.query.setncd = 'true'; + router.push(location); }; handleOnCancelCreation = () => { @@ -178,16 +168,6 @@ export class CreateProjectPage extends React.PureComponent { - this.setState({ - selectedNcd: ncd, - }); - }; - - handleGoBack = () => { - this.setState({ isProjectSetupDone: false }); - }; - renderProjectCreation(mode?: CreateProjectModes) { const { appState: { canAdmin }, @@ -292,61 +272,11 @@ export class CreateProjectPage extends React.PureComponent - - -

{translate('onboarding.create_project.new_code_definition')}

-

- {translate('onboarding.create_project.new_code_definition.description')} -

-

- {translate('onboarding.create_project.new_code_definition.description1')} -

- -

- - {translate('onboarding.create_project.new_code_definition.description2.link')} - - ), - }} - /> -

- - - -
- {translate('back')} - - {translate('onboarding.create_project.new_code_definition.create_project')} - - -
- - ); - } - render() { - const { location } = this.props; - const { creatingAlmDefinition, isProjectSetupDone } = this.state; + const { appState, location, router } = this.props; + const { creatingAlmDefinition } = this.state; const mode: CreateProjectModes | undefined = location.query?.mode; + const isProjectSetupDone = location.query?.setncd === 'true'; return ( @@ -358,7 +288,11 @@ export class CreateProjectPage extends React.PureComponent
- {this.renderNcdSelection()} +
{creatingAlmDefinition && ( diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/Manual-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/Manual-it.tsx index d1cc3348d03..5a3a2a1064c 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/Manual-it.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/Manual-it.tsx @@ -55,7 +55,6 @@ const ui = { }), projectNextButton: byRole('button', { name: 'next' }), newCodeDefinitionHeader: byText('onboarding.create_project.new_code_definition.title'), - newCodeDefinitionBackButton: byRole('button', { name: 'back' }), inheritGlobalNcdRadio: byRole('radio', { name: 'new_code_definition.global_setting' }), projectCreateButton: byRole('button', { name: 'onboarding.create_project.new_code_definition.create_project', @@ -70,7 +69,7 @@ const ui = { ncdOptionDaysRadio: byRole('radio', { name: /new_code_definition.number_days/, }), - ncdOptionDaysInput: byRole('textbox', { + ncdOptionDaysInput: byRole('spinbutton', { name: /new_code_definition.number_days.specify_days/, }), ncdOptionDaysInputError: byText('new_code_definition.number_days.invalid.1.90'), @@ -113,20 +112,12 @@ afterAll(() => { Object.defineProperty(window, 'location', { configurable: true, value: original }); }); -it('should fill form and move to NCD selection and back', async () => { +it('should fill form and move to NCD selection', async () => { const user = userEvent.setup(); renderCreateProject(); await fillFormAndNext('test', user); expect(ui.newCodeDefinitionHeader.get()).toBeInTheDocument(); - - expect(ui.newCodeDefinitionBackButton.get()).toBeInTheDocument(); - await user.click(ui.newCodeDefinitionBackButton.get()); - - expect(ui.manualProjectHeader.get()).toBeInTheDocument(); - - // TODO this must work at some point - // expect(ui.displayNameField.get()).toHaveValue('test'); }); it('should select the global NCD when it is compliant', async () => { @@ -204,7 +195,7 @@ it.each([ui.ncdOptionRefBranchRadio, ui.ncdOptionPreviousVersionRadio])( } ); -it('number of days should show error message if value is not a number', async () => { +it('number of days ignores non-numeric inputs', async () => { jest .mocked(getNewCodePeriod) .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '60' }); @@ -222,21 +213,14 @@ it('number of days should show error message if value is not a number', async () await user.click(ui.ncdOptionDaysRadio.get()); expect(ui.ncdOptionDaysInput.get()).toBeInTheDocument(); - expect(ui.ncdOptionDaysInput.get()).toHaveValue('60'); + expect(ui.ncdOptionDaysInput.get()).toHaveValue(60); expect(ui.projectCreateButton.get()).toBeEnabled(); await user.click(ui.ncdOptionDaysInput.get()); await user.keyboard('abc'); - expect(ui.ncdOptionDaysInputError.get()).toBeInTheDocument(); - expect(ui.projectCreateButton.get()).toBeDisabled(); - - await user.clear(ui.ncdOptionDaysInput.get()); - await user.click(ui.ncdOptionDaysInput.get()); - await user.keyboard('30'); - - expect(ui.ncdOptionDaysInputError.query()).not.toBeInTheDocument(); - expect(ui.projectCreateButton.get()).toBeEnabled(); + // it ignores the input and preserves its value + expect(ui.ncdOptionDaysInput.get()).toHaveValue(60); }); it('the project onboarding page should be displayed when the project is created', async () => { diff --git a/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx b/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx new file mode 100644 index 00000000000..f0678eb6757 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/create/project/components/NewCodeDefinitionSelection.tsx @@ -0,0 +1,94 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { ButtonPrimary, DeferredSpinner, Link, Title } from 'design-system'; +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { Router } from '../../../../components/hoc/withRouter'; +import NewCodeDefinitionSelector from '../../../../components/new-code-definition/NewCodeDefinitionSelector'; +import { useDocUrl } from '../../../../helpers/docs'; +import { addGlobalSuccessMessage } from '../../../../helpers/globalMessages'; +import { translate } from '../../../../helpers/l10n'; +import { getProjectUrl } from '../../../../helpers/urls'; +import { NewCodeDefinitiondWithCompliance } from '../../../../types/new-code-definition'; +import { CreateProjectApiCallback } from '../types'; + +interface Props { + canAdmin: boolean; + createProjectFnRef: CreateProjectApiCallback | null; + router: Router; +} + +export default function NewCodeDefinitionSelection(props: Props) { + const { canAdmin, createProjectFnRef, router } = props; + + const [submitting, setSubmitting] = React.useState(false); + const [selectedDefinition, selectDefinition] = React.useState(); + + const getDocUrl = useDocUrl(); + + const handleProjectCreation = React.useCallback(async () => { + if (createProjectFnRef && selectedDefinition) { + setSubmitting(true); + const { project } = await createProjectFnRef( + selectedDefinition.type, + selectedDefinition.value + ); + setSubmitting(false); + router.push(getProjectUrl(project.key)); + + addGlobalSuccessMessage(translate('onboarding.create_project.success')); + } + }, [createProjectFnRef, router, selectedDefinition]); + + return ( +
+ + {translate('onboarding.create_project.new_code_definition.title')} + + +

+ + {translate('onboarding.create_project.new_code_definition.description.link')} + + ), + }} + /> +

+ + + +
+ + {translate('onboarding.create_project.new_code_definition.create_project')} + + +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingReferenceBranch.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingReferenceBranch.tsx index 4e9b28484af..59f65f0e004 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingReferenceBranch.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingReferenceBranch.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 { SelectionCard } from 'design-system'; import * as React from 'react'; import { components, OptionProps } from 'react-select'; -import RadioCard from '../../../components/controls/RadioCard'; import Select from '../../../components/controls/Select'; import Tooltip from '../../../components/controls/Tooltip'; import AlertErrorIcon from '../../../components/icons/AlertErrorIcon'; @@ -94,8 +94,7 @@ export default function BaselineSettingReferenceBranch(props: BaselineSettingRef }; return ( - props.onSelect(NewCodeDefinitionType.ReferenceBranch)} @@ -132,6 +131,6 @@ export default function BaselineSettingReferenceBranch(props: BaselineSettingRef )} - + ); } diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx index e80de3b008c..5d14760a99b 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BranchBaselineSettingModal.tsx @@ -179,7 +179,7 @@ export default class BranchBaselineSettingModal extends React.PureComponent -
+
-
+
{ await user.click(ui.daysNumberRadio.get()); expect(ui.daysNumberRadio.get()).toBeChecked(); - // Save should be disabled for zero or NaN - expect(ui.daysInput.get()).toHaveValue('30'); + // Save should be disabled for zero + expect(ui.daysInput.get()).toHaveValue(30); await user.clear(ui.daysInput.get()); await user.type(ui.daysInput.get(), '0'); expect(await ui.saveButton.find()).toBeDisabled(); + + // Save should not appear at all for NaN await user.clear(ui.daysInput.get()); await user.type(ui.daysInput.get(), 'asdas'); - expect(ui.saveButton.get()).toBeDisabled(); + expect(ui.saveButton.query()).toBeDisabled(); // Save enabled for valid days number await user.clear(ui.daysInput.get()); @@ -98,7 +100,7 @@ it('renders and behaves properly when the current value is not compliant', async expect(await ui.newCodeTitle.find()).toBeInTheDocument(); expect(ui.daysNumberRadio.get()).toBeChecked(); - expect(ui.daysInput.get()).toHaveValue('91'); + expect(ui.daysInput.get()).toHaveValue(91); // Should warn about non compliant value expect(screen.getByText('baseline.number_days.compliance_warning.title')).toBeInTheDocument(); diff --git a/server/sonar-web/src/main/js/components/new-code-definition/GlobalNewCodeDefinitionDescription.tsx b/server/sonar-web/src/main/js/components/new-code-definition/GlobalNewCodeDefinitionDescription.tsx index b8d3ad3898c..133e3e0b711 100644 --- a/server/sonar-web/src/main/js/components/new-code-definition/GlobalNewCodeDefinitionDescription.tsx +++ b/server/sonar-web/src/main/js/components/new-code-definition/GlobalNewCodeDefinitionDescription.tsx @@ -17,12 +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 { FlagMessage, Link } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { NewCodeDefinition, NewCodeDefinitionType } from '../../types/new-code-definition'; -import Link from '../common/Link'; -import { Alert } from '../ui/Alert'; interface Props { globalNcd: NewCodeDefinition; @@ -54,7 +53,7 @@ export default function GlobalNewCodeDefinitionDescription({ return ( <>
- {setting} + {setting} {isGlobalNcdCompliant && ( <> {description} @@ -63,32 +62,34 @@ export default function GlobalNewCodeDefinitionDescription({ )}
{!isGlobalNcdCompliant && ( - -

- {translate('new_code_definition.compliance.warning.title.global')} -

-

- {canAdmin ? ( - - {translate( - 'new_code_definition.compliance.warning.explanation.action.admin.link' - )} - - ), - }} - /> - ) : ( - translate('new_code_definition.compliance.warning.explanation') - )} -

-
+ + +

+ {translate('new_code_definition.compliance.warning.title.global')} +

+

+ {canAdmin ? ( + + {translate( + 'new_code_definition.compliance.warning.explanation.action.admin.link' + )} + + ), + }} + /> + ) : ( + translate('new_code_definition.compliance.warning.explanation') + )} +

+
+
)} ); diff --git a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionDaysOption.tsx b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionDaysOption.tsx index a3b52e9f642..126ae94e93c 100644 --- a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionDaysOption.tsx +++ b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionDaysOption.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 { FlagErrorIcon, InputField, Note, SelectionCard } from 'design-system'; import * as React from 'react'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { @@ -24,9 +25,6 @@ import { NUMBER_OF_DAYS_MIN_VALUE, } from '../../helpers/new-code-definition'; import { NewCodeDefinitionType } from '../../types/new-code-definition'; -import RadioCard from '../controls/RadioCard'; -import ValidationInput, { ValidationInputErrorPlacement } from '../controls/ValidationInput'; -import MandatoryFieldsExplanation from '../ui/MandatoryFieldsExplanation'; export interface Props { className?: string; @@ -43,8 +41,7 @@ export default function NewCodeDefinitionDaysOption(props: Props) { const { className, days, disabled, isChanged, isValid, onChangeDays, onSelect, selected } = props; return ( - onSelect(NewCodeDefinitionType.NumberOfDays)} @@ -53,36 +50,36 @@ export default function NewCodeDefinitionDaysOption(props: Props) { > <>
-

{translate('new_code_definition.number_days.description')}

-

{translate('new_code_definition.number_days.usecase')}

+

{translate('new_code_definition.number_days.description')}

+

{translate('new_code_definition.number_days.usecase')}

{selected && ( - <> - - - + + + {translateWithParameters( 'new_code_definition.number_days.invalid', NUMBER_OF_DAYS_MIN_VALUE, NUMBER_OF_DAYS_MAX_VALUE )} - label={translate('new_code_definition.number_days.specify_days')} - required - > - onChangeDays(e.currentTarget.value)} - type="text" - value={days} - /> - - + +
)} - + ); } diff --git a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionPreviousVersionOption.tsx b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionPreviousVersionOption.tsx index 60141f592e7..28aed689648 100644 --- a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionPreviousVersionOption.tsx +++ b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionPreviousVersionOption.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 { SelectionCard } from 'design-system'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; import { NewCodeDefinitionType } from '../../types/new-code-definition'; -import RadioCard from '../controls/RadioCard'; interface Props { disabled?: boolean; @@ -36,8 +36,7 @@ export default function NewCodeDefinitionPreviousVersionOption({ selected, }: Props) { return ( - onSelect(NewCodeDefinitionType.PreviousVersion)} selected={selected} @@ -47,9 +46,9 @@ export default function NewCodeDefinitionPreviousVersionOption({ } >
-

{translate('new_code_definition.previous_version.description')}

-

{translate('new_code_definition.previous_version.usecase')}

+

{translate('new_code_definition.previous_version.description')}

+

{translate('new_code_definition.previous_version.usecase')}

-
+ ); } diff --git a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionSelector.tsx b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionSelector.tsx index 2f4660713f6..47dd557065b 100644 --- a/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionSelector.tsx +++ b/server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionSelector.tsx @@ -17,7 +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 { RadioButton } from 'design-system/lib'; +import styled from '@emotion/styled'; +import { + FlagMessage, + PageContentFontWrapper, + RadioButton, + SelectionCard, + themeColor, +} from 'design-system'; import { noop } from 'lodash'; import * as React from 'react'; import { getNewCodePeriod } from '../../api/newCodePeriod'; @@ -31,9 +38,7 @@ import { NewCodeDefinitionType, NewCodeDefinitiondWithCompliance, } from '../../types/new-code-definition'; -import RadioCard from '../controls/RadioCard'; import Tooltip from '../controls/Tooltip'; -import { Alert } from '../ui/Alert'; import GlobalNewCodeDefinitionDescription from './GlobalNewCodeDefinitionDescription'; import NewCodeDefinitionDaysOption from './NewCodeDefinitionDaysOption'; import NewCodeDefinitionPreviousVersionOption from './NewCodeDefinitionPreviousVersionOption'; @@ -99,15 +104,16 @@ export default function NewCodeDefinitionSelector(props: Props) { }, [selectedNcdType, days, isCompliant, onNcdChanged]); return ( - <> +

- {translate('new_code_definition.question')} + + {translate('new_code_definition.question')} +

-
+
handleNcdChanged(NewCodeDefinitionType.Inherited)} value="general" @@ -119,11 +125,16 @@ export default function NewCodeDefinitionSelector(props: Props) { : translate('new_code_definition.compliance.warning.title.global') } > - {translate('new_code_definition.global_setting')} + + {translate('new_code_definition.global_setting')} + -
+ {globalNcd && ( )} -
+ handleNcdChanged(NewCodeDefinitionType.PreviousVersion)} value="specific" > @@ -144,51 +155,52 @@ export default function NewCodeDefinitionSelector(props: Props) {
-
-
- - - - - + + + + + handleNcdChanged(NewCodeDefinitionType.ReferenceBranch)} + selected={selectedNcdType === NewCodeDefinitionType.ReferenceBranch} + title={translate('new_code_definition.reference_branch')} + > +
+

+ {translate('new_code_definition.reference_branch.description')} +

+

{translate('new_code_definition.reference_branch.usecase')}

+ {selectedNcdType === NewCodeDefinitionType.ReferenceBranch && ( + + {translate('new_code_definition.reference_branch.notice')} + )} - onClick={() => handleNcdChanged(NewCodeDefinitionType.ReferenceBranch)} - selected={selectedNcdType === NewCodeDefinitionType.ReferenceBranch} - title={translate('new_code_definition.reference_branch')} - > -
-

- {translate('new_code_definition.reference_branch.description')} -

-

{translate('new_code_definition.reference_branch.usecase')}

- {selectedNcdType === NewCodeDefinitionType.ReferenceBranch && ( - - {translate('new_code_definition.reference_branch.notice')} - - )} -
- -
+
+
- + ); } + +const StyledGlobalSettingWrapper = styled.div<{ selected: boolean }>` + color: ${({ selected }) => (selected ? 'inherit' : themeColor('selectionCardDisabledText'))}; +`; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index e8dab691458..2f8553b6a2c 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3977,11 +3977,8 @@ onboarding.create_project.gitlab.no_projects=No projects could be fetched from G onboarding.create_project.gitlab.link=See on GitLab onboarding.create_project.new_code_definition.title=Set up project for Clean as You Code -onboarding.create_project.new_code_definition=New Code -onboarding.create_project.new_code_definition.description=The new code definition sets which part of your code will be considered new code. -onboarding.create_project.new_code_definition.description1=This helps you focus attention on the most recent changes to your project, enabling you to follow the Clean as You Code methodology. -onboarding.create_project.new_code_definition.description2=Learn more: {link} -onboarding.create_project.new_code_definition.description2.link=Defining New Code +onboarding.create_project.new_code_definition.description=The new code definition sets which part of your code will be considered new code. This helps you focus attention on the most recent changes to your project, enabling you to follow the Clean as You Code methodology. Learn more: {link} +onboarding.create_project.new_code_definition.description.link=Defining New Code onboarding.create_project.new_code_definition.create_project=Create project onboarding.create_project.success=Congratulations! Your project has been created. -- 2.39.5