From cb2feb304d23954ae644d2e7622dc70e51fbd67f Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Sat, 20 May 2023 17:42:26 +0800 Subject: [PATCH] fix: preload relational data (#1847) * fix: getNesterAppends filter bug * fix: associationSelect * fix: associationSelect * fix: associationSelect * fix: getAssociationAppends * fix: sub-form collection context * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * fix: appends * fix: sub-table-appends * fix: undefine id * fix: sub-table appends * fix: sub-table-appends * fix: sub-table-appends * fix: association field appends * fix: association field appends * fix: association field appends * fix: sub-table appends * fix: runWhenParamsChanged * fix: runWhenParamsChanged * chore: eager loading tree * feat: load eager loading tree * fix: support mutiple row * fix: support blockTemplate appends * feat: merge stage of eager loading * feat: merge stage of belongs to * feat: merge stage of has one * fix: dynamic appends not support template schema * feat: merge stage of belongs to many * chore: test * chore: print tree * chore: using eager loading tree in repository find * fix: empty ids load * fix: belongs to many query * fix: load belongs to association * fix: eager load data accessor * fix: has many * fix: test * fix: useAssociationNames * fix: filter with appends * chore: remove handle appends query * chore: console.log * chore: console.log * fix: test * fix: support template block schema * fix: sub-nester-appends --------- Co-authored-by: Chareice --- .../src/block-provider/BlockProvider.tsx | 3 +- .../client/src/block-provider/hooks/index.ts | 95 +++++++++++++------ 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/packages/core/client/src/block-provider/BlockProvider.tsx b/packages/core/client/src/block-provider/BlockProvider.tsx index 4094bff29..15f3290fa 100644 --- a/packages/core/client/src/block-provider/BlockProvider.tsx +++ b/packages/core/client/src/block-provider/BlockProvider.tsx @@ -53,14 +53,13 @@ const useResource = (props: UseResourceProps) => { const api = useAPIClient(); const association = useAssociation(props); const sourceId = useSourceId?.(); - const field = useField(); if (block === 'TableField') { const options = { field, api, resource, - sourceId: sourceId || record[association?.sourceKey || 'id'], + sourceId: sourceId || record[association?.sourceKey || 'id'] || record?.__parent?.[association?.sourceKey || 'id'], }; return new TableFieldResource(options); } diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts index 83e791eda..d8b0bdbf4 100644 --- a/packages/core/client/src/block-provider/hooks/index.ts +++ b/packages/core/client/src/block-provider/hooks/index.ts @@ -1,7 +1,7 @@ import { Schema, SchemaExpressionScopeContext, useField, useFieldSchema, useForm } from '@formily/react'; import { parse } from '@nocobase/utils/client'; import { Modal, message } from 'antd'; -import { cloneDeep } from 'lodash'; +import { cloneDeep, uniq } from 'lodash'; import get from 'lodash/get'; import omit from 'lodash/omit'; import { ChangeEvent, useContext, useEffect } from 'react'; @@ -21,6 +21,7 @@ import { useBlockRequestContext, useFilterByTk } from '../BlockProvider'; import { useDetailsBlockContext } from '../DetailsBlockProvider'; import { mergeFilter } from '../SharedFilterProvider'; import { TableFieldResource } from '../TableFieldProvider'; +import { useSchemaTemplateManager } from '../../schema-templates'; export const usePickActionProps = () => { const form = useForm(); @@ -1072,22 +1073,24 @@ export const useAssociationFilterBlockProps = () => { }; }; -export const useAssociationNames = (collection) => { - const { getCollectionFields, getCollectionJoinField } = useCollectionManager(); - const { getField } = useCollection(); - const collectionFields = getCollectionFields(collection); - const associationFields = new Set(); - for (const collectionField of collectionFields) { - if (collectionField.target) { - associationFields.add(collectionField.name); - const fields = getCollectionFields(collectionField.target); - for (const field of fields) { - if (field.target) { - associationFields.add(`${collectionField.name}.${field.name}`); - } - } - } +const getTemplateSchema = (schema) => { + const conf = { + url: `/uiSchemas:getJsonSchema/${schema?.uid}`, + }; + const { data, loading, run } = useRequest(conf, { manual: true }); + if (loading) { } + useEffect(() => { + if (schema?.uid) { + run(); + } + }, [schema?.uid]); + return schema?.uid ? new Schema(data?.data) : null; +}; + +export const useAssociationNames = (collection) => { + const { getCollectionJoinField } = useCollectionManager(); + const { getTemplateById } = useSchemaTemplateManager(); const fieldSchema = useFieldSchema(); const associationValues = []; const formSchema = fieldSchema.reduceProperties((buf, schema) => { @@ -1097,26 +1100,37 @@ export const useAssociationNames = (collection) => { return buf; }, new Schema({})); + const templateSchema = formSchema.reduceProperties((buf, schema) => { + if (schema['x-component'] === 'BlockTemplate') { + return schema; + } + return buf; + }, null); + const getAssociationAppends = (schema, arr = []) => { const data = schema.reduceProperties((buf, s) => { - const collectionfield = - getField(s.name) || (s['x-collection-field'] && getCollectionJoinField(s['x-collection-field'])); - if (collectionfield && ['hasOne', 'hasMany', 'belongsTo', 'belongsToMany'].includes(collectionfield.type)) { + const collectionfield = s['x-collection-field'] && getCollectionJoinField(s['x-collection-field']); + if ( + collectionfield && + ['hasOne', 'hasMany', 'belongsTo', 'belongsToMany'].includes(collectionfield.type) && + s['x-component'] !== 'TableField' + ) { + buf.push(s.name); if (['Nester', 'SubTable'].includes(s['x-component-props']?.mode)) { associationValues.push(s.name); } - - buf.push(s.name); - if (s['x-component-props'].mode === 'Nester' || s['x-component'] === 'TableField') { + if (s['x-component-props'].mode === 'Nester') { return getAssociationAppends(s, buf); } return buf; } else { - if (s['x-component'] === 'Grid' || s['x-component'] === 'TableV2') { + if (s['x-component'] === 'Grid.Row') { const kk = buf?.concat?.(); return getNesterAppends(s, kk || []); } else { - return !s['x-component']?.includes('Action.') && getAssociationAppends(s, buf); + return !s['x-component']?.includes('Action.') && s['x-component'] !== 'TableField' + ? getAssociationAppends(s, buf) + : buf; } } }, arr); @@ -1130,15 +1144,24 @@ export const useAssociationNames = (collection) => { if (Array.isArray(list[i])) { `${prefix}` !== `${list[i][0]}` && flattenHelper(list[i], `${prefix}.${list[i][0]}`); } else { - const str = prefix.replaceAll(`${list[i]}`, '').replace('..', '.').trim(); - !list.includes(str) && flattenedList.push(`${str}${list[i]}`); + const searchTerm = `.${list[i]}`; + const lastIndex = prefix.lastIndexOf(searchTerm); + let str = ''; + if (lastIndex !== -1) { + str = prefix.slice(0, lastIndex) + prefix.slice(lastIndex + searchTerm.length); + } + if (!str) { + !list.includes(str) && flattenedList.push(`${list[i]}`); + } else { + !list.includes(str) ? flattenedList.push(`${str}.${list[i]}`) : flattenedList.push(str); + } } } } for (let i = 0; i < nestedList.length; i++) { flattenHelper(nestedList[i], nestedList[i][0]); } - return flattenedList.filter((obj) => !obj.startsWith('.')); + return uniq(flattenedList.filter((obj) => !obj?.startsWith('.'))); } const getNesterAppends = (gridSchema, data) => { gridSchema.reduceProperties((buf, s) => { @@ -1147,8 +1170,18 @@ export const useAssociationNames = (collection) => { }, data); return data.filter((g) => g.length); }; - const data = getAssociationAppends(formSchema); - const associations = data.filter((g) => g.length); - const appends = flattenNestedList(associations); - return { appends, updateAssociationValues: appends.filter((v) => associationValues.includes(v)) }; + + const template = getTemplateById(templateSchema?.['x-component-props']?.templateId); + const schema = getTemplateSchema(template); + if (schema) { + const associations = getAssociationAppends(schema); + const appends = flattenNestedList(associations); + console.log(appends, associations); + return { appends, updateAssociationValues: appends.filter((v) => associationValues.includes(v)) }; + } + if (!schema) { + const associations = getAssociationAppends(formSchema); + const appends = flattenNestedList(associations); + return { appends, updateAssociationValues: appends.filter((v) => associationValues.includes(v)) }; + } };