mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 05:36:05 +00:00
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:
parent
6c149aadfc
commit
3fcdd94549
@ -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)
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
);
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
);
|
||||
});
|
||||
|
@ -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>
|
||||
);
|
||||
});
|
||||
|
@ -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>({});
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user