Добавлен input, сортировка, генератор столбца и парсеры TimeOnly

This commit is contained in:
goodmice 2022-05-31 17:17:14 +05:00
parent 9f924f2c7d
commit b21b327aff
6 changed files with 104 additions and 3 deletions

View File

@ -3,6 +3,7 @@ import { Rule } from 'antd/lib/form'
import { ColumnProps } from 'antd/lib/table' import { ColumnProps } from 'antd/lib/table'
export { makeDateColumn } from './date' export { makeDateColumn } from './date'
export { makeTimeColumn } from './time'
export { export {
RegExpIsFloat, RegExpIsFloat,
makeNumericRender, makeNumericRender,

View File

@ -0,0 +1,26 @@
import { ReactNode } from 'react'
import { formatTime } from '@utils/datetime'
import { makeColumn, columnPropsOther } from '.'
import { makeTimeSorter, TimePickerWrapper, TimePickerWrapperProps } from '..'
export const makeTimeColumn = (
title: ReactNode,
key: string,
utc?: boolean,
format?: string,
other?: columnPropsOther,
pickerOther?: TimePickerWrapperProps,
) => makeColumn(title, key, {
...other,
render: (time) => (
<div className={'text-align-r-container'}>
<span>{formatTime(time, utc, format) ?? '-'}</span>
</div>
),
sorter: makeTimeSorter(key),
input: <TimePickerWrapper isUTC={utc} {...pickerOther} />,
})
export default makeTimeColumn

View File

@ -0,0 +1,31 @@
import { Moment } from 'moment'
import { TimePicker, TimePickerProps } from 'antd'
import { memo, useCallback, useMemo } from 'react'
import { defaultTimeFormat, momentToTimeOnly, timeOnlyToMoment } from '@utils/datetime'
import { TimeOnly } from '@api'
export type TimePickerWrapperProps = Omit<Omit<TimePickerProps, 'value'>, 'onChange'> & {
value?: TimeOnly,
onChange?: (date: TimeOnly | null) => any
isUTC?: boolean
}
export const TimePickerWrapper = memo<TimePickerWrapperProps>(({ value, onChange, isUTC, ...other }) => {
const time = useMemo(() => value ? timeOnlyToMoment(value, isUTC) : null, [value, isUTC])
const onTimeChange = useCallback((time: Moment | null) => onChange?.(time ? momentToTimeOnly(time) : null), [onChange])
return (
<TimePicker
allowClear={false}
format={defaultTimeFormat}
defaultValue={timeOnlyToMoment()}
onChange={onTimeChange}
value={time}
{...other}
/>
)
})
export default TimePickerWrapper

View File

@ -1,6 +1,7 @@
export { makeDateSorter, makeNumericSorter, makeStringSorter } from './sorters' export { makeDateSorter, makeNumericSorter, makeStringSorter, makeTimeSorter } from './sorters'
export { EditableTable, makeActionHandler } from './EditableTable' export { EditableTable, makeActionHandler } from './EditableTable'
export { DatePickerWrapper } from './DatePickerWrapper' export { DatePickerWrapper } from './DatePickerWrapper'
export { TimePickerWrapper } from './TimePickerWrapper'
export { DateRangeWrapper } from './DateRangeWrapper' export { DateRangeWrapper } from './DateRangeWrapper'
export { Table } from './Table' export { Table } from './Table'
export { export {
@ -8,6 +9,7 @@ export {
timezoneOptions, timezoneOptions,
TimezoneSelect, TimezoneSelect,
makeDateColumn, makeDateColumn,
makeTimeColumn,
makeGroupColumn, makeGroupColumn,
makeColumn, makeColumn,
makeColumnsPlanFact, makeColumnsPlanFact,
@ -36,6 +38,7 @@ export type {
} from './Columns' } from './Columns'
export type { DateRangeWrapperProps } from './DateRangeWrapper' export type { DateRangeWrapperProps } from './DateRangeWrapper'
export type { DatePickerWrapperProps } from './DatePickerWrapper' export type { DatePickerWrapperProps } from './DatePickerWrapper'
export type { TimePickerWrapperProps } from './TimePickerWrapper'
export type { BaseTableColumn, TableColumns, TableContainer } from './Table' export type { BaseTableColumn, TableColumns, TableContainer } from './Table'
export const defaultPagination = { export const defaultPagination = {

View File

@ -1,4 +1,6 @@
import { timeOnlyToMoment } from '@utils/datetime'
import { isRawDate } from '@utils' import { isRawDate } from '@utils'
import { TimeOnly } from '@api'
import { DataType } from './Columns' import { DataType } from './Columns'
@ -23,3 +25,14 @@ export const makeDateSorter = <T extends unknown>(key: keyof DataType<T>) => (a:
return date.getTime() - new Date(bdate).getTime() return date.getTime() - new Date(bdate).getTime()
} }
export const makeTimeSorter = <T extends TimeOnly>(key: keyof DataType<T>) => (a: DataType<T>, b: DataType<T>) => {
const elma = a[key]
const elmb = b[key]
if (!elma && !elmb) return 0
if (!elma) return 1
if (!elmb) return -1
return timeOnlyToMoment(elma).diff(timeOnlyToMoment(elmb))
}

View File

@ -1,10 +1,11 @@
import moment from 'moment' import moment, { Moment } from 'moment'
import { SimpleTimezoneDto } from '@api' import { SimpleTimezoneDto, TimeOnly } from '@api'
export type RawDate = number | string | Date export type RawDate = number | string | Date
export const defaultFormat: Readonly<string> = 'DD.MM.YYYY HH:mm' export const defaultFormat: Readonly<string> = 'DD.MM.YYYY HH:mm'
export const defaultTimeFormat: Readonly<string> = 'HH:mm:ss'
export enum timeInS { export enum timeInS {
millisecond = 0.001, millisecond = 0.001,
@ -19,12 +20,25 @@ export function isRawDate(value: unknown): value is RawDate {
return !isNaN(Date.parse(String(value))) return !isNaN(Date.parse(String(value)))
} }
export function isTimeOnly(value: unknown): value is TimeOnly {
if (!value || typeof value !== 'object')
return false
const keys = Object.keys(value)
return ['hour', 'minute', 'second'].every((key) => keys.includes(key))
}
export const formatDate = (date: unknown, utc: boolean = false, format: string = defaultFormat) => { export const formatDate = (date: unknown, utc: boolean = false, format: string = defaultFormat) => {
if (!isRawDate(date)) return null if (!isRawDate(date)) return null
const out = utc ? moment.utc(date).local() : moment(date) const out = utc ? moment.utc(date).local() : moment(date)
return out.format(format) return out.format(format)
} }
export const formatTime = (time: unknown, utc: boolean = false, format: string = defaultTimeFormat) => {
if(!isTimeOnly(time)) return
const out = timeOnlyToMoment(time, utc, format)
return out.format(format)
}
export const periodToString = (time?: number) => { export const periodToString = (time?: number) => {
if (!time || time <= 0) return '00:00:00' if (!time || time <= 0) return '00:00:00'
const days = Math.floor(time / timeInS.day) const days = Math.floor(time / timeInS.day)
@ -77,3 +91,16 @@ export const isTimezoneId = (value: unknown): value is TimezoneId => !!value &&
export const findTimezoneId = (value: SimpleTimezoneDto): TimezoneId => export const findTimezoneId = (value: SimpleTimezoneDto): TimezoneId =>
(isTimezoneId(value.timezoneId) && value.timezoneId) || (isTimezoneId(value.timezoneId) && value.timezoneId) ||
(Object.keys(rawTimezones) as TimezoneId[]).find(id => rawTimezones[id] === value.hours) as TimezoneId (Object.keys(rawTimezones) as TimezoneId[]).find(id => rawTimezones[id] === value.hours) as TimezoneId
export const timeOnlyToMoment = (time?: TimeOnly | null, isUtc?: boolean, format: string = defaultTimeFormat): Moment => {
const input = `${time?.hour ?? 0}:${time?.minute ?? 0}:${time?.second ?? 0}`
return isUtc ? moment.utc(input, format).local() : moment(input, format)
}
export const momentToTimeOnly = (time?: Moment | null): TimeOnly => ({
hour: time?.hour() ?? 0,
minute: time?.minute() ?? 0,
second: time?.second() ?? 0,
millisecond: 0,
ticks: 0,
})