Улучшена типизация таблиц и методов работы с ними

This commit is contained in:
goodmice 2022-10-06 11:46:48 +05:00
parent c33674c6c5
commit 443f14c0a8
No known key found for this signature in database
GPG Key ID: 63EA771203189CF1
5 changed files with 39 additions and 26 deletions

View File

@ -10,18 +10,17 @@ import { tryAddKeys } from './EditableTable'
import '@styles/index.css' import '@styles/index.css'
export type BaseTableColumn<T = any> = ColumnGroupType<T> | ColumnType<T> export type BaseTableColumn<T> = ColumnGroupType<T> | ColumnType<T>
export type TableColumns<T = any> = OmitExtends<BaseTableColumn<T>, TableColumnSettings>[] export type TableColumns<T> = OmitExtends<BaseTableColumn<T>, TableColumnSettings>[]
export type TableContainer = TableProps<any> & { export type TableContainer<T> = TableProps<T> & {
columns: TableColumns columns: TableColumns<T>
dataSource: any[]
tableName?: string tableName?: string
showSettingsChanger?: boolean showSettingsChanger?: boolean
} }
export const Table = memo<TableContainer>(({ columns, dataSource, tableName, showSettingsChanger, ...other }) => { const _Table = <T extends object>({ columns, dataSource, tableName, showSettingsChanger, ...other }: TableContainer<T>) => {
const [newColumns, setNewColumns] = useState<TableColumns>([]) const [newColumns, setNewColumns] = useState<TableColumns<T>>([])
const [settings, setSettings] = useState<TableSettings>({}) const [settings, setSettings] = useState<TableSettings>({})
const onSettingsChanged = useCallback((settings?: TableSettings | null) => { const onSettingsChanged = useCallback((settings?: TableSettings | null) => {
@ -52,6 +51,8 @@ export const Table = memo<TableContainer>(({ columns, dataSource, tableName, sho
{...other} {...other}
/> />
) )
}) }
export const Table = memo(_Table) as typeof _Table
export default Table export default Table

View File

@ -7,7 +7,7 @@ import { TableColumnSettings, makeTableSettings, mergeTableSettings, TableSettin
import { TableColumns } from './Table' import { TableColumns } from './Table'
import { makeColumn } from '.' import { makeColumn } from '.'
const parseSettings = (columns?: TableColumns, settings?: TableSettings | null): TableColumnSettings[] => { const parseSettings = <T extends object>(columns?: TableColumns<T>, settings?: TableSettings | null): TableColumnSettings[] => {
const newSettings = mergeTableSettings(makeTableSettings(columns ?? []), settings ?? {}) const newSettings = mergeTableSettings(makeTableSettings(columns ?? []), settings ?? {})
return Object.values(newSettings).map((set, i) => ({ ...set, key: i })) return Object.values(newSettings).map((set, i) => ({ ...set, key: i }))
} }
@ -15,14 +15,14 @@ const parseSettings = (columns?: TableColumns, settings?: TableSettings | null):
const unparseSettings = (columns: TableColumnSettings[]): TableSettings => const unparseSettings = (columns: TableColumnSettings[]): TableSettings =>
Object.fromEntries(columns.map((column) => [column.columnName, column])) Object.fromEntries(columns.map((column) => [column.columnName, column]))
export type TableSettingsChangerProps = { export type TableSettingsChangerProps<T extends object> = {
title?: string title?: string
columns?: TableColumns columns?: TableColumns<T>
settings?: TableSettings | null settings?: TableSettings | null
onChange: (settings: TableSettings | null) => void onChange: (settings: TableSettings | null) => void
} }
export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, columns, settings, onChange }) => { const _TableSettingsChanger = <T extends object>({ title, columns, settings, onChange }: TableSettingsChangerProps<T>) => {
const [visible, setVisible] = useState<boolean>(false) const [visible, setVisible] = useState<boolean>(false)
const [newSettings, setNewSettings] = useState<TableColumnSettings[]>(parseSettings(columns, settings)) const [newSettings, setNewSettings] = useState<TableColumnSettings[]>(parseSettings(columns, settings))
const [tableColumns, setTableColumns] = useState<ColumnsType<TableColumnSettings>>([]) const [tableColumns, setTableColumns] = useState<ColumnsType<TableColumnSettings>>([])
@ -36,10 +36,12 @@ export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, co
}, []) }, [])
const toogleAll = useCallback((show: boolean) => { const toogleAll = useCallback((show: boolean) => {
setNewSettings((oldSettings) => oldSettings.map((column) => { setNewSettings((oldSettings) =>
column.visible = show oldSettings.map((column) => {
return column column.visible = show
})) return column
})
)
}, []) }, [])
useEffect(() => { useEffect(() => {
@ -49,7 +51,9 @@ export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, co
title: () => ( title: () => (
<> <>
Показать Показать
<Button type={'link'} onClick={() => toogleAll(true)}>Показать все</Button> <Button type={'link'} onClick={() => toogleAll(true)}>
Показать все
</Button>
</> </>
), ),
render: (visible: boolean, _?: TableColumnSettings, index: number = NaN) => ( render: (visible: boolean, _?: TableColumnSettings, index: number = NaN) => (
@ -59,7 +63,7 @@ export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, co
unCheckedChildren={'Скрыт'} unCheckedChildren={'Скрыт'}
onChange={(visible) => onVisibilityChange(index, visible)} onChange={(visible) => onVisibilityChange(index, visible)}
/> />
) ),
}), }),
]) ])
}, [toogleAll, onVisibilityChange]) }, [toogleAll, onVisibilityChange])
@ -88,9 +92,17 @@ export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, co
> >
<Table columns={tableColumns} dataSource={newSettings} /> <Table columns={tableColumns} dataSource={newSettings} />
</Modal> </Modal>
<Button size={'small'} style={{ position: 'absolute', left: 0, top: 0, opacity: .5 }} type={'link'} onClick={() => setVisible(true)} icon={<SettingOutlined />}/> <Button
size={'small'}
style={{ position: 'absolute', left: 0, top: 0, opacity: 0.5 }}
type={'link'}
onClick={() => setVisible(true)}
icon={<SettingOutlined />}
/>
</> </>
) )
}) }
export const TableSettingsChanger = memo(_TableSettingsChanger) as typeof _TableSettingsChanger
export default TableSettingsChanger export default TableSettingsChanger

