feat: default value (#679)

* feat: default value

* feat: add global default value

* fix: field default value should be updated

* feat: adjust defaultValue logic

* feat: add hasDefaultValue property

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
金昶 2022-08-03 09:32:16 +08:00 committed by GitHub
parent b9fb69c7aa
commit f4f35bdb43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 132 additions and 2 deletions

View File

@ -11,7 +11,9 @@ import { useCollectionField } from './hooks';
const InternalField: React.FC = (props) => {
const field = useField<Field>();
const fieldSchema = useFieldSchema();
const { name, interface: interfaceType, uiSchema } = useCollectionField();
const { name, interface: interfaceType, uiSchema, defaultValue } = useCollectionField();
const collectionField = useCollectionField();
const component = useComponent(uiSchema?.['x-component']);
const compile = useCompile();
const setFieldProps = (key, value) => {
@ -38,7 +40,10 @@ const InternalField: React.FC = (props) => {
setFieldProps('content', uiSchema['x-content']);
setFieldProps('title', uiSchema.title);
setFieldProps('description', uiSchema.description);
setFieldProps('initialValue', uiSchema.default);
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;

View File

@ -19,7 +19,15 @@ const getSchema = (schema: IField, record: any, compile): ISchema => {
if (!schema) {
return;
}
const properties = cloneDeep(schema.properties) as any;
if (schema.hasDefaultValue === true) {
properties['defaultValue'] = cloneDeep(schema.default.uiSchema);
properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
properties['defaultValue']['x-decorator'] = 'FormItem';
}
const initialValue = {
name: `f_${uid()}`,
...cloneDeep(schema.default),

View File

@ -19,6 +19,13 @@ const getSchema = (schema: IField, record: any, compile): ISchema => {
}
const properties = cloneDeep(schema.properties) as any;
properties.name['x-disabled'] = true;
if (schema.hasDefaultValue === true) {
properties['defaultValue'] = cloneDeep(schema.default.uiSchema);
properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
properties['defaultValue']['x-decorator'] = 'FormItem';
}
return {
type: 'object',
properties: {

View File

@ -15,6 +15,7 @@ export const checkbox: IField = {
'x-component': 'Checkbox',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -17,6 +17,7 @@ export const checkboxGroup: IField = {
'x-component': 'Checkbox.Group',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.enum': dataSource,

View File

@ -20,6 +20,7 @@ export const datetime: IField = {
},
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
...dateTimeProps,

View File

@ -18,6 +18,7 @@ export const email: IField = {
'x-validator': 'email',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -16,6 +16,7 @@ export const icon: IField = {
'x-component': 'IconPicker',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -18,6 +18,7 @@ export const input: IField = {
'x-component': 'Input',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -30,6 +30,7 @@ export const integer: IField = {
'x-validator': 'integer',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -17,6 +17,7 @@ export const markdown: IField = {
'x-component': 'Markdown',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -21,6 +21,7 @@ export const multipleSelect: IField = {
enum: [],
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.enum': dataSource,

View File

@ -24,6 +24,7 @@ export const number: IField = {
},
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.x-component-props.step': {

View File

@ -18,6 +18,7 @@ export const password: IField = {
'x-component': 'Password',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -68,6 +68,7 @@ export const percent: IField = {
},
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.x-component-props.step': {

View File

@ -21,6 +21,7 @@ export const phone: IField = {
// 'x-validator': 'phone',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -17,6 +17,7 @@ export const radioGroup: IField = {
'x-component': 'Radio.Group',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.enum': dataSource,

View File

@ -18,6 +18,7 @@ export const richText: IField = {
'x-component': 'RichText',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -18,6 +18,7 @@ export const select: IField = {
enum: [],
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.enum': dataSource,

View File

@ -18,6 +18,7 @@ export const textarea: IField = {
'x-component': 'Input.TextArea',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
},

View File

@ -16,6 +16,7 @@ export const time: IField = {
'x-component': 'TimePicker',
},
},
hasDefaultValue: true,
properties: {
...defaultProps,
'uiSchema.x-component-props.format': {

View File

@ -255,6 +255,8 @@ export default {
"The field value cannot be greater than ": "数值不能大于",
"The field value cannot be less than ": "数值不能小于",
"The field value is not an integer number": "数字不是整数",
"Set default value": "设置默认值",
"Default value": "默认值",
"is before": "早于",
"is after": "晚于",

View File

@ -326,6 +326,39 @@ FormItem.Designer = (props) => {
}}
/>
)}
{form && !form?.readPretty && collectionField?.uiSchema?.type && (
<SchemaSettings.ModalItem
title={t('Set default value')}
components={{ ArrayCollapse, FormLayout }}
schema={{
type: 'object',
title: t('Set default value'),
properties: {
default: {
...collectionField.uiSchema,
name: 'default',
title: t('Default value'),
'x-decorator': 'FormItem',
default: fieldSchema.default || collectionField.defaultValue,
}
}
} as ISchema}
onSubmit={(v) => {
const schema: ISchema = {
['x-uid']: fieldSchema['x-uid'],
};
if (field.value !== v.default) {
field.value = v.default;
}
fieldSchema.default = v.default;
schema.default = v.default;
dn.emit('patch', {
schema,
});
refresh();
}}
/>
)}
{form && !isSubFormAssocitionField && ['o2o', 'oho', 'obo', 'o2m'].includes(collectionField?.interface) && (
<SchemaSettings.SelectItem
title={t('Field component')}

View File

@ -0,0 +1,51 @@
import { MockServer } from '@nocobase/test';
import { createApp } from '..';
describe('field defaultValue', () => {
let app: MockServer;
beforeEach(async () => {
app = await createApp();
await app.install({ clean: true });
await app.start();
await app
.agent()
.resource('collections')
.create({
values: {
name: 'test1',
},
});
});
afterEach(async () => {
await app.destroy();
});
it('should be updated', async () => {
await app
.agent()
.resource('collections.fields', 'test1')
.create({
values: {
name: 'field1',
type: 'string',
defaultValue: 'abc',
},
});
const response1 = await app.agent().resource('test1').create();
expect(response1.body.data.field1).toBe('abc');
await app
.agent()
.resource('collections.fields', 'test1')
.update({
filterByTk: 'field1',
values: {
type: 'string',
defaultValue: 'cba',
},
});
const response2 = await app.agent().resource('test1').create();
expect(response2.body.data.field1).toBe('cba');
});
});

View File

@ -70,6 +70,12 @@ export class CollectionManagerPlugin extends Plugin {
}
});
this.app.db.on('fields.afterUpdateWithAssociations', async (model, { context, transaction }) => {
if (context) {
await model.load({ transaction });
}
});
this.app.db.on('fields.afterCreateWithAssociations', async (model, { context, transaction }) => {
if (context) {
await model.load({ transaction });