import { ArrayTable } from '@formily/antd-v5';
import { ISchema, useForm } from '@formily/react';
import { uid } from '@formily/shared';
import cloneDeep from 'lodash/cloneDeep';
import omit from 'lodash/omit';
import set from 'lodash/set';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import {
useAPIClient,
IField,
useRequest,
RecordProvider,
useRecord,
ActionContextProvider,
SchemaComponent,
useActionContext,
useCompile,
useResourceActionContext,
useCancelAction,
useCollectionManager_deprecated,
useCurrentAppInfo,
useCollectionParentRecordData,
useDataSourceManager,
} from '@nocobase/client';
import { useRemoteCollectionContext } from './CollectionFields';
const getSchema = ({
schema,
record,
parentRecord,
compile,
getContainer,
}: {
schema: IField;
record: any;
parentRecord: any;
compile;
getContainer;
}): ISchema => {
if (!schema) {
return;
}
const properties = cloneDeep(schema.properties) as any;
if (properties?.name) {
properties.name['x-disabled'] = true;
}
if (schema.hasDefaultValue === true) {
properties['defaultValue'] = cloneDeep(schema.default.uiSchema) || {};
properties.defaultValue.required = false;
properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
properties['defaultValue']['x-decorator'] = 'FormItem';
properties['defaultValue']['x-reactions'] = {
dependencies: [
'uiSchema.x-component-props.gmt',
'uiSchema.x-component-props.showTime',
'uiSchema.x-component-props.dateFormat',
'uiSchema.x-component-props.timeFormat',
],
fulfill: {
state: {
componentProps: {
gmt: '{{$deps[0]}}',
showTime: '{{$deps[1]}}',
dateFormat: '{{$deps[2]}}',
timeFormat: '{{$deps[3]}}',
},
},
},
};
properties['defaultValue']['x-disabled'] = true;
}
return {
type: 'object',
properties: {
[uid()]: {
type: 'void',
'x-component': 'Action.Drawer',
'x-component-props': {
getContainer: '{{ getContainer }}',
},
'x-decorator': 'Form',
'x-decorator-props': {
useValues(options) {
return useRequest(
() =>
Promise.resolve({
data: cloneDeep(omit(schema.default, ['uiSchema.rawTitle'])),
}),
options,
);
},
},
title: `${compile(parentRecord?.title || parentRecord?.name)} - ${compile('{{ t("Edit field") }}')}`,
properties: {
summary: {
type: 'void',
'x-component': 'FieldSummary',
'x-component-props': {
schemaKey: schema.name,
},
},
// @ts-ignore
...properties,
description: {
type: 'string',
title: '{{t("Description")}}',
'x-decorator': 'FormItem',
'x-component': 'Input.TextArea',
},
footer: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
properties: {
action1: {
title: '{{ t("Cancel") }}',
'x-component': 'Action',
'x-component-props': {
useAction: '{{ useCancelAction }}',
},
},
action2: {
title: '{{ t("Submit") }}',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
useAction: '{{ useUpdateCollectionField }}',
},
},
},
},
},
},
},
};
};
const useUpdateCollectionField = () => {
const form = useForm();
const api = useAPIClient();
const ctx = useActionContext();
const { refresh } = useResourceActionContext();
const { targetCollection } = useRemoteCollectionContext();
const { name: dataSourceKey } = useParams();
const { name: filterByTk } = useRecord();
const dm = useDataSourceManager();
return {
async run() {
await form.submit();
const values = cloneDeep(form.values);
if (values.autoCreateReverseField) {
/* empty */
} else {
delete values.reverseField;
}
delete values.autoCreateReverseField;
await api.request({
url: `dataSourcesCollections/${dataSourceKey}.${targetCollection.name}/fields:update?filterByTk=${filterByTk}`,
method: 'post',
data: values,
});
ctx.setVisible(false);
dm.getDataSource(dataSourceKey).reload();
await form.reset();
refresh();
},
};
};
export const EditCollectionField = (props) => {
const record = useRecord();
const parentRecordData = useCollectionParentRecordData();
return ;
};
const EditFieldAction = (props) => {
const { scope, getContainer, item: record, parentItem: parentRecord, children, ...otherProps } = props;
const { getInterface, collections, getCollection } = useCollectionManager_deprecated();
const {
data: { database: currentDatabase },
} = useCurrentAppInfo();
const [visible, setVisible] = useState(false);
const [schema, setSchema] = useState({});
const api = useAPIClient();
const { t } = useTranslation();
const compile = useCompile();
const { name } = useParams();
const isDialect = (dialect: string) => currentDatabase?.dialect === dialect;
const currentCollections = useMemo(() => {
return collections.map((v) => {
return {
label: compile(v.title),
value: v.name,
};
});
}, []);
const scopeKeyOptions = useMemo(() => {
return (
record?.fields ||
getCollection(record.collectionName, name)
?.options?.fields.filter((v) => {
return v.interface === 'select';
})
.map((k) => {
return {
value: k.name,
label: compile(k.uiSchema?.title),
};
})
);
}, [record.name]);
return (
{
const { data } = await api.request({
url: `dataSourcesCollections/${name}.${parentRecord.name}/fields:get?filterByTk=${record.name}`,
params: { appends: ['reverseField'] },
});
const interfaceConf = getInterface(data?.data?.interface);
const defaultValues: any = cloneDeep(data?.data) || {};
if (!defaultValues?.reverseField) {
defaultValues.autoCreateReverseField = false;
defaultValues.reverseField = interfaceConf?.default?.reverseField;
set(defaultValues.reverseField, 'name', `f_${uid()}`);
set(defaultValues.reverseField, 'uiSchema.title', record.__parent?.title);
}
const schema = getSchema({
schema: {
...interfaceConf,
default: defaultValues,
},
record,
parentRecord,
compile,
getContainer,
});
setSchema(schema);
setVisible(true);
}}
>
{children || t('Edit')}
);
};