View File

@ -8,7 +8,7 @@
* @param data Копируемые данные * @param data Копируемые данные
* @returns Полная копия `data` * @returns Полная копия `data`
*/ */
export const deepCopy = <T extends any>(data: T): T => JSON.parse(JSON.stringify(data ?? null)) export const deepCopy = <T,>(data: T): T => JSON.parse(JSON.stringify(data ?? null))
/** /**
* Маппинг полей объекта * Маппинг полей объекта

View File

@ -21,7 +21,7 @@ export const getArrayFromLocalStorage = <T extends string = string>(name: string
return raw.split(sep).map<T>(elm => elm as T) return raw.split(sep).map<T>(elm => elm as T)
} }
export const getJSON = <T extends any>(name: StorageNames): T | null => { export const getJSON = <T,>(name: StorageNames): T | null => {
const raw = localStorage.getItem(name) const raw = localStorage.getItem(name)
if (!raw) return null if (!raw) return null
try { try {
@ -30,7 +30,7 @@ export const getJSON = <T extends any>(name: StorageNames): T | null => {
return null return null
} }
export const setJSON = <T extends any>(name: StorageNames, data: T | null): boolean => { export const setJSON = <T,>(name: StorageNames, data: T | null): boolean => {
try { try {
localStorage.setItem(name, JSON.stringify(data)) localStorage.setItem(name, JSON.stringify(data))
return true return true

View File

@ -9,7 +9,7 @@ export type TableColumnSettings = {
export type TableSettings = Record<string, TableColumnSettings> export type TableSettings = Record<string, TableColumnSettings>
export type TableSettingsStore = Record<string, TableSettings | null> export type TableSettingsStore = Record<string, TableSettings | null>
export const makeTableSettings = (columns: TableColumns): TableSettings => { export const makeTableSettings = <T extends object>(columns: TableColumns<T>): TableSettings => {
const settings: TableSettings = {} const settings: TableSettings = {}
columns.forEach((column) => { columns.forEach((column) => {
if (!column.key) return if (!column.key) return
@ -47,8 +47,8 @@ export const optimizeTableColumn = (column: TableColumnSettings): TableColumnSet
visible: column.visible ?? true, visible: column.visible ?? true,
}) })
export const applyTableSettings = (columns: TableColumns, settings: TableSettings): TableColumns => { export const applyTableSettings = <T extends object>(columns: TableColumns<T>, settings: TableSettings): TableColumns<T> => {
let newColumns: TableColumns = columns.map((column) => ({ ...column })) let newColumns: TableColumns<T> = columns.map((column) => ({ ...column }))
newColumns = newColumns.filter((column) => { newColumns = newColumns.filter((column) => {
const name = String(column.key) const name = String(column.key)
return !(name in settings) || settings[name]?.visible return !(name in settings) || settings[name]?.visible