mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-09 15:39:24 +08:00
* feat: support to add File collection * feat: support to upload files * refactor: rename 'ReadPretty.Attachment' to 'ReadPretty.File' * feat: support to associate the File collection * refactor: add Preview and replace Upload.Selector * fix(Preview): fix some problems in ReadPretty mode * feat: use 'preview' as a default title field * feat: support only local storage now * fix: should not show 'Add new' button * chore: add default value for file storage * fix: fix preview field of file collection cannot be displayed normally * fix: only Table and Details can display File collection * chore: translate * refactor: migration to plugin from core * refactor: change 'preview' to 'url' * fix: only 'belongsTo' and 'belongsToMany' can linked file collection * fix: fix storage and add a field called storage in file collection * feat: add 'deletable' to configure the visibility of the delete button * fix: fix can't upload attachment problem * fix: remove more option * fix: can't use preview to filter * fix: remove Import action option * refactor: remove useless code * chore: optimize condition * chore: remove comment * test: windows compatible * refactor: optimize upload * fix: upload action * fix: createAction * fix: uploads * fix: file collection cannot be inherited by other collections * fix: url should be editable * fix: url is filterable * fix: use input interface for url field * fix: fix error * fix: remove subform * Revert "chore: translate" This reverts commit 53cd346dab8cbee0c52a9da3cf83a99dff2def34. * refactor: move translation to plugin * fix: title is editable * fix: collection?.template === 'file' * fix: fix order of URL * fix(collection-manager): allow collectionCategories:list * chore: add translation * fix(upload): should enable to use drawer * refactor: move code to plugin --------- Co-authored-by: chenos <chenlinxh@gmail.com>
120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import { Field } from '@formily/core';
|
|
import { connect, useField, useFieldSchema } from '@formily/react';
|
|
import { merge } from '@formily/shared';
|
|
import { concat } from 'lodash';
|
|
import React, { useEffect } from 'react';
|
|
import { useActionContext, useCompile, useComponent, useFormBlockContext, useRecord } from '..';
|
|
import { CollectionFieldProvider } from './CollectionFieldProvider';
|
|
import { useCollectionField } from './hooks';
|
|
|
|
// TODO: 初步适配
|
|
const InternalField: React.FC = (props) => {
|
|
const field = useField<Field>();
|
|
const fieldSchema = useFieldSchema();
|
|
const { uiSchema, defaultValue } = useCollectionField();
|
|
const component = useComponent(uiSchema?.['x-component'] || 'Input');
|
|
const compile = useCompile();
|
|
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) {
|
|
setFieldProps('initialValue', fieldSchema.default || defaultValue);
|
|
}
|
|
|
|
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];
|
|
|
|
// if (interfaceType === 'input') {
|
|
// field.componentProps.ellipsis = true;
|
|
// } else if (interfaceType === 'textarea') {
|
|
// field.componentProps.ellipsis = true;
|
|
// } else if (interfaceType === 'markdown') {
|
|
// field.componentProps.ellipsis = true;
|
|
// } else if (interfaceType === 'attachment') {
|
|
// field.componentProps.size = 'small';
|
|
// }
|
|
}, [JSON.stringify(uiSchema)]);
|
|
if (!uiSchema) {
|
|
return null;
|
|
}
|
|
return React.createElement(component, props, props.children);
|
|
};
|
|
|
|
export const InternalFallbackField = () => {
|
|
const { uiSchema } = useCollectionField();
|
|
const field = useField<Field>();
|
|
const fieldSchema = useFieldSchema();
|
|
const record = useRecord();
|
|
|
|
const displayKey = fieldSchema['x-component-props']?.fieldNames?.label ?? 'id';
|
|
|
|
const value = record[fieldSchema.name];
|
|
|
|
useEffect(() => {
|
|
field.title = fieldSchema.title ?? fieldSchema.name;
|
|
}, [uiSchema?.title]);
|
|
|
|
let displayText = value;
|
|
|
|
if (Array.isArray(value) || typeof value === 'object') {
|
|
displayText = []
|
|
.concat(value)
|
|
.map((i) => i[displayKey])
|
|
.join(', ');
|
|
}
|
|
|
|
return <div>{displayText}</div>;
|
|
};
|
|
|
|
export const CollectionField = connect((props) => {
|
|
const fieldSchema = useFieldSchema();
|
|
const field = fieldSchema?.['x-component-props']?.['field'];
|
|
const { snapshot } = useActionContext();
|
|
return (
|
|
<CollectionFieldProvider
|
|
name={fieldSchema.name}
|
|
field={field}
|
|
fallback={snapshot ? <InternalFallbackField /> : null}
|
|
>
|
|
<InternalField {...props} />
|
|
</CollectionFieldProvider>
|
|
);
|
|
});
|
|
|
|
export default CollectionField;
|