Ver código fonte

Fix conflicts after rebase

tags/8.0
Jacek 4 anos atrás
pai
commit
e8f1a84869
20 arquivos alterados com 482 adições e 157 exclusões
  1. 0
    0
      server/sonar-db-dao/src/testFixtures/java/org/sonar/db/newcodeperiod/NewCodePeriodDbTester.java
  2. 1
    4
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx
  3. 0
    9
      server/sonar-web/src/main/js/apps/projectBaseline/__tests__/App-test.tsx
  4. 25
    6
      server/sonar-web/src/main/js/apps/projectBaseline/__tests__/ProjectBaselineSelector-test.tsx
  5. 1
    14
      server/sonar-web/src/main/js/apps/projectBaseline/__tests__/__snapshots__/BranchList-test.tsx.snap
  6. 166
    4
      server/sonar-web/src/main/js/apps/projectBaseline/__tests__/__snapshots__/ProjectBaselineSelector-test.tsx.snap
  7. 76
    1
      server/sonar-web/src/main/js/apps/projectBaseline/__tests__/utils-test.ts
  8. 55
    65
      server/sonar-web/src/main/js/apps/projectBaseline/components/App.tsx
  9. 3
    1
      server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingAnalysis.tsx
  10. 3
    1
      server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx
  11. 4
    1
      server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingPreviousVersion.tsx
  12. 30
    14
      server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisList.tsx
  13. 1
    7
      server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx
  14. 59
    9
      server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx
  15. 16
    1
      server/sonar-web/src/main/js/apps/projectBaseline/styles.css
  16. 20
    5
      server/sonar-web/src/main/js/apps/projectBaseline/utils.ts
  17. 11
    1
      server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx
  18. 6
    9
      server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts
  19. 1
    1
      server/sonar-web/src/main/js/helpers/periods.ts
  20. 4
    4
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDbTester.java → server/sonar-db-dao/src/testFixtures/java/org/sonar/db/newcodeperiod/NewCodePeriodDbTester.java Ver arquivo


+ 1
- 4
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx Ver arquivo

@@ -157,10 +157,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro
};

shouldRenderBaselineMarker(analysis: T.ParsedAnalysis): boolean {
return Boolean(
analysis.manualNewCodePeriodBaseline ||
(this.props.leakPeriodDate && isEqual(this.props.leakPeriodDate, analysis.date))
);
return Boolean(this.props.leakPeriodDate && isEqual(this.props.leakPeriodDate, analysis.date));
}

