Skip to content

Commit

Permalink
wip datepicker
Browse files Browse the repository at this point in the history
  • Loading branch information
skyporter committed May 6, 2024
1 parent 7ff12fa commit d0c96c4
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 133 deletions.
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@import 'select2-bootstrap';
@import "bootstrap4-datetimepicker/build/css/bootstrap-datetimepicker";
@import 'react-leaflet-markercluster/dist/styles.min.css';
@import '@eonasdan/tempus-dominus/dist/css/tempus-dominus.css';

@import './modules/*';
@import './webpack/**/*';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import 'es6-shim';
import PropTypes from 'prop-types';
import React, {useState, useEffect, useRef, forwardRef} from 'react';
import $ from 'jquery';
import 'moment';
import 'bootstrap4-datetimepicker'
import {Namespace, TempusDominus} from '@eonasdan/tempus-dominus';

const DateTimeInput = forwardRef((props, ref) => {
const {
Expand All @@ -20,16 +19,16 @@ const DateTimeInput = forwardRef((props, ref) => {
inputName
} = props

const {topRef, hiddenInputRef} = ref
const {topRef, datepickerRef} = ref
const selectRef = useRef()
const datepickerContainerRef = useRef()

const defaultValues = {Y: '', M: '', D: '', h: '', m: '', s: ''};
const types = ['Y', 'M', 'h', 'YM', 'MD', 'hm', 'YMD', 'hms', 'MDh', 'YMDh', 'MDhm', 'YMDhm', 'MDhms', 'YMDhms'];

const [disabled, setDisabled] = useState(disabledProps)
const [isRange, setIsRange] = useState(isRangeProps)
const [selectedDate, setSelectedDate] = useState('')
const [isDatepickerOpen, setIsDatepickerOpen] = useState(false)
const [localizedDateTimeData, setLocalizedDateTimeData] = useState([])
const [date, setDate] = useState(getData())
const [granularity, setGranularity] = useState(getFieldOptions().format)
Expand All @@ -54,14 +53,19 @@ const DateTimeInput = forwardRef((props, ref) => {


useEffect(() => {
if (topRef.current) {
_initDatePicker();
setLocalizedDateTimeData(localizedDateTimeDataProps);
if (document.querySelector(input) !== null) {
setIsRequired(document.querySelector(input).getAttribute('data-field-required') == 'true')
_initDatePicker();
setLocalizedDateTimeData(localizedDateTimeDataProps);
if (document.querySelector(input) !== null) {
setIsRequired(document.querySelector(input).getAttribute('data-field-required') == 'true')
}

return function cleanup() {
console.log("cleanup")
if (datepickerRef.current) {
datepickerRef.current.dispose();
}
}
}, [topRef])
}, [datepickerRef])

useEffect(() => {
if (disabledProps !== disabled && JSON.stringify(initState) !== JSON.stringify(state)) {
Expand Down Expand Up @@ -90,40 +94,49 @@ const DateTimeInput = forwardRef((props, ref) => {
}, [isRangeProps])

function _initDatePicker() {
if (typeof datepicker !== 'undefined' && datepicker) {
const node = topRef.current
const dateInputElements = node.querySelectorAll('.form-control');
if (!datepickerContainerRef.current)
return

if (dateInputElements.length > 3) {
setStyleMarginRight(' margin-right');
}
if (typeof datepicker !== 'undefined' && datepicker) {

$(hiddenInputRef.current).datetimepicker({
format: format,
locale: locale,
debug: false, // pass to `true` to inspect widget
icons: {
time: 'fa fa-clock-o',
date: 'fa fa-calendar',
up: 'fa fa-chevron-up',
down: 'fa fa-chevron-down',
previous: 'fa fa-arrow-left',
next: 'fa fa-arrow-right',
close: 'fa fa-times'
let displayDate = format.includes('D');
let displayMonth = format.includes('M');
let displayYear = format.includes('Y');
let displayHours = format.includes('h');
let displayMinutes = format.includes('m');
let displaySeconds = format.includes('s');

let datepickerDT = new TempusDominus(datepickerContainerRef.current, {
localization: {
locale: locale
},
display: {
icons: {
type: 'icons',
time: 'fa fa-clock-o',
date: 'fa fa-calendar',
up: 'fa fa-chevron-up',
down: 'fa fa-chevron-down',
previous: 'fa fa-arrow-left',
next: 'fa fa-arrow-right',
today: 'fa fa-calendar-check',
clear: 'fa fa-trash',
close: 'fa fa-times'
},
components: {
calendar: displayDate || displayMonth || displayYear,
date: displayDate,
month: displayMonth,
year: displayYear,
clock: displayHours || displayMinutes || displaySeconds,
hours: displayHours,
minutes: displayMinutes,
seconds: displaySeconds,
},
}
});

$(hiddenInputRef.current).datetimepicker().on('dp.change', (event) => _onDatepickerChangerDate(event));
}
}

function _openCloseDatepicker() {
if (isDatepickerOpen) {
setIsDatepickerOpen(false);
$(hiddenInputRef.current).data("DateTimePicker").hide();
} else {
setIsDatepickerOpen(true);
$(hiddenInputRef.current).data("DateTimePicker").show();
datepickerRef.current = datepickerDT;
datepickerRef.current.subscribe(Namespace.events.change, _onDatepickerChangerDate);
}
}

Expand All @@ -136,20 +149,21 @@ const DateTimeInput = forwardRef((props, ref) => {
}

function _clearDatepicker() {
$(hiddenInputRef.current).data("DateTimePicker").clear();
datepickerRef.current.clear()
updateData({Y: '', M: '', D: '', h: '', m: '', s: ''});
}

function _onDatepickerChangerDate(data) {
if (data.date !== false) {
setSelectedDate(data.date);
function _onDatepickerChangerDate(event) {
const date = event.date;
if (date) {
setSelectedDate(date);
updateData({
Y: data.date.year(),
M: (data.date.month() + 1),
D: data.date.date(),
h: data.date.hour(),
m: data.date.minute(),
s: data.date.second()
Y: date.year,
M: (date.month + 1),
D: date.date,
h: date.hours,
m: date.minutes,
s: date.seconds
});
} else {
setSelectedDate('');
Expand Down Expand Up @@ -277,72 +291,85 @@ const DateTimeInput = forwardRef((props, ref) => {
}

return (
<div id={inputId + '_' + inputSuffixId} ref={topRef}>
{state && localizedDateTimeData.month_names && (
<div className="dateTimeInput rails-bootstrap-forms-datetime-select">
<div className="row">
{fmt.includes('D') ? (
<input id={inputId + '_' + inputSuffixId + '_day'} name={inputName + '[D]'} style={errorStl} type="number"
min="0" max="31" className="input-2 form-control" value={state.D}
onChange={_handleChangeDay} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('M') ? (
<select id={inputId + '_' + inputSuffixId + '_month'} style={errorStl} name={inputName + '[M]'}
className={_getSelectClassNames()} value={state.M} onChange={_handleChangeMonth}
ref={selectRef} readOnly={disabled || isRangeProps}>
{localizedDateTimeData.month_names.map((month, index) => {
if (month !== null) {
month = month.charAt(0).toUpperCase() + month.slice(1);
}
if (index === 0) {
index = ''
}

return <option key={index} value={index}>{month}</option>
}
)}
</select>
) : null
}
{fmt.includes('Y') ? (
<input id={inputId + '_' + inputSuffixId + '_year'} name={inputName + '[Y]'} style={errorStl}
type="number"
className={'input-4 form-control' + styleMarginRight} value={state.Y}
onChange={_handleChangeYear} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('h') ? (
<input id={inputId + '_' + inputSuffixId + '_hour'} name={inputName + '[h]'} style={errorStl} min="0"
max="23" type="number" className="input-2 form-control" value={state.h}
onChange={_handleChangeHours} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('m') ? (
<input id={inputId + '_' + inputSuffixId + '_minute'} name={inputName + '[m]'} style={errorStl} min="0"
max="59" type="number" className="input-2 form-control" value={state.m}
onChange={_handleChangeMinutes} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('s') ? (
<input id={inputId + '_' + inputSuffixId + '_second'} name={inputName + '[s]'} style={errorStl} min="0"
max="59" type="number" className="input-2 form-control" value={state.s}
onChange={_handleChangeSeconds} readOnly={disabled || isRangeProps}/>
) : null
}
<div className="hidden-datepicker">
<input type="text" ref={hiddenInputRef} value={selectedDate} onChange={_selectDate}/>
</div>
<div className="calendar-button-container">
<a id={inputId + '_calendar_icon' + '_' + inputSuffixId} onClick={_openCloseDatepicker} type="button">
<i className="fa fa-calendar"></i></a>
<a onClick={_clearDatepicker} type="button"><i className="fa fa-times"></i></a>
<div id={inputId + '_' + inputSuffixId} ref={topRef}>
{state && localizedDateTimeData.month_names && (
<div className="dateTimeInput rails-bootstrap-forms-datetime-select">
<div className="">
{fmt.includes('D') ? (
<input id={inputId + '_' + inputSuffixId + '_day'} name={inputName + '[D]'} style={errorStl}
type="number"
min="0" max="31" className="input-2 form-control" value={state.D}
onChange={_handleChangeDay} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('M') ? (
<select id={inputId + '_' + inputSuffixId + '_month'} style={errorStl} name={inputName + '[M]'}
className={_getSelectClassNames()} value={state.M} onChange={_handleChangeMonth}
ref={selectRef} readOnly={disabled || isRangeProps}>
{localizedDateTimeData.month_names.map((month, index) => {
if (month !== null) {
month = month.charAt(0).toUpperCase() + month.slice(1);
}
if (index === 0) {
index = ''
}

return <option key={index} value={index}>{month}</option>
}
)}
</select>
) : null
}
{fmt.includes('Y') ? (
<input id={inputId + '_' + inputSuffixId + '_year'} name={inputName + '[Y]'} style={errorStl}
type="number"
className={'input-4 form-control' + styleMarginRight} value={state.Y}
onChange={_handleChangeYear} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('h') ? (
<input id={inputId + '_' + inputSuffixId + '_hour'} name={inputName + '[h]'} style={errorStl}
min="0"
max="23" type="number" className="input-2 form-control" value={state.h}
onChange={_handleChangeHours} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('m') ? (
<input id={inputId + '_' + inputSuffixId + '_minute'} name={inputName + '[m]'} style={errorStl}
min="0"
max="59" type="number" className="input-2 form-control" value={state.m}
onChange={_handleChangeMinutes} readOnly={disabled || isRangeProps}/>
) : null
}
{fmt.includes('s') ? (
<input id={inputId + '_' + inputSuffixId + '_second'} name={inputName + '[s]'} style={errorStl}
min="0"
max="59" type="number" className="input-2 form-control" value={state.s}
onChange={_handleChangeSeconds} readOnly={disabled || isRangeProps}/>
) : null
}
<div className="calendar-button-container d-inline-flex flex-wrap">
<div id={"datetimepicker-" + inputId}
ref={datepickerContainerRef}
data-td-target-input="nearest"
data-td-target-toggle="nearest">
<input
data-td-target={"#datetimepicker-" + inputId}
className="d-none"
value={selectedDate}
onChange={_selectDate} type="text"/>
<a id={inputId + '_calendar_icon' + '_' + inputSuffixId}
data-td-target={"#datetimepicker-" + inputId}
type="button"
data-td-toggle="datetimepicker"><i className="fa fa-calendar"></i></a>
</div>
<a onClick={_clearDatepicker} type="button"><i className="fa fa-times"></i></a>
</div>
</div>
</div>
</div>
</div>
)}
<span className="error helptext">{errorMsg}</span>
</div>
)}
<span className="error helptext">{errorMsg}</span>
</div>
);
})

Expand Down
Loading

0 comments on commit d0c96c4

Please sign in to comment.