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:
Zeke Zhang 2024-04-16 22:50:52 +08:00 committed by GitHub
parent 8b88b29b5e
commit 3d857d2e69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 368 additions and 190 deletions

View File

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

View File

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

View File

@ -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: [

View File

@ -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();
});
});
});

View 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,
},
};

View File

@ -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>,
);
}

View File

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

View File

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

View File

@ -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(() => {

View File

@ -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(() => {

View File

@ -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}`,

View File

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

View File

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

View File

@ -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}
/>
);
};

View File

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

View File

@ -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,
};
};

View File

@ -29,4 +29,6 @@ export interface DataScopeProps {
*
*/
form: Form;
/** 上下文中不需要当前记录 */
noRecord?: boolean;
}

View File

@ -12,5 +12,7 @@ export function generateNTemplate(key: string) {
}
export function useTranslation() {
return useT(NAMESPACE);
return useT([NAMESPACE, 'client'], {
nsMode: 'fallback',
});
}

View File

@ -15,7 +15,7 @@ export function generateNTemplate(key: string) {
}
export function useKanbanTranslation() {
return useTranslation(NAMESPACE, {
return useTranslation([NAMESPACE, 'client'], {
nsMode: 'fallback',
});
}

View File

@ -15,7 +15,7 @@ export function generateNTemplate(key: string) {
}
export function useMapTranslation() {
return useTranslation(NAMESPACE, {
return useTranslation([NAMESPACE, 'client'], {
nsMode: 'fallback',
});
}