-
Notifications
You must be signed in to change notification settings - Fork 21
/
DateTimePicker.tsx
99 lines (91 loc) · 3.37 KB
/
DateTimePicker.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* An example Custom Component:
* https://github.com/CarlosNZ/json-edit-react#custom-nodes
*
* A date/time picker which can be configure to show (using the
* CustomNodeDefinitions at the bottom of this file) when an ISO date/time
* string is present in the JSON data, and present a Date picker interface
* rather than requiring the user to edit the ISO string directly.
*/
import React from 'react'
import DatePicker from 'react-datepicker'
import { Button } from '@chakra-ui/react'
import { CustomNodeProps, CustomNodeDefinition } from '../_imports'
// Styles
import 'react-datepicker/dist/react-datepicker.css'
// For better matching with Chakra-UI
import './style.css'
interface DatePickerCustomProps {
dateFormat: string
showTimeSelect: boolean
}
export const DateTimePicker: React.FC<CustomNodeProps<DatePickerCustomProps>> = ({
value,
setValue,
handleEdit,
handleCancel,
handleKeyPress,
isEditing,
setIsEditing,
getStyles,
nodeData,
customNodeProps,
}) => {
const { dateFormat = 'MMM d, yyyy h:mm aa', showTimeSelect = true } = customNodeProps ?? {}
const date = new Date(value as string)
const textColour = getStyles('container', nodeData).backgroundColor
const okColour = getStyles('iconOk', nodeData).color
const cancelColour = getStyles('iconCancel', nodeData).color
const stringStyle = getStyles('string', nodeData)
return isEditing ? (
// Picker only shows up when "editing". Due to the `showOnView: false` in
// the definition below, this component will not show at all when viewing
// (and so will show raw ISO strings). However, we've defined an alternative
// here too, when showOnView == true, in which case the date/time string is
// shown as a localised date/time.
<DatePicker
// Check to prevent invalid date (from previous data value) crashing the
// component
selected={isNaN(date as any) ? null : date}
showTimeSelect={showTimeSelect}
dateFormat={dateFormat}
onChange={(date: Date | null) => date && setValue(date.toISOString())}
open={true}
onKeyDown={handleKeyPress}
>
<div style={{ display: 'inline-flex', gap: 10 }}>
{/* These buttons are not really necessary -- you can either use the
standard Ok/Cancel icons, or keyboard Enter/Esc, but shown for demo
purposes */}
<Button color={textColour} backgroundColor={okColour} onClick={handleEdit}>
OK
</Button>
<Button color={textColour} backgroundColor={cancelColour} onClick={handleCancel}>
Cancel
</Button>
</div>
</DatePicker>
) : (
<div
// Double-click behaviour same as standard elements
onDoubleClick={() => setIsEditing(true)}
className="jer-value-string"
style={stringStyle}
>
"{new Date(value as string).toLocaleDateString()}"
</div>
)
}
// Definition for custom node behaviour
export const dateNodeDefinition: CustomNodeDefinition = {
// Condition is a regex to match ISO strings
condition: ({ value }) =>
typeof value === 'string' &&
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[\d\.]*(Z?|[\+-][\d:]+)$/.test(value),
element: DateTimePicker, // the component defined above
showOnView: false,
showOnEdit: true,
name: 'Date', // shown in the Type selector menu
showInTypesSelector: true,
defaultValue: new Date().toISOString(), // when instantiated, default to the current date/time
}