renderAnalysis(analysis: T.ParsedAnalysis) {

+ 0
- 9
server/sonar-web/src/main/js/apps/projectBaseline/__tests__/App-test.tsx Ver arquivo

@@ -40,15 +40,6 @@ it('should not display reset button if project setting is not set', () => {
expect(wrapper.find('Button')).toHaveLength(0);
});

it('should display reset button if project setting is set', async () => {
(getNewCodePeriod as jest.Mock).mockResolvedValue({ type: 'NUMBER_OF_DAYS', value: '27' });

const wrapper = shallowRender();

await waitAndUpdate(wrapper);
expect(wrapper.find('Button')).toHaveLength(1);
});

it('should reset the setting correctly', async () => {
const wrapper = shallowRender();
await waitAndUpdate(wrapper);

+ 25
- 6
server/sonar-web/src/main/js/apps/projectBaseline/__tests__/ProjectBaselineSelector-test.tsx Ver arquivo

@@ -25,13 +25,22 @@ import ProjectBaselineSelector, {

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot();
expect(
shallowRender({
branchesEnabled: false,
generalSetting: { type: 'NUMBER_OF_DAYS', value: '23' }
})
).toMatchSnapshot();
expect(
shallowRender({ branchesEnabled: false, generalSetting: { type: 'NUMBER_OF_DAYS', value: '' } })
).toMatchSnapshot();
});

it('should not show save button when unchanged', () => {
const wrapper = shallowRender({
currentSetting: 'PREVIOUS_VERSION',
selected: 'PREVIOUS_VERSION'
selected: 'PREVIOUS_VERSION',
overrideGeneralSetting: true
});
expect(
wrapper
@@ -42,7 +51,11 @@ it('should not show save button when unchanged', () => {
});

it('should show save button when changed', () => {
const wrapper = shallowRender({ currentSetting: 'PREVIOUS_VERSION', selected: 'NUMBER_OF_DAYS' });
const wrapper = shallowRender({
currentSetting: 'PREVIOUS_VERSION',
selected: 'NUMBER_OF_DAYS',
overrideGeneralSetting: true
});
expect(wrapper.find('SubmitButton')).toHaveLength(1);
});

@@ -51,7 +64,8 @@ it('should show save button when value changed', () => {
currentSetting: 'NUMBER_OF_DAYS',
currentSettingValue: '23',
days: '25',
selected: 'NUMBER_OF_DAYS'
selected: 'NUMBER_OF_DAYS',
overrideGeneralSetting: true
});
expect(wrapper.find('SubmitButton')).toHaveLength(1);
});
@@ -61,7 +75,8 @@ it('should disable the save button when saving', () => {
currentSetting: 'NUMBER_OF_DAYS',
currentSettingValue: '25',
saving: true,
selected: 'PREVIOUS_VERSION'
selected: 'PREVIOUS_VERSION',
overrideGeneralSetting: true
});

expect(
@@ -76,7 +91,8 @@ it('should disable the save button when date is invalid', () => {
const wrapper = shallowRender({
currentSetting: 'PREVIOUS_VERSION',
days: 'hello',
selected: 'NUMBER_OF_DAYS'
selected: 'NUMBER_OF_DAYS',
overrideGeneralSetting: true
});

expect(
@@ -93,10 +109,13 @@ function shallowRender(props: Partial<ProjectBaselineSelectorProps> = {}) {
branchesEnabled={true}
component=""
days="12"
generalSetting={{}}
onSelectAnalysis={jest.fn()}
onSelectDays={jest.fn()}
onSelectSetting={jest.fn()}
onSubmit={jest.fn()}
onToggleSpecificSetting={jest.fn()}
overrideGeneralSetting={false}
saving={false}
{...props}
/>

+ 1
- 14
server/sonar-web/src/main/js/apps/projectBaseline/__tests__/__snapshots__/BranchList-test.tsx.snap Ver arquivo

@@ -9,11 +9,6 @@ exports[`should render correctly 1`] = `
<tr>
<th>
branch_list.branch
</th>
<th
className="thin"
>
</th>
<th
className="thin nowrap huge-spacer-right"
@@ -56,7 +51,6 @@ exports[`should render correctly 1`] = `
branches.main_branch
</div>
</td>
<td />
<td
className="huge-spacer-right nowrap"
>
@@ -98,17 +92,10 @@ exports[`should render correctly 1`] = `
/>
branch-6.7
</td>
<td>
<span
className="badge badge-info"
>
default
</span>
</td>
<td
className="huge-spacer-right nowrap"
>
baseline.previous_version
branch_list.default_setting
</td>
<td
className="text-right"

+ 166
- 4
server/sonar-web/src/main/js/apps/projectBaseline/__tests__/__snapshots__/ProjectBaselineSelector-test.tsx.snap Ver arquivo

@@ -6,20 +6,56 @@ exports[`should render correctly 1`] = `
onSubmit={[MockFunction]}
>
<div
className="branch-baseline-setting-modal"
className="big-spacer-top spacer-bottom"
role="radiogroup"
>
<Radio
checked={true}
className="big-spacer-bottom"
onCheck={[Function]}
value="general"
>
project_baseline.general_setting
</Radio>
<div
className="big-spacer-left"
>
<div
className="general-setting"
>
<strong>
baseline.previous_version
</strong>
:
baseline.previous_version.description
</div>
</div>
<Radio
checked={false}
className="huge-spacer-top"
onCheck={[Function]}
value="specific"
>
project_baseline.specific_setting
</Radio>
</div>
<div
className="big-spacer-left big-spacer-right branch-baseline-setting-modal"
>
<div
className="display-flex-row big-spacer-bottom"
role="radiogroup"
>
<BaselineSettingPreviousVersion
disabled={true}
onSelect={[MockFunction]}
selected={false}
/>
<BaselineSettingDays
days="12"
disabled={true}
isChanged={false}
isValid={false}
isValid={true}
onChangeDays={[MockFunction]}
onSelect={[MockFunction]}
selected={false}
@@ -54,25 +90,151 @@ exports[`should render correctly 2`] = `
onSubmit={[MockFunction]}
>
<div
className="branch-baseline-setting-modal"
className="big-spacer-top spacer-bottom"
role="radiogroup"
>
<Radio
checked={true}
className="big-spacer-bottom"
onCheck={[Function]}
value="general"
>
project_baseline.general_setting
</Radio>
<div
className="big-spacer-left"
>
<div
className="general-setting"
>
<strong>
baseline.number_days (duration.days.23)
</strong>
:
baseline.number_days.description
</div>
</div>
<Radio
checked={false}
className="huge-spacer-top"
onCheck={[Function]}
value="specific"
>
project_baseline.specific_setting
</Radio>
</div>
<div
className="big-spacer-left big-spacer-right branch-baseline-setting-modal"
>
<div
className="display-flex-row big-spacer-bottom"
role="radiogroup"
>
<BaselineSettingPreviousVersion
disabled={true}
onSelect={[MockFunction]}
selected={false}
/>
<BaselineSettingDays
days="12"
disabled={true}
isChanged={false}
isValid={true}
onChangeDays={[MockFunction]}
onSelect={[MockFunction]}
selected={false}
/>
<BaselineSettingAnalysis
disabled={true}
onSelect={[MockFunction]}
selected={false}
/>
</div>
</div>
<div
className="big-spacer-top invisible"
>
<p
className="spacer-bottom"
>
baseline.next_analysis_notice
</p>
<DeferredSpinner
className="spacer-right"
loading={false}
timeout={100}
/>
<SubmitButton
disabled={true}
>
save
</SubmitButton>
</div>
</form>
`;

exports[`should render correctly 3`] = `
<form
className="project-baseline-selector"
onSubmit={[MockFunction]}
>
<div
className="big-spacer-top spacer-bottom"
role="radiogroup"
>
<Radio
checked={true}
className="big-spacer-bottom"
onCheck={[Function]}
value="general"
>
project_baseline.general_setting
</Radio>
<div
className="big-spacer-left"
>
<div
className="general-setting"
>
<strong>
baseline.number_days (duration.days.?)
</strong>
:
baseline.number_days.description
</div>
</div>
<Radio
checked={false}
className="huge-spacer-top"
onCheck={[Function]}
value="specific"
>
project_baseline.specific_setting
</Radio>
</div>
<div
className="big-spacer-left big-spacer-right branch-baseline-setting-modal"
>
<div
className="display-flex-row big-spacer-bottom"
role="radiogroup"
>
<BaselineSettingPreviousVersion
disabled={true}
onSelect={[MockFunction]}
selected={false}
/>
<BaselineSettingDays
days="12"
disabled={true}
isChanged={false}
isValid={false}
isValid={true}
onChangeDays={[MockFunction]}
onSelect={[MockFunction]}
selected={false}
/>
<BaselineSettingAnalysis
disabled={true}
onSelect={[MockFunction]}
selected={false}
/>

+ 76
- 1
server/sonar-web/src/main/js/apps/projectBaseline/__tests__/utils-test.ts Ver arquivo

@@ -17,7 +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 { getSettingValue } from '../utils';
import { getSettingValue, validateSetting } from '../utils';

describe('getSettingValue', () => {
it('should work for Days', () => {
@@ -38,3 +38,78 @@ describe('getSettingValue', () => {
).toBeUndefined();
});
});

describe('validateSettings', () => {
it('should validate at branch level', () => {
expect(validateSetting({ days: '' })).toEqual({ isChanged: false, isValid: false });
expect(
validateSetting({
currentSetting: 'PREVIOUS_VERSION',
days: '12',
selected: 'NUMBER_OF_DAYS'
})
).toEqual({ isChanged: true, isValid: true });
expect(
validateSetting({
currentSetting: 'PREVIOUS_VERSION',
days: 'nope',
selected: 'NUMBER_OF_DAYS'
})
).toEqual({ isChanged: true, isValid: false });
expect(
validateSetting({
currentSetting: 'NUMBER_OF_DAYS',
currentSettingValue: '15',
days: '15',
selected: 'NUMBER_OF_DAYS'
})
).toEqual({ isChanged: false, isValid: true });
expect(
validateSetting({
currentSetting: 'NUMBER_OF_DAYS',
currentSettingValue: '15',
days: '13',
selected: 'NUMBER_OF_DAYS'
})
).toEqual({ isChanged: true, isValid: true });
expect(
validateSetting({
analysis: 'analysis1',
currentSetting: 'SPECIFIC_ANALYSIS',
currentSettingValue: 'analysis1',
days: '',
selected: 'SPECIFIC_ANALYSIS'
})
).toEqual({ isChanged: false, isValid: true });
expect(
validateSetting({
analysis: 'analysis2',
currentSetting: 'SPECIFIC_ANALYSIS',
currentSettingValue: 'analysis1',
days: '',
selected: 'SPECIFIC_ANALYSIS'
})
).toEqual({ isChanged: true, isValid: true });
});

it('should validate at project level', () => {
expect(validateSetting({ days: '', overrideGeneralSetting: false })).toEqual({
isChanged: false,
isValid: true
});
expect(validateSetting({ days: '', overrideGeneralSetting: true })).toEqual({
isChanged: true,
isValid: false
});
expect(
validateSetting({
currentSetting: 'PREVIOUS_VERSION',
days: '',
overrideGeneralSetting: false
})
).toEqual({
isChanged: true,
isValid: true
});
});
});

+ 55
- 65
server/sonar-web/src/main/js/apps/projectBaseline/components/App.tsx Ver arquivo

@@ -20,9 +20,8 @@
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import { Button } from 'sonar-ui-common/components/controls/buttons';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getNewCodePeriod, resetNewCodePeriod, setNewCodePeriod } from '../../../api/newCodePeriod';
import '../styles.css';
import { getSettingValue } from '../utils';
@@ -43,6 +42,7 @@ interface State {
days: string;
generalSetting?: T.NewCodePeriod;
loading: boolean;
overrideGeneralSetting?: boolean;
saving: boolean;
selected?: T.NewCodePeriodSettingType;
}
@@ -75,13 +75,17 @@ export default class App extends React.PureComponent<Props, State> {
}) {
const { currentSetting, currentSettingValue, generalSetting } = params;

const defaultDays =
(!currentSetting && generalSetting.type === 'NUMBER_OF_DAYS' && generalSetting.value) || '30';

return {
loading: false,
currentSetting,
currentSettingValue,
generalSetting,
selected: currentSetting,
days: currentSetting === 'NUMBER_OF_DAYS' ? currentSettingValue || '30' : '',
selected: currentSetting || generalSetting.type,
overrideGeneralSetting: Boolean(currentSetting),
days: (currentSetting === 'NUMBER_OF_DAYS' && currentSettingValue) || defaultDays,
analysis: (currentSetting === 'SPECIFIC_ANALYSIS' && currentSettingValue) || ''
};
}
@@ -92,7 +96,7 @@ export default class App extends React.PureComponent<Props, State> {
Promise.all([
getNewCodePeriod(),
getNewCodePeriod({
branch: this.props.branchesEnabled ? 'master' : undefined,
branch: !this.props.branchesEnabled ? 'master' : undefined,
project: this.props.component.key
})
]).then(
@@ -137,11 +141,19 @@ export default class App extends React.PureComponent<Props, State> {

handleSelectSetting = (selected?: T.NewCodePeriodSettingType) => this.setState({ selected });

handleToggleSpecificSetting = (overrideGeneralSetting: boolean) =>
this.setState({ overrideGeneralSetting });

handleSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
e.preventDefault();

const { component } = this.props;
const { analysis, days, selected: type } = this.state;
const { analysis, days, selected: type, overrideGeneralSetting } = this.state;

if (!overrideGeneralSetting) {
this.resetSetting();
return;
}

const value = getSettingValue({ type, analysis, days });

@@ -201,17 +213,6 @@ export default class App extends React.PureComponent<Props, State> {
);
}

renderGeneralSetting(generalSetting: T.NewCodePeriod) {
if (generalSetting.type === 'NUMBER_OF_DAYS') {
return `${translate('baseline.number_days')} (${translateWithParameters(
'duration.days',
generalSetting.value || '?'
)})`;
} else {
return translate('baseline.previous_version');
}
}

render() {
const { branchLikes, branchesEnabled, component } = this.props;
const {
@@ -221,6 +222,7 @@ export default class App extends React.PureComponent<Props, State> {
generalSetting,
loading,
currentSettingValue,
overrideGeneralSetting,
saving,
selected
} = this.state;
@@ -231,57 +233,45 @@ export default class App extends React.PureComponent<Props, State> {
{loading ? (
<DeferredSpinner />
) : (
<div className="panel panel-white">
{branchesEnabled && (
<>
<h2>{translate('project_baseline.default_setting')}</h2>
<p>{translate('project_baseline.default_setting.description')}</p>
</>
)}
<div className="panel-white project-baseline">
{branchesEnabled && <h2>{translate('project_baseline.default_setting')}</h2>}

{generalSetting && (
<div className="text-right spacer-bottom">
{currentSetting && (
<>
<Button className="little-spacer-bottom" onClick={this.resetSetting}>
{translate('project_baseline.reset_to_general')}
</Button>
</>
)}
<div className="spacer-top medium">
<strong>{translate('project_baseline.general_setting')}: </strong>
{this.renderGeneralSetting(generalSetting)}
</div>
</div>
{generalSetting && overrideGeneralSetting !== undefined && (
<ProjectBaselineSelector
analysis={analysis}
branchesEnabled={branchesEnabled}
component={component.key}
currentSetting={currentSetting}
currentSettingValue={currentSettingValue}
days={days}
generalSetting={generalSetting}
onSelectAnalysis={this.handleSelectAnalysis}
onSelectDays={this.handleSelectDays}
onSelectSetting={this.handleSelectSetting}
onSubmit={this.handleSubmit}
onToggleSpecificSetting={this.handleToggleSpecificSetting}
overrideGeneralSetting={overrideGeneralSetting}
saving={saving}
selected={selected}
/>
)}

<ProjectBaselineSelector
analysis={analysis}
branchesEnabled={branchesEnabled}
component={component.key}
currentSetting={currentSetting}
currentSettingValue={currentSettingValue}
days={days}
onSelectAnalysis={this.handleSelectAnalysis}
onSelectDays={this.handleSelectDays}
onSelectSetting={this.handleSelectSetting}
onSubmit={this.handleSubmit}
saving={saving}
selected={selected}
/>
{generalSetting && branchesEnabled && (
<BranchList
branchLikes={branchLikes}
component={component}
inheritedSetting={
currentSetting
? {
type: currentSetting,
value: currentSettingValue
}
: generalSetting
}
/>
<div className="huge-spacer-top branch-baseline-selector">
<hr />
<h2>{translate('project_baseline.configure_branches')}</h2>
<BranchList
branchLikes={branchLikes}
component={component}
inheritedSetting={
currentSetting
? {
type: currentSetting,
value: currentSettingValue
}
: generalSetting
}
/>
</div>
)}
</div>
)}

+ 3
- 1
server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingAnalysis.tsx Ver arquivo

@@ -22,13 +22,15 @@ import RadioCard from 'sonar-ui-common/components/controls/RadioCard';
import { translate } from 'sonar-ui-common/helpers/l10n';

export interface Props {
disabled?: boolean;
onSelect: (selection: T.NewCodePeriodSettingType) => void;
selected: boolean;
}

export default function BaselineSettingAnalysis({ onSelect, selected }: Props) {
export default function BaselineSettingAnalysis({ disabled, onSelect, selected }: Props) {
return (
<RadioCard
disabled={disabled}
onClick={() => onSelect('SPECIFIC_ANALYSIS')}
selected={selected}
title={translate('baseline.specific_analysis')}>

+ 3
- 1
server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx Ver arquivo

@@ -25,6 +25,7 @@ import { translate } from 'sonar-ui-common/helpers/l10n';
export interface Props {
className?: string;
days: string;
disabled?: boolean;
isChanged: boolean;
isValid: boolean;
onChangeDays: (value: string) => void;
@@ -33,10 +34,11 @@ export interface Props {
}

export default function BaselineSettingDays(props: Props) {
const { className, days, isChanged, isValid, onChangeDays, onSelect, selected } = props;
const { className, days, disabled, isChanged, isValid, onChangeDays, onSelect, selected } = props;
return (
<RadioCard
className={className}
disabled={disabled}
onClick={() => onSelect('NUMBER_OF_DAYS')}
selected={selected}
title={translate('baseline.number_days')}>

+ 4
- 1
server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingPreviousVersion.tsx Ver arquivo

@@ -22,14 +22,17 @@ import RadioCard from 'sonar-ui-common/components/controls/RadioCard';
import { translate } from 'sonar-ui-common/helpers/l10n';

export interface Props {
disabled?: boolean;
isDefault?: boolean;
onSelect: (selection: T.NewCodePeriodSettingType) => void;
selected: boolean;
}

export default function BaselineSettingPreviousVersion({ isDefault, onSelect, selected }: Props) {
export default function BaselineSettingPreviousVersion(props: Props) {
const { disabled, isDefault, onSelect, selected } = props;
return (
<RadioCard
disabled={disabled}
onClick={() => onSelect('PREVIOUS_VERSION')}
selected={selected}
title={

+ 30
- 14
server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisList.tsx Ver arquivo

@@ -26,6 +26,7 @@ import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { parseDate, toShortNotSoISOString } from 'sonar-ui-common/helpers/dates';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { scrollToElement } from 'sonar-ui-common/helpers/scrolling';
import { getProjectActivity } from '../../../api/projectActivity';
import DateFormatter from '../../../components/intl/DateFormatter';
import TimeFormatter from '../../../components/intl/TimeFormatter';
@@ -49,6 +50,7 @@ interface State {
export default class BranchAnalysisList extends React.PureComponent<Props, State> {
mounted = false;
badges: T.Dict<HTMLDivElement> = {};
rootNodeRef: React.RefObject<HTMLDivElement>;
state: State = {
analyses: [],
loading: true,
@@ -58,6 +60,7 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State

constructor(props: Props) {
super(props);
this.rootNodeRef = React.createRef<HTMLDivElement>();
this.updateScroll = throttle(this.updateScroll, 20);
}

@@ -70,6 +73,13 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
this.mounted = false;
}

scrollToSelected() {
const selectedNode = document.querySelector('.branch-analysis.selected');
if (this.rootNodeRef.current && selectedNode) {
scrollToElement(selectedNode, { parent: this.rootNodeRef.current, bottomOffset: 40 });
}
}

fetchAnalyses(initial = false) {
const { analysis, branch, component } = this.props;
const { range } = this.state;
@@ -86,13 +96,18 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
return;
}

this.setState({
analyses: result.analyses.map(analysis => ({
...analysis,
date: parseDate(analysis.date)
})) as T.ParsedAnalysis[],
loading: false
});
this.setState(
{
analyses: result.analyses.map(analysis => ({
...analysis,
date: parseDate(analysis.date)
})) as T.ParsedAnalysis[],
loading: false
},
() => {
this.scrollToSelected();
}
);
});
}

@@ -115,11 +130,9 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
}
};

shouldStick = (version: string, index: number) => {
shouldStick = (version: string) => {
const badge = this.badges[version];
return (
badge && Number(badge.getAttribute('originOffsetTop')) < this.state.scroll + 18 + index * 2
);
return badge && Number(badge.getAttribute('originOffsetTop')) < this.state.scroll + 10;
};

getRangeOptions() {
@@ -168,7 +181,10 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
/>
</div>
<div className="branch-analysis-list-wrapper">
<div className="bordered branch-analysis-list" onScroll={this.handleScroll}>
<div
className="bordered branch-analysis-list"
onScroll={this.handleScroll}
ref={this.rootNodeRef}>
{loading && <DeferredSpinner className="big-spacer-top" />}

{!loading && !hasFilteredData ? (
@@ -188,7 +204,7 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
<div
className={classNames('branch-analysis-version-badge', {
first: idx === 0,
sticky: this.shouldStick(version.version, idx)
sticky: this.shouldStick(version.version)
})}
ref={this.registerBadgeNode(version.version)}>
<Tooltip
@@ -212,7 +228,7 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
version.byDay[day].map(analysis => (
<li
className={classNames('branch-analysis', {
selected: false
selected: analysis.key === this.props.analysis
})}
data-date={parseDate(analysis.date).valueOf()}
key={analysis.key}

+ 1
- 7
server/sonar-web/src/main/js/apps/projectBaseline/components/BranchList.tsx Ver arquivo

@@ -168,7 +168,6 @@ export default class BranchList extends React.PureComponent<Props, State> {
<thead>
<tr>
<th>{translate('branch_list.branch')}</th>
<th className="thin"> </th>
<th className="thin nowrap huge-spacer-right">
{translate('branch_list.current_setting')}
</th>
@@ -185,15 +184,10 @@ export default class BranchList extends React.PureComponent<Props, State> {
<div className="badge spacer-left">{translate('branches.main_branch')}</div>
)}
</td>
<td>
{!branch.newCodePeriod && (
<span className="badge badge-info">{translate('default')}</span>
)}
</td>
<td className="huge-spacer-right nowrap">
{branch.newCodePeriod
? this.renderNewCodePeriodSetting(branch.newCodePeriod)
: this.renderNewCodePeriodSetting(this.props.inheritedSetting)}
: translate('branch_list.default_setting')}
</td>
<td className="text-right">
<ActionsDropdown>

+ 59
- 9
server/sonar-web/src/main/js/apps/projectBaseline/components/ProjectBaselineSelector.tsx Ver arquivo

@@ -20,8 +20,9 @@
import * as classNames from 'classnames';
import * as React from 'react';
import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import Radio from 'sonar-ui-common/components/controls/Radio';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import { validateSetting } from '../utils';
import BaselineSettingAnalysis from './BaselineSettingAnalysis';
import BaselineSettingDays from './BaselineSettingDays';
@@ -35,12 +36,36 @@ export interface ProjectBaselineSelectorProps {
currentSetting?: T.NewCodePeriodSettingType;
currentSettingValue?: string;
days: string;
generalSetting: T.NewCodePeriod;
onSelectAnalysis: (analysis: T.ParsedAnalysis) => void;
onSelectDays: (value: string) => void;
onSelectSetting: (value: T.NewCodePeriodSettingType) => void;
onSelectSetting: (value?: T.NewCodePeriodSettingType) => void;
onSubmit: (e: React.SyntheticEvent<HTMLFormElement>) => void;
onToggleSpecificSetting: (selection: boolean) => void;
saving: boolean;
selected?: T.NewCodePeriodSettingType;
overrideGeneralSetting: boolean;
}

function renderGeneralSetting(generalSetting: T.NewCodePeriod) {
let setting: string;
let description: string;
if (generalSetting.type === 'NUMBER_OF_DAYS') {
setting = `${translate('baseline.number_days')} (${translateWithParameters(
'duration.days',
generalSetting.value || '?'
)})`;
description = translate('baseline.number_days.description');
} else {
setting = translate('baseline.previous_version');
description = translate('baseline.previous_version.description');
}

return (
<div className="general-setting">
<strong>{setting}</strong>: {description}
</div>
);
}

export default function ProjectBaselineSelector(props: ProjectBaselineSelectorProps) {
@@ -49,10 +74,12 @@ export default function ProjectBaselineSelector(props: ProjectBaselineSelectorPr
branchesEnabled,
component,
currentSetting,
days,
currentSettingValue,
days,
generalSetting,
saving,
selected
selected,
overrideGeneralSetting
} = props;

const { isChanged, isValid } = validateSetting({
@@ -60,29 +87,52 @@ export default function ProjectBaselineSelector(props: ProjectBaselineSelectorPr
currentSetting,
currentSettingValue,
days,
selected
selected,
overrideGeneralSetting
});

return (
<form className="project-baseline-selector" onSubmit={props.onSubmit}>
<div className="branch-baseline-setting-modal">
<div className="big-spacer-top spacer-bottom" role="radiogroup">
<Radio
checked={!overrideGeneralSetting}
className="big-spacer-bottom"
onCheck={() => props.onToggleSpecificSetting(false)}
value="general">
{translate('project_baseline.general_setting')}
</Radio>
<div className="big-spacer-left">{renderGeneralSetting(generalSetting)}</div>

<Radio
checked={overrideGeneralSetting}
className="huge-spacer-top"
onCheck={() => props.onToggleSpecificSetting(true)}
value="specific">
{translate('project_baseline.specific_setting')}
</Radio>
</div>

<div className="big-spacer-left big-spacer-right branch-baseline-setting-modal">
<div className="display-flex-row big-spacer-bottom" role="radiogroup">
<BaselineSettingPreviousVersion
disabled={!overrideGeneralSetting}
onSelect={props.onSelectSetting}
selected={selected === 'PREVIOUS_VERSION'}
selected={overrideGeneralSetting && selected === 'PREVIOUS_VERSION'}
/>
<BaselineSettingDays
days={days}
disabled={!overrideGeneralSetting}
isChanged={isChanged}
isValid={isValid}
onChangeDays={props.onSelectDays}
onSelect={props.onSelectSetting}
selected={selected === 'NUMBER_OF_DAYS'}
selected={overrideGeneralSetting && selected === 'NUMBER_OF_DAYS'}
/>
{!branchesEnabled && (
<BaselineSettingAnalysis
disabled={!overrideGeneralSetting}
onSelect={props.onSelectSetting}
selected={selected === 'SPECIFIC_ANALYSIS'}
selected={overrideGeneralSetting && selected === 'SPECIFIC_ANALYSIS'}
/>
)}
</div>

+ 16
- 1
server/sonar-web/src/main/js/apps/projectBaseline/styles.css Ver arquivo

@@ -17,12 +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.
*/
.project-baseline {
padding: calc(4 * var(--gridSize));
}

.project-baseline-selector > .branch-baseline-setting-modal {
max-height: 60vh;
padding-top: 2px;
}

.project-baseline-selector .general-setting {
margin-left: 7px;
}

.branch-baseline-selector > hr {
margin: 0 calc(-4 * var(--gridSize)) calc(4 * var(--gridSize));
}

.branch-baseline-setting-modal {
display: flex;
flex-direction: column;
@@ -44,7 +55,7 @@
}

.branch-analysis-list > ul {
padding-top: 52px;
padding-top: 18px;
}

.branch-analysis-date {
@@ -90,6 +101,10 @@
background-color: white;
}

.branch-analysis-version-badge.sticky + .branch-analysis-days-list {
padding-top: 36px;
}

.branch-analysis-version-badge.sticky,
.branch-analysis-version-badge.first {
position: absolute;

+ 20
- 5
server/sonar-web/src/main/js/apps/projectBaseline/utils.ts Ver arquivo

@@ -48,15 +48,30 @@ export function validateSetting(state: {
currentSettingValue?: string;
days: string;
selected?: T.NewCodePeriodSettingType;
overrideGeneralSetting?: boolean;
}) {
const { analysis = '', currentSetting, currentSettingValue, days, selected } = state;
const {
analysis = '',
currentSetting,
currentSettingValue,
days,
selected,
overrideGeneralSetting
} = state;

const isChanged =
selected !== currentSetting ||
(selected === 'NUMBER_OF_DAYS' && days !== currentSettingValue) ||
(selected === 'SPECIFIC_ANALYSIS' && analysis !== currentSettingValue);
let isChanged;
if (!currentSetting && overrideGeneralSetting !== undefined) {
isChanged = overrideGeneralSetting;
} else {
isChanged =
overrideGeneralSetting === false ||
selected !== currentSetting ||
(selected === 'NUMBER_OF_DAYS' && days !== currentSettingValue) ||
(selected === 'SPECIFIC_ANALYSIS' && analysis !== currentSettingValue);
}

const isValid =
overrideGeneralSetting === false ||
selected === 'PREVIOUS_VERSION' ||
(selected === 'SPECIFIC_ANALYSIS' && analysis.length > 0) ||
(selected === 'NUMBER_OF_DAYS' && validateDays(days));

+ 11
- 1
server/sonar-web/src/main/js/apps/settings/components/NewCodePeriod.tsx Ver arquivo

@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import { ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
@@ -84,6 +84,13 @@ export default class NewCodePeriod extends React.PureComponent<{}, State> {
this.setState({ selected, success: false });
};

onCancel = () => {
this.setState(({ currentSetting, currentSettingValue, days }) => ({
selected: currentSetting,
days: currentSetting === 'NUMBER_OF_DAYS' ? String(currentSettingValue) : days
}));
};

onSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
e.preventDefault();

@@ -191,6 +198,9 @@ export default class NewCodePeriod extends React.PureComponent<{}, State> {
<SubmitButton disabled={saving || !isValid}>
{translate('save')}
</SubmitButton>
<ResetButtonLink className="spacer-left" onClick={this.onCancel}>
{translate('cancel')}
</ResetButtonLink>
</div>
)}
{!saving && !loading && success && (

+ 6
- 9
server/sonar-web/src/main/js/helpers/__tests__/periods-test.ts Ver arquivo

@@ -85,15 +85,12 @@ describe('getPeriodLabel', () => {

it('should handle SPECIFIC_ANALYSIS', () => {
expect(
getPeriodLabel(
mockPeriod({
mode: 'SPECIFIC_ANALYSIS',
parameter: 'should be overriden'
}),
formatter
)
).toBe('overview.period.specific_analysis.2019-04-23T02:12:32+0100');
expect(formatter).toBeCalled();
getPeriodLabel(mockPeriod({ mode: 'SPECIFIC_ANALYSIS', modeParam: 'A658678DE' }), formatter)
).toBe('overview.period.specific_analysis.A658678DE');
expect(getPeriodLabel(mockPeriod({ mode: 'SPECIFIC_ANALYSIS' }), formatter)).toBe(
'overview.period.specific_analysis.2019-04-23T02:12:32+0100'
);
expect(formatter).toBeCalledTimes(1);
});

it('should handle PREVIOUS_VERSION', () => {

+ 1
- 1
server/sonar-web/src/main/js/helpers/periods.ts Ver arquivo

@@ -43,7 +43,7 @@ export function getPeriodLabel(

switch (period.mode) {
case 'SPECIFIC_ANALYSIS':
parameter = dateFormatter(period.date);
parameter = parameter || dateFormatter(period.date);
break;
case 'PREVIOUS_VERSION':
parameter = parameter || dateFormatter(period.date);

+ 4
- 4
sonar-core/src/main/resources/org/sonar/l10n/core.properties Ver arquivo

@@ -543,10 +543,10 @@ project_baseline.page.description=Use this page to manage the New Code Period of
project_baseline.page.description.link=Learn More
project_baseline.page.description2=You can adjust this setting globally in {link}
project_baseline.page.description2.link=General Settings
project_baseline.default_setting=Project default setting
project_baseline.default_setting.description=This setting is the default for all branches of the project
project_baseline.general_setting=General setting
project_baseline.reset_to_general=Reset to general setting
project_baseline.default_setting=Project setting
project_baseline.general_setting=Use the general setting
project_baseline.specific_setting=Define a specific setting for this project
project_baseline.configure_branches=Set a specific setting for a branch

baseline.previous_version=Previous version
baseline.previous_version.description=The New Code Period will begin with the analysis following the previous version.

Carregando…
Cancelar
Salvar