Merge branch 'T-2327-and-2771' of github.com:nocobase/nocobase into T-2327-and-2771

This commit is contained in:
katherinehhh 2024-01-18 12:59:45 +08:00
commit 738f9c568e
10 changed files with 65 additions and 58 deletions

View File

@ -303,9 +303,9 @@ export const useBlockContext = () => {
return useContext(BlockContext);
};
export const BlockNamespaceContext = createContext<string>(undefined);
export const useBlockNamespace = () => {
return useContext(BlockNamespaceContext);
export const CollectionNamespace = createContext<string>(undefined);
export const useCollectionNamespace = () => {
return useContext(CollectionNamespace);
};
export const BlockProvider = (props: {
@ -331,7 +331,7 @@ export const BlockProvider = (props: {
return (
<BlockContext.Provider value={blockValue}>
<BlockNamespaceContext.Provider value={namespace}>
<CollectionNamespace.Provider value={namespace}>
<MaybeCollectionProvider collection={collection}>
<BlockAssociationContext.Provider value={association}>
<BlockResourceContext.Provider value={resource}>
@ -345,7 +345,7 @@ export const BlockProvider = (props: {
</BlockResourceContext.Provider>
</BlockAssociationContext.Provider>
</MaybeCollectionProvider>
</BlockNamespaceContext.Provider>
</CollectionNamespace.Provider>
</BlockContext.Provider>
);
};

View File

@ -4,7 +4,7 @@ import { CollectionOptions } from './types';
import React from 'react';
import { DeletedPlaceholder } from '../application/collection/DeletedPlaceholder';
import { CollectionExtendsProvider } from './CollectionManagerProvider';
import { useBlockNamespace } from '../block-provider';
import { useCollectionNamespace } from '../block-provider';
function getCollectionName(name?: string | CollectionOptions): string {
if (!name) return undefined;
@ -17,14 +17,16 @@ export const CollectionProvider: FC<{
collection?: CollectionOptions | string;
allowNull?: boolean;
children?: ReactNode;
}> = ({ children, allowNull, name, collection }) => {
namespace?: string;
}> = ({ children, allowNull, name, namespace, collection }) => {
const collectionName = getCollectionName(name || collection);
const namespace = useBlockNamespace();
const collectionNamespace = useCollectionNamespace();
const namespaceValue = namespace || collectionNamespace || undefined;
const cm = useCollectionManagerV2();
const hasCollection = cm.getCollection(collectionName, { namespace });
const hasCollection = cm.getCollection(collectionName, { namespace: namespaceValue });
if (hasCollection || (allowNull && !collection))
return (
<CollectionProviderV2 allowNull={allowNull} name={collectionName} namespace={namespace}>
<CollectionProviderV2 allowNull={allowNull} name={collectionName} namespace={namespaceValue}>
{children}
</CollectionProviderV2>
);

View File

@ -27,12 +27,14 @@ import { collectionSchema } from './schemas/collections';
const useAsyncDataSource = (service: any, exclude?: string[]) => {
return (field: any, options?: any) => {
field.loading = true;
service(field, options, exclude).then(
action.bound((data: any) => {
field.dataSource = data;
field.loading = false;
}),
);
service(field, options, exclude)
.then(
action.bound((data: any) => {
field.dataSource = data;
field.loading = false;
}),
)
.catch(console.error);
};
};
@ -66,13 +68,15 @@ const useBulkDestroySubField = () => {
// 获取当前字段列表
const useCurrentFields = () => {
const record = useRecord();
const { getCollectionFields } = useCollectionManager();
// 仅当当前字段为子表单时从DataSourceContext中获取已配置的字段列表
if (record.__parent && record.__parent.interface === 'subTable') {
// eslint-disable-next-line react-hooks/rules-of-hooks
const ctx = useContext(DataSourceContext);
return ctx.dataSource;
}
const { getCollectionFields } = useCollectionManager();
const fields = getCollectionFields(record.collectionName || record.name) as any[];
return fields;
};
@ -83,7 +87,7 @@ const useNewId = (prefix) => {
export const ConfigurationTable = () => {
const { t } = useTranslation();
const { collections = [], interfaces } = useCollectionManager();
const { interfaces, getCollections } = useCollectionManager();
const {
data: { database },
} = useCurrentAppInfo();
@ -91,8 +95,6 @@ export const ConfigurationTable = () => {
const data = useContext(CollectionCategroriesContext);
const api = useAPIClient();
const resource = api.resource('dbViews');
const collectonsRef: any = useRef();
collectonsRef.current = collections;
const compile = useCompile();
/**
@ -105,7 +107,7 @@ export const ConfigurationTable = () => {
const loadCollections = async (field, options, exclude?: string[]) => {
const { targetScope } = options;
const isFieldInherits = field.props?.name === 'inherits';
const filteredItems = collectonsRef.current.filter((item) => {
const filteredItems = getCollections().filter((item) => {
if (exclude?.includes(item.template)) {
return false;
}

View File

@ -1,16 +1,16 @@
import { CascaderProps } from 'antd';
import _ from 'lodash';
import { useCallback, useMemo, useState } from 'react';
import { useCompile, useSchemaComponentContext } from '../../schema-component';
import { useCompile } from '../../schema-component';
import { CollectionFieldOptions, CollectionOptions } from '../types';
import { useCollectionManagerV2 } from '../../application';
import { InheritanceCollectionMixin } from '../mixins/InheritanceCollectionMixin';
import { uid } from '@formily/shared';
import { useBlockNamespace } from '../../block-provider';
import { useCollectionNamespace } from '../../block-provider';
export const useCollectionManager = (namespace?: string) => {
const cm = useCollectionManagerV2();
const blockNamespaceValue = useBlockNamespace();
const blockNamespaceValue = useCollectionNamespace();
const namespaceValue = namespace || blockNamespaceValue || undefined;
const [random, setRandom] = useState(uid());
const interfaces = useMemo(() => cm?.getFieldInterfaces(), [cm, random]);
@ -22,17 +22,9 @@ export const useCollectionManager = (namespace?: string) => {
.map((item) => item.getOptions());
}, [cm]);
const collections = useMemo(() => getCollections(), [cm, random]);
const { refresh } = useSchemaComponentContext();
const service = useCallback(() => cm?.reloadMain(refresh), [cm]);
const service = useCallback(() => cm?.reloadMain(() => setRandom(uid())), [cm]);
const updateCollection = cm?.setCollections.bind(cm);
const refreshCM = useCallback(
() =>
cm?.reloadMain(() => {
refresh();
setRandom(uid());
}),
[cm],
);
const refreshCM = useCallback(() => cm?.reloadMain(() => setRandom(uid())), [cm]);
const compile = useCompile();
const getInheritedFields = useCallback(

View File

@ -121,7 +121,7 @@ export function useMenuSearch(data: any, openKey: string, showType?: boolean) {
const currentItems = useMemo(() => {
if (!openKey) return [];
return data.find((item) => item.key === openKey)?.children || [];
return data.find((item) => (item.key || item.name) === openKey)?.children || [];
}, [data, openKey]);
// 根据搜索的值进行处理

View File

@ -13,7 +13,6 @@ export const FormBlockInitializer = () => {
icon={<FormOutlined />}
componentType={'FormItem'}
templateWrap={(templateSchema, { item }) => {
console.log('item', item);
const s = createFormBlockSchema({
isCusomeizeCreate,
namespace: item.namespace,

View File

@ -65,7 +65,7 @@ function InternalFormBlockInitializer({ schema, ...others }) {
export function FormBlockInitializer() {
const itemConfig = useSchemaInitializerItem();
return (
<CollectionProvider collection={itemConfig.schema?.collection}>
<CollectionProvider namespace={itemConfig.schema?.namespace} collection={itemConfig.schema?.collection}>
<InternalFormBlockInitializer {...itemConfig} />
</CollectionProvider>
);

View File

@ -2,7 +2,9 @@ import { createForm } from '@formily/core';
import { RecursionField, useField, useFieldSchema } from '@formily/react';
import {
BlockRequestContext,
CollectionNamespace,
CollectionProvider,
DEFAULT_COLLECTION_NAMESPACE_NAME,
FormActiveFieldsProvider,
FormBlockContext,
FormV2,
@ -19,7 +21,9 @@ export function FormBlockProvider(props) {
const fieldSchema = useFieldSchema();
const field = useField();
const formBlockRef = useRef(null);
const { getAssociationAppends } = useAssociationNames();
const namespace = props.namespace || DEFAULT_COLLECTION_NAMESPACE_NAME;
const { getAssociationAppends } = useAssociationNames(namespace);
const { appends, updateAssociationValues } = getAssociationAppends();
const [formKey] = Object.keys(fieldSchema.toJSON().properties ?? {});
const values = userJob?.result?.[formKey];
@ -50,7 +54,13 @@ export function FormBlockProvider(props) {
};
}, [values]);
const api = useAPIClient();
const resource = api.resource(props.collection);
const headers = useMemo(() => {
if (namespace !== DEFAULT_COLLECTION_NAMESPACE_NAME) {
return { 'x-connection': namespace };
}
}, [namespace]);
const resource = api.resource(props.collection, undefined, headers);
const __parent = useContext(BlockRequestContext);
const formBlockValue = useMemo(() => {
@ -65,21 +75,23 @@ export function FormBlockProvider(props) {
}, [field, form, params, service, updateAssociationValues]);
return !userJob.status || values ? (
<CollectionProvider collection={props.collection}>
<RecordProvider record={values} parent={false}>
<FormActiveFieldsProvider name="form">
<BlockRequestContext.Provider value={{ block: 'form', props, field, service, resource, __parent }}>
<FormBlockContext.Provider value={formBlockValue}>
<Component {...field.componentProps}>
<FormV2.Templates style={{ marginBottom: 18 }} form={form} />
<div ref={formBlockRef}>
<RecursionField schema={fieldSchema} onlyRenderProperties />
</div>
</Component>
</FormBlockContext.Provider>
</BlockRequestContext.Provider>
</FormActiveFieldsProvider>
</RecordProvider>
</CollectionProvider>
<CollectionNamespace.Provider value={namespace}>
<CollectionProvider collection={props.collection}>
<RecordProvider record={values} parent={false}>
<FormActiveFieldsProvider name="form">
<BlockRequestContext.Provider value={{ block: 'form', props, field, service, resource, __parent }}>
<FormBlockContext.Provider value={formBlockValue}>
<Component {...field.componentProps}>
<FormV2.Templates style={{ marginBottom: 18 }} form={form} />
<div ref={formBlockRef}>
<RecursionField schema={fieldSchema} onlyRenderProperties />
</div>
</Component>
</FormBlockContext.Provider>
</BlockRequestContext.Provider>
</FormActiveFieldsProvider>
</RecordProvider>
</CollectionProvider>
</CollectionNamespace.Provider>
) : null;
}

View File

@ -41,9 +41,10 @@ export default {
title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
config: {
useInitializer({ allCollections }) {
const items = useMemo(
const childItems = useMemo(
() =>
allCollections.map(({ nsName, nsTitle, collections }) => ({
key: nsName,
name: nsName,
label: nsTitle,
type: 'subMenu',
@ -63,8 +64,6 @@ export default {
})),
[allCollections],
);
const getMenuItems = useGetSchemaInitializerMenuItems();
const childItems = useMemo(() => getMenuItems(items, 'createRecordForm'), [items]);
const [openMenuKey, setOpenMenuKey] = useState('');
const searchedChildren = useMenuSearch(childItems, openMenuKey);

View File

@ -81,6 +81,7 @@ export default {
const childItems = useMemo(
() =>
allCollections.map(({ nsName, nsTitle, collections }) => ({
key: nsName,
name: nsName,
label: nsTitle,
type: 'subMenu',