@@ -97,7 +107,11 @@ export const QuickEdit = observer(
if (!collectionField) {
return null;
}
- return field.editable ?
:
;
+ return field.editable || field.disabled ? (
+
+ ) : (
+
+ );
},
{ displayName: 'QuickEdit' },
);
diff --git a/packages/core/client/src/schema-component/antd/quick-edit/__tests__/QuickEdit.test.tsx b/packages/core/client/src/schema-component/antd/quick-edit/__tests__/QuickEdit.test.tsx
index 7b43ebe1dc0..2e3cf559ac3 100644
--- a/packages/core/client/src/schema-component/antd/quick-edit/__tests__/QuickEdit.test.tsx
+++ b/packages/core/client/src/schema-component/antd/quick-edit/__tests__/QuickEdit.test.tsx
@@ -8,7 +8,7 @@
*/
import { BlockSchemaComponentPlugin } from '@nocobase/client';
-import { screen, renderAppOptions, sleep, userEvent, waitFor } from '@nocobase/test/client';
+import { renderAppOptions, screen, sleep, userEvent, waitFor } from '@nocobase/test/client';
describe('QuickEdit', () => {
function getRenderOptions(readPretty = false) {
diff --git a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx
index baacd15c7c9..3102eb04272 100644
--- a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx
+++ b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx
@@ -21,6 +21,7 @@ import { FieldNames, Select, SelectProps, defaultFieldNames } from '../select';
import { ReadPretty } from './ReadPretty';
import { useDataSourceHeaders } from '../../../data-source/utils';
import { useDataSourceKey } from '../../../data-source/data-source/DataSourceProvider';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
const EMPTY = 'N/A';
export type RemoteSelectProps
= SelectProps
& {
@@ -44,248 +45,254 @@ export type RemoteSelectProps
= SelectProps
& {
dataSource?: string;
CustomDropdownRender?: (v: any) => any;
optionFilter?: (option: any) => boolean;
+ toOptionsItem?: (data) => any;
};
-const InternalRemoteSelect = connect(
- (props: RemoteSelectProps) => {
- const {
- fieldNames = {} as FieldNames,
- service = {},
- wait = 300,
- value,
- defaultValue,
- objectValue,
- manual = true,
- mapOptions,
- targetField: _targetField,
- CustomDropdownRender,
- optionFilter,
- dataSource: propsDataSource,
- ...others
- } = props;
- const dataSource = useDataSourceKey();
- const headers = useDataSourceHeaders(propsDataSource || dataSource);
- const [open, setOpen] = useState(false);
- const firstRun = useRef(false);
- const fieldSchema = useFieldSchema();
- const isQuickAdd = fieldSchema['x-component-props']?.addMode === 'quickAdd';
- const { getField } = useCollection_deprecated();
- const searchData = useRef(null);
- const { getCollectionJoinField, getInterface } = useCollectionManager_deprecated();
- const colletionFieldName = fieldSchema['x-collection-field'] || fieldSchema.name;
- const collectionField = getField(colletionFieldName) || getCollectionJoinField(colletionFieldName);
- const targetField =
- _targetField ||
- (collectionField?.target &&
- fieldNames?.label &&
- getCollectionJoinField(`${collectionField.target}.${fieldNames.label}`));
+const InternalRemoteSelect = withDynamicSchemaProps(
+ connect(
+ (props: RemoteSelectProps) => {
+ const {
+ fieldNames = {} as FieldNames,
+ service = {},
+ wait = 300,
+ value,
+ defaultValue,
+ objectValue,
+ manual = true,
+ mapOptions,
+ targetField: _targetField,
+ CustomDropdownRender,
+ optionFilter,
+ dataSource: propsDataSource,
+ toOptionsItem = (value) => value,
+ ...others
+ } = props;
+ const dataSource = useDataSourceKey();
+ const headers = useDataSourceHeaders(propsDataSource || dataSource);
+ const [open, setOpen] = useState(false);
+ const firstRun = useRef(false);
+ const fieldSchema = useFieldSchema();
+ const isQuickAdd = fieldSchema['x-component-props']?.addMode === 'quickAdd';
+ const { getField } = useCollection_deprecated();
+ const searchData = useRef(null);
+ const { getCollectionJoinField, getInterface } = useCollectionManager_deprecated();
+ const colletionFieldName = fieldSchema['x-collection-field'] || fieldSchema.name;
+ const collectionField = getField(colletionFieldName) || getCollectionJoinField(colletionFieldName);
+ const targetField =
+ _targetField ||
+ (collectionField?.target &&
+ fieldNames?.label &&
+ getCollectionJoinField(`${collectionField.target}.${fieldNames.label}`));
- const operator = useMemo(() => {
- if (targetField?.interface) {
- return getInterface(targetField.interface)?.filterable?.operators[0].value || '$includes';
- }
- return '$includes';
- }, [targetField]);
- const compile = useCompile();
+ const operator = useMemo(() => {
+ if (targetField?.interface) {
+ return getInterface(targetField.interface)?.filterable?.operators[0].value || '$includes';
+ }
+ return '$includes';
+ }, [targetField]);
+ const compile = useCompile();
- const mapOptionsToTags = useCallback(
- (options) => {
- try {
- return options
- .filter((v) => ['number', 'string'].includes(typeof v[fieldNames.value]))
- .map((option) => {
- let label = compile(option[fieldNames.label]);
+ const mapOptionsToTags = useCallback(
+ (options) => {
+ try {
+ return options
+ .filter((v) => {
+ return ['number', 'string'].includes(typeof v[fieldNames.value]) || !v[fieldNames.value];
+ })
+ .map((option) => {
+ let label = compile(option[fieldNames.label]);
- if (targetField?.uiSchema?.enum) {
- if (Array.isArray(label)) {
- label = label
- .map((item, index) => {
- const option = targetField.uiSchema.enum.find((i) => i.value === item);
- if (option) {
- return (
-
- {option?.label || item}
-
- );
- } else {
- return (
-
- {item}
-
- );
- }
- })
- .reverse();
- } else {
- const item = targetField.uiSchema.enum.find((i) => i.value === label);
- if (item) {
- label = (
-
- {item.label}
-
- );
+ if (targetField?.uiSchema?.enum) {
+ if (Array.isArray(label)) {
+ label = label
+ .map((item, index) => {
+ const option = targetField.uiSchema.enum.find((i) => i.value === item);
+ if (option) {
+ return (
+
+ {option?.label || item}
+
+ );
+ } else {
+ return (
+
+ {item}
+
+ );
+ }
+ })
+ .reverse();
+ } else {
+ const item = targetField.uiSchema.enum.find((i) => i.value === label);
+ if (item) {
+ label = (
+
+ {item.label}
+
+ );
+ }
}
}
- }
- if (targetField?.type === 'date') {
- label = dayjs(label).format('YYYY-MM-DD');
- }
+ if (targetField?.type === 'date') {
+ label = dayjs(label).format('YYYY-MM-DD');
+ }
- if (mapOptions) {
- return mapOptions({
+ if (mapOptions) {
+ return mapOptions({
+ [fieldNames.label]: label || EMPTY,
+ [fieldNames.value]: option[fieldNames.value],
+ });
+ }
+ return {
+ ...option,
[fieldNames.label]: label || EMPTY,
[fieldNames.value]: option[fieldNames.value],
- });
- }
- return {
- ...option,
- [fieldNames.label]: label || EMPTY,
- [fieldNames.value]: option[fieldNames.value],
- };
- })
- .filter(Boolean);
- } catch (err) {
- console.error(err);
- return options;
- }
- },
- [targetField?.uiSchema, fieldNames],
- );
- const { data, run, loading } = useRequest(
- {
- action: 'list',
- ...service,
- headers,
- params: {
- pageSize: 200,
- ...service?.params,
- filter: service?.params?.filter,
+ };
+ })
+ .filter(Boolean);
+ } catch (err) {
+ console.error(err);
+ return options;
+ }
},
- },
- {
- manual,
- debounceWait: wait,
- },
- );
- const runDep = useMemo(
- () =>
- JSON.stringify({
- service,
- fieldNames,
- }),
- [service, fieldNames],
- );
- const CustomRenderCom = useCallback(() => {
- if (searchData.current && CustomDropdownRender) {
- return (
- {
- searchData.current = null;
- setOpen(false);
- }}
- />
- );
- }
- return null;
- }, [searchData.current]);
-
- useEffect(() => {
- // Lazy load
- if (firstRun.current) {
- run();
- }
- }, [runDep]);
-
- const onSearch = async (search) => {
- run({
- filter: mergeFilter([
- search
- ? {
- [fieldNames.label]: {
- [operator]: search,
- },
- }
- : {},
- service?.params?.filter,
- ]),
- });
- searchData.current = search;
- };
-
- const options = useMemo(() => {
- const v = value || defaultValue;
- if (!data?.data?.length) {
- return v != null ? (Array.isArray(v) ? v : [v]) : [];
- }
- const valueOptions =
- (v != null && (Array.isArray(v) ? v : [{ ...v, [fieldNames.value]: v[fieldNames.value] || v }])) || [];
- const filtered = typeof optionFilter === 'function' ? data.data.filter(optionFilter) : data.data;
- return uniqBy(filtered.concat(valueOptions ?? []), fieldNames.value);
- }, [value, defaultValue, data?.data, fieldNames.value, optionFilter]);
- const onDropdownVisibleChange = (visible) => {
- setOpen(visible);
- searchData.current = null;
- if (visible) {
- run();
- }
- firstRun.current = true;
- };
- return (
-