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 <mytharcher@gmail.com> Co-authored-by: Junyi <mytharcher@users.noreply.github.com> Co-authored-by: chenos <chenlinxh@gmail.com> * 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 <chenlinxh@gmail.com> * fix(remote-select): remove fields parameter * Update actions.md * fix: filter --------- Co-authored-by: ChengLei Shao <chareice@live.com> Co-authored-by: chenos <chenlinxh@gmail.com> Co-authored-by: katherinehhh <shunai.tang@hand-china.com> Co-authored-by: mytharcher <mytharcher@gmail.com> Co-authored-by: Junyi <mytharcher@users.noreply.github.com> Co-authored-by: justwho <rov7@qq.com> Co-authored-by: Pearl C <63629092+pearl-cao@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									750081e6aa
								
							
						
					
					
						commit
						68fcadf092
					
				@ -1,45 +1,76 @@
 | 
				
			|||||||
import { useFieldSchema } from '@formily/react';
 | 
					import { useFieldSchema } from '@formily/react';
 | 
				
			||||||
import { useMemo } from 'react';
 | 
					import { useCallback, useMemo } from 'react';
 | 
				
			||||||
import { useCollection, useCollectionManager } from '../../../collection-manager';
 | 
					import { useCollection, useCollectionManager } from '../../../collection-manager';
 | 
				
			||||||
