feat: refactor mobile components and add extend collection in form (#1259)
Reviewed-on: daoyoucloud/tachybase#1259
This commit is contained in:
parent
62ee8730b0
commit
a15f5aedf0
@ -0,0 +1,49 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Plugin } from '../../application/Plugin';
|
||||||
|
import { CollectionOptions, ExtendCollectionsProvider } from '../../data-source';
|
||||||
|
|
||||||
|
export class PluginBuiltInCollections extends Plugin {
|
||||||
|
async load() {
|
||||||
|
this.app.use(BuiltInCollectionsProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const collection: CollectionOptions = {
|
||||||
|
name: 'test-test',
|
||||||
|
title: 'TestTest',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'name',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: 'Name',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Input',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'boolean',
|
||||||
|
name: 'enabled',
|
||||||
|
interface: 'radioGroup',
|
||||||
|
uiSchema: {
|
||||||
|
title: 'Enabled',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
enum: [
|
||||||
|
{ label: 'On', value: true },
|
||||||
|
{ label: 'Off', value: false },
|
||||||
|
],
|
||||||
|
'x-component': 'Radio.Group',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuiltInCollectionsProvider = ({ children }) => {
|
||||||
|
return <ExtendCollectionsProvider collections={[collection]}>{children}</ExtendCollectionsProvider>;
|
||||||
|
};
|
@ -22,6 +22,7 @@ import { BlockTemplateDetails, BlockTemplatePage } from '../schema-templates';
|
|||||||
import { CurrentUserProvider, CurrentUserSettingsMenuProvider } from '../user';
|
import { CurrentUserProvider, CurrentUserSettingsMenuProvider } from '../user';
|
||||||
import { ACLPlugin } from './acl';
|
import { ACLPlugin } from './acl';
|
||||||
import { AdminLayoutPlugin } from './admin-layout';
|
import { AdminLayoutPlugin } from './admin-layout';
|
||||||
|
import { PluginBuiltInCollections } from './built-in-collections';
|
||||||
import { RemoteDocumentTitlePlugin } from './document-title';
|
import { RemoteDocumentTitlePlugin } from './document-title';
|
||||||
import { LocalePlugin } from './locale/LocalePlugin';
|
import { LocalePlugin } from './locale/LocalePlugin';
|
||||||
import { PinnedListPlugin } from './pinned-list';
|
import { PinnedListPlugin } from './pinned-list';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { connect, Field, merge, useField, useFieldSchema } from '@tachybase/schema';
|
import { connect, Field, merge, useField, useFieldSchema } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import { useDeepCompareEffect } from 'ahooks';
|
||||||
import { concat } from 'lodash';
|
import { concat } from 'lodash';
|
||||||
|
|
||||||
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
||||||
@ -41,7 +42,7 @@ export const CollectionFieldInternalField = (props: Props) => {
|
|||||||
ctx.field.added.add(fieldSchema.name);
|
ctx.field.added.add(fieldSchema.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useDeepCompareEffect(() => {
|
||||||
if (!uiSchema) {
|
if (!uiSchema) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,7 +70,6 @@ export const CollectionFieldInternalField = (props: Props) => {
|
|||||||
const originalProps = compile(uiSchema['x-component-props']) || {};
|
const originalProps = compile(uiSchema['x-component-props']) || {};
|
||||||
const componentProps = merge(originalProps, field.componentProps || {});
|
const componentProps = merge(originalProps, field.componentProps || {});
|
||||||
field.component = [Component, componentProps];
|
field.component = [Component, componentProps];
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [uiSchema]);
|
}, [uiSchema]);
|
||||||
if (!uiSchema) {
|
if (!uiSchema) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { createContext, FC, ReactNode, useContext, useMemo } from 'react';
|
import React, { createContext, ReactNode, useContext, useMemo } from 'react';
|
||||||
|
|
||||||
import { useDataSourceKey } from '../data-source/DataSourceProvider';
|
import { useDataSourceKey } from '../data-source/DataSourceProvider';
|
||||||
import { CollectionOptions } from './Collection';
|
import { CollectionOptions } from './Collection';
|
||||||
@ -12,7 +12,7 @@ export interface ExtendCollectionsProviderProps {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExtendCollectionsProvider: FC<ExtendCollectionsProviderProps> = ({ children, collections }) => {
|
export const ExtendCollectionsProvider = ({ children, collections }: ExtendCollectionsProviderProps) => {
|
||||||
const parentCollections = useExtendCollections();
|
const parentCollections = useExtendCollections();
|
||||||
const extendCollections = useMemo(() => {
|
const extendCollections = useMemo(() => {
|
||||||
return parentCollections ? [...parentCollections, ...collections] : collections;
|
return parentCollections ? [...parentCollections, ...collections] : collections;
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
||||||
import { AssociatedFields, ParentCollectionFields } from '../../../../schema-initializer/buttons/FormItemInitializers';
|
import {
|
||||||
|
AssociatedFields,
|
||||||
|
ExtendCollectionFields,
|
||||||
|
ParentCollectionFields,
|
||||||
|
} from '../../../../schema-initializer/buttons/FormItemInitializers';
|
||||||
import { gridRowColWrap, useFormItemInitializerFields } from '../../../../schema-initializer/utils';
|
import { gridRowColWrap, useFormItemInitializerFields } from '../../../../schema-initializer/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +26,10 @@ export const formItemInitializers_deprecated = new CompatibleSchemaInitializer({
|
|||||||
name: 'parentCollectionFields',
|
name: 'parentCollectionFields',
|
||||||
Component: ParentCollectionFields,
|
Component: ParentCollectionFields,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'extendCollectionFields',
|
||||||
|
Component: ExtendCollectionFields,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'associationFields',
|
name: 'associationFields',
|
||||||
Component: AssociatedFields,
|
Component: AssociatedFields,
|
||||||
@ -55,6 +63,10 @@ export const formItemInitializers = new CompatibleSchemaInitializer(
|
|||||||
name: 'parentCollectionFields',
|
name: 'parentCollectionFields',
|
||||||
Component: ParentCollectionFields,
|
Component: ParentCollectionFields,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'extendCollectionFields',
|
||||||
|
Component: ExtendCollectionFields,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'associationFields',
|
name: 'associationFields',
|
||||||
Component: AssociatedFields,
|
Component: AssociatedFields,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { Field, observer, useField, useForm } from '@tachybase/schema';
|
import { Field, observer, SchemaOptionsContext, useField, useForm } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { SchemaComponentOptions } from '../../';
|
import { SchemaComponentOptions } from '../../';
|
||||||
import { useAssociationCreateActionProps as useCAP } from '../../../block-provider/hooks';
|
import { useAssociationCreateActionProps as useCAP } from '../../../block-provider/hooks';
|
||||||
import { useCollection_deprecated } from '../../../collection-manager';
|
import { useCollection_deprecated } from '../../../collection-manager';
|
||||||
import { AssociationFieldProvider } from './AssociationFieldProvider';
|
import { AssociationFieldProvider } from './AssociationFieldProvider';
|
||||||
import { AssociationSelect } from './AssociationSelect';
|
import { AssociationSelect as Select } from './AssociationSelect';
|
||||||
import { CreateRecordAction } from './components/CreateRecordAction';
|
import { CreateRecordAction } from './components/CreateRecordAction';
|
||||||
import { InternalFileManager } from './FileManager';
|
import { InternalFileManager } from './FileManager';
|
||||||
import { useAssociationFieldContext } from './hooks';
|
import { useAssociationFieldContext } from './hooks';
|
||||||
@ -23,6 +25,8 @@ const EditableAssociationField = observer(
|
|||||||
const field: Field = useField();
|
const field: Field = useField();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
const { options: collectionField, currentMode } = useAssociationFieldContext();
|
const { options: collectionField, currentMode } = useAssociationFieldContext();
|
||||||
|
const { components } = useContext(SchemaOptionsContext);
|
||||||
|
const AssociationSelect = _.get(components, 'AlternativeAssociationSelect') || Select;
|
||||||
|
|
||||||
const useCreateActionProps = () => {
|
const useCreateActionProps = () => {
|
||||||
const { onClick } = useCAP();
|
const { onClick } = useCAP();
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useForm } from '@tachybase/schema';
|
||||||
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { SchemaInitializerChildren } from '../../application';
|
import { SchemaInitializerChildren, SchemaInitializerItemType } from '../../application';
|
||||||
import { useCompile } from '../../schema-component';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
|
import { useCollectionManager, useExtendCollections } from '../../data-source';
|
||||||
|
import { useActionContext, useCompile } from '../../schema-component';
|
||||||
import {
|
import {
|
||||||
|
removeGridFormItem,
|
||||||
useAssociatedFormItemInitializerFields,
|
useAssociatedFormItemInitializerFields,
|
||||||
useFilterAssociatedFormItemInitializerFields,
|
useFilterAssociatedFormItemInitializerFields,
|
||||||
useFilterInheritsFormItemInitializerFields,
|
useFilterInheritsFormItemInitializerFields,
|
||||||
@ -29,6 +33,84 @@ export const ParentCollectionFields = () => {
|
|||||||
return <SchemaInitializerChildren>{res}</SchemaInitializerChildren>;
|
return <SchemaInitializerChildren>{res}</SchemaInitializerChildren>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ExtendCollectionFields = (props) => {
|
||||||
|
const collections = useExtendCollections();
|
||||||
|
const form = useForm();
|
||||||
|
const compile = useCompile();
|
||||||
|
const { getInterface, getCollection } = useCollectionManager_deprecated();
|
||||||
|
const { fieldSchema } = useActionContext();
|
||||||
|
if (!collections) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const children = collections.map((collection) => {
|
||||||
|
// FIXME
|
||||||
|
const readPretty = form.readPretty;
|
||||||
|
const block = 'Form';
|
||||||
|
const action = fieldSchema?.['x-action'];
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'subMenu',
|
||||||
|
title: compile(collection.title),
|
||||||
|
children: collection.fields
|
||||||
|
?.filter((field) => field?.interface && !field?.isForeignKey && !field?.treeChildren)
|
||||||
|
?.map((field) => {
|
||||||
|
const interfaceConfig = getInterface(field.interface);
|
||||||
|
const targetCollection = getCollection(field.target);
|
||||||
|
const isFileCollection = field?.target && getCollection(field?.target)?.template === 'file';
|
||||||
|
const isAssociationField = targetCollection;
|
||||||
|
const fieldNames = field?.uiSchema['x-component-props']?.['fieldNames'];
|
||||||
|
const schema = {
|
||||||
|
type: 'string',
|
||||||
|
name: field.name,
|
||||||
|
'x-toolbar': 'FormItemSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:FormItem',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-collection-field': `${collection.name}.${field.name}`,
|
||||||
|
'x-component-props': isFileCollection
|
||||||
|
? {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'preview',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: isAssociationField && fieldNames
|
||||||
|
? {
|
||||||
|
fieldNames: { ...fieldNames, label: targetCollection?.titleField || fieldNames.label },
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
'x-read-pretty': field?.uiSchema?.['x-read-pretty'],
|
||||||
|
};
|
||||||
|
const resultItem = {
|
||||||
|
type: 'item',
|
||||||
|
name: field.name,
|
||||||
|
title: field?.uiSchema?.title || field.name,
|
||||||
|
Component: 'CollectionFieldInitializer',
|
||||||
|
remove: removeGridFormItem,
|
||||||
|
schemaInitialize: (s) => {
|
||||||
|
interfaceConfig?.schemaInitialize?.(s, {
|
||||||
|
field,
|
||||||
|
block,
|
||||||
|
readPretty,
|
||||||
|
action,
|
||||||
|
targetCollection,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
schema,
|
||||||
|
} as SchemaInitializerItemType;
|
||||||
|
return resultItem;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const res = [];
|
||||||
|
res.push({
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: '{{ t("Extend collections") }}',
|
||||||
|
children,
|
||||||
|
});
|
||||||
|
return <SchemaInitializerChildren>{res}</SchemaInitializerChildren>;
|
||||||
|
};
|
||||||
|
|
||||||
export const AssociatedFields = () => {
|
export const AssociatedFields = () => {
|
||||||
const associationFields = useAssociatedFormItemInitializerFields({
|
const associationFields = useAssociatedFormItemInitializerFields({
|
||||||
readPretty: true,
|
readPretty: true,
|
||||||
|
@ -2,7 +2,6 @@ import React, { PropsWithChildren } from 'react';
|
|||||||
import { SchemaComponentOptions } from '@tachybase/client';
|
import { SchemaComponentOptions } from '@tachybase/client';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CollectionField,
|
|
||||||
ImageSearchInitializer,
|
ImageSearchInitializer,
|
||||||
ImageSearchItemIntializer,
|
ImageSearchItemIntializer,
|
||||||
ImageSearchItemToolbar,
|
ImageSearchItemToolbar,
|
||||||
@ -24,8 +23,6 @@ import {
|
|||||||
MSettings,
|
MSettings,
|
||||||
MSettingsBlockInitializer,
|
MSettingsBlockInitializer,
|
||||||
MTabBar,
|
MTabBar,
|
||||||
NoticeBlock,
|
|
||||||
NoticeBlockInitializer,
|
|
||||||
SwiperBlock,
|
SwiperBlock,
|
||||||
SwiperBlockInitializer,
|
SwiperBlockInitializer,
|
||||||
SwiperPage,
|
SwiperPage,
|
||||||
@ -75,22 +72,30 @@ export const MobileCore: React.FC<PropsWithChildren> = (props) => {
|
|||||||
TabSearchCollapsibleInputMItem,
|
TabSearchCollapsibleInputMItem,
|
||||||
TabSearchFieldSchemaInitializerGadget,
|
TabSearchFieldSchemaInitializerGadget,
|
||||||
|
|
||||||
ImageSearchView: ImageSearchView,
|
ImageSearchView,
|
||||||
ImageSearchInitializer: ImageSearchInitializer,
|
ImageSearchInitializer,
|
||||||
ImageSearchProvider: ImageSearchProvider,
|
ImageSearchProvider,
|
||||||
ImageSearchItemIntializer: ImageSearchItemIntializer,
|
ImageSearchItemIntializer,
|
||||||
ImageSearchItemToolbar: ImageSearchItemToolbar,
|
ImageSearchItemToolbar,
|
||||||
ImageSearchItemView: ImageSearchItemView,
|
ImageSearchItemView,
|
||||||
// NoticeBlock,
|
|
||||||
// NoticeBlockInitializer,
|
|
||||||
MInput,
|
MInput,
|
||||||
MCheckbox,
|
MCheckbox,
|
||||||
MDatePicker,
|
MDatePicker,
|
||||||
MRadio,
|
MRadio,
|
||||||
MImageUploader,
|
MImageUploader,
|
||||||
MCascader,
|
MCascader,
|
||||||
CollectionField: CollectionField,
|
|
||||||
MSelect,
|
MSelect,
|
||||||
|
// mobile alternative components
|
||||||
|
Input: MInput,
|
||||||
|
'Input.TextArea': MInput.TextArea,
|
||||||
|
'Radio.Group': MRadio.Group,
|
||||||
|
'Checkbox.Group': MCheckbox.Group,
|
||||||
|
// 只支持图片,所以暂时禁用
|
||||||
|
// 'Upload.Attachment': MImageUploader,
|
||||||
|
DatePicker: MDatePicker,
|
||||||
|
Select: MSelect,
|
||||||
|
AlternativeAssociationSelect: MSelect,
|
||||||
|
Cascader: MCascader,
|
||||||
}}
|
}}
|
||||||
scope={{
|
scope={{
|
||||||
useGridCardBlockItemProps,
|
useGridCardBlockItemProps,
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
|
||||||
import {
|
|
||||||
CollectionFieldProvider,
|
|
||||||
useCollectionField,
|
|
||||||
useCollectionManager,
|
|
||||||
useCollectionManager_deprecated,
|
|
||||||
useCompile,
|
|
||||||
useComponent,
|
|
||||||
useFormBlockContext,
|
|
||||||
useIsAllowToSetDefaultValue,
|
|
||||||
} from '@tachybase/client';
|
|
||||||
import { connect, Field, merge, useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
|
|
||||||
import { concat } from 'lodash';
|
|
||||||
|
|
||||||
import { canMobileField } from '../../CustomComponent';
|
|
||||||
import { useIsMobile } from '../../hooks';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
component: any;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: 初步适配
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
export const CollectionFieldInternalField: React.FC = (props: Props) => {
|
|
||||||
const { component } = props;
|
|
||||||
const compile = useCompile();
|
|
||||||
const field = useField<Field>();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { getCollectionJoinField, getCollection } = useCollectionManager_deprecated();
|
|
||||||
const { uiSchema: uiSchemaOrigin, defaultValue } = useCollectionField();
|
|
||||||
const { isAllowToSetDefaultValue } = useIsAllowToSetDefaultValue();
|
|
||||||
const uiSchema = useMemo(() => compile(uiSchemaOrigin), [JSON.stringify(uiSchemaOrigin)]);
|
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
|
||||||
const currModel = getCurrModel({ getCollectionJoinField, getCollection, fieldSchema, uiSchema });
|
|
||||||
const Component = useComponent(component || uiComponent(isMobile, uiSchema, currModel) || 'Input');
|
|
||||||
|
|
||||||
const setFieldProps = (key, value) => {
|
|
||||||
field[key] = typeof field[key] === 'undefined' ? value : field[key];
|
|
||||||
};
|
|
||||||
const setRequired = () => {
|
|
||||||
if (typeof fieldSchema['required'] === 'undefined') {
|
|
||||||
field.required = !!uiSchema['required'];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const ctx = useFormBlockContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (ctx?.field) {
|
|
||||||
ctx.field.added = ctx.field.added || new Set();
|
|
||||||
ctx.field.added.add(fieldSchema.name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO: 初步适配
|
|
||||||
useEffect(() => {
|
|
||||||
if (!uiSchema) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFieldProps('content', uiSchema['x-content']);
|
|
||||||
setFieldProps('title', uiSchema.title);
|
|
||||||
setFieldProps('description', uiSchema.description);
|
|
||||||
if (ctx?.form) {
|
|
||||||
const defaultVal = isAllowToSetDefaultValue() ? fieldSchema.default || defaultValue : undefined;
|
|
||||||
defaultVal !== null && defaultVal !== undefined && setFieldProps('initialValue', defaultVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!field.validator && (uiSchema['x-validator'] || fieldSchema['x-validator'])) {
|
|
||||||
const concatSchema = concat([], uiSchema['x-validator'] || [], fieldSchema['x-validator'] || []);
|
|
||||||
field.validator = concatSchema;
|
|
||||||
}
|
|
||||||
if (fieldSchema['x-disabled'] === true) {
|
|
||||||
field.disabled = true;
|
|
||||||
}
|
|
||||||
if (fieldSchema['x-read-pretty'] === true) {
|
|
||||||
field.readPretty = true;
|
|
||||||
}
|
|
||||||
setRequired();
|
|
||||||
// @ts-ignore
|
|
||||||
field.dataSource = uiSchema.enum;
|
|
||||||
const originalProps = compile(uiSchema['x-component-props']) || {};
|
|
||||||
const componentProps = merge(originalProps, field.componentProps || {});
|
|
||||||
field.component = [Component, componentProps];
|
|
||||||
}, [JSON.stringify(uiSchema)]);
|
|
||||||
if (!uiSchema) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <Component {...props} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CollectionField = connect((props) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
return (
|
|
||||||
<CollectionFieldProvider name={fieldSchema.name}>
|
|
||||||
<CollectionFieldInternalField {...props} />
|
|
||||||
</CollectionFieldProvider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const uiComponent = (isMobile, uiSchema, currMode?) => {
|
|
||||||
const isMobileComponent = canMobileField(currMode || uiSchema['x-component']);
|
|
||||||
if (isMobile && isMobileComponent) {
|
|
||||||
return isMobileComponent;
|
|
||||||
} else {
|
|
||||||
return uiSchema['x-component'];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getCurrModel = ({ getCollectionJoinField, getCollection, fieldSchema, uiSchema }) => {
|
|
||||||
const collectionField = getCollectionJoinField(fieldSchema['x-collection-field']);
|
|
||||||
const isFileCollection = getCollection(collectionField?.target)?.template === 'file';
|
|
||||||
const isTreeCollection = getCollection(collectionField?.target)?.template === 'tree';
|
|
||||||
|
|
||||||
const currentMode =
|
|
||||||
fieldSchema['x-component-props']?.mode ||
|
|
||||||
(isFileCollection ? 'FileManager' : isTreeCollection ? 'Cascader' : 'Select');
|
|
||||||
return currentMode && uiSchema['x-component'] === 'AssociationField' ? currentMode : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
CollectionField.displayName = 'CollectionField';
|
|
@ -1 +0,0 @@
|
|||||||
export * from './CollectionField';
|
|
@ -1,147 +0,0 @@
|
|||||||
import {
|
|
||||||
AssociatedFields,
|
|
||||||
CompatibleSchemaInitializer,
|
|
||||||
formItemInitializers_deprecated,
|
|
||||||
gridRowColWrap,
|
|
||||||
ParentCollectionFields,
|
|
||||||
SchemaInitializerItemType,
|
|
||||||
useActionContext,
|
|
||||||
useCollection_deprecated,
|
|
||||||
useCollectionManager_deprecated,
|
|
||||||
} from '@tachybase/client';
|
|
||||||
import { Schema, useForm } from '@tachybase/schema';
|
|
||||||
|
|
||||||
import { canMobileField } from '../../CustomComponent';
|
|
||||||
import { useIsMobile } from '../../hooks';
|
|
||||||
|
|
||||||
export const useFormItemInitializerFields = (options?: any) => {
|
|
||||||
const { name, currentFields } = useCollection_deprecated();
|
|
||||||
const isMobile = useIsMobile();
|
|
||||||
const { getInterface, getCollection } = useCollectionManager_deprecated();
|
|
||||||
const form = useForm();
|
|
||||||
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
||||||
const { fieldSchema } = useActionContext();
|
|
||||||
const action = fieldSchema?.['x-action'];
|
|
||||||
|
|
||||||
return currentFields
|
|
||||||
?.filter((field) => field?.interface && !field?.isForeignKey && !field?.treeChildren)
|
|
||||||
?.map((field) => {
|
|
||||||
const interfaceConfig = getInterface(field.interface);
|
|
||||||
const targetCollection = getCollection(field.target);
|
|
||||||
const isFileCollection = field?.target && getCollection(field?.target)?.template === 'file';
|
|
||||||
const isAssociationField = targetCollection;
|
|
||||||
const fieldNames = field?.uiSchema['x-component-props']?.['fieldNames'];
|
|
||||||
const isMobileComponent = canMobileField(field.uiSchema['x-component']);
|
|
||||||
const schema = {
|
|
||||||
type: 'string',
|
|
||||||
name: field.name,
|
|
||||||
'x-toolbar': 'FormItemSchemaToolbar',
|
|
||||||
'x-settings': 'fieldSettings:FormItem',
|
|
||||||
'x-component': 'CollectionField',
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-collection-field': `${name}.${field.name}`,
|
|
||||||
'x-component-props': isFileCollection
|
|
||||||
? {
|
|
||||||
fieldNames: {
|
|
||||||
label: 'preview',
|
|
||||||
value: 'id',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: isAssociationField && fieldNames
|
|
||||||
? {
|
|
||||||
fieldNames: { ...fieldNames, label: targetCollection?.titleField || fieldNames.label },
|
|
||||||
}
|
|
||||||
: {},
|
|
||||||
'x-read-pretty': field?.uiSchema?.['x-read-pretty'],
|
|
||||||
};
|
|
||||||
if (isMobile && isMobileComponent) {
|
|
||||||
schema['x-component-props']['component'] = isMobileComponent;
|
|
||||||
}
|
|
||||||
const resultItem = {
|
|
||||||
type: 'item',
|
|
||||||
name: field.name,
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
Component: 'CollectionFieldInitializer',
|
|
||||||
remove: removeGridFormItem,
|
|
||||||
schemaInitialize: (s) => {
|
|
||||||
interfaceConfig?.schemaInitialize?.(s, {
|
|
||||||
field,
|
|
||||||
block,
|
|
||||||
readPretty,
|
|
||||||
action,
|
|
||||||
targetCollection,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
schema,
|
|
||||||
} as SchemaInitializerItemType;
|
|
||||||
if (block == 'Kanban') {
|
|
||||||
resultItem['find'] = (schema: Schema, key: string, action: string) => {
|
|
||||||
const s = findSchema(schema, 'x-component', block);
|
|
||||||
return findSchema(s, key, action);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultItem;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MobileFormItemInitializers = new CompatibleSchemaInitializer(
|
|
||||||
{
|
|
||||||
name: 'form:configureFields',
|
|
||||||
wrap: gridRowColWrap,
|
|
||||||
icon: 'SettingOutlined',
|
|
||||||
title: '{{t("Configure fields")}}',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
name: 'displayFields',
|
|
||||||
title: '{{t("Display fields")}}',
|
|
||||||
useChildren: useFormItemInitializerFields,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'parentCollectionFields',
|
|
||||||
Component: ParentCollectionFields,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'associationFields',
|
|
||||||
Component: AssociatedFields,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'divider',
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'addText',
|
|
||||||
title: '{{t("Add text")}}',
|
|
||||||
Component: 'MarkdownFormItemInitializer',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
formItemInitializers_deprecated,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const removeGridFormItem = (schema, cb) => {
|
|
||||||
cb(schema, {
|
|
||||||
removeParentsIfNoChildren: true,
|
|
||||||
breakRemoveOn: {
|
|
||||||
'x-component': 'Grid',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const findSchema = (schema: Schema, key: string, action: string) => {
|
|
||||||
if (!Schema.isSchemaInstance(schema)) return null;
|
|
||||||
return schema.reduceProperties((buf, s) => {
|
|
||||||
if (s[key] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
if (s['x-component'] !== 'Action.Container' && s['x-component'] !== 'AssociationField.Viewer') {
|
|
||||||
const c = findSchema(s, key, action);
|
|
||||||
if (c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
};
|
|
@ -1 +0,0 @@
|
|||||||
export * from './MobileFormItemInitializers';
|
|
@ -8,6 +8,4 @@ export * from './image-search';
|
|||||||
export * from './swiper';
|
export * from './swiper';
|
||||||
export * from './tab-search';
|
export * from './tab-search';
|
||||||
export * from './notice';
|
export * from './notice';
|
||||||
export * from './form';
|
|
||||||
export * from './antd-mobile';
|
export * from './antd-mobile';
|
||||||
export * from './collection-field';
|
|
||||||
|
@ -2,6 +2,6 @@ import React, { createContext } from 'react';
|
|||||||
|
|
||||||
export const MobileContext = createContext<any>({ isMobile: false });
|
export const MobileContext = createContext<any>({ isMobile: false });
|
||||||
|
|
||||||
export const MobileProvider = (props) => {
|
export const MobileProvider = ({ children }) => {
|
||||||
return <MobileContext.Provider value={{ isMobile: true }}> {props.children}</MobileContext.Provider>;
|
return <MobileContext.Provider value={{ isMobile: true }}>{children}</MobileContext.Provider>;
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
ImageSearchItemFieldSettings,
|
ImageSearchItemFieldSettings,
|
||||||
mBlockInitializers,
|
mBlockInitializers,
|
||||||
mBlockInitializers_deprecated,
|
mBlockInitializers_deprecated,
|
||||||
MobileFormItemInitializers,
|
|
||||||
SwiperFieldSettings,
|
SwiperFieldSettings,
|
||||||
SwiperPage,
|
SwiperPage,
|
||||||
TabSearchFieldSchemaInitializer,
|
TabSearchFieldSchemaInitializer,
|
||||||
@ -35,7 +34,6 @@ export class MobileClientPlugin extends Plugin {
|
|||||||
this.app.schemaSettingsManager.add(SwiperFieldSettings);
|
this.app.schemaSettingsManager.add(SwiperFieldSettings);
|
||||||
this.app.schemaSettingsManager.add(ImageSearchItemFieldSettings);
|
this.app.schemaSettingsManager.add(ImageSearchItemFieldSettings);
|
||||||
this.app.schemaSettingsManager.add(TabSearchItemFieldSettings);
|
this.app.schemaSettingsManager.add(TabSearchItemFieldSettings);
|
||||||
this.app.schemaInitializerManager.add(MobileFormItemInitializers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addSettings() {
|
addSettings() {
|
||||||
|
Loading…
Reference in New Issue
Block a user