From 68fcadf092b4446a90ad0b6a2543e3dd578e4aba Mon Sep 17 00:00:00 2001 From: Dunqing Date: Mon, 27 Feb 2023 09:14:14 +0800 Subject: [PATCH] fix(association-select): data is incorrect when use data scope (#1491) * fix(association-select): data is incorrect when use data scope * fix: update * feat: improve RemoteSelect performance * feat: use value instated of options when options is empty * fix: data scope not work * fix: loading not work * feat: prepare database method (#1492) * fix: environment variables (#1490) * fix: beforeSubAppLoad emit to async * feat: support custom plugin deployment in dockerfile (#1494) * fix: collection importer has incorrect reference (#1495) * fix: collection importer has incorrect reference * test: reimport test * fix: export collectionTemplates * feat: form/button linkage rules (#1456) * feat(plugin-workflow): add prompt node * feat(plugin-workflow): useValueGetter for all instructions and triggers * feat(plugin-workflow): add workflow block initializer * refactor(plugin-workflow): change prompt node type to manual * feat(plugin-workflow): add ModeConfig component for mode * feat(plugin-workflow): add todo drawer * feat(plugin-workflow): add block value provider * feat(plugin-workflow): improve todo block and drawer * fix(plugin-workflow): fix instruction name in test cases * fix(plugin-workflow): fix test cases * refactor(plugin-workflow): change param type of collection field initializer * feat(plugin-workflow): add filter types for getters * fix(plugin-workflow): fix assignees variable * fix(plugin-workflow): filter todo by exist workflow * fix(plugin-workflow): fix duplicated save action in manual config * fix(plugin-workflow): fix transaction * feat(plugin-workflow): destroy workflow will be cascaded * fix(plugin-workflow): fix merge * fix(plugin-workflow): fix locale * fix(plugin-workflow): allow open ui view when executed * fix(plugin-workflow): change todo table filter * feat(plugin-workflow): use formula for calculation * fix(plugin-workflow): fix variable template regexp * fix(plugin-workflow): fix sub-options logic with types * refactor(plugin-workflow): drop useless component * fix(plugin-workflow): fix manual node action button * feat(plugin-workflow): add new variable input component * refactor(plugin-workflow): change all variable to new component * fix(plugin-workflow): fix type * fix(plugin-workflow): fix functions init * fix(plugin-workflow): change jsonb to json for stable order * fix(plugin-workflow): fix duplicated field name when initialize * fix(plugin-workflow): fix manual result in manual block * test(plugin-workflow): log field initializer props * fix(plugin-workflow): fix nullable arguments * test(plugin-workflow): test initializer fields schema * fix: observer * fix(plugin-workflow): adjust hints * fix(plugin-workflow): fix locale and cursor in variable input * refactor(plugin-workflow): change status keys * fix(plugin-workflow): fix parallel instruction * feat: linkage rules * refactor: linkage rules * refactor: linkage rules update * refactor: linkage rules button * refactor(linakge rules): suport value action * refactor(linakge rules): suport value action * fix(workflow test): workflow test * refactor(linakge rules): action linkage only for detail form * refactor(linakge rules): logic calculation * refactor(linakge rules): logic calculation * refactor(linakge rules): logic calculation * refactor(linakge rules): logic calculation * refactor(linakge rules): linkageAction * refactor(linakge rules): linkageAction * refactor(linakge rules): field value linkageAction * refactor(linakge rules): local * refactor(linakge rules): local * fix(linakge rules): value property * fix(linakge rules): value property * fix(linakge rules): value property * fix(linakge rules): conditionAnalyse * fix(linakge rules): conditionAnalyse * fix(linakge rules): conditionAnalyse * fix(linakge rules): conditionAnalyse form fields * fix(linakge rules): conditionAnalyse form fields * fix(linakge rules): conditionAnalyse operators * fix(linakge rules): form button linkage * fix(linakge rules): form button linkage * fix(linakge rules): select component suport pattern * fix(linakge rules): component suport field patter for disabled * fix(linakge rules): component suport field patter for disabled * fix(linakge rules): component suport field patter for disabled * fix(linakge rules): component suport field patter for disabled * fix(action): action desginer suport linkage * refactor: formula calculation assignment * refactor: formula calculation assignment * style: unified component disable style * feat: richText suport disabled * feat: condiction suport varible * feat: condiction suport varible * refactor: variableInput * refactor: condiction scope * refactor: multi level linkage * fix: empry value linkage * refactor: components using core schema-component * fix: fix template reference linkage * refactor: evalute foumala * fix: mutual linkage fix * refactor: variables suport obo&oho * style: style improve * style: style improve * style: style improve * feat: variables suport m2o * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * fix: actions path * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve --------- Co-authored-by: mytharcher Co-authored-by: Junyi Co-authored-by: chenos * fix: support mysql lower_case_table_names=1 * fix(linkageRules): support empty condiction (#1496) * fix: condiction suport empty * fix: condiction suport empty * fix: condiction suport empty * fix: condiction suport empty * Update zh_CN.ts (#1481) Co-authored-by: chenos * fix(remote-select): remove fields parameter * Update actions.md * fix: filter --------- Co-authored-by: ChengLei Shao Co-authored-by: chenos Co-authored-by: katherinehhh Co-authored-by: mytharcher Co-authored-by: Junyi Co-authored-by: justwho Co-authored-by: Pearl C <63629092+pearl-cao@users.noreply.github.com> --- .../association-select/useServiceOptions.ts | 83 +++++++++++++------ .../antd/remote-select/RemoteSelect.tsx | 57 +++++++++++-- .../schema-component/antd/select/Select.tsx | 2 - .../src/schema-component/hooks/index.ts | 1 - packages/core/database/src/database.ts | 4 +- 5 files changed, 110 insertions(+), 37 deletions(-) diff --git a/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts b/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts index 069c0241b..80755ee0a 100644 --- a/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts +++ b/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts @@ -1,45 +1,76 @@ import { useFieldSchema } from '@formily/react'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { useCollection, useCollectionManager } from '../../../collection-manager'; import { useRecord } from '../../../record-provider'; export default function useServiceOptions(props) { - const { action = 'list', service, value } = props; + const { action = 'list', service, fieldNames } = props; const params = service?.params || {}; const fieldSchema = useFieldSchema(); const { getField } = useCollection(); const { getCollectionFields } = useCollectionManager(); const record = useRecord(); + const recordValue = record[fieldSchema.name]; + + const normalizeValues = useCallback( + (obj) => { + if (obj && typeof obj === 'object') { + return obj[fieldNames.value]; + } + return obj; + }, + [fieldNames.value], + ); + + const value = useMemo(() => { + if (recordValue === undefined || recordValue === null) { + return; + } + if (Array.isArray(recordValue)) { + return recordValue.map(normalizeValues); + } else { + return normalizeValues(recordValue); + } + }, [recordValue, normalizeValues]); const collectionField = useMemo(() => { return getField(fieldSchema.name); }, [fieldSchema.name]); + const sourceValue = record?.[collectionField?.sourceKey]; const filter = useMemo(() => { - if (!collectionField) return params?.filter; - let extraFilter = {}; - if (['oho', 'o2m'].includes(collectionField.interface)) { - const eqValue = record?.[collectionField.sourceKey]; - extraFilter = { - $or: [ - { - [collectionField.foreignKey]: { - $is: null, - }, - }, - eqValue !== undefined && eqValue !== null - ? { - [collectionField.foreignKey]: { - $eq: eqValue, - }, - } - : null, - ].filter(Boolean), - }; - } - - return params?.filter ? { $and: [extraFilter, params?.filter] } : extraFilter; - }, [params?.filter, getCollectionFields, collectionField]); + const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface); + return { + $or: [ + { + $and: [ + isOToAny + ? { + [collectionField.foreignKey]: { + $is: null, + }, + } + : null, + params?.filter, + ], + }, + isOToAny && sourceValue !== undefined && sourceValue !== null + ? { + [collectionField.foreignKey]: { + $eq: sourceValue, + }, + } + : null, + value + ? { + [fieldNames.value]: { + [Array.isArray(value) ? '$in' : '$eq']: value, + }, + } + : null, + ], + }; + }, [params?.filter, getCollectionFields, collectionField, sourceValue, value, fieldNames.value]); return useMemo(() => { return { 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 051ecbb20..979527f0d 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 @@ -1,7 +1,7 @@ import { LoadingOutlined } from '@ant-design/icons'; import { connect, mapProps, mapReadPretty } from '@formily/react'; import { SelectProps } from 'antd'; -import React, { useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { ResourceActionOptions, useRequest } from '../../../api-client'; import { useCompile } from '../../hooks'; import { defaultFieldNames, Select } from '../select'; @@ -17,10 +17,11 @@ export type RemoteSelectProps

= SelectProps & { const InternalRemoteSelect = connect( (props: RemoteSelectProps) => { - const { fieldNames = {}, service = {}, wait = 300, ...others } = props; + const { fieldNames = {}, service = {}, wait = 300, value, objectValue, ...others } = props; const compile = useCompile(); + const firstRun = useRef(false); - const { data, run } = useRequest( + const { data, run, loading } = useRequest( { action: 'list', ...service, @@ -35,11 +36,27 @@ const InternalRemoteSelect = connect( }, }, { + manual: true, debounceWait: wait, - refreshDeps: [service, fieldNames.label, fieldNames.value], }, ); + const runDep = useMemo( + () => + JSON.stringify({ + service, + fieldNames, + }), + [service, fieldNames], + ); + + useEffect(() => { + // Lazy load + if (firstRun.current) { + run(); + } + }, [runDep]); + const onSearch = async (search) => { run({ filter: { @@ -55,14 +72,39 @@ const InternalRemoteSelect = connect( }); }; + const normalizeOptions = useCallback( + (obj) => { + if (objectValue || typeof obj === 'object') { + return { ...obj, [fieldNames.label]: compile(obj[fieldNames.label]) }; + } + return { [fieldNames.value]: obj, [fieldNames.label]: obj }; + }, + [objectValue, fieldNames.value], + ); + const options = useMemo(() => { + if (!data?.data?.length) { + return value !== undefined && value !== null + ? Array.isArray(value) + ? value.map(normalizeOptions) + : [normalizeOptions(value)] + : []; + } return ( data?.data?.map((item) => ({ ...item, [fieldNames.label]: compile(item[fieldNames.label]), })) || [] ); - }, [data, fieldNames.label]); + }, [data, fieldNames.label, objectValue, value]); + + const onDropdownVisibleChange = () => { + if (firstRun.current) { + return; + } + run(); + firstRun.current = true; + }; return (