From 1072e03c5ae39e91237bcf809242ac0afadef594 Mon Sep 17 00:00:00 2001 From: chenos Date: Thu, 2 Dec 2021 17:56:05 +0800 Subject: [PATCH] Revert "refactor: code splitting of the table component (#120)" This reverts commit 0f9eb4e7f23865c05d1cf30f299618715962f4d0. --- .prettierrc | 2 +- .../admin-layout/Collections/index.tsx | 3 +- .../Permissions/ActionPermissionField.tsx | 3 +- .../admin-layout/Permissions/index.tsx | 3 +- .../src/components/schema-renderer/index.tsx | 7 +- .../src/schemas/calendar/DesignableBar.tsx | 2 +- .../client/src/schemas/form/DesignableBar.tsx | 2 +- packages/client/src/schemas/form/index.tsx | 2 +- .../client/src/schemas/grid/DesignableBar.tsx | 2 +- .../src/schemas/kanban/DesignableBar.tsx | 2 +- packages/client/src/schemas/select/index.tsx | 2 +- packages/client/src/schemas/table/Actions.tsx | 40 - .../src/schemas/table/AddActionButton.tsx | 77 - .../client/src/schemas/table/AddColumn.tsx | 232 -- .../client/src/schemas/table/Sortable.tsx | 77 +- .../src/schemas/table/TableActionBar.tsx | 106 - .../table/TableActionDesignableBar.tsx | 143 - .../client/src/schemas/table/TableCell.tsx | 54 - .../client/src/schemas/table/TableColumn.tsx | 24 - .../table/TableColumnDesignableBar.tsx | 158 - .../src/schemas/table/TableDesignableBar.tsx | 275 -- .../table/TableExportActionDesignableBar.tsx | 134 - .../client/src/schemas/table/TableFilter.tsx | 92 - .../table/TableFilterDesignableBar.tsx | 140 - .../client/src/schemas/table/TableIndex.tsx | 8 - .../client/src/schemas/table/TableMain.tsx | 139 - .../src/schemas/table/TableOperation.tsx | 16 - .../src/schemas/table/TableOperationCell.tsx | 13 - .../table/TableOperationDesignableBar.tsx | 194 -- .../src/schemas/table/TablePagination.tsx | 40 - .../src/schemas/table/TableProvider.tsx | 103 - .../src/schemas/table/TableSortHandle.tsx | 7 - packages/client/src/schemas/table/context.ts | 6 - .../hooks/useActionLogDetailsResource.ts | 38 - .../table/hooks/useActionLogsResource.ts | 35 - .../table/hooks/useCollectionFields.ts | 24 - .../src/schemas/table/hooks/useDataSource.ts | 17 - .../table/hooks/useDefaultRowSelection.ts | 5 - .../table/hooks/useDefaultSelectedRowKeys.ts | 6 - .../src/schemas/table/hooks/usePagination.ts | 33 - .../src/schemas/table/hooks/useResource.ts | 51 - .../src/schemas/table/hooks/useTable.ts | 6 - .../schemas/table/hooks/useTableActionBars.ts | 18 - .../schemas/table/hooks/useTableColumns.tsx | 69 - .../table/hooks/useTableCreateAction.ts | 24 - .../table/hooks/useTableDestroyAction.ts | 49 - .../table/hooks/useTableExportAction.ts | 51 - .../table/hooks/useTableFilterAction.ts | 23 - .../src/schemas/table/hooks/useTableIndex.ts | 16 - .../src/schemas/table/hooks/useTableRow.ts | 7 - .../schemas/table/hooks/useTableRowRecord.ts | 7 - .../table/hooks/useTableUpdateAction.ts | 35 - .../src/schemas/table/hooks/useTotal.ts | 10 - packages/client/src/schemas/table/index.tsx | 2687 ++++++++++++++++- packages/client/src/schemas/table/types.ts | 22 - packages/client/src/schemas/table/utils.ts | 164 - 56 files changed, 2722 insertions(+), 2783 deletions(-) delete mode 100644 packages/client/src/schemas/table/Actions.tsx delete mode 100644 packages/client/src/schemas/table/AddActionButton.tsx delete mode 100644 packages/client/src/schemas/table/AddColumn.tsx delete mode 100644 packages/client/src/schemas/table/TableActionBar.tsx delete mode 100644 packages/client/src/schemas/table/TableActionDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TableCell.tsx delete mode 100644 packages/client/src/schemas/table/TableColumn.tsx delete mode 100644 packages/client/src/schemas/table/TableColumnDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TableDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TableExportActionDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TableFilter.tsx delete mode 100644 packages/client/src/schemas/table/TableFilterDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TableIndex.tsx delete mode 100644 packages/client/src/schemas/table/TableMain.tsx delete mode 100644 packages/client/src/schemas/table/TableOperation.tsx delete mode 100644 packages/client/src/schemas/table/TableOperationCell.tsx delete mode 100644 packages/client/src/schemas/table/TableOperationDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/TablePagination.tsx delete mode 100644 packages/client/src/schemas/table/TableProvider.tsx delete mode 100644 packages/client/src/schemas/table/TableSortHandle.tsx delete mode 100644 packages/client/src/schemas/table/context.ts delete mode 100644 packages/client/src/schemas/table/hooks/useActionLogDetailsResource.ts delete mode 100644 packages/client/src/schemas/table/hooks/useActionLogsResource.ts delete mode 100644 packages/client/src/schemas/table/hooks/useCollectionFields.ts delete mode 100644 packages/client/src/schemas/table/hooks/useDataSource.ts delete mode 100644 packages/client/src/schemas/table/hooks/useDefaultRowSelection.ts delete mode 100644 packages/client/src/schemas/table/hooks/useDefaultSelectedRowKeys.ts delete mode 100644 packages/client/src/schemas/table/hooks/usePagination.ts delete mode 100644 packages/client/src/schemas/table/hooks/useResource.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTable.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableActionBars.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableColumns.tsx delete mode 100644 packages/client/src/schemas/table/hooks/useTableCreateAction.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableDestroyAction.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableExportAction.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableFilterAction.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableIndex.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableRow.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableRowRecord.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTableUpdateAction.ts delete mode 100644 packages/client/src/schemas/table/hooks/useTotal.ts delete mode 100644 packages/client/src/schemas/table/types.ts delete mode 100644 packages/client/src/schemas/table/utils.ts diff --git a/.prettierrc b/.prettierrc index 764fbde2e..94beb1484 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,7 @@ { "singleQuote": true, "trailingComma": "all", - "printWidth": 120, + "printWidth": 80, "overrides": [ { "files": ".prettierrc", diff --git a/packages/client/src/components/admin-layout/Collections/index.tsx b/packages/client/src/components/admin-layout/Collections/index.tsx index 665b8a153..eec41a7de 100644 --- a/packages/client/src/components/admin-layout/Collections/index.tsx +++ b/packages/client/src/components/admin-layout/Collections/index.tsx @@ -11,8 +11,7 @@ import { PlusOutlined, DownOutlined } from '@ant-design/icons'; import cls from 'classnames'; import { uid, isValid, clone } from '@formily/shared'; import { Resource } from '../../../resource'; -import { TableRowContext } from '../../../schemas/table/context'; -import { useTable } from '../../../schemas/table/hooks/useTable'; +import { TableRowContext, useTable } from '../../../schemas/table'; import { useRequest } from 'ahooks'; import { VisibleContext } from '../../../context'; import { connect, FormProvider, observer, useForm } from '@formily/react'; diff --git a/packages/client/src/components/admin-layout/Permissions/ActionPermissionField.tsx b/packages/client/src/components/admin-layout/Permissions/ActionPermissionField.tsx index 12962c1da..36153c0d5 100644 --- a/packages/client/src/components/admin-layout/Permissions/ActionPermissionField.tsx +++ b/packages/client/src/components/admin-layout/Permissions/ActionPermissionField.tsx @@ -8,8 +8,7 @@ import { LockOutlined } from '@ant-design/icons'; import cls from 'classnames'; import { uid } from '@formily/shared'; import { Resource } from '../../../resource'; -import { TableRowContext } from '../../../schemas/table/context'; -import { useTable } from '../../../schemas/table/hooks/useTable'; +import { TableRowContext, useTable } from '../../../schemas/table'; import { useRequest } from 'ahooks'; import { VisibleContext } from '../../../context'; import { connect, ISchema, observer, useField } from '@formily/react'; diff --git a/packages/client/src/components/admin-layout/Permissions/index.tsx b/packages/client/src/components/admin-layout/Permissions/index.tsx index 8beec3a04..34c9967b1 100644 --- a/packages/client/src/components/admin-layout/Permissions/index.tsx +++ b/packages/client/src/components/admin-layout/Permissions/index.tsx @@ -8,8 +8,7 @@ import { LockOutlined } from '@ant-design/icons'; import cls from 'classnames'; import { uid, isValid } from '@formily/shared'; import { Resource } from '../../../resource'; -import { TableRowContext } from '../../../schemas/table/context'; -import { useTable } from '../../../schemas/table/hooks/useTable'; +import { TableRowContext, useTable } from '../../../schemas/table'; import { useRequest } from 'ahooks'; import { VisibleContext } from '../../../context'; import { connect, observer, useForm } from '@formily/react'; diff --git a/packages/client/src/components/schema-renderer/index.tsx b/packages/client/src/components/schema-renderer/index.tsx index 554b8d53d..f7ca5841a 100644 --- a/packages/client/src/components/schema-renderer/index.tsx +++ b/packages/client/src/components/schema-renderer/index.tsx @@ -52,8 +52,11 @@ import { Menu } from '../../schemas/menu'; import { Password } from '../../schemas/password'; import { Radio } from '../../schemas/radio'; import { Select } from '../../schemas/select'; -import { Table } from '../../schemas/table'; -import { CollectionFieldContext, TableRowContext } from '../../schemas/table/context'; +import { + CollectionFieldContext, + Table, + TableRowContext, +} from '../../schemas/table'; import { Tabs } from '../../schemas/tabs'; import { TimePicker } from '../../schemas/time-picker'; import { Upload } from '../../schemas/upload'; diff --git a/packages/client/src/schemas/calendar/DesignableBar.tsx b/packages/client/src/schemas/calendar/DesignableBar.tsx index eff67ebb6..d70b39020 100644 --- a/packages/client/src/schemas/calendar/DesignableBar.tsx +++ b/packages/client/src/schemas/calendar/DesignableBar.tsx @@ -38,7 +38,7 @@ import { useEffect } from 'react'; import { uid } from '@formily/shared'; import { getSchemaPath } from '../../components/schema-renderer'; import { useCollection, useCollectionContext } from '../../constate'; -import { useTable } from '../table/hooks/useTable'; +import { useTable } from '../table'; import { fieldsToFilterColumns } from './'; import { set } from 'lodash'; import { DragHandle } from '../../components/Sortable'; diff --git a/packages/client/src/schemas/form/DesignableBar.tsx b/packages/client/src/schemas/form/DesignableBar.tsx index 4046f761c..82e3dee41 100644 --- a/packages/client/src/schemas/form/DesignableBar.tsx +++ b/packages/client/src/schemas/form/DesignableBar.tsx @@ -27,7 +27,7 @@ import { useEffect } from 'react'; import { uid } from '@formily/shared'; import { getSchemaPath } from '../../components/schema-renderer'; import { useCollection, useCollectionContext } from '../../constate'; -import { useTable } from '../table/hooks/useTable'; +import { useTable } from '../table'; import { BlockSchemaContext } from '../../context'; import { DragHandle } from '../../components/Sortable'; import { useTranslation } from 'react-i18next'; diff --git a/packages/client/src/schemas/form/index.tsx b/packages/client/src/schemas/form/index.tsx index 49ac99f64..a17524a61 100644 --- a/packages/client/src/schemas/form/index.tsx +++ b/packages/client/src/schemas/form/index.tsx @@ -44,7 +44,7 @@ import { import { useResource as useGeneralResource } from '../../hooks/useResource'; import { Resource } from '../../resource'; import { BaseResult } from '@ahooksjs/use-request/lib/types'; -import { CollectionFieldContext } from '../table/context'; +import { CollectionFieldContext } from '../table'; import { useTranslation } from 'react-i18next'; export interface DescriptionsContextProps { diff --git a/packages/client/src/schemas/grid/DesignableBar.tsx b/packages/client/src/schemas/grid/DesignableBar.tsx index 30ccd0da9..46d14d31e 100644 --- a/packages/client/src/schemas/grid/DesignableBar.tsx +++ b/packages/client/src/schemas/grid/DesignableBar.tsx @@ -27,7 +27,7 @@ import { useEffect } from 'react'; import { uid } from '@formily/shared'; import { getSchemaPath } from '../../components/schema-renderer'; import { useCollection, useCollectionContext } from '../../constate'; -import { useTable } from '../table/hooks/useTable'; +import { useTable } from '../table'; import { DragHandle } from '../../components/Sortable'; import { useCompile } from '../../hooks/useCompile'; diff --git a/packages/client/src/schemas/kanban/DesignableBar.tsx b/packages/client/src/schemas/kanban/DesignableBar.tsx index 14a25d4b1..e7d14bda4 100644 --- a/packages/client/src/schemas/kanban/DesignableBar.tsx +++ b/packages/client/src/schemas/kanban/DesignableBar.tsx @@ -33,7 +33,7 @@ import { useEffect } from 'react'; import { uid } from '@formily/shared'; import { getSchemaPath } from '../../components/schema-renderer'; import { useCollection, useCollectionContext } from '../../constate'; -import { useTable } from '../table/hooks/useTable'; +import { useTable } from '../table'; import { DragHandle } from '../../components/Sortable'; import { fieldsToFilterColumns } from '../calendar'; import { useTranslation } from 'react-i18next'; diff --git a/packages/client/src/schemas/select/index.tsx b/packages/client/src/schemas/select/index.tsx index a6479c872..710598aeb 100644 --- a/packages/client/src/schemas/select/index.tsx +++ b/packages/client/src/schemas/select/index.tsx @@ -24,7 +24,7 @@ import { Action } from '../action'; import { BlockSchemaContext, VisibleContext } from '../../context'; import { SchemaRenderer } from '../../components/schema-renderer'; import { uid } from '@formily/shared'; -import { CollectionFieldContext } from '../table/context'; +import { CollectionFieldContext } from '../table'; import { CollectionProvider, useCollectionContext, diff --git a/packages/client/src/schemas/table/Actions.tsx b/packages/client/src/schemas/table/Actions.tsx deleted file mode 100644 index a80a55a61..000000000 --- a/packages/client/src/schemas/table/Actions.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { Space } from 'antd'; -import { RecursionField } from '@formily/react'; -import { useDesignable } from '..'; -import { Droppable, SortableItem } from '../../components/Sortable'; -import { getSchemaPath } from '../../components/schema-renderer'; - -export const Actions = (props: any) => { - const { align = 'left' } = props; - const { schema, designable } = useDesignable(); - return ( - - - {schema.mapProperties((s) => { - const currentAlign = s['x-align'] || 'left'; - if (currentAlign !== align) { - return null; - } - return ( - - - - ); - })} - - - ); -}; diff --git a/packages/client/src/schemas/table/AddActionButton.tsx b/packages/client/src/schemas/table/AddActionButton.tsx deleted file mode 100644 index 36ef78ac6..000000000 --- a/packages/client/src/schemas/table/AddActionButton.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { useState } from 'react'; -import { Dropdown, Menu, Button } from 'antd'; -import { SettingOutlined } from '@ant-design/icons'; -import { useTranslation } from 'react-i18next'; -import { Schema } from '@formily/react'; -import { useDesignable, ISchema } from '..'; -import { useDisplayedMapContext, useClient } from '../../constate'; -import SwitchMenuItem from '../../components/SwitchMenuItem'; -import { getSchemaPath } from '../../components/schema-renderer'; -import {generateActionSchema} from './utils'; - -export const AddActionButton = () => { - const { t } = useTranslation(); - const [visible, setVisible] = useState(false); - const displayed = useDisplayedMapContext(); - const { appendChild, remove } = useDesignable(); - const { schema, designable } = useDesignable(); - const { createSchema, removeSchema, updateSchema } = useClient(); - - if (!designable || !schema['x-designable-bar']) { - return null; - } - return ( - - - {[ - { title: t('Filter'), name: 'filter' }, - { title: t('Export'), name: 'export' }, - { title: t('Add new'), name: 'create' }, - { title: t('Delete'), name: 'destroy' }, - ].map((item) => ( - { - if (!checked) { - const s = displayed.get(item.name) as Schema; - const path = getSchemaPath(s); - displayed.remove(item.name); - const removed = remove(path); - await removeSchema(removed); - } else { - const s = generateActionSchema(item.name); - const data = appendChild(s); - await createSchema(data); - } - }} - /> - ))} - - - - {t('Function')} - {t('Popup form')} - {t('Flexible popup')} - - - } - > - - - ); -}; - diff --git a/packages/client/src/schemas/table/AddColumn.tsx b/packages/client/src/schemas/table/AddColumn.tsx deleted file mode 100644 index dcc982557..000000000 --- a/packages/client/src/schemas/table/AddColumn.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import React, { useState } from 'react'; -import { Dropdown, Menu, Button } from 'antd'; -import { SettingOutlined } from '@ant-design/icons'; -import { useTranslation } from 'react-i18next'; -import { uid } from '@formily/shared'; -import { FormDialog, FormLayout } from '@formily/antd'; -import { useDesignable, createCollectionField, ISchema } from '..'; -import { useCollectionContext, useCollectionsContext, useDisplayedMapContext, useClient } from '../../constate'; -import { useTable } from './hooks/useTable'; -import SwitchMenuItem from '../../components/SwitchMenuItem'; -import { isAssociation, options } from '../database-field/interfaces'; -import { getSchemaPath, SchemaField } from '../../components/schema-renderer'; - -export function AddColumn() { - const { t } = useTranslation(); - const [visible, setVisible] = useState(false); - const { appendChild, remove } = useDesignable(); - const { loadCollections } = useCollectionsContext(); - const { collection, fields, refresh } = useCollectionContext(); - const displayed = useDisplayedMapContext(); - const { service } = useTable(); - const { createSchema, removeSchema, updateSchema } = useClient(); - return ( - - - {fields.map((field) => ( - { - if (checked) { - console.log('SwitchMenuItem.field.name', field.dataType, service.params[0]); - const columnSchema: ISchema = { - type: 'void', - 'x-component': 'Table.Column', - 'x-component-props': { - fieldName: field.name, - }, - 'x-designable-bar': 'Table.Column.DesignableBar', - }; - if (field.interface === 'linkTo') { - columnSchema.properties = { - options: { - type: 'void', - 'x-decorator': 'Form', - 'x-component': 'Select.Options.Drawer', - 'x-component-props': { - useOkAction: '{{ Select.useOkAction }}', - }, - title: "{{t('Select record')}}", - properties: { - table: { - type: 'array', - 'x-designable-bar': 'Table.DesignableBar', - 'x-decorator': 'BlockItem', - 'x-decorator-props': { - draggable: false, - }, - 'x-component': 'Table', - default: [], - 'x-component-props': { - rowKey: 'id', - useRowSelection: '{{ Select.useRowSelection }}', - useSelectedRowKeys: '{{ Select.useSelectedRowKeys }}', - onSelect: '{{ Select.useSelect() }}', - collectionName: field.target, - // dragSort: true, - // showIndex: true, - refreshRequestOnChange: true, - pagination: { - pageSize: 10, - }, - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Table.ActionBar', - 'x-designable-bar': 'Table.ActionBar.DesignableBar', - properties: { - [uid()]: { - type: 'void', - title: "{{t('Filter')}}", - 'x-decorator': 'AddNew.Displayed', - 'x-decorator-props': { - displayName: 'filter', - }, - 'x-align': 'left', - 'x-component': 'Table.Filter', - 'x-designable-bar': 'Table.Filter.DesignableBar', - 'x-component-props': { - fieldNames: [], - }, - }, - }, - }, - }, - }, - }, - }, - option: { - type: 'void', - 'x-component': 'Select.OptionTag', - properties: { - [uid()]: { - type: 'void', - title: "{{t('View record')}}", - 'x-component': 'Action.Drawer', - 'x-component-props': { - bodyStyle: { - background: '#f0f2f5', - }, - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Tabs', - 'x-designable-bar': 'Tabs.DesignableBar', - properties: { - [uid()]: { - type: 'void', - title: "{{t('Details')}}", - 'x-designable-bar': 'Tabs.TabPane.DesignableBar', - 'x-component': 'Tabs.TabPane', - 'x-component-props': {}, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Grid', - 'x-component-props': { - addNewComponent: 'AddNew.PaneItem', - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }; - } - const data = appendChild(columnSchema); - await createSchema(data); - if (isAssociation(field)) { - const defaultAppends = service.params[0]?.defaultAppends || []; - defaultAppends.push(field.name); - await service.run({ - ...service.params[0], - defaultAppends, - }); - } - } else { - const s: any = displayed.get(field.name); - const p = getSchemaPath(s); - const removed = remove(p); - await removeSchema(removed); - displayed.remove(field.name); - if (isAssociation(field)) { - const defaultAppends = service.params[0]?.defaultAppends || []; - const index = defaultAppends.indexOf(field.name); - if (index > -1) { - defaultAppends.splice(index, 1); - } - await service.run({ - ...service.params[0], - defaultAppends, - }); - } - } - // service.refresh(); - }} - /> - ))} - - - - {options.map((option) => ( - - {option.children.map((item) => ( - { - setVisible(false); - const values = await FormDialog(t('Add field'), () => { - return ( - - - - ); - }).open({ - initialValues: { - interface: item.name, - ...item.default, - key: uid(), - name: `f_${uid()}`, - }, - }); - await createCollectionField(collection?.name, values); - const data = appendChild({ - type: 'void', - 'x-component': 'Table.Column', - 'x-component-props': { - fieldName: values.name, - }, - 'x-designable-bar': 'Table.Column.DesignableBar', - }); - await createSchema(data); - await refresh(); - }} - > - {item.title} - - ))} - - ))} - - - } - > - - - ); -} diff --git a/packages/client/src/schemas/table/Sortable.tsx b/packages/client/src/schemas/table/Sortable.tsx index 3fc70dfa6..4728a60d8 100644 --- a/packages/client/src/schemas/table/Sortable.tsx +++ b/packages/client/src/schemas/table/Sortable.tsx @@ -1,15 +1,42 @@ -import React, { createContext, useContext, forwardRef, useState } from 'react'; -import { SortableContext, useSortable, horizontalListSortingStrategy } from '@dnd-kit/sortable'; +import React, { forwardRef, useState } from 'react'; +import { + SortableContext, + useSortable, + horizontalListSortingStrategy, + verticalListSortingStrategy, + sortableKeyboardCoordinates, +} from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; +import { Table } from 'antd'; +import { createContext } from 'react'; +import { useContext } from 'react'; +import { range } from 'lodash'; +import parse from 'html-react-parser'; import cls from 'classnames'; -import { DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core'; import { MenuOutlined } from '@ant-design/icons'; + +import { + DndContext, + DragOverlay, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, + useDroppable, + useDraggable, +} from '@dnd-kit/core'; import { createPortal } from 'react-dom'; +import { useRef } from 'react'; import { SortableItem } from '../../components/Sortable'; -import { findPropertyByPath, getSchemaPath, useDesignable } from '../../components/schema-renderer'; +import { + findPropertyByPath, + getSchemaPath, + useDesignable, +} from '../../components/schema-renderer'; import { updateSchema } from '..'; import { Schema } from '@formily/react'; -import { isColumn } from './utils'; +import { isColumn, isColumnComponent } from '.'; export const RowDraggableContext = createContext({}); export const ColDraggableContext = createContext(null); @@ -41,7 +68,9 @@ export function SortableColumn(props) { ref={setDroppableNodeRef} // {...attributes} > - + {props.children} {/* @@ -52,9 +81,22 @@ export function SortableColumn(props) { } export function SortableBodyRow(props: any) { - const { className, style: prevStyle, ['data-row-key']: dataRowKey, ...others } = props; - const { isDragging, attributes, listeners, setNodeRef, setDraggableNodeRef, overIndex, transform, transition } = - useSortable({ id: dataRowKey }); + const { + className, + style: prevStyle, + ['data-row-key']: dataRowKey, + ...others + } = props; + const { + isDragging, + attributes, + listeners, + setNodeRef, + setDraggableNodeRef, + overIndex, + transform, + transition, + } = useSortable({ id: dataRowKey }); const style = { ...prevStyle, @@ -63,9 +105,15 @@ export function SortableBodyRow(props: any) { }; return ( - + {React.Children.map(props.children, (child, index) => ( - {child} + + {child} + ))} @@ -214,7 +264,8 @@ export function SortableBodyCell(props) { export function SortableRowHandle(props) { const { className, ...others } = props; - const { setDraggableNodeRef, attributes, listeners } = useContext(RowDraggableContext); + const { setDraggableNodeRef, attributes, listeners } = + useContext(RowDraggableContext); return setDraggableNodeRef ? ( { - const { align = 'top' } = props; - // const { schema, designable } = useDesignable(); - const { root, schema, insertAfter, remove, appendChild } = useDesignable(); - const moveToAfter = (path1, path2, extra = {}) => { - if (!path1 || !path2) { - return; - } - if (path1.join('.') === path2.join('.')) { - return; - } - const data = findPropertyByPath(root, path1); - if (!data) { - return; - } - remove(path1); - return insertAfter( - { - ...data.toJSON(), - ...extra, - }, - path2, - ); - }; - const { createSchema, removeSchema, updateSchema } = useClient(); - - const [dragOverlayContent, setDragOverlayContent] = useState(''); - return ( - { - setDragOverlayContent(event.active.data?.current?.title || ''); - // const previewRef = event.active.data?.current?.previewRef; - // if (previewRef) { - // setDragOverlayContent(previewRef?.current?.innerHTML); - // } else { - // setDragOverlayContent(''); - // } - }} - onDragEnd={async (event) => { - const path1 = event.active?.data?.current?.path; - const path2 = event.over?.data?.current?.path; - const align = event.over?.data?.current?.align; - const draggable = event.over?.data?.current?.draggable; - if (!path1 || !path2) { - return; - } - if (path1.join('.') === path2.join('.')) { - return; - } - if (!draggable) { - console.log('alignalignalignalign', align); - const p = findPropertyByPath(root, path1); - if (!p) { - return; - } - remove(path1); - const data = appendChild( - { - ...p.toJSON(), - 'x-align': align, - }, - path2, - ); - await updateSchema(data); - } else { - const data = moveToAfter(path1, path2, { - 'x-align': align, - }); - await updateSchema(data); - } - }} - > - - {dragOverlayContent} - {/*
*/} -
- -
-
- -
-
- -
- -
-
-
- ); -}); diff --git a/packages/client/src/schemas/table/TableActionDesignableBar.tsx b/packages/client/src/schemas/table/TableActionDesignableBar.tsx deleted file mode 100644 index ae458f790..000000000 --- a/packages/client/src/schemas/table/TableActionDesignableBar.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import React, { useState } from 'react'; -import { Select, Dropdown, Menu, Switch, Space } from 'antd'; -import { MenuOutlined } from '@ant-design/icons'; -import { useField } from '@formily/react'; -import { FormDialog, FormLayout } from '@formily/antd'; -import cls from 'classnames'; -import { Trans, useTranslation } from 'react-i18next'; -import { useDesignable } from '..'; -import { useDisplayedMapContext, useClient } from '../../constate'; -import { DragHandle } from '../../components/Sortable'; -import { SchemaField } from '../../components/schema-renderer'; - -export const TableActionDesignableBar = () => { - const { t } = useTranslation(); - const { schema, remove, refresh, insertAfter } = useDesignable(); - const [visible, setVisible] = useState(false); - const isPopup = Object.keys(schema.properties || {}).length > 0; - const popupSchema = Object.values(schema.properties || {}).shift(); - const inActionBar = schema.parent['x-component'] === 'Table.ActionBar'; - const displayed = useDisplayedMapContext(); - const field = useField(); - const { createSchema, removeSchema, updateSchema } = useClient(); - const popupComponent = popupSchema?.['x-component'] || 'Action.Drawer'; - return ( -
- { - e.stopPropagation(); - }} - className={cls('designable-bar-actions', { active: visible })} - > - - - { - setVisible(visible); - }} - overlay={ - - { - setVisible(false); - const values = await FormDialog(t('Edit button'), () => { - return ( - - - - ); - }).open({ - initialValues: { - title: schema['title'], - icon: schema['x-component-props']?.['icon'], - }, - }); - schema['title'] = values.title; - schema['x-component-props']['icon'] = values.icon; - field.componentProps.icon = values.icon; - field.title = values.title; - updateSchema(schema); - refresh(); - }} - > - {t('Edit button')} - - {isPopup && ( - - - Open in - - - - )} - {!inActionBar && ( - - {t('Triggered when the row is clicked')}    - - - )} - - { - const displayName = schema?.['x-decorator-props']?.['displayName']; - const data = remove(); - await removeSchema(data); - if (displayName) { - displayed.remove(displayName); - } - setVisible(false); - }} - > - {t('Hide')} - - - } - > - - - - -
- ); -}; diff --git a/packages/client/src/schemas/table/TableCell.tsx b/packages/client/src/schemas/table/TableCell.tsx deleted file mode 100644 index 1c44f9579..000000000 --- a/packages/client/src/schemas/table/TableCell.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useContext } from 'react'; -import { observer, RecursionField, Schema } from '@formily/react'; -import { cloneDeepWith, set } from 'lodash'; -import { uid, merge } from '@formily/shared'; -import { CollectionFieldContext,TableRowContext } from './context'; -import { Table } from '.'; - -export const TableCell = observer((props: any) => { - const ctx = useContext(TableRowContext); - const schema = props.schema; - const collectionField = useContext(CollectionFieldContext); - if (schema['x-component'] === 'Table.Operation') { - return ; - } - let uiSchema = collectionField?.uiSchema as Schema; - if (uiSchema?.['x-component'] === 'Upload.Attachment') { - uiSchema = cloneDeepWith(uiSchema); - set(uiSchema, 'x-component-props.size', 'small'); - } - const componentProps = merge(uiSchema?.['x-component-props'] || {}, schema?.['x-component-props'] || {}, { - arrayMerge: (t, s) => s, - }); - console.log('Table.Cell', collectionField?.interface, componentProps); - return ( -
- -
- ); -}); diff --git a/packages/client/src/schemas/table/TableColumn.tsx b/packages/client/src/schemas/table/TableColumn.tsx deleted file mode 100644 index 43287130c..000000000 --- a/packages/client/src/schemas/table/TableColumn.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { useContext, useEffect } from 'react'; -import { observer } from '@formily/react'; -import { useDesignable } from '..'; -import { useDisplayedMapContext } from '../../constate'; -import { useCompile } from '../../hooks/useCompile'; -import { CollectionFieldContext } from './context'; - -export const TableColumn = observer((props: any) => { - const collectionField = useContext(CollectionFieldContext); - const { schema, DesignableBar } = useDesignable(); - const compile = useCompile(); - const displayed = useDisplayedMapContext(); - useEffect(() => { - if (collectionField?.name) { - displayed.set(collectionField.name, schema); - } - }, [collectionField, schema]); - return ( -
- {compile(schema.title || collectionField?.uiSchema?.title)} - -
- ); -}); diff --git a/packages/client/src/schemas/table/TableColumnDesignableBar.tsx b/packages/client/src/schemas/table/TableColumnDesignableBar.tsx deleted file mode 100644 index b1964443a..000000000 --- a/packages/client/src/schemas/table/TableColumnDesignableBar.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import React, { useContext, useState } from 'react'; -import { useField } from '@formily/react'; -import { Select, Dropdown, Menu, Space } from 'antd'; -import { set } from 'lodash'; -import cls from 'classnames'; -import { MenuOutlined } from '@ant-design/icons'; -import { FormDialog, FormLayout, Submit } from '@formily/antd'; -import { useTranslation } from 'react-i18next'; -import { SchemaField } from '../../components/schema-renderer'; -import { useCollectionsContext, useDisplayedMapContext, useClient } from '../../constate'; -import { DragHandle } from '../../components/Sortable'; -import { useDesignable } from '..'; -import { useCompile } from '../../hooks/useCompile'; -import { useTable } from './hooks/useTable'; -import { CollectionFieldContext } from './hooks/useTableColumns'; - -export const TableColumnDesignableBar = () => { - const field = useField(); - const { t } = useTranslation(); - const compile = useCompile(); - const { service, refresh: refreshTable } = useTable(); - // const fieldSchema = useFieldSchema(); - const { schema, remove, refresh, insertAfter } = useDesignable(); - const [visible, setVisible] = useState(false); - const displayed = useDisplayedMapContext(); - const { getFieldsByCollection } = useCollectionsContext(); - const collectionField = useContext(CollectionFieldContext); - const { createSchema, removeSchema, updateSchema } = useClient(); - console.log('displayed.map', displayed.map); - return ( -
- { - e.stopPropagation(); - }} - className={cls('designable-bar-actions', { active: visible })} - > - - - { - setVisible(visible); - }} - overlay={ - - { - setVisible(false); - const values = await FormDialog(t('Custom name'), () => { - return ( - - - - ); - }).open({ - initialValues: { - fieldName: collectionField?.uiSchema?.title, - title: schema['title'], - }, - }); - const title = values.title || null; - field.title = title; - schema.title = title; - refresh(); - await updateSchema({ - key: schema['key'], - title: title, - }); - }} - > - {t('Custom column name')} - - {collectionField?.interface === 'linkTo' && ( - -
- {t('Label field')}{' '} - { - const componentProps = schema['x-component-props'] || {}; - set(componentProps, 'pagination.defaultPageSize', value); - set(componentProps, 'pagination.pageSize', value); - schema['x-component-props'] = componentProps; - field.componentProps.pagination.pageSize = value; - field.componentProps.pagination.defaultPageSize = value; - refresh(); - updateSchema(schema); - setVisible(false); - }} - defaultValue={defaultPageSize} - > - 10 - 20 - 50 - 100 - - {' items per page'} - - - - { - Modal.confirm({ - title: t('Delete block'), - content: t('Are you sure you want to delete it?'), - onOk: async () => { - const removed = deepRemove(); - // console.log({ removed }) - const last = removed.pop(); - await removeSchema(last); - setVisible(false); - }, - }); - }} - > - {t('Delete')} - -
- } - > - -
-
-
-
- ); -}); diff --git a/packages/client/src/schemas/table/TableExportActionDesignableBar.tsx b/packages/client/src/schemas/table/TableExportActionDesignableBar.tsx deleted file mode 100644 index b00603b60..000000000 --- a/packages/client/src/schemas/table/TableExportActionDesignableBar.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import React, { useState } from 'react'; -import { Dropdown, Menu, Space } from 'antd'; -import { useField } from '@formily/react'; -import { FormDialog, FormLayout } from '@formily/antd'; -import { MenuOutlined } from '@ant-design/icons'; -import cls from 'classnames'; -import { Trans, useTranslation } from 'react-i18next'; -import { DragHandle } from '../../components/Sortable'; -import { useDesignable } from '..'; -import { useCollectionContext, useDisplayedMapContext, useClient } from '../../constate'; -import SwitchMenuItem from '../../components/SwitchMenuItem'; -import { SchemaField } from '../../components/schema-renderer'; - -export const TableExportActionDesignableBar = () => { - const { t } = useTranslation(); - const { schema, remove, refresh, insertAfter } = useDesignable(); - const [visible, setVisible] = useState(false); - const displayed = useDisplayedMapContext(); - const { fields } = useCollectionContext(); - const field = useField(); - const { createSchema, removeSchema, updateSchema } = useClient(); - let fieldNames = field.componentProps.fieldNames || []; - if (fieldNames.length === 0) { - fieldNames = fields.map((field) => field.name); - } - return ( -
- { - e.stopPropagation(); - }} - className={cls('designable-bar-actions', { active: visible })} - > - - - { - setVisible(visible); - }} - overlay={ - - - {fields.map((collectionField) => ( - { - if (checked) { - fieldNames.push(collectionField.name); - } else { - const index = fieldNames.indexOf(collectionField.name); - if (index > -1) { - fieldNames.splice(index, 1); - } - } - console.log({ fieldNames, field }); - schema['x-component-props']['fieldNames'] = fieldNames; - field.componentProps.fieldNames = fieldNames; - updateSchema(schema); - }} - /> - ))} - - - { - setVisible(false); - const values = await FormDialog(t('Edit button'), () => { - return ( - - - - ); - }).open({ - initialValues: { - title: schema['title'], - icon: schema['x-component-props']?.['icon'], - }, - }); - schema['title'] = values.title; - schema['x-component-props']['icon'] = values.icon; - field.componentProps.icon = values.icon; - field.title = values.title; - updateSchema(schema); - refresh(); - }} - > - {t('Edit button')} - - - { - const displayName = schema?.['x-decorator-props']?.['displayName']; - const data = remove(); - await removeSchema(data); - if (displayName) { - displayed.remove(displayName); - } - setVisible(false); - }} - > - {t('Hide')} - - - } - > - - - - -
- ); -}; diff --git a/packages/client/src/schemas/table/TableFilter.tsx b/packages/client/src/schemas/table/TableFilter.tsx deleted file mode 100644 index 42416e7bd..000000000 --- a/packages/client/src/schemas/table/TableFilter.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { useMemo, useState } from 'react'; -import { Popover, Button, } from 'antd'; -import { useTranslation } from 'react-i18next'; -import flatten from 'flat'; -import { createForm } from '@formily/core'; -import { FormProvider, observer } from '@formily/react'; -import { FormButtonGroup, Submit } from '@formily/antd'; -import { interfaces } from '../database-field/interfaces'; -import { useDesignable } from '..'; -import { useCollectionContext, } from '../../constate'; -import { SchemaField } from '../../components/schema-renderer'; -import { useTable } from './hooks/useTable'; -import { useCompile } from '../../hooks/useCompile'; -import IconPicker from '../../components/icon-picker'; - -export const TableFilter = observer((props: any) => { - const { service } = useTable(); - const { fieldNames = [] } = props; - const compile = useCompile(); - const { t } = useTranslation(); - const { schema, DesignableBar } = useDesignable(); - const form = useMemo(() => createForm(), []); - const { fields = [] } = useCollectionContext(); - const [visible, setVisible] = useState(false); - const obj = flatten(form.values.filter || {}); - console.log('flatten', obj, Object.values(obj)); - const count = Object.values(obj).filter((i) => (Array.isArray(i) ? i.length : i)).length; - const icon = props.icon || 'FilterOutlined'; - const properties = fieldsToFilterColumns(fields, { fieldNames }); - schema.mapProperties((p) => { - properties[p.name] = p; - }); - return ( - - - - - - { - const { filter } = form.values; - console.log('Table.Filter', form.values); - setVisible(false); - return service.run({ - ...service.params[0], - filter, - }); - }} - > - {t('Submit')} - - - - - } - > - - - ); -}); diff --git a/packages/client/src/schemas/table/TableFilterDesignableBar.tsx b/packages/client/src/schemas/table/TableFilterDesignableBar.tsx deleted file mode 100644 index d95b21757..000000000 --- a/packages/client/src/schemas/table/TableFilterDesignableBar.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React, { useState } from 'react'; -import { Dropdown, Menu, Space } from 'antd'; -import { useField } from '@formily/react'; -import { FormDialog, FormLayout } from '@formily/antd'; -import { MenuOutlined } from '@ant-design/icons'; -import cls from 'classnames'; -import { useTranslation } from 'react-i18next'; -import { DragHandle } from '../../components/Sortable'; -import { interfaces } from '../database-field/interfaces'; -import { useDesignable } from '..'; -import { useCollectionContext, useDisplayedMapContext, useClient } from '../../constate'; -import SwitchMenuItem from '../../components/SwitchMenuItem'; -import { SchemaField } from '../../components/schema-renderer'; - -export const TableFilterDesignableBar = () => { - const { t } = useTranslation(); - const { schema, remove, refresh, insertAfter } = useDesignable(); - const [visible, setVisible] = useState(false); - const displayed = useDisplayedMapContext(); - const { fields } = useCollectionContext(); - const field = useField(); - const { createSchema, removeSchema, updateSchema } = useClient(); - let fieldNames = field.componentProps.fieldNames || []; - if (fieldNames.length === 0) { - fieldNames = fields.map((field) => field.name); - } - return ( -
- { - e.stopPropagation(); - }} - className={cls('designable-bar-actions', { active: visible })} - > - - - { - setVisible(visible); - }} - overlay={ - - - {fields - .filter((collectionField) => { - const option = interfaces.get(collectionField.interface); - return option?.operations?.length; - }) - .map((collectionField) => ( - { - if (checked) { - fieldNames.push(collectionField.name); - } else { - const index = fieldNames.indexOf(collectionField.name); - if (index > -1) { - fieldNames.splice(index, 1); - } - } - console.log({ fieldNames, field }); - schema['x-component-props']['fieldNames'] = fieldNames; - field.componentProps.fieldNames = fieldNames; - updateSchema(schema); - }} - /> - ))} - - - { - setVisible(false); - const values = await FormDialog(t('Edit button'), () => { - return ( - - - - ); - }).open({ - initialValues: { - title: schema['title'], - icon: schema['x-component-props']?.['icon'], - }, - }); - schema['title'] = values.title; - schema['x-component-props']['icon'] = values.icon; - field.componentProps.icon = values.icon; - field.title = values.title; - updateSchema(schema); - refresh(); - }} - > - {t('Edit button')} - - - { - const displayName = schema?.['x-decorator-props']?.['displayName']; - const data = remove(); - await removeSchema(data); - if (displayName) { - displayed.remove(displayName); - } - setVisible(false); - }} - > - {t('Hide')} - - - } - > - - - - -
- ); -}; diff --git a/packages/client/src/schemas/table/TableIndex.tsx b/packages/client/src/schemas/table/TableIndex.tsx deleted file mode 100644 index f7dbc944a..000000000 --- a/packages/client/src/schemas/table/TableIndex.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { observer } from '@formily/react'; -import { useTableIndex } from './hooks/useTableIndex'; - -export const TableIndex = observer(() => { - const index = useTableIndex(); - return {index + 1}; -}); diff --git a/packages/client/src/schemas/table/TableMain.tsx b/packages/client/src/schemas/table/TableMain.tsx deleted file mode 100644 index faa0723d0..000000000 --- a/packages/client/src/schemas/table/TableMain.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { DndContext } from '@dnd-kit/core'; -import { useState } from 'react'; -import { Table as AntdTable } from 'antd'; -import { findIndex } from 'lodash'; -import cls from 'classnames'; -import { RecursionField, Schema } from '@formily/react'; -import { isValid } from '@formily/shared'; -import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'; -import { SortableBodyRow, SortableHeaderCell, SortableHeaderRow } from './Sortable'; -import { TableRowContext } from './context'; -import { useDataSource } from './hooks/useDataSource'; -import { useDefaultRowSelection } from './hooks/useDefaultRowSelection'; -import { useTable } from './hooks/useTable'; -import { useTableActionBars } from './hooks/useTableActionBars'; -import { useTableColumns } from './hooks/useTableColumns'; -import { Table } from '.'; - -export const TableMain = () => { - const { - resource, - selectedRowKeys, - setSelectedRowKeys, - service, - field, - props: { rowKey, dragSort, showIndex, onSelect, useRowSelection = useDefaultRowSelection }, - refresh, - } = useTable(); - const columns = useTableColumns(); - const dataSource = useDataSource(); - const actionBars = useTableActionBars(); - const [html, setHtml] = useState(''); - const { type } = useRowSelection(); - return ( -
- { - const fromId = event.active?.id as any; - const toId = event.over?.id as any; - if (isValid(fromId) && isValid(toId)) { - const fromIndex = findIndex(field.value, (item) => item[rowKey] === fromId); - const toIndex = findIndex(field.value, (item) => item[rowKey] === toId); - console.log({ fromId, toId, fromIndex, toIndex }); - field.move(fromIndex, toIndex); - refresh(); - await resource.sort({ - resourceKey: fromId, - target: { - [rowKey]: toId, - }, - }); - await service.refresh(); - } - }} - > - {actionBars.map((actionBar) => ( - - ))} - - {}} - loading={service?.loading} - rowKey={rowKey} - dataSource={dataSource} - columns={columns} - // components={{ - // body: { - // row: DragableBodyRow, - // }, - // }} - components={{ - header: { - row: SortableHeaderRow, - cell: SortableHeaderCell, - }, - body: { - // wrapper: (props) => { - // return ( - // - // - //
- // - // {props.children} - // - // ); - // }, - row: SortableBodyRow, - // cell: SortableBodyCell, - }, - }} - rowSelection={{ - type: type || 'checkbox', - selectedRowKeys, - onChange: (rowKeys, rows) => { - setSelectedRowKeys(rowKeys); - onSelect && onSelect(rowKeys, rows); - }, - renderCell: (checked, record, _, originNode) => { - const index = findIndex(field.value, (item) => item[rowKey] === record[rowKey]); - return ( - -
- {dragSort && } - {showIndex && } - {originNode} -
-
- ); - }, - }} - /> - - - -
- ); -}; diff --git a/packages/client/src/schemas/table/TableOperation.tsx b/packages/client/src/schemas/table/TableOperation.tsx deleted file mode 100644 index 4d202cf8a..000000000 --- a/packages/client/src/schemas/table/TableOperation.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { observer } from '@formily/react'; -import { useTranslation } from 'react-i18next'; -import { useDesignable } from '..'; -import { Table } from '.'; - -export const TableOperation = observer((props: any) => { - const { designable, schema } = useDesignable(); - const { t } = useTranslation(); - return ( -
- {t('Operations')} - -
- ); -}); diff --git a/packages/client/src/schemas/table/TableOperationCell.tsx b/packages/client/src/schemas/table/TableOperationCell.tsx deleted file mode 100644 index 22fced4f0..000000000 --- a/packages/client/src/schemas/table/TableOperationCell.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { useContext } from 'react'; -import { observer, RecursionField } from '@formily/react'; -import { TableRowContext } from './context'; - -export const TableOperationCell = observer((props: any) => { - const ctx = useContext(TableRowContext); - const schema = props.schema; - return ( -
- -
- ); -}); diff --git a/packages/client/src/schemas/table/TableOperationDesignableBar.tsx b/packages/client/src/schemas/table/TableOperationDesignableBar.tsx deleted file mode 100644 index 5a0c97996..000000000 --- a/packages/client/src/schemas/table/TableOperationDesignableBar.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import React, { useState } from 'react'; -import { Dropdown, Menu, Space } from 'antd'; -import { useTranslation } from 'react-i18next'; -import { uid, merge } from '@formily/shared'; -import cls from 'classnames'; -import { MenuOutlined } from '@ant-design/icons'; -import { useDesignable, ISchema } from '..'; -import { getSchemaPath } from '../../components/schema-renderer'; -import { useClient } from '../../constate'; -import SwitchMenuItem from '../../components/SwitchMenuItem'; -import { DragHandle } from '../../components/Sortable'; - -export const TableOperationDesignableBar = () => { - const { t } = useTranslation(); - const { schema: columnSchema } = useDesignable(); - const groupSchema = Object.values(columnSchema.properties || {}).shift(); - const groupPath = getSchemaPath(groupSchema); - const { schema, remove, refresh, appendChild } = useDesignable(groupPath); - const [visible, setVisible] = useState(false); - const { createSchema, removeSchema, updateSchema } = useClient(); - - const map = new Map(); - schema.mapProperties((s) => { - if (!s['x-action-type']) { - return; - } - map.set(s['x-action-type'], s.name); - }); - const path = getSchemaPath(schema); - return ( -
- { - e.stopPropagation(); - }} - className={cls('designable-bar-actions', { active: visible })} - > - - - { - setVisible(visible); - }} - overlay={ - - - {[ - { title: t('View'), name: 'view' }, - { title: t('Edit'), name: 'update' }, - { title: t('Delete'), name: 'destroy' }, - ].map((item) => ( - { - if (checked) { - const s = generateMenuActionSchema(item.name); - const data = appendChild(s); - await createSchema(data); - } else if (map.get(item.name)) { - const removed = remove([...path, map.get(item.name)]); - await removeSchema(removed); - } - }} - /> - ))} - - - - {t('Function')} - {t('Popup form')} - {t('Flexible popup')} - - - } - > - - - - -
- ); -}; -function generateMenuActionSchema(type) { - const actions: { [key: string]: ISchema } = { - view: { - key: uid(), - name: uid(), - type: 'void', - title: "{{ t('View') }}", - 'x-component': 'Action', - 'x-component-props': { - type: 'link', - }, - 'x-designable-bar': 'Table.Action.DesignableBar', - 'x-action-type': 'view', - properties: { - [uid()]: { - type: 'void', - title: "{{ t('View record') }}", - 'x-component': 'Action.Drawer', - 'x-component-props': { - bodyStyle: { - background: '#f0f2f5', - // paddingTop: 0, - }, - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Tabs', - 'x-designable-bar': 'Tabs.DesignableBar', - properties: { - [uid()]: { - type: 'void', - title: "{{ t('Details') }}", - 'x-designable-bar': 'Tabs.TabPane.DesignableBar', - 'x-component': 'Tabs.TabPane', - 'x-component-props': {}, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Grid', - 'x-component-props': { - addNewComponent: 'AddNew.PaneItem', - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - update: { - key: uid(), - name: uid(), - type: 'void', - title: "{{ t('Edit') }}", - 'x-component': 'Action', - 'x-component-props': { - type: 'link', - }, - 'x-designable-bar': 'Table.Action.DesignableBar', - 'x-action-type': 'update', - properties: { - [uid()]: { - type: 'void', - title: "{{ t('Edit record') }}", - 'x-decorator': 'Form', - 'x-decorator-props': { - useResource: '{{ Table.useResource }}', - useValues: '{{ Table.useTableRowRecord }}', - }, - 'x-component': 'Action.Drawer', - 'x-component-props': { - useOkAction: '{{ Table.useTableUpdateAction }}', - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Grid', - 'x-component-props': { - addNewComponent: 'AddNew.FormItem', - }, - }, - }, - }, - }, - }, - destroy: { - key: uid(), - name: uid(), - type: 'void', - title: "{{ t('Delete') }}", - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - 'x-action-type': 'destroy', - 'x-component-props': { - useAction: '{{ Table.useTableDestroyAction }}', - type: 'link', - confirm: { - title: "{{ t('Delete record') }}", - content: "{{ t('Are you sure you want to delete it?') }}", - }, - }, - }, - }; - return actions[type]; -} diff --git a/packages/client/src/schemas/table/TablePagination.tsx b/packages/client/src/schemas/table/TablePagination.tsx deleted file mode 100644 index f22eada11..000000000 --- a/packages/client/src/schemas/table/TablePagination.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { Pagination } from 'antd'; -import { observer } from '@formily/react'; -import { useTable } from './hooks/useTable'; -import { useTotal } from './hooks/useTotal'; - -export const TablePagination = observer(() => { - const { service, pagination, setPagination, props } = useTable(); - if (!pagination || Object.keys(pagination).length === 0) { - return null; - } - const { clientSidePagination } = props; - const total = useTotal(); - const { page = 1 } = pagination; - return ( -
- { - const page = pagination.pageSize !== pageSize ? 1 : current; - setPagination({ - page, - pageSize, - }); - // if (clientSidePagination) { - // return; - // } - // service.run({ - // ...service.params[0], - // page, - // pageSize, - // }); - }} - /> -
- ); -}); diff --git a/packages/client/src/schemas/table/TableProvider.tsx b/packages/client/src/schemas/table/TableProvider.tsx deleted file mode 100644 index 47cecc4b4..000000000 --- a/packages/client/src/schemas/table/TableProvider.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import React, { useState } from 'react'; -import { ArrayField } from '@formily/core'; -import { useField } from '@formily/react'; -import { uid } from '@formily/shared'; -import useRequest from '@ahooksjs/use-request'; -import { useDeepCompareEffectNoCheck } from 'use-deep-compare-effect'; -import { useResource as useGeneralResource } from '../../hooks/useResource'; -import { useDesignable } from '..'; -import { useCollectionContext } from '../../constate'; -import { useDefaultSelectedRowKeys } from './hooks/useDefaultSelectedRowKeys'; -import { usePagination } from './hooks/usePagination'; -import { useCollectionFields } from './hooks/useCollectionFields'; -import {TableContext} from './context'; -import {TableMain} from './TableMain'; - -export const TableProvider = (props: any) => { - const { - rowKey = 'id', - dataRequest, - useResource = useGeneralResource, - defaultSelectedRowKeys, - useSelectedRowKeys = useDefaultSelectedRowKeys, - ...others - } = props; - const { schema } = useDesignable(); - const field = useField(); - const [pagination, setPagination] = usePagination(); - const { selectedRowKeys, setSelectedRowKeys } = useSelectedRowKeys(); - console.log('props.useSelectedRowKeys', selectedRowKeys); - const [, refresh] = useState(uid()); - const { resource } = useResource(); - const { sortableField } = useCollectionContext(); - const dragSort = props.dragSort; - const collectionFields = useCollectionFields(schema); - // console.log({ collectionFields, pagination }); - const getDefaultParams = () => { - const defaultParams = { ...pagination }; - if (dragSort) { - defaultParams['sort'] = [sortableField || 'sort']; - } else { - defaultParams['sort'] = (props.defaultSort || []).join(','); - } - defaultParams['defaultAppends'] = [...(props.defaultAppends || []), ...collectionFields]; - if (props.defaultFilter) { - defaultParams['defaultFilter'] = props.defaultFilter; - } - console.log({ defaultParams }); - return defaultParams; - }; - const service = useRequest( - (params?: any) => { - if (!resource) { - return Promise.resolve({ - list: field.value, - total: field?.value?.length, - }); - } - return resource.list(params).then((res) => { - return { - list: res?.data || [], - total: res?.meta?.count || res?.data?.length, - }; - }); - }, - { - onSuccess(data: any) { - field.setValue(data?.list || []); - }, - manual: true, - // defaultParams: [getDefaultParams()], - }, - ); - useDeepCompareEffectNoCheck(() => { - service.run(getDefaultParams()); - }, [pagination?.pageSize, pagination?.page, props.dragSort, props.defaultSort, props.defaultFilter]); - return ( - { - const { page = 1, pageSize } = pagination; - const total = props.clientSidePagination ? field?.value?.length : service?.data?.total; - const maxPage = Math.ceil(total / pageSize); - if (page > maxPage) { - setPagination({ page: maxPage }); - } else { - refresh(uid()); - } - }, - selectedRowKeys, - setSelectedRowKeys, - pagination, - setPagination, - service, - field, - schema, - props: { ...others, rowKey, dataRequest }, - }} - > - - - ); -}; diff --git a/packages/client/src/schemas/table/TableSortHandle.tsx b/packages/client/src/schemas/table/TableSortHandle.tsx deleted file mode 100644 index 226874d13..000000000 --- a/packages/client/src/schemas/table/TableSortHandle.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; -import { observer } from '@formily/react'; -import { SortableRowHandle } from './Sortable'; - -export const TableSortHandle = observer((props: any) => { - return ; -}); diff --git a/packages/client/src/schemas/table/context.ts b/packages/client/src/schemas/table/context.ts deleted file mode 100644 index 4e6e56764..000000000 --- a/packages/client/src/schemas/table/context.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {createContext} from 'react'; -import {ITableContext,ITableRowContext} from './types'; - -export const TableContext = createContext({} as any); -export const CollectionFieldContext = createContext(null); -export const TableRowContext = createContext(null); diff --git a/packages/client/src/schemas/table/hooks/useActionLogDetailsResource.ts b/packages/client/src/schemas/table/hooks/useActionLogDetailsResource.ts deleted file mode 100644 index d0ecefd2c..000000000 --- a/packages/client/src/schemas/table/hooks/useActionLogDetailsResource.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useContext, useEffect } from 'react'; -import { useTable } from './useTable'; -import useRequest from '@ahooksjs/use-request'; -import { useCollectionContext, useResourceRequest } from '../../../constate'; -import { VisibleContext } from '../../../context'; -import { TableRowContext } from '../context'; - -export const useActionLogDetailsResource = ({ onSuccess }) => { - const { props } = useTable(); - const { collection } = useCollectionContext(); - const ctx = useContext(TableRowContext); - const resource = useResourceRequest({ - resourceName: 'action_logs', - resourceKey: ctx.record[props.rowKey], - }); - const service = useRequest( - (params?: any) => { - return resource.get({ - ...params, - appends: ['changes', 'user', 'collection'], - }); - }, - { - formatResult: (result) => result?.data, - onSuccess, - manual: true, - }, - ); - const [visible] = useContext(VisibleContext); - - useEffect(() => { - if (visible) { - service.run({}); - } - }, [visible]); - - return { resource, service, initialValues: service.data, ...service }; -}; diff --git a/packages/client/src/schemas/table/hooks/useActionLogsResource.ts b/packages/client/src/schemas/table/hooks/useActionLogsResource.ts deleted file mode 100644 index aa6a5f1bd..000000000 --- a/packages/client/src/schemas/table/hooks/useActionLogsResource.ts +++ /dev/null @@ -1,35 +0,0 @@ -import React, { useContext, createContext, useEffect, useState } from 'react'; -import { useTable } from './useTable'; -import { ListOptions, Resource } from '../../../resource'; -import { TableRowContext } from '../context'; -import { useResourceRequest } from '../../../constate'; - -export const useActionLogsResource = (options: any = {}) => { - const { props } = useTable(); - const ctx = useContext(TableRowContext); - - class ActionLogoResource extends Resource { - list(options?: ListOptions) { - console.log({ options }); - let defaultFilter = options?.defaultFilter; - if (ctx?.record) { - const extra = { - index: ctx?.record?.id, - collection_name: props.collectionName, - }; - if (defaultFilter) { - defaultFilter = { and: [defaultFilter, extra] }; - } else { - defaultFilter = extra; - } - } - return super.list({ ...options, defaultFilter }); - } - } - - const resource = useResourceRequest('action_logs', ActionLogoResource); - - return { - resource, - }; -}; diff --git a/packages/client/src/schemas/table/hooks/useCollectionFields.ts b/packages/client/src/schemas/table/hooks/useCollectionFields.ts deleted file mode 100644 index bf55b475d..000000000 --- a/packages/client/src/schemas/table/hooks/useCollectionFields.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Schema } from '@formily/react'; -import { isColumn } from '../utils'; - -export const useCollectionFields = (schema: Schema) => { - const columns = schema.reduceProperties((columns, current) => { - if (isColumn(current)) { - if (current['x-hidden']) { - return columns; - } - if (current['x-display'] && current['x-display'] !== 'visible') { - return columns; - } - return [...columns, current]; - } - return [...columns]; - }, []); - - return columns - .map((column) => { - const columnProps = column['x-component-props'] || {}; - return columnProps.fieldName; - }) - .filter(Boolean); -}; diff --git a/packages/client/src/schemas/table/hooks/useDataSource.ts b/packages/client/src/schemas/table/hooks/useDataSource.ts deleted file mode 100644 index a4d10b82b..000000000 --- a/packages/client/src/schemas/table/hooks/useDataSource.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useTable } from './useTable'; - -export const useDataSource = () => { - const { - pagination, - field, - props: { clientSidePagination, dataRequest }, - } = useTable(); - let dataSource = field.value; - // if (pagination && (clientSidePagination || !dataRequest)) { - // const { page = 1, pageSize } = pagination; - // const startIndex = (page - 1) * pageSize; - // const endIndex = startIndex + pageSize - 1; - // dataSource = field.value?.slice(startIndex, endIndex + 1); - // } - return dataSource; -}; diff --git a/packages/client/src/schemas/table/hooks/useDefaultRowSelection.ts b/packages/client/src/schemas/table/hooks/useDefaultRowSelection.ts deleted file mode 100644 index 6b0deb511..000000000 --- a/packages/client/src/schemas/table/hooks/useDefaultRowSelection.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const useDefaultRowSelection = () => { - return { - type: 'checkbox', - }; -}; diff --git a/packages/client/src/schemas/table/hooks/useDefaultSelectedRowKeys.ts b/packages/client/src/schemas/table/hooks/useDefaultSelectedRowKeys.ts deleted file mode 100644 index cda961352..000000000 --- a/packages/client/src/schemas/table/hooks/useDefaultSelectedRowKeys.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { useState } from "react"; - -export const useDefaultSelectedRowKeys = () => { - const [selectedRowKeys, setSelectedRowKeys] = useState([]); - return { selectedRowKeys, setSelectedRowKeys }; -}; diff --git a/packages/client/src/schemas/table/hooks/usePagination.ts b/packages/client/src/schemas/table/hooks/usePagination.ts deleted file mode 100644 index 66a245afb..000000000 --- a/packages/client/src/schemas/table/hooks/usePagination.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ArrayField } from '@formily/core'; -import { useField } from '@formily/react'; - -export const usePagination = () => { - const field = useField(); - const paginationProps = field.componentProps.pagination; - - let pagination = paginationProps; - - // const [pagination, setPagination] = useState(() => { - // if (!paginationProps) { - // return false; - // } - // const { defaultPageSize = 10, ...others } = paginationProps; - // return { page: 1, pageSize: defaultPageSize, ...others }; - // }); - - // useEffect(() => { - // if (!paginationProps) { - // return setPagination(false); - // } - // const { defaultPageSize = 10, ...others } = paginationProps; - // setPagination({ page: 1, pageSize: defaultPageSize, ...others }); - // }, [paginationProps]); - - return [ - pagination, - (params) => { - const defaults = field.componentProps.pagination; - field.componentProps.pagination = { ...defaults, ...params }; - }, - ]; -}; diff --git a/packages/client/src/schemas/table/hooks/useResource.ts b/packages/client/src/schemas/table/hooks/useResource.ts deleted file mode 100644 index 24b405302..000000000 --- a/packages/client/src/schemas/table/hooks/useResource.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useContext } from 'react'; -import { Schema } from '@formily/react'; -import { useTable } from './useTable'; -import { TableRowContext } from '../context'; -import useRequest from '@ahooksjs/use-request'; -import { useCollectionContext, useResourceRequest } from '../../../constate'; -import { useDesignable } from '../..'; - -export const useResource = ({ onSuccess, manual = true }) => { - const { props } = useTable(); - const { collection } = useCollectionContext(); - const ctx = useContext(TableRowContext); - const resource = useResourceRequest({ - resourceName: collection?.name || props.collectionName, - resourceKey: ctx.record[props.rowKey], - }); - const { schema } = useDesignable(); - const fieldFields = (schema: Schema) => { - const names = []; - schema.reduceProperties((buf, current) => { - if (current['x-component'] === 'Form.Field') { - const fieldName = current['x-component-props']?.['fieldName']; - if (fieldName) { - buf.push(fieldName); - } - } else { - const fieldNames = fieldFields(current); - buf.push(...fieldNames); - } - return buf; - }, names); - return names; - }; - console.log( - 'collection?.name || props.collectionName', - collection?.name || props.collectionName, - // fieldFields(schema), - ); - const service = useRequest( - (params?: any) => { - console.log('Table.useResource', params); - return resource.get({ ...params, appends: fieldFields(schema) }); - }, - { - formatResult: (result) => result?.data, - onSuccess, - manual, - }, - ); - return { resource, service, initialValues: service.data, ...service }; -}; diff --git a/packages/client/src/schemas/table/hooks/useTable.ts b/packages/client/src/schemas/table/hooks/useTable.ts deleted file mode 100644 index d9407cc74..000000000 --- a/packages/client/src/schemas/table/hooks/useTable.ts +++ /dev/null @@ -1,6 +0,0 @@ -import React, { useContext,createContext, useEffect, useState } from 'react'; -import {TableContext} from '../context'; - -export const useTable = () => { - return useContext(TableContext); -}; diff --git a/packages/client/src/schemas/table/hooks/useTableActionBars.ts b/packages/client/src/schemas/table/hooks/useTableActionBars.ts deleted file mode 100644 index 6e078898b..000000000 --- a/packages/client/src/schemas/table/hooks/useTableActionBars.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useTable } from './useTable'; - -export const useTableActionBars = () => { - const { - field, - schema, - props: { rowKey }, - } = useTable(); - - const bars = schema.reduceProperties((bars, current) => { - if (current['x-component'] === 'Table.ActionBar') { - return [...bars, current]; - } - return [...bars]; - }, []); - - return bars; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableColumns.tsx b/packages/client/src/schemas/table/hooks/useTableColumns.tsx deleted file mode 100644 index a5ed31ea7..000000000 --- a/packages/client/src/schemas/table/hooks/useTableColumns.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React,{ createContext } from 'react'; -import { findIndex } from 'lodash'; -import { RecursionField, Schema } from '@formily/react'; -import { useDesignable } from '../..'; -import { useTable } from './useTable'; -import {TableRowContext} from '../context'; -import { useCollectionContext } from '../../../constate'; -import {Table, } from '..'; -import {isColumn} from '../utils' -import {AddColumn } from '../AddColumn'; -import {CollectionFieldContext}from '../context'; - -export const useTableColumns = () => { - const { - field, - schema, - props: { rowKey }, - } = useTable(); - const { designable } = useDesignable(); - - const { getField } = useCollectionContext(); - - const columnSchemas = schema.reduceProperties((columns, current) => { - if (isColumn(current)) { - if (current['x-hidden']) { - return columns; - } - if (current['x-display'] && current['x-display'] !== 'visible') { - return columns; - } - return [...columns, current]; - } - return [...columns]; - }, []); - - const columns: any[] = [].concat( - columnSchemas.map((column: Schema) => { - const columnProps = column['x-component-props'] || {}; - const collectionField = getField(columnProps.fieldName); - return { - title: ( - - - - ), - dataIndex: column.name, - ...columnProps, - render: (_: any, record: any) => { - const index = findIndex(field.value, (item) => item[rowKey] === record[rowKey]); - return ( - - - - - - ); - }, - }; - }), - ); - - if (designable && schema['x-designable-bar'] && schema['x-designable-bar'] !== 'Table.SimpleDesignableBar') { - columns.push({ - title: , - dataIndex: 'addnew', - }); - } - return columns; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableCreateAction.ts b/packages/client/src/schemas/table/hooks/useTableCreateAction.ts deleted file mode 100644 index 77525ae03..000000000 --- a/packages/client/src/schemas/table/hooks/useTableCreateAction.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useForm } from '@formily/react'; -import { useTable } from './useTable'; - -export function useTableCreateAction() { - const { - field, - service, - resource, - refresh, - props: { refreshRequestOnChange }, - } = useTable(); - const form = useForm(); - return { - async run() { - console.log('refreshRequestOnChange', refreshRequestOnChange); - if (refreshRequestOnChange) { - await resource.create(form.values); - await form.reset(); - return service.refresh(); - } - field.unshift(form.values); - }, - }; -} diff --git a/packages/client/src/schemas/table/hooks/useTableDestroyAction.ts b/packages/client/src/schemas/table/hooks/useTableDestroyAction.ts deleted file mode 100644 index 096beff48..000000000 --- a/packages/client/src/schemas/table/hooks/useTableDestroyAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { useContext } from "react"; -import { useTable } from "./useTable"; -import { TableRowContext } from "../context"; -import { VisibleContext } from '../../../context'; -import { findIndex } from 'lodash'; - -export const useTableDestroyAction = () => { - const { - resource, - field, - service, - selectedRowKeys, - setSelectedRowKeys, - refresh, - props: { refreshRequestOnChange, rowKey }, - } = useTable(); - const ctx = useContext(TableRowContext); - const [, setVisible] = useContext(VisibleContext); - return { - async run() { - if (refreshRequestOnChange) { - const rowKeys = selectedRowKeys || []; - if (ctx) { - rowKeys.push(ctx.record[rowKey]); - } - await resource.destroy({ - [`${rowKey}.in`]: rowKeys, - }); - setSelectedRowKeys([]); - setVisible && setVisible(false); - return service.refresh(); - } - if (ctx) { - console.log('ctx.index', ctx.index); - field.remove(ctx.index); - refresh(); - } - const rowKeys = [...selectedRowKeys]; - while (rowKeys.length) { - const key = rowKeys.shift(); - const index = findIndex(field.value, (item) => item[rowKey] === key); - field.remove(index); - } - setSelectedRowKeys([]); - refresh(); - return; - }, - }; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableExportAction.ts b/packages/client/src/schemas/table/hooks/useTableExportAction.ts deleted file mode 100644 index e701c4fb7..000000000 --- a/packages/client/src/schemas/table/hooks/useTableExportAction.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useField } from '@formily/react'; -import { useContext } from 'react'; -import { useTable } from './useTable'; -import { TableRowContext } from '../context'; -import { useCollectionContext } from '../../../constate'; - -export const useTableExportAction = () => { - const { - resource, - field, - service, - selectedRowKeys, - setSelectedRowKeys, - refresh, - schema, - props: { refreshRequestOnChange, rowKey }, - } = useTable(); - const ctx = useContext(TableRowContext); - - const actionField = useField(); - const fieldNames = actionField.componentProps.fieldNames || []; - const { getField } = useCollectionContext(); - - const columns = fieldNames - .map((name) => { - const f = getField(name); - return { - title: f?.uiSchema.title, - name, - sort: f?.sort, - }; - }) - .sort((a, b) => a.sort - b.sort); - - return { - async run() { - const rowKeys = selectedRowKeys || []; - const { filter = {}, ...others } = service.params[0]; - if (rowKeys.length) { - filter[`${rowKey}.in`] = rowKeys; - } - await resource.export({ - ...others, - columns, - perPage: -1, - page: 1, - filter, - }); - }, - }; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableFilterAction.ts b/packages/client/src/schemas/table/hooks/useTableFilterAction.ts deleted file mode 100644 index 6307d65ed..000000000 --- a/packages/client/src/schemas/table/hooks/useTableFilterAction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useTable } from './useTable'; -import { useForm } from '@formily/react'; - -export function useTableFilterAction() { - const { - field, - service, - refresh, - props: { refreshRequestOnChange }, - } = useTable(); - const form = useForm(); - return { - async run() { - console.log('useTableFilterAction', form.values); - if (refreshRequestOnChange) { - return service.run({ - ...service.params[0], - // filter, - }); - } - }, - }; -} diff --git a/packages/client/src/schemas/table/hooks/useTableIndex.ts b/packages/client/src/schemas/table/hooks/useTableIndex.ts deleted file mode 100644 index 513477183..000000000 --- a/packages/client/src/schemas/table/hooks/useTableIndex.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useContext } from 'react'; -import { useTable } from './useTable'; -import { TableRowContext } from '../context'; - -export const useTableIndex = () => { - const { pagination, props } = useTable(); - const ctx = useContext(TableRowContext); - const { pageSize, page = 1 } = pagination; - console.log({ pageSize, page }, ctx.index); - return ctx.index + (page - 1) * pageSize; - if (pagination && !props.clientSidePagination) { - const { pageSize, page = 1 } = pagination; - return ctx.index + (page - 1) * pageSize; - } - return ctx.index; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableRow.ts b/packages/client/src/schemas/table/hooks/useTableRow.ts deleted file mode 100644 index 4eada4723..000000000 --- a/packages/client/src/schemas/table/hooks/useTableRow.ts +++ /dev/null @@ -1,7 +0,0 @@ -import React, { useContext } from 'react'; -import {TableRowContext} from '../context'; - - -export const useTableRow = () => { - return useContext(TableRowContext); -}; diff --git a/packages/client/src/schemas/table/hooks/useTableRowRecord.ts b/packages/client/src/schemas/table/hooks/useTableRowRecord.ts deleted file mode 100644 index 524ca1118..000000000 --- a/packages/client/src/schemas/table/hooks/useTableRowRecord.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useContext } from "react"; -import { TableRowContext } from "../context"; - -export const useTableRowRecord = () => { - const ctx = useContext(TableRowContext); - return ctx.record; -}; diff --git a/packages/client/src/schemas/table/hooks/useTableUpdateAction.ts b/packages/client/src/schemas/table/hooks/useTableUpdateAction.ts deleted file mode 100644 index dc1f417b5..000000000 --- a/packages/client/src/schemas/table/hooks/useTableUpdateAction.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useForm } from "@formily/react"; -import { useContext } from "react"; -import { useTable } from "./useTable"; -import { TableRowContext } from "../context"; -import { DescriptionsContext } from '../../form'; - -export const useTableUpdateAction = () => { - const { - resource, - field, - service, - refresh, - props: { refreshRequestOnChange, rowKey }, - } = useTable(); - const ctx = useContext(TableRowContext); - const form = useForm(); - const { service: formService } = useContext(DescriptionsContext); - - return { - async run() { - if (refreshRequestOnChange) { - await resource.save(form.values, { - resourceKey: ctx.record[rowKey], - }); - if (formService) { - await formService.refresh(); - } - await service.refresh(); - return; - } - field.value[ctx.index] = form.values; - // refresh(); - }, - }; -}; diff --git a/packages/client/src/schemas/table/hooks/useTotal.ts b/packages/client/src/schemas/table/hooks/useTotal.ts deleted file mode 100644 index eb7c29851..000000000 --- a/packages/client/src/schemas/table/hooks/useTotal.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useTable } from './useTable'; - -export const useTotal = () => { - const { - field, - service, - props: { clientSidePagination }, - } = useTable(); - return clientSidePagination ? field?.value?.length : service?.data?.total; -}; diff --git a/packages/client/src/schemas/table/index.tsx b/packages/client/src/schemas/table/index.tsx index d1449ced3..75ef11bc5 100644 --- a/packages/client/src/schemas/table/index.tsx +++ b/packages/client/src/schemas/table/index.tsx @@ -1,31 +1,950 @@ -import React, { useState } from 'react'; -import { observer } from '@formily/react'; -import { CollectionProvider, DisplayedMapProvider } from '../../constate'; +import { + FormProvider, + observer, + RecursionField, + Schema, + useField, + useForm, +} from '@formily/react'; +import { Modal, Pagination, Popover, Table as AntdTable } from 'antd'; +import { cloneDeep, cloneDeepWith, findIndex, forIn, range, set } from 'lodash'; +import React, { Fragment, useEffect, useState } from 'react'; +import { useContext } from 'react'; +import { createContext } from 'react'; +import { useDeepCompareEffectNoCheck } from 'use-deep-compare-effect'; +import { useDesignable, createCollectionField, ISchema } from '..'; +import { uid, merge } from '@formily/shared'; +import useRequest from '@ahooksjs/use-request'; +import { BaseResult } from '@ahooksjs/use-request/lib/types'; +import cls from 'classnames'; +import { MenuOutlined, DragOutlined, FilterOutlined } from '@ant-design/icons'; +import { DndContext, DragOverlay } from '@dnd-kit/core'; +import { + SortableContext, + useSortable, + verticalListSortingStrategy, +} from '@dnd-kit/sortable'; +import { Select, Dropdown, Menu, Switch, Button, Space } from 'antd'; +import { PlusOutlined, SettingOutlined } from '@ant-design/icons'; +import './style.less'; +import { + findPropertyByPath, + getSchemaPath, + SchemaField, + SchemaRenderer, +} from '../../components/schema-renderer'; +import { + interfaces, + isAssociation, + options, +} from '../database-field/interfaces'; +import { DraggableBlockContext } from '../../components/drag-and-drop'; +import AddNew from '../add-new'; +import { isGridRowOrCol } from '../grid'; +import { ListOptions, Resource } from '../../resource'; +import { + CollectionProvider, + DisplayedMapProvider, + useCollection, + useCollectionContext, + useCollectionsContext, + useDisplayedMapContext, + useClient, + useResourceRequest, +} from '../../constate'; +import { useResource as useGeneralResource } from '../../hooks/useResource'; +import SwitchMenuItem from '../../components/SwitchMenuItem'; +import { useMemo } from 'react'; +import { ArrayField, createForm,LifeCycleTypes } from '@formily/core'; +import { + ColDraggableContext, + SortableBodyCell, + SortableBodyRow, + SortableColumn, + SortableHeaderCell, + SortableHeaderRow, + SortableRowHandle, +} from './Sortable'; +import { DragHandle, Droppable, SortableItem } from '../../components/Sortable'; +import { isValid } from '@formily/shared'; +import { FormButtonGroup, FormDialog, FormLayout, Submit } from '@formily/antd'; +import flatten from 'flat'; +import IconPicker from '../../components/icon-picker'; +import { DescriptionsContext } from '../form'; +import { VisibleContext } from '../../context'; import { SimpleDesignableBar } from './SimpleDesignableBar'; -import { useActionLogsResource } from './hooks/useActionLogsResource'; -import { useTableDestroyAction } from './hooks/useTableDestroyAction'; -import { useActionLogDetailsResource } from './hooks/useActionLogDetailsResource'; -import { TableActionBar } from './TableActionBar'; -import { TablePagination } from './TablePagination'; -import { TableFilter } from './TableFilter'; -import { TableFilterDesignableBar } from './TableFilterDesignableBar'; -import { TableExportActionDesignableBar } from './TableExportActionDesignableBar'; -import { useResource } from './hooks/useResource'; -import { TableDesignableBar } from './TableDesignableBar'; -import { useTableFilterAction } from './hooks/useTableFilterAction'; -import { useTableCreateAction } from './hooks/useTableCreateAction'; -import { useTableUpdateAction } from './hooks/useTableUpdateAction'; -import { useTableExportAction } from './hooks/useTableExportAction'; -import { useTableIndex } from './hooks/useTableIndex'; -import { useTableRowRecord } from './hooks/useTableRowRecord'; -import { TableSortHandle } from './TableSortHandle'; -import { TableOperation } from './TableOperation'; -import { TableOperationCell } from './TableOperationCell'; -import { TableCell } from './TableCell'; -import { TableColumn } from './TableColumn'; -import { TableActionDesignableBar } from './TableActionDesignableBar'; -import { TableOperationDesignableBar } from './TableOperationDesignableBar'; -import { TableProvider } from './TableProvider'; +import { Trans, useTranslation } from 'react-i18next'; +import { useCompile } from '../../hooks/useCompile'; + +export interface ITableContext { + props: any; + field: ArrayField; + schema: Schema; + service: BaseResult; + selectedRowKeys?: any; + setSelectedRowKeys?: any; + pagination?: any; + setPagination?: any; + refresh?: any; + resource?: Resource; +} + +export interface ITableRowContext { + index: number; + record: any; +} + +const TableContext = createContext({} as any); +export const TableRowContext = createContext(null); +export const CollectionFieldContext = createContext(null); + +export const useTable = () => { + return useContext(TableContext); +}; + +const useTableRow = () => { + return useContext(TableRowContext); +}; + +function useTableFilterAction() { + const { + field, + service, + refresh, + props: { refreshRequestOnChange }, + } = useTable(); + const form = useForm(); + return { + async run() { + console.log('useTableFilterAction', form.values); + if (refreshRequestOnChange) { + return service.run({ + ...service.params[0], + // filter, + }); + } + }, + }; +} + +function useTableCreateAction() { + const { + field, + service, + resource, + refresh, + props: { refreshRequestOnChange }, + } = useTable(); + const form = useForm(); + return { + async run() { + console.log('refreshRequestOnChange', refreshRequestOnChange); + if (refreshRequestOnChange) { + await resource.create(form.values); + await form.reset(); + return service.refresh(); + } + field.unshift(form.values); + }, + }; +} + +const useTableUpdateAction = () => { + const { + resource, + field, + service, + refresh, + props: { refreshRequestOnChange, rowKey }, + } = useTable(); + const ctx = useContext(TableRowContext); + const form = useForm(); + const { service: formService } = useContext(DescriptionsContext); + + return { + async run() { + if (refreshRequestOnChange) { + await resource.save(form.values, { + resourceKey: ctx.record[rowKey], + }); + if (formService) { + await formService.refresh(); + } + await service.refresh(); + return; + } + field.value[ctx.index] = form.values; + // refresh(); + }, + }; +}; + +const useTableDestroyAction = () => { + const { + resource, + field, + service, + selectedRowKeys, + setSelectedRowKeys, + refresh, + props: { refreshRequestOnChange, rowKey }, + } = useTable(); + const ctx = useContext(TableRowContext); + const [, setVisible] = useContext(VisibleContext); + return { + async run() { + if (refreshRequestOnChange) { + const rowKeys = selectedRowKeys || []; + if (ctx) { + rowKeys.push(ctx.record[rowKey]); + } + await resource.destroy({ + [`${rowKey}.in`]: rowKeys, + }); + setSelectedRowKeys([]); + setVisible && setVisible(false); + return service.refresh(); + } + if (ctx) { + console.log('ctx.index', ctx.index); + field.remove(ctx.index); + refresh(); + } + const rowKeys = [...selectedRowKeys]; + while (rowKeys.length) { + const key = rowKeys.shift(); + const index = findIndex(field.value, (item) => item[rowKey] === key); + field.remove(index); + } + setSelectedRowKeys([]); + refresh(); + return; + }, + }; +}; + +const useTableExportAction = () => { + const { + resource, + field, + service, + selectedRowKeys, + setSelectedRowKeys, + refresh, + schema, + props: { refreshRequestOnChange, rowKey }, + } = useTable(); + const ctx = useContext(TableRowContext); + + const actionField = useField(); + const fieldNames = actionField.componentProps.fieldNames || []; + const { getField } = useCollectionContext(); + + const columns = fieldNames + .map((name) => { + const f = getField(name); + return { + title: f?.uiSchema.title, + name, + sort: f?.sort, + }; + }) + .sort((a, b) => a.sort - b.sort); + + return { + async run() { + const rowKeys = selectedRowKeys || []; + const { filter = {}, ...others } = service.params[0]; + if (rowKeys.length) { + filter[`${rowKey}.in`] = rowKeys; + } + await resource.export({ + ...others, + columns, + perPage: -1, + page: 1, + filter, + }); + }, + }; +}; + +const useTableRowRecord = () => { + const ctx = useContext(TableRowContext); + return ctx.record; +}; + +const useTableIndex = () => { + const { pagination, props } = useTable(); + const ctx = useContext(TableRowContext); + const { pageSize, page = 1 } = pagination; + console.log({ pageSize, page }, ctx.index); + return ctx.index + (page - 1) * pageSize; + if (pagination && !props.clientSidePagination) { + const { pageSize, page = 1 } = pagination; + return ctx.index + (page - 1) * pageSize; + } + return ctx.index; +}; + +const useTableActionBars = () => { + const { + field, + schema, + props: { rowKey }, + } = useTable(); + + const bars = schema.reduceProperties((bars, current) => { + if (current['x-component'] === 'Table.ActionBar') { + return [...bars, current]; + } + return [...bars]; + }, []); + + return bars; +}; + +export function isOperationColumn(schema: Schema) { + return ['Table.Operation'].includes(schema['x-component']); +} + +export function isColumn(schema: Schema) { + return ['Table.Column'].includes(schema['x-component']); +} + +export function isColumnComponent(component: string) { + return ['Table.Operation', 'Table.Column'].includes(component); +} + +const useCollectionFields = (schema: Schema) => { + const columns = schema.reduceProperties((columns, current) => { + if (isColumn(current)) { + if (current['x-hidden']) { + return columns; + } + if (current['x-display'] && current['x-display'] !== 'visible') { + return columns; + } + return [...columns, current]; + } + return [...columns]; + }, []); + + return columns + .map((column) => { + const columnProps = column['x-component-props'] || {}; + return columnProps.fieldName; + }) + .filter(Boolean); +}; + +const useTableColumns = () => { + const { + field, + schema, + props: { rowKey }, + } = useTable(); + const { designable } = useDesignable(); + + const { getField } = useCollectionContext(); + + const columnSchemas = schema.reduceProperties((columns, current) => { + if (isColumn(current)) { + if (current['x-hidden']) { + return columns; + } + if (current['x-display'] && current['x-display'] !== 'visible') { + return columns; + } + return [...columns, current]; + } + return [...columns]; + }, []); + + const columns: any[] = [].concat( + columnSchemas.map((column: Schema) => { + const columnProps = column['x-component-props'] || {}; + const collectionField = getField(columnProps.fieldName); + return { + title: ( + + + + ), + dataIndex: column.name, + ...columnProps, + render: (_: any, record: any) => { + const index = findIndex( + field.value, + (item) => item[rowKey] === record[rowKey], + ); + return ( + + + + + + ); + }, + }; + }), + ); + + if ( + designable && + schema['x-designable-bar'] && + schema['x-designable-bar'] !== 'Table.SimpleDesignableBar' + ) { + columns.push({ + title: , + dataIndex: 'addnew', + }); + } + return columns; +}; + +function AddColumn() { + const { t } = useTranslation(); + const [visible, setVisible] = useState(false); + const { appendChild, remove } = useDesignable(); + const { loadCollections } = useCollectionsContext(); + const { collection, fields, refresh } = useCollectionContext(); + const displayed = useDisplayedMapContext(); + const { service } = useTable(); + const { createSchema, removeSchema, updateSchema } = useClient(); + return ( + + + {fields.map((field) => ( + { + if (checked) { + console.log( + 'SwitchMenuItem.field.name', + field.dataType, + service.params[0], + ); + const columnSchema: ISchema = { + type: 'void', + 'x-component': 'Table.Column', + 'x-component-props': { + fieldName: field.name, + }, + 'x-designable-bar': 'Table.Column.DesignableBar', + }; + if (field.interface === 'linkTo') { + columnSchema.properties = { + options: { + type: 'void', + 'x-decorator': 'Form', + 'x-component': 'Select.Options.Drawer', + 'x-component-props': { + useOkAction: '{{ Select.useOkAction }}', + }, + title: "{{t('Select record')}}", + properties: { + table: { + type: 'array', + 'x-designable-bar': 'Table.DesignableBar', + 'x-decorator': 'BlockItem', + 'x-decorator-props': { + draggable: false, + }, + 'x-component': 'Table', + default: [], + 'x-component-props': { + rowKey: 'id', + useRowSelection: '{{ Select.useRowSelection }}', + useSelectedRowKeys: + '{{ Select.useSelectedRowKeys }}', + onSelect: '{{ Select.useSelect() }}', + collectionName: field.target, + // dragSort: true, + // showIndex: true, + refreshRequestOnChange: true, + pagination: { + pageSize: 10, + }, + }, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Table.ActionBar', + 'x-designable-bar': + 'Table.ActionBar.DesignableBar', + properties: { + [uid()]: { + type: 'void', + title: "{{t('Filter')}}", + 'x-decorator': 'AddNew.Displayed', + 'x-decorator-props': { + displayName: 'filter', + }, + 'x-align': 'left', + 'x-component': 'Table.Filter', + 'x-designable-bar': + 'Table.Filter.DesignableBar', + 'x-component-props': { + fieldNames: [], + }, + }, + }, + }, + }, + }, + }, + }, + option: { + type: 'void', + 'x-component': 'Select.OptionTag', + properties: { + [uid()]: { + type: 'void', + title: "{{t('View record')}}", + 'x-component': 'Action.Drawer', + 'x-component-props': { + bodyStyle: { + background: '#f0f2f5', + }, + }, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Tabs', + 'x-designable-bar': 'Tabs.DesignableBar', + properties: { + [uid()]: { + type: 'void', + title: "{{t('Details')}}", + 'x-designable-bar': + 'Tabs.TabPane.DesignableBar', + 'x-component': 'Tabs.TabPane', + 'x-component-props': {}, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Grid', + 'x-component-props': { + addNewComponent: 'AddNew.PaneItem', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }; + } + const data = appendChild(columnSchema); + await createSchema(data); + if (isAssociation(field)) { + const defaultAppends = + service.params[0]?.defaultAppends || []; + defaultAppends.push(field.name); + await service.run({ + ...service.params[0], + defaultAppends, + }); + } + } else { + const s: any = displayed.get(field.name); + const p = getSchemaPath(s); + const removed = remove(p); + await removeSchema(removed); + displayed.remove(field.name); + if (isAssociation(field)) { + const defaultAppends = + service.params[0]?.defaultAppends || []; + const index = defaultAppends.indexOf(field.name); + if (index > -1) { + defaultAppends.splice(index, 1); + } + await service.run({ + ...service.params[0], + defaultAppends, + }); + } + } + // service.refresh(); + }} + /> + ))} + + + + {options.map((option) => ( + + {option.children.map((item) => ( + { + setVisible(false); + const values = await FormDialog(t('Add field'), () => { + return ( + + + + ); + }).open({ + initialValues: { + interface: item.name, + ...item.default, + key: uid(), + name: `f_${uid()}`, + }, + }); + await createCollectionField(collection?.name, values); + const data = appendChild({ + type: 'void', + 'x-component': 'Table.Column', + 'x-component-props': { + fieldName: values.name, + }, + 'x-designable-bar': 'Table.Column.DesignableBar', + }); + await createSchema(data); + await refresh(); + }} + > + {item.title} + + ))} + + ))} + + + } + > + + + ); +} + +const useDefaultRowSelection = () => { + return { + type: 'checkbox', + }; +}; + +const useDataSource = () => { + const { + pagination, + field, + props: { clientSidePagination, dataRequest }, + } = useTable(); + let dataSource = field.value; + // if (pagination && (clientSidePagination || !dataRequest)) { + // const { page = 1, pageSize } = pagination; + // const startIndex = (page - 1) * pageSize; + // const endIndex = startIndex + pageSize - 1; + // dataSource = field.value?.slice(startIndex, endIndex + 1); + // } + return dataSource; +}; + +const TableMain = () => { + const { + resource, + selectedRowKeys, + setSelectedRowKeys, + service, + field, + props: { + rowKey, + dragSort, + showIndex, + onSelect, + useRowSelection = useDefaultRowSelection, + }, + refresh, + } = useTable(); + const columns = useTableColumns(); + const dataSource = useDataSource(); + const actionBars = useTableActionBars(); + const [html, setHtml] = useState(''); + const { type } = useRowSelection(); + return ( +
+ { + const fromId = event.active?.id as any; + const toId = event.over?.id as any; + if (isValid(fromId) && isValid(toId)) { + const fromIndex = findIndex( + field.value, + (item) => item[rowKey] === fromId, + ); + const toIndex = findIndex( + field.value, + (item) => item[rowKey] === toId, + ); + console.log({ fromId, toId, fromIndex, toIndex }); + field.move(fromIndex, toIndex); + refresh(); + await resource.sort({ + resourceKey: fromId, + target: { + [rowKey]: toId, + }, + }); + await service.refresh(); + } + }} + > + {actionBars.map((actionBar) => ( + + ))} + + {}} + loading={service?.loading} + rowKey={rowKey} + dataSource={dataSource} + columns={columns} + // components={{ + // body: { + // row: DragableBodyRow, + // }, + // }} + components={{ + header: { + row: SortableHeaderRow, + cell: SortableHeaderCell, + }, + body: { + // wrapper: (props) => { + // return ( + // + // + //
+ // + // {props.children} + // + // ); + // }, + row: SortableBodyRow, + // cell: SortableBodyCell, + }, + }} + rowSelection={{ + type: type || 'checkbox', + selectedRowKeys, + onChange: (rowKeys, rows) => { + setSelectedRowKeys(rowKeys); + onSelect && onSelect(rowKeys, rows); + }, + renderCell: (checked, record, _, originNode) => { + const index = findIndex( + field.value, + (item) => item[rowKey] === record[rowKey], + ); + return ( + +
+ {dragSort && } + {showIndex && } + {originNode} +
+
+ ); + }, + }} + /> + + + +
+ ); +}; + +const usePagination = () => { + const field = useField(); + const paginationProps = field.componentProps.pagination; + + let pagination = paginationProps; + + // const [pagination, setPagination] = useState(() => { + // if (!paginationProps) { + // return false; + // } + // const { defaultPageSize = 10, ...others } = paginationProps; + // return { page: 1, pageSize: defaultPageSize, ...others }; + // }); + + // useEffect(() => { + // if (!paginationProps) { + // return setPagination(false); + // } + // const { defaultPageSize = 10, ...others } = paginationProps; + // setPagination({ page: 1, pageSize: defaultPageSize, ...others }); + // }, [paginationProps]); + + return [ + pagination, + (params) => { + const defaults = field.componentProps.pagination; + field.componentProps.pagination = { ...defaults, ...params }; + }, + ]; +}; + +const useDefaultSelectedRowKeys = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + return { selectedRowKeys, setSelectedRowKeys }; +}; + +const TableProvider = (props: any) => { + const { + rowKey = 'id', + dataRequest, + useResource = useGeneralResource, + defaultSelectedRowKeys, + useSelectedRowKeys = useDefaultSelectedRowKeys, + ...others + } = props; + const { schema } = useDesignable(); + const field = useField(); + const [pagination, setPagination] = usePagination(); + const { selectedRowKeys, setSelectedRowKeys } = useSelectedRowKeys(); + console.log('props.useSelectedRowKeys', selectedRowKeys); + const [, refresh] = useState(uid()); + const { resource } = useResource(); + const { sortableField } = useCollectionContext(); + const dragSort = props.dragSort; + const collectionFields = useCollectionFields(schema); + // console.log({ collectionFields, pagination }); + const getDefaultParams = () => { + const defaultParams = { ...pagination }; + if (dragSort) { + defaultParams['sort'] = [sortableField || 'sort']; + } else { + defaultParams['sort'] = (props.defaultSort || []).join(','); + } + defaultParams['defaultAppends'] = [ + ...(props.defaultAppends || []), + ...collectionFields, + ]; + if (props.defaultFilter) { + defaultParams['defaultFilter'] = props.defaultFilter; + } + console.log({ defaultParams }); + return defaultParams; + }; + const service = useRequest( + (params?: any) => { + if (!resource) { + return Promise.resolve({ + list: field.value, + total: field?.value?.length, + }); + } + return resource.list(params).then((res) => { + return { + list: res?.data || [], + total: res?.meta?.count || res?.data?.length, + }; + }); + }, + { + onSuccess(data: any) { + field.setValue(data?.list || []); + }, + manual: true, + // defaultParams: [getDefaultParams()], + }, + ); + useDeepCompareEffectNoCheck(() => { + service.run(getDefaultParams()); + }, [ + pagination?.pageSize, + pagination?.page, + props.dragSort, + props.defaultSort, + props.defaultFilter, + ]); + return ( + { + const { page = 1, pageSize } = pagination; + const total = props.clientSidePagination + ? field?.value?.length + : service?.data?.total; + const maxPage = Math.ceil(total / pageSize); + if (page > maxPage) { + setPagination({ page: maxPage }); + } else { + refresh(uid()); + } + }, + selectedRowKeys, + setSelectedRowKeys, + pagination, + setPagination, + service, + field, + schema, + props: { ...others, rowKey, dataRequest }, + }} + > + + + ); +}; export const Table: any = observer((props: any) => { const [visible, setVisible] = useState(false); @@ -38,24 +957,1703 @@ export const Table: any = observer((props: any) => { ); }); -Table.Pagination = TablePagination; -Table.ActionBar = TableActionBar; -Table.Filter = TableFilter; -Table.Filter.DesignableBar = TableFilterDesignableBar; -Table.ExportActionDesignableBar = TableExportActionDesignableBar; -Table.Operation = TableOperation; -Table.Operation.Cell = TableOperationCell; -Table.Operation.DesignableBar = TableOperationDesignableBar; -Table.Action = () => null; -Table.Action.DesignableBar = TableActionDesignableBar; -Table.Cell = TableCell; -Table.Column = TableColumn; -Table.SortHandle = TableSortHandle; -Table.DesignableBar = TableDesignableBar; -Table.SimpleDesignableBar = SimpleDesignableBar; +const useTotal = () => { + const { + field, + service, + props: { clientSidePagination }, + } = useTable(); + return clientSidePagination ? field?.value?.length : service?.data?.total; +}; + +Table.Pagination = observer(() => { + const { service, pagination, setPagination, props } = useTable(); + if (!pagination || Object.keys(pagination).length === 0) { + return null; + } + const { clientSidePagination } = props; + const total = useTotal(); + const { page = 1 } = pagination; + return ( +
+ { + const page = pagination.pageSize !== pageSize ? 1 : current; + setPagination({ + page, + pageSize, + }); + // if (clientSidePagination) { + // return; + // } + // service.run({ + // ...service.params[0], + // page, + // pageSize, + // }); + }} + /> +
+ ); +}); + +function generateActionSchema(type) { + const actions: { [key: string]: ISchema } = { + filter: { + key: uid(), + name: uid(), + type: 'void', + title: "{{ t('Filter') }}", + 'x-align': 'left', + 'x-decorator': 'AddNew.Displayed', + 'x-decorator-props': { + displayName: 'filter', + }, + 'x-component': 'Table.Filter', + 'x-designable-bar': 'Table.Filter.DesignableBar', + 'x-component-props': { + fieldNames: [], + }, + }, + export: { + key: uid(), + type: 'void', + name: uid(), + title: "{{ t('Export') }}", + 'x-align': 'right', + 'x-decorator': 'AddNew.Displayed', + 'x-decorator-props': { + displayName: 'export', + }, + 'x-action-type': 'export', + 'x-component': 'Action', + 'x-designable-bar': 'Table.ExportActionDesignableBar', + 'x-component-props': { + fieldNames: [], + icon: 'ExportOutlined', + useAction: '{{ Table.useTableExportAction }}', + }, + }, + create: { + key: uid(), + type: 'void', + name: uid(), + title: "{{ t('Add new') }}", + 'x-align': 'right', + 'x-decorator': 'AddNew.Displayed', + 'x-decorator-props': { + displayName: 'create', + }, + 'x-component': 'Action', + 'x-component-props': { + type: 'primary', + icon: 'PlusOutlined', + }, + 'x-designable-bar': 'Table.Action.DesignableBar', + properties: { + modal: { + type: 'void', + title: "{{ t('Add record') }}", + 'x-decorator': 'Form', + 'x-component': 'Action.Drawer', + 'x-component-props': { + useOkAction: '{{ Table.useTableCreateAction }}', + }, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Grid', + 'x-component-props': { + addNewComponent: 'AddNew.FormItem', + }, + }, + }, + }, + }, + }, + destroy: { + key: uid(), + type: 'void', + name: uid(), + title: "{{ t('Delete') }}", + 'x-align': 'right', + 'x-decorator': 'AddNew.Displayed', + 'x-decorator-props': { + displayName: 'destroy', + }, + 'x-action-type': 'destroy', + 'x-component': 'Action', + 'x-designable-bar': 'Table.Action.DesignableBar', + 'x-component-props': { + confirm: { + title: "{{ t('Delete record') }}", + content: "{{ t('Are you sure you want to delete it?') }}", + }, + useAction: '{{ Table.useTableDestroyAction }}', + }, + }, + view: {}, + update: {}, + }; + return actions[type]; +} + +function generateMenuActionSchema(type) { + const actions: { [key: string]: ISchema } = { + view: { + key: uid(), + name: uid(), + type: 'void', + title: "{{ t('View') }}", + 'x-component': 'Action', + 'x-component-props': { + type: 'link', + }, + 'x-designable-bar': 'Table.Action.DesignableBar', + 'x-action-type': 'view', + properties: { + [uid()]: { + type: 'void', + title: "{{ t('View record') }}", + 'x-component': 'Action.Drawer', + 'x-component-props': { + bodyStyle: { + background: '#f0f2f5', + // paddingTop: 0, + }, + }, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Tabs', + 'x-designable-bar': 'Tabs.DesignableBar', + properties: { + [uid()]: { + type: 'void', + title: "{{ t('Details') }}", + 'x-designable-bar': 'Tabs.TabPane.DesignableBar', + 'x-component': 'Tabs.TabPane', + 'x-component-props': {}, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Grid', + 'x-component-props': { + addNewComponent: 'AddNew.PaneItem', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + update: { + key: uid(), + name: uid(), + type: 'void', + title: "{{ t('Edit') }}", + 'x-component': 'Action', + 'x-component-props': { + type: 'link', + }, + 'x-designable-bar': 'Table.Action.DesignableBar', + 'x-action-type': 'update', + properties: { + [uid()]: { + type: 'void', + title: "{{ t('Edit record') }}", + 'x-decorator': 'Form', + 'x-decorator-props': { + useResource: '{{ Table.useResource }}', + useValues: '{{ Table.useTableRowRecord }}', + }, + 'x-component': 'Action.Drawer', + 'x-component-props': { + useOkAction: '{{ Table.useTableUpdateAction }}', + }, + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Grid', + 'x-component-props': { + addNewComponent: 'AddNew.FormItem', + }, + }, + }, + }, + }, + }, + destroy: { + key: uid(), + name: uid(), + type: 'void', + title: "{{ t('Delete') }}", + 'x-component': 'Action', + 'x-designable-bar': 'Table.Action.DesignableBar', + 'x-action-type': 'destroy', + 'x-component-props': { + useAction: '{{ Table.useTableDestroyAction }}', + type: 'link', + confirm: { + title: "{{ t('Delete record') }}", + content: "{{ t('Are you sure you want to delete it?') }}", + }, + }, + }, + }; + return actions[type]; +} + +function AddActionButton() { + const { t } = useTranslation(); + const [visible, setVisible] = useState(false); + const displayed = useDisplayedMapContext(); + const { appendChild, remove } = useDesignable(); + const { schema, designable } = useDesignable(); + const { createSchema, removeSchema, updateSchema } = useClient(); + + if (!designable || !schema['x-designable-bar']) { + return null; + } + return ( + + + {[ + { title: t('Filter'), name: 'filter' }, + { title: t('Export'), name: 'export' }, + { title: t('Add new'), name: 'create' }, + { title: t('Delete'), name: 'destroy' }, + ].map((item) => ( + { + if (!checked) { + const s = displayed.get(item.name) as Schema; + const path = getSchemaPath(s); + displayed.remove(item.name); + const removed = remove(path); + await removeSchema(removed); + } else { + const s = generateActionSchema(item.name); + const data = appendChild(s); + await createSchema(data); + } + }} + /> + ))} + + + + {t('Function')} + {t('Popup form')} + {t('Flexible popup')} + + + } + > + + + ); +} + +function Actions(props: any) { + const { align = 'left' } = props; + const { schema, designable } = useDesignable(); + return ( + + + {schema.mapProperties((s) => { + const currentAlign = s['x-align'] || 'left'; + if (currentAlign !== align) { + return null; + } + return ( + + + + ); + })} + + + ); +} + +Table.ActionBar = observer((props: any) => { + const { align = 'top' } = props; + // const { schema, designable } = useDesignable(); + const { root, schema, insertAfter, remove, appendChild } = useDesignable(); + const moveToAfter = (path1, path2, extra = {}) => { + if (!path1 || !path2) { + return; + } + if (path1.join('.') === path2.join('.')) { + return; + } + const data = findPropertyByPath(root, path1); + if (!data) { + return; + } + remove(path1); + return insertAfter( + { + ...data.toJSON(), + ...extra, + }, + path2, + ); + }; + const { createSchema, removeSchema, updateSchema } = useClient(); + + const [dragOverlayContent, setDragOverlayContent] = useState(''); + return ( + { + setDragOverlayContent(event.active.data?.current?.title || ''); + // const previewRef = event.active.data?.current?.previewRef; + // if (previewRef) { + // setDragOverlayContent(previewRef?.current?.innerHTML); + // } else { + // setDragOverlayContent(''); + // } + }} + onDragEnd={async (event) => { + const path1 = event.active?.data?.current?.path; + const path2 = event.over?.data?.current?.path; + const align = event.over?.data?.current?.align; + const draggable = event.over?.data?.current?.draggable; + if (!path1 || !path2) { + return; + } + if (path1.join('.') === path2.join('.')) { + return; + } + if (!draggable) { + console.log('alignalignalignalign', align); + const p = findPropertyByPath(root, path1); + if (!p) { + return; + } + remove(path1); + const data = appendChild( + { + ...p.toJSON(), + 'x-align': align, + }, + path2, + ); + await updateSchema(data); + } else { + const data = moveToAfter(path1, path2, { + 'x-align': align, + }); + await updateSchema(data); + } + }} + > + + {dragOverlayContent} + {/*
*/} +
+ +
+
+ +
+
+ +
+ +
+
+
+ ); +}); + +const fieldsToFilterColumns = (fields: any[], options: any = {}) => { + const { fieldNames = [] } = options; + const properties = {}; + fields.forEach((field, index) => { + if (fieldNames?.length && !fieldNames.includes(field.name)) { + return; + } + const fieldOption = interfaces.get(field.interface); + if (!fieldOption?.operations) { + return; + } + properties[`column${index}`] = { + type: 'void', + title: field?.uiSchema?.title, + 'x-component': 'Filter.Column', + 'x-component-props': { + operations: fieldOption.operations, + }, + properties: { + [field.name]: { + ...field.uiSchema, + 'x-decorator': 'FormilyFormItem', + title: null, + }, + }, + }; + }); + return properties; +}; + +const fieldsToSortColumns = (fields: any[]) => { + const dataSource = []; + + fields.forEach((field) => { + const fieldOption = interfaces.get(field.interface); + if (!fieldOption?.sortable) { + return; + } + dataSource.push({ + value: field.name, + label: field?.uiSchema?.title, + }); + }); + + return dataSource; +}; + +Table.Filter = observer((props: any) => { + const { service } = useTable(); + const { fieldNames = [] } = props; + const compile = useCompile(); + const { t } = useTranslation(); + const { schema, DesignableBar } = useDesignable(); + const form = useMemo(() => createForm(), []); + const { fields = [] } = useCollectionContext(); + const [visible, setVisible] = useState(false); + const obj = flatten(form.values.filter || {}); + console.log('flatten', obj, Object.values(obj)); + const count = Object.values(obj).filter((i) => + Array.isArray(i) ? i.length : i, + ).length; + const icon = props.icon || 'FilterOutlined'; + const properties = fieldsToFilterColumns(fields, { fieldNames }); + schema.mapProperties((p) => { + properties[p.name] = p; + }); + return ( + + + + + + { + const { filter } = form.values; + console.log('Table.Filter', form.values); + setVisible(false); + return service.run({ + ...service.params[0], + filter, + }); + }} + > + {t('Submit')} + + + +
+ } + > + + + ); +}); + +Table.Filter.DesignableBar = () => { + const { t } = useTranslation(); + const { schema, remove, refresh, insertAfter } = useDesignable(); + const [visible, setVisible] = useState(false); + const displayed = useDisplayedMapContext(); + const { fields } = useCollectionContext(); + const field = useField(); + const { createSchema, removeSchema, updateSchema } = useClient(); + let fieldNames = field.componentProps.fieldNames || []; + if (fieldNames.length === 0) { + fieldNames = fields.map((field) => field.name); + } + return ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + + + { + setVisible(visible); + }} + overlay={ + + + {fields + .filter((collectionField) => { + const option = interfaces.get(collectionField.interface); + return option?.operations?.length; + }) + .map((collectionField) => ( + { + if (checked) { + fieldNames.push(collectionField.name); + } else { + const index = fieldNames.indexOf( + collectionField.name, + ); + if (index > -1) { + fieldNames.splice(index, 1); + } + } + console.log({ fieldNames, field }); + schema['x-component-props']['fieldNames'] = + fieldNames; + field.componentProps.fieldNames = fieldNames; + updateSchema(schema); + }} + /> + ))} + + + { + setVisible(false); + const values = await FormDialog(t('Edit button'), () => { + return ( + + + + ); + }).open({ + initialValues: { + title: schema['title'], + icon: schema['x-component-props']?.['icon'], + }, + }); + schema['title'] = values.title; + schema['x-component-props']['icon'] = values.icon; + field.componentProps.icon = values.icon; + field.title = values.title; + updateSchema(schema); + refresh(); + }} + > + {t('Edit button')} + + + { + const displayName = + schema?.['x-decorator-props']?.['displayName']; + const data = remove(); + await removeSchema(data); + if (displayName) { + displayed.remove(displayName); + } + setVisible(false); + }} + > + {t('Hide')} + + + } + > + + + + +
+ ); +}; + +Table.ExportActionDesignableBar = () => { + const { t } = useTranslation(); + const { schema, remove, refresh, insertAfter } = useDesignable(); + const [visible, setVisible] = useState(false); + const displayed = useDisplayedMapContext(); + const { fields } = useCollectionContext(); + const field = useField(); + const { createSchema, removeSchema, updateSchema } = useClient(); + let fieldNames = field.componentProps.fieldNames || []; + if (fieldNames.length === 0) { + fieldNames = fields.map((field) => field.name); + } + return ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + + + { + setVisible(visible); + }} + overlay={ + + + {fields.map((collectionField) => ( + { + if (checked) { + fieldNames.push(collectionField.name); + } else { + const index = fieldNames.indexOf( + collectionField.name, + ); + if (index > -1) { + fieldNames.splice(index, 1); + } + } + console.log({ fieldNames, field }); + schema['x-component-props']['fieldNames'] = fieldNames; + field.componentProps.fieldNames = fieldNames; + updateSchema(schema); + }} + /> + ))} + + + { + setVisible(false); + const values = await FormDialog(t('Edit button'), () => { + return ( + + + + ); + }).open({ + initialValues: { + title: schema['title'], + icon: schema['x-component-props']?.['icon'], + }, + }); + schema['title'] = values.title; + schema['x-component-props']['icon'] = values.icon; + field.componentProps.icon = values.icon; + field.title = values.title; + updateSchema(schema); + refresh(); + }} + > + {t('Edit button')} + + + { + const displayName = + schema?.['x-decorator-props']?.['displayName']; + const data = remove(); + await removeSchema(data); + if (displayName) { + displayed.remove(displayName); + } + setVisible(false); + }} + > + {t('Hide')} + + + } + > + + + + +
+ ); +}; + +Table.Operation = observer((props: any) => { + const { designable, schema } = useDesignable(); + const { t } = useTranslation(); + return ( +
+ {t('Operations')} + +
+ ); +}); + +Table.Operation.Cell = observer((props: any) => { + const ctx = useContext(TableRowContext); + const schema = props.schema; + return ( +
+ +
+ ); +}); + +Table.Operation.DesignableBar = () => { + const { t } = useTranslation(); + const { schema: columnSchema } = useDesignable(); + const groupSchema = Object.values(columnSchema.properties || {}).shift(); + const groupPath = getSchemaPath(groupSchema); + const { schema, remove, refresh, appendChild } = useDesignable(groupPath); + const [visible, setVisible] = useState(false); + const { createSchema, removeSchema, updateSchema } = useClient(); + + const map = new Map(); + schema.mapProperties((s) => { + if (!s['x-action-type']) { + return; + } + map.set(s['x-action-type'], s.name); + }); + const path = getSchemaPath(schema); + return ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + + + { + setVisible(visible); + }} + overlay={ + + + {[ + { title: t('View'), name: 'view' }, + { title: t('Edit'), name: 'update' }, + { title: t('Delete'), name: 'destroy' }, + ].map((item) => ( + { + if (checked) { + const s = generateMenuActionSchema(item.name); + const data = appendChild(s); + await createSchema(data); + } else if (map.get(item.name)) { + const removed = remove([...path, map.get(item.name)]); + await removeSchema(removed); + } + }} + /> + ))} + + + + + {t('Function')} + + {t('Popup form')} + {t('Flexible popup')} + + + } + > + + + + +
+ ); +}; + +Table.Action = () => null; + +Table.Action.DesignableBar = () => { + const { t } = useTranslation(); + const { schema, remove, refresh, insertAfter } = useDesignable(); + const [visible, setVisible] = useState(false); + const isPopup = Object.keys(schema.properties || {}).length > 0; + const popupSchema = Object.values(schema.properties || {}).shift(); + const inActionBar = schema.parent['x-component'] === 'Table.ActionBar'; + const displayed = useDisplayedMapContext(); + const field = useField(); + const { createSchema, removeSchema, updateSchema } = useClient(); + const popupComponent = popupSchema?.['x-component'] || 'Action.Drawer'; + return ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + + + { + setVisible(visible); + }} + overlay={ + + { + setVisible(false); + const values = await FormDialog(t('Edit button'), () => { + return ( + + + + ); + }).open({ + initialValues: { + title: schema['title'], + icon: schema['x-component-props']?.['icon'], + }, + }); + schema['title'] = values.title; + schema['x-component-props']['icon'] = values.icon; + field.componentProps.icon = values.icon; + field.title = values.title; + updateSchema(schema); + refresh(); + }} + > + {t('Edit button')} + + {isPopup && ( + + + Open in + + + + )} + {!inActionBar && ( + + {t('Triggered when the row is clicked')}    + + + )} + + { + const displayName = + schema?.['x-decorator-props']?.['displayName']; + const data = remove(); + await removeSchema(data); + if (displayName) { + displayed.remove(displayName); + } + setVisible(false); + }} + > + {t('Hide')} + + + } + > + + + + +
+ ); +}; + +Table.Cell = observer((props: any) => { + const ctx = useContext(TableRowContext); + const schema = props.schema; + const collectionField = useContext(CollectionFieldContext); + if (schema['x-component'] === 'Table.Operation') { + return ; + } + let uiSchema = collectionField?.uiSchema as Schema; + if (uiSchema?.['x-component'] === 'Upload.Attachment') { + uiSchema = cloneDeepWith(uiSchema); + set(uiSchema, 'x-component-props.size', 'small'); + } + const componentProps = merge( + uiSchema?.['x-component-props'] || {}, + schema?.['x-component-props'] || {}, + { + arrayMerge: (t, s) => s, + }, + ); + console.log('Table.Cell', collectionField?.interface, componentProps); + return ( +
+ +
+ ); +}); + +Table.Column = observer((props: any) => { + const collectionField = useContext(CollectionFieldContext); + const { schema, DesignableBar } = useDesignable(); + const compile = useCompile(); + const displayed = useDisplayedMapContext(); + useEffect(() => { + if (collectionField?.name) { + displayed.set(collectionField.name, schema); + } + }, [collectionField, schema]); + return ( +
+ {compile(schema.title || collectionField?.uiSchema?.title)} + +
+ ); +}); + +Table.Column.DesignableBar = () => { + const field = useField(); + const { t } = useTranslation(); + const compile = useCompile(); + const { service, refresh: refreshTable } = useTable(); + // const fieldSchema = useFieldSchema(); + const { schema, remove, refresh, insertAfter } = useDesignable(); + const [visible, setVisible] = useState(false); + const displayed = useDisplayedMapContext(); + const { getFieldsByCollection } = useCollectionsContext(); + const collectionField = useContext(CollectionFieldContext); + const { createSchema, removeSchema, updateSchema } = useClient(); + console.log('displayed.map', displayed.map); + return ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + + + { + setVisible(visible); + }} + overlay={ + + { + setVisible(false); + const values = await FormDialog(t('Custom name'), () => { + return ( + + + + ); + }).open({ + initialValues: { + fieldName: collectionField?.uiSchema?.title, + title: schema['title'], + }, + }); + const title = values.title || null; + field.title = title; + schema.title = title; + refresh(); + await updateSchema({ + key: schema['key'], + title: title, + }); + }} + > + {t('Custom column name')} + + {collectionField?.interface === 'linkTo' && ( + +
+ {t('Label field')}{' '} + { + const componentProps = + schema['x-component-props'] || {}; + set( + componentProps, + 'pagination.defaultPageSize', + value, + ); + set(componentProps, 'pagination.pageSize', value); + schema['x-component-props'] = componentProps; + field.componentProps.pagination.pageSize = value; + field.componentProps.pagination.defaultPageSize = value; + refresh(); + updateSchema(schema); + setVisible(false); + }} + defaultValue={defaultPageSize} + > + 10 + 20 + 50 + 100 + + {' items per page'} + + + + { + Modal.confirm({ + title: t('Delete block'), + content: t('Are you sure you want to delete it?'), + onOk: async () => { + const removed = deepRemove(); + // console.log({ removed }) + const last = removed.pop(); + await removeSchema(last); + setVisible(false); + }, + }); + }} + > + {t('Delete')} + +
+ } + > + +
+
+
+
+ ); +}); + +Table.useResource = ({ onSuccess, manual = true }) => { + const { props } = useTable(); + const { collection } = useCollectionContext(); + const ctx = useContext(TableRowContext); + const resource = useResourceRequest({ + resourceName: collection?.name || props.collectionName, + resourceKey: ctx.record[props.rowKey], + }); + const { schema } = useDesignable(); + const fieldFields = (schema: Schema) => { + const names = []; + schema.reduceProperties((buf, current) => { + if (current['x-component'] === 'Form.Field') { + const fieldName = current['x-component-props']?.['fieldName']; + if (fieldName) { + buf.push(fieldName); + } + } else { + const fieldNames = fieldFields(current); + buf.push(...fieldNames); + } + return buf; + }, names); + return names; + }; + console.log( + 'collection?.name || props.collectionName', + collection?.name || props.collectionName, + // fieldFields(schema), + ); + const service = useRequest( + (params?: any) => { + console.log('Table.useResource', params); + return resource.get({ ...params, appends: fieldFields(schema) }); + }, + { + formatResult: (result) => result?.data, + onSuccess, + manual, + }, + ); + return { resource, service, initialValues: service.data, ...service }; +}; + +Table.useActionLogDetailsResource = ({ onSuccess }) => { + const { props } = useTable(); + const { collection } = useCollectionContext(); + const ctx = useContext(TableRowContext); + const resource = useResourceRequest({ + resourceName: 'action_logs', + resourceKey: ctx.record[props.rowKey], + }); + const service = useRequest( + (params?: any) => { + return resource.get({ + ...params, + appends: ['changes', 'user', 'collection'], + }); + }, + { + formatResult: (result) => result?.data, + onSuccess, + manual: true, + }, + ); + const [visible] = useContext(VisibleContext); + + useEffect(() => { + if (visible) { + service.run({}); + } + }, [visible]); + + return { resource, service, initialValues: service.data, ...service }; +}; + +const useActionLogsResource = (options: any = {}) => { + const { props } = useTable(); + const ctx = useContext(TableRowContext); + + class ActionLogoResource extends Resource { + list(options?: ListOptions) { + console.log({ options }); + let defaultFilter = options?.defaultFilter; + if (ctx?.record) { + const extra = { + index: ctx?.record?.id, + collection_name: props.collectionName, + }; + if (defaultFilter) { + defaultFilter = { and: [defaultFilter, extra] }; + } else { + defaultFilter = extra; + } + } + return super.list({ ...options, defaultFilter }); + } + } + + const resource = useResourceRequest('action_logs', ActionLogoResource); + + return { + resource, + }; +}; -Table.useResource = useResource; -Table.useActionLogDetailsResource = useActionLogDetailsResource; Table.useActionLogsResource = useActionLogsResource; Table.useTableFilterAction = useTableFilterAction; Table.useTableCreateAction = useTableCreateAction; @@ -64,3 +2662,4 @@ Table.useTableDestroyAction = useTableDestroyAction; Table.useTableExportAction = useTableExportAction; Table.useTableIndex = useTableIndex; Table.useTableRowRecord = useTableRowRecord; +Table.SimpleDesignableBar = SimpleDesignableBar; diff --git a/packages/client/src/schemas/table/types.ts b/packages/client/src/schemas/table/types.ts deleted file mode 100644 index e14abd146..000000000 --- a/packages/client/src/schemas/table/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ArrayField } from '@formily/core'; -import { FormProvider, observer, RecursionField, Schema, useField, useForm } from '@formily/react'; -import { BaseResult } from '@ahooksjs/use-request/lib/types'; -import { ListOptions, Resource } from '../../resource'; - -export interface ITableContext { - props: any; - field: ArrayField; - schema: Schema; - service: BaseResult; - selectedRowKeys?: any; - setSelectedRowKeys?: any; - pagination?: any; - setPagination?: any; - refresh?: any; - resource?: Resource; -} - -export interface ITableRowContext { - index: number; - record: any; -} diff --git a/packages/client/src/schemas/table/utils.ts b/packages/client/src/schemas/table/utils.ts deleted file mode 100644 index b59e8f10e..000000000 --- a/packages/client/src/schemas/table/utils.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { Schema } from '@formily/react'; -import { uid } from '@formily/shared'; -import { interfaces } from '../database-field/interfaces'; -import { ISchema } from '..'; - -export const fieldsToSortColumns = (fields: any[]) => { - const dataSource = []; - - fields.forEach((field) => { - const fieldOption = interfaces.get(field.interface); - if (!fieldOption?.sortable) { - return; - } - dataSource.push({ - value: field.name, - label: field?.uiSchema?.title, - }); - }); - - return dataSource; -}; - -export const fieldsToFilterColumns = (fields: any[], options: any = {}) => { - const { fieldNames = [] } = options; - const properties = {}; - fields.forEach((field, index) => { - if (fieldNames?.length && !fieldNames.includes(field.name)) { - return; - } - const fieldOption = interfaces.get(field.interface); - if (!fieldOption?.operations) { - return; - } - properties[`column${index}`] = { - type: 'void', - title: field?.uiSchema?.title, - 'x-component': 'Filter.Column', - 'x-component-props': { - operations: fieldOption.operations, - }, - properties: { - [field.name]: { - ...field.uiSchema, - 'x-decorator': 'FormilyFormItem', - title: null, - }, - }, - }; - }); - return properties; -}; - -export const generateActionSchema = (type) => { - const actions: { [key: string]: ISchema } = { - filter: { - key: uid(), - name: uid(), - type: 'void', - title: "{{ t('Filter') }}", - 'x-align': 'left', - 'x-decorator': 'AddNew.Displayed', - 'x-decorator-props': { - displayName: 'filter', - }, - 'x-component': 'Table.Filter', - 'x-designable-bar': 'Table.Filter.DesignableBar', - 'x-component-props': { - fieldNames: [], - }, - }, - export: { - key: uid(), - type: 'void', - name: uid(), - title: "{{ t('Export') }}", - 'x-align': 'right', - 'x-decorator': 'AddNew.Displayed', - 'x-decorator-props': { - displayName: 'export', - }, - 'x-action-type': 'export', - 'x-component': 'Action', - 'x-designable-bar': 'Table.ExportActionDesignableBar', - 'x-component-props': { - fieldNames: [], - icon: 'ExportOutlined', - useAction: '{{ Table.useTableExportAction }}', - }, - }, - create: { - key: uid(), - type: 'void', - name: uid(), - title: "{{ t('Add new') }}", - 'x-align': 'right', - 'x-decorator': 'AddNew.Displayed', - 'x-decorator-props': { - displayName: 'create', - }, - 'x-component': 'Action', - 'x-component-props': { - type: 'primary', - icon: 'PlusOutlined', - }, - 'x-designable-bar': 'Table.Action.DesignableBar', - properties: { - modal: { - type: 'void', - title: "{{ t('Add record') }}", - 'x-decorator': 'Form', - 'x-component': 'Action.Drawer', - 'x-component-props': { - useOkAction: '{{ Table.useTableCreateAction }}', - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Grid', - 'x-component-props': { - addNewComponent: 'AddNew.FormItem', - }, - }, - }, - }, - }, - }, - destroy: { - key: uid(), - type: 'void', - name: uid(), - title: "{{ t('Delete') }}", - 'x-align': 'right', - 'x-decorator': 'AddNew.Displayed', - 'x-decorator-props': { - displayName: 'destroy', - }, - 'x-action-type': 'destroy', - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - 'x-component-props': { - confirm: { - title: "{{ t('Delete record') }}", - content: "{{ t('Are you sure you want to delete it?') }}", - }, - useAction: '{{ Table.useTableDestroyAction }}', - }, - }, - view: {}, - update: {}, - }; - return actions[type]; -}; - -export function isColumn(schema: Schema) { - return ['Table.Column'].includes(schema['x-component']); -} - -export function isColumnComponent(component: string) { - return ['Table.Operation', 'Table.Column'].includes(component); -} - -export function isOperationColumn(schema: Schema) { - return ['Table.Operation'].includes(schema['x-component']); -}