nocobase/packages/core/client/src/block-provider/TableBlockProvider.tsx
chenos cc0f945dbf
feat: date type fields support setting the picker type (#5345)
* refactor: date field support picker

* refactor: date field support picker

* refactor: date time field

* refactor: date time field

* refactor: locale improve

* refactor: defaultValue

* refactor: datetime field

* refactor: remove week

* fix: bug

* fix: bug

* fix:  bug

* fix: test

* fix: test

* fix: test

* fix: test

* fix: test

* refactor: test

* refactor: test

* fix: bug

* fix:  bug

* fix: bug

* refactor: expiresRadio

* refactor: datepicker

* fix: bug

* fix: bug

* fix: bug

* fix: test

* refactor: change operator

* refactor: change picker

* refactor: datetime operator schema

* refactor: filterWithPicker

* refactor: support linkage rule

* fix: bug

* refactor: useFilterFormItemInitializerFields

* refactor: useFilterFormItemInitializerFields

* fix: default value for datetime

* fix: bug

* fix: filter date time

* fix: filter date time

* fix: bug

* fix: bug

* refactor: datePicker RangePicker

* refactor: datePicker RangePicker

* style: date picker style improve

* fix: bug

* fix: bug

* fix: bug

* fix: default value

* fix: bulk edit datetime field

* fix: picker support third party data source

* fix: test

* fix: bug

* chore: fix unit test

---------

Co-authored-by: katherinehhh <katherine_15995@163.com>
Co-authored-by: Zeke Zhang <958414905@qq.com>
2024-09-30 18:38:08 +08:00

193 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { createForm } from '@formily/core';
import { FormContext, useField, useFieldSchema } from '@formily/react';
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useCollectionManager_deprecated } from '../collection-manager';
import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { useTableBlockParams } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
import { FixedBlockWrapper, SchemaComponentOptions } from '../schema-component';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useBlockHeightProps } from './hooks';
/**
* @internal
*/
export const TableBlockContext = createContext<any>({});
TableBlockContext.displayName = 'TableBlockContext';
/**
* @internal
*/
export function getIdsWithChildren(nodes) {
const ids = [];
if (nodes) {
for (const node of nodes) {
if (node?.children && node.children.length > 0) {
ids.push(node.id);
ids.push(...getIdsWithChildren(node?.children));
}
}
}
return ids;
}
interface Props {
params?: any;
showIndex?: boolean;
dragSort?: boolean;
rowKey?: string;
childrenColumnName: any;
fieldNames?: any;
/**
* Table 区块的 collection name
*/
collection?: string;
children?: any;
expandFlag?: boolean;
}
const InternalTableBlockProvider = (props: Props) => {
const {
params,
showIndex,
dragSort,
rowKey,
childrenColumnName,
expandFlag: propsExpandFlag = false,
fieldNames,
...others
} = props;
const field: any = useField();
const { resource, service } = useBlockRequestContext();
const fieldSchema = useFieldSchema();
const [expandFlag, setExpandFlag] = useState(fieldNames || propsExpandFlag ? true : false);
const { heightProps } = useBlockHeightProps();
useEffect(() => {
setExpandFlag(fieldNames || propsExpandFlag);
}, [fieldNames || propsExpandFlag]);
const allIncludesChildren = useMemo(() => {
const { treeTable } = fieldSchema?.['x-decorator-props'] || {};
const data = service?.data?.data;
if (treeTable) {
const keys = getIdsWithChildren(data);
return keys;
}
}, [service?.loading, fieldSchema]);
const setExpandFlagValue = useCallback(
(flag) => {
setExpandFlag(flag || !expandFlag);
},
[expandFlag],
);
return (
<FixedBlockWrapper>
<TableBlockContext.Provider
value={{
...others,
field,
service,
resource,
params,
showIndex,
dragSort,
rowKey,
expandFlag,
childrenColumnName,
allIncludesChildren,
setExpandFlag: setExpandFlagValue,
heightProps,
}}
>
{props.children}
</TableBlockContext.Provider>
</FixedBlockWrapper>
);
};
/**
* @internal
* 用于兼容旧版本的 schema当不需要兼容时可直接移除该方法
* @param props
* @returns
*/
const useTableBlockParamsCompat = (props) => {
const fieldSchema = useFieldSchema();
let params,
parseVariableLoading = false;
// 1. 新版本的 schema 存在 x-use-decorator-props 属性
if (fieldSchema['x-use-decorator-props']) {
params = props.params;
parseVariableLoading = props.parseVariableLoading;
} else {
// 2. 旧版本的 schema 不存在 x-use-decorator-props 属性
// 因为 schema 中是否存在 x-use-decorator-props 是固定不变的,所以这里可以使用 hooks
// eslint-disable-next-line react-hooks/rules-of-hooks
const tableBlockParams = useTableBlockParams(props);
params = tableBlockParams.params;
parseVariableLoading = tableBlockParams.parseVariableLoading;
}
return { params, parseVariableLoading };
};
export const TableBlockProvider = withDynamicSchemaProps((props) => {
const resourceName = props.resource || props.association;
const fieldSchema = useFieldSchema();
const { getCollection, getCollectionField } = useCollectionManager_deprecated(props.dataSource);
const collection = getCollection(props.collection, props.dataSource);
const { treeTable, pagingMode } = fieldSchema?.['x-decorator-props'] || {};
const { params, parseVariableLoading } = useTableBlockParamsCompat(props);
let childrenColumnName = 'children';
if (treeTable) {
if (resourceName?.includes('.')) {
const f = getCollectionField(resourceName);
if (f?.treeChildren) {
childrenColumnName = f.name;
}
params['tree'] = true;
} else {
const f = collection?.fields.find((f) => f.treeChildren);
if (f) {
childrenColumnName = f.name;
}
params['tree'] = true;
}
}
const form = useMemo(() => createForm(), [treeTable]);
// 在解析变量的时候不渲染,避免因为重复请求数据导致的资源浪费
if (parseVariableLoading) {
return null;
}
return (
<SchemaComponentOptions scope={{ treeTable }}>
<FormContext.Provider value={form}>
<BlockProvider name={props.name || 'table'} {...props} params={params} runWhenParamsChanged>
<InternalTableBlockProvider {...props} childrenColumnName={childrenColumnName} params={params} />
</BlockProvider>
</FormContext.Provider>
</SchemaComponentOptions>
);
});
/**
* @internal
*/
export const useTableBlockContext = () => {
return useContext(TableBlockContext);
};