mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-01 18:52:20 +08:00
fix(variable): missing variables and invalid translations (#4054)
* fix(variable): missing variables and invalid translations * refactor: better * fix: should display current record variable * fix: template * chore: add deps * chore: add e2e for table view * fix: current record variable * chore: avoid error * fix: bugs * chore: fix failed e2e * chore: fix e2e * fix: colection name
This commit is contained in:
parent
8b88b29b5e
commit
3d857d2e69
@ -2,6 +2,7 @@ import { ArrayItems } from '@formily/antd-v5';
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
|
||||
import { SchemaSettingsItemType } from '../../../../application/schema-settings/types';
|
||||
import { useFormBlockContext } from '../../../../block-provider';
|
||||
import { useDetailsBlockContext } from '../../../../block-provider/DetailsBlockProvider';
|
||||
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
|
||||
@ -9,7 +10,6 @@ import { removeNullCondition, useDesignable } from '../../../../schema-component
|
||||
import { SchemaSettingsBlockTitleItem, SchemaSettingsTemplate } from '../../../../schema-settings';
|
||||
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
|
||||
import { setDataLoadingModeSettingsItem } from './setDataLoadingModeSettingsItem';
|
||||
import { SchemaSettingsItemType } from '../../../../application/schema-settings/types';
|
||||
|
||||
const commonItems: SchemaSettingsItemType[] = [
|
||||
{
|
||||
@ -29,6 +29,7 @@ const commonItems: SchemaSettingsItemType[] = [
|
||||
collectionName: name,
|
||||
defaultFilter: fieldSchema?.['x-decorator-props']?.params?.filter || {},
|
||||
form,
|
||||
noRecord: true,
|
||||
onSubmit: ({ filter }) => {
|
||||
filter = removeNullCondition(filter);
|
||||
const params = field.decoratorProps.params || {};
|
||||
|
@ -51,19 +51,23 @@ export const FormBlockInitializer = ({
|
||||
},
|
||||
[createBlockSchema, createFormBlock],
|
||||
);
|
||||
const doTemplateWrap = useCallback(
|
||||
(templateSchema, options) => {
|
||||
if (customizeTemplateWrap) {
|
||||
return customizeTemplateWrap(templateSchema, options);
|
||||
}
|
||||
|
||||
return templateWrap(templateSchema, options);
|
||||
},
|
||||
[customizeTemplateWrap, templateWrap],
|
||||
);
|
||||
|
||||
return (
|
||||
<DataBlockInitializer
|
||||
{...itemConfig}
|
||||
icon={<FormOutlined />}
|
||||
componentType={componentType}
|
||||
templateWrap={(templateSchema, options) => {
|
||||
if (customizeTemplateWrap) {
|
||||
return customizeTemplateWrap(templateSchema, options);
|
||||
}
|
||||
|
||||
return templateWrap(templateSchema, options);
|
||||
}}
|
||||
templateWrap={doTemplateWrap}
|
||||
onCreateBlockSchema={onCreateFormBlockSchema}
|
||||
filter={filterCollections}
|
||||
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||
@ -80,28 +84,34 @@ export const useCreateFormBlock = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
const { isCusomeizeCreate: isCustomizeCreate } = itemConfig;
|
||||
|
||||
const createFormBlock = ({ item }) => {
|
||||
insert(
|
||||
createCreateFormBlockUISchema({
|
||||
collectionName: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
isCusomeizeCreate: isCustomizeCreate,
|
||||
}),
|
||||
);
|
||||
};
|
||||
const createFormBlock = useCallback(
|
||||
({ item }) => {
|
||||
insert(
|
||||
createCreateFormBlockUISchema({
|
||||
collectionName: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
isCusomeizeCreate: isCustomizeCreate,
|
||||
}),
|
||||
);
|
||||
},
|
||||
[insert, isCustomizeCreate],
|
||||
);
|
||||
|
||||
const templateWrap = (templateSchema, { item }) => {
|
||||
const schema = createCreateFormBlockUISchema({
|
||||
isCusomeizeCreate: isCustomizeCreate,
|
||||
dataSource: item.dataSource,
|
||||
templateSchema: templateSchema,
|
||||
collectionName: item.name,
|
||||
});
|
||||
if (item.template && item.mode === 'reference') {
|
||||
schema['x-template-key'] = item.template.key;
|
||||
}
|
||||
return schema;
|
||||
};
|
||||
const templateWrap = useCallback(
|
||||
(templateSchema, { item }) => {
|
||||
const schema = createCreateFormBlockUISchema({
|
||||
isCusomeizeCreate: isCustomizeCreate,
|
||||
dataSource: item.dataSource,
|
||||
templateSchema: templateSchema,
|
||||
collectionName: item.name,
|
||||
});
|
||||
if (item.template && item.mode === 'reference') {
|
||||
schema['x-template-key'] = item.template.key;
|
||||
}
|
||||
return schema;
|
||||
},
|
||||
[isCustomizeCreate],
|
||||
);
|
||||
|
||||
return {
|
||||
createFormBlock,
|
||||
|
@ -9,74 +9,6 @@ import {
|
||||
SchemaSettingsLinkageRules,
|
||||
} from '../../../../schema-settings';
|
||||
|
||||
// TODO: 0.20 版之后可以删除
|
||||
export const creationFormBlockSettings = new SchemaSettings({
|
||||
name: 'blockSettings:creationForm',
|
||||
items: [
|
||||
{
|
||||
name: 'title',
|
||||
Component: SchemaSettingsBlockTitleItem,
|
||||
},
|
||||
{
|
||||
name: 'linkageRules',
|
||||
Component: SchemaSettingsLinkageRules,
|
||||
useComponentProps() {
|
||||
const { name } = useCollection_deprecated();
|
||||
return {
|
||||
collectionName: name,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'dataTemplates',
|
||||
Component: SchemaSettingsDataTemplates,
|
||||
useVisible() {
|
||||
const { action } = useFormBlockContext();
|
||||
return !action;
|
||||
},
|
||||
useComponentProps() {
|
||||
const { name } = useCollection_deprecated();
|
||||
return {
|
||||
collectionName: name,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: 'formItemTemplate',
|
||||
Component: SchemaSettingsFormItemTemplate,
|
||||
useComponentProps() {
|
||||
const { name } = useCollection_deprecated();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const defaultResource =
|
||||
fieldSchema?.['x-decorator-props']?.resource || fieldSchema?.['x-decorator-props']?.association;
|
||||
return {
|
||||
componentName: 'FormItem',
|
||||
collectionName: name,
|
||||
resourceName: defaultResource,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider2',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: 'remove',
|
||||
type: 'remove',
|
||||
componentProps: {
|
||||
removeParentsIfNoChildren: true,
|
||||
breakRemoveOn: {
|
||||
'x-component': 'Grid',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const createFormBlockSettings = new SchemaSettings({
|
||||
name: 'blockSettings:createForm',
|
||||
items: [
|
||||
|
@ -0,0 +1,19 @@
|
||||
import { expect, test } from '@nocobase/test/e2e';
|
||||
import { tableViewLinkageRulesVariables } from './templates';
|
||||
|
||||
test.describe('variables', () => {
|
||||
test('linkage rules of table view action', async ({ page, mockPage }) => {
|
||||
await mockPage(tableViewLinkageRulesVariables).goto();
|
||||
|
||||
// 1. 打开联动规则设置弹窗,并显示变量列表
|
||||
await page.getByLabel('action-Action.Link-View-view-').hover();
|
||||
await page.getByLabel('designer-schema-settings-Action.Link-actionSettings:view-users').hover();
|
||||
await page.getByRole('menuitem', { name: 'Linkage rules' }).click();
|
||||
await page.getByLabel('variable-button').click();
|
||||
|
||||
// 2. 断言应该显示的变量
|
||||
['Constant', 'Current user', 'Current role', 'Date variables', 'Current record'].forEach(async (name) => {
|
||||
await expect(page.getByRole('menuitemcheckbox', { name })).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
229
packages/core/client/src/modules/variable/__e2e__/templates.ts
Normal file
229
packages/core/client/src/modules/variable/__e2e__/templates.ts
Normal file
@ -0,0 +1,229 @@
|
||||
export const tableViewLinkageRulesVariables = {
|
||||
pageSchema: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Page',
|
||||
properties: {
|
||||
g1wycipht9k: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'page:addBlock',
|
||||
properties: {
|
||||
'7i8pwd4xhj5': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
pblvpmq357i: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
dwwc54m8ky1: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'TableBlockProvider',
|
||||
'x-acl-action': 'users:list',
|
||||
'x-use-decorator-props': 'useTableBlockDecoratorProps',
|
||||
'x-decorator-props': {
|
||||
collection: 'users',
|
||||
dataSource: 'main',
|
||||
action: 'list',
|
||||
params: {
|
||||
pageSize: 20,
|
||||
},
|
||||
rowKey: 'id',
|
||||
showIndex: true,
|
||||
dragSort: false,
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:table',
|
||||
'x-component': 'CardItem',
|
||||
'x-filter-targets': [],
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-initializer': 'table:configureActions',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
style: {
|
||||
marginBottom: 'var(--nb-spacing)',
|
||||
},
|
||||
},
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
'x-uid': 'dwfejl3y35l',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
b0gp5kve5cy: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'array',
|
||||
'x-initializer': 'table:configureColumns',
|
||||
'x-component': 'TableV2',
|
||||
'x-use-component-props': 'useTableBlockProps',
|
||||
'x-component-props': {
|
||||
rowKey: 'id',
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
},
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("Actions") }}',
|
||||
'x-action-column': 'actions',
|
||||
'x-decorator': 'TableV2.Column.ActionBar',
|
||||
'x-component': 'TableV2.Column',
|
||||
'x-designer': 'TableV2.ActionColumnDesigner',
|
||||
'x-initializer': 'table:configureItemActions',
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
tf980vw8dg7: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'DndContext',
|
||||
'x-component': 'Space',
|
||||
'x-component-props': {
|
||||
split: '|',
|
||||
},
|
||||
'x-app-version': '0.21.0-alpha.8',
|
||||
properties: {
|
||||
dmpqsodnxr6: {
|
||||
'x-uid': 'vivhb5goy37',
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("View") }}',
|
||||
'x-action': 'view',
|
||||
'x-toolbar': 'ActionSchemaToolbar',
|
||||
'x-settings': 'actionSettings:view',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component-props': {
|
||||
openMode: 'drawer',
|
||||
},
|
||||
'x-decorator': 'ACLActionProvider',
|
||||
'x-designer-props': {
|
||||
linkageAction: true,
|
||||
},
|
||||
'x-linkage-rules': [
|
||||
{
|
||||
condition: {
|
||||
$and: [{}],
|
||||
},
|
||||
actions: [],
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
drawer: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("View record") }}',
|
||||
'x-component': 'Action.Container',
|
||||
'x-component-props': {
|
||||
className: 'nb-action-popup',
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
'x-component-props': {},
|
||||
'x-initializer': 'popup:addTab',
|
||||
properties: {
|
||||
tab1: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{t("Details")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-designer': 'Tabs.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'popup:common:addBlock',
|
||||
'x-uid': '8mxgjwcq1lu',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '9fbdmfbk67y',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'dn6hvykic0s',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'czk4w54afwy',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '3hbqk34vlxs',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'fptg47gw3v0',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'r6rocjxtxwr',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': 'gy0al0nl08m',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '2vkcx6nt5y0',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '2zeeh485ev6',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'ckrzeha5h5t',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'qnwmpeqykgx',
|
||||
'x-async': true,
|
||||
'x-index': 1,
|
||||
},
|
||||
};
|
@ -9,10 +9,16 @@ import { StablePopover, useActionContext } from '../..';
|
||||
import { useDesignable } from '../../';
|
||||
import { useACLActionParamsContext } from '../../../acl';
|
||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
|
||||
import { useCollectionParentRecordData, useDataBlockRequest } from '../../../data-source';
|
||||
import {
|
||||
useCollection,
|
||||
useCollectionParentRecordData,
|
||||
useCollectionRecordData,
|
||||
useDataBlockRequest,
|
||||
} from '../../../data-source';
|
||||
import { Icon } from '../../../icon';
|
||||
import { TreeRecordProvider } from '../../../modules/blocks/data-blocks/table/TreeRecordProvider';
|
||||
import { RecordProvider, useRecord } from '../../../record-provider';
|
||||
import { DeclareVariable } from '../../../modules/variable/DeclareVariable';
|
||||
import { RecordProvider } from '../../../record-provider';
|
||||
import { useLocalVariables, useVariables } from '../../../variables';
|
||||
import { SortableItem } from '../../common';
|
||||
import { useCompile, useComponent, useDesigner } from '../../hooks';
|
||||
@ -63,8 +69,9 @@ export const Action: ComposedAction = withDynamicSchemaProps(
|
||||
const fieldSchema = useFieldSchema();
|
||||
const compile = useCompile();
|
||||
const form = useForm();
|
||||
const record = useRecord();
|
||||
const recordData = useCollectionRecordData();
|
||||
const parentRecordData = useCollectionParentRecordData();
|
||||
const collection = useCollection();
|
||||
const designerProps = fieldSchema['x-designer-props'];
|
||||
const openMode = fieldSchema?.['x-component-props']?.['openMode'];
|
||||
const openSize = fieldSchema?.['x-component-props']?.['openSize'];
|
||||
@ -76,7 +83,7 @@ export const Action: ComposedAction = withDynamicSchemaProps(
|
||||
const tarComponent = useComponent(component) || component;
|
||||
const { modal } = App.useApp();
|
||||
const variables = useVariables();
|
||||
const localVariables = useLocalVariables({ currentForm: { values: record } as any });
|
||||
const localVariables = useLocalVariables({ currentForm: { values: recordData } as any });
|
||||
const { getAriaLabel } = useGetAriaLabelOfAction(title);
|
||||
const service = useDataBlockRequest();
|
||||
|
||||
@ -196,7 +203,14 @@ export const Action: ComposedAction = withDynamicSchemaProps(
|
||||
>
|
||||
{popover && <RecursionField basePath={field.address} onlyRenderProperties schema={fieldSchema} />}
|
||||
{!popover && renderButton()}
|
||||
{!popover && props.children}
|
||||
<DeclareVariable
|
||||
name="$nPopupRecord"
|
||||
title={t('Current popup record')}
|
||||
value={recordData}
|
||||
collection={collection}
|
||||
>
|
||||
{!popover && props.children}
|
||||
</DeclareVariable>
|
||||
{element}
|
||||
</ActionContextProvider>
|
||||
);
|
||||
@ -206,7 +220,7 @@ export const Action: ComposedAction = withDynamicSchemaProps(
|
||||
return wrapSSR(
|
||||
// fix https://nocobase.height.app/T-3966
|
||||
<RecordProvider record={null} parent={parentRecordData}>
|
||||
<TreeRecordProvider parent={record}>{result}</TreeRecordProvider>
|
||||
<TreeRecordProvider parent={recordData}>{result}</TreeRecordProvider>
|
||||
</RecordProvider>,
|
||||
);
|
||||
}
|
||||
|
@ -3,11 +3,8 @@ import { ObjectField } from '@formily/core';
|
||||
import { useField } from '@formily/react';
|
||||
import { Card } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
|
||||
import { useCollectionParentRecordData } from '../../../data-source/collection-record/CollectionRecordProvider';
|
||||
import { useCollection } from '../../../data-source/collection/CollectionProvider';
|
||||
import { DeclareVariable } from '../../../modules/variable/DeclareVariable';
|
||||
import { RecordProvider } from '../../../record-provider';
|
||||
|
||||
const itemCss = css`
|
||||
@ -32,22 +29,13 @@ const gridCardCss = css`
|
||||
|
||||
export const GridCardItem = withDynamicSchemaProps(
|
||||
(props) => {
|
||||
const { t } = useTranslation();
|
||||
const collection = useCollection();
|
||||
const field = useField<ObjectField>();
|
||||
const parentRecordData = useCollectionParentRecordData();
|
||||
return (
|
||||
<Card role="button" aria-label="grid-card-item" className={gridCardCss}>
|
||||
<div className={itemCss}>
|
||||
<RecordProvider record={field.value} parent={parentRecordData}>
|
||||
<DeclareVariable
|
||||
name="$nPopupRecord"
|
||||
title={t('Current popup record')}
|
||||
value={field.value}
|
||||
collection={collection}
|
||||
>
|
||||
{props.children}
|
||||
</DeclareVariable>
|
||||
{props.children}
|
||||
</RecordProvider>
|
||||
</div>
|
||||
</Card>
|
||||
|
@ -5,16 +5,11 @@ import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
import { useDesignable } from '../../hooks';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
|
||||
import { useCollectionParentRecordData } from '../../../data-source/collection-record/CollectionRecordProvider';
|
||||
import { useCollection } from '../../../data-source/collection/CollectionProvider';
|
||||
import { DeclareVariable } from '../../../modules/variable/DeclareVariable';
|
||||
import { RecordProvider } from '../../../record-provider';
|
||||
|
||||
export const ListItem = withDynamicSchemaProps((props) => {
|
||||
const { t } = useTranslation();
|
||||
const collection = useCollection();
|
||||
const field = useField<ObjectField>();
|
||||
const { designable } = useDesignable();
|
||||
const parentRecordData = useCollectionParentRecordData();
|
||||
@ -31,14 +26,7 @@ export const ListItem = withDynamicSchemaProps((props) => {
|
||||
])}
|
||||
>
|
||||
<RecordProvider record={field.value} parent={parentRecordData}>
|
||||
<DeclareVariable
|
||||
name="$nPopupRecord"
|
||||
title={t('Current popup record')}
|
||||
value={field.value}
|
||||
collection={collection}
|
||||
>
|
||||
{props.children}
|
||||
</DeclareVariable>
|
||||
{props.children}
|
||||
</RecordProvider>
|
||||
</div>
|
||||
);
|
||||
|
@ -28,7 +28,6 @@ import {
|
||||
import { useACLFieldWhitelist } from '../../../acl/ACLProvider';
|
||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
|
||||
import { isNewRecord } from '../../../data-source/collection-record/isNewRecord';
|
||||
import { DeclareVariable } from '../../../modules/variable/DeclareVariable';
|
||||
import { useToken } from '../__builtins__';
|
||||
import { SubFormProvider } from '../association-field/hooks';
|
||||
import { ColumnFieldProvider } from './components/ColumnFieldProvider';
|
||||
@ -57,7 +56,6 @@ export const useColumnsDeepMemoized = (columns: any[]) => {
|
||||
};
|
||||
|
||||
const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { token } = useToken();
|
||||
const field = useArrayField(props);
|
||||
const schema = useFieldSchema();
|
||||
@ -108,24 +106,17 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
|
||||
const index = field.value?.indexOf(record);
|
||||
const basePath = field.address.concat(record.__index || index);
|
||||
return (
|
||||
<DeclareVariable
|
||||
name="$nPopupRecord"
|
||||
title={t('Current popup record')}
|
||||
value={record}
|
||||
collection={collection}
|
||||
>
|
||||
<SubFormProvider value={{ value: record, collection }}>
|
||||
<RecordIndexProvider index={record.__index || index}>
|
||||
<RecordProvider isNew={isNewRecord(record)} record={record} parent={parentRecordData}>
|
||||
<ColumnFieldProvider schema={s} basePath={basePath}>
|
||||
<span role="button" className={schemaToolbarBigger}>
|
||||
<RecursionField basePath={basePath} schema={s} onlyRenderProperties />
|
||||
</span>
|
||||
</ColumnFieldProvider>
|
||||
</RecordProvider>
|
||||
</RecordIndexProvider>
|
||||
</SubFormProvider>
|
||||
</DeclareVariable>
|
||||
<SubFormProvider value={{ value: record, collection }}>
|
||||
<RecordIndexProvider index={record.__index || index}>
|
||||
<RecordProvider isNew={isNewRecord(record)} record={record} parent={parentRecordData}>
|
||||
<ColumnFieldProvider schema={s} basePath={basePath}>
|
||||
<span role="button" className={schemaToolbarBigger}>
|
||||
<RecursionField basePath={basePath} schema={s} onlyRenderProperties />
|
||||
</span>
|
||||
</ColumnFieldProvider>
|
||||
</RecordProvider>
|
||||
</RecordIndexProvider>
|
||||
</SubFormProvider>
|
||||
);
|
||||
},
|
||||
} as TableColumnProps<any>;
|
||||
@ -133,15 +124,7 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
|
||||
// 这里不能把 columnsSchema 作为依赖,因为其每次都会变化,这里使用 hasChangedColumns 作为依赖
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}),
|
||||
[
|
||||
hasChangedColumns,
|
||||
schema,
|
||||
field,
|
||||
parentRecordData,
|
||||
schemaInWhitelist,
|
||||
token.paddingContentVerticalLG,
|
||||
token.marginSM,
|
||||
],
|
||||
[columnsSchema, field.value, field.address, collection, parentRecordData, schemaToolbarBigger],
|
||||
);
|
||||
|
||||
const tableColumns = useMemo(() => {
|
||||
|
@ -280,14 +280,11 @@ export interface DataBlockInitializerProps {
|
||||
/** 如果只有一项数据表时,不显示 children 列表 */
|
||||
hideChildrenIfSingleCollection?: boolean;
|
||||
items?: ReturnType<typeof useCollectionDataSourceItems>[];
|
||||
/**
|
||||
* 是否是点击弹窗中的 Others 选项进入的
|
||||
*/
|
||||
fromOthersInPopup?: boolean;
|
||||
/**
|
||||
* 隐藏弹窗中的 Other records 选项
|
||||
*/
|
||||
hideOtherRecordsInPopup?: boolean;
|
||||
onClick?: (args: any) => void;
|
||||
}
|
||||
|
||||
export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
@ -305,14 +302,20 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
hideChildrenIfSingleCollection,
|
||||
filterDataSource,
|
||||
items: itemsFromProps,
|
||||
fromOthersInPopup,
|
||||
hideOtherRecordsInPopup,
|
||||
onClick: propsOnClick,
|
||||
} = props;
|
||||
const { insert, setVisible } = useSchemaInitializer();
|
||||
const compile = useCompile();
|
||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||
const onClick = useCallback(
|
||||
async ({ item }) => {
|
||||
async (options) => {
|
||||
const { item, fromOthersInPopup } = options;
|
||||
|
||||
if (propsOnClick) {
|
||||
return propsOnClick(options);
|
||||
}
|
||||
|
||||
if (item.template) {
|
||||
const s = await getTemplateSchemaByMode(item);
|
||||
templateWrap ? insert(templateWrap(s, { item, fromOthersInPopup })) : insert(s);
|
||||
@ -323,7 +326,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
}
|
||||
setVisible(false);
|
||||
},
|
||||
[fromOthersInPopup, getTemplateSchemaByMode, insert, onCreateBlockSchema, setVisible, templateWrap],
|
||||
[getTemplateSchemaByMode, insert, onCreateBlockSchema, propsOnClick, setVisible, templateWrap],
|
||||
);
|
||||
const items =
|
||||
itemsFromProps ||
|
||||
@ -336,6 +339,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
showAssociationFields,
|
||||
dataBlockInitializerProps: props,
|
||||
hideOtherRecordsInPopup,
|
||||
onClick,
|
||||
});
|
||||
const getMenuItems = useGetSchemaInitializerMenuItems(onClick);
|
||||
const childItems = useMemo(() => {
|
||||
|
@ -79,10 +79,9 @@ export function useCreateAssociationFormBlock() {
|
||||
|
||||
const templateWrap = useCallback(
|
||||
(templateSchema, { item }) => {
|
||||
const field = item.associationField;
|
||||
const collection = getCollection(field.target);
|
||||
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
if (item.template.componentName === 'FormItem' && item.associationField) {
|
||||
const field = item.associationField;
|
||||
const collection = getCollection(field.target);
|
||||
const blockSchema = createCreateFormBlockUISchema({
|
||||
dataSource: collection.dataSource,
|
||||
association: `${field.collectionName}.${field.name}`,
|
||||
|
@ -13,13 +13,13 @@ import {
|
||||
useDataSourceKey,
|
||||
useFormBlockContext,
|
||||
} from '../';
|
||||
import { useFormActiveFields } from '../block-provider/hooks/useFormActiveFields';
|
||||
import { FieldOptions, useCollectionManager_deprecated, useCollection_deprecated } from '../collection-manager';
|
||||
import { Collection, CollectionFieldOptions } from '../data-source/collection/Collection';
|
||||
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
|
||||
import { isAssocField } from '../filter-provider/utils';
|
||||
import { useActionContext, useCompile, useDesignable } from '../schema-component';
|
||||
import { useSchemaTemplateManager } from '../schema-templates';
|
||||
import { useFormActiveFields } from '../block-provider/hooks/useFormActiveFields';
|
||||
export const itemsMerge = (items1) => {
|
||||
return items1;
|
||||
};
|
||||
@ -842,6 +842,7 @@ export const useCollectionDataSourceItems = ({
|
||||
filterDataSource,
|
||||
dataBlockInitializerProps,
|
||||
hideOtherRecordsInPopup,
|
||||
onClick,
|
||||
}: {
|
||||
componentName;
|
||||
filter?: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||
@ -853,6 +854,7 @@ export const useCollectionDataSourceItems = ({
|
||||
* 隐藏弹窗中的 Other records 选项
|
||||
*/
|
||||
hideOtherRecordsInPopup?: boolean;
|
||||
onClick?: (options: any) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const dm = useDataSourceManager();
|
||||
@ -956,11 +958,13 @@ export const useCollectionDataSourceItems = ({
|
||||
onlyCurrentDataSource: false,
|
||||
hideChildrenIfSingleCollection: false,
|
||||
onCreateBlockSchema: dataBlockInitializerProps.onCreateBlockSchema,
|
||||
fromOthersInPopup: true,
|
||||
componentType: componentTypeMap[componentName] || componentName,
|
||||
filter({ collection: c, associationField }) {
|
||||
return true;
|
||||
},
|
||||
onClick(options) {
|
||||
onClick({ ...options, fromOthersInPopup: true });
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1008,6 +1012,7 @@ export const useCollectionDataSourceItems = ({
|
||||
dataBlockInitializerProps,
|
||||
hideOtherRecordsInPopup,
|
||||
noAssociationMenu,
|
||||
onClick,
|
||||
t,
|
||||
]);
|
||||
}
|
||||
@ -1608,7 +1613,6 @@ function useAssociationFields({
|
||||
};
|
||||
});
|
||||
}, [
|
||||
cm,
|
||||
collection.fields,
|
||||
compile,
|
||||
componentName,
|
||||
|
@ -65,7 +65,6 @@ import {
|
||||
useGlobalTheme,
|
||||
useLinkageCollectionFilterOptions,
|
||||
useRecord,
|
||||
useSchemaSettingsItem,
|
||||
useSortFields,
|
||||
} from '..';
|
||||
import {
|
||||
@ -947,6 +946,8 @@ export interface SchemaSettingsModalItemProps {
|
||||
asyncGetInitialValues?: () => Promise<any>;
|
||||
eventKey?: string;
|
||||
hide?: boolean;
|
||||
/** 上下文中不需要当前记录 */
|
||||
noRecord?: boolean;
|
||||
}
|
||||
export const SchemaSettingsModalItem: FC<SchemaSettingsModalItemProps> = (props) => {
|
||||
const {
|
||||
@ -959,6 +960,7 @@ export const SchemaSettingsModalItem: FC<SchemaSettingsModalItemProps> = (props)
|
||||
asyncGetInitialValues,
|
||||
initialValues,
|
||||
width = 'fit-content',
|
||||
noRecord = false,
|
||||
...others
|
||||
} = props;
|
||||
const options = useContext(SchemaOptionsContext);
|
||||
@ -1000,7 +1002,7 @@ export const SchemaSettingsModalItem: FC<SchemaSettingsModalItemProps> = (props)
|
||||
value={popupRecordVariable.value}
|
||||
collection={popupRecordVariable.collection}
|
||||
>
|
||||
<CollectionRecordProvider record={record}>
|
||||
<CollectionRecordProvider record={noRecord ? null : record}>
|
||||
<FormBlockContext.Provider value={formCtx}>
|
||||
<SubFormProvider value={{ value: subFormValue, collection: subFormCollection }}>
|
||||
<FormActiveFieldsProvider
|
||||
|
@ -7,10 +7,10 @@ import { useCollectionFilterOptionsV2 } from '../collection-manager/action-hooks
|
||||
import { FlagProvider, useFlag } from '../flag-provider';
|
||||
import { DynamicComponentProps } from '../schema-component/antd/filter/DynamicComponent';
|
||||
import { useLocalVariables, useVariables } from '../variables';
|
||||
import { SchemaSettingsModalItem } from './SchemaSettings';
|
||||
import { VariableInput, getShouldChange } from './VariableInput/VariableInput';
|
||||
import { BaseVariableProvider, IsDisabledParams } from './VariableInput/hooks/useBaseVariable';
|
||||
import { DataScopeProps } from './types';
|
||||
import { SchemaSettingsModalItem } from './SchemaSettings';
|
||||
|
||||
export const SchemaSettingsDataScope: FC<DataScopeProps> = function DataScopeConfigure(props) {
|
||||
const { t } = useTranslation();
|
||||
@ -76,6 +76,7 @@ export const SchemaSettingsDataScope: FC<DataScopeProps> = function DataScopeCon
|
||||
initialValues={{ filter: props.defaultFilter }}
|
||||
schema={getSchema as () => ISchema}
|
||||
onSubmit={props.onSubmit}
|
||||
noRecord={props.noRecord}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -23,10 +23,7 @@ import {
|
||||
detailsBlockSettings,
|
||||
singleDataDetailsBlockSettings,
|
||||
} from '../modules/blocks/data-blocks/details-single/detailsBlockSettings';
|
||||
import {
|
||||
createFormBlockSettings,
|
||||
creationFormBlockSettings,
|
||||
} from '../modules/blocks/data-blocks/form/createFormBlockSettings';
|
||||
import { createFormBlockSettings } from '../modules/blocks/data-blocks/form/createFormBlockSettings';
|
||||
import { editFormBlockSettings } from '../modules/blocks/data-blocks/form/editFormBlockSettings';
|
||||
import { fieldSettingsFormItem } from '../modules/blocks/data-blocks/form/fieldSettingsFormItem';
|
||||
import { gridCardBlockSettings } from '../modules/blocks/data-blocks/grid-card/gridCardBlockSettings';
|
||||
@ -43,6 +40,7 @@ import { cascadeSelectComponentFieldSettings } from '../modules/fields/component
|
||||
import { datePickerComponentFieldSettings } from '../modules/fields/component/DatePicker/datePickerComponentFieldSettings';
|
||||
import { fileManagerComponentFieldSettings } from '../modules/fields/component/FileManager/fileManagerComponentFieldSettings';
|
||||
import { uploadAttachmentComponentFieldSettings } from '../modules/fields/component/FileManager/uploadAttachmentComponentFieldSettings';
|
||||
import { inputNumberComponentFieldSettings } from '../modules/fields/component/InputNumber/inputNumberComponentFieldSettings';
|
||||
import { subformComponentFieldSettings } from '../modules/fields/component/Nester/subformComponentFieldSettings';
|
||||
import { recordPickerComponentFieldSettings } from '../modules/fields/component/Picker/recordPickerComponentFieldSettings';
|
||||
import { subformPopoverComponentFieldSettings } from '../modules/fields/component/PopoverNester/subformPopoverComponentFieldSettings';
|
||||
@ -50,13 +48,11 @@ import { selectComponentFieldSettings } from '../modules/fields/component/Select
|
||||
import { subTablePopoverComponentFieldSettings } from '../modules/fields/component/SubTable/subTablePopoverComponentFieldSettings';
|
||||
import { tagComponentFieldSettings } from '../modules/fields/component/Tag/tagComponentFieldSettings';
|
||||
import { unixTimestampComponentFieldSettings } from '../modules/fields/component/UnixTimestamp/unixTimestampComponentFieldSettings';
|
||||
import { inputNumberComponentFieldSettings } from '../modules/fields/component/InputNumber/inputNumberComponentFieldSettings';
|
||||
|
||||
export class SchemaSettingsPlugin extends Plugin {
|
||||
async load() {
|
||||
// block settings
|
||||
this.schemaSettingsManager.add(tableBlockSettings);
|
||||
this.schemaSettingsManager.add(creationFormBlockSettings);
|
||||
this.schemaSettingsManager.add(createFormBlockSettings);
|
||||
this.schemaSettingsManager.add(editFormBlockSettings);
|
||||
this.schemaSettingsManager.add(filterFormBlockSettings);
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Schema } from '@formily/json-schema';
|
||||
import _ from 'lodash';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CollectionFieldOptions_deprecated } from '../../../collection-manager';
|
||||
import { useBaseVariable } from './useBaseVariable';
|
||||
import { useFormBlockContext } from '../../../block-provider/FormBlockProvider';
|
||||
import { CollectionFieldOptions_deprecated } from '../../../collection-manager';
|
||||
import { useCollection, useCollectionRecordData } from '../../../data-source';
|
||||
import { useBaseVariable } from './useBaseVariable';
|
||||
|
||||
interface Props {
|
||||
collectionField?: CollectionFieldOptions_deprecated;
|
||||
@ -45,13 +46,16 @@ export const useRecordVariable = (props: Props) => {
|
||||
*/
|
||||
export const useCurrentRecordVariable = (props: Props = {}) => {
|
||||
const { t } = useTranslation();
|
||||
const collection = useCollection();
|
||||
const recordData = useCollectionRecordData();
|
||||
const { formRecord, collectionName } = useFormBlockContext();
|
||||
const realCollectionName = formRecord?.data ? collectionName : collection?.name;
|
||||
const currentRecordSettings = useBaseVariable({
|
||||
collectionField: props.collectionField,
|
||||
uiSchema: props.schema,
|
||||
name: '$nRecord',
|
||||
title: t('Current record'),
|
||||
collectionName: collectionName,
|
||||
collectionName: realCollectionName,
|
||||
noDisabled: props.noDisabled,
|
||||
targetFieldSchema: props.targetFieldSchema,
|
||||
});
|
||||
@ -60,10 +64,10 @@ export const useCurrentRecordVariable = (props: Props = {}) => {
|
||||
/** 变量配置 */
|
||||
currentRecordSettings,
|
||||
/** 变量值 */
|
||||
currentRecordCtx: formRecord?.data,
|
||||
currentRecordCtx: formRecord?.data || recordData,
|
||||
/** 用于判断是否需要显示配置项 */
|
||||
shouldDisplayCurrentRecord: !formRecord?.isNew && !_.isEmpty(formRecord?.data),
|
||||
shouldDisplayCurrentRecord: !_.isEmpty(_.omit(recordData, ['__collectionName', '__parent'])) || !!formRecord?.data,
|
||||
/** 当前记录对应的 collection name */
|
||||
collectionName,
|
||||
collectionName: realCollectionName,
|
||||
};
|
||||
};
|
||||
|
@ -29,4 +29,6 @@ export interface DataScopeProps {
|
||||
* 当前表单区块中的表单实例
|
||||
*/
|
||||
form: Form;
|
||||
/** 上下文中不需要当前记录 */
|
||||
noRecord?: boolean;
|
||||
}
|
||||
|
@ -12,5 +12,7 @@ export function generateNTemplate(key: string) {
|
||||
}
|
||||
|
||||
export function useTranslation() {
|
||||
return useT(NAMESPACE);
|
||||
return useT([NAMESPACE, 'client'], {
|
||||
nsMode: 'fallback',
|
||||
});
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export function generateNTemplate(key: string) {
|
||||
}
|
||||
|
||||
export function useKanbanTranslation() {
|
||||
return useTranslation(NAMESPACE, {
|
||||
return useTranslation([NAMESPACE, 'client'], {
|
||||
nsMode: 'fallback',
|
||||
});
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export function generateNTemplate(key: string) {
|
||||
}
|
||||
|
||||
export function useMapTranslation() {
|
||||
return useTranslation(NAMESPACE, {
|
||||
return useTranslation([NAMESPACE, 'client'], {
|
||||
nsMode: 'fallback',
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user