Skip to content

Commit

Permalink
refactor(KtTable): make type for store specific data more explicit
Browse files Browse the repository at this point in the history
  • Loading branch information
Isokaeder committed Jul 25, 2024
1 parent adbafa8 commit ebf11cb
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 67 deletions.
23 changes: 13 additions & 10 deletions packages/kotti-ui/source/kotti-table/components/TableHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<script lang="ts">
import { KT_TABLE, KT_STORE } from '../constants'
import { KottiTable } from '../types'
import type { Store } from '../logic/types'
import { computed, defineComponent, inject, ref } from 'vue'
import { TableHeaderCell } from './TableHeaderCell'
Expand All @@ -67,8 +68,10 @@ export default defineComponent({
'TableRowCell: Component was used without providing the right contexts',
)
const dropTargetColumn = ref<KottiTable.Column.PropsInternal | null>(null)
const draggedColumn = ref<KottiTable.Column.PropsInternal | null>(null)
const dropTargetColumn =
ref<Store.StateComponents.ColumnRepresentation | null>(null)
const draggedColumn =
ref<Store.StateComponents.ColumnRepresentation | null>(null)
const useColumnDragToOrder = computed(() => tableState.useColumnDragToOrder)
const isDraggedOver = (column: unknown) =>
Expand All @@ -84,20 +87,20 @@ export default defineComponent({
handleDragEnd: () => {
dropTargetColumn.value = null
},
handleDragEnter: (column: KottiTable.Column.PropsInternal) => {
handleDragEnter: (column: Store.StateComponents.ColumnRepresentation) => {
dropTargetColumn.value = column
},
handleDragStart: (column: KottiTable.Column.PropsInternal) => {
handleDragStart: (column: Store.StateComponents.ColumnRepresentation) => {
draggedColumn.value = column
},
handleDrop: (column: KottiTable.Column.PropsInternal) => {
handleDrop: (column: Store.StateComponents.ColumnRepresentation) => {
if (draggedColumn.value) {
tableStore.commit('orderBefore', draggedColumn.value, column)
draggedColumn.value = null
}
dropTargetColumn.value = null
},
getThClasses: (column: KottiTable.Column.PropsInternal) => [
getThClasses: (column: Store.StateComponents.ColumnRepresentation) => [
{
'drag-over': isDraggedOver(column),
clickable: canSort(column),
Expand All @@ -108,7 +111,7 @@ export default defineComponent({
tableState.thClasses,
column.thClass,
],
getThStyle: (column: KottiTable.Column.PropsInternal) => ({
getThStyle: (column: Store.StateComponents.ColumnRepresentation) => ({
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
textAlign: column.align ?? KottiTable.Column.Align.LEFT,
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
Expand All @@ -117,7 +120,7 @@ export default defineComponent({
handleSelectAll: () => {
tableStore.commit('toggleAllSelection')
},
handleThClick: (column: KottiTable.Column.PropsInternal) => {
handleThClick: (column: Store.StateComponents.ColumnRepresentation) => {
if (!useQuickSortControl.value) return
if (!canSort(column)) return
Expand All @@ -129,9 +132,9 @@ export default defineComponent({
isExpandable: computed(() => tableState.isExpandable),
isSelectable: computed(() => tableState.isSelectable),
isSorted,
isSortedByAsc: (column: KottiTable.Column.PropsInternal) =>
isSortedByAsc: (column: Store.StateComponents.ColumnRepresentation) =>
tableStore.get('isSortedByAsc', column),
isSortedByDsc: (column: KottiTable.Column.PropsInternal) =>
isSortedByDsc: (column: Store.StateComponents.ColumnRepresentation) =>
tableStore.get('isSortedByDsc', column),
tableColumns: computed(() => tableStore.state.columns),
tableHeaderClass: computed(() => [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { defineComponent, h } from 'vue'
import type { PropType } from 'vue'
import type { KottiTable } from '../types'
import type { Store } from '../logic/types'

// eslint-disable-next-line @typescript-eslint/naming-convention
export const TableHeaderCell = defineComponent({
name: 'TableHeaderCell',
props: {
column: {
required: true,
type: Object as PropType<KottiTable.Column.PropsInternal>,
type: Object as PropType<Store.StateComponents.ColumnRepresentation>,
},
columnIndex: {
required: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { computed, defineComponent, h, inject } from 'vue'

import { KT_TABLE, KT_STORE } from '../constants'
import { type KottiTable } from '../types'
import type { Store } from '../logic/types'

// eslint-disable-next-line @typescript-eslint/naming-convention
export const TableRowCell = defineComponent({
name: 'TableRowCell',
props: {
column: {
required: true,
type: Object as PropType<KottiTable.Column.PropsInternal>,
type: Object as PropType<Store.StateComponents.ColumnRepresentation>,
},
columnIndex: {
required: true,
Expand Down Expand Up @@ -61,7 +62,7 @@ export const TableRowCell = defineComponent({
$event: MouseEvent,
data: {
value: unknown
column: KottiTable.Column.PropsInternal
column: Store.StateComponents.ColumnRepresentation
columnIndex: number
row: KottiTable.Row.Props
rowIndex: number
Expand Down
17 changes: 13 additions & 4 deletions packages/kotti-ui/source/kotti-table/constants.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import type { CreateElement, InjectionKey, VNodeChildren } from 'vue'
import type { Vue as VueType } from 'vue/types/vue'

import type { KottiTable } from './types'
import type { TypedEmit } from '../types/typed-emit'
import type { TableStore } from './logic/store'
import type { Vue as VueType } from 'vue/types/vue'
import type { Store } from './logic/types'

export const IS_ASC = /ascending|^1/
export const IS_DSC = /descending|^-1/
Expand All @@ -15,7 +16,7 @@ interface KottiTableContext {
activateRow: [unknown, number]
cellClick: [
{
column: KottiTable.Column.PropsInternal
column: Store.StateComponents.ColumnRepresentation
columnIndex: number
row: KottiTable.Row.Props
rowIndex: number
Expand Down Expand Up @@ -87,8 +88,16 @@ export const COLUMN_TYPE = Symbol('kt-table-column')

export const DEFAULT_DISABLE_ROW = (): boolean => false

export const PUBLIC_SORT_PROPS = ['prop', 'sortBy', 'sortOrder'] as const
export const PUBLIC_COLUMN_PROPS = ['prop', 'order', 'hidden'] as const
export const PUBLIC_SORT_PROPS = [
'prop',
'sortBy',
'sortOrder',
] satisfies (keyof Store.StateComponents.ColumnRepresentation)[]
export const PUBLIC_COLUMN_PROPS = [
'prop',
'order',
'hidden',
] satisfies (keyof Store.StateComponents.ColumnRepresentation)[]

export const DEFAULT_RENDER_CELL = function defaultRenderCell(
_h: CreateElement,
Expand Down
31 changes: 19 additions & 12 deletions packages/kotti-ui/source/kotti-table/logic/column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,33 @@ import { resolveColumnsOrder, getOrderedColumns } from './order'
import { setSortedColumn } from './sort'
import type { Store } from './types'

export function getColumnRealIndex(state: any, column: any) {
return state._columnsArray.findIndex(({ id }: any) => id == column.id)
export function getColumnRealIndex(
state: Store.State,
column: Store.StateComponents.ColumnRepresentation,
) {
return state._columnsArray.findIndex(({ id }) => id == column.id)
}

export function getColumnIndex(state: any, column: any) {
return state._columns[column.prop].index
export function getColumnIndex(state: Store.State, columnProp: string): number {
const columnInStore = state._columns[columnProp]

if (!columnInStore?.index)
throw new Error(`Could not find column ${columnProp} in KtTable Store`)

return columnInStore.index
}

export function setColumnsArray(
state: any,
prop: any,
shapeKeys: any,
columns: any,
mergeStrategy = Object.assign,
state: Store.State,
prop: keyof Store.State,
shapeKeys: (keyof Store.StateComponents.ColumnRepresentation)[],
columns: Store.StateComponents.ColumnRepresentation[],
) {
state[prop] = columns.map((column: any) => {
// eslint-disable-next-line no-param-reassign
column = pick(column, shapeKeys)
const oldColumn = state._columns[column.prop] ?? {}
return mergeStrategy(oldColumn, column)
return Object.assign(oldColumn, column)
})
}

Expand Down Expand Up @@ -73,7 +80,7 @@ export const mutations: Store.MutationComponents.Column = {
const { state } = store
const deleted = state._destroyedColumns[column.prop]

const newColumn: KottiTable.Column.PropsInternal = (() => {
const newColumn: Store.StateComponents.ColumnRepresentation = (() => {
const oldColumn = state._columns[column.prop]

if (!oldColumn) {
Expand Down Expand Up @@ -103,7 +110,7 @@ export const mutations: Store.MutationComponents.Column = {
},
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
(value) => value !== undefined,
) as KottiTable.Column.PropsInternal
) as Store.StateComponents.ColumnRepresentation
})()
Vue.set(state._columns, newColumn.prop, newColumn)

Expand Down
2 changes: 1 addition & 1 deletion packages/kotti-ui/source/kotti-table/logic/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const mutations: Store.MutationComponents.Order = {
orderBefore(store, fromColumn, toColumn) {
const { state } = store
if (fromColumn.id === toColumn.id) return
const fromIndex = getColumnIndex(state, fromColumn)
const fromIndex = getColumnIndex(state, fromColumn.prop)
state._columnsArray.splice(fromIndex, 1)

const toIndex = getColumnRealIndex(state, toColumn)
Expand Down
27 changes: 21 additions & 6 deletions packages/kotti-ui/source/kotti-table/logic/types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import type { Kotti } from '../../types'
import type { KottiTable } from '../types'
import type { TableStore } from './store'

export module Store {
export module StateComponents {
export type ColumnRepresentation = Omit<
KottiTable.Column.Props,
'align' | 'renderCell' | 'renderHeader' | 'width'
> & {
_deleted: boolean
align: KottiTable.Column.Align
id: string
isPropDefined: boolean
renderCell: KottiTable.Column.RenderCell
renderHeader: KottiTable.Column.RenderHeader
width: string
}

export type Column = {
_columns: Record<string, KottiTable.Column.PropsInternal>
_columnsArray: KottiTable.Column.PropsInternal[]
_columns: Record<string, ColumnRepresentation>
_columnsArray: ColumnRepresentation[]
_destroyedColumns: Record<string, number>
columns: KottiTable.Column.PropsInternal[]
columns: ColumnRepresentation[]
refreshColumnArray: boolean
}

Expand Down Expand Up @@ -84,7 +96,10 @@ export module Store {
insertColumn(
this: TableStore,
store: TableStore,
payload: { column: KottiTable.Column.PropsInternal; index?: number },
payload: {
column: Store.StateComponents.ColumnRepresentation
index?: number
},
): void
removeColumn(this: TableStore, store: TableStore, column: any): void
setColumns(this: TableStore, store: TableStore, columns: any): void
Expand Down Expand Up @@ -175,7 +190,7 @@ export module Store {
this: TableStore,
store: TableStore,
options: {
column: KottiTable.Column.PropsInternal
column: Store.StateComponents.ColumnRepresentation
order?: any
},
): void
Expand Down
53 changes: 23 additions & 30 deletions packages/kotti-ui/source/kotti-table/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CreateElement, VNode, VNodeChildren } from 'vue'
import type { Store } from './logic/types'

export module KottiTable {
export module Column {
Expand Down Expand Up @@ -27,8 +28,10 @@ export module KottiTable {
| -1
| 0

export type SortMethod = ((a: unknown, b: unknown) => number) | null

export interface Context {
column: Column.PropsInternal
column: Store.StateComponents.ColumnRepresentation
columnIndex: number
row: Row.Props
rowIndex: number
Expand Down Expand Up @@ -56,6 +59,21 @@ export module KottiTable {
sortOrder: SortOrder
}

export type Formatter = (
value: Context['value'],
row: Context['row'],
column: Context['column'],
columnIndex: Context['columnIndex'],
rowIndex: Context['rowIndex'],
) => unknown

export type RenderCell = (h: CreateElement, data: Context) => VNodeChildren

export type RenderHeader = (
h: CreateElement,
data: Pick<Context, 'column' | 'columnIndex' | 'value'>,
) => VNodeChildren

export type Props = {
index?: number // Unused
label?: string
Expand All @@ -75,42 +93,17 @@ export module KottiTable {
hidden?: boolean

sortBy?: SortBy
sortMethod?: ((a: unknown, b: unknown) => number) | null
sortMethod?: SortMethod
sortOrder?: SortOrder
sortOrders?: SortOrders[]
// whether this column is sortable, string means sortOrder is remote
sortable?: boolean | string

default?: string
disableRowClick?: boolean
formatter?: (
value: Context['value'],
row: Context['row'],
column: Context['column'],
columnIndex: Context['columnIndex'],
rowIndex: Context['rowIndex'],
) => unknown
renderCell?: (h: CreateElement, data: Context) => VNode
renderHeader?: (
h: CreateElement,
data: Pick<Context, 'column' | 'columnIndex' | 'value'>,
) => VNode
}

export type PropsInternal = Omit<
Props,
'align' | 'renderCell' | 'renderHeader' | 'width'
> & {
_deleted: boolean
align: Align
id: string
isPropDefined: boolean
renderCell: (h: CreateElement, data: Context) => VNodeChildren
renderHeader: (
h: CreateElement,
data: Pick<Context, 'column' | 'columnIndex' | 'value'>,
) => VNodeChildren
width: string
formatter?: Formatter
renderCell?: RenderCell
renderHeader?: RenderHeader
}

export module Slots {
Expand Down

0 comments on commit ebf11cb

Please sign in to comment.