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:
Dunqing 2023-02-27 09:14:14 +08:00 committed by GitHub
parent 750081e6aa
commit 68fcadf092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 37 deletions

View File

@ -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)) { $or: [
const eqValue = record?.[collectionField.sourceKey]; {
extraFilter = { $and: [
$or: [ isOToAny
{ ? {
[collectionField.foreignKey]: { [collectionField.foreignKey]: {
$is: null, $is: null,
}, },
}, }
eqValue !== undefined && eqValue !== null : null,
? { params?.filter,
[collectionField.foreignKey]: { ],
$eq: eqValue, },
}, isOToAny && sourceValue !== undefined && sourceValue !== null
} ? {
: null, [collectionField.foreignKey]: {
].filter(Boolean), $eq: sourceValue,
}; },
} }
: null,
return params?.filter ? { $and: [extraFilter, params?.filter] } : extraFilter; value
}, [params?.filter, getCollectionFields, collectionField]); ? {
[fieldNames.value]: {
[Array.isArray(value) ? '$in' : '$eq']: value,
},
}
: null,
],
};
}, [params?.filter, getCollectionFields, collectionField, sourceValue, value, fieldNames.value]);
return useMemo(() => { return useMemo(() => {
return { return {

View File

@ -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 {

View File

@ -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 {

View File

@ -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';

View File

@ -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';