forked from ddrilling/asb_cloud_front
238 lines
7.4 KiB
TypeScript
238 lines
7.4 KiB
TypeScript
import { ReactNode } from 'react'
|
||
import { Select, Table as RawTable } from 'antd'
|
||
import { OptionsType } from 'rc-select/lib/interface'
|
||
import { tryAddKeys } from './EditableTable'
|
||
import { makeNumericSorter, makeStringSorter} from './sorters'
|
||
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
|
||
export { EditableTable } from './EditableTable'
|
||
export { DatePickerWrapper } from './DatePickerWrapper'
|
||
export { SelectFromDictionary } from './SelectFromDictionary'
|
||
|
||
export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/
|
||
export const formatDate='YYYY.MM.DD HH:mm'
|
||
|
||
export const makeNumericRender = (fixed?: number) => (value: any, row: object): ReactNode => {
|
||
let val = '-'
|
||
if ((value ?? null) !== null && Number.isFinite(+value)) {
|
||
val = !!fixed
|
||
? (+value).toFixed(fixed)
|
||
: (+value).toPrecision(5)
|
||
}
|
||
|
||
return (
|
||
<div className={'text-align-r-container'}>
|
||
<span>{val}</span>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export const makeNumericColumnOptions = (fixed?: number, sorterKey?: string ) => ({
|
||
editable: true,
|
||
initialValue: 0,
|
||
width:100,
|
||
sorter: sorterKey? makeNumericSorter(sorterKey) : null,
|
||
formItemRules: [
|
||
{
|
||
required: true,
|
||
message: `Введите число`,
|
||
pattern: RegExpIsFloat,
|
||
},
|
||
],
|
||
render: makeNumericRender(fixed),
|
||
})
|
||
|
||
/*
|
||
other - объект с дополнительными свойствами колонки
|
||
поддерживаются все базовые свойства из описания https://ant.design/components/table/#Column
|
||
плю дополнительные для колонок EditableTable: */
|
||
interface columnPropsOther {
|
||
// редактируемая колонка
|
||
editable?: boolean
|
||
// react компонента редактора
|
||
input?: ReactNode
|
||
// значение может быть пустым
|
||
isRequired?: boolean
|
||
// css класс для <FormItem/>, если требуется
|
||
formItemClass?: string
|
||
// массив правил валидации значений https://ant.design/components/form/#Rule
|
||
formItemRules?: any[]
|
||
// дефолтное значение при добавлении новой строки
|
||
initialValue?: string|number
|
||
|
||
render?: (...attributes: any) => any
|
||
}
|
||
|
||
export const makeColumn = (title: string | ReactNode, key: string, other?: columnPropsOther) => ({
|
||
title: title,
|
||
key: key,
|
||
dataIndex: key,
|
||
...other,
|
||
})
|
||
|
||
export const makeColumnsPlanFact = (
|
||
title:string | ReactNode,
|
||
key:string | string[],
|
||
columsOther?: any | any[],
|
||
gruopOther?: any
|
||
) => {
|
||
let keyPlanLocal = key
|
||
let keyFactLocal = key
|
||
|
||
if (key instanceof Array) {
|
||
keyPlanLocal = key[0]
|
||
keyFactLocal = key[1]
|
||
} else {
|
||
keyPlanLocal = key + 'Plan'
|
||
keyFactLocal = key + 'Fact'
|
||
}
|
||
|
||
let columsOtherLoacl : any[2]
|
||
if (columsOther instanceof Array)
|
||
columsOtherLoacl = [columsOther[0], columsOther[1]]
|
||
else
|
||
columsOtherLoacl = [columsOther, columsOther]
|
||
|
||
return {
|
||
title: title,
|
||
...gruopOther,
|
||
children: [
|
||
makeColumn('план', keyPlanLocal, columsOtherLoacl[0]),
|
||
makeColumn('факт', keyFactLocal, columsOtherLoacl[1]),
|
||
]
|
||
}
|
||
}
|
||
|
||
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
|
||
dataItem[key] === filterValue
|
||
|
||
export const makeGroupColumn = (title: string, children: object[]) => ({
|
||
title: title,
|
||
children: children,
|
||
})
|
||
|
||
export const makeTextColumn = (
|
||
title: string,
|
||
dataIndex: string,
|
||
filters: object[],
|
||
sorter?: (key: string) => any,
|
||
render?: any,
|
||
other?: any
|
||
) => ({
|
||
title: title,
|
||
dataIndex: dataIndex,
|
||
key: dataIndex,
|
||
filters: filters,
|
||
onFilter: filters ? makeFilterTextMatch(dataIndex) : null,
|
||
sorter: sorter ?? makeStringSorter(dataIndex),
|
||
render: render,
|
||
...other
|
||
})
|
||
|
||
export const makeNumericColumn = (
|
||
title: string,
|
||
dataIndex: string,
|
||
filters: object[],
|
||
filterDelegate: (key: string | number) => any,
|
||
renderDelegate: (_: any, row: object) => any,
|
||
width: string,
|
||
other?: columnPropsOther
|
||
) => ({
|
||
title: title,
|
||
dataIndex: dataIndex,
|
||
key: dataIndex,
|
||
filters: filters,
|
||
onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
|
||
sorter: makeNumericSorter(dataIndex),
|
||
width: width,
|
||
render: renderDelegate??makeNumericRender(),
|
||
align: 'right',
|
||
...other
|
||
})
|
||
|
||
export const makeNumericColumnPlanFact = (
|
||
title: string,
|
||
dataIndex: string,
|
||
filters: object[],
|
||
filterDelegate: (key: string | number) => any,
|
||
renderDelegate: (_: any, row: object) => any,
|
||
width: string
|
||
) => makeGroupColumn(title, [
|
||
makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width),
|
||
makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width),
|
||
])
|
||
|
||
export const makeNumericStartEnd = (
|
||
title: string,
|
||
dataIndex: string,
|
||
fixed: number,
|
||
filters: object[],
|
||
filterDelegate: (key: string | number) => any,
|
||
renderDelegate: (_: any, row: object) => any,
|
||
width: string,
|
||
) => makeGroupColumn(title, [
|
||
makeNumericColumn('старт', dataIndex + 'Start', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Start')),
|
||
makeNumericColumn('конец', dataIndex + 'End', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'End'))
|
||
])
|
||
|
||
export const makeNumericMinMax = (
|
||
title: string,
|
||
dataIndex: string,
|
||
fixed: number,
|
||
filters: object[],
|
||
filterDelegate: (key: string | number) => any,
|
||
renderDelegate: (_: any, row: object) => any,
|
||
width: string,
|
||
) => makeGroupColumn(title, [
|
||
makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
|
||
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max')),
|
||
])
|
||
|
||
export const makeNumericAvgRange = (
|
||
title: string,
|
||
dataIndex: string,
|
||
fixed: number,
|
||
filters: object[],
|
||
filterDelegate: (key: string | number) => any,
|
||
renderDelegate: (_: any, row: object) => any,
|
||
width: string
|
||
) => makeGroupColumn(title, [
|
||
makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
|
||
makeNumericColumn('сред', dataIndex + 'Avg', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Avg')),
|
||
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max'))
|
||
])
|
||
|
||
export const makeSelectColumn = <T extends unknown = string>(
|
||
title: string,
|
||
dataIndex: string,
|
||
options: OptionsType,
|
||
defaultValue?: T,
|
||
other?: columnPropsOther
|
||
) => makeColumn(title, dataIndex, {
|
||
input: <Select options={options}/>,
|
||
render: (value) => options.find(option => option?.value === value)?.label ?? defaultValue ?? '--',
|
||
...other
|
||
})
|
||
|
||
type PaginationContainer = {
|
||
skip?: number
|
||
take?: number
|
||
count?: number
|
||
items?: any[] | null
|
||
}
|
||
|
||
export const makePaginationObject = (сontainer: PaginationContainer, ...other: any) => ({
|
||
...other,
|
||
pageSize: сontainer.take,
|
||
total: сontainer.count ?? сontainer.items?.length ?? 0,
|
||
current: 1 + Math.floor((сontainer.skip ?? 0) / (сontainer.take ?? 1))
|
||
})
|
||
|
||
interface TableContainer {
|
||
dataSource: any[]
|
||
children?: any
|
||
}
|
||
|
||
export const Table = ({dataSource, children, ...other}: TableContainer) => (
|
||
<RawTable dataSource={tryAddKeys(dataSource)} {...other}>{children}</RawTable>
|
||
)
|