refactor: namespace to dataSource

This commit is contained in:
dream2023 2024-01-22 17:06:27 +08:00
parent 9c25e10668
commit 2a8cf7a5b8
52 changed files with 289 additions and 406 deletions

View File

@ -37,10 +37,10 @@ const Demo = () => {
```tsx | pure
const Demo = () => {
const collectionManager = useCollectionManagerV2();
const collectionNamespaces = useMemo(() => collectionManager.getCollectionNames(), [collectionManager]);
const dataSources = useMemo(() => collectionManager.getCollectionNames(), [collectionManager]);
return <div>
{collectionNamespaces.map((namespace) => {
{dataSources.map((namespace) => {
return <div key={namespace.name}>{namespace.name}: {namespace.title}</div>;
})}
</div>;
@ -54,10 +54,10 @@ import { Application, useCollectionManagerV2, useCompile } from '@nocobase/clien
const Demo = () => {
const compile = useCompile();
const collectionManager = useCollectionManagerV2();
const collectionNamespaces = useMemo(() => collectionManager.getCollectionNamespaces(), [collectionManager]);
const dataSources = useMemo(() => collectionManager.getDataSources(), [collectionManager]);
return <div>
{collectionNamespaces.map((namespace) => {
{dataSources.map((namespace) => {
return <div key={namespace.name}>{namespace.name}: { compile(namespace.title)}</div>;
})}
</div>;
@ -66,7 +66,7 @@ const Demo = () => {
const app = new Application({
providers: [Demo],
collectionManager: {
collectionNamespaces: {
dataSources: {
'db2': "DB 2",
}
}

View File

@ -10,12 +10,12 @@ interface CollectionManagerOptionsV2 {
collectionTemplates?: (typeof CollectionTemplateBase)[];
fieldInterfaces?: (typeof CollectionFieldInterfaceBase)[];
fieldGroups?: Record<string, { label: string; order?: number }>;
collectionNamespaces?: Record<string, string>;
dataSources?: Record<string, string>;
collectionMixins?: CollectionMixinConstructor[];
}
interface GetCollectionOptions {
namespace?: string;
dataSource?: string;
}
class CollectionManagerV2 {
@ -23,8 +23,8 @@ class CollectionManagerV2 {
constructor(options: CollectionManagerOptionsV2 = {}, app: Application);
addCollectionNamespaces(collectionNamespaces: Record<string, string>): void;
getCollectionNamespaces(): { name: string; title: string }[];
addDataSources(dataSources: Record<string, string>): void;
getDataSources(): { name: string; title: string }[];
addCollectionTemplates(templateClasses: (typeof CollectionTemplateBase)[]): void;
getCollectionTemplates(): CollectionTemplateBase[];
@ -173,7 +173,7 @@ interface CollectionManagerOptionsV2 {
collectionTemplates?: (typeof CollectionTemplateBase)[];
fieldInterfaces?: (typeof CollectionFieldInterfaceBase)[];
fieldGroups?: Record<string, { label: string; order?: number }>;
collectionNamespaces?: Record<string, string>;
dataSources?: Record<string, string>;
collectionMixins?: CollectionMixinConstructor[];
}
```
@ -224,7 +224,7 @@ const app = new Application({
collections: [userCollectionOptions],
collectionTemplates: [TreeCollectionTemplate],
fieldInterfaces: [CheckboxFieldInterface],
collectionNamespaces: {
dataSources: {
"db2": "DB2"
},
fieldGroups: {
@ -241,11 +241,11 @@ const app = new Application({
2. `collections` 如果是一个对象,则 Key 为命名空间名称Value 为数据表数组;如果是数组,则会添加到默认命名空间。例如:
```tsx | pure
import { DEFAULT_COLLECTION_NAMESPACE_NAME } from '@nocobase/client';
import { DEFAULT_DATA_SOURCE_NAME } from '@nocobase/client';
const collectionManager = new CollectionManager({
collections: {
[DEFAULT_COLLECTION_NAMESPACE_NAME]: [postCollection],
[DEFAULT_DATA_SOURCE_NAME]: [postCollection],
"db2": [userCollection],
}
})
@ -253,7 +253,7 @@ const collectionManager = new CollectionManager({
```tsx | pure
import { DEFAULT_COLLECTION_NAMESPACE_NAME } from '@nocobase/client';
import { DEFAULT_DATA_SOURCE_NAME } from '@nocobase/client';
const collectionManager = new CollectionManager({
collections: [userCollection]
@ -262,7 +262,7 @@ const collectionManager = new CollectionManager({
// 等同于
const collectionManager = new CollectionManager({
collections: {
[DEFAULT_COLLECTION_NAMESPACE_NAME]: [userCollection]
[DEFAULT_DATA_SOURCE_NAME]: [userCollection]
}
})
```
@ -274,7 +274,7 @@ import { Plugin } from '@nocobase/client';
class MyPlugin extends Plugin {
async load() {
this.app.collectionManager.addCollectionNamespaces({
this.app.collectionManager.addDataSources({
"db2": "DB2"
});
@ -286,7 +286,7 @@ class MyPlugin extends Plugin {
## 实例方法
### cm.addCollectionNamespaces(collectionNamespaces)
### cm.addDataSources(dataSources)
添加数据表命名空间。
@ -294,7 +294,7 @@ class MyPlugin extends Plugin {
```tsx | pure
class CollectionManagerV2 {
addCollectionNamespaces(collectionNamespaces: Record<string, string>): void;
addDataSources(dataSources: Record<string, string>): void;
}
```
@ -305,14 +305,14 @@ import { Plugin } from '@nocobase/client';
class MyPlugin extends Plugin {
async load() {
this.app.collectionManager.addCollectionNamespaces({
this.app.collectionManager.addDataSources({
"db2": "DB2"
});
}
}
```
### cm.getCollectionNamespaces()
### cm.getDataSources()
获取数据表命名空间。
@ -320,14 +320,14 @@ class MyPlugin extends Plugin {
```tsx | pure
class CollectionManagerV2 {
getCollectionNamespaces(): { name: string; title: string }[];
getDataSources(): { name: string; title: string }[];
}
```
- 示例
```tsx | pure
collectionManager.getCollectionNamespaces(); // [ { name: 'main', title: '主数据源' }, { name: 'db2', title: 'DB2' }]
collectionManager.getDataSources(); // [ { name: 'main', title: '主数据源' }, { name: 'db2', title: 'DB2' }]
```
### cm.addCollectionTemplates(templates)

View File

@ -11,7 +11,7 @@
```tsx | pure
interface CollectionProviderProps {
name: string;
namespace?: string;
dataSource?: string;
children?: ReactNode;
}
```

View File

@ -55,7 +55,7 @@ const usersCollection = new CollectionV2({
export interface CollectionOptionsV2 {
name: string;
title?: string;
namespace?: string;
dataSource?: string;
isLocal?: boolean;
/**
* Used for @nocobase/plugin-duplicator

View File

@ -11,7 +11,7 @@ import { useResourceActionContext } from '../collection-manager/ResourceActionPr
import { useRecord } from '../record-provider';
import { SchemaComponentOptions, useDesignable } from '../schema-component';
import { useApp } from '../application';
import { useCollectionNamespace } from '../block-provider/BlockProvider';
import { useDataSourceName } from '../block-provider/BlockProvider';
export const ACLContext = createContext<any>({});
@ -93,9 +93,9 @@ export const ACLActionParamsContext = createContext<any>({});
export const useACLRolesCheck = () => {
const ctx = useContext(ACLContext);
const ns = useCollectionNamespace();
const dataSourceName = useDataSourceName();
const { dataSources: dataSourcesAcl } = ctx?.data?.meta || {};
const data = { ...ctx?.data?.data, ...omit(dataSourcesAcl?.[ns], 'snippets') };
const data = { ...ctx?.data?.data, ...omit(dataSourcesAcl?.[dataSourceName], 'snippets') };
const getActionAlias = (actionPath: string) => {
const actionName = actionPath.split(':').pop();
return data?.actionAlias?.[actionName] || actionName;

View File

@ -6,23 +6,23 @@ import { useCollectionManagerV2 } from './CollectionManagerProvider';
import { DeletedPlaceholder } from './DeletedPlaceholder';
export interface AssociationProviderProps {
namespace?: string;
dataSource?: string;
name: string;
children?: ReactNode;
}
export const AssociationProviderV2: FC<AssociationProviderProps> = (props) => {
const { name, namespace, children } = props;
const { name, dataSource, children } = props;
const collectionManager = useCollectionManagerV2();
const collectionName = collectionManager.getCollectionName(name, { namespace });
const collectionName = collectionManager.getCollectionName(name, { dataSource });
if (!collectionName) return <DeletedPlaceholder type="Collection" name={collectionName} />;
return (
<CollectionProviderV2 name={name.split('.')[0]} namespace={namespace}>
<CollectionProviderV2 name={name.split('.')[0]} dataSource={dataSource}>
<CollectionFieldProviderV2 name={name}>
<CollectionProviderV2 name={collectionName} namespace={namespace}>
<CollectionProviderV2 name={collectionName} dataSource={dataSource}>
{children}
</CollectionProviderV2>
</CollectionFieldProviderV2>

View File

@ -20,7 +20,7 @@ export interface CollectionFieldOptionsV2 {
export interface CollectionOptionsV2 {
name: string;
title?: string;
namespace?: string;
dataSource?: string;
isLocal?: boolean;
/**
* Used for @nocobase/plugin-duplicator

View File

@ -3,7 +3,6 @@ import { CollectionTemplateBase } from './CollectionTemplate';
import { CollectionFieldOptionsV2, CollectionOptionsV2, CollectionV2 } from './Collection';
import type { Application } from '../Application';
import { SchemaKey } from '@formily/react';
import { merge } from 'lodash';
export type CollectionMixinConstructor<T = {}> = new (...args: any[]) => T;
@ -47,45 +46,46 @@ const defaultCollectionTransform = (collection: CollectionOptionsV2, app: Applic
};
};
export const DEFAULT_COLLECTION_NAMESPACE_TITLE = '{{t("main")}}';
export const DEFAULT_COLLECTION_NAMESPACE_NAME = 'main';
export const DEFAULT_DATA_SOURCE_TITLE = '{{t("main")}}';
export const DEFAULT_DATA_SOURCE_NAME = 'main';
export interface GetCollectionOptions {
namespace?: string;
dataSource?: string;
}
type NamespacesType = Record<string, string>;
interface DataSource {
name: string;
description: string;
collections?: CollectionOptionsV2[];
[key: string]: any;
}
type DataSourceName = string;
export interface CollectionManagerOptionsV2 {
collections?: CollectionOptionsV2[] | Record<string, CollectionOptionsV2[]>;
collections?: CollectionOptionsV2[];
collectionTemplates?: (typeof CollectionTemplateBase)[];
fieldInterfaces?: (typeof CollectionFieldInterfaceBase)[];
fieldGroups?: Record<string, { label: string; order?: number }>;
collectionNamespaces?: Record<string, string>;
collectionMixins?: CollectionMixinConstructor[];
}
type ThirdResource = (
...args: any[]
) => Promise<{ name: string; description: string; collections: CollectionOptionsV2[] }[]>;
type ThirdDataResourceFn = () => Promise<DataSource[]>;
type MainDataSOurceFn = () => Promise<CollectionOptionsV2[]>;
type ReloadCallback = (collections: CollectionOptionsV2[]) => void;
export class CollectionManagerV2 {
public app: Application;
protected collections: Record<string, Record<string, CollectionV2>> = {};
protected collections: Record<string, Record<DataSourceName, CollectionV2>> = {};
protected collectionTemplateInstances: Record<string, CollectionTemplateBase> = {};
protected fieldInterfaceInstances: Record<string, CollectionFieldInterfaceBase> = {};
protected collectionMixins: CollectionMixinConstructor[] = [];
protected collectionNamespaces: NamespacesType = {
[DEFAULT_COLLECTION_NAMESPACE_NAME]: DEFAULT_COLLECTION_NAMESPACE_NAME,
};
protected dataSourceMap: Record<DataSourceName, Omit<DataSource, 'collections'>> = {};
protected collectionFieldGroups: Record<string, { label: string; order?: number }> = {};
protected mainResource: (...args: any[]) => Promise<CollectionOptionsV2[]>;
protected thirdResources: Record<string, ThirdResource> = {};
protected reloadCallbacks: {
[key: string]: ((collections: CollectionOptionsV2[]) => void)[];
} = {};
protected mainDataSourceFn: MainDataSOurceFn;
protected thirdDataSourceFn: ThirdDataResourceFn;
protected reloadCallbacks: Record<string, ReloadCallback[]> = {};
protected collectionArr: Record<string, CollectionV2[]> = {};
protected sourceNamespaceMap: Record<string, string[]> = {};
protected options: CollectionManagerOptionsV2 = {};
constructor(options: CollectionManagerOptionsV2 = {}, app: Application) {
@ -95,26 +95,21 @@ export class CollectionManagerV2 {
}
private init(options: CollectionManagerOptionsV2) {
this.initDataSourceMap();
this.collectionMixins.push(...(options.collectionMixins || []));
this.addCollectionTemplates(options.collectionTemplates || []);
this.addFieldInterfaces(options.fieldInterfaces || []);
this.addFieldGroups(options.fieldGroups || {});
this.addCollectionNamespaces(options.collectionNamespaces || {});
if (Array.isArray(options.collections)) {
this.addCollections(options.collections);
} else {
Object.keys(options.collections || {}).forEach((namespace) => {
this.addCollections(options.collections[namespace], { namespace });
});
}
this.addCollections(options.collections || []);
}
private checkNamespace(namespace: string) {
if (!this.collectionNamespaces[namespace]) {
throw new Error(
`[@nocobase/client]: CollectionManager "${namespace}" does not exist in namespace, you should call collectionManager.addNamespaces() to add it`,
);
}
private initDataSourceMap() {
this.dataSourceMap = {
[DEFAULT_DATA_SOURCE_NAME]: {
name: DEFAULT_DATA_SOURCE_NAME,
description: DEFAULT_DATA_SOURCE_TITLE,
},
};
}
// collection mixins
@ -124,17 +119,16 @@ export class CollectionManagerV2 {
this.collectionMixins.push(...newMixins);
// 重新添加数据表
Object.keys(this.collections).forEach((namespace) => {
const collections = this.getCollections({ namespace });
this.addCollections(collections, { namespace });
Object.keys(this.collections).forEach((dataSource) => {
const collections = this.getCollections({ dataSource }).map((item) => item.getOptions());
this.addCollections(collections, { dataSource });
});
}
// collections
addCollections(collections: CollectionOptionsV2[], options: GetCollectionOptions = {}) {
const { namespace = DEFAULT_COLLECTION_NAMESPACE_NAME } = options;
this.checkNamespace(namespace);
this.collectionArr[namespace] = undefined;
const { dataSource = DEFAULT_DATA_SOURCE_NAME } = options;
this.collectionArr[dataSource] = undefined;
collections
.map((collection) => {
@ -142,46 +136,46 @@ export class CollectionManagerV2 {
const Cls = collectionTemplateInstance?.Collection || CollectionV2;
const transform = collectionTemplateInstance?.transform || defaultCollectionTransform;
const transformedCollection = transform(collection, this.app);
const instance = new Cls({ ...transformedCollection, namespace: namespace }, this.app, this);
const instance = new Cls({ ...transformedCollection, dataSource }, this.app, this);
applyMixins(instance, this.collectionMixins);
return instance;
})
.forEach((collectionInstance) => {
if (!this.collections[namespace]) {
this.collections[namespace] = {};
if (!this.collections[dataSource]) {
this.collections[dataSource] = {};
}
this.collections[namespace][collectionInstance.name] = collectionInstance;
this.collections[dataSource][collectionInstance.name] = collectionInstance;
});
}
setCollections(collections: CollectionOptionsV2[], options: GetCollectionOptions = {}) {
const { namespace = DEFAULT_COLLECTION_NAMESPACE_NAME } = options;
this.checkNamespace(namespace);
this.collections[namespace] = {};
const { dataSource = DEFAULT_DATA_SOURCE_NAME } = options;
this.collections[dataSource] = {};
this.addCollections(collections, options);
}
getAllCollections(
predicate?: (collection: CollectionV2) => boolean,
): { nsName: string; nsTitle: string; source?: string; collections: CollectionV2[] }[] {
return Object.keys(this.collectionNamespaces).reduce<
{ nsName: string; nsTitle: string; source?: string; collections: CollectionV2[] }[]
>((acc, namespace) => {
acc.push({
nsName: namespace,
nsTitle: this.collectionNamespaces[namespace],
collections: this.getCollections({ predicate, namespace }),
});
return acc;
}, []);
): (Omit<DataSource, 'collections'> & { collections: CollectionV2[] })[] {
return Object.keys(this.dataSourceMap).reduce<Omit<DataSource, 'collections'> & { collections: CollectionV2[] }[]>(
(acc, dataSourceName) => {
const dataSource = this.dataSourceMap[dataSourceName];
acc.push({
...dataSource,
collections: this.getCollections({ predicate, dataSource: dataSourceName }),
});
return acc;
},
[],
);
}
getCollections(options: { predicate?: (collection: CollectionV2) => boolean; namespace?: string } = {}) {
const { namespace = DEFAULT_COLLECTION_NAMESPACE_NAME, predicate } = options;
if (!this.collectionArr[namespace]?.length) {
this.collectionArr[namespace] = Object.values(this.collections[namespace] || {});
getCollections(options: { predicate?: (collection: CollectionV2) => boolean; dataSource?: string } = {}) {
const { dataSource = DEFAULT_DATA_SOURCE_NAME, predicate } = options;
if (!this.collectionArr[dataSource]?.length) {
this.collectionArr[dataSource] = Object.values(this.collections[dataSource] || {});
}
if (predicate) {
return this.collectionArr[namespace].filter(predicate);
return this.collectionArr[dataSource].filter(predicate);
}
return this.collectionArr[namespace];
return this.collectionArr[dataSource];
}
/**
*
@ -191,15 +185,15 @@ export class CollectionManagerV2 {
* getCollection('a.b.c'); // 获取 a 表的 b 字段的关联表,然后 b.target 表对应的 c 字段的关联表
*/
getCollection<Mixins = {}>(path: string, options: GetCollectionOptions = {}): (Mixins & CollectionV2) | undefined {
const { namespace = DEFAULT_COLLECTION_NAMESPACE_NAME } = options;
const { dataSource = DEFAULT_DATA_SOURCE_NAME } = options;
if (!path || typeof path !== 'string') return undefined;
if (path.split('.').length > 1) {
// 获取到关联字段
const associationField = this.getCollectionField(path);
return this.getCollection(associationField.target, { namespace });
return this.getCollection(associationField.target, { dataSource });
}
return this.collections[namespace]?.[path] as Mixins & CollectionV2;
return this.collections[dataSource]?.[path] as Mixins & CollectionV2;
}
getCollectionName(path: string, options: GetCollectionOptions = {}): string | undefined {
const res = this.getCollection(path, options);
@ -222,23 +216,20 @@ export class CollectionManagerV2 {
return;
}
const [collectionName, ...fieldNames] = String(path).split('.');
const { namespace = DEFAULT_COLLECTION_NAMESPACE_NAME } = options || {};
const collection = this.getCollection(collectionName, { namespace });
const { dataSource = DEFAULT_DATA_SOURCE_NAME } = options || {};
const collection = this.getCollection(collectionName, { dataSource });
if (!collection) {
return;
}
return collection.getField(fieldNames.join('.'));
}
// collectionNamespaces
addCollectionNamespaces(collectionNamespaces: NamespacesType) {
this.collectionNamespaces = merge(this.collectionNamespaces, collectionNamespaces);
// dataSources
getDataSources() {
return Object.values(this.dataSourceMap);
}
setCollectionNamespaces(collectionNamespaces: NamespacesType) {
Object.assign(this.collectionNamespaces, collectionNamespaces);
}
getCollectionNamespaces() {
return this.collectionNamespaces;
getDataSource(name: string) {
return this.dataSourceMap[name];
}
// CollectionTemplates
@ -252,20 +243,20 @@ export class CollectionManagerV2 {
// 重新添加数据表
const reAddCollections = Object.keys(this.collections).reduce<Record<string, CollectionOptionsV2[]>>(
(acc, namespace) => {
acc[namespace] = this.getCollections({
(acc, dataSource) => {
acc[dataSource] = this.getCollections({
predicate: (collection) => {
return newCollectionTemplateInstances[collection.template];
},
namespace,
dataSource,
}).map((collection) => collection.getOptions());
return acc;
},
{},
);
Object.keys(reAddCollections).forEach((namespace) => {
this.addCollections(reAddCollections[namespace], { namespace });
Object.keys(reAddCollections).forEach((dataSource) => {
this.addCollections(reAddCollections[dataSource], { dataSource });
});
}
getCollectionTemplates() {
@ -302,58 +293,50 @@ export class CollectionManagerV2 {
return this.collectionFieldGroups[name];
}
setMainResource(fn: (...args: any[]) => Promise<CollectionOptionsV2[]>) {
this.mainResource = fn;
setMainDataSource(fn: MainDataSOurceFn) {
this.mainDataSourceFn = fn;
}
addThirdResource(name: string, fn: ThirdResource) {
this.thirdResources[name] = fn;
setThirdDataSource(fn: ThirdDataResourceFn) {
this.thirdDataSourceFn = fn;
}
async reloadMain(callback?: (collections?: CollectionOptionsV2[]) => void) {
const collections = await this.mainResource();
async reloadMain(callback?: ReloadCallback) {
const collections = await this.mainDataSourceFn();
this.setCollections(collections);
callback && callback(collections);
this.reloadCallbacks[DEFAULT_COLLECTION_NAMESPACE_NAME]?.forEach((cb) => cb(collections));
this.reloadCallbacks[DEFAULT_DATA_SOURCE_NAME]?.forEach((cb) => cb(collections));
}
async reloadThirdResource(sourceName: string) {
const thirdResource = this.thirdResources[sourceName];
const oldNamespaces = this.sourceNamespaceMap[sourceName] || [];
const data = await thirdResource();
oldNamespaces.forEach((namespace) => {
delete this.collectionNamespaces[namespace];
async reloadThirdDataSource(callback?: () => void) {
if (!this.thirdDataSourceFn) return;
const data = await this.thirdDataSourceFn();
this.initDataSourceMap();
data.forEach((dataSource) => {
const { collections: _unUse, ...rest } = dataSource;
this.dataSourceMap[dataSource.name] = rest;
});
this.sourceNamespaceMap[sourceName] = data.map(({ name }) => name);
data.forEach(({ name, description, collections }) => {
this.addCollectionNamespaces({ [name]: description });
this.setCollections(collections, { namespace: name });
data.forEach(({ name, collections, ...others }) => {
this.dataSourceMap[name] = { ...others, name };
this.setCollections(collections, { dataSource: name });
this.reloadCallbacks[name]?.forEach((cb) => cb(collections));
});
}
async reloadThirdResources(callback?: () => void) {
await Promise.all(
Object.keys(this.thirdResources).map((thirdResourceName) => this.reloadThirdResource(thirdResourceName)),
);
callback && callback();
}
async reloadAll(callback?: () => void) {
await this.reloadMain();
await this.reloadThirdResources();
await this.reloadThirdDataSource();
callback && callback();
}
addReloadCallback(
callback: (collections: CollectionOptionsV2[]) => void,
namespace = DEFAULT_COLLECTION_NAMESPACE_NAME,
) {
if (!this.reloadCallbacks[namespace]) {
this.reloadCallbacks[namespace] = [];
addReloadCallback(callback: ReloadCallback, dataSource = DEFAULT_DATA_SOURCE_NAME) {
if (!this.reloadCallbacks[dataSource]) {
this.reloadCallbacks[dataSource] = [];
}
this.reloadCallbacks[namespace].push(callback);
this.reloadCallbacks[dataSource].push(callback);
}
private getInheritData() {
@ -362,11 +345,10 @@ export class CollectionManagerV2 {
collectionTemplateInstances: this.collectionTemplateInstances,
fieldInterfaceInstances: this.fieldInterfaceInstances,
collectionMixins: this.collectionMixins,
collectionNamespaces: this.collectionNamespaces,
dataSourceMap: this.dataSourceMap,
collectionFieldGroups: this.collectionFieldGroups,
mainResource: this.mainResource,
thirdResources: this.thirdResources,
sourceNamespaceMap: this.sourceNamespaceMap,
mainDataSourceFn: this.mainDataSourceFn,
thirdDataSourceFn: this.thirdDataSourceFn,
reloadCallbacks: this.reloadCallbacks,
collectionArr: this.collectionArr,
options: this.options,

View File

@ -1,5 +1,5 @@
import React, { FC, ReactNode, createContext, useContext, useMemo } from 'react';
import type { CollectionManagerV2, GetCollectionOptions } from './CollectionManager';
import type { CollectionManagerV2 } from './CollectionManager';
import type { CollectionV2 } from './Collection';
export const CollectionManagerContextV2 = createContext<CollectionManagerV2>(null);
@ -23,7 +23,7 @@ export function useCollectionManagerV2() {
export const useCollectionsV2 = (options?: {
predicate?: (collection: CollectionV2) => boolean;
namespace?: string;
dataSources?: string;
}) => {
const collectionManager = useCollectionManagerV2();
const collections = useMemo(() => collectionManager.getCollections(options), [collectionManager, options]);

View File

@ -11,15 +11,15 @@ export interface CollectionProviderProps {
name: string;
children?: ReactNode;
allowNull?: boolean;
namespace?: string;
dataSource?: string;
}
export const CollectionProviderV2: FC<CollectionProviderProps> = (props) => {
const { name, children, allowNull, namespace } = props;
const { name, children, allowNull, dataSource } = props;
const collectionManager = useCollectionManagerV2();
const collection = useMemo(
() => collectionManager.getCollection(name, { namespace }),
[collectionManager, name, namespace],
() => collectionManager.getCollection(name, { dataSource }),
[collectionManager, name, dataSource],
);
if (!collection && allowNull) return <>{props.children}</>;
if (!collection && !allowNull) return <DeletedPlaceholder type="Collection" name={name} />;

View File

@ -7,7 +7,7 @@ export const DeletedPlaceholder: FC<{ type: string; name?: string | number }> =
const { designable } = useDesignable();
const { t } = useTranslation();
if (!name) {
console.warn('DeletedPlaceholder: name is required');
console.error(`DeletedPlaceholder: ${type} name is required`);
return null;
}
if (!designable && process.env.NODE_ENV !== 'development') return null;

View File

@ -8,7 +8,7 @@ import template from 'lodash/template';
import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import {
DEFAULT_COLLECTION_NAMESPACE_NAME,
DEFAULT_DATA_SOURCE_NAME,
TableFieldResource,
WithoutTableFieldResource,
useAPIClient,
@ -46,7 +46,7 @@ interface UseResourceProps {
association?: any;
useSourceId?: any;
collection?: any;
namespace?: any;
dataSource?: any;
block?: any;
}
@ -61,7 +61,7 @@ export const useAssociation = (props) => {
};
const useResource = (props: UseResourceProps) => {
const { block, collection, namespace, resource, useSourceId } = props;
const { block, collection, dataSource, resource, useSourceId } = props;
const record = useRecord();
const api = useAPIClient();
const { fieldSchema } = useActionContext();
@ -72,10 +72,10 @@ const useResource = (props: UseResourceProps) => {
const withoutTableFieldResource = useContext(WithoutTableFieldResource);
const __parent = useContext(BlockRequestContext);
const headers = useMemo(() => {
if (namespace && namespace !== DEFAULT_COLLECTION_NAMESPACE_NAME) {
return { 'x-connection': namespace };
if (dataSource && dataSource !== DEFAULT_DATA_SOURCE_NAME) {
return { 'x-connection': dataSource };
}
}, [namespace]);
}, [dataSource]);
if (block === 'TableField') {
const options = {
@ -303,9 +303,9 @@ export const useBlockContext = () => {
return useContext(BlockContext);
};
export const CollectionNamespace = createContext<string>(undefined);
export const useCollectionNamespace = () => {
return useContext(CollectionNamespace);
export const DataSourceName = createContext<string>(undefined);
export const useDataSourceName = () => {
return useContext(DataSourceName);
};
export const BlockProvider = (props: {
@ -313,13 +313,13 @@ export const BlockProvider = (props: {
resource: any;
collection?: any;
association?: any;
namespace?: string;
dataSource?: string;
params?: any;
children?: any;
}) => {
const { collection, association, name, namespace } = props;
const { collection, association, name, dataSource } = props;
const resource = useResource(props);
const { getAssociationAppends } = useAssociationNames(namespace);
const { getAssociationAppends } = useAssociationNames(dataSource);
const { appends, updateAssociationValues } = getAssociationAppends();
const params = useMemo(() => {
if (!props.params?.['appends']) {
@ -331,7 +331,7 @@ export const BlockProvider = (props: {
return (
<BlockContext.Provider value={blockValue}>
<CollectionNamespace.Provider value={namespace}>
<DataSourceName.Provider value={dataSource}>
<MaybeCollectionProvider collection={collection}>
<BlockAssociationContext.Provider value={association}>
<BlockResourceContext.Provider value={resource}>
@ -345,7 +345,7 @@ export const BlockProvider = (props: {
</BlockResourceContext.Provider>
</BlockAssociationContext.Provider>
</MaybeCollectionProvider>
</CollectionNamespace.Provider>
</DataSourceName.Provider>
</BlockContext.Provider>
);
};

View File

@ -77,7 +77,7 @@ export const TableBlockProvider = (props) => {
const resourceName = props.resource;
const params = useMemo(() => ({ ...props.params }), [props.params]);
const fieldSchema = useFieldSchema();
const { getCollection, getCollectionField } = useCollectionManager(props.namespace);
const { getCollection, getCollectionField } = useCollectionManager(props.dataSource);
const record = useRecord();
const collection = getCollection(props.collection);
const { treeTable, dragSortBy } = fieldSchema?.['x-decorator-props'] || {};

View File

@ -1296,10 +1296,10 @@ export function getAssociationPath(str) {
return str;
}
export const useAssociationNames = (namespace?: string) => {
export const useAssociationNames = (dataSource?: string) => {
let updateAssociationValues = new Set([]);
let appends = new Set([]);
const { getCollectionJoinField, getCollection } = useCollectionManager(namespace);
const { getCollectionJoinField, getCollection } = useCollectionManager(dataSource);
const fieldSchema = useFieldSchema();
const _getAssociationAppends = (schema, str) => {
schema.reduceProperties((pre, s) => {

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 { useCollectionNamespace } from '../block-provider/BlockProvider';
import { useDataSourceName } from '../block-provider/BlockProvider';
function getCollectionName(name?: string | CollectionOptions): string {
if (!name) return undefined;
@ -17,16 +17,16 @@ export const CollectionProvider: FC<{
collection?: CollectionOptions | string;
allowNull?: boolean;
children?: ReactNode;
namespace?: string;
}> = ({ children, allowNull, name, namespace, collection }) => {
dataSource?: string;
}> = ({ children, allowNull, name, dataSource, collection }) => {
const collectionName = getCollectionName(name || collection);
const collectionNamespace = useCollectionNamespace();
const namespaceValue = namespace || collectionNamespace || undefined;
const dataSourceName = useDataSourceName();
const dataSourceValue = dataSource || dataSourceName || undefined;
const cm = useCollectionManagerV2();
const hasCollection = cm.getCollection(collectionName, { namespace: namespaceValue });
const hasCollection = cm.getCollection(collectionName, { dataSource: dataSourceValue });
if (hasCollection || (allowNull && !collection))
return (
<CollectionProviderV2 allowNull={allowNull} name={collectionName} namespace={namespaceValue}>
<CollectionProviderV2 allowNull={allowNull} name={collectionName} dataSource={dataSourceValue}>
{children}
</CollectionProviderV2>
);

View File

@ -57,7 +57,7 @@ export class CollectionPlugin extends Plugin {
this.addFieldInterfaces();
this.addFieldGroups();
this.collectionManager.setMainResource(this.reloadCollections.bind(this));
this.collectionManager.setMainDataSource(this.reloadCollections.bind(this));
}
addFieldGroups() {

View File

@ -6,12 +6,12 @@ import { CollectionFieldOptions, CollectionOptions } from '../types';
import { useCollectionManagerV2 } from '../../application';
import { InheritanceCollectionMixin } from '../mixins/InheritanceCollectionMixin';
import { uid } from '@formily/shared';
import { useCollectionNamespace } from '../../block-provider/BlockProvider';
import { useDataSourceName } from '../../block-provider/BlockProvider';
export const useCollectionManager = (namespace?: string) => {
export const useCollectionManager = (dataSourceName?: string) => {
const cm = useCollectionManagerV2();
const blockNamespaceValue = useCollectionNamespace();
const namespaceValue = namespace || blockNamespaceValue || undefined;
const blockDataSourceName = useDataSourceName();
const dataSourceNameValue = dataSourceName || blockDataSourceName || undefined;
const [random, setRandom] = useState(uid());
const { refresh } = useSchemaComponentContext();
const interfaces = useMemo(() => cm?.getFieldInterfaces(), [cm, random]);
@ -46,7 +46,7 @@ export const useCollectionManager = (namespace?: string) => {
(name: string, customNamespace?: string) => {
return (
cm
?.getCollection<InheritanceCollectionMixin>(name, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(name, { dataSource: customNamespace || dataSourceNameValue })
?.getInheritedFields() || []
);
},
@ -59,7 +59,7 @@ export const useCollectionManager = (namespace?: string) => {
return (
cm
?.getCollection<InheritanceCollectionMixin>(typeof name === 'object' ? name.name : name, {
namespace: customNamespace || namespaceValue,
dataSource: customNamespace || dataSourceNameValue,
})
?.getAllFields() || []
);
@ -69,7 +69,7 @@ export const useCollectionManager = (namespace?: string) => {
const getCollectionField = useCallback(
(name: string, customNamespace?: string) => {
if (!name || name.split('.').length < 2) return;
return cm?.getCollectionField(name, { namespace: customNamespace || namespaceValue });
return cm?.getCollectionField(name, { dataSource: customNamespace || dataSourceNameValue });
},
[cm],
);
@ -78,7 +78,7 @@ export const useCollectionManager = (namespace?: string) => {
if (!name) return [];
return (
cm
?.getCollection<InheritanceCollectionMixin>(name, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(name, { dataSource: customNamespace || dataSourceNameValue })
?.getParentCollectionsName() || []
);
},
@ -90,7 +90,7 @@ export const useCollectionManager = (namespace?: string) => {
if (!name) return [];
return (
cm
?.getCollection<InheritanceCollectionMixin>(name, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(name, { dataSource: customNamespace || dataSourceNameValue })
?.getChildrenCollections(isSupportView) || []
);
},
@ -101,7 +101,7 @@ export const useCollectionManager = (namespace?: string) => {
if (!name) return [];
return (
cm
?.getCollection<InheritanceCollectionMixin>(name, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(name, { dataSource: customNamespace || dataSourceNameValue })
?.getCurrentFields() || []
);
},
@ -114,7 +114,7 @@ export const useCollectionManager = (namespace?: string) => {
collectionName: string,
type: string | string[] = 'string',
opts?: {
namespace?: string;
dataSource?: string;
cached?: Record<string, any>;
collectionNames?: string[];
/**
@ -150,7 +150,7 @@ export const useCollectionManager = (namespace?: string) => {
exceptInterfaces = [],
prefixFieldValue = '',
usePrefix = false,
namespace: customNamespace,
dataSource: customDataSourceNameValue,
} = opts || {};
if (collectionNames.length - 1 > maxDepth) {
@ -165,7 +165,7 @@ export const useCollectionManager = (namespace?: string) => {
if (typeof type === 'string') {
type = [type];
}
const fields = getCollectionFields(collectionName, customNamespace);
const fields = getCollectionFields(collectionName, customDataSourceNameValue);
const options = fields
?.filter(
(field) =>
@ -189,7 +189,7 @@ export const useCollectionManager = (namespace?: string) => {
: getCollectionFieldsOptions(field.target, type, {
...opts,
cached,
namespace: customNamespace,
dataSource: customDataSourceNameValue,
collectionNames: [...collectionNames, field.target],
prefixFieldValue: usePrefix
? prefixFieldValue
@ -215,7 +215,7 @@ export const useCollectionManager = (namespace?: string) => {
const getCollection = useCallback(
(name: any, customNamespace?: string): CollectionOptions => {
return cm?.getCollection(name, { namespace: customNamespace || namespaceValue });
return cm?.getCollection(name, { dataSource: customNamespace || dataSourceNameValue });
},
[cm],
);
@ -224,7 +224,9 @@ export const useCollectionManager = (namespace?: string) => {
const getAllCollectionsInheritChain = useCallback(
(collectionName: string, customNamespace?: string) => {
return cm
?.getCollection<InheritanceCollectionMixin>(collectionName, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(collectionName, {
dataSource: customNamespace || dataSourceNameValue,
})
?.getAllCollectionsInheritChain();
},
[cm],
@ -238,7 +240,9 @@ export const useCollectionManager = (namespace?: string) => {
const getInheritCollectionsChain = useCallback(
(collectionName: string, customNamespace?: string) => () => {
return cm
?.getCollection<InheritanceCollectionMixin>(collectionName, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(collectionName, {
dataSource: customNamespace || dataSourceNameValue,
})
?.getInheritCollectionsChain();
},
[cm],
@ -258,7 +262,9 @@ export const useCollectionManager = (namespace?: string) => {
const getParentCollectionFields = (parentCollection, currentCollection, customNamespace?: string) => {
return cm
?.getCollection<InheritanceCollectionMixin>(currentCollection, { namespace: customNamespace || namespaceValue })
?.getCollection<InheritanceCollectionMixin>(currentCollection, {
dataSource: customNamespace || dataSourceNameValue,
})
?.getParentCollectionFields(parentCollection);
};

View File

@ -26,7 +26,7 @@ export const CreateFormBlockInitializer = () => {
const blockSchema = createFormBlockSchema({
actionInitializers: 'CreateFormActionInitializers',
association,
namespace: collection.namespace,
dataSource: collection.dataSource,
collection: collection.name,
template: s,
});
@ -42,7 +42,7 @@ export const CreateFormBlockInitializer = () => {
createFormBlockSchema({
actionInitializers: 'CreateFormActionInitializers',
association,
namespace: collection.namespace,
dataSource: collection.dataSource,
collection: collection.name,
}),
);

View File

@ -289,7 +289,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
insert(
createBlockSchema({
collection: item.collectionName || item.name,
namespace: item.namespace,
dataSource: item.dataSource,
isCusomeizeCreate,
}),
);

View File

@ -15,10 +15,10 @@ export const DetailsBlockInitializer = () => {
icon={<TableOutlined />}
componentType={'Details'}
onCreateBlockSchema={async ({ item }) => {
const collection = getCollection(item.name, item.namespace);
const collection = getCollection(item.name, item.dataSource);
const schema = createDetailsBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
rowKey: collection.filterTargetKey || 'id',
actionInitializers:
(collection.template !== 'view' || collection?.writableView) &&

View File

@ -17,7 +17,7 @@ export const FilterCollapseBlockInitializer = () => {
isItem={itemConfig?.name === 'filterCollapseBlockInTableSelector'}
onCreateBlockSchema={async ({ item }) => {
const schema = createCollapseBlockSchema({
namespace: item.namespace,
dataSource: item.dataSource,
collection: item.collectionName || item.name,
// 与数据区块做区分
blockType: 'filter',

View File

@ -16,7 +16,7 @@ export const FilterFormBlockInitializer = () => {
templateWrap={(templateSchema, { item }) => {
const s = createFilterFormBlockSchema({
template: templateSchema,
namespace: item.namespace,
dataSource: item.dataSource,
collection: item.collectionName,
});
if (item.template && item.mode === 'reference') {

View File

@ -15,7 +15,7 @@ export const FormBlockInitializer = () => {
templateWrap={(templateSchema, { item }) => {
const s = createFormBlockSchema({
isCusomeizeCreate,
namespace: item.namespace,
dataSource: item.dataSource,
template: templateSchema,
collection: item.name,
});

View File

@ -15,10 +15,10 @@ export const GridCardBlockInitializer = () => {
icon={<OrderedListOutlined />}
componentType={'GridCard'}
onCreateBlockSchema={async ({ item }) => {
const collection = getCollection(item.name, item.namespace);
const collection = getCollection(item.name, item.dataSource);
const schema = createGridCardBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
rowKey: collection.filterTargetKey || 'id',
});
insert(schema);

View File

@ -15,10 +15,10 @@ export const ListBlockInitializer = () => {
icon={<OrderedListOutlined />}
componentType={'List'}
onCreateBlockSchema={async ({ item }) => {
const collection = getCollection(item.name, item.namespace);
const collection = getCollection(item.name, item.dataSource);
const schema = createListBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
rowKey: collection.filterTargetKey || 'id',
});
insert(schema);

View File

@ -28,7 +28,7 @@ export const RecordAssociationBlockInitializer = () => {
createTableBlockSchema({
rowKey: collection.filterTargetKey,
collection: field.target,
namespace: collection.namespace,
dataSource: collection.dataSource,
resource,
association: resource,
}),

View File

@ -28,7 +28,7 @@ export const RecordAssociationDetailsBlockInitializer = () => {
createDetailsBlockSchema({
collection: field.target,
resource,
namespace: collection.namespace,
dataSource: collection.dataSource,
association: resource,
rowKey: collection.filterTargetKey || 'id',
}),

View File

@ -31,7 +31,7 @@ export const RecordAssociationFormBlockInitializer = () => {
if (item.template.componentName === 'FormItem') {
const blockSchema = createFormBlockSchema({
collection: collectionName,
namespace: collection.namespace,
dataSource: collection.dataSource,
resource,
association: resource,
action,
@ -52,7 +52,7 @@ export const RecordAssociationFormBlockInitializer = () => {
createFormBlockSchema({
collection: collectionName,
resource,
namespace: collection.namespace,
dataSource: collection.dataSource,
association: resource,
action,
useSourceId: '{{ useSourceIdFromParentRecord }}',

View File

@ -30,7 +30,7 @@ export const RecordAssociationGridCardBlockInitializer = () => {
rowKey: collection.filterTargetKey,
collection: field.target,
resource,
namespace: collection.namespace,
dataSource: collection.dataSource,
association: resource,
}),
);

View File

@ -30,7 +30,7 @@ export const RecordAssociationListBlockInitializer = () => {
rowKey: collection.filterTargetKey,
collection: field.target,
resource,
namespace: collection.namespace,
dataSource: collection.dataSource,
association: resource,
}),
);

View File

@ -25,7 +25,7 @@ export const RecordFormBlockInitializer = () => {
const blockSchema = createFormBlockSchema({
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
action: 'get',
useSourceId: '{{ useSourceIdFromParentRecord }}',
useParams: '{{ useParamsFromRecord }}',
@ -44,7 +44,7 @@ export const RecordFormBlockInitializer = () => {
createFormBlockSchema({
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
action: 'get',
useSourceId: '{{ useSourceIdFromParentRecord }}',
useParams: '{{ useParamsFromRecord }}',

View File

@ -33,7 +33,7 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
const blockSchema = createReadPrettyFormBlockSchema({
actionInitializers,
collection: collectionName,
namespace: collection.namespace,
dataSource: collection.dataSource,
resource,
association: resource,
action: 'get',
@ -55,7 +55,7 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
collection: collectionName,
resource,
association: resource,
namespace: collection.namespace,
dataSource: collection.dataSource,
action: 'get',
useSourceId: '{{ useSourceIdFromParentRecord }}',
useParams: '{{ useParamsFromRecord }}',

View File

@ -37,7 +37,7 @@ export const RecordReadPrettyFormBlockInitializer = () => {
actionInitializers,
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
action: 'get',
useSourceId: '{{ useSourceIdFromParentRecord }}',
useParams: '{{ useParamsFromRecord }}',
@ -56,7 +56,7 @@ export const RecordReadPrettyFormBlockInitializer = () => {
actionInitializers,
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
action: 'get',
useSourceId: '{{ useSourceIdFromParentRecord }}',
useParams: '{{ useParamsFromRecord }}',

View File

@ -15,10 +15,10 @@ export const TableBlockInitializer = () => {
icon={<TableOutlined />}
componentType={'Table'}
onCreateBlockSchema={async ({ item }) => {
const collection = getCollection(item.name, item.namespace);
const collection = getCollection(item.name, item.dataSource);
const schema = createTableBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
rowKey: collection.filterTargetKey || 'id',
});
insert(schema);

View File

@ -19,7 +19,7 @@ export const TableSelectorInitializer = () => {
createTableSelectorSchema({
rowKey: collection.filterTargetKey,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
resource: collection.name,
}),
);

View File

@ -874,16 +874,16 @@ export const useCollectionDataSourceItems = (
const allCollections = cm.getAllCollections((collection) => notLocal(collection) && filter(collection));
const { getTemplatesByCollection } = useSchemaTemplateManager();
const res = useMemo(() => {
return allCollections.map(({ nsName, nsTitle, collections }) => ({
name: nsName,
label: nsTitle,
return allCollections.map(({ name, description, collections }) => ({
name: name,
label: description,
type: 'subMenu',
children: getChildrenV3({
children: getChildren({
collections,
collectionManager: cm,
componentName,
searchValue: '',
namespace: nsName,
dataSource: name,
getTemplatesByCollection,
t,
}),
@ -898,7 +898,7 @@ export const createDetailsBlockSchema = (options) => {
formItemInitializers = 'ReadPrettyFormItemInitializers',
actionInitializers = 'DetailsActionInitializers',
collection,
namespace,
dataSource,
association,
resource,
template,
@ -911,7 +911,7 @@ export const createDetailsBlockSchema = (options) => {
'x-decorator': 'DetailsBlockProvider',
'x-decorator-props': {
resource: resourceName,
namespace,
dataSource,
collection,
association,
readPretty: true,
@ -970,7 +970,7 @@ export const createListBlockSchema = (options) => {
actionInitializers = 'ListActionInitializers',
itemActionInitializers = 'ListItemActionInitializers',
collection,
namespace,
dataSource,
association,
resource,
template,
@ -984,7 +984,7 @@ export const createListBlockSchema = (options) => {
'x-decorator-props': {
resource: resourceName,
collection,
namespace,
dataSource,
association,
readPretty: true,
action: 'list',
@ -1061,7 +1061,7 @@ export const createGridCardBlockSchema = (options) => {
association,
resource,
template,
namespace,
dataSource,
...others
} = options;
const resourceName = resource || association || collection;
@ -1073,7 +1073,7 @@ export const createGridCardBlockSchema = (options) => {
resource: resourceName,
collection,
association,
namespace,
dataSource,
readPretty: true,
action: 'list',
params: {
@ -1148,7 +1148,7 @@ export const createFormBlockSchema = (options) => {
actionInitializers = 'FormActionInitializers',
collection,
resource,
namespace,
dataSource,
association,
action,
actions = {},
@ -1168,7 +1168,7 @@ export const createFormBlockSchema = (options) => {
'x-decorator-props': {
...others,
action,
namespace,
dataSource,
resource: resourceName,
collection,
association,
@ -1220,7 +1220,7 @@ export const createFilterFormBlockSchema = (options) => {
collection,
resource,
association,
namespace,
dataSource,
action,
template,
...others
@ -1233,7 +1233,7 @@ export const createFilterFormBlockSchema = (options) => {
...others,
action,
resource: resourceName,
namespace,
dataSource,
collection,
association,
},
@ -1282,7 +1282,7 @@ export const createReadPrettyFormBlockSchema = (options) => {
actionInitializers = 'ReadPrettyFormActionInitializers',
collection,
association,
namespace,
dataSource,
resource,
template,
...others
@ -1296,7 +1296,7 @@ export const createReadPrettyFormBlockSchema = (options) => {
resource: resourceName,
collection,
association,
namespace,
dataSource,
readPretty: true,
action: 'get',
useParams: '{{ useParamsFromRecord }}',
@ -1349,7 +1349,7 @@ export const createTableBlockSchema = (options) => {
tableBlockProvider,
disableTemplate,
TableBlockDesigner,
namespace,
dataSource,
blockType,
pageSize = 20,
...others
@ -1360,7 +1360,7 @@ export const createTableBlockSchema = (options) => {
'x-acl-action': `${resource || collection}:list`,
'x-decorator-props': {
collection,
namespace,
dataSource,
resource: resource || collection,
action: 'list',
params: {
@ -1429,13 +1429,13 @@ export const createTableBlockSchema = (options) => {
};
export const createCollapseBlockSchema = (options) => {
const { collection, namespace, blockType } = options;
const { collection, dataSource, blockType } = options;
const schema: ISchema = {
type: 'void',
'x-decorator': 'AssociationFilter.Provider',
'x-decorator-props': {
collection,
namespace,
dataSource,
blockType,
associationFilterStyle: {
width: '100%',
@ -1460,7 +1460,7 @@ export const createCollapseBlockSchema = (options) => {
};
export const createTableSelectorSchema = (options) => {
const { collection, namespace, resource, rowKey, ...others } = options;
const { collection, dataSource, resource, rowKey, ...others } = options;
const schema: ISchema = {
type: 'void',
'x-acl-action': `${resource || collection}:list`,
@ -1468,7 +1468,7 @@ export const createTableSelectorSchema = (options) => {
'x-decorator-props': {
collection,
resource: resource || collection,
namespace,
dataSource,
action: 'list',
params: {
pageSize: 20,
@ -1509,114 +1509,9 @@ export const createTableSelectorSchema = (options) => {
};
const getChildren = ({
collections,
getCollectionFields,
componentName,
searchValue,
getTemplatesByCollection,
t,
}: {
collections: any[];
getCollectionFields: (name: any) => CollectionFieldOptions[];
componentName: string;
searchValue: string;
getTemplatesByCollection: (collectionName: string, resourceName?: string) => any;
t;
}) => {
return collections
?.filter((item) => {
if (item.inherit) {
return false;
}
const fields = getCollectionFields(item.name);
if (item.autoGenId === false && !fields.find((v) => v.primaryKey)) {
return false;
} else if (
['Kanban', 'FormItem'].includes(componentName) &&
((item.template === 'view' && !item.writableView) || item.template === 'sql')
) {
return false;
} else if (item.template === 'file' && ['Kanban', 'FormItem', 'Calendar'].includes(componentName)) {
return false;
} else {
if (!item.title) {
return false;
}
return item.title.toUpperCase().includes(searchValue.toUpperCase()) && !(item?.isThrough && item?.autoCreate);
}
})
?.map((item, index) => {
const templates = getTemplatesByCollection(item.name).filter((template) => {
return (
componentName &&
template.componentName === componentName &&
(!template.resourceName || template.resourceName === item.name)
);
});
if (!templates.length) {
return {
type: 'item',
name: item.name,
title: item.title,
};
}
return {
key: `${componentName}_table_subMenu_${index}`,
type: 'subMenu',
name: `${item.name}_${index}`,
title: item.title,
children: [
{
type: 'item',
name: item.name,
title: t('Blank block'),
},
{
type: 'divider',
},
{
key: `${componentName}_table_subMenu_${index}_copy`,
type: 'subMenu',
name: 'copy',
title: t('Duplicate template'),
children: templates.map((template) => {
const templateName =
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
return {
type: 'item',
mode: 'copy',
name: item.name,
template,
title: templateName || t('Untitled'),
};
}),
},
{
key: `${componentName}_table_subMenu_${index}_ref`,
type: 'subMenu',
name: 'ref',
title: t('Reference template'),
children: templates.map((template) => {
const templateName =
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
return {
type: 'item',
mode: 'reference',
name: item.name,
template,
title: templateName || t('Untitled'),
};
}),
},
],
};
});
};
const getChildrenV3 = ({
collections,
collectionManager,
namespace,
dataSource,
componentName,
searchValue,
getTemplatesByCollection,
@ -1626,7 +1521,7 @@ const getChildrenV3 = ({
collectionManager: CollectionManagerV2;
componentName: string;
searchValue: string;
namespace: string;
dataSource: string;
getTemplatesByCollection: (collectionName: string, resourceName?: string) => any;
t;
}) => {
@ -1635,7 +1530,7 @@ const getChildrenV3 = ({
if (item.inherit) {
return false;
}
const fields = collectionManager.getCollectionFields(item.name, { namespace });
const fields = collectionManager.getCollectionFields(item.name, { dataSource });
if (item.autoGenId === false && !fields.find((v) => v.primaryKey)) {
return false;
} else if (
@ -1667,7 +1562,7 @@ const getChildrenV3 = ({
type: 'item',
name: item.name,
title,
namespace,
dataSource,
};
}
return {
@ -1675,12 +1570,12 @@ const getChildrenV3 = ({
type: 'subMenu',
name: `${item.name}_${index}`,
title,
namespace,
dataSource,
children: [
{
type: 'item',
name: item.name,
namespace,
dataSource,
title: t('Blank block'),
},
{
@ -1690,7 +1585,7 @@ const getChildrenV3 = ({
key: `${componentName}_table_subMenu_${index}_copy`,
type: 'subMenu',
name: 'copy',
namespace,
dataSource,
title: t('Duplicate template'),
children: templates.map((template) => {
const templateName =
@ -1700,7 +1595,7 @@ const getChildrenV3 = ({
mode: 'copy',
name: item.name,
template,
namespace,
dataSource,
title: templateName || t('Untitled'),
};
}),
@ -1709,7 +1604,7 @@ const getChildrenV3 = ({
key: `${componentName}_table_subMenu_${index}_ref`,
type: 'subMenu',
name: 'ref',
namespace,
dataSource,
title: t('Reference template'),
children: templates.map((template) => {
const templateName =
@ -1719,7 +1614,7 @@ const getChildrenV3 = ({
mode: 'reference',
name: item.name,
template,
namespace,
dataSource,
title: templateName || t('Untitled'),
};
}),

View File

@ -30,7 +30,7 @@ export const CreateFormBulkEditBlockInitializer = () => {
actionInitializers: 'CreateFormActionInitializers',
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
template: s,
});
if (item.mode === 'reference') {
@ -47,7 +47,7 @@ export const CreateFormBulkEditBlockInitializer = () => {
actionInitializers: 'BulkEditFormActionInitializers',
association,
collection: collection.name,
namespace: collection.namespace,
dataSource: collection.dataSource,
}),
);
}

View File

@ -29,10 +29,10 @@ export const CalendarBlockInitializer = () => {
componentType={'Calendar'}
icon={<FormOutlined />}
onCreateBlockSchema={async ({ item }) => {
const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { namespace: item.namespace });
const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { dataSource: item.dataSource });
const dateFieldsOptions = getCollectionFieldsOptions(item.name, 'date', {
association: ['o2o', 'obo', 'oho', 'm2o'],
namespace: item.namespace,
dataSource: item.dataSource,
});
const values = await FormDialog(
@ -79,7 +79,7 @@ export const CalendarBlockInitializer = () => {
insert(
createCalendarBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
fieldNames: {
...values,
},

View File

@ -3,14 +3,14 @@ import { uid } from '@formily/shared';
import { generateNTemplate } from '../../locale';
export const createCalendarBlockSchema = (options) => {
const { collection, namespace, resource, fieldNames, ...others } = options;
const { collection, dataSource, resource, fieldNames, ...others } = options;
const schema: ISchema = {
type: 'void',
'x-acl-action': `${resource || collection}:list`,
'x-decorator': 'CalendarBlockProvider',
'x-decorator-props': {
collection: collection,
namespace,
dataSource,
resource: resource || collection,
action: 'list',
fieldNames: {

View File

@ -36,7 +36,7 @@ const ChartInitializer = () => {
schema: {},
field: null,
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
service: null,
data: undefined,
});

View File

@ -10,7 +10,7 @@ export type ChartConfigCurrent = {
schema: ISchema;
field: any;
collection: string;
namespace: string;
dataSource: string;
service: any;
initialValues?: any;
data: any[];

View File

@ -320,7 +320,7 @@ ChartConfigure.Query = function Query() {
schema,
field,
collection: value,
namespace: current.namespace,
dataSource: current.dataSource,
service: current.service,
initialValues: {},
data: undefined,

View File

@ -84,14 +84,14 @@ ChartRenderer.Designer = function Designer() {
const field = useField();
const schema = useFieldSchema();
const { insertAdjacent } = useDesignable();
const { name, title, namespace } = useCollection();
const { name, title, dataSource } = useCollection();
return (
<GeneralSchemaDesigner disableInitializer title={title || name}>
<SchemaSettingsItem
title="Configure"
key="configure"
onClick={async () => {
setCurrent({ schema, field, namespace, collection: name, service, data: service.data });
setCurrent({ schema, field, dataSource, collection: name, service, data: service.data });
setVisible(true);
}}
>

View File

@ -30,7 +30,7 @@ export const GanttBlockInitializer = () => {
componentType={'Gantt'}
icon={<FormOutlined />}
onCreateBlockSchema={async ({ item }) => {
const collectionFields = getCollectionFields(item.name, item.namespace);
const collectionFields = getCollectionFields(item.name, item.dataSource);
const stringFields = collectionFields
?.filter((field) => field.type === 'string')
?.map((field) => {
@ -122,7 +122,7 @@ export const GanttBlockInitializer = () => {
insert(
createGanttBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
fieldNames: {
...values,
},

View File

@ -32,7 +32,7 @@ export const KanbanBlockInitializer = () => {
componentType={'Kanban'}
icon={<FormOutlined />}
onCreateBlockSchema={async ({ item }) => {
const collectionFields = getCollectionFields(item.name, item.namespace);
const collectionFields = getCollectionFields(item.name, item.dataSource);
const fields = collectionFields
?.filter((field) => ['select', 'radioGroup'].includes(field.interface))
?.map((field) => {
@ -93,7 +93,7 @@ export const KanbanBlockInitializer = () => {
createKanbanBlockSchema({
groupField: values.groupField.value,
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
params: {
sort: [sortName],
paginate: false,

View File

@ -75,7 +75,7 @@ const recursiveProperties = (schema: Schema, component = 'CollectionField', asso
};
const useAssociationNames = (collection) => {
const { getCollectionFields } = useCollectionManager(collection.namespace);
const { getCollectionFields } = useCollectionManager(collection.dataSource);
const collectionFields = getCollectionFields(collection);
const associationFields = new Set();
for (const collectionField of collectionFields) {

View File

@ -29,10 +29,10 @@ export const MapBlockInitializer = () => {
onCreateBlockSchema={async ({ item }) => {
const mapFieldOptions = getCollectionFieldsOptions(item.name, ['point', 'lineString', 'polygon'], {
association: ['o2o', 'obo', 'oho', 'o2m', 'm2o', 'm2m'],
namespace: item.namespace,
dataSource: item.dataSource,
});
const markerFieldOptions = getCollectionFieldsOptions(item.name, 'string', {
namespace: item.namespace,
dataSource: item.dataSource,
});
const values = await FormDialog(
t('Create map block'),
@ -86,7 +86,7 @@ export const MapBlockInitializer = () => {
insert(
createMapBlockSchema({
collection: item.name,
namespace: item.namespace,
dataSource: item.dataSource,
fieldNames: {
...values,
},

View File

@ -90,7 +90,7 @@ const BlockProvider = (props) => {
export const SnapshotBlockProvider = (props) => {
const record = useRecord();
const { __tableName } = record;
const { getInheritCollections } = useCollectionManager(props.namespace);
const { getInheritCollections } = useCollectionManager(props.dataSource);
const inheritCollections = getInheritCollections(__tableName);
const { designable } = useDesignable();
const flag =

View File

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

View File

@ -2,9 +2,9 @@ import { createForm } from '@formily/core';
import { RecursionField, useField, useFieldSchema } from '@formily/react';
import {
BlockRequestContext,
CollectionNamespace,
CollectionProvider,
DEFAULT_COLLECTION_NAMESPACE_NAME,
DEFAULT_DATA_SOURCE_NAME,
DataSourceName,
FormActiveFieldsProvider,
FormBlockContext,
FormV2,
@ -21,9 +21,9 @@ export function FormBlockProvider(props) {
const fieldSchema = useFieldSchema();
const field = useField();
const formBlockRef = useRef(null);
const namespace = props.namespace || DEFAULT_COLLECTION_NAMESPACE_NAME;
const dataSource = props.dataSource || DEFAULT_DATA_SOURCE_NAME;
const { getAssociationAppends } = useAssociationNames(namespace);
const { getAssociationAppends } = useAssociationNames(dataSource);
const { appends, updateAssociationValues } = getAssociationAppends();
const [formKey] = Object.keys(fieldSchema.toJSON().properties ?? {});
const values = userJob?.result?.[formKey];
@ -55,10 +55,10 @@ export function FormBlockProvider(props) {
}, [values]);
const api = useAPIClient();
const headers = useMemo(() => {
if (namespace && namespace !== DEFAULT_COLLECTION_NAMESPACE_NAME) {
return { 'x-connection': namespace };
if (dataSource && dataSource !== DEFAULT_DATA_SOURCE_NAME) {
return { 'x-connection': dataSource };
}
}, [namespace]);
}, [dataSource]);
const resource = api.resource(props.collection, undefined, headers);
const __parent = useContext(BlockRequestContext);
@ -75,7 +75,7 @@ export function FormBlockProvider(props) {
}, [field, form, params, service, updateAssociationValues]);
return !userJob.status || values ? (
<CollectionNamespace.Provider value={namespace}>
<DataSourceName.Provider value={dataSource}>
<CollectionProvider collection={props.collection}>
<RecordProvider record={values} parent={false}>
<FormActiveFieldsProvider name="form">
@ -92,6 +92,6 @@ export function FormBlockProvider(props) {
</FormActiveFieldsProvider>
</RecordProvider>
</CollectionProvider>
</CollectionNamespace.Provider>
</DataSourceName.Provider>
) : null;
}

View File

@ -43,10 +43,10 @@ export default {
useInitializer({ allCollections }) {
const childItems = useMemo(
() =>
allCollections.map(({ nsName, nsTitle, collections }) => ({
key: nsName,
name: nsName,
label: nsTitle,
allCollections.map(({ dataSourceName, dataSourceDescription, collections }) => ({
key: dataSourceName,
name: dataSourceName,
label: dataSourceDescription,
type: 'subMenu',
children: collections.map((item) => ({
name: _.camelCase(`createRecordForm-child-${item.name}`),
@ -54,7 +54,7 @@ export default {
title: item.title || item.tableName,
schema: {
collection: item.name,
namespace: nsName,
dataSource: dataSourceName,
title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
formType: 'create',
'x-designer': 'CreateFormDesigner',

View File

@ -80,10 +80,10 @@ export default {
useInitializer({ allCollections }) {
const childItems = useMemo(
() =>
allCollections.map(({ nsName, nsTitle, collections }) => ({
key: nsName,
name: nsName,
label: nsTitle,
allCollections.map(({ dataSourceName, dataSourceDescription, collections }) => ({
key: dataSourceName,
name: dataSourceName,
label: dataSourceDescription,
type: 'subMenu',
children: collections.map((item) => ({
name: _.camelCase(`updateRecordForm-child-${item.name}`),
@ -91,7 +91,7 @@ export default {
title: item.title || item.tableName,
schema: {
collection: item.name,
namespace: nsName,
dataSource: dataSourceName,
title: `{{t("Update record", { ns: "${NAMESPACE}" })}}`,
formType: 'update',
'x-designer': 'UpdateFormDesigner',