Просмотр исходного кода

SONAR-20954 Improve project new code settings style

tags/10.5.0.89998
David Cho-Lerat 3 месяцев назад
Родитель
Сommit
b1a7fcdccc

+ 16
- 6
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}

+ 24
- 16
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>

+ 0
- 5
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' }),

+ 15
- 3
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>
);
}

+ 0
- 1
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

Загрузка…
Отмена
Сохранить