feat: 添加移动端选择框组件 (#1093)
Reviewed-on: daoyoucloud/tachybase#1093 Reviewed-by: sealday <zhanglin@daoyoucloud.com> Co-authored-by: wangjiahui <wwwjh0710@163.com> Co-committed-by: wangjiahui <wwwjh0710@163.com>
This commit is contained in:
parent
ab49b68213
commit
bc0f05ded2
@ -1,12 +1,14 @@
|
||||
import { Field } from '@tachybase/schema';
|
||||
import { useField, useFieldSchema } from '@tachybase/schema';
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { Field, useField, useFieldSchema } from '@tachybase/schema';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
|
||||
import { useFormBlockContext } from '../../../../block-provider';
|
||||
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../../../collection-manager';
|
||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../../collection-manager';
|
||||
import { useFieldComponentName } from '../../../../common/useFieldComponentName';
|
||||
import { useCollectionField } from '../../../../data-source';
|
||||
import { useRecord } from '../../../../record-provider';
|
||||
import { removeNullCondition, useDesignable, useFieldModeOptions, useIsAddNewForm } from '../../../../schema-component';
|
||||
import { isSubMode } from '../../../../schema-component/antd/association-field/util';
|
||||
@ -18,12 +20,11 @@ import {
|
||||
useTitleFieldOptions,
|
||||
} from '../../../../schema-component/antd/form-item/FormItem.Settings';
|
||||
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
|
||||
import { VariableInput, getShouldChange } from '../../../../schema-settings';
|
||||
import { getShouldChange, VariableInput } from '../../../../schema-settings';
|
||||
import { useIsShowMultipleSwitch } from '../../../../schema-settings/hooks/useIsShowMultipleSwitch';
|
||||
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
|
||||
import { SchemaSettingsSortingRule } from '../../../../schema-settings/SchemaSettingsSortingRule';
|
||||
import { useIsShowMultipleSwitch } from '../../../../schema-settings/hooks/useIsShowMultipleSwitch';
|
||||
import { useLocalVariables, useVariables } from '../../../../variables';
|
||||
import { useCollectionField } from '../../../../data-source';
|
||||
|
||||
const enableLink = {
|
||||
name: 'enableLink',
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { RecursionField, observer, useField, useFieldSchema } from '@tachybase/schema';
|
||||
import React, { useState } from 'react';
|
||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
|
||||
|
||||
import { CollectionProvider_deprecated, useCollectionManager_deprecated } from '../../../../collection-manager';
|
||||
import { CreateAction } from '../../../../schema-initializer/components';
|
||||
import { ActionContextProvider, useActionContext } from '../../action';
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
MMenuBlockInitializer,
|
||||
MPage,
|
||||
MRadio,
|
||||
MSelect,
|
||||
MSettings,
|
||||
MSettingsBlockInitializer,
|
||||
MTabBar,
|
||||
@ -87,6 +88,7 @@ export const MobileCore: React.FC<PropsWithChildren> = (props) => {
|
||||
MRadio,
|
||||
MImageUploader,
|
||||
CollectionField: CollectionField,
|
||||
MSelect,
|
||||
}}
|
||||
scope={{
|
||||
useGridCardBlockItemProps,
|
||||
|
@ -1,10 +1,11 @@
|
||||
const custonComponent = {
|
||||
const customComponent = {
|
||||
Input: 'MInput',
|
||||
'Input.TextArea': 'MInput.TextArea',
|
||||
'Radio.Group': 'MRadio.Group',
|
||||
'Checkbox.Group': 'MCheckbox.Group',
|
||||
'Upload.Attachment': 'MImageUploader',
|
||||
DatePicker: 'MDatePicker',
|
||||
Select: 'MSelect',
|
||||
};
|
||||
|
||||
export const canMobileField = (componentName: string) => custonComponent[componentName];
|
||||
export const canMobileField = (componentName: string) => customComponent[componentName];
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useCollectionField } from '@tachybase/client';
|
||||
import { css, useCollectionField } from '@tachybase/client';
|
||||
import { connect, isValid, mapProps, mapReadPretty, useField } from '@tachybase/schema';
|
||||
|
||||
import { Checkbox, CheckboxGroupProps, CheckboxProps, Tag } from 'antd-mobile';
|
||||
@ -27,7 +27,7 @@ MCheckbox.Group = connect(
|
||||
<Checkbox
|
||||
value={item.value}
|
||||
key={index}
|
||||
style={{ marginRight: '10px' }}
|
||||
style={{ '--icon-size': '12px', '--font-size': '12px' }}
|
||||
onChange={(status) => {
|
||||
if (status) {
|
||||
check.push(item.value);
|
||||
@ -37,6 +37,7 @@ MCheckbox.Group = connect(
|
||||
}
|
||||
props.onChange(check);
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{item.label}
|
||||
</Checkbox>
|
||||
|
@ -36,8 +36,8 @@ export const MDatePicker = connect(
|
||||
}),
|
||||
mapReadPretty((props) => {
|
||||
const changeProps = { ...props };
|
||||
changeProps.value = dayjs(props.value).format(props.dateFormat);
|
||||
return <Input {...changeProps} readOnly />;
|
||||
changeProps.value = props.value ? dayjs(props.value).format('YYYY-MM-DD') : '';
|
||||
return <div>{changeProps.value}</div>;
|
||||
}),
|
||||
);
|
||||
export default MDatePicker;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { css } from '@tachybase/client';
|
||||
import { connect, mapProps, mapReadPretty } from '@tachybase/schema';
|
||||
|
||||
import { Input, InputProps, TextArea, TextAreaProps } from 'antd-mobile';
|
||||
@ -10,20 +11,40 @@ type ComposedInput = React.FC<InputProps> & {
|
||||
export const MInput: ComposedInput = connect(
|
||||
Input,
|
||||
mapProps((props) => {
|
||||
return { placeholder: '请输入内容', clearable: true, ...props, style: { fontSize: '12px' } };
|
||||
return { placeholder: '请输入内容', clearable: true, ...props, style: { '--font-size': '12px' } };
|
||||
}),
|
||||
mapReadPretty((props) => {
|
||||
return <Input {...props} readOnly style={{ fontSize: '12px' }} />;
|
||||
return (
|
||||
<Input
|
||||
{...props}
|
||||
readOnly
|
||||
className={css`
|
||||
.adm-text-area-element {
|
||||
font-size: 12px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const MTextArea = connect(
|
||||
TextArea,
|
||||
mapProps((props) => {
|
||||
return { ...props, placeholder: '请输入内容', clearable: true, style: { fontSize: '12px' } };
|
||||
return { ...props, placeholder: '请输入内容', clearable: true, style: { '--font-size': '12px' } };
|
||||
}),
|
||||
mapReadPretty((props) => {
|
||||
return <TextArea {...props} readOnly style={{ fontSize: '12px' }} />;
|
||||
return (
|
||||
<TextArea
|
||||
{...props}
|
||||
readOnly
|
||||
className={css`
|
||||
.adm-text-area-element {
|
||||
font-size: 12px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -26,7 +26,11 @@ MRadio.Group = connect(
|
||||
<Radio.Group {...props}>
|
||||
{dataSource.map((item, index) => {
|
||||
return (
|
||||
<Radio value={item.value} key={index} style={{ marginRight: '10px' }}>
|
||||
<Radio
|
||||
value={item.value}
|
||||
key={index}
|
||||
style={{ '--font-size': '12px', '--icon-size': '18px', marginLeft: '10px' }}
|
||||
>
|
||||
{item.label}
|
||||
</Radio>
|
||||
);
|
||||
|
@ -0,0 +1,7 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
export const AntdPopupContext = createContext({});
|
||||
|
||||
export const useAntdPopupContext = () => {
|
||||
return useContext(AntdPopupContext);
|
||||
};
|
@ -0,0 +1,237 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { observer, RecursionField, useField, useFieldSchema, useForm } from '@tachybase/schema';
|
||||
|
||||
import { Button, CheckList, Divider, Modal, PickerView, Popup, SearchBar, Space, Tag, Toast } from 'antd-mobile';
|
||||
|
||||
import { MInput } from '../Input';
|
||||
|
||||
import './style';
|
||||
|
||||
import {
|
||||
BlockItem,
|
||||
CollectionProvider_deprecated,
|
||||
useAPIClient,
|
||||
useCollectionManager,
|
||||
useDesignable,
|
||||
useRequest,
|
||||
} from '@tachybase/client';
|
||||
import { isArray } from '@tachybase/utils/client';
|
||||
|
||||
import { CreateRecordAction } from './CreateRecordAction';
|
||||
import { useInsertSchema } from './hook/hooks';
|
||||
import schema from './schema';
|
||||
import { useStyles } from './style';
|
||||
|
||||
export const AntdSelect = observer((props) => {
|
||||
const { value, collectionName, service, fieldNames, addMode, onChange, multiple } = props as any;
|
||||
const [popupVisible, setPopupVisible] = useState(false);
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const { styles } = useStyles();
|
||||
const [options, setOptions] = useState([]);
|
||||
const fieldSchema = useFieldSchema();
|
||||
const cm = useCollectionManager();
|
||||
const [visibleValue, setVisibleValue] = useState({});
|
||||
const [filter, setFilter] = useState(service?.params?.filter);
|
||||
const api = useAPIClient();
|
||||
const field = useField();
|
||||
const { insertAfterBegin } = useDesignable();
|
||||
const insertAddNewer = useInsertSchema('AddNewer', fieldSchema, insertAfterBegin);
|
||||
const [selectValue, setSelectValue] = useState(value);
|
||||
const { data, run } = useRequest(
|
||||
{
|
||||
resource: collectionName,
|
||||
action: 'list',
|
||||
params: {
|
||||
filter,
|
||||
},
|
||||
},
|
||||
{
|
||||
manual: true,
|
||||
},
|
||||
);
|
||||
useEffect(() => {
|
||||
checkedPopup();
|
||||
}, [filter]);
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const dataOption = data['data']?.map((value) => {
|
||||
return {
|
||||
...value,
|
||||
label: value[fieldNames.label],
|
||||
value: value[fieldNames.value],
|
||||
};
|
||||
});
|
||||
setOptions(dataOption);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const checkedPopup = () => {
|
||||
if (collectionName) {
|
||||
run();
|
||||
} else {
|
||||
const field = cm.getCollectionField(fieldSchema['x-collection-field']);
|
||||
const data = field.uiSchema?.enum;
|
||||
setVisibleValue(data.find((item) => item.value === value) || '');
|
||||
setOptions(data);
|
||||
}
|
||||
};
|
||||
|
||||
const addData = () => {
|
||||
api
|
||||
.request({
|
||||
url: collectionName + ':create',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
Toast.show({
|
||||
icon: 'success',
|
||||
content: '添加成功',
|
||||
});
|
||||
} else {
|
||||
Toast.show({
|
||||
icon: 'fail',
|
||||
content: '失败成功',
|
||||
});
|
||||
}
|
||||
const paramsFilter = { ...filter };
|
||||
delete paramsFilter[fieldNames.label];
|
||||
setFilter(paramsFilter);
|
||||
setSearchValue('');
|
||||
setPopupVisible(false);
|
||||
})
|
||||
.catch(() => {
|
||||
console.error;
|
||||
});
|
||||
};
|
||||
const quickAdd = () => {
|
||||
const data = {};
|
||||
data[fieldNames.label] = searchValue;
|
||||
addData();
|
||||
};
|
||||
const modalAdd = () => {
|
||||
const collectionField = cm.getCollectionField(fieldSchema['x-collection-field']);
|
||||
// console.log('🚀 ~ modalAdd ~ collectionField:', collectionField);
|
||||
const targetCollection = cm.getCollection(collectionField?.target);
|
||||
|
||||
// insertAddNewer(schema.AddNewer);
|
||||
// const props = {
|
||||
// fieldSchema,
|
||||
// field,
|
||||
// targetCollection,
|
||||
// };
|
||||
Modal.show({
|
||||
content: (
|
||||
<CollectionProvider_deprecated name={targetCollection?.name}>
|
||||
<RecursionField
|
||||
onlyRenderProperties
|
||||
basePath={field.address}
|
||||
schema={fieldSchema}
|
||||
filterProperties={(s) => {
|
||||
return s['x-component'] === 'AssociationField.AddNewer';
|
||||
}}
|
||||
/>
|
||||
</CollectionProvider_deprecated>
|
||||
),
|
||||
showCloseButton: true,
|
||||
});
|
||||
};
|
||||
return (
|
||||
<BlockItem>
|
||||
{collectionName ? (
|
||||
<div
|
||||
onClick={() => {
|
||||
setPopupVisible(true);
|
||||
checkedPopup();
|
||||
}}
|
||||
style={{ color: '#c5c5c5' }}
|
||||
>
|
||||
{isArray(value) ? (
|
||||
value.map((item, index) => (
|
||||
<Space key={index}>{`${item.label}${value.length - 1 === index ? '' : ','}`}</Space>
|
||||
))
|
||||
) : (
|
||||
<Space>{value?.label || '请选择内容'}</Space>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Tag color={'default'}>{value?.['label']}</Tag>
|
||||
)}
|
||||
|
||||
<Popup visible={popupVisible} className={`${styles['PopupStyle']}`} closeOnMaskClick>
|
||||
<SearchBar
|
||||
placeholder="请输入内容"
|
||||
value={searchValue}
|
||||
onChange={(value) => {
|
||||
const paramsFilter = { ...filter };
|
||||
paramsFilter[fieldNames.label] = { $includes: value };
|
||||
setFilter(paramsFilter);
|
||||
setSearchValue(value);
|
||||
}}
|
||||
/>
|
||||
{searchValue && addMode === 'quickAdd' ? (
|
||||
<Space justify="center" align="center" onClick={quickAdd}>
|
||||
+ 创建{searchValue}
|
||||
</Space>
|
||||
) : null}
|
||||
<Divider />
|
||||
{multiple ? (
|
||||
<CheckList
|
||||
multiple
|
||||
className={`${styles['checkListStyle']}`}
|
||||
onChange={(value) => {
|
||||
if (!value.length) {
|
||||
setSelectValue(null);
|
||||
return;
|
||||
}
|
||||
const filterValue = options.filter((item) => value.includes(item.value));
|
||||
setSelectValue(filterValue);
|
||||
}}
|
||||
>
|
||||
{options.map((item, index) => {
|
||||
return (
|
||||
<CheckList.Item key={index} value={item.value}>
|
||||
{item.label}
|
||||
</CheckList.Item>
|
||||
);
|
||||
})}
|
||||
</CheckList>
|
||||
) : (
|
||||
<PickerView
|
||||
columns={[options]}
|
||||
onChange={(value) => {
|
||||
const changeValue = options.find((item) => item[fieldNames.value] === value[0]);
|
||||
setSelectValue(changeValue);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Space justify="evenly" align="center">
|
||||
{/* {addMode === 'modalAdd' ? (
|
||||
<Button color="primary" fill="outline" onClick={modalAdd}>
|
||||
添加
|
||||
</Button>
|
||||
) : null} */}
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setPopupVisible(false);
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
onChange(selectValue);
|
||||
setPopupVisible(false);
|
||||
}}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</Space>
|
||||
</Popup>
|
||||
</BlockItem>
|
||||
);
|
||||
});
|
@ -0,0 +1,7 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
export const AntdSelectContext = createContext({});
|
||||
|
||||
export const useAntdSelectContext = () => {
|
||||
return useContext(AntdSelectContext);
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
CollectionProvider,
|
||||
CollectionProvider_deprecated,
|
||||
useActionContext,
|
||||
useCollectionManager,
|
||||
useCollectionManager_deprecated,
|
||||
} from '@tachybase/client';
|
||||
import { RecursionField } from '@tachybase/schema';
|
||||
|
||||
import { useInsertSchema } from './hook/hooks';
|
||||
import schema from './schema';
|
||||
|
||||
export const CreateRecordAction = ({ field, fieldSchema, targetCollection }) => {
|
||||
const [currentCollection, setCurrentCollection] = useState(targetCollection?.name);
|
||||
const [currentDataSource, setCurrentDataSource] = useState(targetCollection?.dataSource);
|
||||
return (
|
||||
<CollectionProvider_deprecated name={currentCollection} dataSource={currentDataSource}>
|
||||
<RecursionField
|
||||
onlyRenderProperties
|
||||
basePath={field.address}
|
||||
schema={fieldSchema}
|
||||
filterProperties={(s) => {
|
||||
return s['x-component'] === 'AssociationField.AddNewer';
|
||||
}}
|
||||
/>
|
||||
</CollectionProvider_deprecated>
|
||||
);
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { css, useCollectionField, useCollectionManager } from '@tachybase/client';
|
||||
import { connect, isValid, mapProps, mapReadPretty, useField, useFieldSchema } from '@tachybase/schema';
|
||||
import { isArray } from '@tachybase/utils/client';
|
||||
|
||||
import { Input, Space, Tag } from 'antd-mobile';
|
||||
|
||||
import { getMobileColor } from '../../../CustomColor';
|
||||
import { AntdSelect } from './AntdSelect';
|
||||
|
||||
export const MSelect = connect(
|
||||
AntdSelect,
|
||||
mapProps((props) => {
|
||||
const filterProps = { ...props };
|
||||
const fieldSchema = useFieldSchema();
|
||||
const cm = useCollectionManager();
|
||||
const collection = cm.getCollection(fieldSchema['x-collection-field']);
|
||||
if (collection) {
|
||||
filterProps['collectionName'] = collection.name;
|
||||
}
|
||||
return { ...filterProps };
|
||||
}),
|
||||
mapReadPretty((props) => {
|
||||
const { value, fieldNames } = props;
|
||||
const isCollectionField = typeof value === 'object' && fieldNames;
|
||||
if (isCollectionField) {
|
||||
const isArrayField = isArray(value);
|
||||
return isArrayField ? (
|
||||
<div>
|
||||
{value.map((item, index) => (
|
||||
<Space key={index}>{`${item?.[fieldNames.label] || ''}${value.length - 1 === index ? '' : ','}`}</Space>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<Space>{value?.[fieldNames.label] || ''}</Space>
|
||||
);
|
||||
} else {
|
||||
const field = useField<any>();
|
||||
const collectionField = useCollectionField();
|
||||
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
||||
return (
|
||||
<div>
|
||||
{dataSource
|
||||
.filter((option) => option.value == value)
|
||||
.map((option, key) => (
|
||||
<Tag key={key} color={getMobileColor(option.color)}>
|
||||
{option.label}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
export default MSelect;
|
@ -0,0 +1,23 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useDesignable } from '@tachybase/client';
|
||||
import { GeneralField, reaction, useField, useFieldSchema } from '@tachybase/schema';
|
||||
import { flatten, getValuesByPath } from '@tachybase/utils/client';
|
||||
|
||||
import _, { isString } from 'lodash';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
export const useInsertSchema = (component, fieldSchema, insertAfterBegin) => {
|
||||
const insert = (ss) => {
|
||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
||||
if (s['x-component'] === 'AssociationField.' + component) {
|
||||
return s;
|
||||
}
|
||||
return buf;
|
||||
}, null);
|
||||
if (!schema) {
|
||||
insertAfterBegin(cloneDeep(ss));
|
||||
}
|
||||
};
|
||||
|
||||
return insert;
|
||||
};
|
@ -0,0 +1 @@
|
||||
export * from './Select';
|
@ -0,0 +1,131 @@
|
||||
export default {
|
||||
Nester: {
|
||||
type: 'void',
|
||||
'x-component': 'AssociationField.Nester',
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'form:configureFields',
|
||||
},
|
||||
},
|
||||
},
|
||||
AddNewer: {
|
||||
type: 'void',
|
||||
'x-component': 'AssociationField.AddNewer',
|
||||
'x-action': 'create',
|
||||
title: '{{ t("Add record") }}',
|
||||
'x-component-props': {
|
||||
className: 'nb-action-popup',
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
'x-component-props': {},
|
||||
'x-initializer': 'TabPaneInitializersForCreateFormBlock',
|
||||
properties: {
|
||||
tab1: {
|
||||
type: 'void',
|
||||
title: '{{t("Add new")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-designer': 'Tabs.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'popup:addNew:addBlock',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Selector: {
|
||||
type: 'void',
|
||||
'x-component': 'AssociationField.Selector',
|
||||
title: '{{ t("Select record") }}',
|
||||
'x-component-props': {
|
||||
className: 'nb-record-picker-selector',
|
||||
},
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'popup:tableSelector:addBlock',
|
||||
properties: {},
|
||||
},
|
||||
footer: {
|
||||
'x-component': 'Action.Container.Footer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
actions: {
|
||||
type: 'void',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
submit: {
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-action': 'submit',
|
||||
'x-component': 'Action',
|
||||
'x-use-component-props': 'usePickActionProps',
|
||||
// 'x-designer': 'Action.Designer',
|
||||
'x-toolbar': 'ActionSchemaToolbar',
|
||||
'x-settings': 'actionSettings:submit',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
htmlType: 'submit',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Viewer: {
|
||||
type: 'void',
|
||||
title: '{{ t("View record") }}',
|
||||
'x-component': 'AssociationField.Viewer',
|
||||
'x-component-props': {
|
||||
className: 'nb-action-popup',
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
'x-component-props': {},
|
||||
'x-initializer': 'TabPaneInitializers',
|
||||
properties: {
|
||||
tab1: {
|
||||
type: 'void',
|
||||
title: '{{t("Details")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-designer': 'Tabs.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'popup:common:addBlock',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SubTable: {
|
||||
type: 'void',
|
||||
'x-component': 'AssociationField.SubTable',
|
||||
'x-initializer': 'table:configureColumns',
|
||||
'x-initializer-props': {
|
||||
action: false,
|
||||
},
|
||||
properties: {},
|
||||
},
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
import { createStyles } from '@tachybase/client';
|
||||
|
||||
export const useStyles = createStyles(({ css }) => ({
|
||||
PopupStyle: css`
|
||||
.adm-popup-body {
|
||||
padding: 10px;
|
||||
.adm-space {
|
||||
width: 100%;
|
||||
margin: 10px 0 10px 0;
|
||||
color: #4592ff;
|
||||
button {
|
||||
width: 23vw;
|
||||
}
|
||||
}
|
||||
.adm-divider {
|
||||
margin: 0;
|
||||
}
|
||||
.adm-list-body {
|
||||
height: 30vh;
|
||||
overflow: auto;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}));
|
@ -3,3 +3,4 @@ export * from './Checkbox';
|
||||
export * from './DatePicker';
|
||||
export * from './ImageUploader';
|
||||
export * from './Radio';
|
||||
export * from './Select';
|
||||
|
@ -2,6 +2,8 @@ import React, { useEffect, useMemo } from 'react';
|
||||
import {
|
||||
CollectionFieldProvider,
|
||||
useCollectionField,
|
||||
useCollectionManager,
|
||||
useCollectionManager_deprecated,
|
||||
useCompile,
|
||||
useComponent,
|
||||
useFormBlockContext,
|
||||
@ -28,11 +30,15 @@ export const CollectionFieldInternalField: React.FC = (props: 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 Component = useComponent(component || uiComponent(isMobile, uiSchema) || 'Input');
|
||||
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];
|
||||
};
|
||||
@ -95,8 +101,8 @@ export const CollectionField = connect((props) => {
|
||||
);
|
||||
});
|
||||
|
||||
export const uiComponent = (isMobile, uiSchema) => {
|
||||
const isMobileComponent = canMobileField(uiSchema['x-component']);
|
||||
export const uiComponent = (isMobile, uiSchema, currMode?) => {
|
||||
const isMobileComponent = canMobileField(currMode || uiSchema['x-component']);
|
||||
if (isMobile && isMobileComponent) {
|
||||
return isMobileComponent;
|
||||
} else {
|
||||
@ -104,4 +110,15 @@ export const uiComponent = (isMobile, uiSchema) => {
|
||||
}
|
||||
};
|
||||
|
||||
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';
|
||||
|
Loading…
Reference in New Issue
Block a user