Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(KtTable): make type for store specific data more explicit #981

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = <T>(a: T, b: T) => number

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
Loading