asb_cloud_front/src/components/Table/index.tsx
2021-10-18 11:48:07 +05:00

199 lines
6.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ReactNode } from 'react'
import { Table as RawTable } from 'antd'
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 => {
const placeholder = '-'
let val = placeholder
if((value !== null) &&
(value !== undefined) &&
!Number.isNaN(value) &&
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
}
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 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'))
])
type PaginationContainer = {
skip?: number;
take?: number;
count?: number;
items?: any[] | null;
}
export const makePaginationObject = (paginationContainer:PaginationContainer, ...other:any) => {
let page = 1 + Math.floor((paginationContainer.skip??0) /(paginationContainer.take??1));
return {
...other,
pageSize: paginationContainer.take,
total: paginationContainer.count ?? paginationContainer.items?.length ?? 0,
current: page,
}
}
interface TableContainer {
dataSource: any[];
children?: any;
}
export const Table = ({dataSource, children, ...other}: TableContainer) => {
return <RawTable dataSource={tryAddKeys(dataSource)} {...other}>{children}</RawTable>
}