aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionApp.tsx22
-rw-r--r--server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.tsx40
-rw-r--r--server/sonar-web/src/main/js/apps/projectNewCode/components/__tests__/ProjectNewCodeDefinitionApp-it.tsx5
-rw-r--r--server/sonar-web/src/main/js/components/new-code-definition/GlobalNewCodeDefinitionDescription.tsx18
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties1
5 files changed, 55 insertions, 31 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionApp.tsx b/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionApp.tsx
index 700a997d771..7f5dbca55af 100644
--- a/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionApp.tsx
+++ b/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionApp.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 { HeadingDark, LargeCenteredLayout, PageContentFontWrapper, Spinner } from 'design-system';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Helmet } from 'react-helmet-async';
@@ -61,6 +62,7 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
const [numberOfDays, setNumberOfDays] = useState(getNumberOfDaysDefaultValue());
const [referenceBranch, setReferenceBranch] = useState<string | undefined>(undefined);
const [specificAnalysis, setSpecificAnalysis] = useState<string | undefined>(undefined);
+
const [selectedNewCodeDefinitionType, setSelectedNewCodeDefinitionType] =
useState<NewCodeDefinitionType>(DEFAULT_NEW_CODE_DEFINITION_TYPE);
@@ -68,6 +70,7 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
data: globalNewCodeDefinition = { type: DEFAULT_NEW_CODE_DEFINITION_TYPE },
isLoading: isGlobalNCDLoading,
} = useNewCodeDefinitionQuery();
+
const { data: projectNewCodeDefinition, isLoading: isProjectNCDLoading } =
useNewCodeDefinitionQuery({
branchName: hasFeature(Feature.BranchSupport) ? undefined : branchLike?.name,
@@ -78,10 +81,12 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
const branchList = useMemo(() => {
return sortBranches(branchLikes.filter(isBranch));
}, [branchLikes]);
+
const isFormTouched = useMemo(() => {
if (isSpecificNewCodeDefinition === undefined) {
return false;
}
+
if (isSpecificNewCodeDefinition !== !projectNewCodeDefinition?.inherited) {
return true;
}
@@ -97,10 +102,13 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
switch (selectedNewCodeDefinitionType) {
case NewCodeDefinitionType.NumberOfDays:
return numberOfDays !== String(projectNewCodeDefinition?.value);
+
case NewCodeDefinitionType.ReferenceBranch:
return referenceBranch !== projectNewCodeDefinition?.value;
+
case NewCodeDefinitionType.SpecificAnalysis:
return specificAnalysis !== projectNewCodeDefinition?.value;
+
default:
return false;
}
@@ -121,15 +129,19 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
setIsSpecificNewCodeDefinition(
projectNewCodeDefinition === undefined ? undefined : !projectNewCodeDefinition.inherited,
);
+
setSelectedNewCodeDefinitionType(
projectNewCodeDefinition?.type ?? DEFAULT_NEW_CODE_DEFINITION_TYPE,
);
+
setNumberOfDays(getNumberOfDaysDefaultValue(globalNewCodeDefinition, projectNewCodeDefinition));
+
setReferenceBranch(
projectNewCodeDefinition?.type === NewCodeDefinitionType.ReferenceBranch
? projectNewCodeDefinition.value
: defaultReferenceBranch,
);
+
setSpecificAnalysis(
projectNewCodeDefinition?.type === NewCodeDefinitionType.SpecificAnalysis
? projectNewCodeDefinition.value
@@ -180,19 +192,16 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
return (
<LargeCenteredLayout id="new-code-rules-page">
<Suggestions suggestions="project_baseline" />
+
<Helmet defer={false} title={translate('project_baseline.page')} />
+
<PageContentFontWrapper className="sw-my-8 sw-body-sm">
<AppHeader canAdmin={!!appState.canAdmin} />
+
<Spinner loading={isLoading} />
{!isLoading && (
<div className="it__project-baseline">
- {branchSupportEnabled && (
- <HeadingDark as="h3" className="sw-mt-4">
- {translate('project_baseline.default_setting')}
- </HeadingDark>
- )}
-
{globalNewCodeDefinition && isSpecificNewCodeDefinition !== undefined && (
<ProjectNewCodeDefinitionSelector
analysis={specificAnalysis}
@@ -225,6 +234,7 @@ function ProjectNewCodeDefinitionApp(props: Readonly<ProjectNewCodeDefinitionApp
<HeadingDark as="h3" className="sw-mb-4">
{translate('project_baseline.configure_branches')}
</HeadingDark>
+
<BranchList
branchList={branchList}
component={component}
diff --git a/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.tsx b/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.tsx
index a3bbf303f1b..ced1729d12d 100644
--- a/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.tsx
+++ b/server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.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 { ButtonPrimary, ButtonSecondary, FlagMessage, RadioButton, Spinner } from 'design-system';
import { noop } from 'lodash';
import * as React from 'react';
@@ -34,26 +35,26 @@ import NewCodeDefinitionSettingReferenceBranch from './NewCodeDefinitionSettingR
export interface ProjectBaselineSelectorProps {
analysis?: string;
branch?: Branch;
- branchList: Branch[];
branchesEnabled?: boolean;
+ branchList: Branch[];
component: string;
- newCodeDefinitionType?: NewCodeDefinitionType;
- newCodeDefinitionValue?: string;
- previousNonCompliantValue?: string;
- projectNcdUpdatedAt?: number;
days: string;
globalNewCodeDefinition: NewCodeDefinition;
isChanged: boolean;
+ newCodeDefinitionType?: NewCodeDefinitionType;
+ newCodeDefinitionValue?: string;
onCancel: () => void;
onSelectDays: (value: string) => void;
onSelectReferenceBranch: (value: string) => void;
onSelectSetting: (value: NewCodeDefinitionType) => void;
onSubmit: (e: React.SyntheticEvent<HTMLFormElement>) => void;
onToggleSpecificSetting: (selection: boolean) => void;
+ overrideGlobalNewCodeDefinition: boolean;
+ previousNonCompliantValue?: string;
+ projectNcdUpdatedAt?: number;
referenceBranch?: string;
saving: boolean;
selectedNewCodeDefinitionType?: NewCodeDefinitionType;
- overrideGlobalNewCodeDefinition: boolean;
}
function branchToOption(b: Branch) {
@@ -66,17 +67,17 @@ export default function ProjectNewCodeDefinitionSelector(
const {
analysis,
branch,
- branchList,
branchesEnabled,
+ branchList,
component,
- newCodeDefinitionType,
- newCodeDefinitionValue,
- previousNonCompliantValue,
- projectNcdUpdatedAt,
days,
globalNewCodeDefinition,
isChanged,
+ newCodeDefinitionType,
+ newCodeDefinitionValue,
overrideGlobalNewCodeDefinition,
+ previousNonCompliantValue,
+ projectNcdUpdatedAt,
referenceBranch,
saving,
selectedNewCodeDefinitionType,
@@ -105,7 +106,7 @@ export default function ProjectNewCodeDefinitionSelector(
<span>{translate('project_baseline.global_setting')}</span>
</RadioButton>
- <div className="sw-ml-4">
+ <div className="sw-ml-6">
<GlobalNewCodeDefinitionDescription globalNcd={globalNewCodeDefinition} />
</div>
@@ -128,26 +129,28 @@ export default function ProjectNewCodeDefinitionSelector(
selectedNewCodeDefinitionType === NewCodeDefinitionType.PreviousVersion
}
/>
+
<NewCodeDefinitionDaysOption
- days={days}
currentDaysValue={
newCodeDefinitionType === NewCodeDefinitionType.NumberOfDays
? newCodeDefinitionValue
: undefined
}
- previousNonCompliantValue={previousNonCompliantValue}
- updatedAt={projectNcdUpdatedAt}
+ days={days}
disabled={!overrideGlobalNewCodeDefinition}
isChanged={isChanged}
isValid={isValid}
onChangeDays={props.onSelectDays}
onSelect={props.onSelectSetting}
+ previousNonCompliantValue={previousNonCompliantValue}
selected={
overrideGlobalNewCodeDefinition &&
selectedNewCodeDefinitionType === NewCodeDefinitionType.NumberOfDays
}
settingLevel={NewCodeDefinitionLevels.Project}
+ updatedAt={projectNcdUpdatedAt}
/>
+
{branchesEnabled && (
<NewCodeDefinitionSettingReferenceBranch
branchList={branchList.map(branchToOption)}
@@ -162,12 +165,13 @@ export default function ProjectNewCodeDefinitionSelector(
settingLevel={NewCodeDefinitionLevels.Project}
/>
)}
+
{!branchesEnabled && newCodeDefinitionType === NewCodeDefinitionType.SpecificAnalysis && (
<NewCodeDefinitionSettingAnalysis
- onSelect={noop}
analysis={analysis ?? ''}
branch={branch.name}
component={component}
+ onSelect={noop}
selected={
overrideGlobalNewCodeDefinition &&
selectedNewCodeDefinitionType === NewCodeDefinitionType.SpecificAnalysis
@@ -175,16 +179,19 @@ export default function ProjectNewCodeDefinitionSelector(
/>
)}
</div>
+
<div className="sw-mt-4">
{isChanged && (
<FlagMessage variant="info" className="sw-mb-4">
{translate('baseline.next_analysis_notice')}
</FlagMessage>
)}
+
<div className="sw-flex sw-items-center">
<ButtonPrimary type="submit" disabled={!isValid || !isChanged || saving}>
{translate('save')}
</ButtonPrimary>
+
<ButtonSecondary
className="sw-ml-2"
disabled={saving || !isChanged}
@@ -192,6 +199,7 @@ export default function ProjectNewCodeDefinitionSelector(
>
{translate('cancel')}
</ButtonSecondary>
+
<Spinner className="sw-ml-2" loading={saving} />
</div>
</div>
diff --git a/server/sonar-web/src/main/js/apps/projectNewCode/components/__tests__/ProjectNewCodeDefinitionApp-it.tsx b/server/sonar-web/src/main/js/apps/projectNewCode/components/__tests__/ProjectNewCodeDefinitionApp-it.tsx
index 67ca5267991..f15b977a390 100644
--- a/server/sonar-web/src/main/js/apps/projectNewCode/components/__tests__/ProjectNewCodeDefinitionApp-it.tsx
+++ b/server/sonar-web/src/main/js/apps/projectNewCode/components/__tests__/ProjectNewCodeDefinitionApp-it.tsx
@@ -66,8 +66,6 @@ it('renders correctly without branch support feature', async () => {
// User is not admin
expect(ui.generalSettingsLink.query()).not.toBeInTheDocument();
- // Specific branch setting is not rendered without feature branch
- expect(ui.branchListHeading.query()).not.toBeInTheDocument();
expect(ui.referenceBranchRadio.query()).not.toBeInTheDocument();
});
@@ -85,8 +83,6 @@ it('renders correctly with branch support feature', async () => {
// User is admin
expect(ui.generalSettingsLink.get()).toBeInTheDocument();
- // Specific branch setting is rendered with feature support branch
- expect(ui.branchListHeading.get()).toBeInTheDocument();
expect(ui.referenceBranchRadio.get()).toBeInTheDocument();
});
@@ -381,7 +377,6 @@ function getPageObjects() {
const ui = {
pageHeading: byRole('heading', { name: 'project_baseline.page' }),
branchTableHeading: byText('branch_list.branch'),
- branchListHeading: byRole('heading', { name: 'project_baseline.default_setting' }),
generalSettingsLink: byRole('link', { name: 'project_baseline.page.description2.link' }),
generalSettingRadio: byRole('radio', { name: 'project_baseline.global_setting' }),
specificSettingRadio: byRole('radio', { name: 'project_baseline.specific_setting' }),
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 1dca66f95d1..fcf2ab84676 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,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 { TextSubdued } from 'design-system';
import * as React from 'react';
import { translate, translateWithParameters } from '../../helpers/l10n';
import { NewCodeDefinition, NewCodeDefinitionType } from '../../types/new-code-definition';
@@ -29,11 +31,13 @@ export default function GlobalNewCodeDefinitionDescription({ globalNcd }: Readon
let setting: string;
let description: string;
let useCase: string;
+
if (globalNcd.type === NewCodeDefinitionType.NumberOfDays) {
setting = `${translate('new_code_definition.number_days')} (${translateWithParameters(
'duration.days',
globalNcd.value ?? '?',
)})`;
+
description = translate('new_code_definition.number_days.description');
useCase = translate('new_code_definition.number_days.usecase');
} else {
@@ -44,9 +48,17 @@ export default function GlobalNewCodeDefinitionDescription({ globalNcd }: Readon
return (
<div className="sw-flex sw-flex-col sw-gap-2 sw-max-w-[800px]">
- <strong className="sw-font-bold">{setting}</strong>
- <span>{description}</span>
- <span>{useCase}</span>
+ <TextSubdued>
+ <strong className="sw-font-bold">{setting}</strong>
+ </TextSubdued>
+
+ <TextSubdued>
+ <span>{description}</span>
+ </TextSubdued>
+
+ <TextSubdued>
+ <span>{useCase}</span>
+ </TextSubdued>
</div>
);
}
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 3f1fccb3184..ec24a2706a4 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -669,7 +669,6 @@ project_baseline.page.description=The new code definition sets which part of you
project_baseline.page.description2=You can adjust this setting globally in {link}.
project_baseline.page.description2.link=General Settings
project_baseline.page.question=Choose the baseline for new code for this project
-project_baseline.default_setting=Project setting
project_baseline.global_setting=Use the global setting
project_baseline.specific_setting=Define a specific setting for this project
project_baseline.configure_branches=Set a specific setting for a branch