Skip to content
6 changes: 6 additions & 0 deletions .changeset/spotty-chairs-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@example/erp": patch
"@genseki/react": patch
---

feat: add action select
114 changes: 8 additions & 106 deletions examples/erp/genseki/collections/posts.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,20 @@ import { useState } from 'react'
import { type SubmitErrorHandler, type SubmitHandler, useFormContext } from 'react-hook-form'

import { zodResolver } from '@hookform/resolvers/zod'
import { DotsThreeVerticalIcon } from '@phosphor-icons/react'
import { useQueryClient } from '@tanstack/react-query'
import { createColumnHelper } from '@tanstack/react-table'
import z from 'zod'

import type { BaseData, CollectionLayoutProps, InferCreateFields } from '@genseki/react'
import type { CollectionLayoutProps, InferCreateFields } from '@genseki/react'
import {
BaseIcon,
actionsColumn,
Button,
Checkbox,
CollectionListToolbar,
createDeleteActionItem,
createEditActionItem,
createSeparatorItem,
Form,
type InferFields,
Menu,
MenuContent,
MenuItem,
MenuSeparator,
MenuTrigger,
SubmitButton,
TanstackTable,
toast,
Expand Down Expand Up @@ -71,6 +67,7 @@ export const columns = [
header: 'Updated At',
cell: (info) => <div>{new Date(info.getValue()).toLocaleDateString('en-GB')}</div>,
}),
actionsColumn([createEditActionItem(), createSeparatorItem(), createDeleteActionItem()]),
]

/**
Expand All @@ -82,7 +79,7 @@ export function PostClientToolbar() {

return (
<div>
<CollectionListToolbar actions={context.actions} />
<CollectionListToolbar toolbar={context.toolbar} />
</div>
)
}
Expand Down Expand Up @@ -115,105 +112,10 @@ export const PostClientTable = (props: { children?: React.ReactNode }) => {
},
})

const columnHelper = createColumnHelper<BaseData>()
// You can setup your own custom columns
const enhancedColumns = [
...(context.actions?.delete
? [
columnHelper.display({
id: 'select',
header: ({ table }) => (
<Checkbox
isSelected={table.getIsAllRowsSelected()}
isIndeterminate={table.getIsSomeRowsSelected()}
onChange={(checked) =>
table.getToggleAllRowsSelectedHandler()({ target: { checked } })
}
/>
),
cell: ({ row }) => (
<input
type="checkbox"
checked={row.getIsSelected()}
onChange={(event) => {
const handler = row.getToggleSelectedHandler()
handler(event)
}}
/>
),
}),
]
: []),
...context.columns,
columnHelper.display({
id: 'actions',
cell: ({ row }) => {
if (!context.actions?.one && !context.actions?.update && !context.actions?.delete) {
return null
}

return (
<div className="grid place-items-center">
<Menu>
<MenuTrigger aria-label="Actions Icon" className="cursor-pointer">
<BaseIcon icon={DotsThreeVerticalIcon} size="md" weight="bold" />
</MenuTrigger>
<MenuContent aria-label="Actions" placement="left top">
{context.actions?.one && (
<MenuItem
aria-label="View"
onAction={() => {
navigation.navigate(`./${context.slug}/${row.original.__id}`)
}}
>
View
</MenuItem>
)}
{context.actions?.update && (
<MenuItem
aria-label="Edit"
onAction={() => {
navigation.navigate(`./${context.slug}/update/${row.original.__id}`)
}}
>
Edit
</MenuItem>
)}
{context.actions?.delete && (
<>
{context.actions?.one || (context.actions?.update && <MenuSeparator />)}
<MenuItem
aria-label="Delete"
isDanger
onAction={() => {
deleteMutation.mutate([row.original.__id.toString()])
}}
>
Delete
</MenuItem>
</>
)}
<MenuSeparator />
<MenuItem
aria-label="Revert"
onAction={() => {
confirm('Confirm to revert the action?')
}}
>
Revert
</MenuItem>
</MenuContent>
</Menu>
</div>
)
},
}),
]

const table = useListTable({
total: query.data?.total,
data: query.data?.data || [],
columns: enhancedColumns,
columns: context.columns,
})

return (
Expand Down
5 changes: 4 additions & 1 deletion examples/erp/genseki/collections/posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ export const postsCollection = createPlugin('posts', (app) => {
search: ['title'],
sortBy: ['updatedAt', 'title'],
},
actions: { delete: true, update: true, create: true },
toolbar: {
create: true,
delete: true,
},
layout: Layout,
page: CustomListPage,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,33 @@

import { createColumnHelper } from '@tanstack/react-table'

import type { InferFields } from '@genseki/react'
import {
actionsColumn,
createDeleteActionItem,
createEditActionItem,
createSeparatorItem,
createViewActionItem,
type InferFields,
selectColumn,
} from '@genseki/react'

import type { fields } from './tags'

type Tag = InferFields<typeof fields>
const columnHelper = createColumnHelper<Tag>()

export const columns = [
selectColumn(),
columnHelper.accessor('__id', {
cell: (info) => info.getValue(),
}),
columnHelper.accessor('name', {
cell: (info) => info.getValue(),
}),
actionsColumn([
createViewActionItem(),
createEditActionItem(),
createSeparatorItem(),
createDeleteActionItem(),
]),
]
4 changes: 2 additions & 2 deletions examples/erp/genseki/collections/tags.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please provide an example for the select flag?

Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export const tagsCollection = createPlugin('tags', (app) => {
search: ['name'],
sortBy: ['name'],
},
actions: {
toolbar: {
create: true,
update: true,
delete: true,
},
})
)
.addPageAndApiRouter(collection.create(fields, {}))
.addPageAndApiRouter(collection.update(fields, {}))
.addPageAndApiRouter(collection.one(fields))
.addApiRouter(collection.deleteApiRouter(fields))
})
13 changes: 3 additions & 10 deletions packages/react/src/core/collection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,7 @@
/**
* @param actions will decide whether or not to show actios in `list` view screen, This is not related to available features of collection, but rather only visible UI part of the `list` page
*/
actions?: {
create?: boolean
update?: boolean
delete?: boolean
one?: boolean
}
toolbar?: CollectionToolbarActions
}

