Merge pull request '子表单(弹窗)迁移到框架内' (#399) from subform_drawer_table into @hera/dev
Reviewed-on: daoyoucloud/tachycode#399 Reviewed-by: wangjiahui <wwwjh0710@163.com>
This commit is contained in:
		
						commit
						77585e6280
					
				@ -267,6 +267,7 @@
 | 
			
		||||
  "Sub-table": "Sub-table",
 | 
			
		||||
  "Sub-details": "Sub-details",
 | 
			
		||||
  "Sub-form(Popover)": "Sub-form(Popover)",
 | 
			
		||||
  "Sub-form(Drawer)": "Sub-form(Drawer)",
 | 
			
		||||
  "System info": "System info",
 | 
			
		||||
  "Created at": "Created at",
 | 
			
		||||
  "Last updated at": "Last updated at",
 | 
			
		||||
 | 
			
		||||
@ -331,6 +331,7 @@
 | 
			
		||||
  "Subtable": "子表格",
 | 
			
		||||
  "Sub-form": "子表单",
 | 
			
		||||
  "Sub-form(Popover)": "子表单(弹窗)",
 | 
			
		||||
  "Sub-form(Drawer)": "子表单(抽屉)",
 | 
			
		||||
  "Sub-details": "子详情",
 | 
			
		||||
  "Record picker": "数据选择器",
 | 
			
		||||
  "Toggles the subfield mode": "切换子字段模式",
 | 
			
		||||
 | 
			
		||||
@ -4,12 +4,12 @@ import { RecursionField, connect, mapProps, observer, useField, useFieldSchema,
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
import { Space, message } from 'antd';
 | 
			
		||||
import { isFunction } from 'mathjs';
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import React, { useEffect, useMemo, useState } from 'react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { RecordProvider, useAPIClient, useCollectionRecordData } from '../../../';
 | 
			
		||||
import { RecordProvider, useAPIClient, useApp, useCollectionRecordData } from '../../../';
 | 
			
		||||
import { isVariable } from '../../../variables/utils/isVariable';
 | 
			
		||||
import { getInnermostKeyAndValue } from '../../common/utils/uitls';
 | 
			
		||||
import { RemoteSelect, RemoteSelectProps } from '../remote-select';
 | 
			
		||||
import { RemoteSelectProps } from '../remote-select';
 | 
			
		||||
import useServiceOptions, { useAssociationFieldContext } from './hooks';
 | 
			
		||||
 | 
			
		||||
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
 | 
			
		||||
@ -60,6 +60,9 @@ const InternalAssociationSelect = observer(
 | 
			
		||||
    const resource = api.resource(collectionField.target);
 | 
			
		||||
    const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
 | 
			
		||||
    const recordData = useCollectionRecordData();
 | 
			
		||||
    const app = useApp();
 | 
			
		||||
    const RemoteSelect = useMemo(() => app.getComponent('RemoteSelect'), [app]);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
      const initValue = isVariable(field.value) ? undefined : field.value;
 | 
			
		||||
      const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
 | 
			
		||||
@ -165,6 +168,8 @@ export const AssociationSelect = InternalAssociationSelect as unknown as Associa
 | 
			
		||||
export const AssociationSelectReadPretty = connect(
 | 
			
		||||
  (props: any) => {
 | 
			
		||||
    const service = useServiceOptions(props);
 | 
			
		||||
    const app = useApp();
 | 
			
		||||
    const RemoteSelect = useMemo(() => app.getComponent('RemoteSelect'), [app]) as any;
 | 
			
		||||
    if (props.fieldNames) {
 | 
			
		||||
      return <RemoteSelect.ReadPretty {...props} service={service}></RemoteSelect.ReadPretty>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,8 @@ import { InternaPopoverNester } from './InternalPopoverNester';
 | 
			
		||||
import { InternalSubTable } from './InternalSubTable';
 | 
			
		||||
import { CreateRecordAction } from './components/CreateRecordAction';
 | 
			
		||||
import { useAssociationFieldContext } from './hooks';
 | 
			
		||||
import { InternalCascader } from './InternalCascader';
 | 
			
		||||
import { InternaDrawerSubTable } from './InternalDrawerSubTable';
 | 
			
		||||
 | 
			
		||||
const EditableAssociationField = observer(
 | 
			
		||||
  (props: any) => {
 | 
			
		||||
@ -57,6 +59,8 @@ const EditableAssociationField = observer(
 | 
			
		||||
        {currentMode === 'SubTable' && <InternalSubTable {...props} />}
 | 
			
		||||
        {currentMode === 'FileManager' && <InternalFileManager {...props} />}
 | 
			
		||||
        {currentMode === 'CascadeSelect' && <InternalCascadeSelect {...props} />}
 | 
			
		||||
        {currentMode === 'DrawerSubTable' && <InternaDrawerSubTable {...props} />}
 | 
			
		||||
        {currentMode === 'Cascader' && <InternalCascader {...props} />}
 | 
			
		||||
      </SchemaComponentOptions>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,12 @@ import { observer } from '@formily/react';
 | 
			
		||||
import React, { useContext, useRef, useState } from 'react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { InternalSubTable } from './InternalSubTable';
 | 
			
		||||
import { ActionContext, ActionContextProvider, __UNSAFE__, useGetAriaLabelOfPopover } from '@nocobase/client';
 | 
			
		||||
import { Button, Drawer } from 'antd';
 | 
			
		||||
const { useAssociationFieldContext, useSetAriaLabelForPopover, ReadPrettyInternalViewer } = __UNSAFE__;
 | 
			
		||||
import { useAssociationFieldContext } from './hooks';
 | 
			
		||||
import { ActionContext, ActionContextProvider } from '../action/context';
 | 
			
		||||
import { useGetAriaLabelOfPopover } from '../action';
 | 
			
		||||
import { ReadPrettyInternalViewer } from './InternalViewer';
 | 
			
		||||
import { useSetAriaLabelForPopover } from '../action/hooks/useSetAriaLabelForPopover';
 | 
			
		||||
 | 
			
		||||
export const InternaDrawerSubTable = observer(
 | 
			
		||||
  (props) => {
 | 
			
		||||
@ -55,6 +55,7 @@ export const useFieldModeOptions = (props?) => {
 | 
			
		||||
            { label: t('Cascade Select'), value: 'CascadeSelect' },
 | 
			
		||||
            !isTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
			
		||||
            { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
			
		||||
            { label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
 | 
			
		||||
            { label: t('Cascader'), value: 'Cascader' },
 | 
			
		||||
          ];
 | 
			
		||||
    }
 | 
			
		||||
@ -72,6 +73,7 @@ export const useFieldModeOptions = (props?) => {
 | 
			
		||||
              { label: t('Record picker'), value: 'Picker' },
 | 
			
		||||
              !isTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
			
		||||
              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
			
		||||
              { label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
 | 
			
		||||
              !isTableField && { label: t('Sub-table'), value: 'SubTable' },
 | 
			
		||||
            ];
 | 
			
		||||
      case 'm2m':
 | 
			
		||||
@ -88,6 +90,7 @@ export const useFieldModeOptions = (props?) => {
 | 
			
		||||
              !isTableField && { label: t('Sub-table'), value: 'SubTable' },
 | 
			
		||||
              !isTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
			
		||||
              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
			
		||||
              { label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
 | 
			
		||||
            ];
 | 
			
		||||
      case 'm2o':
 | 
			
		||||
      case 'linkTo':
 | 
			
		||||
@ -102,6 +105,7 @@ export const useFieldModeOptions = (props?) => {
 | 
			
		||||
              { label: t('Record picker'), value: 'Picker' },
 | 
			
		||||
              !isTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
			
		||||
              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
			
		||||
              { label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
 | 
			
		||||
              { label: t('Cascader'), value: 'Cascader' },
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
@ -117,6 +121,7 @@ export const useFieldModeOptions = (props?) => {
 | 
			
		||||
              { label: t('Record picker'), value: 'Picker' },
 | 
			
		||||
              !isTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
			
		||||
              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
			
		||||
              { label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
 | 
			
		||||
            ];
 | 
			
		||||
    }
 | 
			
		||||
  }, [t, collectionField?.interface, label]);
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,6 @@ import { isValid } from '@formily/shared';
 | 
			
		||||
import { useCreateActionProps } from './hooks/useCreateActionProps';
 | 
			
		||||
import { PageLayout } from './pages/PageLayout';
 | 
			
		||||
import { useOutboundActionProps } from './hooks/useOutboundActionProps';
 | 
			
		||||
import { ExtendedAssociationField } from './schema-components/association-field/Editable';
 | 
			
		||||
import { AssociatedField } from './components/AssociatedField';
 | 
			
		||||
import { DatePicker } from './schema-components/date-picker';
 | 
			
		||||
import { Page } from './schema-components/page';
 | 
			
		||||
@ -162,7 +161,6 @@ export class PluginCoreClient extends Plugin {
 | 
			
		||||
      DatePicker,
 | 
			
		||||
      RemoteSelect,
 | 
			
		||||
      SignatureInput,
 | 
			
		||||
      AssociationField: ExtendedAssociationField,
 | 
			
		||||
      OutboundButton,
 | 
			
		||||
      OutboundLinkActionInitializer,
 | 
			
		||||
      PDFViewerBlockInitializer,
 | 
			
		||||
 | 
			
		||||
@ -1,182 +0,0 @@
 | 
			
		||||
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
 | 
			
		||||
import { onFieldChange, FormPath } from '@formily/core';
 | 
			
		||||
import { RecursionField, connect, mapProps, observer, useField, useFieldSchema, useForm } from '@formily/react';
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
import { Space, message } from 'antd';
 | 
			
		||||
import { isFunction } from 'mathjs2';
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { RecordProvider, RemoteSelectProps, useAPIClient } from '@nocobase/client';
 | 
			
		||||
import { __UNSAFE__ } from '@nocobase/client';
 | 
			
		||||
import { RemoteSelect } from '../remote-select';
 | 
			
		||||
 | 
			
		||||
const { getInnermostKeyAndValue, useServiceOptions, useAssociationFieldContext, isVariable } = __UNSAFE__;
 | 
			
		||||
 | 
			
		||||
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
 | 
			
		||||
  action?: string;
 | 
			
		||||
  multiple?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const filterAnalyses = (filters): any[] => {
 | 
			
		||||
  if (!filters) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  const type = Object.keys(filters)[0] || '$and';
 | 
			
		||||
  const conditions = filters[type];
 | 
			
		||||
  const results = [];
 | 
			
		||||
  conditions?.map((c) => {
 | 
			
		||||
    const jsonlogic = getInnermostKeyAndValue(c);
 | 
			
		||||
    const operator = jsonlogic?.key;
 | 
			
		||||
 | 
			
		||||
    if (!operator) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    const regex = /\{\{\$(?:[a-zA-Z_]\w*)\.([a-zA-Z_]\w*)(?:\.id)?\}\}/;
 | 
			
		||||
    const fieldName = jsonlogic?.value?.match?.(regex)?.[1];
 | 
			
		||||
    if (fieldName) {
 | 
			
		||||
      results.push(fieldName);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  return results;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
 | 
			
		||||
  const { objectValue = true } = props;
 | 
			
		||||
  const field: any = useField();
 | 
			
		||||
  const fieldSchema = useFieldSchema();
 | 
			
		||||
  const service = useServiceOptions(props);
 | 
			
		||||
  const { options: collectionField } = useAssociationFieldContext();
 | 
			
		||||
  const initValue = isVariable(props.value) ? undefined : props.value;
 | 
			
		||||
  const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
 | 
			
		||||
  // 因为通过 Schema 的形式书写的组件,在值变更的时候 `value` 的值没有改变,所以需要维护一个 `innerValue` 来变更值
 | 
			
		||||
  const [innerValue, setInnerValue] = useState(value);
 | 
			
		||||
  const addMode = fieldSchema['x-component-props']?.addMode;
 | 
			
		||||
  const isAllowAddNew = fieldSchema['x-add-new'];
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
  const { multiple } = props;
 | 
			
		||||
  const form = useForm();
 | 
			
		||||
  const api = useAPIClient();
 | 
			
		||||
  const resource = api.resource(collectionField.target);
 | 
			
		||||
  const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const initValue = isVariable(field.value) ? undefined : field.value;
 | 
			
		||||
    const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
 | 
			
		||||
    setInnerValue(value);
 | 
			
		||||
  }, [field.value]);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const id = uid();
 | 
			
		||||
    form.addEffects(id, () => {
 | 
			
		||||
      if (linkageFields?.length > 0) {
 | 
			
		||||
        //支持深层次子表单
 | 
			
		||||
        onFieldChange('*', (fieldPath: any) => {
 | 
			
		||||
          if (linkageFields.includes(fieldPath.props.name) && field.value) {
 | 
			
		||||
            props.onChange(field.initialValue);
 | 
			
		||||
            setInnerValue(field.initialValue);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return () => {
 | 
			
		||||
      form.removeEffects(id);
 | 
			
		||||
    };
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const handleCreateAction = async (props) => {
 | 
			
		||||
    const { search: value, callBack } = props;
 | 
			
		||||
    const {
 | 
			
		||||
      data: { data },
 | 
			
		||||
    } = await resource.create({
 | 
			
		||||
      values: {
 | 
			
		||||
        [field?.componentProps?.fieldNames?.label || 'id']: value,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
    if (data) {
 | 
			
		||||
      if (['m2m', 'o2m'].includes(collectionField?.interface) && multiple !== false) {
 | 
			
		||||
        const values = form.getValuesIn(field.path) || [];
 | 
			
		||||
        values.push(data);
 | 
			
		||||
        form.setValuesIn(field.path, values);
 | 
			
		||||
        field.onInput(values);
 | 
			
		||||
      } else {
 | 
			
		||||
        form.setValuesIn(field.path, data);
 | 
			
		||||
        field.onInput(data);
 | 
			
		||||
      }
 | 
			
		||||
      isFunction(callBack) && callBack?.();
 | 
			
		||||
      message.success(t('Saved successfully'));
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  const QuickAddContent = (props) => {
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
        onClick={() => handleCreateAction(props)}
 | 
			
		||||
        style={{ cursor: 'pointer', padding: '5px 12px', color: '#0d0c0c' }}
 | 
			
		||||
      >
 | 
			
		||||
        <PlusOutlined />
 | 
			
		||||
        <span style={{ paddingLeft: 5 }}>{t('Add') + ` “${props.search}” `}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
  return (
 | 
			
		||||
    <div key={fieldSchema.name}>
 | 
			
		||||
      <Space.Compact style={{ display: 'flex', lineHeight: '32px' }}>
 | 
			
		||||
        <RemoteSelect
 | 
			
		||||
          style={{ width: '100%' }}
 | 
			
		||||
          {...props}
 | 
			
		||||
          size={'middle'}
 | 
			
		||||
          objectValue={objectValue}
 | 
			
		||||
          value={value || innerValue}
 | 
			
		||||
          service={service}
 | 
			
		||||
          onChange={(value) => {
 | 
			
		||||
            const val = value?.length !== 0 ? value : null;
 | 
			
		||||
            props.onChange?.(val);
 | 
			
		||||
          }}
 | 
			
		||||
          CustomDropdownRender={addMode === 'quickAdd' && QuickAddContent}
 | 
			
		||||
        ></RemoteSelect>
 | 
			
		||||
 | 
			
		||||
        {(addMode === 'modalAdd' || isAllowAddNew) && (
 | 
			
		||||
          <RecordProvider record={null}>
 | 
			
		||||
            <RecursionField
 | 
			
		||||
              onlyRenderProperties
 | 
			
		||||
              basePath={field.address}
 | 
			
		||||
              schema={fieldSchema}
 | 
			
		||||
              filterProperties={(s) => {
 | 
			
		||||
                return s['x-component'] === 'Action';
 | 
			
		||||
              }}
 | 
			
		||||
            />
 | 
			
		||||
          </RecordProvider>
 | 
			
		||||
        )}
 | 
			
		||||
      </Space.Compact>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interface AssociationSelectInterface {
 | 
			
		||||
  (props: any): React.ReactElement;
 | 
			
		||||
  Designer: React.FC;
 | 
			
		||||
  FilterDesigner: React.FC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const AssociationSelect = InternalAssociationSelect as unknown as AssociationSelectInterface;
 | 
			
		||||
 | 
			
		||||
export const AssociationSelectReadPretty = connect(
 | 
			
		||||
  (props: any) => {
 | 
			
		||||
    const service = useServiceOptions(props);
 | 
			
		||||
    if (props.fieldNames) {
 | 
			
		||||
      return <RemoteSelect.ReadPretty {...props} service={service}></RemoteSelect.ReadPretty>;
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  },
 | 
			
		||||
  mapProps(
 | 
			
		||||
    {
 | 
			
		||||
      dataSource: 'options',
 | 
			
		||||
      loading: true,
 | 
			
		||||
    },
 | 
			
		||||
    (props, field) => {
 | 
			
		||||
      return {
 | 
			
		||||
        ...props,
 | 
			
		||||
        fieldNames: props.fieldNames && { ...props.fieldNames, ...field.componentProps.fieldNames },
 | 
			
		||||
        suffixIcon: field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffixIcon,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  ),
 | 
			
		||||
);
 | 
			
		||||
@ -1,95 +0,0 @@
 | 
			
		||||
import { Field } from '@formily/core';
 | 
			
		||||
import { connect, mapReadPretty, observer, useField, useForm } from '@formily/react';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import {
 | 
			
		||||
  SchemaComponentOptions,
 | 
			
		||||
  useCollection_deprecated,
 | 
			
		||||
  useAssociationCreateActionProps as useCAP,
 | 
			
		||||
  Action,
 | 
			
		||||
  __UNSAFE__,
 | 
			
		||||
} from '@nocobase/client';
 | 
			
		||||
import { InternaDrawerSubTable } from './InternalDrawerSubTable';
 | 
			
		||||
import { AssociationSelect } from './AssociationSelect';
 | 
			
		||||
const {
 | 
			
		||||
  CreateRecordAction,
 | 
			
		||||
  useAssociationFieldContext,
 | 
			
		||||
  InternalPicker,
 | 
			
		||||
  InternalNester,
 | 
			
		||||
  AssociationFieldProvider,
 | 
			
		||||
  InternaPopoverNester,
 | 
			
		||||
  InternalSubTable,
 | 
			
		||||
  InternalCascader,
 | 
			
		||||
  InternalFileManager,
 | 
			
		||||
  InternalCascadeSelect,
 | 
			
		||||
  SubTable,
 | 
			
		||||
  ReadPretty,
 | 
			
		||||
  Nester,
 | 
			
		||||
} = __UNSAFE__;
 | 
			
		||||
 | 
			
		||||
const EditableAssociationField = observer(
 | 
			
		||||
  (props: any) => {
 | 
			
		||||
    const { multiple } = props;
 | 
			
		||||
    const field: Field = useField();
 | 
			
		||||
    const form = useForm();
 | 
			
		||||
    const { options: collectionField, currentMode } = useAssociationFieldContext();
 | 
			
		||||
 | 
			
		||||
    const useCreateActionProps = () => {
 | 
			
		||||
      const { onClick } = useCAP();
 | 
			
		||||
      const actionField: any = useField();
 | 
			
		||||
      const { getPrimaryKey } = useCollection_deprecated();
 | 
			
		||||
      const primaryKey = getPrimaryKey();
 | 
			
		||||
      return {
 | 
			
		||||
        async onClick() {
 | 
			
		||||
          await onClick();
 | 
			
		||||
          const { data } = actionField.data?.data?.data || {};
 | 
			
		||||
          if (data) {
 | 
			
		||||
            if (['m2m', 'o2m'].includes(collectionField?.interface) && multiple !== false) {
 | 
			
		||||
              const values = form.getValuesIn(field.path) || [];
 | 
			
		||||
              if (!values.find((v) => v[primaryKey] === data[primaryKey])) {
 | 
			
		||||
                values.push(data);
 | 
			
		||||
                form.setValuesIn(field.path, values);
 | 
			
		||||
                field.onInput(values);
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              form.setValuesIn(field.path, data);
 | 
			
		||||
              field.onInput(data);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
    return (
 | 
			
		||||
      <SchemaComponentOptions scope={{ useCreateActionProps }} components={{ CreateRecordAction }}>
 | 
			
		||||
        {currentMode === 'Picker' && <InternalPicker {...props} />}
 | 
			
		||||
        {currentMode === 'Nester' && <InternalNester {...props} />}
 | 
			
		||||
        {currentMode === 'PopoverNester' && <InternaPopoverNester {...props} />}
 | 
			
		||||
        {currentMode === 'Select' && <AssociationSelect {...props} />}
 | 
			
		||||
        {currentMode === 'SubTable' && <InternalSubTable {...props} />}
 | 
			
		||||
        {currentMode === 'FileManager' && <InternalFileManager {...props} />}
 | 
			
		||||
        {currentMode === 'CascadeSelect' && <InternalCascadeSelect {...props} />}
 | 
			
		||||
        {currentMode === 'DrawerSubTable' && <InternaDrawerSubTable {...props} />}
 | 
			
		||||
        {currentMode === 'Cascader' && <InternalCascader {...props} />}
 | 
			
		||||
      </SchemaComponentOptions>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  { displayName: 'EditableAssociationField' },
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const ExtendedEditable = observer(
 | 
			
		||||
  (props) => {
 | 
			
		||||
    return (
 | 
			
		||||
      <AssociationFieldProvider>
 | 
			
		||||
        <EditableAssociationField {...props} />
 | 
			
		||||
      </AssociationFieldProvider>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  { displayName: 'ExtendedEditable' },
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const ExtendedAssociationField: any = connect(ExtendedEditable, mapReadPretty(ReadPretty));
 | 
			
		||||
ExtendedAssociationField.SubTable = SubTable;
 | 
			
		||||
ExtendedAssociationField.Nester = Nester;
 | 
			
		||||
ExtendedAssociationField.AddNewer = Action.Container;
 | 
			
		||||
ExtendedAssociationField.Selector = Action.Container;
 | 
			
		||||
ExtendedAssociationField.Viewer = Action.Container;
 | 
			
		||||
ExtendedAssociationField.InternalSelect = InternalPicker;
 | 
			
		||||
@ -1,69 +0,0 @@
 | 
			
		||||
import { css, cx } from '@emotion/css';
 | 
			
		||||
import { FormLayout } from '@formily/antd-v5';
 | 
			
		||||
import { RecursionField, useField, useFieldSchema, observer } from '@formily/react';
 | 
			
		||||
import React, { useEffect } from 'react';
 | 
			
		||||
import { useInsertSchema } from '../../components/AssociatedField';
 | 
			
		||||
import {
 | 
			
		||||
  ACLCollectionProvider,
 | 
			
		||||
  CollectionProvider_deprecated,
 | 
			
		||||
  __UNSAFE__,
 | 
			
		||||
  useACLActionParamsContext,
 | 
			
		||||
} from '@nocobase/client';
 | 
			
		||||
const { useAssociationFieldContext, schema } = __UNSAFE__;
 | 
			
		||||
 | 
			
		||||
export const InternalSubTable = observer(
 | 
			
		||||
  () => {
 | 
			
		||||
    const field = useField();
 | 
			
		||||
    const fieldSchema = useFieldSchema();
 | 
			
		||||
    const insertNester = useInsertSchema('SubTable');
 | 
			
		||||
    const { options: collectionField } = useAssociationFieldContext();
 | 
			
		||||
    const showTitle = fieldSchema['x-decorator-props']?.showTitle ?? true;
 | 
			
		||||
    const { actionName } = useACLActionParamsContext();
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
      insertNester(schema.SubTable);
 | 
			
		||||
    }, []);
 | 
			
		||||
    return (
 | 
			
		||||
      <CollectionProvider_deprecated name={collectionField.target}>
 | 
			
		||||
        <ACLCollectionProvider actionPath={`${collectionField.target}:${actionName}`}>
 | 
			
		||||
          <FormLayout layout={'vertical'}>
 | 
			
		||||
            <div
 | 
			
		||||
              className={cx(
 | 
			
		||||
                css`
 | 
			
		||||
                  & .ant-formily-item-layout-vertical {
 | 
			
		||||
                    margin-bottom: 10px;
 | 
			
		||||
                  }
 | 
			
		||||
                  .ant-card-body {
 | 
			
		||||
                    padding: 15px 20px 5px;
 | 
			
		||||
                  }
 | 
			
		||||
                  .ant-divider-horizontal {
 | 
			
		||||
                    margin: 10px 0;
 | 
			
		||||
                  }
 | 
			
		||||
                `,
 | 
			
		||||
                {
 | 
			
		||||
                  [css`
 | 
			
		||||
                    .ant-card-body {
 | 
			
		||||
                      padding: 0px 20px 20px 0px;
 | 
			
		||||
                    }
 | 
			
		||||
                    > .ant-card-bordered {
 | 
			
		||||
                      border: none;
 | 
			
		||||
                    }
 | 
			
		||||
                  `]: showTitle === false,
 | 
			
		||||
                },
 | 
			
		||||
              )}
 | 
			
		||||
            >
 | 
			
		||||
              <RecursionField
 | 
			
		||||
                onlyRenderProperties
 | 
			
		||||
                basePath={field.address}
 | 
			
		||||
                schema={fieldSchema}
 | 
			
		||||
                filterProperties={(s) => {
 | 
			
		||||
                  return s['x-component'] === 'AssociationField.SubTable';
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
          </FormLayout>
 | 
			
		||||
        </ACLCollectionProvider>
 | 
			
		||||
      </CollectionProvider_deprecated>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  { displayName: 'InternalSubTable' },
 | 
			
		||||
);
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user