fix:association appends (#1842)

* fix: getNesterAppends filter bug

* fix: associationSelect

* fix: associationSelect

* fix: associationSelect

* fix: getAssociationAppends

* fix: sub-form collection context

* refactor: code improve

* refactor: code improve

* refactor: code improve

* refactor: code improve

* refactor: code improve
This commit is contained in:
katherinehhh 2023-05-12 07:20:27 +08:00 committed by GitHub
parent 6c149aadfc
commit 3fcdd94549
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 79 additions and 64 deletions

View File

@ -1074,6 +1074,7 @@ export const useAssociationFilterBlockProps = () => {
export const useAssociationNames = (collection) => {
const { getCollectionFields, getCollectionJoinField } = useCollectionManager();
const { getField } = useCollection();
const collectionFields = getCollectionFields(collection);
const associationFields = new Set();
for (const collectionField of collectionFields) {
@ -1098,7 +1099,8 @@ export const useAssociationNames = (collection) => {
const getAssociationAppends = (schema, arr = []) => {
const data = schema.reduceProperties((buf, s) => {
const collectionfield = s['x-collection-field'] && getCollectionJoinField(s['x-collection-field']);
const collectionfield =
getField(s.name) || (s['x-collection-field'] && getCollectionJoinField(s['x-collection-field']));
if (
collectionfield &&
['createdBy', 'updatedBy', 'o2m', 'obo', 'oho', 'm2o', 'm2m'].includes(collectionfield.interface)

View File

@ -1,19 +1,28 @@
import { useField, useFieldSchema } from '@formily/react';
import { useField, useFieldSchema, observer } from '@formily/react';
import React, { useMemo } from 'react';
import { useCollectionManager } from '../../../collection-manager';
import { AssociationFieldContext } from './context';
export function AssociationFieldProvider(props) {
export const AssociationFieldProvider = observer((props) => {
const field = useField();
const { getCollectionField } = useCollectionManager();
const { getCollectionJoinField, getCollection } = useCollectionManager();
const fieldSchema = useFieldSchema();
const collectionField = useMemo(
() => getCollectionField(fieldSchema['x-collection-field']),
() => getCollectionJoinField(fieldSchema['x-collection-field']),
[fieldSchema['x-collection-field'], fieldSchema.name],
);
const isFileCollection = useMemo(
() => getCollection(collectionField?.target)?.template === 'file',
[fieldSchema['x-collection-field']],
);
return (
<AssociationFieldContext.Provider value={{ options: collectionField, field }}>
const currentMode = useMemo(
() => fieldSchema['x-component-props'].mode || (isFileCollection ? 'FileManager' : 'Select'),
[fieldSchema['x-component-props'].mode],
);
return collectionField ? (
<AssociationFieldContext.Provider value={{ options: collectionField, field, currentMode }}>
{props.children}
</AssociationFieldContext.Provider>
);
}
) : null;
});

View File

@ -3,9 +3,10 @@ import { RecursionField, connect, mapProps, observer, useField, useFieldSchema }
import { Button, Input } from 'antd';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { CollectionProvider, useCollection } from '../../../collection-manager';
import { CollectionProvider } from '../../../collection-manager';
import { useFieldTitle } from '../../hooks';
import { ActionContext } from '../action';
import { useAssociationFieldContext } from './hooks';
import { RemoteSelect, RemoteSelectProps } from '../remote-select';
import useServiceOptions, { useInsertSchema } from './hooks';
import schema from './schema';
@ -18,11 +19,10 @@ export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
const { fieldNames, objectValue = true } = props;
const field: any = useField();
const [visibleAddNewer, setVisibleAddNewer] = useState(false);
const { getField } = useCollection();
const collectionField = getField(field.props.name);
const service = useServiceOptions(props);
const fieldSchema = useFieldSchema();
const [visibleAddNewer, setVisibleAddNewer] = useState(false);
const service = useServiceOptions(props);
const { options: collectionField } = useAssociationFieldContext();
const isFilterForm = fieldSchema['x-designer'] === 'FormItem.FilterFormDesigner';
const isAllowAddNew = fieldSchema['x-add-new'];
const insertAddNewer = useInsertSchema('AddNewer');
@ -74,7 +74,7 @@ const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
</Input.Group>
<ActionContext.Provider value={{ openMode: 'drawer', visible: visibleAddNewer, setVisible: setVisibleAddNewer }}>
<CollectionProvider name={collectionField?.target}>
<CollectionProvider name={collectionField.target}>
<RecursionField
onlyRenderProperties
basePath={field.address}

View File

@ -5,24 +5,18 @@ import { InternalNester } from './InternalNester';
import { InternalPicker } from './InternalPicker';
import { AssociationSelect } from './AssociationSelect';
import { useAssociationCreateActionProps as useCAP } from '../../../block-provider/hooks';
import { useCollection, useCollectionManager } from '../../../collection-manager';
import { SchemaComponentOptions } from '../../';
import { InternalSubTable } from './InternalSubTable';
import { InternalFileManager } from './FileManager';
import { useAssociationFieldContext } from './hooks';
export const Editable = observer((props: any) => {
useEffect(() => {
props.mode && setCurrentMode(props.mode);
}, [props.mode]);
const EditableAssociationField = observer((props: any) => {
const { multiple } = props;
const field: any = useField();
const form = useForm();
const fieldSchema = useFieldSchema();
const { getField } = useCollection();
const { getCollection } = useCollectionManager();
const collectionField = getField(field.props.name);
const isFileCollection = getCollection(collectionField?.target)?.template === 'file';
const [currentMode, setCurrentMode] = useState(props.mode || (isFileCollection ? 'FileManager' : 'Select'));
const { options: collectionField, currentMode } = useAssociationFieldContext();
const useCreateActionProps = () => {
const { onClick } = useCAP();
const actionField: any = useField();
@ -49,15 +43,21 @@ export const Editable = observer((props: any) => {
},
};
};
return (
<SchemaComponentOptions scope={{ useCreateActionProps }}>
{currentMode === 'Picker' && <InternalPicker {...props} />}
{currentMode === 'Nester' && <InternalNester {...props} />}
{currentMode === 'Select' && <AssociationSelect {...props} />}
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
{currentMode === 'FileManager' && <InternalFileManager {...props} />}
</SchemaComponentOptions>
);
});
export const Editable = observer((props) => {
return (
<AssociationFieldProvider>
<SchemaComponentOptions scope={{ useCreateActionProps }}>
{currentMode === 'Picker' && <InternalPicker {...props} />}
{currentMode === 'Nester' && <InternalNester {...props} />}
{currentMode === 'Select' && <AssociationSelect {...props} />}
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
{currentMode === 'FileManager' && <InternalFileManager {...props} />}
</SchemaComponentOptions>
<EditableAssociationField {...props} />
</AssociationFieldProvider>
);
});

View File

@ -2,19 +2,21 @@ import { FormLayout } from '@formily/antd';
import { RecursionField, useField, useFieldSchema } from '@formily/react';
import React, { useEffect } from 'react';
import { CollectionProvider } from '../../../collection-manager';
import { useAssociationFieldContext, useInsertSchema } from './hooks';
import { useInsertSchema } from './hooks';
import { useAssociationFieldContext } from './hooks';
import schema from './schema';
export const InternalNester = () => {
const field = useField();
const fieldSchema = useFieldSchema();
const insertNester = useInsertSchema('Nester');
const { options } = useAssociationFieldContext();
const { options: collectionField } = useAssociationFieldContext();
useEffect(() => {
insertNester(schema.Nester);
}, []);
return (
<CollectionProvider name={options.target}>
<CollectionProvider name={collectionField.target}>
<FormLayout layout={'vertical'}>
<RecursionField
onlyRenderProperties

View File

@ -14,11 +14,12 @@ import {
TableSelectorParamsProvider,
useTableSelectorProps as useTsp,
} from '../../../block-provider/TableSelectorProvider';
import { CollectionProvider, useCollection } from '../../../collection-manager';
import { CollectionProvider, useCollection, useCollectionManager } from '../../../collection-manager';
import { useCompile } from '../../hooks';
import { ActionContext } from '../action';
import { useFieldNames, useInsertSchema } from './hooks';
import schema from './schema';
import { useAssociationFieldContext } from './hooks';
import { flatData, getLabelFormatValue, useLabelUiSchema } from './util';
const useTableSelectorProps = () => {
@ -69,10 +70,9 @@ export const InternalPicker = observer((props: any) => {
const fieldSchema = useFieldSchema();
const insertAddNewer = useInsertSchema('AddNewer');
const insertSelector = useInsertSchema('Selector');
const { getField } = useCollection();
const { t } = useTranslation();
const collectionField = getField(field.props.name);
const addbuttonClick = () => {
const { options: collectionField } = useAssociationFieldContext();
const addbuttonClick = () => {
insertAddNewer(schema.AddNewer);
setVisibleAddNewer(true);
};

View File

@ -2,7 +2,7 @@ import { RecursionField, observer, useField, useFieldSchema } from '@formily/rea
import { toArr } from '@formily/shared';
import React, { Fragment, useRef, useState } from 'react';
import { BlockAssociationContext, WithoutTableFieldResource } from '../../../block-provider';
import { CollectionProvider, useCollection, useCollectionManager } from '../../../collection-manager';
import { CollectionProvider } from '../../../collection-manager';
import { RecordProvider, useRecord } from '../../../record-provider';
import { FormProvider } from '../../core';
import { useCompile } from '../../hooks';
@ -11,6 +11,7 @@ import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
import { useFieldNames, useInsertSchema } from './hooks';
import schema from './schema';
import { getLabelFormatValue, useLabelUiSchema } from './util';
import { useAssociationFieldContext } from './hooks';
interface IEllipsisWithTooltipRef {
setPopoverVisible: (boolean) => void;
@ -26,14 +27,12 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => {
const fieldSchema = useFieldSchema();
const recordCtx = useRecord();
const { enableLink } = fieldSchema['x-component-props'];
const { getCollectionJoinField } = useCollectionManager();
// value 做了转换,但 props.value 和原来 useField().value 的值不一致
const field = useField();
const fieldNames = useFieldNames(props);
const [visible, setVisible] = useState(false);
const insertViewer = useInsertSchema('Viewer');
const { getField } = useCollection();
const collectionField = getField(fieldSchema.name) || getCollectionJoinField(fieldSchema?.['x-collection-field']);
const { options: collectionField } = useAssociationFieldContext();
const [record, setRecord] = useState({});
const compile = useCompile();
const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label');
@ -98,7 +97,7 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => {
);
};
return collectionField ? (
return (
<div>
<BlockAssociationContext.Provider value={`${collectionField.collectionName}.${collectionField.name}`}>
<CollectionProvider name={collectionField.target ?? collectionField.targetCollection}>
@ -113,5 +112,5 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => {
</CollectionProvider>
</BlockAssociationContext.Provider>
</div>
) : null;
);
});

View File

@ -3,26 +3,27 @@ import { useField, observer } from '@formily/react';
import { AssociationFieldProvider } from './AssociationFieldProvider';
import { InternalNester } from './InternalNester';
import { ReadPrettyInternalViewer } from './InternalViewer';
import { useCollection, useCollectionManager } from '../../../collection-manager';
import { InternalSubTable } from './InternalSubTable';
import { FileManageReadPretty } from './FileManager';
import { useAssociationFieldContext } from './hooks';
const ReadPrettyAssociationField = observer((props: any) => {
const { currentMode } = useAssociationFieldContext();
export const ReadPretty = observer((props: any) => {
const field: any = useField();
const { getField } = useCollection();
const { getCollection } = useCollectionManager();
const collectionField = getField(field.props.name);
const isFileCollection = getCollection(collectionField?.target)?.template === 'file';
const [currentMode, setCurrentMode] = useState(props.mode || (isFileCollection ? 'FileManager' : 'Select'));
useEffect(() => {
props.mode && setCurrentMode(props.mode);
}, [props.mode]);
return (
<AssociationFieldProvider>
<>
{['Select', 'Picker'].includes(currentMode) && <ReadPrettyInternalViewer {...props} />}
{currentMode === 'Nester' && <InternalNester {...props} />}
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
{currentMode === 'FileManager' && <FileManageReadPretty {...props} />}
</>
);
});
export const ReadPretty = observer((props) => {
return (
<AssociationFieldProvider>
<ReadPrettyAssociationField {...props} />
</AssociationFieldProvider>
);
});

View File

@ -2,8 +2,9 @@ import { GeneralField } from '@formily/core';
import { createContext } from 'react';
export interface AssociationFieldContextProps {
options: any;
field: GeneralField;
options?: any;
field?: GeneralField;
currentMode?:string;
}
export const AssociationFieldContext = createContext<AssociationFieldContextProps>(null);
export const AssociationFieldContext = createContext<AssociationFieldContextProps>({});

View File

@ -30,15 +30,15 @@ export const useInsertSchema = (component) => {
};
export function useAssociationFieldContext<F extends GeneralField>() {
return useContext(AssociationFieldContext) as { options: any; field: F };
return useContext(AssociationFieldContext) as { options: any; field: F; currentMode: string };
}
export default function useServiceOptions(props) {
const { action = 'list', service, fieldNames } = props;
const params = service?.params || {};
const fieldSchema = useFieldSchema();
const { getField, fields } = useCollection();
const { getCollectionFields } = useCollectionManager();
const { getField } = useCollection();
const { getCollectionFields, getCollectionJoinField } = useCollectionManager();
const record = useRecord();
const normalizeValues = useCallback(
@ -63,8 +63,9 @@ export default function useServiceOptions(props) {
}, [props.value, normalizeValues]);
const collectionField = useMemo(() => {
return getField(fieldSchema.name);
return getField(fieldSchema.name) || getCollectionJoinField(fieldSchema?.['x-collection-field']);
}, [fieldSchema.name]);
const sourceValue = record?.[collectionField?.sourceKey];
const filter = useMemo(() => {
const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface);