From c2d14cf9650f14aaa8adfeaa2cc600dec2fce398 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Wed, 23 Mar 2022 17:39:58 +0100 Subject: [PATCH] chore: more work on the date picker in logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • issues with date inputs in the date picker, commented out for now • also need to add restrictions in place so restricted dates cannot be selected --- .../interfaces/Settings/Logs/LogTable.tsx | 42 ++-- .../Settings/Logs/PreviewFilterPanel.tsx | 115 ++++++++-- .../components/ui/DatePicker/DatePicker.tsx | 85 +++++-- .../ui/DatePicker/DatePicker.types.ts | 27 +++ .../ui/DatePicker/DateSplitInput.tsx | 216 ++++++++++-------- .../ui/DatePicker/TimeSplitInput.tsx | 20 +- 6 files changed, 333 insertions(+), 172 deletions(-) create mode 100644 studio/components/ui/DatePicker/DatePicker.types.ts diff --git a/studio/components/interfaces/Settings/Logs/LogTable.tsx b/studio/components/interfaces/Settings/Logs/LogTable.tsx index aa166827dd3..59657136efe 100644 --- a/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -46,28 +46,28 @@ const LogTable = ({ isCustomQuery, data = [], queryType }: Props) => { (v) => ({ key: v, name: v, - width: hasLogDataFormat && v === 'timestamp' ? 210 : undefined, + // width: hasLogDataFormat && v === 'timestamp' ? 210 : undefined, resizable: true, - headerRenderer: () => { - return
{v}
- }, - formatter: ({ row }: any) => { - let value = row[v] - if (hasLogDataFormat && v === 'timestamp') { - value = dayjs(Number(row['timestamp']) / 1000).toISOString() - } - return ( -

- {value} -

- ) - }, + // headerRenderer: () => { + // return
{v}
+ // }, + // formatter: ({ row }: any) => { + // let value = row[v] + // if (hasLogDataFormat && v === 'timestamp') { + // value = dayjs(Number(row['timestamp']) / 1000).toISOString() + // } + // return ( + //

+ // {value} + //

+ // ) + // }, }) ) diff --git a/studio/components/interfaces/Settings/Logs/PreviewFilterPanel.tsx b/studio/components/interfaces/Settings/Logs/PreviewFilterPanel.tsx index 4009b9aea69..e79a7180d1b 100644 --- a/studio/components/interfaces/Settings/Logs/PreviewFilterPanel.tsx +++ b/studio/components/interfaces/Settings/Logs/PreviewFilterPanel.tsx @@ -65,7 +65,9 @@ const PreviewFilterPanel: FC = ({ table, }) => { const [search, setSearch] = useState('') + const [to, setTo] = useState({ value: '', error: '' }) + const [from, setFrom] = useState({ value: '', error: '' }) const [defaultTimestamp, setDefaultTimestamp] = useState(dayjs().utc().toISOString()) const [localSearchValue, setlocalSearchValue] = useState(search) @@ -85,14 +87,6 @@ const PreviewFilterPanel: FC = ({ } }, [defaultToValue]) - const handleFromChange = (e: React.ChangeEvent) => { - const value = e.target.value - if (value !== '' && isNaN(Date.parse(value))) { - setTo({ value, error: 'Invalid ISO 8601 timestamp' }) - } else { - setTo({ value, error: '' }) - } - } const handleFromReset = async () => { setTo({ value: '', error: '' }) const value = dayjs().utc().toISOString() @@ -102,12 +96,12 @@ const PreviewFilterPanel: FC = ({ // const handleSearch = () => onSearch({ query: search, to: to.value }) - const handleSearch = (value: string) => - onSearch({ - query: value, - to: to.value, - // , from: from.value - }) + // const handleSearch = (value: string) => + // onSearch({ + // query: value, + // to: to.value, + // // , from: from.value + // }) const RefreshButton = () => { return !isCustomQuery ? ( @@ -142,8 +136,38 @@ const PreviewFilterPanel: FC = ({ ) : null } + const handleToChange = (e: React.ChangeEvent) => { + const value = e.target.value + if (value !== '' && isNaN(Date.parse(value))) { + setTo({ value, error: 'Invalid ISO 8601 timestamp' }) + } else { + setTo({ value, error: '' }) + } + } + + const handleFromChange = (e: React.ChangeEvent) => { + const value = e.target.value + if (value !== '' && isNaN(Date.parse(value))) { + setFrom({ value, error: 'Invalid ISO 8601 timestamp' }) + } else { + setFrom({ value, error: '' }) + } + } + + const handleReset = async () => { + setTo({ value: '', error: '' }) + setFrom({ value: '', error: '' }) + const value = dayjs().utc().toISOString() + setDefaultTimestamp(value) + onSearch({ query: search, to: '', from: '' }) + } + + const showReset = to.value !== '' || from.value !== '' + const showFromReset = to.value !== '' + const handleSearch = () => onSearch({ query: search, to: to.value, from: from.value }) + // console.log('this is what is going through', FILTER_OPTIONS[table]) return ( @@ -238,10 +262,69 @@ const PreviewFilterPanel: FC = ({ })} +
+ + + +
+ +
+ + } + > + +
+ {showReset && ( +
+ {/* {!isCustomQuery && ( +
+

Show event chart

+ +
+ )} */} + {!isCustomQuery && ( <>
- = ({ > {to.value ? 'Custom' : 'Now'} - + */} {/* Clear the filters could be here */}
diff --git a/studio/components/ui/DatePicker/DatePicker.tsx b/studio/components/ui/DatePicker/DatePicker.tsx index 1fd6d03f92a..3d8f33d0dce 100644 --- a/studio/components/ui/DatePicker/DatePicker.tsx +++ b/studio/components/ui/DatePicker/DatePicker.tsx @@ -20,6 +20,7 @@ import { import { format } from 'date-fns' import TimeSplitInput from './TimeSplitInput' +import DateSplitInput from './DateSplitInput' import DividerSlash from './DividerSlash' import dayjs from 'dayjs' @@ -32,6 +33,10 @@ dayjs.extend(timezone) interface RootProps { handleChange?: ({}) => void + initialValues?: { + to: number + from: number + } } const START_DATE_DEFAULT = new Date() @@ -44,7 +49,7 @@ const TIME_NOW = format(new Date(), 'HH:mm:ss').split(':') const START_TIME_DEFAULT = { HH: TIME_NOW[0], mm: TIME_NOW[1], ss: TIME_NOW[2] } const END_TIME_DEFAULT = { HH: TIME_NOW[0], mm: TIME_NOW[1], ss: TIME_NOW[2] } -function _DatePicker({ handleChange }: RootProps) { +function _DatePicker({ handleChange, initialValues }: RootProps) { const [open, setOpen] = useState(false) const [showTime, setShowTime] = useState(true) @@ -58,21 +63,49 @@ function _DatePicker({ handleChange }: RootProps) { const [startTime, setStartTime] = useState(START_TIME_DEFAULT) const [endTime, setEndTime] = useState(END_TIME_DEFAULT) + if (initialValues) { + const from = dayjs(initialValues.from) + const to = dayjs(initialValues.to) + } + + function handleDatePickerChange(dates: [from: string, to: string]) { + const [from, to] = dates + + console.log('start', from) + console.log('end', to) + setStartDate(from) + setEndDate(to) + } + function handleSubmit() { setOpen(false) setAppliedStartDate(startDate) setAppliedEndDate(endDate) - if (handleChange) - handleChange({ - from: dayjs( - `${format(new Date(startDate), 'yyyy-MM-dd')} ${Object.values(startTime).join(':')}` - ).toISOString(), - to: dayjs( - `${format(new Date(endDate), 'yyyy-MM-dd')} ${Object.values(endTime).join(':')}` - ).toISOString(), - }) + const from = `${format(new Date(startDate), 'yyyy-MM-dd')} ${Object.values(startTime).join( + ':' + )}` + const to = `${format(new Date(endDate), 'yyyy-MM-dd')} ${Object.values(endTime).join(':')}` + + function isoPayload() { + return { + from: dayjs(from).toISOString(), + to: dayjs(to).toISOString(), + } + } + + function unixPayload() { + return { + from: dayjs(from).valueOf(), + to: dayjs(to).valueOf(), + } + } + + // console.log('unixPayload', unixPayload()) + // console.log('isoPayload', isoPayload()) + + if (handleChange) handleChange(unixPayload()) } function handleClear() { @@ -101,7 +134,7 @@ function _DatePicker({ handleChange }: RootProps) { <>
-
-
+
*/} + + {/* setStartDate(e)} + startDate={startDate} + endDate={endDate} + /> */} {showTime && (
-
-
+
*/} + {/* setEndDate(e)} + startDate={startDate} + endDate={endDate} + /> */} {showTime && ( { - const [start, end] = date - console.log('start', start) - console.log('end', end) - setStartDate(start) - // setEndDate(!end ? start : end) - setEndDate(end) + onChange={(dates) => { + handleDatePickerChange(dates) }} dateFormat="MMMM d, yyyy h:mm aa" startDate={startDate} diff --git a/studio/components/ui/DatePicker/DatePicker.types.ts b/studio/components/ui/DatePicker/DatePicker.types.ts new file mode 100644 index 00000000000..feeb68dfd74 --- /dev/null +++ b/studio/components/ui/DatePicker/DatePicker.types.ts @@ -0,0 +1,27 @@ +export type Time = { + HH: string + mm: string + ss: string +} + +export type TimeType = 'HH' | 'mm' | 'ss' + +export interface TimeSplitInputProps { + time: Time + setTime: (x: Time) => void + type: 'start' | 'end' + setStartTime: (x: Time) => void + setEndTime: (x: Time) => void + startTime: Time + endTime: Time + startDate: any + endDate: any +} + +export type Date = { + YYYY: string + MM: string + DD: string +} + +export type DateType = 'YYYY' | 'MM' | 'DD' diff --git a/studio/components/ui/DatePicker/DateSplitInput.tsx b/studio/components/ui/DatePicker/DateSplitInput.tsx index 3596a985a9a..aeeda582845 100644 --- a/studio/components/ui/DatePicker/DateSplitInput.tsx +++ b/studio/components/ui/DatePicker/DateSplitInput.tsx @@ -1,87 +1,112 @@ import React, { useState } from 'react' import { IconClock } from '@supabase/ui' +import DividerSlash from './DividerSlash' import { format } from 'date-fns' +import { DateType } from './DatePicker.types' +import dayjs from 'dayjs' -type TimeType = 'DD' | 'MM' | 'YYYY' +var advancedFormat = require('dayjs/plugin/advancedFormat') +var utc = require('dayjs/plugin/utc') +var timezone = require('dayjs/plugin/timezone') // dependent on utc plugin -type Time = { - HH: string - mm: string - ss: string -} +dayjs.extend(advancedFormat) +dayjs.extend(utc) +dayjs.extend(timezone) +dayjs.tz.guess() + +// type TimeType = 'DD' | 'MM' | 'YYYY' + +// type Time = { +// HH: string +// mm: string +// ss: string +// } interface TimeSplitInputProps { - time: Time - setTime: (x: Time) => void + date: string + // setTime: (x: Time) => void type: 'start' | 'end' - setStartTime: (x: Time) => void - setEndTime: (x: Time) => void - startTime: Time - endTime: Time + // setStartTime: (x: Time) => void + // setEndTime: (x: Time) => void + // startTime: Time + // endTime: Time startDate: any endDate: any + setDate: ({}) => void } -const TimeSplitInput = ({ +const DateSplitInput = ({ type, - time, - setTime, - setStartTime, - setEndTime, - startTime, - endTime, + date, + // setTime, + // setStartTime, + // setEndTime, + // startTime, + // endTime, startDate, endDate, + setDate, }: TimeSplitInputProps) => { const [focus, setFocus] = useState(false) - function handleOnChange(value: string, valueType: TimeType) { + const [splitDate, setSplitDate] = useState({ + DD: format(new Date(date), 'dd'), + MM: format(new Date(date), 'MM'), + YYYY: format(new Date(date), 'yyyy'), + }) + + function handleOnChange() { // console.log('handleOnChange') const payload = { - HH: time.HH, - mm: time.mm, - ss: time.ss, + DD: splitDate.DD, + MM: splitDate.MM, + YYYY: splitDate.YYYY, } - if (value.length > 2) return - switch (valueType) { - case 'DD': - if (value && Number(value) > 23) return - break - case 'MM': - if (value && Number(value) > 59) return - break - case 'YYYY': - if (value && Number(value) > 59) return - break - default: - break - } + // if (Number(payload.YYYY) > 2021) { + // payload.YYYY = 2021 + // } + // if (value.length > 2) return + + // switch (valueType) { + // case 'DD': + // if (value && Number(value) > 23) return + // break + // case 'MM': + // if (value && Number(value) > 59) return + // break + // case 'YYYY': + // if (value && Number(value) > 59) return + // break + // default: + // break + // } // console.log('got here') - payload[valueType] = value - setTime({ ...payload }) + // payload[valueType] = value - // if (endTimeChanges) { - // setEndTime(endTimePayload) - // } + const dns_format = new Date(Number(payload.YYYY), Number(payload.MM), Number(payload.DD)) + + // console.log('format:', dns_format) + + setDate(dns_format) } - function handleOnBlur(valueType: TimeType) { + function sanitize(valueType: DateType) { // console.log('handle blur') - const _time = time - // console.log('_time.HH.length', _time.HH.length) + const _time = splitDate + // console.log('_time.MM.length', _time.MM.length) - if (_time.HH.length === 1) _time.HH = '0' + _time.HH - if (_time.mm.length === 1) _time.mm = '0' + _time.mm - if (_time.ss.length === 1) _time.ss = '0' + _time.ss + if (_time.DD.length === 1) _time.DD = '0' + _time.DD + if (_time.MM.length === 1) _time.MM = '0' + _time.MM + if (_time.YYYY.length === 1) _time.YYYY = '0' + _time.YYYY - if (!_time.HH) _time.HH = '00' - if (!_time.mm) _time.mm = '00' - if (!_time.ss) _time.ss = '00' + if (!_time.DD) _time.DD = '00' + if (!_time.MM) _time.MM = '00' + if (!_time.YYYY) _time.YYYY = '00' // console.log('_time', _time) @@ -101,35 +126,35 @@ const TimeSplitInput = ({ if (type === 'start') { // console.log('HH in start switch') - if (_time.HH && Number(_time.HH) > Number(endTime.HH)) { - endTimePayload.HH = _time.HH + if (_time.MM && Number(_time.MM) > Number(endTime.HH)) { + endTimePayload.HH = _time.MM endTimeChanges = true } if ( // also check the hour - _time.HH && - Number(_time.HH) >= Number(endTime.HH) && + _time.MM && + Number(_time.MM) >= Number(endTime.HH) && // check the minutes - _time.mm && - Number(_time.mm) > Number(endTime.mm) + _time.MM && + Number(_time.MM) > Number(endTime.mm) ) { - endTimePayload.mm = _time.mm + endTimePayload.mm = _time.MM endTimeChanges = true } if ( // also check the hour - _time.HH && - Number(_time.HH) >= Number(endTime.HH) && + _time.MM && + Number(_time.MM) >= Number(endTime.HH) && // check the minutes - _time.mm && - Number(_time.mm) >= Number(endTime.mm) && + _time.MM && + Number(_time.MM) >= Number(endTime.mm) && // check the seconds - _time.ss && - Number(_time.ss) > Number(endTime.ss) + _time.YYYY && + Number(_time.YYYY) > Number(endTime.ss) ) { - endTimePayload.ss = _time.ss + endTimePayload.ss = _time.YYYY endTimeChanges = true } } @@ -137,35 +162,35 @@ const TimeSplitInput = ({ if (type === 'end') { // console.log('HH in start switch') - if (_time.HH && Number(_time.HH) < Number(startTime.HH)) { - startTimePayload.HH = _time.HH + if (_time.MM && Number(_time.MM) < Number(startTime.HH)) { + startTimePayload.HH = _time.MM startTimeChanges = true } if ( // also check the hour - _time.HH && - Number(_time.HH) <= Number(startTime.HH) && + _time.MM && + Number(_time.MM) <= Number(startTime.HH) && // check the minutes - _time.mm && - Number(_time.mm) < Number(startTime.mm) + _time.MM && + Number(_time.MM) < Number(startTime.mm) ) { - startTimePayload.mm = _time.mm + startTimePayload.mm = _time.MM startTimeChanges = true } if ( // also check the hour - _time.HH && - Number(_time.HH) <= Number(startTime.HH) && + _time.MM && + Number(_time.MM) <= Number(startTime.HH) && // check the minutes - _time.mm && - Number(_time.mm) <= Number(startTime.mm) && + _time.MM && + Number(_time.MM) <= Number(startTime.mm) && // check the seconds - _time.ss && - Number(_time.ss) < Number(startTime.ss) + _time.YYYY && + Number(_time.YYYY) < Number(startTime.ss) ) { - startTimePayload.ss = _time.ss + startTimePayload.ss = _time.YYYY startTimeChanges = true } } @@ -196,43 +221,44 @@ const TimeSplitInput = ({ ${focus && ' outline outline-2 outline-scale-500 border-scale-800'} `} > -
- -
handleOnBlur('DD')} + onBlur={() => handleOnChange()} onFocus={handleFocus} pattern="[0-31]*" placeholder="00" - onChange={(e) => handleOnChange(e.target.value, 'DD')} + maxLength={2} + onChange={(e) => setSplitDate({ ...splitDate, DD: e.target.value })} aria-label="Days" className="text-scale-1200 w-5 bg-transparent text-center outline-none" - value={time.HH} + value={splitDate.DD} /> - : + handleOnBlur('MM')} + onBlur={() => handleOnChange()} onFocus={handleFocus} pattern="[0-12]*" placeholder="00" - onChange={(e) => handleOnChange(e.target.value, 'MM')} + maxLength={2} + onChange={(e) => setSplitDate({ ...splitDate, MM: e.target.value })} aria-label="Months" className="text-scale-1200 w-5 bg-transparent text-center outline-none" - value={time.mm} + value={splitDate.MM} /> - : + handleOnBlur('YYYY')} + onBlur={() => handleOnChange()} onFocus={handleFocus} pattern="[2021-2022]*" placeholder="00" - onChange={(e) => handleOnChange(e.target.value, 'YYYY')} + maxLength={4} + minLength={4} + onChange={(e) => setSplitDate({ ...splitDate, YYYY: e.target.value })} aria-label="Years" - className="text-scale-1200 w-5 bg-transparent text-center outline-none" - value={time.ss} + className="text-scale-1200 w-8 bg-transparent text-center outline-none" + value={splitDate.YYYY} /> ) } -export default TimeSplitInput +export default DateSplitInput diff --git a/studio/components/ui/DatePicker/TimeSplitInput.tsx b/studio/components/ui/DatePicker/TimeSplitInput.tsx index c5d79314766..a6c31c56e5d 100644 --- a/studio/components/ui/DatePicker/TimeSplitInput.tsx +++ b/studio/components/ui/DatePicker/TimeSplitInput.tsx @@ -3,25 +3,7 @@ import { IconClock } from '@supabase/ui' import { format } from 'date-fns' -type TimeType = 'HH' | 'mm' | 'ss' - -type Time = { - HH: string - mm: string - ss: string -} - -interface TimeSplitInputProps { - time: Time - setTime: (x: Time) => void - type: 'start' | 'end' - setStartTime: (x: Time) => void - setEndTime: (x: Time) => void - startTime: Time - endTime: Time - startDate: any - endDate: any -} +import { TimeType, Time, TimeSplitInputProps } from './DatePicker.types' const TimeSplitInput = ({ type,