feat(association-field): association field support sub-form(popover) (#2373)
* refactor: association field support sub-form(popover) * refactor: code improve * refactor: code improve * refactor: sub-table support field component cinfig * refactor: sub-table support field component cinfig * refactor: sub-table support field component cinfig * refactor: code improve * refactor: code improve * refactor: useAssociationNames * refactor: locale improve * refactor: locale improve * refactor: code improve * refactor: code improve * refactor: code improve * fix: code improve * refactor: code refactor * style: style improve * Update database.ts * refactor: code imporve * refactor: code imporve * style: style improve * style: style improve * refactor: code imporve * style: style improve * refactor: code imporve --------- Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
		
							parent
							
								
									d84c52618d
								
							
						
					
					
						commit
						d333ad201a
					
				@ -151,12 +151,8 @@ export const useCreateActionProps = () => {
 | 
				
			|||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async onClick() {
 | 
					    async onClick() {
 | 
				
			||||||
      const fieldNames = fields.map((field) => field.name);
 | 
					      const fieldNames = fields.map((field) => field.name);
 | 
				
			||||||
      const {
 | 
					      const { assignedValues: originalAssignedValues = {}, onSuccess, overwriteValues, skipValidator } =
 | 
				
			||||||
        assignedValues: originalAssignedValues = {},
 | 
					        actionSchema?.['x-action-settings'] ?? {};
 | 
				
			||||||
        onSuccess,
 | 
					 | 
				
			||||||
        overwriteValues,
 | 
					 | 
				
			||||||
        skipValidator,
 | 
					 | 
				
			||||||
      } = actionSchema?.['x-action-settings'] ?? {};
 | 
					 | 
				
			||||||
      const addChild = fieldSchema?.['x-component-props']?.addChild;
 | 
					      const addChild = fieldSchema?.['x-component-props']?.addChild;
 | 
				
			||||||
      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
					      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
				
			||||||
      if (!skipValidator) {
 | 
					      if (!skipValidator) {
 | 
				
			||||||
@ -226,12 +222,8 @@ export const useAssociationCreateActionProps = () => {
 | 
				
			|||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async onClick() {
 | 
					    async onClick() {
 | 
				
			||||||
      const fieldNames = fields.map((field) => field.name);
 | 
					      const fieldNames = fields.map((field) => field.name);
 | 
				
			||||||
      const {
 | 
					      const { assignedValues: originalAssignedValues = {}, onSuccess, overwriteValues, skipValidator } =
 | 
				
			||||||
        assignedValues: originalAssignedValues = {},
 | 
					        actionSchema?.['x-action-settings'] ?? {};
 | 
				
			||||||
        onSuccess,
 | 
					 | 
				
			||||||
        overwriteValues,
 | 
					 | 
				
			||||||
        skipValidator,
 | 
					 | 
				
			||||||
      } = actionSchema?.['x-action-settings'] ?? {};
 | 
					 | 
				
			||||||
      const addChild = fieldSchema?.['x-component-props']?.addChild;
 | 
					      const addChild = fieldSchema?.['x-component-props']?.addChild;
 | 
				
			||||||
      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
					      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
				
			||||||
      if (!skipValidator) {
 | 
					      if (!skipValidator) {
 | 
				
			||||||
@ -415,11 +407,8 @@ export const useCustomizeUpdateActionProps = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async onClick() {
 | 
					    async onClick() {
 | 
				
			||||||
      const {
 | 
					      const { assignedValues: originalAssignedValues = {}, onSuccess, skipValidator } =
 | 
				
			||||||
        assignedValues: originalAssignedValues = {},
 | 
					        actionSchema?.['x-action-settings'] ?? {};
 | 
				
			||||||
        onSuccess,
 | 
					 | 
				
			||||||
        skipValidator,
 | 
					 | 
				
			||||||
      } = actionSchema?.['x-action-settings'] ?? {};
 | 
					 | 
				
			||||||
      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
					      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
				
			||||||
      if (skipValidator === false) {
 | 
					      if (skipValidator === false) {
 | 
				
			||||||
        await form.submit();
 | 
					        await form.submit();
 | 
				
			||||||
@ -473,11 +462,8 @@ export const useCustomizeBulkUpdateActionProps = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async onClick() {
 | 
					    async onClick() {
 | 
				
			||||||
      const {
 | 
					      const { assignedValues: originalAssignedValues = {}, onSuccess, updateMode } =
 | 
				
			||||||
        assignedValues: originalAssignedValues = {},
 | 
					        actionSchema?.['x-action-settings'] ?? {};
 | 
				
			||||||
        onSuccess,
 | 
					 | 
				
			||||||
        updateMode,
 | 
					 | 
				
			||||||
      } = actionSchema?.['x-action-settings'] ?? {};
 | 
					 | 
				
			||||||
      actionField.data = field.data || {};
 | 
					      actionField.data = field.data || {};
 | 
				
			||||||
      actionField.data.loading = true;
 | 
					      actionField.data.loading = true;
 | 
				
			||||||
      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentUser });
 | 
					      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentUser });
 | 
				
			||||||
@ -732,12 +718,8 @@ export const useUpdateActionProps = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async onClick() {
 | 
					    async onClick() {
 | 
				
			||||||
      const {
 | 
					      const { assignedValues: originalAssignedValues = {}, onSuccess, overwriteValues, skipValidator } =
 | 
				
			||||||
        assignedValues: originalAssignedValues = {},
 | 
					        actionSchema?.['x-action-settings'] ?? {};
 | 
				
			||||||
        onSuccess,
 | 
					 | 
				
			||||||
        overwriteValues,
 | 
					 | 
				
			||||||
        skipValidator,
 | 
					 | 
				
			||||||
      } = actionSchema?.['x-action-settings'] ?? {};
 | 
					 | 
				
			||||||
      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
					      const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
 | 
				
			||||||
      if (!skipValidator) {
 | 
					      if (!skipValidator) {
 | 
				
			||||||
        await form.submit();
 | 
					        await form.submit();
 | 
				
			||||||
@ -1124,7 +1106,7 @@ export const useAssociationNames = () => {
 | 
				
			|||||||
        const fieldPath = !isAssociationField && isAssociationSubfield ? getAssociationPath(s.name) : s.name;
 | 
					        const fieldPath = !isAssociationField && isAssociationSubfield ? getAssociationPath(s.name) : s.name;
 | 
				
			||||||
        const path = prefix === '' || !prefix ? fieldPath : prefix + '.' + fieldPath;
 | 
					        const path = prefix === '' || !prefix ? fieldPath : prefix + '.' + fieldPath;
 | 
				
			||||||
        appends.add(path);
 | 
					        appends.add(path);
 | 
				
			||||||
        if (['Nester', 'SubTable'].includes(s['x-component-props']?.mode)) {
 | 
					        if (['Nester', 'SubTable', 'PopoverNester'].includes(s['x-component-props']?.mode)) {
 | 
				
			||||||
          updateAssociationValues.add(path);
 | 
					          updateAssociationValues.add(path);
 | 
				
			||||||
          const bufPrefix = prefix && prefix !== '' ? prefix + '.' + s.name : s.name;
 | 
					          const bufPrefix = prefix && prefix !== '' ? prefix + '.' + s.name : s.name;
 | 
				
			||||||
          getAssociationAppends(s, bufPrefix);
 | 
					          getAssociationAppends(s, bufPrefix);
 | 
				
			||||||
 | 
				
			|||||||
@ -251,6 +251,7 @@ export default {
 | 
				
			|||||||
  "Link to description": "Used to create collection relationships quickly and compatible with most common scenarios. Suitable for non-developer use. When present as a field, it is a drop-down selection used to select records from the target collection. Once created, it will simultaneously generate the associated fields of the current collection in the target collection.",
 | 
					  "Link to description": "Used to create collection relationships quickly and compatible with most common scenarios. Suitable for non-developer use. When present as a field, it is a drop-down selection used to select records from the target collection. Once created, it will simultaneously generate the associated fields of the current collection in the target collection.",
 | 
				
			||||||
  "Sub-table": "Sub-table",
 | 
					  "Sub-table": "Sub-table",
 | 
				
			||||||
  "Sub-details":"Sub-details",
 | 
					  "Sub-details":"Sub-details",
 | 
				
			||||||
 | 
					  "Sub-form(Popover)":"Sub-form(Popover)",
 | 
				
			||||||
  "System info": "System info",
 | 
					  "System info": "System info",
 | 
				
			||||||
  "Created at": "Created at",
 | 
					  "Created at": "Created at",
 | 
				
			||||||
  "Last updated at": "Last updated at",
 | 
					  "Last updated at": "Last updated at",
 | 
				
			||||||
 | 
				
			|||||||
@ -222,6 +222,7 @@ export default {
 | 
				
			|||||||
  "Link to": "リンク",
 | 
					  "Link to": "リンク",
 | 
				
			||||||
  "Link to description": "コレクションの関連付けを素早く作成するためにしようされ、ほとんどの一般的なシナリオに対応しています。開発者以外の方のしようにも適しています。フィールドとして存在する場合、参照元コレクションのレコードを選択するために使用されるドロップダウンです。一度作成されると、参照先コレクションに現在のコレクションの関連フィールドが同時に生成されます。",
 | 
					  "Link to description": "コレクションの関連付けを素早く作成するためにしようされ、ほとんどの一般的なシナリオに対応しています。開発者以外の方のしようにも適しています。フィールドとして存在する場合、参照元コレクションのレコードを選択するために使用されるドロップダウンです。一度作成されると、参照先コレクションに現在のコレクションの関連フィールドが同時に生成されます。",
 | 
				
			||||||
  "Sub-table": "サブテーブル",
 | 
					  "Sub-table": "サブテーブル",
 | 
				
			||||||
 | 
					  "Sub-form(Popover)":"サブフォーム(ポップアップ窓)",
 | 
				
			||||||
  "System info": "システム情報",
 | 
					  "System info": "システム情報",
 | 
				
			||||||
  "Created at": "作成日",
 | 
					  "Created at": "作成日",
 | 
				
			||||||
  "Last updated at": "最終更新日",
 | 
					  "Last updated at": "最終更新日",
 | 
				
			||||||
 | 
				
			|||||||
@ -317,6 +317,7 @@ export default {
 | 
				
			|||||||
  "Select file": "选择文件",
 | 
					  "Select file": "选择文件",
 | 
				
			||||||
  "Subtable": "子表格",
 | 
					  "Subtable": "子表格",
 | 
				
			||||||
  "Sub-form": "子表单",
 | 
					  "Sub-form": "子表单",
 | 
				
			||||||
 | 
					  "Sub-form(Popover)":"子表单(弹窗)",
 | 
				
			||||||
  "Sub-details":"子详情",
 | 
					  "Sub-details":"子详情",
 | 
				
			||||||
  "Record picker": "数据选择器",
 | 
					  "Record picker": "数据选择器",
 | 
				
			||||||
  "Toggles the subfield mode": "切换子字段模式",
 | 
					  "Toggles the subfield mode": "切换子字段模式",
 | 
				
			||||||
 | 
				
			|||||||
@ -28,19 +28,6 @@ export const AssociationFieldProvider = observer(
 | 
				
			|||||||
      [fieldSchema['x-component-props']?.mode],
 | 
					      [fieldSchema['x-component-props']?.mode],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // const targetKeyValue = useMemo(() => {
 | 
					 | 
				
			||||||
    //   if (!field.value) return '';
 | 
					 | 
				
			||||||
    //   if (['belongsTo', 'hasOne'].includes(collectionField.type)) {
 | 
					 | 
				
			||||||
    //     return field.value[collectionField.targetKey] ?? '';
 | 
					 | 
				
			||||||
    //   }
 | 
					 | 
				
			||||||
    //   if (['belongsToMany', 'hasMany'].includes(collectionField.type)) {
 | 
					 | 
				
			||||||
    //     if (Array.isArray(field.value)) {
 | 
					 | 
				
			||||||
    //       return field.value.map((v) => v[collectionField.targetKey] ?? '').join(',');
 | 
					 | 
				
			||||||
    //     }
 | 
					 | 
				
			||||||
    //   }
 | 
					 | 
				
			||||||
    //   return '';
 | 
					 | 
				
			||||||
    // }, [collectionField, field.value]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const fieldValue = useMemo(() => JSON.stringify(field.value), [field.value]);
 | 
					    const fieldValue = useMemo(() => JSON.stringify(field.value), [field.value]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [loading, setLoading] = useState(true);
 | 
					    const [loading, setLoading] = useState(true);
 | 
				
			||||||
@ -52,7 +39,7 @@ export const AssociationFieldProvider = observer(
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // 如果是表单模板数据,使用子表单和子表格组件时,过滤掉关系 ID
 | 
					      // 如果是表单模板数据,使用子表单和子表格组件时,过滤掉关系 ID
 | 
				
			||||||
      if (field.value && field.form['__template'] && ['Nester', 'SubTable'].includes(currentMode)) {
 | 
					      if (field.value && field.form['__template'] && ['Nester', 'SubTable', 'PopoverNester'].includes(currentMode)) {
 | 
				
			||||||
        if (['belongsTo', 'hasOne'].includes(collectionField.type)) {
 | 
					        if (['belongsTo', 'hasOne'].includes(collectionField.type)) {
 | 
				
			||||||
          if (field.value?.[collectionField.targetKey]) {
 | 
					          if (field.value?.[collectionField.targetKey]) {
 | 
				
			||||||
            delete field.value[collectionField.targetKey];
 | 
					            delete field.value[collectionField.targetKey];
 | 
				
			||||||
@ -69,7 +56,7 @@ export const AssociationFieldProvider = observer(
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      if (field.value !== null && field.value !== undefined) {
 | 
					      if (field.value !== null && field.value !== undefined) {
 | 
				
			||||||
        // Nester 子表单时,如果没数据初始化一个 [null] 的占位
 | 
					        // Nester 子表单时,如果没数据初始化一个 [null] 的占位
 | 
				
			||||||
        if (currentMode === 'Nester' && Array.isArray(field.value)) {
 | 
					        if (['Nester', 'PopoverNester'].includes(currentMode) && Array.isArray(field.value)) {
 | 
				
			||||||
          if (field.value.length === 0 && ['belongsToMany', 'hasMany'].includes(collectionField.type)) {
 | 
					          if (field.value.length === 0 && ['belongsToMany', 'hasMany'].includes(collectionField.type)) {
 | 
				
			||||||
            field.value = [{}];
 | 
					            field.value = [{}];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -77,7 +64,7 @@ export const AssociationFieldProvider = observer(
 | 
				
			|||||||
        setLoading(false);
 | 
					        setLoading(false);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (currentMode === 'Nester') {
 | 
					      if (['Nester', 'PopoverNester'].includes(currentMode)) {
 | 
				
			||||||
        if (['belongsTo', 'hasOne'].includes(collectionField.type)) {
 | 
					        if (['belongsTo', 'hasOne'].includes(collectionField.type)) {
 | 
				
			||||||
          field.value = {};
 | 
					          field.value = {};
 | 
				
			||||||
        } else if (['belongsToMany', 'hasMany'].includes(collectionField.type)) {
 | 
					        } else if (['belongsToMany', 'hasMany'].includes(collectionField.type)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import { InternalFileManager } from './FileManager';
 | 
				
			|||||||
import { InternalNester } from './InternalNester';
 | 
					import { InternalNester } from './InternalNester';
 | 
				
			||||||
import { InternalPicker } from './InternalPicker';
 | 
					import { InternalPicker } from './InternalPicker';
 | 
				
			||||||
import { InternalSubTable } from './InternalSubTable';
 | 
					import { InternalSubTable } from './InternalSubTable';
 | 
				
			||||||
 | 
					import { InternaPopoverNester } from './InternalPopoverNester';
 | 
				
			||||||
import { CreateRecordAction } from './components/CreateRecordAction';
 | 
					import { CreateRecordAction } from './components/CreateRecordAction';
 | 
				
			||||||
import { useAssociationFieldContext } from './hooks';
 | 
					import { useAssociationFieldContext } from './hooks';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -45,6 +46,7 @@ const EditableAssociationField = observer(
 | 
				
			|||||||
      <SchemaComponentOptions scope={{ useCreateActionProps }} components={{ CreateRecordAction }}>
 | 
					      <SchemaComponentOptions scope={{ useCreateActionProps }} components={{ CreateRecordAction }}>
 | 
				
			||||||
        {currentMode === 'Picker' && <InternalPicker {...props} />}
 | 
					        {currentMode === 'Picker' && <InternalPicker {...props} />}
 | 
				
			||||||
        {currentMode === 'Nester' && <InternalNester {...props} />}
 | 
					        {currentMode === 'Nester' && <InternalNester {...props} />}
 | 
				
			||||||
 | 
					        {currentMode === 'PopoverNester' && <InternaPopoverNester {...props} />}
 | 
				
			||||||
        {currentMode === 'Select' && <AssociationSelect {...props} />}
 | 
					        {currentMode === 'Select' && <AssociationSelect {...props} />}
 | 
				
			||||||
        {currentMode === 'SubTable' && <InternalSubTable {...props} />}
 | 
					        {currentMode === 'SubTable' && <InternalSubTable {...props} />}
 | 
				
			||||||
        {currentMode === 'FileManager' && <InternalFileManager {...props} />}
 | 
					        {currentMode === 'FileManager' && <InternalFileManager {...props} />}
 | 
				
			||||||
 | 
				
			|||||||
@ -23,13 +23,9 @@ import { flatData, getLabelFormatValue, isShowFilePicker, useLabelUiSchema } fro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const useTableSelectorProps = () => {
 | 
					const useTableSelectorProps = () => {
 | 
				
			||||||
  const field: any = useField();
 | 
					  const field: any = useField();
 | 
				
			||||||
  const {
 | 
					  const { multiple, options = [], setSelectedRows, selectedRows: rcSelectRows = [], onChange } = useContext(
 | 
				
			||||||
    multiple,
 | 
					    RecordPickerContext,
 | 
				
			||||||
    options = [],
 | 
					  );
 | 
				
			||||||
    setSelectedRows,
 | 
					 | 
				
			||||||
    selectedRows: rcSelectRows = [],
 | 
					 | 
				
			||||||
    onChange,
 | 
					 | 
				
			||||||
  } = useContext(RecordPickerContext);
 | 
					 | 
				
			||||||
  const { onRowSelectionChange, rowKey = 'id', ...others } = useTsp();
 | 
					  const { onRowSelectionChange, rowKey = 'id', ...others } = useTsp();
 | 
				
			||||||
  const { setVisible } = useActionContext();
 | 
					  const { setVisible } = useActionContext();
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
@ -72,6 +68,7 @@ const InternalFileManager = (props) => {
 | 
				
			|||||||
  const collectionField = getField(field.props.name);
 | 
					  const collectionField = getField(field.props.name);
 | 
				
			||||||
  const labelUiSchema = useLabelUiSchema(collectionField?.target, fieldNames?.label || 'label');
 | 
					  const labelUiSchema = useLabelUiSchema(collectionField?.target, fieldNames?.label || 'label');
 | 
				
			||||||
  const compile = useCompile();
 | 
					  const compile = useCompile();
 | 
				
			||||||
 | 
					  const { setVisible, modalProps } = useActionContext();
 | 
				
			||||||
  const getFilter = () => {
 | 
					  const getFilter = () => {
 | 
				
			||||||
    const targetKey = collectionField?.targetKey || 'id';
 | 
					    const targetKey = collectionField?.targetKey || 'id';
 | 
				
			||||||
    const list = options.map((option) => option[targetKey]).filter(Boolean);
 | 
					    const list = options.map((option) => option[targetKey]).filter(Boolean);
 | 
				
			||||||
@ -119,7 +116,6 @@ const InternalFileManager = (props) => {
 | 
				
			|||||||
    collectionField,
 | 
					    collectionField,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  const usePickActionProps = () => {
 | 
					  const usePickActionProps = () => {
 | 
				
			||||||
    const { setVisible } = useActionContext();
 | 
					 | 
				
			||||||
    const { multiple, selectedRows, onChange, options, collectionField } = useContext(RecordPickerContext);
 | 
					    const { multiple, selectedRows, onChange, options, collectionField } = useContext(RecordPickerContext);
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      onClick() {
 | 
					      onClick() {
 | 
				
			||||||
@ -159,7 +155,7 @@ const InternalFileManager = (props) => {
 | 
				
			|||||||
          visible: visibleSelector,
 | 
					          visible: visibleSelector,
 | 
				
			||||||
          setVisible: setVisibleSelector,
 | 
					          setVisible: setVisibleSelector,
 | 
				
			||||||
          modalProps: {
 | 
					          modalProps: {
 | 
				
			||||||
            getContainer: others?.getContainer,
 | 
					            getContainer: others?.getContainer || modalProps?.getContainer,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          formValueChanged: false,
 | 
					          formValueChanged: false,
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,13 @@
 | 
				
			|||||||
import { css, cx } from '@emotion/css';
 | 
					import { css, cx } from '@emotion/css';
 | 
				
			||||||
import { FormLayout } from '@formily/antd-v5';
 | 
					import { FormLayout } from '@formily/antd-v5';
 | 
				
			||||||
import { RecursionField, useField, useFieldSchema } from '@formily/react';
 | 
					import { RecursionField, useField, useFieldSchema, observer } from '@formily/react';
 | 
				
			||||||
import React, { useEffect } from 'react';
 | 
					import React, { useEffect } from 'react';
 | 
				
			||||||
import { CollectionProvider } from '../../../collection-manager';
 | 
					import { CollectionProvider } from '../../../collection-manager';
 | 
				
			||||||
import { useAssociationFieldContext, useInsertSchema } from './hooks';
 | 
					import { useAssociationFieldContext, useInsertSchema } from './hooks';
 | 
				
			||||||
import schema from './schema';
 | 
					import schema from './schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const InternalNester = () => {
 | 
					export const InternalNester = observer(
 | 
				
			||||||
 | 
					  () => {
 | 
				
			||||||
    const field = useField();
 | 
					    const field = useField();
 | 
				
			||||||
    const fieldSchema = useFieldSchema();
 | 
					    const fieldSchema = useFieldSchema();
 | 
				
			||||||
    const insertNester = useInsertSchema('Nester');
 | 
					    const insertNester = useInsertSchema('Nester');
 | 
				
			||||||
@ -55,4 +56,6 @@ export const InternalNester = () => {
 | 
				
			|||||||
        </FormLayout>
 | 
					        </FormLayout>
 | 
				
			||||||
      </CollectionProvider>
 | 
					      </CollectionProvider>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					  },
 | 
				
			||||||
 | 
					  { displayName: 'InternalNester' },
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -23,13 +23,9 @@ import { flatData, getLabelFormatValue, useLabelUiSchema } from './util';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const useTableSelectorProps = () => {
 | 
					const useTableSelectorProps = () => {
 | 
				
			||||||
  const field: any = useField();
 | 
					  const field: any = useField();
 | 
				
			||||||
  const {
 | 
					  const { multiple, options = [], setSelectedRows, selectedRows: rcSelectRows = [], onChange } = useContext(
 | 
				
			||||||
    multiple,
 | 
					    RecordPickerContext,
 | 
				
			||||||
    options = [],
 | 
					  );
 | 
				
			||||||
    setSelectedRows,
 | 
					 | 
				
			||||||
    selectedRows: rcSelectRows = [],
 | 
					 | 
				
			||||||
    onChange,
 | 
					 | 
				
			||||||
  } = useContext(RecordPickerContext);
 | 
					 | 
				
			||||||
  const { onRowSelectionChange, rowKey = 'id', ...others } = useTsp();
 | 
					  const { onRowSelectionChange, rowKey = 'id', ...others } = useTsp();
 | 
				
			||||||
  const { setVisible } = useActionContext();
 | 
					  const { setVisible } = useActionContext();
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
@ -62,7 +58,7 @@ const useTableSelectorProps = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const InternalPicker = observer(
 | 
					export const InternalPicker = observer(
 | 
				
			||||||
  (props: any) => {
 | 
					  (props: any) => {
 | 
				
			||||||
    const { value, multiple, onChange, quickUpload, selectFile, ...others } = props;
 | 
					    const { value, multiple, onChange, quickUpload, selectFile, shouldMountElement, ...others } = props;
 | 
				
			||||||
    const field: any = useField();
 | 
					    const field: any = useField();
 | 
				
			||||||
    const fieldNames = useFieldNames(props);
 | 
					    const fieldNames = useFieldNames(props);
 | 
				
			||||||
    const [visibleSelector, setVisibleSelector] = useState(false);
 | 
					    const [visibleSelector, setVisibleSelector] = useState(false);
 | 
				
			||||||
@ -176,7 +172,13 @@ export const InternalPicker = observer(
 | 
				
			|||||||
            </RecordProvider>
 | 
					            </RecordProvider>
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
        </Input.Group>
 | 
					        </Input.Group>
 | 
				
			||||||
        <ActionContextProvider value={{ openMode: 'drawer', visible: visibleSelector, setVisible: setVisibleSelector }}>
 | 
					        <ActionContextProvider
 | 
				
			||||||
 | 
					          value={{
 | 
				
			||||||
 | 
					            openMode: 'drawer',
 | 
				
			||||||
 | 
					            visible: visibleSelector,
 | 
				
			||||||
 | 
					            setVisible: setVisibleSelector,
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <RecordPickerProvider {...pickerProps}>
 | 
					          <RecordPickerProvider {...pickerProps}>
 | 
				
			||||||
            <CollectionProvider name={collectionField?.target}>
 | 
					            <CollectionProvider name={collectionField?.target}>
 | 
				
			||||||
              <FormProvider>
 | 
					              <FormProvider>
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					import { Popover } from 'antd';
 | 
				
			||||||
 | 
					import { css } from '@emotion/css';
 | 
				
			||||||
 | 
					import { EditOutlined } from '@ant-design/icons';
 | 
				
			||||||
 | 
					import { observer } from '@formily/react';
 | 
				
			||||||
 | 
					import React, { useContext, useRef, useState } from 'react';
 | 
				
			||||||
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
 | 
					import { ReadPrettyInternalViewer } from './InternalViewer';
 | 
				
			||||||
 | 
					import { InternalNester } from './InternalNester';
 | 
				
			||||||
 | 
					import { useAssociationFieldContext } from './hooks';
 | 
				
			||||||
 | 
					import { ActionContextProvider, ActionContext } from '../action/context';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const InternaPopoverNester = observer(
 | 
				
			||||||
 | 
					  (props) => {
 | 
				
			||||||
 | 
					    const { options } = useAssociationFieldContext();
 | 
				
			||||||
 | 
					    const [visible, setVisible] = useState(false);
 | 
				
			||||||
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
					    const ref = useRef();
 | 
				
			||||||
 | 
					    const nesterProps = {
 | 
				
			||||||
 | 
					      ...props,
 | 
				
			||||||
 | 
					      shouldMountElement: true,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const content = (
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        ref={ref}
 | 
				
			||||||
 | 
					        style={{ minWidth: '600px', maxWidth: '800px', maxHeight: '440px', overflow: 'auto' }}
 | 
				
			||||||
 | 
					        className={css`
 | 
				
			||||||
 | 
					          min-width: 600px;
 | 
				
			||||||
 | 
					          max-height: 440px;
 | 
				
			||||||
 | 
					          overflow: auto;
 | 
				
			||||||
 | 
					          .ant-card {
 | 
				
			||||||
 | 
					            border: 0px;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        `}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <InternalNester {...nesterProps} />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    const titleProps = {
 | 
				
			||||||
 | 
					      ...props,
 | 
				
			||||||
 | 
					      enableLink: true,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const getContainer = () => ref.current;
 | 
				
			||||||
 | 
					    const ctx = useContext(ActionContext);
 | 
				
			||||||
 | 
					    const modalProps = {
 | 
				
			||||||
 | 
					      getContainer: getContainer,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <ActionContextProvider value={{ ...ctx, modalProps }}>
 | 
				
			||||||
 | 
					        <Popover
 | 
				
			||||||
 | 
					          overlayStyle={{ padding: '0px' }}
 | 
				
			||||||
 | 
					          content={content}
 | 
				
			||||||
 | 
					          trigger="click"
 | 
				
			||||||
 | 
					          placement="topLeft"
 | 
				
			||||||
 | 
					          open={visible}
 | 
				
			||||||
 | 
					          onOpenChange={(open) => setVisible(open)}
 | 
				
			||||||
 | 
					          title={t(options?.uiSchema?.rawTitle)}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <span style={{ cursor: 'pointer', display: 'flex' }}>
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              className={css`
 | 
				
			||||||
 | 
					                max-width: 95%;
 | 
				
			||||||
 | 
					              `}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <ReadPrettyInternalViewer {...titleProps} />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <EditOutlined style={{ display: 'inline-flex', marginLeft: '5px' }} />
 | 
				
			||||||
 | 
					          </span>
 | 
				
			||||||
 | 
					        </Popover>
 | 
				
			||||||
 | 
					        {visible && (
 | 
				
			||||||
 | 
					          <div
 | 
				
			||||||
 | 
					            onClick={() => setVisible(false)}
 | 
				
			||||||
 | 
					            className={css`
 | 
				
			||||||
 | 
					              position: fixed;
 | 
				
			||||||
 | 
					              top: 0;
 | 
				
			||||||
 | 
					              left: 0;
 | 
				
			||||||
 | 
					              width: 100%;
 | 
				
			||||||
 | 
					              height: 100%;
 | 
				
			||||||
 | 
					              background-color: transparent;
 | 
				
			||||||
 | 
					              z-index: 9999;
 | 
				
			||||||
 | 
					            `}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      </ActionContextProvider>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  { displayName: 'InternaPopoverNester' },
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { css } from '@emotion/css';
 | 
					import { css } from '@emotion/css';
 | 
				
			||||||
import { FormItem, FormLayout } from '@formily/antd-v5';
 | 
					import { FormLayout } from '@formily/antd-v5';
 | 
				
			||||||
import { RecursionField, observer, useField, useFieldSchema, SchemaOptionsContext } from '@formily/react';
 | 
					import { RecursionField, observer, useField, useFieldSchema, SchemaOptionsContext } from '@formily/react';
 | 
				
			||||||
import React, { useEffect } from 'react';
 | 
					import React, { useEffect } from 'react';
 | 
				
			||||||
import { CollectionProvider } from '../../../collection-manager';
 | 
					import { CollectionProvider } from '../../../collection-manager';
 | 
				
			||||||
@ -22,7 +22,6 @@ export const InternalSubTable = observer(
 | 
				
			|||||||
    const option = useSchemaOptionsContext();
 | 
					    const option = useSchemaOptionsContext();
 | 
				
			||||||
    const components = {
 | 
					    const components = {
 | 
				
			||||||
      ...option.components,
 | 
					      ...option.components,
 | 
				
			||||||
      FormItem: (props) => <FormItem {...props} />,
 | 
					 | 
				
			||||||
      'Radio.Group': Select,
 | 
					      'Radio.Group': Select,
 | 
				
			||||||
      'Checkbox.Group': (props) => <Select multiple={true} mode="multiple" {...props} />,
 | 
					      'Checkbox.Group': (props) => <Select multiple={true} mode="multiple" {...props} />,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@ -38,9 +37,8 @@ export const InternalSubTable = observer(
 | 
				
			|||||||
              .ant-checkbox-wrapper {
 | 
					              .ant-checkbox-wrapper {
 | 
				
			||||||
                margin-left: 8px;
 | 
					                margin-left: 8px;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              .ant-btn {
 | 
					              .ant-table {
 | 
				
			||||||
                border: none !important;
 | 
					                margin: 0px !important;
 | 
				
			||||||
                box-shadow: none;
 | 
					 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          `}
 | 
					          `}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,6 @@ export const ReadPrettyInternalViewer: React.FC = observer(
 | 
				
			|||||||
    const { designable } = useDesignable();
 | 
					    const { designable } = useDesignable();
 | 
				
			||||||
    const { snapshot } = useActionContext();
 | 
					    const { snapshot } = useActionContext();
 | 
				
			||||||
    const ellipsisWithTooltipRef = useRef<IEllipsisWithTooltipRef>();
 | 
					    const ellipsisWithTooltipRef = useRef<IEllipsisWithTooltipRef>();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const renderRecords = () =>
 | 
					    const renderRecords = () =>
 | 
				
			||||||
      toArr(props.value).map((record, index, arr) => {
 | 
					      toArr(props.value).map((record, index, arr) => {
 | 
				
			||||||
        const val = toValue(compile(record?.[fieldNames?.label || 'label']), 'N/A');
 | 
					        const val = toValue(compile(record?.[fieldNames?.label || 'label']), 'N/A');
 | 
				
			||||||
@ -53,7 +52,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
 | 
				
			|||||||
            <span>
 | 
					            <span>
 | 
				
			||||||
              {snapshot ? (
 | 
					              {snapshot ? (
 | 
				
			||||||
                text
 | 
					                text
 | 
				
			||||||
              ) : enableLink !== false ? (
 | 
					              ) : enableLink !== false && !props.enableLink ? (
 | 
				
			||||||
                <a
 | 
					                <a
 | 
				
			||||||
                  onClick={(e) => {
 | 
					                  onClick={(e) => {
 | 
				
			||||||
                    e.stopPropagation();
 | 
					                    e.stopPropagation();
 | 
				
			||||||
@ -76,7 +75,6 @@ export const ReadPrettyInternalViewer: React.FC = observer(
 | 
				
			|||||||
          </Fragment>
 | 
					          </Fragment>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const renderWithoutTableFieldResourceProvider = () => (
 | 
					    const renderWithoutTableFieldResourceProvider = () => (
 | 
				
			||||||
      <WithoutTableFieldResource.Provider value={true}>
 | 
					      <WithoutTableFieldResource.Provider value={true}>
 | 
				
			||||||
        <FormProvider>
 | 
					        <FormProvider>
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@ const ToOneNester = (props) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const ToManyNester = observer(
 | 
					const ToManyNester = observer(
 | 
				
			||||||
  (props) => {
 | 
					  (props) => {
 | 
				
			||||||
 | 
					    console.log(props);
 | 
				
			||||||
    const fieldSchema = useFieldSchema();
 | 
					    const fieldSchema = useFieldSchema();
 | 
				
			||||||
    const { options, field, allowMultiple, allowDissociate } = useAssociationFieldContext<ArrayField>();
 | 
					    const { options, field, allowMultiple, allowDissociate } = useAssociationFieldContext<ArrayField>();
 | 
				
			||||||
    const { t } = useTranslation();
 | 
					    const { t } = useTranslation();
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import React from 'react';
 | 
				
			|||||||
import { useTranslation } from 'react-i18next';
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
import { useCollectionFilterOptions, useCollectionManager } from '../../../collection-manager';
 | 
					import { useCollectionFilterOptions, useCollectionManager } from '../../../collection-manager';
 | 
				
			||||||
import { GeneralSchemaDesigner, SchemaSettings, isPatternDisabled, isShowDefaultValue } from '../../../schema-settings';
 | 
					import { GeneralSchemaDesigner, SchemaSettings, isPatternDisabled, isShowDefaultValue } from '../../../schema-settings';
 | 
				
			||||||
import { useCompile, useDesignable } from '../../hooks';
 | 
					import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
 | 
				
			||||||
import { useAssociationFieldContext } from '../association-field/hooks';
 | 
					import { useAssociationFieldContext } from '../association-field/hooks';
 | 
				
			||||||
import { removeNullCondition } from '../filter';
 | 
					import { removeNullCondition } from '../filter';
 | 
				
			||||||
import { FilterDynamicComponent } from './FilterDynamicComponent';
 | 
					import { FilterDynamicComponent } from './FilterDynamicComponent';
 | 
				
			||||||
@ -62,6 +62,10 @@ export const TableColumnDesigner = (props) => {
 | 
				
			|||||||
  const defaultFilter = fieldSchema?.['x-component-props']?.service?.params?.filter || {};
 | 
					  const defaultFilter = fieldSchema?.['x-component-props']?.service?.params?.filter || {};
 | 
				
			||||||
  const dataSource = useCollectionFilterOptions(collectionField?.target);
 | 
					  const dataSource = useCollectionFilterOptions(collectionField?.target);
 | 
				
			||||||
  const isDateField = ['datetime', 'createdAt', 'updatedAt'].includes(collectionField?.interface);
 | 
					  const isDateField = ['datetime', 'createdAt', 'updatedAt'].includes(collectionField?.interface);
 | 
				
			||||||
 | 
					  const isAssociationField = ['obo', 'oho', 'o2o', 'o2m', 'm2m', 'm2o', 'snapshot'].includes(
 | 
				
			||||||
 | 
					    collectionField?.interface,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  const fieldModeOptions = useFieldModeOptions({ fieldSchema });
 | 
				
			||||||
  const fieldMode = fieldSchema?.['x-component-props']?.['mode'] || 'Select';
 | 
					  const fieldMode = fieldSchema?.['x-component-props']?.['mode'] || 'Select';
 | 
				
			||||||
  let readOnlyMode = 'editable';
 | 
					  let readOnlyMode = 'editable';
 | 
				
			||||||
  if (fieldSchema['x-disabled'] === true) {
 | 
					  if (fieldSchema['x-disabled'] === true) {
 | 
				
			||||||
@ -250,15 +254,18 @@ export const TableColumnDesigner = (props) => {
 | 
				
			|||||||
          }}
 | 
					          }}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
      {readOnlyMode === 'read-pretty' &&
 | 
					      {isAssociationField && (
 | 
				
			||||||
        ['linkTo', 'm2m', 'm2o', 'o2m', 'obo', 'oho', 'snapshot'].includes(collectionField?.interface) && (
 | 
					 | 
				
			||||||
        <SchemaSettings.SelectItem
 | 
					        <SchemaSettings.SelectItem
 | 
				
			||||||
          key="field-mode"
 | 
					          key="field-mode"
 | 
				
			||||||
          title={t('Field component')}
 | 
					          title={t('Field component')}
 | 
				
			||||||
            options={[
 | 
					          options={
 | 
				
			||||||
 | 
					            readOnlyMode === 'read-pretty'
 | 
				
			||||||
 | 
					              ? [
 | 
				
			||||||
                  { label: t('Title'), value: 'Select' },
 | 
					                  { label: t('Title'), value: 'Select' },
 | 
				
			||||||
                  { label: t('Tag'), value: 'Tag' },
 | 
					                  { label: t('Tag'), value: 'Tag' },
 | 
				
			||||||
            ]}
 | 
					                ]
 | 
				
			||||||
 | 
					              : fieldModeOptions
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
          value={fieldMode}
 | 
					          value={fieldMode}
 | 
				
			||||||
          onChange={(mode) => {
 | 
					          onChange={(mode) => {
 | 
				
			||||||
            const schema = {
 | 
					            const schema = {
 | 
				
			||||||
@ -299,7 +306,6 @@ export const TableColumnDesigner = (props) => {
 | 
				
			|||||||
          }}
 | 
					          }}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
 | 
					 | 
				
			||||||
      {isSubTableColumn && !field.readPretty && !uiSchema?.['x-read-pretty'] && (
 | 
					      {isSubTableColumn && !field.readPretty && !uiSchema?.['x-read-pretty'] && (
 | 
				
			||||||
        <SchemaSettings.SwitchItem
 | 
					        <SchemaSettings.SwitchItem
 | 
				
			||||||
          key="required"
 | 
					          key="required"
 | 
				
			||||||
 | 
				
			|||||||
@ -3,11 +3,13 @@ import { useMemo } from 'react';
 | 
				
			|||||||
import { useTranslation } from 'react-i18next';
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
import { useCollection, useCollectionManager } from '../../collection-manager';
 | 
					import { useCollection, useCollectionManager } from '../../collection-manager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useFieldModeOptions = () => {
 | 
					export const useFieldModeOptions = (props?) => {
 | 
				
			||||||
  const { getCollectionJoinField, getCollection } = useCollectionManager();
 | 
					  const { getCollectionJoinField, getCollection } = useCollectionManager();
 | 
				
			||||||
  const fieldSchema = useFieldSchema();
 | 
					  const currentFieldSchema = useFieldSchema();
 | 
				
			||||||
 | 
					  const fieldSchema = props?.fieldSchema || currentFieldSchema;
 | 
				
			||||||
  const field = useField();
 | 
					  const field = useField();
 | 
				
			||||||
  const isReadPretty = field.readPretty;
 | 
					  const isReadPretty = field.readPretty;
 | 
				
			||||||
 | 
					  const isSubTableField = props?.fieldSchema;
 | 
				
			||||||
  const { getField } = useCollection();
 | 
					  const { getField } = useCollection();
 | 
				
			||||||
  const collectionField = getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']);
 | 
					  const collectionField = getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']);
 | 
				
			||||||
  const { t } = useTranslation();
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
@ -16,7 +18,6 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
    if (!collectionField || !collectionField?.interface) {
 | 
					    if (!collectionField || !collectionField?.interface) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!['o2o', 'oho', 'obo', 'o2m', 'linkTo', 'm2o', 'm2m'].includes(collectionField.interface)) return;
 | 
					    if (!['o2o', 'oho', 'obo', 'o2m', 'linkTo', 'm2o', 'm2m'].includes(collectionField.interface)) return;
 | 
				
			||||||
    const collection = getCollection(collectionField.target);
 | 
					    const collection = getCollection(collectionField.target);
 | 
				
			||||||
    if (collection?.template === 'file') {
 | 
					    if (collection?.template === 'file') {
 | 
				
			||||||
@ -29,10 +30,9 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
        : [
 | 
					        : [
 | 
				
			||||||
            { label: t('Select'), value: 'Select' },
 | 
					            { label: t('Select'), value: 'Select' },
 | 
				
			||||||
            { label: t('Record picker'), value: 'Picker' },
 | 
					            { label: t('Record picker'), value: 'Picker' },
 | 
				
			||||||
            { label: t('File manager'), value: 'FileManager' },
 | 
					            !isSubTableField && { label: t('File manager'), value: 'FileManager' },
 | 
				
			||||||
          ];
 | 
					          ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (collectionField.interface) {
 | 
					    switch (collectionField.interface) {
 | 
				
			||||||
      case 'o2m':
 | 
					      case 'o2m':
 | 
				
			||||||
        return isReadPretty
 | 
					        return isReadPretty
 | 
				
			||||||
@ -45,8 +45,9 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
          : [
 | 
					          : [
 | 
				
			||||||
              { label: t('Select'), value: 'Select' },
 | 
					              { label: t('Select'), value: 'Select' },
 | 
				
			||||||
              { label: t('Record picker'), value: 'Picker' },
 | 
					              { label: t('Record picker'), value: 'Picker' },
 | 
				
			||||||
              { label: t('Sub-form'), value: 'Nester' },
 | 
					              !isSubTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
				
			||||||
              { label: t('Sub-table'), value: 'SubTable' },
 | 
					              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
				
			||||||
 | 
					              !isSubTableField && { label: t('Sub-table'), value: 'SubTable' },
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
      case 'm2m':
 | 
					      case 'm2m':
 | 
				
			||||||
        return isReadPretty
 | 
					        return isReadPretty
 | 
				
			||||||
@ -59,8 +60,9 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
          : [
 | 
					          : [
 | 
				
			||||||
              { label: t('Select'), value: 'Select' },
 | 
					              { label: t('Select'), value: 'Select' },
 | 
				
			||||||
              { label: t('Record picker'), value: 'Picker' },
 | 
					              { label: t('Record picker'), value: 'Picker' },
 | 
				
			||||||
              { label: t('Sub-table'), value: 'SubTable' },
 | 
					              !isSubTableField && { label: t('Sub-table'), value: 'SubTable' },
 | 
				
			||||||
              { label: t('Sub-form'), value: 'Nester' },
 | 
					              !isSubTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
				
			||||||
 | 
					              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
      case 'm2o':
 | 
					      case 'm2o':
 | 
				
			||||||
      case 'linkTo':
 | 
					      case 'linkTo':
 | 
				
			||||||
@ -73,7 +75,8 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
          : [
 | 
					          : [
 | 
				
			||||||
              { label: t('Select'), value: 'Select' },
 | 
					              { label: t('Select'), value: 'Select' },
 | 
				
			||||||
              { label: t('Record picker'), value: 'Picker' },
 | 
					              { label: t('Record picker'), value: 'Picker' },
 | 
				
			||||||
              { label: t('Sub-form'), value: 'Nester' },
 | 
					              !isSubTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
				
			||||||
 | 
					              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
@ -86,9 +89,10 @@ export const useFieldModeOptions = () => {
 | 
				
			|||||||
          : [
 | 
					          : [
 | 
				
			||||||
              { label: t('Select'), value: 'Select' },
 | 
					              { label: t('Select'), value: 'Select' },
 | 
				
			||||||
              { label: t('Record picker'), value: 'Picker' },
 | 
					              { label: t('Record picker'), value: 'Picker' },
 | 
				
			||||||
              { label: t('Sub-form'), value: 'Nester' },
 | 
					              !isSubTableField && { label: t('Sub-form'), value: 'Nester' },
 | 
				
			||||||
 | 
					              { label: t('Sub-form(Popover)'), value: 'PopoverNester' },
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }, [t, collectionField?.interface, label]);
 | 
					  }, [t, collectionField?.interface, label]);
 | 
				
			||||||
  return fieldModeOptions;
 | 
					  return (fieldModeOptions || []).filter(Boolean);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -290,6 +290,17 @@ export class Database extends EventEmitter implements AsyncEmitter {
 | 
				
			|||||||
      }),
 | 
					      }),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.migrator = new Umzug({
 | 
				
			||||||
 | 
					      logger: migratorOptions.logger || console,
 | 
				
			||||||
 | 
					      migrations: this.migrations.callback(),
 | 
				
			||||||
 | 
					      context,
 | 
				
			||||||
 | 
					      storage: new SequelizeStorage({
 | 
				
			||||||
 | 
					        modelName: `${this.options.tablePrefix || ''}migrations`,
 | 
				
			||||||
 | 
					        ...migratorOptions.storage,
 | 
				
			||||||
 | 
					        sequelize: this.sequelize,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.initListener();
 | 
					    this.initListener();
 | 
				
			||||||
    patchSequelizeQueryInterface(this);
 | 
					    patchSequelizeQueryInterface(this);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user