export type CollectionUpdateApiArgs<
Expand Down Expand Up @@ -356,7 +351,7 @@
}

// TODO: This is not correct, it should return default value of form instead of just simple findOne response
export type CollectionUpdateDefaultApiReturn<TFields extends Fields> = any

Check warning on line 354 in packages/react/src/core/collection/index.tsx

View workflow job for this annotation

GitHub Actions / ci

'TFields' is defined but never used. Allowed unused vars must match /^_/u

export type CollectionUpdateDefaultApiHandler<
TContext extends AnyContextable,
Expand Down Expand Up @@ -538,7 +533,7 @@
columns={config.columns}
search={config.configuration?.search}
sortBy={config.configuration?.sortBy}
actions={config.actions}
toolbar={config.toolbar}
>
<Layout>{page}</Layout>
</CollectionListProvider>
Expand Down Expand Up @@ -774,9 +769,7 @@
}
}

export interface CollectionListActions {
export interface CollectionToolbarActions {
create?: boolean
update?: boolean
delete?: boolean
one?: boolean
}
6 changes: 3 additions & 3 deletions packages/react/src/react/views/collections/list/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { CollectionListPagination } from './table/pagination'
import { CollectionListToolbar, type CollectionListToolbarProps } from './toolbar'

import { toast } from '../../../..'
import type { CollectionListActions } from '../../../../core/collection'
import type { CollectionToolbarActions } from '../../../../core/collection'
import type { FieldsClient } from '../../../../core/field'
import { TableStatesProvider, useTableStatesContext } from '../../../providers/table'
import { useCollection } from '../context'
Expand Down Expand Up @@ -51,7 +51,7 @@ export interface CollectionListContextValue<T extends BaseData = BaseData> {
columns: ColumnDef<T, any>[]
search?: string[]
sortBy?: string[]
actions?: CollectionListActions
toolbar?: CollectionToolbarActions

// Helper functions
deleteRows: (rows?: string[]) => void
Expand All @@ -66,7 +66,7 @@ export interface CollectionListProviderProps<T extends BaseData = BaseData> {
columns: ColumnDef<T, any>[]
search?: string[]
sortBy?: string[]
actions?: CollectionListActions
toolbar?: CollectionToolbarActions
}

/**
Expand Down
Loading
Loading