import { useRecord } from '../../../record-provider';
 | 
					import { useRecord } from '../../../record-provider';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function useServiceOptions(props) {
 | 
					export default function useServiceOptions(props) {
 | 
				
			||||||
  const { action = 'list', service, value } = props;
 | 
					  const { action = 'list', service, fieldNames } = props;
 | 
				
			||||||
  const params = service?.params || {};
 | 
					  const params = service?.params || {};
 | 
				
			||||||
  const fieldSchema = useFieldSchema();
 | 
					  const fieldSchema = useFieldSchema();
 | 
				
			||||||
  const { getField } = useCollection();
 | 
					  const { getField } = useCollection();
 | 
				
			||||||
  const { getCollectionFields } = useCollectionManager();
 | 
					  const { getCollectionFields } = useCollectionManager();
 | 
				
			||||||
  const record = useRecord();
 | 
					  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(() => {
 | 
					  const collectionField = useMemo(() => {
 | 
				
			||||||
    return getField(fieldSchema.name);
 | 
					    return getField(fieldSchema.name);
 | 
				
			||||||
  }, [fieldSchema.name]);
 | 
					  }, [fieldSchema.name]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const sourceValue = record?.[collectionField?.sourceKey];
 | 
				
			||||||
  const filter = useMemo(() => {
 | 
					  const filter = useMemo(() => {
 | 
				
			||||||
    if (!collectionField) return params?.filter;
 | 
					    const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface);
 | 
				
			||||||
    let extraFilter = {};
 | 
					    return {
 | 
				
			||||||
    if (['oho', 'o2m'].includes(collectionField.interface)) {
 | 
					 | 
				
			||||||
      const eqValue = record?.[collectionField.sourceKey];
 | 
					 | 
				
			||||||
      extraFilter = {
 | 
					 | 
				
			||||||
      $or: [
 | 
					      $or: [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          $and: [
 | 
				
			||||||
 | 
					            isOToAny
 | 
				
			||||||
 | 
					              ? {
 | 
				
			||||||
                  [collectionField.foreignKey]: {
 | 
					                  [collectionField.foreignKey]: {
 | 
				
			||||||
                    $is: null,
 | 
					                    $is: null,
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              : null,
 | 
				
			||||||
 | 
					            params?.filter,
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
          eqValue !== undefined && eqValue !== null
 | 
					        isOToAny && sourceValue !== undefined && sourceValue !== null
 | 
				
			||||||
          ? {
 | 
					          ? {
 | 
				
			||||||
              [collectionField.foreignKey]: {
 | 
					              [collectionField.foreignKey]: {
 | 
				
			||||||
                  $eq: eqValue,
 | 
					                $eq: sourceValue,
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          : null,
 | 
					          : null,
 | 
				
			||||||
        ].filter(Boolean),
 | 
					        value
 | 
				
			||||||
      };
 | 
					          ? {
 | 
				
			||||||
 | 
					              [fieldNames.value]: {
 | 
				
			||||||
 | 
					                [Array.isArray(value) ? '$in' : '$eq']: value,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					          : null,
 | 
				
			||||||
    return params?.filter ? { $and: [extraFilter, params?.filter] } : extraFilter;
 | 
					      ],
 | 
				
			||||||
  }, [params?.filter, getCollectionFields, collectionField]);
 | 
					    };
 | 
				
			||||||
 | 
					  }, [params?.filter, getCollectionFields, collectionField, sourceValue, value, fieldNames.value]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return useMemo(() => {
 | 
					  return useMemo(() => {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { LoadingOutlined } from '@ant-design/icons';
 | 
					import { LoadingOutlined } from '@ant-design/icons';
 | 
				
			||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
 | 
					import { connect, mapProps, mapReadPretty } from '@formily/react';
 | 
				
			||||||
import { SelectProps } from 'antd';
 | 
					import { SelectProps } from 'antd';
 | 
				
			||||||
import React, { useMemo } from 'react';
 | 
					import React, { useCallback, useEffect, useMemo, useRef } from 'react';
 | 
				
			||||||
import { ResourceActionOptions, useRequest } from '../../../api-client';
 | 
					import { ResourceActionOptions, useRequest } from '../../../api-client';
 | 
				
			||||||
import { useCompile } from '../../hooks';
 | 
					import { useCompile } from '../../hooks';
 | 
				
			||||||
import { defaultFieldNames, Select } from '../select';
 | 
					import { defaultFieldNames, Select } from '../select';
 | 
				
			||||||
@ -17,10 +17,11 @@ export type RemoteSelectProps<P = any> = SelectProps<P, any> & {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const InternalRemoteSelect = connect(
 | 
					const InternalRemoteSelect = connect(
 | 
				
			||||||
  (props: RemoteSelectProps) => {
 | 
					  (props: RemoteSelectProps) => {
 | 
				
			||||||
    const { fieldNames = {}, service = {}, wait = 300, ...others } = props;
 | 
					    const { fieldNames = {}, service = {}, wait = 300, value, objectValue, ...others } = props;
 | 
				
			||||||
    const compile = useCompile();
 | 
					    const compile = useCompile();
 | 
				
			||||||
 | 
					    const firstRun = useRef(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { data, run } = useRequest(
 | 
					    const { data, run, loading } = useRequest(
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        action: 'list',
 | 
					        action: 'list',
 | 
				
			||||||
        ...service,
 | 
					        ...service,
 | 
				
			||||||
@ -35,11 +36,27 @@ const InternalRemoteSelect = connect(
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 | 
					        manual: true,
 | 
				
			||||||
        debounceWait: wait,
 | 
					        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) => {
 | 
					    const onSearch = async (search) => {
 | 
				
			||||||
      run({
 | 
					      run({
 | 
				
			||||||
        filter: {
 | 
					        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(() => {
 | 
					    const options = useMemo(() => {
 | 
				
			||||||
 | 
					      if (!data?.data?.length) {
 | 
				
			||||||
 | 
					        return value !== undefined && value !== null
 | 
				
			||||||
 | 
					          ? Array.isArray(value)
 | 
				
			||||||
 | 
					            ? value.map(normalizeOptions)
 | 
				
			||||||
 | 
					            : [normalizeOptions(value)]
 | 
				
			||||||
 | 
					          : [];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        data?.data?.map((item) => ({
 | 
					        data?.data?.map((item) => ({
 | 
				
			||||||
          ...item,
 | 
					          ...item,
 | 
				
			||||||
          [fieldNames.label]: compile(item[fieldNames.label]),
 | 
					          [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 (
 | 
					    return (
 | 
				
			||||||
      <Select
 | 
					      <Select
 | 
				
			||||||
@ -71,7 +113,11 @@ const InternalRemoteSelect = connect(
 | 
				
			|||||||
        filterSort={null}
 | 
					        filterSort={null}
 | 
				
			||||||
        fieldNames={fieldNames}
 | 
					        fieldNames={fieldNames}
 | 
				
			||||||
        onSearch={onSearch}
 | 
					        onSearch={onSearch}
 | 
				
			||||||
 | 
					        onDropdownVisibleChange={onDropdownVisibleChange}
 | 
				
			||||||
 | 
					        objectValue={objectValue}
 | 
				
			||||||
 | 
					        value={value}
 | 
				
			||||||
        {...others}
 | 
					        {...others}
 | 
				
			||||||
 | 
					        loading={loading}
 | 
				
			||||||
        options={options}
 | 
					        options={options}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@ -79,7 +125,6 @@ const InternalRemoteSelect = connect(
 | 
				
			|||||||
  mapProps(
 | 
					  mapProps(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      dataSource: 'options',
 | 
					      dataSource: 'options',
 | 
				
			||||||
      loading: true,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    (props, field) => {
 | 
					    (props, field) => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,6 @@ const InternalSelect = connect(
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return v;
 | 
					      return v;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    console.log('props', props);
 | 
					 | 
				
			||||||
    if (objectValue) {
 | 
					    if (objectValue) {
 | 
				
			||||||
      return <ObjectSelect {...others} value={toValue(value)} mode={mode} />;
 | 
					      return <ObjectSelect {...others} value={toValue(value)} mode={mode} />;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -98,7 +97,6 @@ const InternalSelect = connect(
 | 
				
			|||||||
  mapProps(
 | 
					  mapProps(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      dataSource: 'options',
 | 
					      dataSource: 'options',
 | 
				
			||||||
      loading: true,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    (props, field) => {
 | 
					    (props, field) => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,4 +7,3 @@ export * from './useFieldProps';
 | 
				
			|||||||
export * from './useSchemaComponentContext';
 | 
					export * from './useSchemaComponentContext';
 | 
				
			||||||
export * from './useFieldComponentOptions';
 | 
					export * from './useFieldComponentOptions';
 | 
				
			||||||
export * from './useFieldTitle';
 | 
					export * from './useFieldTitle';
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import {
 | 
				
			|||||||
  Sequelize,
 | 
					  Sequelize,
 | 
				
			||||||
  SyncOptions,
 | 
					  SyncOptions,
 | 
				
			||||||
  Transactionable,
 | 
					  Transactionable,
 | 
				
			||||||
  Utils
 | 
					  Utils,
 | 
				
			||||||
} from 'sequelize';
 | 
					} from 'sequelize';
 | 
				
			||||||
import { SequelizeStorage, Umzug } from 'umzug';
 | 
					import { SequelizeStorage, Umzug } from 'umzug';
 | 
				
			||||||
import { Collection, CollectionOptions, RepositoryType } from './collection';
 | 
					import { Collection, CollectionOptions, RepositoryType } from './collection';
 | 
				
			||||||
@ -58,7 +58,7 @@ import {
 | 
				
			|||||||
  SyncListener,
 | 
					  SyncListener,
 | 
				
			||||||
  UpdateListener,
 | 
					  UpdateListener,
 | 
				
			||||||
  UpdateWithAssociationsListener,
 | 
					  UpdateWithAssociationsListener,
 | 
				
			||||||
  ValidateListener
 | 
					  ValidateListener,
 | 
				
			||||||
} from './types';
 | 
					} from './types';
 | 
				
			||||||
import { patchSequelizeQueryInterface, snakeCase } from './utils';
 | 
					import { patchSequelizeQueryInterface, snakeCase } from './utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user