Browse Source

SONAR-17000 SONAR-16974

* [894088] Element inappropriately uses semantic markup
* [894116] Label is not persistent
tags/9.7.0.61563
Wouter Admiraal 1 year ago
parent
commit
4be6479134
20 changed files with 401 additions and 277 deletions
  1. 0
    1
      server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx
  2. 0
    4
      server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css
  3. 20
    16
      server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.tsx
  4. 33
    13
      server/sonar-web/src/main/js/apps/background-tasks/components/Search.tsx
  5. 34
    29
      server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.tsx
  6. 3
    1
      server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.tsx
  7. 2
    2
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.tsx
  8. 1
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.tsx
  9. 76
    0
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFilters.tsx
  10. 0
    72
      server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.tsx
  11. 2
    2
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityPageFilters-test.tsx
  12. 1
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.tsx.snap
  13. 3
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityDateInput-test.tsx.snap
  14. 50
    0
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageFilters-test.tsx.snap
  15. 0
    40
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageHeader-test.tsx.snap
  16. 11
    12
      server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.tsx
  17. 1
    1
      server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/__snapshots__/ChangelogSearch-test.tsx.snap
  18. 3
    0
      server/sonar-web/src/main/js/components/controls/DateInput.tsx
  19. 37
    23
      server/sonar-web/src/main/js/components/controls/DateRangeInput.tsx
  20. 124
    58
      server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateRangeInput-test.tsx.snap

+ 0
- 1
server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx View File

@@ -119,7 +119,6 @@ export default function AuditAppRenderer(props: AuditAppRendererProps) {
</ul>

<DateRangeInput
className="big-spacer-left"
onChange={props.handleDateSelection}
minDate={subDays(now(), HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy])}
maxDate={now()}

+ 0
- 4
server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css View File

@@ -26,10 +26,6 @@
margin-left: 16px;
}

.bt-search-form-label {
margin-bottom: 4px;
}

.bt-search-form-field {
padding: 4px 0;
}

+ 20
- 16
server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.tsx View File

@@ -22,25 +22,29 @@ import Checkbox from '../../../components/controls/Checkbox';
import { translate } from '../../../helpers/l10n';
import { CURRENTS } from '../constants';

