Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated project to be compatible with Material-UI Pickers v4 #52

Closed
wants to merge 10 commits into from
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"rules": {
"react/jsx-filename-extension": 0,
"react/forbid-prop-types": 0
}
},
"env": { "es6": true },
"parser": "babel-eslint"
}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ node_modules
.eslintignore
.eslintrc
example/

.idea/
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# react-admin-date-inputs

\<DateInput>, \<TimeInput> and \<DateTimeInput> components for [React-Admin](https://github.com/marmelab/react-admin).
\<DateInput>, \<TimeInput>, \<DateTimeInput> and \<DateRangeInput> components for [React-Admin](https://github.com/marmelab/react-admin).

![date-time-picker.gif](date-time-picker.gif)

Expand All @@ -27,7 +27,7 @@ import {
TabbedForm,
FormTab,
} from 'react-admin'
import { DateInput, TimeInput, DateTimeInput } from 'react-admin-date-inputs';
import { DateInput, DateRangeInput, DateTimeInput, TimeInput } from 'react-admin-date-inputs';

export const NewsEdit = (props) => (
<Edit title={<NewsTitle />} {...props}>
Expand All @@ -37,6 +37,7 @@ export const NewsEdit = (props) => (
<DateInput source="startDate" label="Start date" options={{ format: 'DD/MM/YYYY' }} />
<TimeInput source="startTime" label="Start time" options={{ format: 'HH:mm:ss' }} />
<DateTimeInput source="endDate" label="End time" options={{ format: 'DD/MM/YYYY, HH:mm:ss', ampm: false, clearable: true }} />
<DateRangeInput sourceStart="startDate" sourceEnd="endDate" labelStart="Start date" labelEnd="End date"/>
</FormTab>
</TabbedForm>
</Edit>
Expand All @@ -50,19 +51,20 @@ The options prop is passed down to the pickers. Documentation for these options

## providerOptions prop

If you want to use a date parser utils library other than `date-fns` or you want a locale other than english, you can pass the `providerOptions` prop:
If you want to use a date adapter library other than `date-fns` or you want a locale other than english, you can pass the `providerOptions` prop:

```jsx
import DateFnsUtils from '@date-io/date-fns';
import MomentUtils from 'material-ui-pickers/utils/moment-utils';
import frLocale from "date-fns/locale/fr";
import moment from "moment";

...
<DateInput source="date" label="Date using moment" providerOptions={{ utils: MomentUtils }} />
<DateInput source="date" label="Date in French!" providerOptions={{ utils: DateFnsUtils, locale: frLocale }} />
<DateInput source="date" label="Date using moment" providerOptions={{ dateAdapter: MomentUtils, dateLibInstance: moment }} />
<DateInput source="date" label="Date in French!" providerOptions={{ dateAdapter: DateFnsUtils, locale: frLocale }} />
```

**NOTE:** When specifying a locale you must also specify the utils, even if it's the default `DateFnsUtils`.
**NOTE:** When specifying a locale you must also specify the `dateAdapter`, even if it's the default `DateFnsUtils`.

## Development

Expand Down
136 changes: 136 additions & 0 deletions lib/Picker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _raCore = require('ra-core');

var _pickers = require('@material-ui/pickers');

var _core = require('@material-ui/core');

var _dateFns = require('@date-io/date-fns');

var _dateFns2 = _interopRequireDefault(_dateFns);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

var Picker = function Picker(_ref) {
var Component = _ref.Component,
props = _objectWithoutProperties(_ref, ['Component']);

var options = props.options,
label = props.label,
source = props.source,
resource = props.resource,
className = props.className,
isRequired = props.isRequired,
providerOptions = props.providerOptions,
fullWidth = props.fullWidth,
onChange = props.onChange;


var translate = (0, _raCore.useTranslate)();

var _useInput = (0, _raCore.useInput)({ source: source }),
input = _useInput.input,
meta = _useInput.meta;

var touched = meta.touched,
error = meta.error;


var handleChange = (0, _react.useCallback)(function (value) {
onChange(value);

Date.parse(value) ? input.onChange(value.toISOString()) : input.onChange(null);
}, [input]);

return _react2.default.createElement(
'div',
{ className: 'picker' },
_react2.default.createElement(
_pickers.LocalizationProvider,
providerOptions,
_react2.default.createElement(Component, _extends({}, options, {
label: _react2.default.createElement(_raCore.FieldTitle, {
label: label,
source: source,
resource: resource,
isRequired: isRequired
}),
margin: 'normal',
error: !!(touched && error),
helperText: touched && error,
className: className,
value: input.value ? new Date(input.value) : null,
clearText: translate('ra.action.clear_input_value'),
cancelText: translate('ra.action.cancel'),
onChange: function onChange(date) {
return handleChange(date);
},
onBlur: function onBlur() {
return input.onBlur(input.value ? new Date(input.value).toISOString() : null);
},
renderInput: function renderInput(props) {
return _react2.default.createElement(_core.TextField, _extends({}, props, {
margin: 'normal',
variant: 'filled',
fullWidth: fullWidth }));
}
}))
)
);
};

Picker.propTypes = {
input: _propTypes2.default.object,
isRequired: _propTypes2.default.bool,
label: _propTypes2.default.string,
meta: _propTypes2.default.object,
options: _propTypes2.default.object,
resource: _propTypes2.default.string,
source: _propTypes2.default.string,
labelTime: _propTypes2.default.string,
className: _propTypes2.default.string,
providerOptions: _propTypes2.default.shape({
dateAdapter: _propTypes2.default.func,
dateLibInstance: _propTypes2.default.func,
locale: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.string])
}),
fullWidth: _propTypes2.default.bool,
onChange: _propTypes2.default.func
};

Picker.defaultProps = {
input: {},
isRequired: false,
meta: { touched: false, error: false },
options: {},
resource: '',
source: '',
labelTime: '',
className: '',
providerOptions: {
dateAdapter: _dateFns2.default,
locale: undefined
},
fullWidth: false,
onChange: function onChange() {}
};

exports.default = Picker;
module.exports = exports['default'];
154 changes: 154 additions & 0 deletions lib/RangePicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _raCore = require('ra-core');

var _pickers = require('@material-ui/pickers');

var _core = require('@material-ui/core');

var _dateFns = require('@date-io/date-fns');

var _dateFns2 = _interopRequireDefault(_dateFns);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

var RangePicker = function RangePicker(_ref) {
var Component = _ref.Component,
props = _objectWithoutProperties(_ref, ['Component']);

var options = props.options,
labelStart = props.labelStart,
labelEnd = props.labelEnd,
sourceStart = props.sourceStart,
sourceEnd = props.sourceEnd,
resource = props.resource,
className = props.className,
isRequired = props.isRequired,
providerOptions = props.providerOptions,
fullWidth = props.fullWidth,
onChange = props.onChange;


var translate = (0, _raCore.useTranslate)();

var _useInput = (0, _raCore.useInput)({ source: sourceStart }),
inputStart = _useInput.input;

var _useInput2 = (0, _raCore.useInput)({ source: sourceEnd }),
inputEnd = _useInput2.input;

var handleChange = (0, _react.useCallback)(function (value) {
onChange(value);

if (null !== value[0]) Date.parse(value[0]) ? inputStart.onChange(value[0].toISOString()) : inputStart.onChange(null);
if (null !== value[1]) Date.parse(value[1]) ? inputEnd.onChange(value[1].toISOString()) : inputEnd.onChange(null);
}, [inputStart, inputEnd]);

return _react2.default.createElement(
'div',
{ className: 'picker' },
_react2.default.createElement(
_pickers.LocalizationProvider,
providerOptions,
_react2.default.createElement(Component, _extends({}, options, {
startText: _react2.default.createElement(_raCore.FieldTitle, {
label: labelStart,
source: sourceStart,
resource: resource,
isRequired: isRequired
}),
endText: _react2.default.createElement(_raCore.FieldTitle, {
label: labelEnd,
source: sourceEnd,
resource: resource,
isRequired: isRequired
}),
margin: 'normal',
className: className,
value: [inputStart.value ? new Date(inputStart.value) : null, inputEnd.value ? new Date(inputEnd.value) : null],
clearText: translate('ra.action.clear_input_value'),
cancelText: translate('ra.action.cancel'),
onChange: function onChange(date) {
return handleChange(date);
},
renderInput: function renderInput(startProps, endProps) {
return _react2.default.createElement(
_react.Fragment,
null,
_react2.default.createElement(_core.TextField, _extends({}, startProps, {
margin: 'normal',
variant: 'filled',
fullWidth: fullWidth })),
_react2.default.createElement(
_pickers.DateRangeDelimiter,
null,
' to '
),
_react2.default.createElement(_core.TextField, _extends({}, endProps, {
margin: 'normal',
variant: 'filled',
fullWidth: fullWidth }))
);
}
}))
)
);
};

RangePicker.propTypes = {
input: _propTypes2.default.object,
isRequired: _propTypes2.default.bool,
labelStart: _propTypes2.default.string,
labelEnd: _propTypes2.default.string,
meta: _propTypes2.default.object,
options: _propTypes2.default.object,
resource: _propTypes2.default.string,
sourceStart: _propTypes2.default.string,
sourceEnd: _propTypes2.default.string,
labelTime: _propTypes2.default.string,
className: _propTypes2.default.string,
providerOptions: _propTypes2.default.shape({
dateAdapter: _propTypes2.default.func,
dateLibInstance: _propTypes2.default.func,
locale: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.string])
}),
fullWidth: _propTypes2.default.bool,
onChange: _propTypes2.default.func
};

RangePicker.defaultProps = {
input: {},
isRequired: false,
meta: { touched: false, error: false },
options: {},
resource: '',
sourceStart: '',
sourceEnd: '',
labelTime: '',
className: '',
providerOptions: {
dateAdapter: _dateFns2.default,
locale: undefined
},
fullWidth: false,
onChange: function onChange() {}
};

exports.default = RangePicker;
module.exports = exports['default'];
Loading