refactor(DataBlock): details block (#3776)
* refactor: remove useless code related 'TableField' * refactor: add details block UI schema and hooks * refactor: update details block schema and create new hook for details block without paging props * refactor: add useDetailsBlockWithoutPagingDecoratorProps and useDetailsBlockWithPagingDecoratorProps * test: add unit tests * chore: fix build * chore: fix import path for withDynamicSchemaProps * fix: fix import typo in createDetailsBlockWithoutPagingUISchema test * chore: fix unit test * refactor: should not get collection on getting association in UISchema * chore: fix unit test * refactor: use x-use-component-props instead of useProps * chore: fix Pagination * chore: skip weird tests * chore: remove weird test * refactor: update details block initializers and associated schemas * refactor: rename to useDetailsWithPaginationProps * refactor: rename to useDetailsWithPaginationDecoratorProps * refactor: rename to createDetailsWithPaginationUISchema * chore: fix unit test * refactor: rename to createDetailsUISchema * refactor: rename to useDetailsDecoratorProps * refactor: rename to useDetailsProps * refactor: rename to 'blockSettings:details' * chore: fix e2e
This commit is contained in:
		
							parent
							
								
									7566a7b357
								
							
						
					
					
						commit
						2468caeeb9
					
				@ -27,6 +27,10 @@ import { useCollapseBlockDecoratorProps } from '../modules/blocks/filter-blocks/
 | 
			
		||||
import { useFilterFormBlockProps } from '../modules/blocks/filter-blocks/form/hooks/useFilterFormBlockProps';
 | 
			
		||||
import { useFilterFormBlockDecoratorProps } from '../modules/blocks/filter-blocks/form/hooks/useFilterFormBlockDecoratorProps';
 | 
			
		||||
import { useGridCardBlockDecoratorProps } from '../modules/blocks/data-blocks/grid-card/hooks/useGridCardBlockDecoratorProps';
 | 
			
		||||
import { useDetailsProps } from '../modules/blocks/data-blocks/details-single/hooks/useDetailsProps';
 | 
			
		||||
import { useDetailsWithPaginationProps } from '../modules/blocks/data-blocks/details-multi/hooks/useDetailsWithPaginationProps';
 | 
			
		||||
import { useDetailsDecoratorProps } from '../modules/blocks/data-blocks/details-single/hooks/useDetailsDecoratorProps';
 | 
			
		||||
import { useDetailsWithPaginationDecoratorProps } from '../modules/blocks/data-blocks/details-multi/hooks/useDetailsWithPaginationDecoratorProps';
 | 
			
		||||
 | 
			
		||||
// TODO: delete this, replaced by `BlockSchemaComponentPlugin`
 | 
			
		||||
export const BlockSchemaComponentProvider: React.FC = (props) => {
 | 
			
		||||
@ -54,6 +58,10 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
 | 
			
		||||
        useEditFormBlockProps,
 | 
			
		||||
        useFormFieldProps,
 | 
			
		||||
        useDetailsBlockProps,
 | 
			
		||||
        useDetailsProps,
 | 
			
		||||
        useDetailsWithPaginationProps,
 | 
			
		||||
        useDetailsDecoratorProps,
 | 
			
		||||
        useDetailsWithPaginationDecoratorProps,
 | 
			
		||||
        useTableFieldProps,
 | 
			
		||||
        useTableBlockProps,
 | 
			
		||||
        useTableSelectorProps,
 | 
			
		||||
@ -108,6 +116,10 @@ export class BlockSchemaComponentPlugin extends Plugin {
 | 
			
		||||
      useEditFormBlockProps,
 | 
			
		||||
      useFormFieldProps,
 | 
			
		||||
      useDetailsBlockProps,
 | 
			
		||||
      useDetailsProps,
 | 
			
		||||
      useDetailsWithPaginationProps,
 | 
			
		||||
      useDetailsDecoratorProps,
 | 
			
		||||
      useDetailsWithPaginationDecoratorProps,
 | 
			
		||||
      useTableFieldProps,
 | 
			
		||||
      useTableBlockProps,
 | 
			
		||||
      useTableSelectorProps,
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import { useCollectionParentRecord } from '../data-source/collection-record/Coll
 | 
			
		||||
import { RecordProvider } from '../record-provider';
 | 
			
		||||
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
 | 
			
		||||
import { useParsedFilter } from './hooks';
 | 
			
		||||
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
 | 
			
		||||
 | 
			
		||||
export const DetailsBlockContext = createContext<any>({});
 | 
			
		||||
DetailsBlockContext.displayName = 'DetailsBlockContext';
 | 
			
		||||
@ -57,13 +58,13 @@ const InternalDetailsBlockProvider = (props) => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const DetailsBlockProvider = (props) => {
 | 
			
		||||
export const DetailsBlockProvider = withDynamicSchemaProps((props) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <BlockProvider name="details" {...props}>
 | 
			
		||||
      <InternalDetailsBlockProvider {...props} />
 | 
			
		||||
    </BlockProvider>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
@ -72,6 +73,11 @@ export const useDetailsBlockContext = () => {
 | 
			
		||||
  return useContext(DetailsBlockContext);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 * 即将废弃,请用 useDetailsWithPaginationProps 或者 useDetailsProps
 | 
			
		||||
 * @returns
 | 
			
		||||
 */
 | 
			
		||||
export const useDetailsBlockProps = () => {
 | 
			
		||||
  const ctx = useDetailsBlockContext();
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
 | 
			
		||||
@ -53,6 +53,10 @@ export const detailsActionInitializers_deprecated = new CompatibleSchemaInitiali
 | 
			
		||||
  ],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 * 已弃用,请使用 readPrettyFormActionInitializers 代替
 | 
			
		||||
 */
 | 
			
		||||
export const detailsActionInitializers = new CompatibleSchemaInitializer(
 | 
			
		||||
  {
 | 
			
		||||
    name: 'detailsWithPaging:configureActions',
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,9 @@ import { TableOutlined } from '@ant-design/icons';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
 | 
			
		||||
import { useCollectionManager_deprecated } from '../../../../collection-manager';
 | 
			
		||||
import { createDetailsBlockSchema } from '../../../../schema-initializer/utils';
 | 
			
		||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
 | 
			
		||||
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
 | 
			
		||||
import { createDetailsWithPaginationUISchema } from './createDetailsWithPaginationUISchema';
 | 
			
		||||
 | 
			
		||||
export const DetailsBlockInitializer = ({
 | 
			
		||||
  filterCollections,
 | 
			
		||||
@ -51,15 +51,14 @@ export const DetailsBlockInitializer = ({
 | 
			
		||||
 | 
			
		||||
        const { item } = options;
 | 
			
		||||
        const collection = getCollection(item.name, item.dataSource);
 | 
			
		||||
        const schema = createDetailsBlockSchema({
 | 
			
		||||
          collection: item.name,
 | 
			
		||||
        const schema = createDetailsWithPaginationUISchema({
 | 
			
		||||
          collectionName: item.name,
 | 
			
		||||
          dataSource: item.dataSource,
 | 
			
		||||
          rowKey: collection.filterTargetKey || 'id',
 | 
			
		||||
          actionInitializers:
 | 
			
		||||
          hideActionInitializer: !(
 | 
			
		||||
            (collection.template !== 'view' || collection?.writableView) &&
 | 
			
		||||
            collection.template !== 'sql' &&
 | 
			
		||||
            'detailsWithPaging:configureActions',
 | 
			
		||||
          settings: 'blockSettings:multiDataDetails',
 | 
			
		||||
            collection.template !== 'sql'
 | 
			
		||||
          ),
 | 
			
		||||
        });
 | 
			
		||||
        insert(schema);
 | 
			
		||||
      }}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,69 @@
 | 
			
		||||
import { createDetailsWithPaginationUISchema } from '../createDetailsWithPaginationUISchema';
 | 
			
		||||
 | 
			
		||||
vi.mock('@formily/shared', () => ({
 | 
			
		||||
  uid: vi.fn().mockReturnValue('mocked-uid'),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
describe('createDetailsBlockWithPaginationUISchema', () => {
 | 
			
		||||
  it('should return the correct schema', () => {
 | 
			
		||||
    const schema = createDetailsWithPaginationUISchema({
 | 
			
		||||
      collectionName: 'users',
 | 
			
		||||
      dataSource: 'users',
 | 
			
		||||
      rowKey: 'id',
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    expect(schema).toMatchInlineSnapshot(`
 | 
			
		||||
      {
 | 
			
		||||
        "properties": {
 | 
			
		||||
          "mocked-uid": {
 | 
			
		||||
            "properties": {
 | 
			
		||||
              "grid": {
 | 
			
		||||
                "properties": {},
 | 
			
		||||
                "type": "void",
 | 
			
		||||
                "x-component": "Grid",
 | 
			
		||||
                "x-initializer": "details:configureFields",
 | 
			
		||||
              },
 | 
			
		||||
              "mocked-uid": {
 | 
			
		||||
                "properties": {},
 | 
			
		||||
                "type": "void",
 | 
			
		||||
                "x-component": "ActionBar",
 | 
			
		||||
                "x-component-props": {
 | 
			
		||||
                  "style": {
 | 
			
		||||
                    "marginBottom": 24,
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                "x-initializer": "details:configureActions",
 | 
			
		||||
              },
 | 
			
		||||
              "pagination": {
 | 
			
		||||
                "type": "void",
 | 
			
		||||
                "x-component": "Pagination",
 | 
			
		||||
                "x-use-component-props": "useDetailsPaginationProps",
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "type": "void",
 | 
			
		||||
            "x-component": "Details",
 | 
			
		||||
            "x-read-pretty": true,
 | 
			
		||||
            "x-use-component-props": "useDetailsWithPaginationProps",
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        "type": "void",
 | 
			
		||||
        "x-acl-action": "users:view",
 | 
			
		||||
        "x-component": "CardItem",
 | 
			
		||||
        "x-decorator": "DetailsBlockProvider",
 | 
			
		||||
        "x-decorator-props": {
 | 
			
		||||
          "action": "list",
 | 
			
		||||
          "association": undefined,
 | 
			
		||||
          "collection": "users",
 | 
			
		||||
          "dataSource": "users",
 | 
			
		||||
          "params": {
 | 
			
		||||
            "pageSize": 1,
 | 
			
		||||
          },
 | 
			
		||||
          "readPretty": true,
 | 
			
		||||
        },
 | 
			
		||||
        "x-settings": "blockSettings:detailsWithPagination",
 | 
			
		||||
        "x-toolbar": "BlockSchemaToolbar",
 | 
			
		||||
        "x-use-decorator-props": "useDetailsWithPaginationDecoratorProps",
 | 
			
		||||
      }
 | 
			
		||||
    `);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,70 @@
 | 
			
		||||
import { ISchema } from '@formily/react';
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
 | 
			
		||||
export function createDetailsWithPaginationUISchema(options: {
 | 
			
		||||
  dataSource: string;
 | 
			
		||||
  rowKey: string;
 | 
			
		||||
  collectionName?: string;
 | 
			
		||||
  association?: string;
 | 
			
		||||
  templateSchema?: ISchema;
 | 
			
		||||
  hideActionInitializer?: boolean;
 | 
			
		||||
}): ISchema {
 | 
			
		||||
  const { collectionName, dataSource, association, templateSchema, hideActionInitializer, rowKey } = options;
 | 
			
		||||
  const resourceName = association || collectionName;
 | 
			
		||||
 | 
			
		||||
  if (!dataSource || !rowKey) {
 | 
			
		||||
    throw new Error('dataSource and rowKey are required');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    type: 'void',
 | 
			
		||||
    'x-acl-action': `${resourceName}:view`,
 | 
			
		||||
    'x-decorator': 'DetailsBlockProvider',
 | 
			
		||||
    'x-use-decorator-props': 'useDetailsWithPaginationDecoratorProps',
 | 
			
		||||
    'x-decorator-props': {
 | 
			
		||||
      dataSource,
 | 
			
		||||
      collection: collectionName,
 | 
			
		||||
      association,
 | 
			
		||||
      readPretty: true,
 | 
			
		||||
      action: 'list',
 | 
			
		||||
      params: {
 | 
			
		||||
        pageSize: 1,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    'x-toolbar': 'BlockSchemaToolbar',
 | 
			
		||||
    'x-settings': 'blockSettings:detailsWithPagination',
 | 
			
		||||
    'x-component': 'CardItem',
 | 
			
		||||
    properties: {
 | 
			
		||||
      [uid()]: {
 | 
			
		||||
        type: 'void',
 | 
			
		||||
        'x-component': 'Details',
 | 
			
		||||
        'x-read-pretty': true,
 | 
			
		||||
        'x-use-component-props': 'useDetailsWithPaginationProps',
 | 
			
		||||
        properties: {
 | 
			
		||||
          [uid()]: {
 | 
			
		||||
            type: 'void',
 | 
			
		||||
            'x-initializer': hideActionInitializer ? undefined : 'details:configureActions',
 | 
			
		||||
            'x-component': 'ActionBar',
 | 
			
		||||
            'x-component-props': {
 | 
			
		||||
              style: {
 | 
			
		||||
                marginBottom: 24,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            properties: {},
 | 
			
		||||
          },
 | 
			
		||||
          grid: templateSchema || {
 | 
			
		||||
            type: 'void',
 | 
			
		||||
            'x-component': 'Grid',
 | 
			
		||||
            'x-initializer': 'details:configureFields',
 | 
			
		||||
            properties: {},
 | 
			
		||||
          },
 | 
			
		||||
          pagination: {
 | 
			
		||||
            type: 'void',
 | 
			
		||||
            'x-component': 'Pagination',
 | 
			
		||||
            'x-use-component-props': 'useDetailsPaginationProps',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,216 @@
 | 
			
		||||
import { ArrayItems } from '@formily/antd-v5';
 | 
			
		||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
 | 
			
		||||
import { useFormBlockContext } from '../../../../block-provider';
 | 
			
		||||
import { useDetailsBlockContext } from '../../../../block-provider/DetailsBlockProvider';
 | 
			
		||||
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
 | 
			
		||||
import { removeNullCondition, useDesignable } from '../../../../schema-component';
 | 
			
		||||
import { SchemaSettingsBlockTitleItem, SchemaSettingsTemplate } from '../../../../schema-settings';
 | 
			
		||||
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
 | 
			
		||||
import { setDataLoadingModeSettingsItem, useDataLoadingMode } from './setDataLoadingModeSettingsItem';
 | 
			
		||||
import { SchemaSettingsItemType } from '../../../../application/schema-settings/types';
 | 
			
		||||
 | 
			
		||||
const commonItems: SchemaSettingsItemType[] = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'title',
 | 
			
		||||
    Component: SchemaSettingsBlockTitleItem,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'dataScope',
 | 
			
		||||
    Component: SchemaSettingsDataScope,
 | 
			
		||||
    useComponentProps() {
 | 
			
		||||
      const { name } = useCollection_deprecated();
 | 
			
		||||
      const fieldSchema = useFieldSchema();
 | 
			
		||||
      const { form } = useFormBlockContext();
 | 
			
		||||
      const field = useField();
 | 
			
		||||
      const { service } = useDetailsBlockContext();
 | 
			
		||||
      const { dn } = useDesignable();
 | 
			
		||||
      const dataLoadingMode = useDataLoadingMode();
 | 
			
		||||
      return {
 | 
			
		||||
        collectionName: name,
 | 
			
		||||
        defaultFilter: fieldSchema?.['x-decorator-props']?.params?.filter || {},
 | 
			
		||||
        form,
 | 
			
		||||
        onSubmit: ({ filter }) => {
 | 
			
		||||
          filter = removeNullCondition(filter);
 | 
			
		||||
          const params = field.decoratorProps.params || {};
 | 
			
		||||
          params.filter = filter;
 | 
			
		||||
          field.decoratorProps.params = params;
 | 
			
		||||
          fieldSchema['x-decorator-props']['params'] = params;
 | 
			
		||||
 | 
			
		||||
          if (dataLoadingMode === 'auto') {
 | 
			
		||||
            service.run({ ...service.params?.[0], filter });
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          dn.emit('patch', {
 | 
			
		||||
            schema: {
 | 
			
		||||
              ['x-uid']: fieldSchema['x-uid'],
 | 
			
		||||
              'x-decorator-props': fieldSchema['x-decorator-props'],
 | 
			
		||||
            },
 | 
			
		||||
          });
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'sortingRules',
 | 
			
		||||
    type: 'modal',
 | 
			
		||||
    useComponentProps() {
 | 
			
		||||
      const { name } = useCollection_deprecated();
 | 
			
		||||
      const { t } = useTranslation();
 | 
			
		||||
      const fieldSchema = useFieldSchema();
 | 
			
		||||
      const field = useField();
 | 
			
		||||
      const { service } = useDetailsBlockContext();
 | 
			
		||||
      const { dn } = useDesignable();
 | 
			
		||||
      const sortFields = useSortFields(name);
 | 
			
		||||
      const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || [];
 | 
			
		||||
      const sort = defaultSort?.map((item: string) => {
 | 
			
		||||
        return item.startsWith('-')
 | 
			
		||||
          ? {
 | 
			
		||||
              field: item.substring(1),
 | 
			
		||||
              direction: 'desc',
 | 
			
		||||
            }
 | 
			
		||||
          : {
 | 
			
		||||
              field: item,
 | 
			
		||||
              direction: 'asc',
 | 
			
		||||
            };
 | 
			
		||||
      });
 | 
			
		||||
      return {
 | 
			
		||||
        title: t('Set default sorting rules'),
 | 
			
		||||
        components: {
 | 
			
		||||
          ArrayItems,
 | 
			
		||||
        },
 | 
			
		||||
        schema: {
 | 
			
		||||
          type: 'object',
 | 
			
		||||
          title: t('Set default sorting rules'),
 | 
			
		||||
          properties: {
 | 
			
		||||
            sort: {
 | 
			
		||||
              type: 'array',
 | 
			
		||||
              default: sort,
 | 
			
		||||
              'x-component': 'ArrayItems',
 | 
			
		||||
              'x-decorator': 'FormItem',
 | 
			
		||||
              items: {
 | 
			
		||||
                type: 'object',
 | 
			
		||||
                properties: {
 | 
			
		||||
                  space: {
 | 
			
		||||
                    type: 'void',
 | 
			
		||||
                    'x-component': 'Space',
 | 
			
		||||
                    properties: {
 | 
			
		||||
                      sort: {
 | 
			
		||||
                        type: 'void',
 | 
			
		||||
                        'x-decorator': 'FormItem',
 | 
			
		||||
                        'x-component': 'ArrayItems.SortHandle',
 | 
			
		||||
                      },
 | 
			
		||||
                      field: {
 | 
			
		||||
                        type: 'string',
 | 
			
		||||
                        enum: sortFields,
 | 
			
		||||
                        required: true,
 | 
			
		||||
                        'x-decorator': 'FormItem',
 | 
			
		||||
                        'x-component': 'Select',
 | 
			
		||||
                        'x-component-props': {
 | 
			
		||||
                          style: {
 | 
			
		||||
                            width: 260,
 | 
			
		||||
                          },
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                      direction: {
 | 
			
		||||
                        type: 'string',
 | 
			
		||||
                        'x-decorator': 'FormItem',
 | 
			
		||||
                        'x-component': 'Radio.Group',
 | 
			
		||||
                        'x-component-props': {
 | 
			
		||||
                          optionType: 'button',
 | 
			
		||||
                        },
 | 
			
		||||
                        enum: [
 | 
			
		||||
                          {
 | 
			
		||||
                            label: t('ASC'),
 | 
			
		||||
                            value: 'asc',
 | 
			
		||||
                          },
 | 
			
		||||
                          {
 | 
			
		||||
                            label: t('DESC'),
 | 
			
		||||
                            value: 'desc',
 | 
			
		||||
                          },
 | 
			
		||||
                        ],
 | 
			
		||||
                      },
 | 
			
		||||
                      remove: {
 | 
			
		||||
                        type: 'void',
 | 
			
		||||
                        'x-decorator': 'FormItem',
 | 
			
		||||
                        'x-component': 'ArrayItems.Remove',
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
              properties: {
 | 
			
		||||
                add: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
                  title: t('Add sort field'),
 | 
			
		||||
                  'x-component': 'ArrayItems.Addition',
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        } as ISchema,
 | 
			
		||||
        onSubmit({ sort }) {
 | 
			
		||||
          const sortArr = sort.map((item) => {
 | 
			
		||||
            return item.direction === 'desc' ? `-${item.field}` : item.field;
 | 
			
		||||
          });
 | 
			
		||||
          const params = field.decoratorProps.params || {};
 | 
			
		||||
          params.sort = sortArr;
 | 
			
		||||
          field.decoratorProps.params = params;
 | 
			
		||||
          fieldSchema['x-decorator-props']['params'] = params;
 | 
			
		||||
          dn.emit('patch', {
 | 
			
		||||
            schema: {
 | 
			
		||||
              ['x-uid']: fieldSchema['x-uid'],
 | 
			
		||||
              'x-decorator-props': fieldSchema['x-decorator-props'],
 | 
			
		||||
            },
 | 
			
		||||
          });
 | 
			
		||||
          service.run({ ...service.params?.[0], sort: sortArr });
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  setDataLoadingModeSettingsItem,
 | 
			
		||||
  {
 | 
			
		||||
    name: 'template',
 | 
			
		||||
    Component: SchemaSettingsTemplate,
 | 
			
		||||
    useComponentProps() {
 | 
			
		||||
      const { name } = useCollection_deprecated();
 | 
			
		||||
      const fieldSchema = useFieldSchema();
 | 
			
		||||
      const defaultResource =
 | 
			
		||||
        fieldSchema?.['x-decorator-props']?.resource || fieldSchema?.['x-decorator-props']?.association;
 | 
			
		||||
      return {
 | 
			
		||||
        componentName: 'Details',
 | 
			
		||||
        collectionName: name,
 | 
			
		||||
        resourceName: defaultResource,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'divider',
 | 
			
		||||
    type: 'divider',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'remove',
 | 
			
		||||
    type: 'remove',
 | 
			
		||||
    componentProps: {
 | 
			
		||||
      removeParentsIfNoChildren: true,
 | 
			
		||||
      breakRemoveOn: {
 | 
			
		||||
        'x-component': 'Grid',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 * 已弃用,请使用 detailsWithPaginationSettings 代替
 | 
			
		||||
 */
 | 
			
		||||
export const multiDataDetailsBlockSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:multiDataDetails',
 | 
			
		||||
  items: commonItems,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const detailsWithPaginationSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:detailsWithPagination',
 | 
			
		||||
  items: commonItems,
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,15 @@
 | 
			
		||||
import { useDataBlockSourceId } from '../../../../../block-provider/hooks/useDataBlockSourceId';
 | 
			
		||||
 | 
			
		||||
export function useDetailsWithPaginationDecoratorProps(props) {
 | 
			
		||||
  let sourceId;
 | 
			
		||||
 | 
			
		||||
  // association 的值是固定不变的,所以可以在条件中使用 hooks
 | 
			
		||||
  if (props.association) {
 | 
			
		||||
    // eslint-disable-next-line react-hooks/rules-of-hooks
 | 
			
		||||
    sourceId = useDataBlockSourceId({ association: props.association });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    sourceId,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
import { useDetailsBlockProps } from '../../../../../block-provider/DetailsBlockProvider';
 | 
			
		||||
 | 
			
		||||
export function useDetailsWithPaginationProps() {
 | 
			
		||||
  return useDetailsBlockProps();
 | 
			
		||||
}
 | 
			
		||||
@ -1,204 +0,0 @@
 | 
			
		||||
import { ArrayItems } from '@formily/antd-v5';
 | 
			
		||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
 | 
			
		||||
import { useFormBlockContext } from '../../../../block-provider';
 | 
			
		||||
import { useDetailsBlockContext } from '../../../../block-provider/DetailsBlockProvider';
 | 
			
		||||
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
 | 
			
		||||
import { removeNullCondition, useDesignable } from '../../../../schema-component';
 | 
			
		||||
import { SchemaSettingsBlockTitleItem, SchemaSettingsTemplate } from '../../../../schema-settings';
 | 
			
		||||
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
 | 
			
		||||
import { setDataLoadingModeSettingsItem, useDataLoadingMode } from './setDataLoadingModeSettingsItem';
 | 
			
		||||
 | 
			
		||||
export const multiDataDetailsBlockSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:multiDataDetails',
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'title',
 | 
			
		||||
      Component: SchemaSettingsBlockTitleItem,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'dataScope',
 | 
			
		||||
      Component: SchemaSettingsDataScope,
 | 
			
		||||
      useComponentProps() {
 | 
			
		||||
        const { name } = useCollection_deprecated();
 | 
			
		||||
        const fieldSchema = useFieldSchema();
 | 
			
		||||
        const { form } = useFormBlockContext();
 | 
			
		||||
        const field = useField();
 | 
			
		||||
        const { service } = useDetailsBlockContext();
 | 
			
		||||
        const { dn } = useDesignable();
 | 
			
		||||
        const dataLoadingMode = useDataLoadingMode();
 | 
			
		||||
        return {
 | 
			
		||||
          collectionName: name,
 | 
			
		||||
          defaultFilter: fieldSchema?.['x-decorator-props']?.params?.filter || {},
 | 
			
		||||
          form,
 | 
			
		||||
          onSubmit: ({ filter }) => {
 | 
			
		||||
            filter = removeNullCondition(filter);
 | 
			
		||||
            const params = field.decoratorProps.params || {};
 | 
			
		||||
            params.filter = filter;
 | 
			
		||||
            field.decoratorProps.params = params;
 | 
			
		||||
            fieldSchema['x-decorator-props']['params'] = params;
 | 
			
		||||
 | 
			
		||||
            if (dataLoadingMode === 'auto') {
 | 
			
		||||
              service.run({ ...service.params?.[0], filter });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            dn.emit('patch', {
 | 
			
		||||
              schema: {
 | 
			
		||||
                ['x-uid']: fieldSchema['x-uid'],
 | 
			
		||||
                'x-decorator-props': fieldSchema['x-decorator-props'],
 | 
			
		||||
              },
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'sortingRules',
 | 
			
		||||
      type: 'modal',
 | 
			
		||||
      useComponentProps() {
 | 
			
		||||
        const { name } = useCollection_deprecated();
 | 
			
		||||
        const { t } = useTranslation();
 | 
			
		||||
        const fieldSchema = useFieldSchema();
 | 
			
		||||
        const field = useField();
 | 
			
		||||
        const { service } = useDetailsBlockContext();
 | 
			
		||||
        const { dn } = useDesignable();
 | 
			
		||||
        const sortFields = useSortFields(name);
 | 
			
		||||
        const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || [];
 | 
			
		||||
        const sort = defaultSort?.map((item: string) => {
 | 
			
		||||
          return item.startsWith('-')
 | 
			
		||||
            ? {
 | 
			
		||||
                field: item.substring(1),
 | 
			
		||||
                direction: 'desc',
 | 
			
		||||
              }
 | 
			
		||||
            : {
 | 
			
		||||
                field: item,
 | 
			
		||||
                direction: 'asc',
 | 
			
		||||
              };
 | 
			
		||||
        });
 | 
			
		||||
        return {
 | 
			
		||||
          title: t('Set default sorting rules'),
 | 
			
		||||
          components: {
 | 
			
		||||
            ArrayItems,
 | 
			
		||||
          },
 | 
			
		||||
          schema: {
 | 
			
		||||
            type: 'object',
 | 
			
		||||
            title: t('Set default sorting rules'),
 | 
			
		||||
            properties: {
 | 
			
		||||
              sort: {
 | 
			
		||||
                type: 'array',
 | 
			
		||||
                default: sort,
 | 
			
		||||
                'x-component': 'ArrayItems',
 | 
			
		||||
                'x-decorator': 'FormItem',
 | 
			
		||||
                items: {
 | 
			
		||||
                  type: 'object',
 | 
			
		||||
                  properties: {
 | 
			
		||||
                    space: {
 | 
			
		||||
                      type: 'void',
 | 
			
		||||
                      'x-component': 'Space',
 | 
			
		||||
                      properties: {
 | 
			
		||||
                        sort: {
 | 
			
		||||
                          type: 'void',
 | 
			
		||||
                          'x-decorator': 'FormItem',
 | 
			
		||||
                          'x-component': 'ArrayItems.SortHandle',
 | 
			
		||||
                        },
 | 
			
		||||
                        field: {
 | 
			
		||||
                          type: 'string',
 | 
			
		||||
                          enum: sortFields,
 | 
			
		||||
                          required: true,
 | 
			
		||||
                          'x-decorator': 'FormItem',
 | 
			
		||||
                          'x-component': 'Select',
 | 
			
		||||
                          'x-component-props': {
 | 
			
		||||
                            style: {
 | 
			
		||||
                              width: 260,
 | 
			
		||||
                            },
 | 
			
		||||
                          },
 | 
			
		||||
                        },
 | 
			
		||||
                        direction: {
 | 
			
		||||
                          type: 'string',
 | 
			
		||||
                          'x-decorator': 'FormItem',
 | 
			
		||||
                          'x-component': 'Radio.Group',
 | 
			
		||||
                          'x-component-props': {
 | 
			
		||||
                            optionType: 'button',
 | 
			
		||||
                          },
 | 
			
		||||
                          enum: [
 | 
			
		||||
                            {
 | 
			
		||||
                              label: t('ASC'),
 | 
			
		||||
                              value: 'asc',
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                              label: t('DESC'),
 | 
			
		||||
                              value: 'desc',
 | 
			
		||||
                            },
 | 
			
		||||
                          ],
 | 
			
		||||
                        },
 | 
			
		||||
                        remove: {
 | 
			
		||||
                          type: 'void',
 | 
			
		||||
                          'x-decorator': 'FormItem',
 | 
			
		||||
                          'x-component': 'ArrayItems.Remove',
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                properties: {
 | 
			
		||||
                  add: {
 | 
			
		||||
                    type: 'void',
 | 
			
		||||
                    title: t('Add sort field'),
 | 
			
		||||
                    'x-component': 'ArrayItems.Addition',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          } as ISchema,
 | 
			
		||||
          onSubmit({ sort }) {
 | 
			
		||||
            const sortArr = sort.map((item) => {
 | 
			
		||||
              return item.direction === 'desc' ? `-${item.field}` : item.field;
 | 
			
		||||
            });
 | 
			
		||||
            const params = field.decoratorProps.params || {};
 | 
			
		||||
            params.sort = sortArr;
 | 
			
		||||
            field.decoratorProps.params = params;
 | 
			
		||||
            fieldSchema['x-decorator-props']['params'] = params;
 | 
			
		||||
            dn.emit('patch', {
 | 
			
		||||
              schema: {
 | 
			
		||||
                ['x-uid']: fieldSchema['x-uid'],
 | 
			
		||||
                'x-decorator-props': fieldSchema['x-decorator-props'],
 | 
			
		||||
              },
 | 
			
		||||
            });
 | 
			
		||||
            service.run({ ...service.params?.[0], sort: sortArr });
 | 
			
		||||
          },
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    setDataLoadingModeSettingsItem,
 | 
			
		||||
    {
 | 
			
		||||
      name: 'template',
 | 
			
		||||
      Component: SchemaSettingsTemplate,
 | 
			
		||||
      useComponentProps() {
 | 
			
		||||
        const { name } = useCollection_deprecated();
 | 
			
		||||
        const fieldSchema = useFieldSchema();
 | 
			
		||||
        const defaultResource =
 | 
			
		||||
          fieldSchema?.['x-decorator-props']?.resource || fieldSchema?.['x-decorator-props']?.association;
 | 
			
		||||
        return {
 | 
			
		||||
          componentName: 'Details',
 | 
			
		||||
          collectionName: name,
 | 
			
		||||
          resourceName: defaultResource,
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'divider',
 | 
			
		||||
      type: 'divider',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'remove',
 | 
			
		||||
      type: 'remove',
 | 
			
		||||
      componentProps: {
 | 
			
		||||
        removeParentsIfNoChildren: true,
 | 
			
		||||
        breakRemoveOn: {
 | 
			
		||||
          'x-component': 'Grid',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
});
 | 
			
		||||
@ -47,6 +47,7 @@ const AssociatedFields = () => {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 * 已弃用,请使用 readPrettyFormItemInitializers 代替
 | 
			
		||||
 */
 | 
			
		||||
export const readPrettyFormItemInitializers_deprecated = new CompatibleSchemaInitializer({
 | 
			
		||||
  name: 'ReadPrettyFormItemInitializers',
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
import { FormOutlined } from '@ant-design/icons';
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
 | 
			
		||||
import { useBlockAssociationContext, useBlockRequestContext } from '../../../../block-provider';
 | 
			
		||||
import { useBlockAssociationContext } from '../../../../block-provider';
 | 
			
		||||
import { useCollection_deprecated } from '../../../../collection-manager';
 | 
			
		||||
import { useSchemaTemplateManager } from '../../../../schema-templates';
 | 
			
		||||
import { createDetailsBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
 | 
			
		||||
import { useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
 | 
			
		||||
import { createDetailsUISchema } from './createDetailsUISchema';
 | 
			
		||||
 | 
			
		||||
export const RecordReadPrettyFormBlockInitializer = () => {
 | 
			
		||||
  const itemConfig = useSchemaInitializerItem();
 | 
			
		||||
@ -24,29 +25,27 @@ export const RecordReadPrettyFormBlockInitializer = () => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function useCreateSingleDetailsSchema() {
 | 
			
		||||
  const itemConfig = useSchemaInitializerItem();
 | 
			
		||||
  const { insert } = useSchemaInitializer();
 | 
			
		||||
  const { getTemplateSchemaByMode } = useSchemaTemplateManager();
 | 
			
		||||
  const association = useBlockAssociationContext();
 | 
			
		||||
  const { block } = useBlockRequestContext();
 | 
			
		||||
  const actionInitializers =
 | 
			
		||||
    block !== 'TableField' ? itemConfig.actionInitializers || 'details:configureActions' : null;
 | 
			
		||||
 | 
			
		||||
  const templateWrap = useCallback(
 | 
			
		||||
    (templateSchema, options) => {
 | 
			
		||||
      const { item } = options;
 | 
			
		||||
      if (item.template.componentName === 'ReadPrettyFormItem') {
 | 
			
		||||
        const blockSchema = createDetailsBlockSchema({
 | 
			
		||||
          actionInitializers,
 | 
			
		||||
          association,
 | 
			
		||||
          collection: item.collectionName || item.name,
 | 
			
		||||
          dataSource: item.dataSource,
 | 
			
		||||
          action: 'get',
 | 
			
		||||
          useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
          useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
          template: templateSchema,
 | 
			
		||||
          settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
        });
 | 
			
		||||
        const blockSchema = createDetailsUISchema(
 | 
			
		||||
          association
 | 
			
		||||
            ? {
 | 
			
		||||
                association,
 | 
			
		||||
                dataSource: item.dataSource,
 | 
			
		||||
                templateSchema: templateSchema,
 | 
			
		||||
              }
 | 
			
		||||
            : {
 | 
			
		||||
                collectionName: item.collectionName || item.name,
 | 
			
		||||
                dataSource: item.dataSource,
 | 
			
		||||
                templateSchema: templateSchema,
 | 
			
		||||
              },
 | 
			
		||||
        );
 | 
			
		||||
        if (item.mode === 'reference') {
 | 
			
		||||
          blockSchema['x-template-key'] = item.template.key;
 | 
			
		||||
        }
 | 
			
		||||
@ -55,7 +54,7 @@ export function useCreateSingleDetailsSchema() {
 | 
			
		||||
        return templateSchema;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    [actionInitializers, association],
 | 
			
		||||
    [association],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const createSingleDetailsSchema = useCallback(
 | 
			
		||||
@ -65,20 +64,21 @@ export function useCreateSingleDetailsSchema() {
 | 
			
		||||
        insert(templateWrap(template, { item }));
 | 
			
		||||
      } else {
 | 
			
		||||
        insert(
 | 
			
		||||
          createDetailsBlockSchema({
 | 
			
		||||
            actionInitializers,
 | 
			
		||||
            association,
 | 
			
		||||
            collection: item.collectionName || item.name,
 | 
			
		||||
            dataSource: item.dataSource,
 | 
			
		||||
            action: 'get',
 | 
			
		||||
            useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
            useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
            settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
          }),
 | 
			
		||||
          createDetailsUISchema(
 | 
			
		||||
            association
 | 
			
		||||
              ? {
 | 
			
		||||
                  association,
 | 
			
		||||
                  dataSource: item.dataSource,
 | 
			
		||||
                }
 | 
			
		||||
              : {
 | 
			
		||||
                  collectionName: item.collectionName || item.name,
 | 
			
		||||
                  dataSource: item.dataSource,
 | 
			
		||||
                },
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    [actionInitializers, association, getTemplateSchemaByMode, insert, templateWrap],
 | 
			
		||||
    [association, getTemplateSchemaByMode, insert, templateWrap],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return { createSingleDetailsSchema, templateWrap };
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,62 @@
 | 
			
		||||
import { createDetailsUISchema } from '../createDetailsUISchema';
 | 
			
		||||
 | 
			
		||||
// Mock uid to always return a fixed value
 | 
			
		||||
vi.mock('@formily/shared', () => ({
 | 
			
		||||
  uid: () => 'fixed-uid',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
describe('createDetailsBlockWithoutPagingUISchema', () => {
 | 
			
		||||
  it('should create a valid schema with mandatory fields', () => {
 | 
			
		||||
    const options = {
 | 
			
		||||
      collectionName: 'users',
 | 
			
		||||
      dataSource: 'usersDataSource',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const result = createDetailsUISchema(options);
 | 
			
		||||
    expect(result).toMatchInlineSnapshot(`
 | 
			
		||||
      {
 | 
			
		||||
        "properties": {
 | 
			
		||||
          "fixed-uid": {
 | 
			
		||||
            "properties": {
 | 
			
		||||
              "fixed-uid": {
 | 
			
		||||
                "properties": {},
 | 
			
		||||
                "type": "void",
 | 
			
		||||
                "x-component": "ActionBar",
 | 
			
		||||
                "x-component-props": {
 | 
			
		||||
                  "style": {
 | 
			
		||||
                    "marginBottom": 24,
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                "x-initializer": "details:configureActions",
 | 
			
		||||
              },
 | 
			
		||||
              "grid": {
 | 
			
		||||
                "properties": {},
 | 
			
		||||
                "type": "void",
 | 
			
		||||
                "x-component": "Grid",
 | 
			
		||||
                "x-initializer": "details:configureFields",
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "type": "void",
 | 
			
		||||
            "x-component": "Details",
 | 
			
		||||
            "x-read-pretty": true,
 | 
			
		||||
            "x-use-component-props": "useDetailsProps",
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        "type": "void",
 | 
			
		||||
        "x-acl-action": "users:get",
 | 
			
		||||
        "x-component": "CardItem",
 | 
			
		||||
        "x-decorator": "DetailsBlockProvider",
 | 
			
		||||
        "x-decorator-props": {
 | 
			
		||||
          "action": "get",
 | 
			
		||||
          "association": undefined,
 | 
			
		||||
          "collection": "users",
 | 
			
		||||
          "dataSource": "usersDataSource",
 | 
			
		||||
          "readPretty": true,
 | 
			
		||||
        },
 | 
			
		||||
        "x-settings": "blockSettings:details",
 | 
			
		||||
        "x-toolbar": "BlockSchemaToolbar",
 | 
			
		||||
        "x-use-decorator-props": "useDetailsDecoratorProps",
 | 
			
		||||
      }
 | 
			
		||||
    `);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,60 @@
 | 
			
		||||
import { ISchema } from '@formily/react';
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
 | 
			
		||||
export function createDetailsUISchema(options: {
 | 
			
		||||
  dataSource: string;
 | 
			
		||||
  collectionName?: string;
 | 
			
		||||
  association?: string;
 | 
			
		||||
  templateSchema?: ISchema;
 | 
			
		||||
}): ISchema {
 | 
			
		||||
  const { collectionName, dataSource, association, templateSchema } = options;
 | 
			
		||||
  const resourceName = association || collectionName;
 | 
			
		||||
 | 
			
		||||
  if (!dataSource) {
 | 
			
		||||
    throw new Error('dataSource are required');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    type: 'void',
 | 
			
		||||
    'x-acl-action': `${resourceName}:get`,
 | 
			
		||||
    'x-decorator': 'DetailsBlockProvider',
 | 
			
		||||
    'x-use-decorator-props': 'useDetailsDecoratorProps',
 | 
			
		||||
    'x-decorator-props': {
 | 
			
		||||
      dataSource,
 | 
			
		||||
      collection: collectionName,
 | 
			
		||||
      association,
 | 
			
		||||
      readPretty: true,
 | 
			
		||||
      action: 'get',
 | 
			
		||||
    },
 | 
			
		||||
    'x-toolbar': 'BlockSchemaToolbar',
 | 
			
		||||
    'x-settings': 'blockSettings:details',
 | 
			
		||||
    'x-component': 'CardItem',
 | 
			
		||||
    properties: {
 | 
			
		||||
      [uid()]: {
 | 
			
		||||
        type: 'void',
 | 
			
		||||
        'x-component': 'Details',
 | 
			
		||||
        'x-read-pretty': true,
 | 
			
		||||
        'x-use-component-props': 'useDetailsProps',
 | 
			
		||||
        properties: {
 | 
			
		||||
          [uid()]: {
 | 
			
		||||
            type: 'void',
 | 
			
		||||
            'x-initializer': 'details:configureActions',
 | 
			
		||||
            'x-component': 'ActionBar',
 | 
			
		||||
            'x-component-props': {
 | 
			
		||||
              style: {
 | 
			
		||||
                marginBottom: 24,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            properties: {},
 | 
			
		||||
          },
 | 
			
		||||
          grid: templateSchema || {
 | 
			
		||||
            type: 'void',
 | 
			
		||||
            'x-component': 'Grid',
 | 
			
		||||
            'x-initializer': 'details:configureFields',
 | 
			
		||||
            properties: {},
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
import { useFieldSchema } from '@formily/react';
 | 
			
		||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
 | 
			
		||||
import { useCollection_deprecated } from '../../../../collection-manager';
 | 
			
		||||
import { SchemaSettingsBlockTitleItem, SchemaSettingsFormItemTemplate } from '../../../../schema-settings';
 | 
			
		||||
import { SchemaSettingsItemType } from '../../../../application/schema-settings/types';
 | 
			
		||||
 | 
			
		||||
const commonItems: SchemaSettingsItemType[] = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'title',
 | 
			
		||||
    Component: SchemaSettingsBlockTitleItem,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'formItemTemplate',
 | 
			
		||||
    Component: SchemaSettingsFormItemTemplate,
 | 
			
		||||
    useComponentProps() {
 | 
			
		||||
      const { name } = useCollection_deprecated();
 | 
			
		||||
      const fieldSchema = useFieldSchema();
 | 
			
		||||
      const defaultResource =
 | 
			
		||||
        fieldSchema?.['x-decorator-props']?.resource || fieldSchema?.['x-decorator-props']?.association;
 | 
			
		||||
      return {
 | 
			
		||||
        insertAdjacentPosition: 'beforeEnd',
 | 
			
		||||
        componentName: 'ReadPrettyFormItem',
 | 
			
		||||
        collectionName: name,
 | 
			
		||||
        resourceName: defaultResource,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'divider',
 | 
			
		||||
    type: 'divider',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'remove',
 | 
			
		||||
    type: 'remove',
 | 
			
		||||
    componentProps: {
 | 
			
		||||
      removeParentsIfNoChildren: true,
 | 
			
		||||
      breakRemoveOn: {
 | 
			
		||||
        'x-component': 'Grid',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 * 已弃用,请使用 detailsBlockSettings 代替
 | 
			
		||||
 */
 | 
			
		||||
export const singleDataDetailsBlockSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:singleDataDetails',
 | 
			
		||||
  items: commonItems,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const detailsBlockSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:details',
 | 
			
		||||
  items: commonItems,
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
import { useParamsFromRecord } from '../../../../../block-provider/BlockProvider';
 | 
			
		||||
import { useDataBlockSourceId } from '../../../../../block-provider/hooks/useDataBlockSourceId';
 | 
			
		||||
 | 
			
		||||
export function useDetailsDecoratorProps(props) {
 | 
			
		||||
  const params = useParamsFromRecord();
 | 
			
		||||
  let sourceId;
 | 
			
		||||
 | 
			
		||||
  // association 的值是固定不变的,所以可以在条件中使用 hooks
 | 
			
		||||
  if (props.association) {
 | 
			
		||||
    // eslint-disable-next-line react-hooks/rules-of-hooks
 | 
			
		||||
    sourceId = useDataBlockSourceId({ association: props.association });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    params,
 | 
			
		||||
    sourceId,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
import { useDetailsBlockProps } from '../../../../../block-provider/DetailsBlockProvider';
 | 
			
		||||
 | 
			
		||||
export function useDetailsProps() {
 | 
			
		||||
  return useDetailsBlockProps();
 | 
			
		||||
}
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
import { useFieldSchema } from '@formily/react';
 | 
			
		||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
 | 
			
		||||
import { useCollection_deprecated } from '../../../../collection-manager';
 | 
			
		||||
import { SchemaSettingsBlockTitleItem, SchemaSettingsFormItemTemplate } from '../../../../schema-settings';
 | 
			
		||||
 | 
			
		||||
export const singleDataDetailsBlockSettings = new SchemaSettings({
 | 
			
		||||
  name: 'blockSettings:singleDataDetails',
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'title',
 | 
			
		||||
      Component: SchemaSettingsBlockTitleItem,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'formItemTemplate',
 | 
			
		||||
      Component: SchemaSettingsFormItemTemplate,
 | 
			
		||||
      useComponentProps() {
 | 
			
		||||
        const { name } = useCollection_deprecated();
 | 
			
		||||
        const fieldSchema = useFieldSchema();
 | 
			
		||||
        const defaultResource =
 | 
			
		||||
          fieldSchema?.['x-decorator-props']?.resource || fieldSchema?.['x-decorator-props']?.association;
 | 
			
		||||
        return {
 | 
			
		||||
          insertAdjacentPosition: 'beforeEnd',
 | 
			
		||||
          componentName: 'ReadPrettyFormItem',
 | 
			
		||||
          collectionName: name,
 | 
			
		||||
          resourceName: defaultResource,
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'divider',
 | 
			
		||||
      type: 'divider',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'remove',
 | 
			
		||||
      type: 'remove',
 | 
			
		||||
      componentProps: {
 | 
			
		||||
        removeParentsIfNoChildren: true,
 | 
			
		||||
        breakRemoveOn: {
 | 
			
		||||
          'x-component': 'Grid',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
});
 | 
			
		||||
@ -88,7 +88,7 @@ test.describe('where to open a popup and what can be added to it', () => {
 | 
			
		||||
    // 删除已创建的 blocks,腾出页面空间
 | 
			
		||||
    // delete details block
 | 
			
		||||
    await page.getByText('GeneralConfigure actionsConfigure fields').hover();
 | 
			
		||||
    await page.getByLabel('designer-schema-settings-CardItem-blockSettings:singleDataDetails-general').hover();
 | 
			
		||||
    await page.getByLabel('designer-schema-settings-CardItem-blockSettings:details-general').hover();
 | 
			
		||||
    await page.getByRole('menuitem', { name: 'Delete' }).click();
 | 
			
		||||
    await page.getByRole('button', { name: 'OK', exact: true }).click();
 | 
			
		||||
    // delete form block
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,9 @@ import { FormV2 } from '../form-v2';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { Empty } from 'antd';
 | 
			
		||||
import { useDataBlockRequest } from '../../../data-source';
 | 
			
		||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
 | 
			
		||||
 | 
			
		||||
export const Details = (props) => {
 | 
			
		||||
export const Details = withDynamicSchemaProps((props) => {
 | 
			
		||||
  const request = useDataBlockRequest();
 | 
			
		||||
 | 
			
		||||
  if (!request?.loading && _.isEmpty(request?.data?.data)) {
 | 
			
		||||
@ -12,4 +13,4 @@ export const Details = (props) => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <FormV2 {...props} />;
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
import { render } from '@nocobase/test/client';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { Pagination } from '../index';
 | 
			
		||||
 | 
			
		||||
describe('Pagination', () => {
 | 
			
		||||
  it('should render correctly', () => {
 | 
			
		||||
    render(<Pagination />);
 | 
			
		||||
    expect(document.querySelector('.ant-pagination')).toBeInTheDocument();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('hidden', () => {
 | 
			
		||||
    render(<Pagination hidden />);
 | 
			
		||||
    expect(document.querySelector('.ant-pagination')).not.toBeInTheDocument();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -2,24 +2,29 @@ import { observer } from '@formily/react';
 | 
			
		||||
import { Pagination as AntdPagination } from 'antd';
 | 
			
		||||
import React, { KeyboardEventHandler } from 'react';
 | 
			
		||||
import { useProps } from '../../hooks/useProps';
 | 
			
		||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
 | 
			
		||||
 | 
			
		||||
export const Pagination = observer(
 | 
			
		||||
  (props: any) => {
 | 
			
		||||
    const { hidden, ...others } = useProps(props);
 | 
			
		||||
    if (hidden) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
    const onKeypress: KeyboardEventHandler<HTMLDivElement> = (e) => {
 | 
			
		||||
      if (e.key === 'Enter') {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
export const Pagination = withDynamicSchemaProps(
 | 
			
		||||
  observer(
 | 
			
		||||
    (props: any) => {
 | 
			
		||||
      // 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema
 | 
			
		||||
      const { hidden, ...others } = useProps(props);
 | 
			
		||||
 | 
			
		||||
      if (hidden) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
      const onKeypress: KeyboardEventHandler<HTMLDivElement> = (e) => {
 | 
			
		||||
        if (e.key === 'Enter') {
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div onKeyPress={onKeypress}>
 | 
			
		||||
        <AntdPagination {...others} />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  { displayName: 'Pagination' },
 | 
			
		||||
      return (
 | 
			
		||||
        <div onKeyPress={onKeypress}>
 | 
			
		||||
          <AntdPagination {...others} />
 | 
			
		||||
        </div>
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    { displayName: 'Pagination' },
 | 
			
		||||
  ),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,8 @@ import React, { useCallback } from 'react';
 | 
			
		||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
 | 
			
		||||
import { useCollectionManager_deprecated } from '../../collection-manager';
 | 
			
		||||
import { useSchemaTemplateManager } from '../../schema-templates';
 | 
			
		||||
import { createDetailsBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
 | 
			
		||||
import { useRecordCollectionDataSourceItems } from '../utils';
 | 
			
		||||
import { createDetailsWithPaginationUISchema } from '../../modules/blocks/data-blocks/details-multi/createDetailsWithPaginationUISchema';
 | 
			
		||||
 | 
			
		||||
export const RecordAssociationDetailsBlockInitializer = () => {
 | 
			
		||||
  const itemConfig = useSchemaInitializerItem();
 | 
			
		||||
@ -25,13 +26,10 @@ export const RecordAssociationDetailsBlockInitializer = () => {
 | 
			
		||||
          insert(s);
 | 
			
		||||
        } else {
 | 
			
		||||
          insert(
 | 
			
		||||
            createDetailsBlockSchema({
 | 
			
		||||
              collection: field.target,
 | 
			
		||||
              resource,
 | 
			
		||||
            createDetailsWithPaginationUISchema({
 | 
			
		||||
              dataSource: collection.dataSource,
 | 
			
		||||
              association: resource,
 | 
			
		||||
              rowKey: collection.filterTargetKey || 'id',
 | 
			
		||||
              settings: 'blockSettings:multiDataDetails',
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
@ -51,12 +49,10 @@ export function useCreateAssociationDetailsBlock() {
 | 
			
		||||
      const collection = getCollection(field.target);
 | 
			
		||||
 | 
			
		||||
      insert(
 | 
			
		||||
        createDetailsBlockSchema({
 | 
			
		||||
          collection: field.target,
 | 
			
		||||
        createDetailsWithPaginationUISchema({
 | 
			
		||||
          dataSource: collection.dataSource,
 | 
			
		||||
          association: `${field.collectionName}.${field.name}`,
 | 
			
		||||
          rowKey: collection.filterTargetKey || 'id',
 | 
			
		||||
          settings: 'blockSettings:multiDataDetails',
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,10 @@ import { FormOutlined } from '@ant-design/icons';
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
 | 
			
		||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
 | 
			
		||||
import { useBlockRequestContext } from '../../block-provider';
 | 
			
		||||
import { useSchemaTemplateManager } from '../../schema-templates';
 | 
			
		||||
import { createDetailsBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
 | 
			
		||||
import { useRecordCollectionDataSourceItems } from '../utils';
 | 
			
		||||
import { useCollectionManager_deprecated } from '../../collection-manager';
 | 
			
		||||
import { createDetailsUISchema } from '../../modules/blocks/data-blocks/details-single/createDetailsUISchema';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
@ -22,8 +22,6 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
 | 
			
		||||
  const collection = getCollection(collectionName);
 | 
			
		||||
 | 
			
		||||
  const resource = `${field.collectionName}.${field.name}`;
 | 
			
		||||
  const { block } = useBlockRequestContext();
 | 
			
		||||
  const actionInitializers = block !== 'TableField' ? 'details:configureActions' : null;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <SchemaInitializerItem
 | 
			
		||||
@ -33,17 +31,10 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
 | 
			
		||||
        if (item.template) {
 | 
			
		||||
          const s = await getTemplateSchemaByMode(item);
 | 
			
		||||
          if (item.template.componentName === 'ReadPrettyFormItem') {
 | 
			
		||||
            const blockSchema = createDetailsBlockSchema({
 | 
			
		||||
              actionInitializers,
 | 
			
		||||
              collection: collectionName,
 | 
			
		||||
            const blockSchema = createDetailsUISchema({
 | 
			
		||||
              dataSource: collection.dataSource,
 | 
			
		||||
              resource,
 | 
			
		||||
              association: resource,
 | 
			
		||||
              action: 'get',
 | 
			
		||||
              useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
              useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
              template: s,
 | 
			
		||||
              settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
              templateSchema: s,
 | 
			
		||||
            });
 | 
			
		||||
            if (item.mode === 'reference') {
 | 
			
		||||
              blockSchema['x-template-key'] = item.template.key;
 | 
			
		||||
@ -54,16 +45,9 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          insert(
 | 
			
		||||
            createDetailsBlockSchema({
 | 
			
		||||
              actionInitializers,
 | 
			
		||||
              collection: collectionName,
 | 
			
		||||
              resource,
 | 
			
		||||
            createDetailsUISchema({
 | 
			
		||||
              association: resource,
 | 
			
		||||
              dataSource: collection.dataSource,
 | 
			
		||||
              action: 'get',
 | 
			
		||||
              useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
              useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
              settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
@ -76,8 +60,6 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
 | 
			
		||||
export function useCreateAssociationDetailsWithoutPagination() {
 | 
			
		||||
  const { insert } = useSchemaInitializer();
 | 
			
		||||
  const { getCollection } = useCollectionManager_deprecated();
 | 
			
		||||
  const { block } = useBlockRequestContext();
 | 
			
		||||
  const actionInitializers = block !== 'TableField' ? 'details:configureActions' : null;
 | 
			
		||||
 | 
			
		||||
  const createAssociationDetailsWithoutPagination = useCallback(
 | 
			
		||||
    ({ item }) => {
 | 
			
		||||
@ -85,19 +67,13 @@ export function useCreateAssociationDetailsWithoutPagination() {
 | 
			
		||||
      const collection = getCollection(field.target);
 | 
			
		||||
 | 
			
		||||
      insert(
 | 
			
		||||
        createDetailsBlockSchema({
 | 
			
		||||
          actionInitializers,
 | 
			
		||||
          collection: field.target,
 | 
			
		||||
        createDetailsUISchema({
 | 
			
		||||
          dataSource: collection.dataSource,
 | 
			
		||||
          association: `${field.collectionName}.${field.name}`,
 | 
			
		||||
          action: 'get',
 | 
			
		||||
          useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
          useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
          settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    [actionInitializers, getCollection, insert],
 | 
			
		||||
    [getCollection, insert],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const templateWrap = useCallback(
 | 
			
		||||
@ -106,16 +82,10 @@ export function useCreateAssociationDetailsWithoutPagination() {
 | 
			
		||||
      const collection = getCollection(field.target);
 | 
			
		||||
 | 
			
		||||
      if (item.template.componentName === 'ReadPrettyFormItem') {
 | 
			
		||||
        const blockSchema = createDetailsBlockSchema({
 | 
			
		||||
          actionInitializers,
 | 
			
		||||
          collection: field.target,
 | 
			
		||||
        const blockSchema = createDetailsUISchema({
 | 
			
		||||
          dataSource: collection.dataSource,
 | 
			
		||||
          association: `${field.collectionName}.${field.name}`,
 | 
			
		||||
          action: 'get',
 | 
			
		||||
          useSourceId: '{{ useSourceIdFromParentRecord }}',
 | 
			
		||||
          useParams: '{{ useParamsFromRecord }}',
 | 
			
		||||
          template: templateSchema,
 | 
			
		||||
          settings: 'blockSettings:singleDataDetails',
 | 
			
		||||
          templateSchema: templateSchema,
 | 
			
		||||
        });
 | 
			
		||||
        if (item.mode === 'reference') {
 | 
			
		||||
          blockSchema['x-template-key'] = item.template.key;
 | 
			
		||||
@ -125,7 +95,7 @@ export function useCreateAssociationDetailsWithoutPagination() {
 | 
			
		||||
        return templateSchema;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    [actionInitializers, getCollection],
 | 
			
		||||
    [getCollection],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return { createAssociationDetailsWithoutPagination, templateWrap };
 | 
			
		||||
 | 
			
		||||
@ -893,7 +893,18 @@ export const useCollectionDataSourceItems = ({
 | 
			
		||||
  return res;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const createDetailsBlockSchema = (options) => {
 | 
			
		||||
export const createDetailsBlockSchema = (options: {
 | 
			
		||||
  collection: string;
 | 
			
		||||
  dataSource: string;
 | 
			
		||||
  rowKey?: string;
 | 
			
		||||
  formItemInitializers?: string;
 | 
			
		||||
  actionInitializers?: string;
 | 
			
		||||
  association?: string;
 | 
			
		||||
  template?: any;
 | 
			
		||||
  settings?: string;
 | 
			
		||||
  action?: string;
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
}) => {
 | 
			
		||||
  const {
 | 
			
		||||
    formItemInitializers = 'details:configureFields',
 | 
			
		||||
    actionInitializers = 'detailsWithPaging:configureActions',
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,14 @@ import { customizeUpdateRecordActionSettings } from '../modules/actions/update-r
 | 
			
		||||
import { customizePopupActionSettings } from '../modules/actions/view-edit-popup/customizePopupActionSettings';
 | 
			
		||||
import { editActionSettings } from '../modules/actions/view-edit-popup/editActionSettings';
 | 
			
		||||
import { viewActionSettings } from '../modules/actions/view-edit-popup/viewActionSettings';
 | 
			
		||||
import { multiDataDetailsBlockSettings } from '../modules/blocks/data-blocks/details-multi/multiDataDetailsBlockSettings';
 | 
			
		||||
import { singleDataDetailsBlockSettings } from '../modules/blocks/data-blocks/details-single/singleDataDetailsBlockSettings';
 | 
			
		||||
import {
 | 
			
		||||
  detailsWithPaginationSettings,
 | 
			
		||||
  multiDataDetailsBlockSettings,
 | 
			
		||||
} from '../modules/blocks/data-blocks/details-multi/detailsWithPaginationSettings';
 | 
			
		||||
import {
 | 
			
		||||
  detailsBlockSettings,
 | 
			
		||||
  singleDataDetailsBlockSettings,
 | 
			
		||||
} from '../modules/blocks/data-blocks/details-single/detailsBlockSettings';
 | 
			
		||||
import {
 | 
			
		||||
  createFormBlockSettings,
 | 
			
		||||
  creationFormBlockSettings,
 | 
			
		||||
@ -56,7 +62,9 @@ export class SchemaSettingsPlugin extends Plugin {
 | 
			
		||||
    this.schemaSettingsManager.add(filterFormBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(filterFormItemFieldSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(multiDataDetailsBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(detailsWithPaginationSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(singleDataDetailsBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(detailsBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(tableSelectorBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(listBlockSettings);
 | 
			
		||||
    this.schemaSettingsManager.add(gridCardBlockSettings);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user