Skip to content

Commit 69107e1

Browse files
MariaAgajeff-phillips-18
authored andcommitted
feat(DateTimePicker): Add DateTimePicker component (#1420)
1 parent cc733d1 commit 69107e1

File tree

9 files changed

+354
-4
lines changed

9 files changed

+354
-4
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.bootstrap-datetimepicker-widget.date-time-picker-pf.top {
2+
margin-top: -10px;
3+
}
4+
5+
.bootstrap-datetimepicker-widget.date-time-picker-pf.bottom {
6+
margin-top: 10px !important;
7+
}
8+
9+
.bootstrap-datetimepicker-widget.date-picker-pf,
10+
.bootstrap-datetimepicker-widget.date-time-picker-pf {
11+
max-width: none;
12+
13+
.arrow {
14+
left: 10% !important;
15+
}
16+
17+
.popover-content {
18+
color: $color-pf-black-900;
19+
padding: 0;
20+
}
21+
22+
.clock-btn {
23+
border: 0;
24+
box-shadow: none;
25+
color: #363636;
26+
display: block;
27+
padding-bottom: 4px;
28+
padding-top: 4px;
29+
}
30+
31+
table td {
32+
.today-button {
33+
padding: 0 16px 0 0;
34+
border: 0;
35+
background-color: transparent;
36+
37+
span {
38+
height: 24px;
39+
line-height: 24px;
40+
color: @color-pf-blue-400;
41+
}
42+
}
43+
}
44+
45+
&.bootstrap-timepicker-widget {
46+
width: 16em;
47+
48+
.popover-content {
49+
padding-left: 0;
50+
}
51+
}
52+
53+
&.date-picker-pf {
54+
.popover-content {
55+
padding: 10px;
56+
}
57+
}
58+
59+
.timepicker {
60+
table td {
61+
height: initial;
62+
line-height: initial;
63+
}
64+
}
65+
66+
.timepicker-hours .table-condensed>tbody>tr>td,
67+
.timepicker-minutes .table-condensed>tbody>tr>td {
68+
padding: 7px 0;
69+
}
70+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import DatePicker from './DatePicker';
4+
5+
test('DatePicker is working properly', () => {
6+
const component = mount(<DatePicker value="2/21/2019, 2:22:31 PM" />);
7+
8+
expect(component.render()).toMatchSnapshot();
9+
});
10+
11+
test('Edit form of DatePicker', () => {
12+
const component = mount(<DatePicker value="2/21/2019" />);
13+
expect(component.render()).toMatchSnapshot();
14+
component.find('input').simulate('change', { target: { value: '2/22/2019' } });
15+
component.find('input').simulate('blur');
16+
expect(component.state().value).toEqual(new Date('2/22/2019'));
17+
});
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { FormControl, InputGroup, Icon, OverlayTrigger, Popover } from '../../';
4+
import DateInput from './DateComponents/DateInput';
5+
import TodayButton from './DateComponents/TodayButton';
6+
import TimeInput from './TimeComponents/TimeInput';
7+
import { MONTH } from './DateComponents/DateConstants';
8+
9+
class DateTimePicker extends React.Component {
10+
constructor(props) {
11+
super(props);
12+
this.state = {
13+
value: new Date(this.props.value),
14+
tmpValue: this.formatDate(new Date(this.props.value)),
15+
typeOfDateInput: MONTH,
16+
isTimeTableOpen: false
17+
};
18+
}
19+
20+
formatDate = date => {
21+
const { locale } = this.props;
22+
const options = [
23+
{ year: 'numeric', month: 'numeric', day: 'numeric' },
24+
{ hour: '2-digit', minute: '2-digit' }
25+
];
26+
if (Date.parse(date)) {
27+
const parsedValue = new Date(date);
28+
return `${parsedValue.toLocaleString(
29+
locale,
30+
options[0]
31+
)} ${parsedValue.toLocaleString(locale, options[1])}`;
32+
}
33+
return date;
34+
}
35+
36+
setSelected = date => {
37+
let newDate = new Date(this.state.value);
38+
if (Date.parse(date)) {
39+
newDate = new Date(date);
40+
}
41+
this.setState({
42+
value: newDate,
43+
tmpValue: this.formatDate(newDate),
44+
typeOfDateInput: 'M',
45+
isTimeTableOpen: false
46+
});
47+
}
48+
49+
render() {
50+
const { locale, weekStartsOn, id, placement } = this.props;
51+
const { value, typeOfDateInput, isTimeTableOpen, hiddenValue } = this.state;
52+
const popover = (
53+
<Popover
54+
id={id}
55+
className="bootstrap-datetimepicker-widget date-time-picker-pf dropdown-menu timepicker-sbs"
56+
>
57+
<div className="row">
58+
<DateInput
59+
date={value}
60+
setSelected={this.setSelected}
61+
locale={locale}
62+
weekStartsOn={weekStartsOn}
63+
className="col-md-6"
64+
typeOfDateInput={typeOfDateInput}
65+
/>
66+
<TimeInput
67+
time={value}
68+
setSelected={this.setSelected}
69+
isTimeTableOpen={isTimeTableOpen}
70+
locale={locale}
71+
className="col-md-6"
72+
/>
73+
</div>
74+
<li className="picker-switch accordion-toggle">
75+
<TodayButton setSelected={this.setSelected} />
76+
</li>
77+
</Popover>
78+
);
79+
return (
80+
<div>
81+
<InputGroup className="input-group date-time-picker-pf">
82+
<FormControl
83+
aria-label="date-picker-input"
84+
type="text"
85+
value={this.state.tmpValue}
86+
onChange={e => this.setState({ tmpValue: e.target.value })}
87+
onBlur={e => this.setSelected(e.target.value)}
88+
/>
89+
<OverlayTrigger
90+
trigger="click"
91+
placement={placement}
92+
overlay={popover}
93+
rootClose
94+
>
95+
<InputGroup.Addon
96+
className="date-time-picker-pf"
97+
onClick={() =>
98+
this.setState({ tmpValue: formatTime(value, locale) })
99+
}
100+
>
101+
<Icon type="fa" name="calendar" />
102+
</InputGroup.Addon>
103+
</OverlayTrigger>
104+
</InputGroup>
105+
</div>
106+
);
107+
}
108+
}
109+
110+
DateTimePicker.propTypes = {
111+
value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
112+
locale: PropTypes.string,
113+
weekStartsOn: PropTypes.number,
114+
id: PropTypes.string,
115+
hiddenValue: PropTypes.bool,
116+
placement: PropTypes.oneOf(['top', 'bottom'])
117+
};
118+
DateTimePicker.defaultProps = {
119+
value: new Date(),
120+
locale: 'en-US',
121+
weekStartsOn: 1,
122+
id: 'datetime-picker-popover',
123+
hiddenValue: true,
124+
placement: 'top'
125+
};
126+
export default DateTimePicker;

packages/patternfly-3/patternfly-react/src/components/DateTimePicker/TimePicker.stories.js renamed to packages/patternfly-3/patternfly-react/src/components/DateTimePicker/DateTimePicker.stories.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,41 @@ import React from 'react';
22
import { inlineTemplate } from 'storybook/decorators/storyTemplates';
33
import { storiesOf } from '@storybook/react';
44
import { storybookPackageName, DOCUMENTATION_URL, STORYBOOK_CATEGORY } from 'storybook/constants/siteConstants';
5-
import { select, withKnobs } from '@storybook/addon-knobs';
5+
import { number, select, withKnobs } from '@storybook/addon-knobs';
66
import { name } from '../../../package.json';
7-
import { TimePicker } from './index';
7+
import { DateTimePicker } from './index';
8+
import DatePicker from './DatePicker';
9+
import TimePicker from './TimePicker';
810

911
const stories = storiesOf(
1012
`${storybookPackageName(name)}/${STORYBOOK_CATEGORY.FORMS_AND_CONTROLS}/Date Time Picker`,
1113
module
1214
);
1315
stories.addDecorator(withKnobs);
14-
stories.addWithInfo('TimePicker', '', () => {
16+
stories.addWithInfo('DateTimePicker', '', () => {
1517
const story = (
1618
<div style={{ paddingTop: 60, paddingBottom: 60 }}>
19+
<label>Date Time picker</label>
20+
<div className="row">
21+
<div className="col-md-5">
22+
<DateTimePicker
23+
weekStartsOn={number('Week Start Date Time', 1)}
24+
placement={select('Placement Date Time', ['top', 'bottom'], 'top')}
25+
/>
26+
</div>
27+
</div>
28+
<br />
29+
<br />
30+
<br />
31+
<label>Date picker</label>
32+
<div className="row">
33+
<div className="col-md-3">
34+
<DatePicker
35+
weekStartsOn={number('Week Start Date ', 1)}
36+
placement={select('Placement Date', ['top', 'bottom'], 'top')}
37+
/>
38+
</div>
39+
</div>
1740
<label>Time picker</label>
1841
<div className="row">
1942
<div className="col-md-3">
@@ -23,7 +46,7 @@ stories.addWithInfo('TimePicker', '', () => {
2346
</div>
2447
);
2548
return inlineTemplate({
26-
title: 'TimePicker',
49+
title: 'DateTimePicker',
2750
documentationLink: `${DOCUMENTATION_URL.FORMS_AND_CONTROLS}#date-time-picker`,
2851
reactBootstrapDocumentationLink: `${DOCUMENTATION_URL.REACT_BOOTSTRAP_COMPONENT}date-time-picker/`,
2952
description: '',
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import { DateTimePicker } from './index';
4+
5+
test('DateTimePicker is working properly', () => {
6+
const component = mount(<DateTimePicker value="2/21/2019, 2:22:31 PM" />);
7+
8+
expect(component.render()).toMatchSnapshot();
9+
});
10+
11+
test('Edit form of DateTimePicker', () => {
12+
const component = mount(<DateTimePicker value="2/21/2019, 2:22:31 PM" />);
13+
expect(component.render()).toMatchSnapshot();
14+
component.find('input').simulate('change', { target: { value: '2/22/2019, 2:22:31 PM' } });
15+
component.find('input').simulate('blur');
16+
expect(component.state().value).toEqual(new Date('2/22/2019, 2:22:31 PM'));
17+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`DatePicker is working properly 1`] = `
4+
<div>
5+
<span
6+
class="input-group date-time-picker-pf input-group"
7+
>
8+
<input
9+
aria-label="date-time-picker-input"
10+
class="form-control"
11+
type="text"
12+
value="2/21/2019"
13+
/>
14+
<span
15+
class="date-picker-pf input-group-addon"
16+
>
17+
<span
18+
aria-hidden="true"
19+
class="fa fa-calendar"
20+
/>
21+
</span>
22+
</span>
23+
</div>
24+
`;
25+
26+
exports[`Edit form of DatePicker 1`] = `
27+
<div>
28+
<span
29+
class="input-group date-time-picker-pf input-group"
30+
>
31+
<input
32+
aria-label="date-time-picker-input"
33+
class="form-control"
34+
type="text"
35+
value="2/21/2019"
36+
/>
37+
<span
38+
class="date-picker-pf input-group-addon"
39+
>
40+
<span
41+
aria-hidden="true"
42+
class="fa fa-calendar"
43+
/>
44+
</span>
45+
</span>
46+
</div>
47+
`;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`DateTimePicker is working properly 1`] = `
4+
<div>
5+
<span
6+
class="input-group date-time-picker-pf input-group"
7+
>
8+
<input
9+
aria-label="date-picker-input"
10+
class="form-control"
11+
type="text"
12+
value="2/21/2019 2:22 PM"
13+
/>
14+
<span
15+
class="date-time-picker-pf input-group-addon"
16+
>
17+
<span
18+
aria-hidden="true"
19+
class="fa fa-calendar"
20+
/>
21+
</span>
22+
</span>
23+
</div>
24+
`;
25+
26+
exports[`Edit form of DateTimePicker 1`] = `
27+
<div>
28+
<span
29+
class="input-group date-time-picker-pf input-group"
30+
>
31+
<input
32+
aria-label="date-picker-input"
33+
class="form-control"
34+
type="text"
35+
value="2/21/2019 2:22 PM"
36+
/>
37+
<span
38+
class="date-time-picker-pf input-group-addon"
39+
>
40+
<span
41+
aria-hidden="true"
42+
class="fa fa-calendar"
43+
/>
44+
</span>
45+
</span>
46+
</div>
47+
`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import TimePicker from './TimePicker';
22
import DatePicker from './DatePicker';
3+
import DateTimePicker from './DateTimePicker';
34

45
export { TimePicker };
56
export { DatePicker };
7+
export { DateTimePicker };

packages/patternfly-3/patternfly-react/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,4 @@ export * from './components/ExpandCollapse';
5959
export * from './components/Overlay';
6060
export * from './components/BreadcrumbSwitcher';
6161
export * from './components/ClassificationBanner';
62+
export * from './components/DateTimePicker';

0 commit comments

Comments
 (0)