@@ -20,7 +20,7 @@ | |||
import classNames from 'classnames'; | |||
import * as React from 'react'; | |||
import { fetchWebApi } from '../../../../../../api/web-api'; | |||
import SelectLegacy from '../../../../../../components/controls/SelectLegacy'; | |||
import Select from '../../../../../../components/controls/Select'; | |||
import { getLocalizedMetricName, translate } from '../../../../../../helpers/l10n'; | |||
import { Dict, Metric } from '../../../../../../types/types'; | |||
import withMetricsContext from '../../../../metrics/withMetricsContext'; | |||
@@ -78,7 +78,7 @@ export class BadgeParams extends React.PureComponent<Props> { | |||
getFormatOptions = () => { | |||
return ['md', 'url'].map(format => ({ | |||
label: translate('overview.badges.options.formats', format), | |||
value: format | |||
value: format as BadgeFormats | |||
})); | |||
}; | |||
@@ -102,20 +102,19 @@ export class BadgeParams extends React.PureComponent<Props> { | |||
renderBadgeType = (type: BadgeType, options: BadgeOptions) => { | |||
if (type === BadgeType.measure) { | |||
const metricOptions = this.getMetricOptions(); | |||
return ( | |||
<> | |||
<label className="spacer-right" htmlFor="badge-metric"> | |||
{translate('overview.badges.metric')}: | |||
</label> | |||
<SelectLegacy | |||
className="input-medium" | |||
clearable={false} | |||
menuStyle={{ maxHeight: 100 }} | |||
<Select | |||
className="input-medium it__badge-metric" | |||
name="badge-metric" | |||
isSearchable={false} | |||
onChange={this.handleMetricChange} | |||
options={this.getMetricOptions()} | |||
searchable={false} | |||
value={options.metric} | |||
options={metricOptions} | |||
value={metricOptions.find(o => o.value === options.metric)} | |||
/> | |||
</> | |||
); | |||
@@ -125,6 +124,7 @@ export class BadgeParams extends React.PureComponent<Props> { | |||
render() { | |||
const { className, options, type } = this.props; | |||
const formatOptions = this.getFormatOptions(); | |||
return ( | |||
<div className={className}> | |||
{this.renderBadgeType(type, options)} | |||
@@ -136,14 +136,14 @@ export class BadgeParams extends React.PureComponent<Props> { | |||
htmlFor="badge-format"> | |||
{translate('format')}: | |||
</label> | |||
<SelectLegacy | |||
<Select | |||
className="input-medium" | |||
clearable={false} | |||
name="badge-format" | |||
isSearchable={false} | |||
onChange={this.handleFormatChange} | |||
options={this.getFormatOptions()} | |||
searchable={false} | |||
value={this.props.options.format || 'md'} | |||
options={formatOptions} | |||
value={formatOptions.find(o => o.value === options.format)} | |||
defaultValue={formatOptions.find(o => o.value === 'md')} | |||
/> | |||
</div> | |||
); |
@@ -9,19 +9,12 @@ exports[`should display measure badge params 1`] = ` | |||
overview.badges.metric | |||
: | |||
</label> | |||
<SelectLegacy | |||
className="input-medium" | |||
clearable={false} | |||
menuStyle={ | |||
Object { | |||
"maxHeight": 100, | |||
} | |||
} | |||
<Select | |||
className="input-medium it__badge-metric" | |||
isSearchable={false} | |||
name="badge-metric" | |||
onChange={[Function]} | |||
options={Array []} | |||
searchable={false} | |||
value="alert_status" | |||
/> | |||
<label | |||
className="spacer-right spacer-top" | |||
@@ -30,9 +23,15 @@ exports[`should display measure badge params 1`] = ` | |||
format | |||
: | |||
</label> | |||
<SelectLegacy | |||
<Select | |||
className="input-medium" | |||
clearable={false} | |||
defaultValue={ | |||
Object { | |||
"label": "overview.badges.options.formats.md", | |||
"value": "md", | |||
} | |||
} | |||
isSearchable={false} | |||
name="badge-format" | |||
onChange={[Function]} | |||
options={ | |||
@@ -47,8 +46,6 @@ exports[`should display measure badge params 1`] = ` | |||
}, | |||
] | |||
} | |||
searchable={false} | |||
value="md" | |||
/> | |||
</div> | |||
`; | |||
@@ -62,9 +59,15 @@ exports[`should display quality gate badge params 1`] = ` | |||
format | |||
: | |||
</label> | |||
<SelectLegacy | |||
<Select | |||
className="input-medium" | |||
clearable={false} | |||
defaultValue={ | |||
Object { | |||
"label": "overview.badges.options.formats.md", | |||
"value": "md", | |||
} | |||
} | |||
isSearchable={false} | |||
name="badge-format" | |||
onChange={[Function]} | |||
options={ | |||
@@ -79,8 +82,6 @@ exports[`should display quality gate badge params 1`] = ` | |||
}, | |||
] | |||
} | |||
searchable={false} | |||
value="md" | |||
/> | |||
</div> | |||
`; |
@@ -22,7 +22,7 @@ import * as React from 'react'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { GraphType } from '../../types/project-activity'; | |||
import { Metric } from '../../types/types'; | |||
import SelectLegacy from '../controls/SelectLegacy'; | |||
import Select from '../controls/Select'; | |||
import AddGraphMetric from './AddGraphMetric'; | |||
import './styles.css'; | |||
import { getGraphTypes, isCustomGraph } from './utils'; | |||
@@ -65,13 +65,12 @@ export default class GraphsHeader extends React.PureComponent<Props> { | |||
return ( | |||
<div className={classNames(className, 'position-relative')}> | |||
<SelectLegacy | |||
<Select | |||
className="pull-left input-medium" | |||
clearable={false} | |||
isSearchable={false} | |||
onChange={this.handleGraphChange} | |||
options={selectOptions} | |||
searchable={false} | |||
value={graph} | |||
value={selectOptions.find(option => option.value === graph)} | |||
/> | |||
{isCustomGraph(graph) && | |||
addCustomMetric !== undefined && |
@@ -31,7 +31,7 @@ import ChevronRightIcon from '../../components/icons/ChevronRightIcon'; | |||
import { getShortMonthName, getShortWeekDayName, getWeekDayName } from '../../helpers/l10n'; | |||
import { lazyLoadComponent } from '../lazyLoadComponent'; | |||
import './DayPicker.css'; | |||
import SelectLegacy from './SelectLegacy'; | |||
import Select from './Select'; | |||
import './styles.css'; | |||
const DayPicker = lazyLoadComponent(() => import('react-day-picker'), 'DayPicker'); | |||
@@ -118,8 +118,17 @@ export default class DateInput extends React.PureComponent<Props, State> { | |||
}; | |||
render() { | |||
const { highlightFrom, highlightTo, minDate, value } = this.props; | |||
const { lastHovered } = this.state; | |||
const { | |||
highlightFrom, | |||
highlightTo, | |||
minDate, | |||
value, | |||
name, | |||
className, | |||
inputClassName, | |||
placeholder | |||
} = this.props; | |||
const { lastHovered, currentMonth, open } = this.state; | |||
const after = this.props.maxDate || new Date(); | |||
@@ -142,50 +151,53 @@ export default class DateInput extends React.PureComponent<Props, State> { | |||
const weekdaysLong = range(7).map(getWeekDayName) as Week; | |||
const weekdaysShort = range(7).map(getShortWeekDayName) as Week; | |||
const monthOptions = months.map(month => ({ | |||
label: getShortMonthName(month), | |||
value: month | |||
})); | |||
const yearOptions = years.map(year => ({ label: String(year), value: year })); | |||
return ( | |||
<OutsideClickHandler onClickOutside={this.closeCalendar}> | |||
<span className={classNames('date-input-control', this.props.className)}> | |||
<span className={classNames('date-input-control', className)}> | |||
<InputWrapper | |||
className={classNames('date-input-control-input', this.props.inputClassName, { | |||
'is-filled': this.props.value !== undefined | |||
className={classNames('date-input-control-input', inputClassName, { | |||
'is-filled': value !== undefined | |||
})} | |||
innerRef={(node: HTMLInputElement | null) => (this.input = node)} | |||
name={this.props.name} | |||
name={name} | |||
onFocus={this.openCalendar} | |||
placeholder={this.props.placeholder} | |||
placeholder={placeholder} | |||
readOnly={true} | |||
type="text" | |||
value={value} | |||
/> | |||
<CalendarIcon className="date-input-control-icon" fill="" /> | |||
{this.props.value !== undefined && ( | |||
{value !== undefined && ( | |||
<ClearButton | |||
className="button-tiny date-input-control-reset" | |||
iconProps={{ size: 12 }} | |||
onClick={this.handleResetClick} | |||
/> | |||
)} | |||
{this.state.open && ( | |||
{open && ( | |||
<div className="date-input-calendar"> | |||
<nav className="date-input-calendar-nav"> | |||
<ButtonIcon className="button-small" onClick={this.handlePreviousMonthClick}> | |||
<ChevronLeftIcon /> | |||
</ButtonIcon> | |||
<div className="date-input-calender-month"> | |||
<SelectLegacy | |||
<Select | |||
className="date-input-calender-month-select" | |||
onChange={this.handleCurrentMonthChange} | |||
options={months.map(month => ({ | |||
label: getShortMonthName(month), | |||
value: month | |||
}))} | |||
value={this.state.currentMonth.getMonth()} | |||
options={monthOptions} | |||
value={monthOptions.find(month => month.value === currentMonth.getMonth())} | |||
/> | |||
<SelectLegacy | |||
<Select | |||
className="date-input-calender-month-select spacer-left" | |||
onChange={this.handleCurrentYearChange} | |||
options={years.map(year => ({ label: String(year), value: year }))} | |||
value={this.state.currentMonth.getFullYear()} | |||
options={yearOptions} | |||
value={yearOptions.find(year => year.value === currentMonth.getFullYear())} | |||
/> | |||
</div> | |||
<ButtonIcon className="button-small" onClick={this.handleNextMonthClick}> | |||
@@ -197,7 +209,7 @@ export default class DateInput extends React.PureComponent<Props, State> { | |||
disabledDays={{ after, before: minDate }} | |||
firstDayOfWeek={1} | |||
modifiers={modifiers} | |||
month={this.state.currentMonth} | |||
month={currentMonth} | |||
navbarElement={<NullComponent />} | |||
onDayClick={this.handleDayClick} | |||
onDayMouseEnter={this.handleDayMouseEnter} |
@@ -52,7 +52,11 @@ export default class OutsideClickHandler extends React.Component<Props> { | |||
if (this.mounted) { | |||
// eslint-disable-next-line react/no-find-dom-node | |||
const node = findDOMNode(this); | |||
if (!node || !node.contains(event.target as Node)) { | |||
if ( | |||
node && | |||
!node.contains(event.target as Node) && | |||
window.document.contains(event.target as Node) | |||
) { | |||
this.props.onClickOutside(); | |||
} | |||
} |
@@ -56,6 +56,7 @@ it('should call event handler on click on window', () => { | |||
window.addEventListener = jest.fn((event, callback) => { | |||
map[event] = callback as EventListener; | |||
}); | |||
jest.spyOn(window.document, 'contains').mockReturnValue(true); | |||
mount( | |||
<div id="outside-element"> |
@@ -100,7 +100,7 @@ exports[`should render 3`] = ` | |||
<div | |||
className="date-input-calender-month" | |||
> | |||
<SelectLegacy | |||
<Select | |||
className="date-input-calender-month-select" | |||
onChange={[Function]} | |||
options={ | |||
@@ -155,9 +155,14 @@ exports[`should render 3`] = ` | |||
}, | |||
] | |||
} | |||
value={0} | |||
value={ | |||
Object { | |||
"label": "Jan", | |||
"value": 0, | |||
} | |||
} | |||
/> | |||
<SelectLegacy | |||
<Select | |||
className="date-input-calender-month-select spacer-left" | |||
onChange={[Function]} | |||
options={ | |||
@@ -208,7 +213,12 @@ exports[`should render 3`] = ` | |||
}, | |||
] | |||
} | |||
value={2018} | |||
value={ | |||
Object { | |||
"label": "2018", | |||
"value": 2018, | |||
} | |||
} | |||
/> | |||
</div> | |||
<ButtonIcon |
@@ -75,8 +75,10 @@ | |||
} | |||
.date-input-calender-month { | |||
display: flex; | |||
justify-content: center; | |||
} | |||
.date-input-calender-month-select { | |||
.date-input-calender-month .date-input-calender-month-select { | |||
width: 70px; | |||
} |