interface Props {
interface CurrentsFilterProps {
value?: string;
id: string;
onChange: (value: string) => void;
}

export default class CurrentsFilter extends React.PureComponent<Props> {
handleChange = (value: boolean) => {
const newValue = value ? CURRENTS.ONLY_CURRENTS : CURRENTS.ALL;
this.props.onChange(newValue);
};
export default function CurrentsFilter(props: CurrentsFilterProps) {
const { id, value, onChange } = props;
const checked = value === CURRENTS.ONLY_CURRENTS;

render() {
const checked = this.props.value === CURRENTS.ONLY_CURRENTS;
return (
<div className="bt-search-form-field">
<Checkbox checked={checked} onCheck={this.handleChange}>
<span className="little-spacer-left">{translate('yes')}</span>
</Checkbox>
</div>
);
}
const handleChange = React.useCallback(
(value: boolean) => {
const newValue = value ? CURRENTS.ONLY_CURRENTS : CURRENTS.ALL;
onChange(newValue);
},
[onChange]
);

return (
<div className="bt-search-form-field">
<Checkbox id={id} checked={checked} onCheck={handleChange}>
<span className="little-spacer-left">{translate('yes')}</span>
</Checkbox>
</div>
);
}

+ 33
- 13
server/sonar-web/src/main/js/apps/background-tasks/components/Search.tsx View File

@@ -102,29 +102,49 @@ export default class Search extends React.PureComponent<Props> {
<section className="big-spacer-top big-spacer-bottom">
<ul className="bt-search-form">
<li>
<h6 id="background-task-status-filter-label" className="bt-search-form-label">
{translate('status')}
</h6>
<StatusFilter onChange={this.handleStatusChange} value={status} />
<div className="display-flex-column">
<label
id="background-task-status-filter-label"
className="text-bold little-spacer-bottom"
htmlFor="status-filter">
{translate('status')}
</label>
<StatusFilter id="status-filter" onChange={this.handleStatusChange} value={status} />
</div>
</li>
{types.length > 1 && (
<li>
<h6 id="background-task-type-filter-label" className="bt-search-form-label">
{translate('type')}
</h6>
<TypesFilter onChange={this.handleTypeChange} types={types} value={taskType} />
<div className="display-flex-column">
<label
id="background-task-type-filter-label"
className="text-bold little-spacer-bottom"
htmlFor="types-filter">
{translate('type')}
</label>
<TypesFilter
id="types-filter"
onChange={this.handleTypeChange}
types={types}
value={taskType}
/>
</div>
</li>
)}
{!component && (
<li>
<h6 className="bt-search-form-label">
{translate('background_tasks.currents_filter.ONLY_CURRENTS')}
</h6>
<CurrentsFilter onChange={this.handleCurrentsChange} value={currents} />
<div className="display-flex-column">
<label className="text-bold little-spacer-bottom" htmlFor="currents-filter">
{translate('background_tasks.currents_filter.ONLY_CURRENTS')}
</label>
<CurrentsFilter
id="currents-filter"
onChange={this.handleCurrentsChange}
value={currents}
/>
</div>
</li>
)}
<li>
<h6 className="bt-search-form-label">{translate('date')}</h6>
<DateFilter
maxExecutedAt={maxExecutedAt}
minSubmittedAt={minSubmittedAt}

+ 34
- 29
server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.tsx View File

@@ -23,39 +23,44 @@ import { translate } from '../../../helpers/l10n';
import { TaskStatuses } from '../../../types/tasks';
import { STATUSES } from '../constants';

interface Props {
interface StatusFilterProps {
value?: string;
id: string;
onChange: (value?: string) => void;
}

export default class StatusFilter extends React.PureComponent<Props> {
handleChange = ({ value }: BasicSelectOption) => {
this.props.onChange(value);
};
export default function StatusFilter(props: StatusFilterProps) {
const { id, value, onChange } = props;

render() {
const options: BasicSelectOption[] = [
{ value: STATUSES.ALL, label: translate('background_task.status.ALL') },
{
value: STATUSES.ALL_EXCEPT_PENDING,
label: translate('background_task.status.ALL_EXCEPT_PENDING')
},
{ value: TaskStatuses.Pending, label: translate('background_task.status.PENDING') },
{ value: TaskStatuses.InProgress, label: translate('background_task.status.IN_PROGRESS') },
{ value: TaskStatuses.Success, label: translate('background_task.status.SUCCESS') },
{ value: TaskStatuses.Failed, label: translate('background_task.status.FAILED') },
{ value: TaskStatuses.Canceled, label: translate('background_task.status.CANCELED') }
];
const options: BasicSelectOption[] = [
{ value: STATUSES.ALL, label: translate('background_task.status.ALL') },
{
value: STATUSES.ALL_EXCEPT_PENDING,
label: translate('background_task.status.ALL_EXCEPT_PENDING')
},
{ value: TaskStatuses.Pending, label: translate('background_task.status.PENDING') },
{ value: TaskStatuses.InProgress, label: translate('background_task.status.IN_PROGRESS') },
{ value: TaskStatuses.Success, label: translate('background_task.status.SUCCESS') },
{ value: TaskStatuses.Failed, label: translate('background_task.status.FAILED') },
{ value: TaskStatuses.Canceled, label: translate('background_task.status.CANCELED') }
];

return (
<Select
aria-labelledby="background-task-status-filter-label"
className="input-medium"
onChange={this.handleChange}
options={options}
value={options.find(o => o.value === this.props.value)}
isSearchable={false}
/>
);
}
const handleChange = React.useCallback(
({ value }: BasicSelectOption) => {
onChange(value);
},
[onChange]
);

return (
<Select
aria-labelledby="background-task-status-filter-label"
className="input-medium"
id={id}
onChange={handleChange}
options={options}
value={options.find(o => o.value === value)}
isSearchable={false}
/>
);
}

+ 3
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.tsx View File

@@ -24,6 +24,7 @@ import { ALL_TYPES } from '../constants';

interface Props {
value: string;
id: string;
onChange: Function;
types: string[];
}
@@ -34,7 +35,7 @@ export default class TypesFilter extends React.PureComponent<Props> {
};

render() {
const { value, types } = this.props;
const { value, types, id } = this.props;
const options = types.map(t => {
return {
value: t,
@@ -51,6 +52,7 @@ export default class TypesFilter extends React.PureComponent<Props> {
<Select
aria-labelledby="background-task-type-filter-label"
className="input-large"
id={id}
isClearable={false}
onChange={this.handleChange}
options={allOptions}

+ 2
- 2
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.tsx View File

@@ -29,7 +29,7 @@ import { Query } from '../utils';
import './projectActivity.css';
import ProjectActivityAnalysesList from './ProjectActivityAnalysesList';
import ProjectActivityGraphs from './ProjectActivityGraphs';
import ProjectActivityPageHeader from './ProjectActivityPageHeader';
import ProjectActivityPageFilters from './ProjectActivityPageFilters';

interface Props {
addCustomEvent: (analysis: string, name: string, category?: string) => Promise<void>;
@@ -62,7 +62,7 @@ export default function ProjectActivityApp(props: Props) {

<A11ySkipTarget anchor="activity_main" />

<ProjectActivityPageHeader
<ProjectActivityPageFilters
category={query.category}
from={query.from}
project={props.project}

+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.tsx View File

@@ -40,7 +40,7 @@ export default class ProjectActivityDateInput extends React.PureComponent<Props>

render() {
return (
<div>
<div className="display-flex-end">
<DateRangeInput
onChange={this.handleChange}
value={{ from: this.props.from, to: this.props.to }}

+ 76
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFilters.tsx View File

@@ -0,0 +1,76 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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 * as React from 'react';
import Select from '../../../components/controls/Select';
import { translate } from '../../../helpers/l10n';
import { ComponentQualifier } from '../../../types/component';
import { Component } from '../../../types/types';
import { APPLICATION_EVENT_TYPES, EVENT_TYPES, Query } from '../utils';
import ProjectActivityDateInput from './ProjectActivityDateInput';

interface ProjectActivityPageFiltersProps {
category?: string;
from?: Date;
project: Pick<Component, 'qualifier'>;
to?: Date;
updateQuery: (changes: Partial<Query>) => void;
}

export default function ProjectActivityPageFilters(props: ProjectActivityPageFiltersProps) {
const { project, category, from, to, updateQuery } = props;

const isApp = project.qualifier === ComponentQualifier.Application;
const eventTypes = isApp ? APPLICATION_EVENT_TYPES : EVENT_TYPES;
const options = eventTypes.map(category => ({
label: translate('event.category', category),
value: category
}));

const handleCategoryChange = React.useCallback(
(option: { value: string } | null) => {
updateQuery({ category: option ? option.value : '' });
},
[updateQuery]
);

return (
<div className="page-header display-flex-start">
{!([ComponentQualifier.Portfolio, ComponentQualifier.SubPortfolio] as string[]).includes(
project.qualifier
) && (
<div className="display-flex-column big-spacer-right">
<label className="text-bold little-spacer-bottom" htmlFor="filter-events">
{translate('project_activity.filter_events')}
</label>
<Select
className={isApp ? 'input-large' : 'input-medium'}
id="filter-events"
isClearable={true}
isSearchable={false}
onChange={handleCategoryChange}
options={options}
value={options.filter(o => o.value === category)}
/>
</div>
)}
<ProjectActivityDateInput from={from} onChange={props.updateQuery} to={to} />
</div>
);
}

+ 0
- 72
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.tsx View File

@@ -1,72 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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 classNames from 'classnames';
import * as React from 'react';
import Select from '../../../components/controls/Select';
import { translate } from '../../../helpers/l10n';
import { Component } from '../../../types/types';
import { APPLICATION_EVENT_TYPES, EVENT_TYPES, Query } from '../utils';
import ProjectActivityDateInput from './ProjectActivityDateInput';

interface Props {
category?: string;
from?: Date;
project: Pick<Component, 'qualifier'>;
to?: Date;
updateQuery: (changes: Partial<Query>) => void;
}

export default class ProjectActivityPageHeader extends React.PureComponent<Props> {
handleCategoryChange = (option: { value: string } | null) =>
this.props.updateQuery({ category: option ? option.value : '' });

render() {
const isApp = this.props.project.qualifier === 'APP';
const eventTypes = isApp ? APPLICATION_EVENT_TYPES : EVENT_TYPES;
const options = eventTypes.map(category => ({
label: translate('event.category', category),
value: category
}));

return (
<header className="page-header">
{!['VW', 'SVW'].includes(this.props.project.qualifier) && (
<Select
className={classNames('pull-left big-spacer-right', {
'input-medium': !isApp,
'input-large': isApp
})}
placeholder={translate('project_activity.filter_events') + '...'}
isClearable={true}
isSearchable={false}
onChange={this.handleCategoryChange}
options={options}
value={options.filter(o => o.value === this.props.category)}
/>
)}
<ProjectActivityDateInput
from={this.props.from}
onChange={this.props.updateQuery}
to={this.props.to}
/>
</header>
);
}
}

server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityPageHeader-test.tsx → server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityPageFilters-test.tsx View File

@@ -20,12 +20,12 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { parseDate } from '../../../../helpers/dates';
import ProjectActivityPageHeader from '../ProjectActivityPageHeader';
import ProjectActivityPageFilters from '../ProjectActivityPageFilters';

it('should render correctly the list of series', () => {
expect(
shallow(
<ProjectActivityPageHeader
<ProjectActivityPageFilters
category=""
from={parseDate('2016-10-27T12:21:15+0200')}
project={{ qualifier: 'TRK' }}

+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.tsx.snap View File

@@ -17,7 +17,7 @@ exports[`should render correctly 1`] = `
<A11ySkipTarget
anchor="activity_main"
/>
<ProjectActivityPageHeader
<ProjectActivityPageFilters
category=""
project={
Object {

+ 3
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityDateInput-test.tsx.snap View File

@@ -1,7 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly the date inputs 1`] = `
<div>
<div
className="display-flex-end"
>
<DateRangeInput
onChange={[Function]}
value={

+ 50
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageFilters-test.tsx.snap View File

@@ -0,0 +1,50 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly the list of series 1`] = `
<div
className="page-header display-flex-start"
>
<div
className="display-flex-column big-spacer-right"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="filter-events"
>
project_activity.filter_events
</label>
<Select
className="input-medium"
id="filter-events"
isClearable={true}
isSearchable={false}
onChange={[Function]}
options={
Array [
Object {
"label": "event.category.VERSION",
"value": "VERSION",
},
Object {
"label": "event.category.QUALITY_GATE",
"value": "QUALITY_GATE",
},
Object {
"label": "event.category.QUALITY_PROFILE",
"value": "QUALITY_PROFILE",
},
Object {
"label": "event.category.OTHER",
"value": "OTHER",
},
]
}
value={Array []}
/>
</div>
<ProjectActivityDateInput
from={2016-10-27T10:21:15.000Z}
onChange={[Function]}
/>
</div>
`;

+ 0
- 40
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityPageHeader-test.tsx.snap View File

@@ -1,40 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly the list of series 1`] = `
<header
className="page-header"
>
<Select
className="pull-left big-spacer-right input-medium"
isClearable={true}
isSearchable={false}
onChange={[Function]}
options={
Array [
Object {
"label": "event.category.VERSION",
"value": "VERSION",
},
Object {
"label": "event.category.QUALITY_GATE",
"value": "QUALITY_GATE",
},
Object {
"label": "event.category.QUALITY_PROFILE",
"value": "QUALITY_PROFILE",
},
Object {
"label": "event.category.OTHER",
"value": "OTHER",
},
]
}
placeholder="project_activity.filter_events..."
value={Array []}
/>
<ProjectActivityDateInput
from={2016-10-27T10:21:15.000Z}
onChange={[Function]}
/>
</header>
`;

+ 11
- 12
server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.tsx View File

@@ -22,21 +22,20 @@ import { Button } from '../../../components/controls/buttons';
import DateRangeInput from '../../../components/controls/DateRangeInput';
import { translate } from '../../../helpers/l10n';

interface Props {
interface ChangelogSearchProps {
dateRange: { from?: Date; to?: Date } | undefined;
onDateRangeChange: (range: { from?: Date; to?: Date }) => void;
onReset: () => void;
}

export default class ChangelogSearch extends React.PureComponent<Props> {
render() {
return (
<div className="display-inline-block" id="quality-profile-changelog-form">
<DateRangeInput onChange={this.props.onDateRangeChange} value={this.props.dateRange} />
<Button className="spacer-left text-top" onClick={this.props.onReset}>
{translate('reset_verb')}
</Button>
</div>
);
}
export default function ChangelogSearch(props: ChangelogSearchProps) {
const { dateRange } = props;
return (
<div className="display-flex-end" id="quality-profile-changelog-form">
<DateRangeInput onChange={props.onDateRangeChange} value={dateRange} />
<Button className="spacer-left text-top" onClick={props.onReset}>
{translate('reset_verb')}
</Button>
</div>
);
}

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/__snapshots__/ChangelogSearch-test.tsx.snap View File

@@ -2,7 +2,7 @@

exports[`should render 1`] = `
<div
className="display-inline-block"
className="display-flex-end"
id="quality-profile-changelog-form"
>
<DateRangeInput

+ 3
- 0
server/sonar-web/src/main/js/components/controls/DateInput.tsx View File

@@ -47,6 +47,7 @@ interface Props {
maxDate?: Date;
minDate?: Date;
name?: string;
id?: string;
onChange: (date: Date | undefined) => void;
placeholder: string;
value?: Date;
@@ -128,6 +129,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
name,
className,
inputClassName,
id,
placeholder
} = this.props;
const { lastHovered, currentMonth, open } = this.state;
@@ -166,6 +168,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
className={classNames('date-input-control-input', inputClassName, {
'is-filled': value !== undefined
})}
id={id}
innerRef={(node: HTMLInputElement | null) => (this.input = node)}
name={name}
onFocus={this.openCalendar}

+ 37
- 23
server/sonar-web/src/main/js/components/controls/DateRangeInput.tsx View File

@@ -63,29 +63,43 @@ export default class DateRangeInput extends React.PureComponent<Props> {
const { minDate, maxDate } = this.props;

return (
<div className={classNames('display-inline-flex-center', this.props.className)}>
<DateInput
currentMonth={this.to}
data-test="from"
highlightTo={this.to}
minDate={minDate}
maxDate={maxDate && this.to ? min([maxDate, this.to]) : maxDate || this.to}
onChange={this.handleFromChange}
placeholder={translate('start_date')}
value={this.from}
/>
<span className="note little-spacer-left little-spacer-right">{translate('to_')}</span>
<DateInput
currentMonth={this.from}
data-test="to"
highlightFrom={this.from}
minDate={minDate && this.from ? max([minDate, this.from]) : minDate || this.from}
maxDate={maxDate}
onChange={this.handleToChange}
placeholder={translate('end_date')}
ref={element => (this.toDateInput = element)}
value={this.to}
/>
<div className={classNames('display-flex-end', this.props.className)}>
<div className="display-flex-column">
<label className="text-bold little-spacer-bottom" htmlFor="date-from">
{translate('start_date')}
</label>
<DateInput
currentMonth={this.to}
data-test="from"
id="date-from"
highlightTo={this.to}
minDate={minDate}
maxDate={maxDate && this.to ? min([maxDate, this.to]) : maxDate || this.to}
onChange={this.handleFromChange}
placeholder={translate('start_date')}
value={this.from}
/>
</div>
<span className="note little-spacer-left little-spacer-right little-spacer-bottom">
{translate('to_')}
</span>
<div className="display-flex-column">
<label className="text-bold little-spacer-bottom" htmlFor="date-to">
{translate('end_date')}
</label>
<DateInput
currentMonth={this.from}
data-test="to"
id="date-to"
highlightFrom={this.from}
minDate={minDate && this.from ? max([minDate, this.from]) : minDate || this.from}
maxDate={maxDate}
onChange={this.handleToChange}
placeholder={translate('end_date')}
ref={element => (this.toDateInput = element)}
value={this.to}
/>
</div>
</div>
);
}

+ 124
- 58
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateRangeInput-test.tsx.snap View File

@@ -2,88 +2,154 @@

exports[`should render 1`] = `
<div
className="display-inline-flex-center"
className="display-flex-end"
>
<DateInput
currentMonth={2018-02-05T00:00:00.000Z}
data-test="from"
highlightTo={2018-02-05T00:00:00.000Z}
maxDate={2018-02-05T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
value={2018-01-17T00:00:00.000Z}
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-from"
>
start_date
</label>
<DateInput
currentMonth={2018-02-05T00:00:00.000Z}
data-test="from"
highlightTo={2018-02-05T00:00:00.000Z}
id="date-from"
maxDate={2018-02-05T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
value={2018-01-17T00:00:00.000Z}
/>
</div>
<span
className="note little-spacer-left little-spacer-right"
className="note little-spacer-left little-spacer-right little-spacer-bottom"
>
to_
</span>
<DateInput
currentMonth={2018-01-17T00:00:00.000Z}
data-test="to"
highlightFrom={2018-01-17T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
value={2018-02-05T00:00:00.000Z}
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-to"
>
end_date
</label>
<DateInput
currentMonth={2018-01-17T00:00:00.000Z}
data-test="to"
highlightFrom={2018-01-17T00:00:00.000Z}
id="date-to"
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
value={2018-02-05T00:00:00.000Z}
/>
</div>
</div>
`;

exports[`should render: with min/max 1`] = `
<div
className="display-inline-flex-center"
className="display-flex-end"
>
<DateInput
data-test="from"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-from"
>
start_date
</label>
<DateInput
data-test="from"
id="date-from"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
/>
</div>
<span
className="note little-spacer-left little-spacer-right"
className="note little-spacer-left little-spacer-right little-spacer-bottom"
>
to_
</span>
<DateInput
data-test="to"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-to"
>
end_date
</label>
<DateInput
data-test="to"
id="date-to"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
/>
</div>
</div>
`;

exports[`should render: with min/max and value 1`] = `
<div
className="display-inline-flex-center"
className="display-flex-end"
>
<DateInput
currentMonth={2018-02-05T00:00:00.000Z}
data-test="from"
highlightTo={2018-02-05T00:00:00.000Z}
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
value={2018-01-17T00:00:00.000Z}
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-from"
>
start_date
</label>
<DateInput
currentMonth={2018-02-05T00:00:00.000Z}
data-test="from"
highlightTo={2018-02-05T00:00:00.000Z}
id="date-from"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="start_date"
value={2018-01-17T00:00:00.000Z}
/>
</div>
<span
className="note little-spacer-left little-spacer-right"
className="note little-spacer-left little-spacer-right little-spacer-bottom"
>
to_
</span>
<DateInput
currentMonth={2018-01-17T00:00:00.000Z}
data-test="to"
highlightFrom={2018-01-17T00:00:00.000Z}
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
value={2018-02-05T00:00:00.000Z}
/>
<div
className="display-flex-column"
>
<label
className="text-bold little-spacer-bottom"
htmlFor="date-to"
>
end_date
</label>
<DateInput
currentMonth={2018-01-17T00:00:00.000Z}
data-test="to"
highlightFrom={2018-01-17T00:00:00.000Z}
id="date-to"
maxDate={2018-02-05T00:00:00.000Z}
minDate={2018-01-17T00:00:00.000Z}
onChange={[Function]}
placeholder="end_date"
value={2018-02-05T00:00:00.000Z}
/>
</div>
</div>
`;

Loading…
Cancel
Save