Merge remote-tracking branch 'hera/@hera/dev' into feat_drawer_in_page
This commit is contained in:
commit
85ba307506
@ -267,6 +267,7 @@
|
|||||||
"Sub-table": "Sub-table",
|
"Sub-table": "Sub-table",
|
||||||
"Sub-details": "Sub-details",
|
"Sub-details": "Sub-details",
|
||||||
"Sub-form(Popover)": "Sub-form(Popover)",
|
"Sub-form(Popover)": "Sub-form(Popover)",
|
||||||
|
"Sub-form(Drawer)": "Sub-form(Drawer)",
|
||||||
"System info": "System info",
|
"System info": "System info",
|
||||||
"Created at": "Created at",
|
"Created at": "Created at",
|
||||||
"Last updated at": "Last updated at",
|
"Last updated at": "Last updated at",
|
||||||
|
@ -331,6 +331,7 @@
|
|||||||
"Subtable": "子表格",
|
"Subtable": "子表格",
|
||||||
"Sub-form": "子表单",
|
"Sub-form": "子表单",
|
||||||
"Sub-form(Popover)": "子表单(弹窗)",
|
"Sub-form(Popover)": "子表单(弹窗)",
|
||||||
|
"Sub-form(Drawer)": "子表单(抽屉)",
|
||||||
"Sub-details": "子详情",
|
"Sub-details": "子详情",
|
||||||
"Record picker": "数据选择器",
|
"Record picker": "数据选择器",
|
||||||
"Toggles the subfield mode": "切换子字段模式",
|
"Toggles the subfield mode": "切换子字段模式",
|
||||||
|
@ -4,12 +4,12 @@ import { RecursionField, connect, mapProps, observer, useField, useFieldSchema,
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import { Space, message } from 'antd';
|
import { Space, message } from 'antd';
|
||||||
import { isFunction } from 'mathjs';
|
import { isFunction } from 'mathjs';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { RecordProvider, useAPIClient, useCollectionRecordData } from '../../../';
|
import { RecordProvider, useAPIClient, useApp, useCollectionRecordData } from '../../../';
|
||||||
import { isVariable } from '../../../variables/utils/isVariable';
|
import { isVariable } from '../../../variables/utils/isVariable';
|
||||||
import { getInnermostKeyAndValue } from '../../common/utils/uitls';
|
import { getInnermostKeyAndValue } from '../../common/utils/uitls';
|
||||||
import { RemoteSelect, RemoteSelectProps } from '../remote-select';
|
import { RemoteSelectProps } from '../remote-select';
|
||||||
import useServiceOptions, { useAssociationFieldContext } from './hooks';
|
import useServiceOptions, { useAssociationFieldContext } from './hooks';
|
||||||
|
|
||||||
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
|
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
|
||||||
@ -60,6 +60,9 @@ const InternalAssociationSelect = observer(
|
|||||||
const resource = api.resource(collectionField.target);
|
const resource = api.resource(collectionField.target);
|
||||||
const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
|
const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
|
||||||
const recordData = useCollectionRecordData();
|
const recordData = useCollectionRecordData();
|
||||||
|
const app = useApp();
|
||||||
|
const RemoteSelect = useMemo(() => app.getComponent('RemoteSelect'), [app]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initValue = isVariable(field.value) ? undefined : field.value;
|
const initValue = isVariable(field.value) ? undefined : field.value;
|
||||||
const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
|
const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
|
||||||
@ -165,6 +168,8 @@ export const AssociationSelect = InternalAssociationSelect as unknown as Associa
|
|||||||
export const AssociationSelectReadPretty = connect(
|
export const AssociationSelectReadPretty = connect(
|
||||||
(props: any) => {
|
(props: any) => {
|
||||||
const service = useServiceOptions(props);
|
const service = useServiceOptions(props);
|
||||||
|
const app = useApp();
|
||||||
|
const RemoteSelect = useMemo(() => app.getComponent('RemoteSelect'), [app]) as any;
|
||||||
if (props.fieldNames) {
|
if (props.fieldNames) {
|
||||||
return <RemoteSelect.ReadPretty {...props} service={service}></RemoteSelect.ReadPretty>;
|
return <RemoteSelect.ReadPretty {...props} service={service}></RemoteSelect.ReadPretty>;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ import { InternaPopoverNester } from './InternalPopoverNester';
|
|||||||
import { InternalSubTable } from './InternalSubTable';
|
import { InternalSubTable } from './InternalSubTable';
|
||||||
import { CreateRecordAction } from './components/CreateRecordAction';
|
import { CreateRecordAction } from './components/CreateRecordAction';
|
||||||
import { useAssociationFieldContext } from './hooks';
|
import { useAssociationFieldContext } from './hooks';
|
||||||
|
import { InternalCascader } from './InternalCascader';
|
||||||
|
import { InternaDrawerSubTable } from './InternalDrawerSubTable';
|
||||||
|
|
||||||
const EditableAssociationField = observer(
|
const EditableAssociationField = observer(
|
||||||
(props: any) => {
|
(props: any) => {
|
||||||
@ -57,6 +59,8 @@ const EditableAssociationField = observer(
|
|||||||
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
|
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
|
||||||
{currentMode === 'FileManager' && <InternalFileManager {...props} />}
|
{currentMode === 'FileManager' && <InternalFileManager {...props} />}
|
||||||
{currentMode === 'CascadeSelect' && <InternalCascadeSelect {...props} />}
|
{currentMode === 'CascadeSelect' && <InternalCascadeSelect {...props} />}
|
||||||
|
{currentMode === 'DrawerSubTable' && <InternaDrawerSubTable {...props} />}
|
||||||
|
{currentMode === 'Cascader' && <InternalCascader {...props} />}
|
||||||
</SchemaComponentOptions>
|
</SchemaComponentOptions>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -4,9 +4,12 @@ import { observer } from '@formily/react';
|
|||||||
import React, { useContext, useRef, useState } from 'react';
|
import React, { useContext, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { InternalSubTable } from './InternalSubTable';
|
import { InternalSubTable } from './InternalSubTable';
|
||||||
import { ActionContext, ActionContextProvider, __UNSAFE__, useGetAriaLabelOfPopover } from '@nocobase/client';
|
|
||||||
import { Button, Drawer } from 'antd';
|
import { Button, Drawer } from 'antd';
|
||||||
const { useAssociationFieldContext, useSetAriaLabelForPopover, ReadPrettyInternalViewer } = __UNSAFE__;
|
import { useAssociationFieldContext } from './hooks';
|
||||||
|
import { ActionContext, ActionContextProvider } from '../action/context';
|
||||||
|
import { useGetAriaLabelOfPopover } from '../action';
|
||||||
|
import { ReadPrettyInternalViewer } from './InternalViewer';
|
||||||
|
import { useSetAriaLabelForPopover } from '../action/hooks/useSetAriaLabelForPopover';
|
||||||
|
|
||||||
export const InternaDrawerSubTable = observer(
|
export const InternaDrawerSubTable = observer(
|
||||||
(props) => {
|
(props) => {
|
@ -55,6 +55,7 @@ export const useFieldModeOptions = (props?) => {
|
|||||||
{ label: t('Cascade Select'), value: 'CascadeSelect' },
|
{ label: t('Cascade Select'), value: 'CascadeSelect' },
|
||||||
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
||||||
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
||||||
|
{ label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
|
||||||
{ label: t('Cascader'), value: 'Cascader' },
|
{ label: t('Cascader'), value: 'Cascader' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -72,6 +73,7 @@ export const useFieldModeOptions = (props?) => {
|
|||||||
{ label: t('Record picker'), value: 'Picker' },
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
||||||
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
||||||
|
{ label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
|
||||||
!isTableField && { label: t('Sub-table'), value: 'SubTable' },
|
!isTableField && { label: t('Sub-table'), value: 'SubTable' },
|
||||||
];
|
];
|
||||||
case 'm2m':
|
case 'm2m':
|
||||||
@ -88,6 +90,7 @@ export const useFieldModeOptions = (props?) => {
|
|||||||
!isTableField && { label: t('Sub-table'), value: 'SubTable' },
|
!isTableField && { label: t('Sub-table'), value: 'SubTable' },
|
||||||
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
||||||
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
||||||
|
{ label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
|
||||||
];
|
];
|
||||||
case 'm2o':
|
case 'm2o':
|
||||||
case 'linkTo':
|
case 'linkTo':
|
||||||
@ -102,6 +105,7 @@ export const useFieldModeOptions = (props?) => {
|
|||||||
{ label: t('Record picker'), value: 'Picker' },
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
||||||
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
||||||
|
{ label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
|
||||||
{ label: t('Cascader'), value: 'Cascader' },
|
{ label: t('Cascader'), value: 'Cascader' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -117,6 +121,7 @@ export const useFieldModeOptions = (props?) => {
|
|||||||
{ label: t('Record picker'), value: 'Picker' },
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
!isTableField && { label: t('Sub-form'), value: 'Nester' },
|
||||||
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
{ label: t('Sub-form(Popover)'), value: 'PopoverNester' },
|
||||||
|
{ label: t('Sub-form(Drawer)'), value: 'DrawerSubTable' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}, [t, collectionField?.interface, label]);
|
}, [t, collectionField?.interface, label]);
|
||||||
|
@ -31,7 +31,6 @@ import { useFieldSchema } from '@formily/react';
|
|||||||
import { isValid } from '@formily/shared';
|
import { isValid } from '@formily/shared';
|
||||||
import { useCreateActionProps } from './hooks/useCreateActionProps';
|
import { useCreateActionProps } from './hooks/useCreateActionProps';
|
||||||
import { useOutboundActionProps } from './hooks/useOutboundActionProps';
|
import { useOutboundActionProps } from './hooks/useOutboundActionProps';
|
||||||
import { ExtendedAssociationField } from './schema-components/association-field/Editable';
|
|
||||||
import { AssociatedField } from './components/AssociatedField';
|
import { AssociatedField } from './components/AssociatedField';
|
||||||
import { DatePicker } from './schema-components/date-picker';
|
import { DatePicker } from './schema-components/date-picker';
|
||||||
import { SettingBlockInitializer } from './schema-initializer/SettingBlockInitializer';
|
import { SettingBlockInitializer } from './schema-initializer/SettingBlockInitializer';
|
||||||
@ -156,7 +155,6 @@ export class PluginCoreClient extends Plugin {
|
|||||||
DatePicker,
|
DatePicker,
|
||||||
RemoteSelect,
|
RemoteSelect,
|
||||||
SignatureInput,
|
SignatureInput,
|
||||||
AssociationField: ExtendedAssociationField,
|
|
||||||
OutboundButton,
|
OutboundButton,
|
||||||
OutboundLinkActionInitializer,
|
OutboundLinkActionInitializer,
|
||||||
PDFViewerBlockInitializer,
|
PDFViewerBlockInitializer,
|
||||||
|
@ -1,182 +0,0 @@
|
|||||||
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
|
|
||||||
import { onFieldChange, FormPath } from '@formily/core';
|
|
||||||
import { RecursionField, connect, mapProps, observer, useField, useFieldSchema, useForm } from '@formily/react';
|
|
||||||
import { uid } from '@formily/shared';
|
|
||||||
import { Space, message } from 'antd';
|
|
||||||
import { isFunction } from 'mathjs2';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { RecordProvider, RemoteSelectProps, useAPIClient } from '@nocobase/client';
|
|
||||||
import { __UNSAFE__ } from '@nocobase/client';
|
|
||||||
import { RemoteSelect } from '../remote-select';
|
|
||||||
|
|
||||||
const { getInnermostKeyAndValue, useServiceOptions, useAssociationFieldContext, isVariable } = __UNSAFE__;
|
|
||||||
|
|
||||||
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
|
|
||||||
action?: string;
|
|
||||||
multiple?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const filterAnalyses = (filters): any[] => {
|
|
||||||
if (!filters) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const type = Object.keys(filters)[0] || '$and';
|
|
||||||
const conditions = filters[type];
|
|
||||||
const results = [];
|
|
||||||
conditions?.map((c) => {
|
|
||||||
const jsonlogic = getInnermostKeyAndValue(c);
|
|
||||||
const operator = jsonlogic?.key;
|
|
||||||
|
|
||||||
if (!operator) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const regex = /\{\{\$(?:[a-zA-Z_]\w*)\.([a-zA-Z_]\w*)(?:\.id)?\}\}/;
|
|
||||||
const fieldName = jsonlogic?.value?.match?.(regex)?.[1];
|
|
||||||
if (fieldName) {
|
|
||||||
results.push(fieldName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
|
|
||||||
const { objectValue = true } = props;
|
|
||||||
const field: any = useField();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const service = useServiceOptions(props);
|
|
||||||
const { options: collectionField } = useAssociationFieldContext();
|
|
||||||
const initValue = isVariable(props.value) ? undefined : props.value;
|
|
||||||
const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
|
|
||||||
// 因为通过 Schema 的形式书写的组件,在值变更的时候 `value` 的值没有改变,所以需要维护一个 `innerValue` 来变更值
|
|
||||||
const [innerValue, setInnerValue] = useState(value);
|
|
||||||
const addMode = fieldSchema['x-component-props']?.addMode;
|
|
||||||
const isAllowAddNew = fieldSchema['x-add-new'];
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { multiple } = props;
|
|
||||||
const form = useForm();
|
|
||||||
const api = useAPIClient();
|
|
||||||
const resource = api.resource(collectionField.target);
|
|
||||||
const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
|
|
||||||
useEffect(() => {
|
|
||||||
const initValue = isVariable(field.value) ? undefined : field.value;
|
|
||||||
const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
|
|
||||||
setInnerValue(value);
|
|
||||||
}, [field.value]);
|
|
||||||
useEffect(() => {
|
|
||||||
const id = uid();
|
|
||||||
form.addEffects(id, () => {
|
|
||||||
if (linkageFields?.length > 0) {
|
|
||||||
//支持深层次子表单
|
|
||||||
onFieldChange('*', (fieldPath: any) => {
|
|
||||||
if (linkageFields.includes(fieldPath.props.name) && field.value) {
|
|
||||||
props.onChange(field.initialValue);
|
|
||||||
setInnerValue(field.initialValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
form.removeEffects(id);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleCreateAction = async (props) => {
|
|
||||||
const { search: value, callBack } = props;
|
|
||||||
const {
|
|
||||||
data: { data },
|
|
||||||
} = await resource.create({
|
|
||||||
values: {
|
|
||||||
[field?.componentProps?.fieldNames?.label || 'id']: value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (data) {
|
|
||||||
if (['m2m', 'o2m'].includes(collectionField?.interface) && multiple !== false) {
|
|
||||||
const values = form.getValuesIn(field.path) || [];
|
|
||||||
values.push(data);
|
|
||||||
form.setValuesIn(field.path, values);
|
|
||||||
field.onInput(values);
|
|
||||||
} else {
|
|
||||||
form.setValuesIn(field.path, data);
|
|
||||||
field.onInput(data);
|
|
||||||
}
|
|
||||||
isFunction(callBack) && callBack?.();
|
|
||||||
message.success(t('Saved successfully'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const QuickAddContent = (props) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onClick={() => handleCreateAction(props)}
|
|
||||||
style={{ cursor: 'pointer', padding: '5px 12px', color: '#0d0c0c' }}
|
|
||||||
>
|
|
||||||
<PlusOutlined />
|
|
||||||
<span style={{ paddingLeft: 5 }}>{t('Add') + ` “${props.search}” `}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div key={fieldSchema.name}>
|
|
||||||
<Space.Compact style={{ display: 'flex', lineHeight: '32px' }}>
|
|
||||||
<RemoteSelect
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
{...props}
|
|
||||||
size={'middle'}
|
|
||||||
objectValue={objectValue}
|
|
||||||
value={value || innerValue}
|
|
||||||
service={service}
|
|
||||||
onChange={(value) => {
|
|
||||||
const val = value?.length !== 0 ? value : null;
|
|
||||||
props.onChange?.(val);
|
|
||||||
}}
|
|
||||||
CustomDropdownRender={addMode === 'quickAdd' && QuickAddContent}
|
|
||||||
></RemoteSelect>
|
|
||||||
|
|
||||||
{(addMode === 'modalAdd' || isAllowAddNew) && (
|
|
||||||
<RecordProvider record={null}>
|
|
||||||
<RecursionField
|
|
||||||
onlyRenderProperties
|
|
||||||
basePath={field.address}
|
|
||||||
schema={fieldSchema}
|
|
||||||
filterProperties={(s) => {
|
|
||||||
return s['x-component'] === 'Action';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</RecordProvider>
|
|
||||||
)}
|
|
||||||
</Space.Compact>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
interface AssociationSelectInterface {
|
|
||||||
(props: any): React.ReactElement;
|
|
||||||
Designer: React.FC;
|
|
||||||
FilterDesigner: React.FC;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AssociationSelect = InternalAssociationSelect as unknown as AssociationSelectInterface;
|
|
||||||
|
|
||||||
export const AssociationSelectReadPretty = connect(
|
|
||||||
(props: any) => {
|
|
||||||
const service = useServiceOptions(props);
|
|
||||||
if (props.fieldNames) {
|
|
||||||
return <RemoteSelect.ReadPretty {...props} service={service}></RemoteSelect.ReadPretty>;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
mapProps(
|
|
||||||
{
|
|
||||||
dataSource: 'options',
|
|
||||||
loading: true,
|
|
||||||
},
|
|
||||||
(props, field) => {
|
|
||||||
return {
|
|
||||||
...props,
|
|
||||||
fieldNames: props.fieldNames && { ...props.fieldNames, ...field.componentProps.fieldNames },
|
|
||||||
suffixIcon: field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffixIcon,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
@ -1,95 +0,0 @@
|
|||||||
import { Field } from '@formily/core';
|
|
||||||
import { connect, mapReadPretty, observer, useField, useForm } from '@formily/react';
|
|
||||||
import React from 'react';
|
|
||||||
import {
|
|
||||||
SchemaComponentOptions,
|
|
||||||
useCollection_deprecated,
|
|
||||||
useAssociationCreateActionProps as useCAP,
|
|
||||||
Action,
|
|
||||||
__UNSAFE__,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
import { InternaDrawerSubTable } from './InternalDrawerSubTable';
|
|
||||||
import { AssociationSelect } from './AssociationSelect';
|
|
||||||
const {
|
|
||||||
CreateRecordAction,
|
|
||||||
useAssociationFieldContext,
|
|
||||||
InternalPicker,
|
|
||||||
InternalNester,
|
|
||||||
AssociationFieldProvider,
|
|
||||||
InternaPopoverNester,
|
|
||||||
InternalSubTable,
|
|
||||||
InternalCascader,
|
|
||||||
InternalFileManager,
|
|
||||||
InternalCascadeSelect,
|
|
||||||
SubTable,
|
|
||||||
ReadPretty,
|
|
||||||
Nester,
|
|
||||||
} = __UNSAFE__;
|
|
||||||
|
|
||||||
const EditableAssociationField = observer(
|
|
||||||
(props: any) => {
|
|
||||||
const { multiple } = props;
|
|
||||||
const field: Field = useField();
|
|
||||||
const form = useForm();
|
|
||||||
const { options: collectionField, currentMode } = useAssociationFieldContext();
|
|
||||||
|
|
||||||
const useCreateActionProps = () => {
|
|
||||||
const { onClick } = useCAP();
|
|
||||||
const actionField: any = useField();
|
|
||||||
const { getPrimaryKey } = useCollection_deprecated();
|
|
||||||
const primaryKey = getPrimaryKey();
|
|
||||||
return {
|
|
||||||
async onClick() {
|
|
||||||
await onClick();
|
|
||||||
const { data } = actionField.data?.data?.data || {};
|
|
||||||
if (data) {
|
|
||||||
if (['m2m', 'o2m'].includes(collectionField?.interface) && multiple !== false) {
|
|
||||||
const values = form.getValuesIn(field.path) || [];
|
|
||||||
if (!values.find((v) => v[primaryKey] === data[primaryKey])) {
|
|
||||||
values.push(data);
|
|
||||||
form.setValuesIn(field.path, values);
|
|
||||||
field.onInput(values);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
form.setValuesIn(field.path, data);
|
|
||||||
field.onInput(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<SchemaComponentOptions scope={{ useCreateActionProps }} components={{ CreateRecordAction }}>
|
|
||||||
{currentMode === 'Picker' && <InternalPicker {...props} />}
|
|
||||||
{currentMode === 'Nester' && <InternalNester {...props} />}
|
|
||||||
{currentMode === 'PopoverNester' && <InternaPopoverNester {...props} />}
|
|
||||||
{currentMode === 'Select' && <AssociationSelect {...props} />}
|
|
||||||
{currentMode === 'SubTable' && <InternalSubTable {...props} />}
|
|
||||||
{currentMode === 'FileManager' && <InternalFileManager {...props} />}
|
|
||||||
{currentMode === 'CascadeSelect' && <InternalCascadeSelect {...props} />}
|
|
||||||
{currentMode === 'DrawerSubTable' && <InternaDrawerSubTable {...props} />}
|
|
||||||
{currentMode === 'Cascader' && <InternalCascader {...props} />}
|
|
||||||
</SchemaComponentOptions>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'EditableAssociationField' },
|
|
||||||
);
|
|
||||||
|
|
||||||
const ExtendedEditable = observer(
|
|
||||||
(props) => {
|
|
||||||
return (
|
|
||||||
<AssociationFieldProvider>
|
|
||||||
<EditableAssociationField {...props} />
|
|
||||||
</AssociationFieldProvider>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'ExtendedEditable' },
|
|
||||||
);
|
|
||||||
|
|
||||||
export const ExtendedAssociationField: any = connect(ExtendedEditable, mapReadPretty(ReadPretty));
|
|
||||||
ExtendedAssociationField.SubTable = SubTable;
|
|
||||||
ExtendedAssociationField.Nester = Nester;
|
|
||||||
ExtendedAssociationField.AddNewer = Action.Container;
|
|
||||||
ExtendedAssociationField.Selector = Action.Container;
|
|
||||||
ExtendedAssociationField.Viewer = Action.Container;
|
|
||||||
ExtendedAssociationField.InternalSelect = InternalPicker;
|
|
@ -1,69 +0,0 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
|
||||||
import { FormLayout } from '@formily/antd-v5';
|
|
||||||
import { RecursionField, useField, useFieldSchema, observer } from '@formily/react';
|
|
||||||
import React, { useEffect } from 'react';
|
|
||||||
import { useInsertSchema } from '../../components/AssociatedField';
|
|
||||||
import {
|
|
||||||
ACLCollectionProvider,
|
|
||||||
CollectionProvider_deprecated,
|
|
||||||
__UNSAFE__,
|
|
||||||
useACLActionParamsContext,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
const { useAssociationFieldContext, schema } = __UNSAFE__;
|
|
||||||
|
|
||||||
export const InternalSubTable = observer(
|
|
||||||
() => {
|
|
||||||
const field = useField();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const insertNester = useInsertSchema('SubTable');
|
|
||||||
const { options: collectionField } = useAssociationFieldContext();
|
|
||||||
const showTitle = fieldSchema['x-decorator-props']?.showTitle ?? true;
|
|
||||||
const { actionName } = useACLActionParamsContext();
|
|
||||||
useEffect(() => {
|
|
||||||
insertNester(schema.SubTable);
|
|
||||||
}, []);
|
|
||||||
return (
|
|
||||||
<CollectionProvider_deprecated name={collectionField.target}>
|
|
||||||
<ACLCollectionProvider actionPath={`${collectionField.target}:${actionName}`}>
|
|
||||||
<FormLayout layout={'vertical'}>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
css`
|
|
||||||
& .ant-formily-item-layout-vertical {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.ant-card-body {
|
|
||||||
padding: 15px 20px 5px;
|
|
||||||
}
|
|
||||||
.ant-divider-horizontal {
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
[css`
|
|
||||||
.ant-card-body {
|
|
||||||
padding: 0px 20px 20px 0px;
|
|
||||||
}
|
|
||||||
> .ant-card-bordered {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
`]: showTitle === false,
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<RecursionField
|
|
||||||
onlyRenderProperties
|
|
||||||
basePath={field.address}
|
|
||||||
schema={fieldSchema}
|
|
||||||
filterProperties={(s) => {
|
|
||||||
return s['x-component'] === 'AssociationField.SubTable';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</FormLayout>
|
|
||||||
</ACLCollectionProvider>
|
|
||||||
</CollectionProvider_deprecated>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'InternalSubTable' },
|
|
||||||
);
|
|
Loading…
Reference in New Issue
Block a user