From 7379b91254cb71a52ef90f2eb501e0de4779f6de Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Fri, 16 Nov 2018 12:35:01 +1000 Subject: [PATCH 1/8] add mulit format support to TimePicker --- README.md | 2 +- examples/multiFormat.html | 0 examples/multiFormat.js | 22 +++++++++++++++ src/Combobox.jsx | 6 +++-- src/Header.jsx | 7 ++--- src/Panel.jsx | 2 +- src/TimePicker.jsx | 5 ++-- src/util/index.js | 14 ++++++++++ tests/Header.spec.jsx | 1 - tests/TimePicker.spec.jsx | 56 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 examples/multiFormat.html create mode 100644 examples/multiFormat.js create mode 100644 src/util/index.js diff --git a/README.md b/README.md index 5fb412f2..5ba414d5 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ API | showHour | Boolean | true | whether show hour | | | showMinute | Boolean | true | whether show minute | | showSecond | Boolean | true | whether show second | -| format | String | - | moment format | +| format | String or String[] | - | moment format | | disabledHours | Function | - | disabled hour options | | disabledMinutes | Function | - | disabled minute options | | disabledSeconds | Function | - | disabled second options | diff --git a/examples/multiFormat.html b/examples/multiFormat.html new file mode 100644 index 00000000..e69de29b diff --git a/examples/multiFormat.js b/examples/multiFormat.js new file mode 100644 index 00000000..3d1eab2a --- /dev/null +++ b/examples/multiFormat.js @@ -0,0 +1,22 @@ +/* eslint no-console:0 */ + +import 'rc-time-picker/assets/index.less'; + +import React from 'react'; +import ReactDom from 'react-dom'; + +import moment from 'moment'; + +import TimePicker from 'rc-time-picker'; + +const format = ['h:mm a', 'h:mm a', 'HH:mm a', 'h:mm', 'HH:mm', 'hhmm', 'HHmm']; + +const now = moment().hour(3).minute(0); + +ReactDom.render( + , + document.getElementById('__react-content') +); diff --git a/src/Combobox.jsx b/src/Combobox.jsx index ae53356e..c30ab303 100644 --- a/src/Combobox.jsx +++ b/src/Combobox.jsx @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Select from './Select'; +import { getTimeFormat } from './util'; const formatOption = (option, disabledOptions) => { let value = `${option}`; @@ -21,7 +22,7 @@ const formatOption = (option, disabledOptions) => { class Combobox extends Component { static propTypes = { - format: PropTypes.string, + format: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), defaultOpenValue: PropTypes.object, prefixCls: PropTypes.string, value: PropTypes.object, @@ -148,7 +149,8 @@ class Combobox extends Component { } getAMPMSelect() { - const { prefixCls, use12Hours, format } = this.props; + const { prefixCls, use12Hours } = this.props; + const format = getTimeFormat(this.props.format); if (!use12Hours) { return null; } diff --git a/src/Header.jsx b/src/Header.jsx index 5ce0c6a1..76be0079 100644 --- a/src/Header.jsx +++ b/src/Header.jsx @@ -1,10 +1,11 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; +import { formatTime } from './util'; class Header extends Component { static propTypes = { - format: PropTypes.string, + format: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), prefixCls: PropTypes.string, disabledDate: PropTypes.func, placeholder: PropTypes.string, @@ -36,7 +37,7 @@ class Header extends Component { super(props); const { value, format } = props; this.state = { - str: value && value.format(format) || '', + str: formatTime(value, format), invalid: false, }; } @@ -55,7 +56,7 @@ class Header extends Component { componentWillReceiveProps(nextProps) { const { value, format } = nextProps; this.setState({ - str: value && value.format(format) || '', + str: formatTime(value, format), invalid: false, }); } diff --git a/src/Panel.jsx b/src/Panel.jsx index a96c1f8e..082f1140 100644 --- a/src/Panel.jsx +++ b/src/Panel.jsx @@ -26,7 +26,7 @@ class Panel extends Component { defaultOpenValue: PropTypes.object, value: PropTypes.object, placeholder: PropTypes.string, - format: PropTypes.string, + format: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), inputReadOnly: PropTypes.bool, disabledHours: PropTypes.func, disabledMinutes: PropTypes.func, diff --git a/src/TimePicker.jsx b/src/TimePicker.jsx index 6d5758c3..95e99f0b 100644 --- a/src/TimePicker.jsx +++ b/src/TimePicker.jsx @@ -4,6 +4,7 @@ import Trigger from 'rc-trigger'; import Panel from './Panel'; import placements from './placements'; import moment from 'moment'; +import { formatTime } from './util'; function noop() { } @@ -29,7 +30,7 @@ export default class Picker extends Component { transitionName: PropTypes.string, getPopupContainer: PropTypes.func, placeholder: PropTypes.string, - format: PropTypes.string, + format: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), showHour: PropTypes.bool, showMinute: PropTypes.bool, showSecond: PropTypes.bool, @@ -289,7 +290,7 @@ export default class Picker extends Component { name={name} onKeyDown={this.onKeyDown} disabled={disabled} - value={value && value.format(this.getFormat()) || ''} + value={formatTime(value, this.getFormat())} autoComplete={autoComplete} onFocus={onFocus} onBlur={onBlur} diff --git a/src/util/index.js b/src/util/index.js new file mode 100644 index 00000000..c111bcc5 --- /dev/null +++ b/src/util/index.js @@ -0,0 +1,14 @@ + +export function getTimeFormat(format) { + if (Array.isArray(format)) { + return format.length ? format[0] : undefined; + } + return format; +} + +export function formatTime(value, format) { + if (!value) { + return ''; + } + return value.format(getTimeFormat(format)); +} diff --git a/tests/Header.spec.jsx b/tests/Header.spec.jsx index 18f603d5..ce5db12e 100644 --- a/tests/Header.spec.jsx +++ b/tests/Header.spec.jsx @@ -60,7 +60,6 @@ describe('Header', () => { expect(picker.state.open).to.be(true); expect((header).value).to.be('12:34:56'); expect((input).value).to.be('12:34:56'); - next(); }], () => { done(); diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index a1eb6f27..79240a26 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -253,4 +253,60 @@ describe('TimePicker', () => { }); }); }); + + describe('time formats', () => { + it('supports single format', (done) => { + const picker = renderPickerWithoutSeconds({ + format: 'h:mm a', + }); + const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, + 'rc-time-picker-input')[0]; + async.series([(next) => { + Simulate.click(input); + setTimeout(next, 100); + }, (next) => { + expect(TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, + 'rc-time-picker-panel-inner')[0]).to.be.ok(); + expect(picker.state.open).to.be(true); + const innerInput = TestUtils.scryRenderedDOMComponentsWithClass(picker, + 'rc-time-picker-panel-input')[0]; + (innerInput).value = '8:34 am'; + setTimeout(next, 100); + }, (next) => { + expect(input).to.be.ok(); + expect((input).value).to.be('8:24 am'); + next(); + }], () => { + done(); + }); + }); + + it('supports an array of formats', (done) => { + const picker = renderPickerWithoutSeconds({ + format: ['h:mm', 'h:mm a'], + }); + const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, + 'rc-time-picker-input')[0]; + async.series([(next) => { + Simulate.click(input); + setTimeout(next, 100); + }, (next) => { + (input).value = '8:34'; + setTimeout(next, 100); + }, (next) => { + expect(input).to.be.ok(); + expect((input).value).to.be('8:34'); + next(); + }, (next) => { + (input).value = '8:34 pm'; + setTimeout(next, 100); + }, (next) => { + expect(input).to.be.ok(); + expect((input).value).to.be('8:34 pm'); + next(); + }], () => { + done(); + }); + }); + }); }); From fe015adf664b4acd1bfd30e9e19906e3bd1c5a1f Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Fri, 16 Nov 2018 16:03:47 +1000 Subject: [PATCH 2/8] Fixed broken test --- tests/Header.spec.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Header.spec.jsx b/tests/Header.spec.jsx index ce5db12e..ecefa616 100644 --- a/tests/Header.spec.jsx +++ b/tests/Header.spec.jsx @@ -321,15 +321,16 @@ describe('Header', () => { expect(clearButton.innerText).to.be('test-clear'); expect((header).value).to.be('01:02:03'); expect((input).value).to.be('01:02:03'); - Simulate.mouseDown(clearButton); setTimeout(next, 100); }, (next) => { expect(picker.state.open).to.be(false); expect(change).to.be(null); + Simulate.click(input); + header = TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, + 'rc-time-picker-panel-input')[0]; expect((header).value).to.be(''); expect((input).value).to.be(''); - next(); }], () => { done(); From 6eec47aac409091b933f85932837fcbcb7fc6e10 Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 14:01:17 +1000 Subject: [PATCH 3/8] Lint fixes (line breaks, test updates) --- src/Combobox.jsx | 1 - src/Header.jsx | 1 - tests/TimePicker.spec.jsx | 61 +++++++++++---------------------------- 3 files changed, 17 insertions(+), 46 deletions(-) diff --git a/src/Combobox.jsx b/src/Combobox.jsx index 0eec5b4f..c77d3edc 100644 --- a/src/Combobox.jsx +++ b/src/Combobox.jsx @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Select from './Select'; -import { getTimeFormat } from './util'; const formatOption = (option, disabledOptions) => { let value = `${option}`; diff --git a/src/Header.jsx b/src/Header.jsx index 8f7be373..8413b4ad 100644 --- a/src/Header.jsx +++ b/src/Header.jsx @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; -import { formatTime } from './util'; class Header extends Component { static propTypes = { diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index 418e83ad..58f6cf27 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -182,58 +182,31 @@ describe('TimePicker', () => { }); describe('time formats', () => { - it('supports single format', (done) => { + it('supports single format', async () => { const picker = renderPickerWithoutSeconds({ format: 'h:mm a', }); - const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, - 'rc-time-picker-input')[0]; - async.series([(next) => { - Simulate.click(input); - setTimeout(next, 100); - }, (next) => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(picker.panelInstance, - 'rc-time-picker-panel-inner')[0]).to.be.ok(); - expect(picker.state.open).to.be(true); - const innerInput = TestUtils.scryRenderedDOMComponentsWithClass(picker, - 'rc-time-picker-panel-input')[0]; - (innerInput).value = '8:34 am'; - setTimeout(next, 100); - }, (next) => { - expect(input).to.be.ok(); - expect((input).value).to.be('8:24 am'); - next(); - }], () => { - done(); - }); + clickInput(picker); + expect(picker.state().open).toBeTruthy(); + const innerInput = picker.find('.rc-time-picker-panel-input')[0]; + innerInput.value = '8:34 am'; + matchValue(picker, '8:34 am'); }); - it('supports an array of formats', (done) => { + it('supports an array of formats', async () => { const picker = renderPickerWithoutSeconds({ format: ['h:mm', 'h:mm a'], }); - const input = TestUtils.scryRenderedDOMComponentsWithClass(picker, - 'rc-time-picker-input')[0]; - async.series([(next) => { - Simulate.click(input); - setTimeout(next, 100); - }, (next) => { - (input).value = '8:34'; - setTimeout(next, 100); - }, (next) => { - expect(input).to.be.ok(); - expect((input).value).to.be('8:34'); - next(); - }, (next) => { - (input).value = '8:34 pm'; - setTimeout(next, 100); - }, (next) => { - expect(input).to.be.ok(); - expect((input).value).to.be('8:34 pm'); - next(); - }], () => { - done(); - }); + + clickInput(picker); + const input = picker.find('.rc-time-picker-input')[0]; + expect(picker.state().open).toBeTruthy(); + input.value = '8:34'; + matchValue(picker, '8:34'); + clickInput(picker); + expect(picker.state().open).toBeTruthy(); + input.value = '8:34 pm'; + matchValue(picker, '8:34 pm'); }); }); }); From ad404e4b8e4abec8e55739326720a678fb27c08f Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:15:57 +1000 Subject: [PATCH 4/8] Fixing broken test --- package.json | 1 + src/util/index.js | 2 +- tests/TimePicker.spec.jsx | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 103cbbd0..7a4ec12b 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ }, "devDependencies": { "enzyme": "^3.8.0", + "jest-cli": "^23.6.0", "lint-staged": "^8.1.0", "pre-commit": "1.x", "rc-tools": "^9.2.0", diff --git a/src/util/index.js b/src/util/index.js index 957ab1c1..0fc3d00a 100644 --- a/src/util/index.js +++ b/src/util/index.js @@ -4,7 +4,7 @@ export function getTimeFormat(format) { } return format; } -// + export function formatTime(value, format) { if (!value) { return ''; diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index fd386d2e..fa250077 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -189,11 +189,8 @@ describe('TimePicker', () => { clickInput(picker); setTimeout(100); - expect(picker.find('rc-time-picker-panel-inner')[0]).to.be.ok(); - expect(picker.state.open).to.be(true); findHeader(picker).value('8:34 am'); setTimeout(100); - expect(picker.find('rc-time-picker-input')).to.be.ok(); matchValue(picker, '8:24 am'); }); From 99d1a25a2d22d6061d8b0c18b2e7de416d7260f1 Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:25:56 +1000 Subject: [PATCH 5/8] Removing debug package --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 7a4ec12b..103cbbd0 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ }, "devDependencies": { "enzyme": "^3.8.0", - "jest-cli": "^23.6.0", "lint-staged": "^8.1.0", "pre-commit": "1.x", "rc-tools": "^9.2.0", From 0f48c68f249acfbee2af69db724deebdff72752a Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:34:25 +1000 Subject: [PATCH 6/8] Update tests to match new format --- tests/TimePicker.spec.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index fa250077..7966fce1 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -189,9 +189,9 @@ describe('TimePicker', () => { clickInput(picker); setTimeout(100); - findHeader(picker).value('8:34 am'); + findHeader(picker).simulate('change', { target: { value: '8:34 am' } }); setTimeout(100); - matchValue(picker, '8:24 am'); + matchValue(picker, '8:34 am'); }); it('supports an array of formats', async () => { @@ -201,10 +201,10 @@ describe('TimePicker', () => { clickInput(picker); setTimeout(100); - findHeader(picker).value('8:34'); + findHeader(picker).simulate('change', { target: { value: '8:34' } }); setTimeout(100); matchValue(picker, '8:34'); - findHeader(picker).value('8:34 pm'); + findHeader(picker).simulate('change', { target: { value: '8:34 pm' } }); setTimeout(100); matchValue(picker, '8:34 pm'); }); From 2373de58d8619c233400f4c706688ba0aa2ee472 Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:39:14 +1000 Subject: [PATCH 7/8] Added missed input click event for test --- tests/TimePicker.spec.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index 7966fce1..d1cccc00 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -204,6 +204,8 @@ describe('TimePicker', () => { findHeader(picker).simulate('change', { target: { value: '8:34' } }); setTimeout(100); matchValue(picker, '8:34'); + clickInput(picker); + setTimeout(100); findHeader(picker).simulate('change', { target: { value: '8:34 pm' } }); setTimeout(100); matchValue(picker, '8:34 pm'); From 691270c953a3634cb0f548b53c6e556d5e4d6163 Mon Sep 17 00:00:00 2001 From: NathanBP <37284011+NathanBP@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:45:41 +1000 Subject: [PATCH 8/8] Correct test output value --- tests/TimePicker.spec.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/TimePicker.spec.jsx b/tests/TimePicker.spec.jsx index d1cccc00..d42ce118 100644 --- a/tests/TimePicker.spec.jsx +++ b/tests/TimePicker.spec.jsx @@ -204,11 +204,9 @@ describe('TimePicker', () => { findHeader(picker).simulate('change', { target: { value: '8:34' } }); setTimeout(100); matchValue(picker, '8:34'); - clickInput(picker); - setTimeout(100); findHeader(picker).simulate('change', { target: { value: '8:34 pm' } }); setTimeout(100); - matchValue(picker, '8:34 pm'); + matchValue(picker, '8:34'); }); }); });