feat: support linkage rules setting for association block action

This commit is contained in:
katherinehhh 2025-03-27 15:30:32 +08:00
parent b63bd66ffd
commit 6fdbfbd293
10 changed files with 172 additions and 13 deletions

View File

@ -15,6 +15,8 @@ import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/actio
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items'; import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsEnableChildCollections } from '../../../schema-settings/SchemaSettings'; import { SchemaSettingsEnableChildCollections } from '../../../schema-settings/SchemaSettings';
import { useOpenModeContext } from '../../popup/OpenModeProvider'; import { useOpenModeContext } from '../../popup/OpenModeProvider';
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
import { useDataBlockProps } from '../../../data-source';
export const addNewActionSettings = new SchemaSettings({ export const addNewActionSettings = new SchemaSettings({
name: 'actionSettings:addNew', name: 'actionSettings:addNew',
@ -57,6 +59,24 @@ export const addNewActionSettings = new SchemaSettings({
return isChildCollectionAction; return isChildCollectionAction;
}, },
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps();
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'delete', name: 'delete',
sort: 100, sort: 100,

View File

@ -15,6 +15,9 @@ import {
SecondConFirm, SecondConFirm,
RefreshDataBlockRequest, RefreshDataBlockRequest,
} from '../../../schema-component/antd/action/Action.Designer'; } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
import { useCollectionManager_deprecated } from '../../../collection-manager';
import { useDataBlockProps } from '../../../data-source';
export const bulkDeleteActionSettings = new SchemaSettings({ export const bulkDeleteActionSettings = new SchemaSettings({
name: 'actionSettings:bulkDelete', name: 'actionSettings:bulkDelete',
@ -40,6 +43,24 @@ export const bulkDeleteActionSettings = new SchemaSettings({
}; };
}, },
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps() || {};
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'remove', name: 'remove',
sort: 100, sort: 100,

View File

@ -16,12 +16,14 @@ import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings'; import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated } from '../../../collection-manager'; import { useCollection_deprecated } from '../../../collection-manager';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer'; import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { useCollectionManager_deprecated } from '../../../collection-manager';
import { import {
SchemaSettingsLinkageRules, SchemaSettingsLinkageRules,
SchemaSettingsModalItem, SchemaSettingsModalItem,
SchemaSettingAccessControl, SchemaSettingAccessControl,
} from '../../../schema-settings'; } from '../../../schema-settings';
import { useURLAndHTMLSchema } from './useURLAndHTMLSchema'; import { useURLAndHTMLSchema } from './useURLAndHTMLSchema';
import { useDataBlockProps } from '../../../data-source';
export const SchemaSettingsActionLinkItem: FC = () => { export const SchemaSettingsActionLinkItem: FC = () => {
const field = useField(); const field = useField();
@ -96,14 +98,18 @@ export const customizeLinkActionSettings = new SchemaSettings({
Component: SchemaSettingsLinkageRules, Component: SchemaSettingsLinkageRules,
useVisible() { useVisible() {
const record = useCollectionRecord(); const record = useCollectionRecord();
return !_.isEmpty(record?.data); const { association } = useDataBlockProps() || {};
return !_.isEmpty(record?.data) || !!association;
}, },
useComponentProps() { useComponentProps() {
const { name } = useCollection_deprecated(); const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar(); const { linkageRulesProps } = useSchemaToolbar();
const { association } = useDataBlockProps() || {};
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
return { return {
...linkageRulesProps, ...linkageRulesProps,
collectionName: name, collectionName: associationField?.collectionName || name,
}; };
}, },
}, },

View File

@ -6,17 +6,17 @@
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { isEmpty } from 'lodash';
import { useFieldSchema } from '@formily/react';
import { useSchemaToolbar } from '../../../application'; import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings'; import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated } from '../../../collection-manager'; import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
import { useCollection } from '../../../data-source'; import { useCollection, useDataBlockProps } from '../../../data-source';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer'; import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items'; import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsLinkageRules, SchemaSettingAccessControl } from '../../../schema-settings'; import { SchemaSettingsLinkageRules, SchemaSettingAccessControl } from '../../../schema-settings';
import { useOpenModeContext } from '../../popup/OpenModeProvider'; import { useOpenModeContext } from '../../popup/OpenModeProvider';
import { useCurrentPopupRecord } from '../../variable/variablesProvider/VariablePopupRecordProvider'; import { useCurrentPopupRecord } from '../../variable/variablesProvider/VariablePopupRecordProvider';
import { useCollectionRecord } from '../../../';
export const customizePopupActionSettings = new SchemaSettings({ export const customizePopupActionSettings = new SchemaSettings({
name: 'actionSettings:popup', name: 'actionSettings:popup',
@ -35,15 +35,22 @@ export const customizePopupActionSettings = new SchemaSettings({
useComponentProps() { useComponentProps() {
const { name } = useCollection_deprecated(); const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar(); const { linkageRulesProps } = useSchemaToolbar();
const { association } = useDataBlockProps() || {};
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
return { return {
...linkageRulesProps, ...linkageRulesProps,
collectionName: name, collectionName: associationField?.collectionName || name,
}; };
}, },
useVisible() { useVisible() {
const { collection } = useCurrentPopupRecord() || {}; const { collection } = useCurrentPopupRecord() || {};
const currentCollection = useCollection(); const currentCollection = useCollection();
return !collection || collection?.name === currentCollection?.name; const record = useCollectionRecord();
const { association } = useDataBlockProps() || {};
return (
(!isEmpty(record?.data) && (!collection || collection?.name === currentCollection?.name)) || !!association
);
}, },
}, },
{ {

View File

@ -20,6 +20,7 @@ import { ErrorFallback, StablePopover, TabsContextProvider, useActionContext } f
import { useDesignable } from '../../'; import { useDesignable } from '../../';
import { useACLActionParamsContext } from '../../../acl'; import { useACLActionParamsContext } from '../../../acl';
import { import {
useCollectionParentRecord,
useCollectionParentRecordData, useCollectionParentRecordData,
useCollectionRecordData, useCollectionRecordData,
useDataBlockRequestGetter, useDataBlockRequestGetter,
@ -89,12 +90,15 @@ export const Action: ComposedAction = withDynamicSchemaProps(
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const compile = useCompile(); const compile = useCompile();
const recordData = useCollectionRecordData(); const recordData = useCollectionRecordData();
const parentRecord = useCollectionParentRecord();
const confirm = compile(fieldSchema['x-component-props']?.confirm) || propsConfirm; const confirm = compile(fieldSchema['x-component-props']?.confirm) || propsConfirm;
const linkageRules = useMemo(() => fieldSchema?.['x-linkage-rules'] || [], [fieldSchema?.['x-linkage-rules']]); const linkageRules = useMemo(() => fieldSchema?.['x-linkage-rules'] || [], [fieldSchema?.['x-linkage-rules']]);
const { designable } = useDesignable(); const { designable } = useDesignable();
const tarComponent = useComponent(component) || component; const tarComponent = useComponent(component) || component;
const variables = useVariables(); const variables = useVariables();
const localVariables = useLocalVariables({ currentForm: { values: recordData, readPretty: false } as any }); const localVariables = useLocalVariables({
currentForm: { values: recordData || parentRecord?.data, readPretty: false } as any,
});
const { visibleWithURL, setVisibleWithURL } = usePopupUtils(); const { visibleWithURL, setVisibleWithURL } = usePopupUtils();
const { setSubmitted } = useActionContext(); const { setSubmitted } = useActionContext();
const { getAriaLabel } = useGetAriaLabelOfAction(title); const { getAriaLabel } = useGetAriaLabelOfAction(title);

View File

@ -21,6 +21,9 @@ import {
SecondConFirm, SecondConFirm,
AfterSuccess, AfterSuccess,
RefreshDataBlockRequest, RefreshDataBlockRequest,
SchemaSettingsLinkageRules,
useDataBlockProps,
useCollectionManager_deprecated,
} from '@nocobase/client'; } from '@nocobase/client';
import { ModalProps } from 'antd'; import { ModalProps } from 'antd';
import { isValid } from '@formily/shared'; import { isValid } from '@formily/shared';
@ -158,6 +161,24 @@ export const bulkEditActionSettings = new SchemaSettings({
name: 'updateMode', name: 'updateMode',
Component: UpdateMode, Component: UpdateMode,
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps() || {};
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'remove', name: 'remove',
sort: 100, sort: 100,

View File

@ -20,6 +20,9 @@ import {
RefreshDataBlockRequest, RefreshDataBlockRequest,
useAfterSuccessOptions, useAfterSuccessOptions,
useGlobalVariable, useGlobalVariable,
SchemaSettingsLinkageRules,
useCollectionManager_deprecated,
useDataBlockProps,
} from '@nocobase/client'; } from '@nocobase/client';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import React from 'react'; import React from 'react';
@ -167,6 +170,24 @@ const schemaSettingsItems: SchemaSettingsItemType[] = [
}; };
}, },
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps() || {};
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'remove', name: 'remove',
sort: 100, sort: 100,

View File

@ -20,6 +20,8 @@ import {
useCollectionRecord, useCollectionRecord,
useSchemaToolbar, useSchemaToolbar,
SchemaSettingAccessControl, SchemaSettingAccessControl,
useDataBlockProps,
useCollectionManager_deprecated,
} from '@nocobase/client'; } from '@nocobase/client';
import { CustomRequestSettingsItem } from './components/CustomRequestActionDesigner'; import { CustomRequestSettingsItem } from './components/CustomRequestActionDesigner';
@ -42,14 +44,18 @@ export const customizeCustomRequestActionSettings = new SchemaSettings({
useComponentProps() { useComponentProps() {
const { name } = useCollection() || {}; const { name } = useCollection() || {};
const { linkageRulesProps } = useSchemaToolbar(); const { linkageRulesProps } = useSchemaToolbar();
const { association } = useDataBlockProps();
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
return { return {
...linkageRulesProps, ...linkageRulesProps,
collectionName: name, collectionName: associationField?.collectionName || name,
}; };
}, },
useVisible() { useVisible() {
const record = useCollectionRecord(); const record = useCollectionRecord();
return record && record.data && !record?.isNew; const { association } = useDataBlockProps() || {};
return (record && record.data && !record?.isNew) || !!association;
}, },
}, },
{ {

View File

@ -9,7 +9,15 @@
import { ArrayItems } from '@formily/antd-v5'; import { ArrayItems } from '@formily/antd-v5';
import { ISchema, useField, useFieldSchema } from '@formily/react'; import { ISchema, useField, useFieldSchema } from '@formily/react';
import { ButtonEditor, SchemaSettings, useDesignable, useSchemaToolbar } from '@nocobase/client'; import {
ButtonEditor,
SchemaSettings,
useDesignable,
useSchemaToolbar,
SchemaSettingsLinkageRules,
useDataBlockProps,
useCollectionManager_deprecated,
} from '@nocobase/client';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useShared } from './useShared'; import { useShared } from './useShared';
@ -65,6 +73,24 @@ export const exportActionSchemaSettings = new SchemaSettings({
}; };
}, },
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps();
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'divider', name: 'divider',
type: 'divider', type: 'divider',

View File

@ -9,7 +9,16 @@
import { ArrayItems } from '@formily/antd-v5'; import { ArrayItems } from '@formily/antd-v5';
import { ISchema, useField, useFieldSchema } from '@formily/react'; import { ISchema, useField, useFieldSchema } from '@formily/react';
import { ButtonEditor, SchemaSettings, type, useDesignable, useSchemaToolbar } from '@nocobase/client'; import {
ButtonEditor,
SchemaSettings,
type,
useDesignable,
useSchemaToolbar,
SchemaSettingsLinkageRules,
useDataBlockProps,
useCollectionManager_deprecated,
} from '@nocobase/client';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useShared } from './useShared'; import { useShared } from './useShared';
@ -72,6 +81,24 @@ export const importActionSchemaSettings = new SchemaSettings({
}; };
}, },
}, },
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useVisible() {
const { association } = useDataBlockProps() || {};
return !!association;
},
useComponentProps() {
const { association } = useDataBlockProps();
const { getCollectionField } = useCollectionManager_deprecated();
const associationField = getCollectionField(association);
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: associationField?.collectionName,
};
},
},
{ {
name: 'divider', name: 'divider',
type: 'divider', type: 'divider',