aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/projectNewCode
diff options
context:
space:
mode:
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>2024-01-31 14:49:53 +0100
committersonartech <sonartech@sonarsource.com>2024-02-08 20:02:46 +0000
commitb1a7fcdccc111af237b2e0ce206df150a12ed3c4 (patch)
treec82ccd9b8a3c4492f57e6cd17859d9bf4ba2ade2 /server/sonar-web/src/main/js/apps/projectNewCode
parent9514512f38767dc9c09e0346ff6a9580d07be83a (diff)
downloadsonarqube-b1a7fcdccc111af237b2e0ce206df150a12ed3c4.tar.gz
sonarqube-b1a7fcdccc111af237b2e0ce206df150a12ed3c4.zip
SONAR-20954 Improve project new code settings style
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projectNewCode')
-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
3 files changed, 40 insertions, 27 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' }),