Reviewed-on: daoyoucloud/tachybase#1072
This commit is contained in:
parent
9e1bfbf8c4
commit
dc175f789f
@ -1,4 +1,5 @@
|
|||||||
import React, { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
import { APIClient } from './APIClient';
|
import { APIClient } from './APIClient';
|
||||||
|
|
||||||
export const APIClientContext = createContext<APIClient>(new APIClient());
|
export const APIClientContext = createContext<APIClient>(new APIClient());
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { APIClientContext } from '../context';
|
import { APIClientContext } from '../context';
|
||||||
|
|
||||||
export function useAPIClient() {
|
export function useAPIClient() {
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { merge } from '@tachybase/schema';
|
import { merge } from '@tachybase/schema';
|
||||||
|
|
||||||
import { useRequest as useReq, useSetState } from 'ahooks';
|
import { useRequest as useReq, useSetState } from 'ahooks';
|
||||||
import { Options, Result } from 'ahooks/es/useRequest/src/types';
|
import { Options, Result } from 'ahooks/es/useRequest/src/types';
|
||||||
|
import { SetState } from 'ahooks/lib/useSetState';
|
||||||
import { AxiosRequestConfig } from 'axios';
|
import { AxiosRequestConfig } from 'axios';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
import { assign } from './assign';
|
import { assign } from './assign';
|
||||||
import { useAPIClient } from './useAPIClient';
|
import { useAPIClient } from './useAPIClient';
|
||||||
import { SetState } from 'ahooks/lib/useSetState';
|
|
||||||
|
|
||||||
type FunctionService = (...args: any[]) => Promise<any>;
|
type FunctionService = (...args: any[]) => Promise<any>;
|
||||||
|
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
import { ChangeEvent, useCallback, useContext, useEffect, useMemo } from 'react';
|
import { ChangeEvent, useCallback, useEffect } from 'react';
|
||||||
import {
|
import { Field, Form, untracked, useField, useFieldSchema, useForm } from '@tachybase/schema';
|
||||||
Field,
|
|
||||||
Form,
|
|
||||||
SchemaExpressionScopeContext,
|
|
||||||
untracked,
|
|
||||||
useField,
|
|
||||||
useFieldSchema,
|
|
||||||
useForm,
|
|
||||||
} from '@tachybase/schema';
|
|
||||||
import { isURL, parse } from '@tachybase/utils/client';
|
import { isURL, parse } from '@tachybase/utils/client';
|
||||||
|
|
||||||
import { App, message } from 'antd';
|
import { App, message } from 'antd';
|
||||||
@ -25,7 +17,6 @@ import {
|
|||||||
useDataSourceHeaders,
|
useDataSourceHeaders,
|
||||||
useFormActiveFields,
|
useFormActiveFields,
|
||||||
useFormBlockContext,
|
useFormBlockContext,
|
||||||
useTableBlockContext,
|
|
||||||
} from '../..';
|
} from '../..';
|
||||||
import { useAPIClient, useRequest } from '../../api-client';
|
import { useAPIClient, useRequest } from '../../api-client';
|
||||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
@ -1313,7 +1304,7 @@ function getTargetField(obj) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 之所以不直接使用 form.reset() 是因为其无法将子表格重置为空
|
* 之所以不直接使用 form.reset() 是因为其无法将子表格重置为空
|
||||||
* 主要用于修复这个问题:https://tachybase.height.app/T-3106
|
* 主要用于修复这个问题:
|
||||||
* @param form
|
* @param form
|
||||||
*/
|
*/
|
||||||
async function resetFormCorrectly(form: Form) {
|
async function resetFormCorrectly(form: Form) {
|
||||||
|
@ -15,8 +15,6 @@ import {
|
|||||||
* 是需要从 recordData 还是 parentRecordData 中获取;解决方法是通过更改 schema,在不同类型的关系区块中
|
* 是需要从 recordData 还是 parentRecordData 中获取;解决方法是通过更改 schema,在不同类型的关系区块中
|
||||||
* (`通过点击关系字段按钮打开的弹窗中创建的非关系字段区块`和`关系字段区块`)使用不同的 hook。
|
* (`通过点击关系字段按钮打开的弹窗中创建的非关系字段区块`和`关系字段区块`)使用不同的 hook。
|
||||||
*
|
*
|
||||||
* 更新:上面所说的“需要更改 schema 才能解决的问题”已在这个任务中更改:https://tachybase.height.app/T-3848/description
|
|
||||||
*
|
|
||||||
* @param param0
|
* @param param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
PinnedPluginList,
|
PinnedPluginList,
|
||||||
RemoteCollectionManagerProvider,
|
RemoteCollectionManagerProvider,
|
||||||
RemoteSchemaTemplateManagerPlugin,
|
RemoteSchemaTemplateManagerPlugin,
|
||||||
RemoteSchemaTemplateManagerProvider,
|
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
useACLRoleContext,
|
useACLRoleContext,
|
||||||
useAdminSchemaUid,
|
useAdminSchemaUid,
|
||||||
@ -445,13 +444,11 @@ export const AdminProvider = (props) => {
|
|||||||
return (
|
return (
|
||||||
<CurrentAppInfoProvider>
|
<CurrentAppInfoProvider>
|
||||||
<NavigateIfNotSignIn>
|
<NavigateIfNotSignIn>
|
||||||
<RemoteSchemaTemplateManagerProvider>
|
<RemoteCollectionManagerProvider>
|
||||||
<RemoteCollectionManagerProvider>
|
<VariablesProvider>
|
||||||
<VariablesProvider>
|
<ACLRolesCheckProvider>{props.children}</ACLRolesCheckProvider>
|
||||||
<ACLRolesCheckProvider>{props.children}</ACLRolesCheckProvider>
|
</VariablesProvider>
|
||||||
</VariablesProvider>
|
</RemoteCollectionManagerProvider>
|
||||||
</RemoteCollectionManagerProvider>
|
|
||||||
</RemoteSchemaTemplateManagerProvider>
|
|
||||||
</NavigateIfNotSignIn>
|
</NavigateIfNotSignIn>
|
||||||
</CurrentAppInfoProvider>
|
</CurrentAppInfoProvider>
|
||||||
);
|
);
|
||||||
|
@ -587,7 +587,6 @@ export const useFilterActionProps = () => {
|
|||||||
const options = useFilterFieldOptions(collection.fields);
|
const options = useFilterFieldOptions(collection.fields);
|
||||||
const service = useResourceActionContext();
|
const service = useResourceActionContext();
|
||||||
return useFilterFieldProps({
|
return useFilterFieldProps({
|
||||||
// 目前仅需要支持筛选 title 和 name,其它字段可能会报错。详见:https://tachybase.height.app/T-2745
|
|
||||||
options: options.filter((option) => ['title', 'name'].includes(option.name)),
|
options: options.filter((option) => ['title', 'name'].includes(option.name)),
|
||||||
params: service.state?.params?.[0] || service.params,
|
params: service.state?.params?.[0] || service.params,
|
||||||
service,
|
service,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Select } from 'antd';
|
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
import { Select } from 'antd';
|
||||||
|
|
||||||
export interface SelectWithTitleProps {
|
export interface SelectWithTitleProps {
|
||||||
title?: any;
|
title?: any;
|
||||||
defaultValue?: any;
|
defaultValue?: any;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Field } from '@tachybase/schema';
|
import { Field, useField, useFieldSchema } from '@tachybase/schema';
|
||||||
import { useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
|
import { useCollectionField, useCollectionManager } from '../data-source';
|
||||||
import { useIsFileField } from '../schema-component/antd/form-item/FormItem.Settings';
|
import { useIsFileField } from '../schema-component/antd/form-item/FormItem.Settings';
|
||||||
import { useColumnSchema } from '../schema-component/antd/table-v2/Table.Column.Decorator';
|
import { useColumnSchema } from '../schema-component/antd/table-v2/Table.Column.Decorator';
|
||||||
import { useCollectionField, useCollectionManager } from '../data-source';
|
|
||||||
|
|
||||||
export function useFieldComponentName(): string {
|
export function useFieldComponentName(): string {
|
||||||
const { fieldSchema: tableColumnSchema, collectionField: tableColumnField } = useColumnSchema();
|
const { fieldSchema: tableColumnSchema, collectionField: tableColumnField } = useColumnSchema();
|
||||||
|
@ -21,5 +21,6 @@ export const useNiceDropdownMaxHeight = (deps: any[] = []) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
return useMemo(() => heightRef.current - 40, deps);
|
return useMemo(() => heightRef.current - 40, deps);
|
||||||
};
|
};
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
|
import React, { createContext, ReactNode, useContext, useMemo } from 'react';
|
||||||
import { IResource } from '@tachybase/sdk';
|
import { IResource } from '@tachybase/sdk';
|
||||||
import React, { FC, ReactNode, createContext, useContext, useMemo } from 'react';
|
|
||||||
|
|
||||||
import { useCollectionManager } from '../collection';
|
|
||||||
import { useDataBlockProps } from './DataBlockProvider';
|
|
||||||
import { useAPIClient } from '../../api-client';
|
import { useAPIClient } from '../../api-client';
|
||||||
|
import { useCollectionManager } from '../collection';
|
||||||
import { CollectionRecord } from '../collection-record';
|
import { CollectionRecord } from '../collection-record';
|
||||||
import { useDataSourceHeaders } from '../utils';
|
import { useDataSourceHeaders } from '../utils';
|
||||||
|
import { useDataBlockProps } from './DataBlockProvider';
|
||||||
|
|
||||||
export const DataBlockResourceContext = createContext<IResource>(null);
|
export const DataBlockResourceContext = createContext<IResource>(null);
|
||||||
DataBlockResourceContext.displayName = 'DataBlockResourceContext';
|
DataBlockResourceContext.displayName = 'DataBlockResourceContext';
|
||||||
|
|
||||||
export const DataBlockResourceProvider: FC<{ children?: ReactNode }> = ({ children }) => {
|
export const DataBlockResourceProvider = ({ children }: { children?: ReactNode }) => {
|
||||||
const dataBlockProps = useDataBlockProps();
|
const dataBlockProps = useDataBlockProps();
|
||||||
const cm = useCollectionManager();
|
const cm = useCollectionManager();
|
||||||
const { association, collection, dataSource, sourceId, parentRecord } = dataBlockProps;
|
const { association, collection, dataSource, sourceId, parentRecord } = dataBlockProps;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import type { CollectionOptions } from '../collection';
|
import { CollectionManager, type CollectionOptions } from '../collection';
|
||||||
import type { DataSourceManager } from './DataSourceManager';
|
import type { DataSourceManager } from './DataSourceManager';
|
||||||
|
|
||||||
import { CollectionManager } from '../collection';
|
|
||||||
|
|
||||||
type LoadCallback = (collections: CollectionOptions[]) => void;
|
type LoadCallback = (collections: CollectionOptions[]) => void;
|
||||||
|
|
||||||
export interface DataSourceOptions {
|
export interface DataSourceOptions {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import type { CollectionOptions, Collection } from '../collection';
|
|
||||||
import type { Application } from '../../application/Application';
|
|
||||||
|
|
||||||
import { type DataSourceOptions, DataSource, LocalDataSource, DataSourceFactory } from './DataSource';
|
|
||||||
import { type CollectionTemplateFactory, CollectionTemplateManager } from '../collection-template';
|
|
||||||
import { type CollectionFieldInterfaceFactory, CollectionFieldInterfaceManager } from '../collection-field-interface';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import type { Application } from '../../application/Application';
|
||||||
|
import type { Collection, CollectionOptions } from '../collection';
|
||||||
|
import { CollectionFieldInterfaceManager, type CollectionFieldInterfaceFactory } from '../collection-field-interface';
|
||||||
|
import { CollectionTemplateManager, type CollectionTemplateFactory } from '../collection-template';
|
||||||
|
import { DataSource, DataSourceFactory, LocalDataSource, type DataSourceOptions } from './DataSource';
|
||||||
|
|
||||||
export const DEFAULT_DATA_SOURCE_KEY = 'main';
|
export const DEFAULT_DATA_SOURCE_KEY = 'main';
|
||||||
export const DEFAULT_DATA_SOURCE_TITLE = '{{t("Main")}}';
|
export const DEFAULT_DATA_SOURCE_TITLE = '{{t("Main")}}';
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { FC, ReactNode, createContext, useContext } from 'react';
|
import React, { createContext, ReactNode, useContext } from 'react';
|
||||||
|
|
||||||
import type { DataSourceManager } from './DataSourceManager';
|
import type { DataSourceManager } from './DataSourceManager';
|
||||||
|
|
||||||
export const DataSourceManagerContext = createContext<DataSourceManager>(null);
|
export const DataSourceManagerContext = createContext<DataSourceManager>(null);
|
||||||
@ -9,7 +10,7 @@ export interface DataSourceManagerProviderProps {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DataSourceManagerProvider: FC<DataSourceManagerProviderProps> = ({ children, dataSourceManager }) => {
|
export const DataSourceManagerProvider = ({ children, dataSourceManager }: DataSourceManagerProviderProps) => {
|
||||||
return <DataSourceManagerContext.Provider value={dataSourceManager}>{children}</DataSourceManagerContext.Provider>;
|
return <DataSourceManagerContext.Provider value={dataSourceManager}>{children}</DataSourceManagerContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import React, { FC, ReactNode, createContext, useContext } from 'react';
|
import React, { createContext, ReactNode, useContext } from 'react';
|
||||||
|
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Result } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { CardItem, useSchemaComponentContext } from '../../schema-component';
|
||||||
|
import { CollectionDeletedPlaceholder } from '../components/CollectionDeletedPlaceholder';
|
||||||
import type { DataSource } from './DataSource';
|
import type { DataSource } from './DataSource';
|
||||||
import { useDataSourceManager } from './DataSourceManagerProvider';
|
import { useDataSourceManager } from './DataSourceManagerProvider';
|
||||||
import { CollectionDeletedPlaceholder } from '../components/CollectionDeletedPlaceholder';
|
|
||||||
import { CardItem, useSchemaComponentContext } from '../../schema-component';
|
|
||||||
import { Button, Result } from 'antd';
|
|
||||||
import { LoadingOutlined } from '@ant-design/icons';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export const DataSourceContext = createContext<DataSource>(null);
|
export const DataSourceContext = createContext<DataSource>(null);
|
||||||
DataSourceContext.displayName = 'DataSourceContext';
|
DataSourceContext.displayName = 'DataSourceContext';
|
||||||
@ -15,7 +17,7 @@ export interface DataSourceProviderProps {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DataSourceProvider: FC<DataSourceProviderProps> = ({ children, dataSource }) => {
|
export const DataSourceProvider = ({ children, dataSource }: DataSourceProviderProps) => {
|
||||||
const dataSourceManager = useDataSourceManager();
|
const dataSourceManager = useDataSourceManager();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { refresh } = useSchemaComponentContext();
|
const { refresh } = useSchemaComponentContext();
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
// import { CascaderProps } from 'antd';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { CollectionFieldOptions } from './collection';
|
|
||||||
import { DEFAULT_DATA_SOURCE_KEY, DataSourceManager } from './data-source/DataSourceManager';
|
|
||||||
|
|
||||||
// 等把老的去掉后,再把这个函数的实现从那边移动过来
|
import _ from 'lodash';
|
||||||
// export function getCollectionFieldsOptions(){}
|
|
||||||
|
import { CollectionFieldOptions } from './collection';
|
||||||
|
import { DataSourceManager, DEFAULT_DATA_SOURCE_KEY } from './data-source/DataSourceManager';
|
||||||
|
|
||||||
export const isTitleField = (dm: DataSourceManager, field: CollectionFieldOptions) => {
|
export const isTitleField = (dm: DataSourceManager, field: CollectionFieldOptions) => {
|
||||||
return !field.isForeignKey && dm.collectionFieldInterfaceManager.getFieldInterface(field.interface)?.titleUsable;
|
return !field.isForeignKey && dm.collectionFieldInterfaceManager.getFieldInterface(field.interface)?.titleUsable;
|
||||||
@ -15,7 +13,6 @@ export const useDataSourceHeaders = (dataSource?: string): any => {
|
|||||||
const headers = useMemo(() => {
|
const headers = useMemo(() => {
|
||||||
if (dataSource && dataSource !== DEFAULT_DATA_SOURCE_KEY) {
|
if (dataSource && dataSource !== DEFAULT_DATA_SOURCE_KEY) {
|
||||||
return { 'x-data-source': dataSource };
|
return { 'x-data-source': dataSource };
|
||||||
// return { 'x-connection': dataSource };
|
|
||||||
}
|
}
|
||||||
}, [dataSource]);
|
}, [dataSource]);
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { useCollectionManager, useDataBlockProps } from '../../data-source';
|
import { useCollectionManager, useDataBlockProps } from '../../data-source';
|
||||||
import { useCollection } from '../../data-source/collection/CollectionProvider';
|
import { useCollection } from '../../data-source/collection/CollectionProvider';
|
||||||
import { useCompile } from '../../schema-component';
|
import { useCompile } from '../../schema-component';
|
||||||
|
@ -3,7 +3,7 @@ import { expect, test } from '@tachybase/test/e2e';
|
|||||||
import { T3529 } from './templatesOfBug';
|
import { T3529 } from './templatesOfBug';
|
||||||
|
|
||||||
test.describe('association form block', () => {
|
test.describe('association form block', () => {
|
||||||
// https://tachybase.height.app/T-3529
|
//
|
||||||
test('should be created instead of updated', async ({ page, mockPage, mockRecord }) => {
|
test('should be created instead of updated', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T3529).waitForInit();
|
const nocoPage = await mockPage(T3529).waitForInit();
|
||||||
await mockRecord('general');
|
await mockRecord('general');
|
||||||
|
@ -50,7 +50,7 @@ test.describe('display association fields', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2615
|
//
|
||||||
test('should load association data', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2615).waitForInit();
|
const nocoPage = await mockPage(T2615).waitForInit();
|
||||||
await mockRecord('T2615');
|
await mockRecord('T2615');
|
||||||
@ -88,7 +88,7 @@ test.describe('display association fields', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2845
|
//
|
||||||
test('should load association data of subform', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data of subform', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2845).waitForInit();
|
const nocoPage = await mockPage(T2845).waitForInit();
|
||||||
// 和 T2615 使用一样的数据表结构
|
// 和 T2615 使用一样的数据表结构
|
||||||
@ -137,7 +137,7 @@ test.describe('display association fields', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2614
|
//
|
||||||
test('should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2614).waitForInit();
|
const nocoPage = await mockPage(T2614).waitForInit();
|
||||||
await mockRecord('T2614');
|
await mockRecord('T2614');
|
||||||
@ -165,7 +165,7 @@ test.describe('display association fields', () => {
|
|||||||
).toHaveText(`ID:1`);
|
).toHaveText(`ID:1`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2993
|
//
|
||||||
test('should load association data of sub details', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data of sub details', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2993).waitForInit();
|
const nocoPage = await mockPage(T2993).waitForInit();
|
||||||
const record = await mockRecord('T2993');
|
const record = await mockRecord('T2993');
|
||||||
@ -265,7 +265,7 @@ test.describe('association fields', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2200
|
// fix
|
||||||
test('should be possible to change the value of the association field normally', async ({ page, mockPage }) => {
|
test('should be possible to change the value of the association field normally', async ({ page, mockPage }) => {
|
||||||
await mockPage(T2200).goto();
|
await mockPage(T2200).goto();
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ test.describe('variables with default value', () => {
|
|||||||
.getByRole('textbox'),
|
.getByRole('textbox'),
|
||||||
).toHaveValue('1');
|
).toHaveValue('1');
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2805 ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
await page
|
await page
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.m2oField0-m2oField0')
|
.getByLabel('block-item-CollectionField-general-form-general.m2oField0-m2oField0')
|
||||||
.getByTestId('select-object-single')
|
.getByTestId('select-object-single')
|
||||||
|
@ -81,7 +81,7 @@ test.describe('configure actions', () => {
|
|||||||
await expect(page.getByRole('button', { name: 'Submit' })).not.toBeVisible();
|
await expect(page.getByRole('button', { name: 'Submit' })).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3106
|
//
|
||||||
test('subTable: should clear form value after submit', async ({ page, mockPage }) => {
|
test('subTable: should clear form value after submit', async ({ page, mockPage }) => {
|
||||||
await mockPage(T3106).goto();
|
await mockPage(T3106).goto();
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ test.describe('configure actions', () => {
|
|||||||
).toHaveValue('test name');
|
).toHaveValue('test name');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3469
|
//
|
||||||
test('default values for fields should not be cleared after submission', async ({ page, mockPage }) => {
|
test('default values for fields should not be cleared after submission', async ({ page, mockPage }) => {
|
||||||
await mockPage(T3469).goto();
|
await mockPage(T3469).goto();
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ test.describe('creation form block schema settings', () => {
|
|||||||
).toHaveValue('123');
|
).toHaveValue('123');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2165
|
//
|
||||||
test('variable labels should be displayed normally', async ({ page, mockPage }) => {
|
test('variable labels should be displayed normally', async ({ page, mockPage }) => {
|
||||||
await mockPage(T2165).goto();
|
await mockPage(T2165).goto();
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ test.describe('creation form block schema settings', () => {
|
|||||||
await expect(page.getByText('Current form / Phone')).toBeVisible();
|
await expect(page.getByText('Current form / Phone')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3251
|
//
|
||||||
test('nested conditions', async ({ page, mockPage }) => {
|
test('nested conditions', async ({ page, mockPage }) => {
|
||||||
await mockPage(T3251).goto();
|
await mockPage(T3251).goto();
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ test.describe('creation form block schema settings', () => {
|
|||||||
).toBeEditable();
|
).toBeEditable();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3806
|
//
|
||||||
test('after save as block template', async ({ page, mockPage }) => {
|
test('after save as block template', async ({ page, mockPage }) => {
|
||||||
await mockPage(T3806).goto();
|
await mockPage(T3806).goto();
|
||||||
|
|
||||||
@ -732,7 +732,7 @@ test.describe('creation form block schema settings', () => {
|
|||||||
).toHaveValue('new value');
|
).toHaveValue('new value');
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2174
|
// fix
|
||||||
test('should show default value option', async ({ page, mockPage, mockRecord }) => {
|
test('should show default value option', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2174).waitForInit();
|
const nocoPage = await mockPage(T2174).waitForInit();
|
||||||
await mockRecord('test2174');
|
await mockRecord('test2174');
|
||||||
|
@ -5696,7 +5696,7 @@ export const T3469: PageConfig = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3529
|
//
|
||||||
export const T3529: PageConfig = {
|
export const T3529: PageConfig = {
|
||||||
collections: generalWithMultiLevelM2mFields,
|
collections: generalWithMultiLevelM2mFields,
|
||||||
pageSchema: {
|
pageSchema: {
|
||||||
|
@ -2,7 +2,7 @@ import { expect, test } from '@tachybase/test/e2e';
|
|||||||
|
|
||||||
import { T2187 } from '../templatesOfBug';
|
import { T2187 } from '../templatesOfBug';
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2187
|
// fix
|
||||||
test('in the Duplicate mode, the Roles field should not have a value after clicking it because it is not selected', async ({
|
test('in the Duplicate mode, the Roles field should not have a value after clicking it because it is not selected', async ({
|
||||||
page,
|
page,
|
||||||
mockPage,
|
mockPage,
|
||||||
|
@ -2,7 +2,7 @@ import { expect, test } from '@tachybase/test/e2e';
|
|||||||
|
|
||||||
import { T2183, T2186 } from '../templatesOfBug';
|
import { T2183, T2186 } from '../templatesOfBug';
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2183
|
// fix
|
||||||
test('should save conditions', async ({ page, mockPage }) => {
|
test('should save conditions', async ({ page, mockPage }) => {
|
||||||
await mockPage(T2183).goto();
|
await mockPage(T2183).goto();
|
||||||
await page.getByLabel('action-Filter.Action-Filter-filter-users-table').click();
|
await page.getByLabel('action-Filter.Action-Filter-filter-users-table').click();
|
||||||
@ -19,7 +19,7 @@ test('should save conditions', async ({ page, mockPage }) => {
|
|||||||
await expect(page.getByTestId('select-filter-operator').getByText('is')).toBeVisible();
|
await expect(page.getByTestId('select-filter-operator').getByText('is')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2186
|
// fix
|
||||||
test('the input box displayed should correspond to the field type', async ({ page, mockPage }) => {
|
test('the input box displayed should correspond to the field type', async ({ page, mockPage }) => {
|
||||||
await mockPage(T2186).goto();
|
await mockPage(T2186).goto();
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { expect, test } from '@tachybase/test/e2e';
|
|||||||
import { T2797, T2838 } from './templatesOfBug';
|
import { T2797, T2838 } from './templatesOfBug';
|
||||||
|
|
||||||
test.describe('z-index of dialog', () => {
|
test.describe('z-index of dialog', () => {
|
||||||
// https://tachybase.height.app/T-2797
|
//
|
||||||
test('edit block title', async ({ page, mockPage }) => {
|
test('edit block title', async ({ page, mockPage }) => {
|
||||||
await mockPage(T2797).goto();
|
await mockPage(T2797).goto();
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ test.describe('z-index of dialog', () => {
|
|||||||
await expect(page.getByLabel('block-item-Input-users-Block')).not.toBeVisible();
|
await expect(page.getByLabel('block-item-Input-users-Block')).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2838
|
//
|
||||||
test('multilevel modal', async ({ page, mockPage, mockRecord }) => {
|
test('multilevel modal', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2838).waitForInit();
|
const nocoPage = await mockPage(T2838).waitForInit();
|
||||||
await mockRecord('general');
|
await mockRecord('general');
|
||||||
|
@ -174,7 +174,7 @@ export const Action: ComposedAction = withDynamicSchemaProps(
|
|||||||
</ActionContextProvider>
|
</ActionContextProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-3235/description
|
// fix /description
|
||||||
if (addChild) {
|
if (addChild) {
|
||||||
return wrapSSR(
|
return wrapSSR(
|
||||||
<RecordProvider record={null} parent={record}>
|
<RecordProvider record={null} parent={record}>
|
||||||
|
@ -31,7 +31,7 @@ describe('Filter', () => {
|
|||||||
expect(inputs[0]).toHaveValue('aa');
|
expect(inputs[0]).toHaveValue('aa');
|
||||||
expect(inputs[1]).toHaveValue('aaa');
|
expect(inputs[1]).toHaveValue('aaa');
|
||||||
|
|
||||||
// 点击下拉框中的选项,Popover 不应该关闭。详见:https://tachybase.height.app/T-1508
|
// 点击下拉框中的选项,Popover 不应该关闭。详见:
|
||||||
await userEvent.click(screen.getByText(/any/i));
|
await userEvent.click(screen.getByText(/any/i));
|
||||||
await userEvent.click(screen.getByText(/all/i));
|
await userEvent.click(screen.getByText(/all/i));
|
||||||
expect(tooltip).toBeInTheDocument();
|
expect(tooltip).toBeInTheDocument();
|
||||||
@ -97,7 +97,7 @@ describe('Filter', () => {
|
|||||||
expect(inputs[0]).toHaveValue('');
|
expect(inputs[0]).toHaveValue('');
|
||||||
expect(inputs[1]).toHaveValue('aaa');
|
expect(inputs[1]).toHaveValue('aaa');
|
||||||
|
|
||||||
// 点击下拉框中的选项,Popover 不应该关闭。详见:https://tachybase.height.app/T-1508
|
// 点击下拉框中的选项,Popover 不应该关闭。详见:
|
||||||
await userEvent.click(screen.getByText(/any/i));
|
await userEvent.click(screen.getByText(/any/i));
|
||||||
await userEvent.click(screen.getByText(/all/i));
|
await userEvent.click(screen.getByText(/all/i));
|
||||||
expect(tooltip).toBeInTheDocument();
|
expect(tooltip).toBeInTheDocument();
|
||||||
|
@ -110,8 +110,8 @@ export function FormDialog(title: any, id: any, renderer?: any, theme?: any): IF
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
// fix https://tachybase.height.app/T-2797
|
// fix
|
||||||
// fix https://tachybase.height.app/T-2838
|
// fix
|
||||||
zIndex={token.zIndexPopupBase + 1000}
|
zIndex={token.zIndexPopupBase + 1000}
|
||||||
{...modal}
|
{...modal}
|
||||||
open={open}
|
open={open}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GeneralSchemaDesigner } from '../../../schema-settings';
|
import { GeneralSchemaDesigner } from '../../../schema-settings';
|
||||||
|
|
||||||
export const FilterFormDesigner = () => {
|
export const FilterFormDesigner = () => {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useField, useFieldSchema } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { SchemaSettings } from '../../../application/schema-settings';
|
import { SchemaSettings } from '../../../application/schema-settings';
|
||||||
import { useFormBlockContext } from '../../../block-provider';
|
import { useFormBlockContext } from '../../../block-provider';
|
||||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
|
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
|
||||||
import { useRecord } from '../../../record-provider';
|
import { useRecord } from '../../../record-provider';
|
||||||
import { VariableInput, getShouldChange } from '../../../schema-settings';
|
import { getShouldChange, VariableInput } from '../../../schema-settings';
|
||||||
|
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
|
||||||
import { useLocalVariables, useVariables } from '../../../variables';
|
import { useLocalVariables, useVariables } from '../../../variables';
|
||||||
import { useDesignable } from '../../hooks';
|
import { useDesignable } from '../../hooks';
|
||||||
import { removeNullCondition } from '../filter';
|
import { removeNullCondition } from '../filter';
|
||||||
@ -21,7 +24,6 @@ import {
|
|||||||
EditTooltip,
|
EditTooltip,
|
||||||
EditValidationRules,
|
EditValidationRules,
|
||||||
} from './SchemaSettingOptions';
|
} from './SchemaSettingOptions';
|
||||||
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { ArrayCollapse, FormLayout } from '@tachybase/components';
|
|
||||||
import { Field } from '@tachybase/schema';
|
|
||||||
import { ISchema, useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { ArrayCollapse, FormLayout } from '@tachybase/components';
|
||||||
|
import { Field, ISchema, useField, useFieldSchema } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { SchemaSettings } from '../../../application/schema-settings';
|
import { SchemaSettings } from '../../../application/schema-settings';
|
||||||
import { useFormBlockContext } from '../../../block-provider/FormBlockProvider';
|
import { useFormBlockContext } from '../../../block-provider/FormBlockProvider';
|
||||||
import {
|
import {
|
||||||
@ -13,16 +14,17 @@ import {
|
|||||||
useCollectionManager_deprecated,
|
useCollectionManager_deprecated,
|
||||||
} from '../../../collection-manager';
|
} from '../../../collection-manager';
|
||||||
import { useRecord } from '../../../record-provider';
|
import { useRecord } from '../../../record-provider';
|
||||||
|
import { useColumnSchema } from '../../../schema-component/antd/table-v2/Table.Column.Decorator';
|
||||||
import { generalSettingsItems } from '../../../schema-items/GeneralSettings';
|
import { generalSettingsItems } from '../../../schema-items/GeneralSettings';
|
||||||
import { isPatternDisabled } from '../../../schema-settings/isPatternDisabled';
|
|
||||||
import { SchemaSettingsSortingRule } from '../../../schema-settings/SchemaSettingsSortingRule';
|
|
||||||
import { SchemaSettingsDateFormat } from '../../../schema-settings/SchemaSettingsDateFormat';
|
|
||||||
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
|
|
||||||
import { SchemaSettingsDefaultValue } from '../../../schema-settings/SchemaSettingsDefaultValue';
|
|
||||||
import { ActionType } from '../../../schema-settings/LinkageRules/type';
|
|
||||||
import { VariableInput, getShouldChange } from '../../../schema-settings/VariableInput/VariableInput';
|
|
||||||
import { useIsAllowToSetDefaultValue } from '../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
|
import { useIsAllowToSetDefaultValue } from '../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
|
||||||
import { useIsShowMultipleSwitch } from '../../../schema-settings/hooks/useIsShowMultipleSwitch';
|
import { useIsShowMultipleSwitch } from '../../../schema-settings/hooks/useIsShowMultipleSwitch';
|
||||||
|
import { isPatternDisabled } from '../../../schema-settings/isPatternDisabled';
|
||||||
|
import { ActionType } from '../../../schema-settings/LinkageRules/type';
|
||||||
|
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
|
||||||
|
import { SchemaSettingsDateFormat } from '../../../schema-settings/SchemaSettingsDateFormat';
|
||||||
|
import { SchemaSettingsDefaultValue } from '../../../schema-settings/SchemaSettingsDefaultValue';
|
||||||
|
import { SchemaSettingsSortingRule } from '../../../schema-settings/SchemaSettingsSortingRule';
|
||||||
|
import { getShouldChange, VariableInput } from '../../../schema-settings/VariableInput/VariableInput';
|
||||||
import { useLocalVariables, useVariables } from '../../../variables';
|
import { useLocalVariables, useVariables } from '../../../variables';
|
||||||
import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
|
import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
|
||||||
import { isSubMode } from '../association-field/util';
|
import { isSubMode } from '../association-field/util';
|
||||||
@ -30,7 +32,6 @@ import { removeNullCondition } from '../filter';
|
|||||||
import { DynamicComponentProps } from '../filter/DynamicComponent';
|
import { DynamicComponentProps } from '../filter/DynamicComponent';
|
||||||
import { getTempFieldState } from '../form-v2/utils';
|
import { getTempFieldState } from '../form-v2/utils';
|
||||||
import { useColorFields } from '../table-v2/Table.Column.Designer';
|
import { useColorFields } from '../table-v2/Table.Column.Designer';
|
||||||
import { useColumnSchema } from '../../../schema-component/antd/table-v2/Table.Column.Decorator';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
@ -486,7 +487,6 @@ export const formItemSettings = new SchemaSettings({
|
|||||||
'x-action': 'create',
|
'x-action': 'create',
|
||||||
'x-acl-action': 'create',
|
'x-acl-action': 'create',
|
||||||
title: "{{t('Add new')}}",
|
title: "{{t('Add new')}}",
|
||||||
// 'x-designer': 'Action.Designer',
|
|
||||||
'x-toolbar': 'ActionSchemaToolbar',
|
'x-toolbar': 'ActionSchemaToolbar',
|
||||||
'x-settings': 'actonSettings:addNew',
|
'x-settings': 'actonSettings:addNew',
|
||||||
'x-component': 'Action',
|
'x-component': 'Action',
|
||||||
@ -549,7 +549,6 @@ export const formItemSettings = new SchemaSettings({
|
|||||||
'x-action': 'create',
|
'x-action': 'create',
|
||||||
'x-acl-action': 'create',
|
'x-acl-action': 'create',
|
||||||
title: "{{t('Add new')}}",
|
title: "{{t('Add new')}}",
|
||||||
// 'x-designer': 'Action.Designer',
|
|
||||||
'x-toolbar': 'ActionSchemaToolbar',
|
'x-toolbar': 'ActionSchemaToolbar',
|
||||||
'x-settings': 'actonSettings:addNew',
|
'x-settings': 'actonSettings:addNew',
|
||||||
'x-component': 'Action',
|
'x-component': 'Action',
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ArrayCollapse, FormLayout } from '@tachybase/components';
|
|
||||||
import { Field } from '@tachybase/schema';
|
|
||||||
import { ISchema, Schema, useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
import { uid } from '@tachybase/schema';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { ArrayCollapse, FormLayout } from '@tachybase/components';
|
||||||
|
import { Field, ISchema, Schema, useField, useFieldSchema } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { useFormBlockContext } from '../../../block-provider';
|
import { useFormBlockContext } from '../../../block-provider';
|
||||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
|
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
|
||||||
import { SchemaSettingsModalItem, SchemaSettingsSelectItem, SchemaSettingsSwitchItem } from '../../../schema-settings';
|
import { SchemaSettingsModalItem, SchemaSettingsSelectItem, SchemaSettingsSwitchItem } from '../../../schema-settings';
|
||||||
@ -12,6 +12,7 @@ import { isPatternDisabled } from '../../../schema-settings/isPatternDisabled';
|
|||||||
import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
|
import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
|
||||||
import { useOperatorList } from '../filter/useOperators';
|
import { useOperatorList } from '../filter/useOperators';
|
||||||
import { isFileCollection } from './FormItem';
|
import { isFileCollection } from './FormItem';
|
||||||
|
|
||||||
export const findFilterOperators = (schema: Schema) => {
|
export const findFilterOperators = (schema: Schema) => {
|
||||||
while (schema) {
|
while (schema) {
|
||||||
if (schema['x-filter-operators']) {
|
if (schema['x-filter-operators']) {
|
||||||
@ -25,16 +26,6 @@ export const findFilterOperators = (schema: Schema) => {
|
|||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const divWrap = (schema: ISchema) => {
|
|
||||||
return {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'div',
|
|
||||||
properties: {
|
|
||||||
[schema.name || uid()]: schema,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EditTitle = () => {
|
export const EditTitle = () => {
|
||||||
const { getCollectionJoinField } = useCollectionManager_deprecated();
|
const { getCollectionJoinField } = useCollectionManager_deprecated();
|
||||||
const { getField } = useCollection_deprecated();
|
const { getField } = useCollection_deprecated();
|
||||||
@ -297,10 +288,6 @@ export const EditValidationRules = () => {
|
|||||||
const schema = {
|
const schema = {
|
||||||
['x-uid']: fieldSchema['x-uid'],
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
};
|
};
|
||||||
// return;
|
|
||||||
// if (['number'].includes(collectionField?.interface) && collectionField?.uiSchema?.['x-component-props']?.['stringMode'] === true) {
|
|
||||||
// rules['numberStringMode'] = true;
|
|
||||||
// }
|
|
||||||
if (['percent'].includes(collectionField?.interface)) {
|
if (['percent'].includes(collectionField?.interface)) {
|
||||||
for (const rule of rules) {
|
for (const rule of rules) {
|
||||||
if (!!rule.maxValue || !!rule.minValue) {
|
if (!!rule.maxValue || !!rule.minValue) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { render, screen, waitFor } from '@tachybase/test/client';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { render, screen, waitFor } from '@tachybase/test/client';
|
||||||
|
|
||||||
import App1 from '../demos/demo1';
|
import App1 from '../demos/demo1';
|
||||||
|
|
||||||
describe('FormItem', () => {
|
describe('FormItem', () => {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
APIClientProvider,
|
APIClientProvider,
|
||||||
CurrentUserProvider,
|
CurrentUserProvider,
|
||||||
@ -6,7 +7,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
} from '@tachybase/client';
|
} from '@tachybase/client';
|
||||||
import React from 'react';
|
|
||||||
import { mockAPIClient } from '../../../../testUtils';
|
import { mockAPIClient } from '../../../../testUtils';
|
||||||
|
|
||||||
const { apiClient, mockRequest } = mockAPIClient();
|
const { apiClient, mockRequest } = mockAPIClient();
|
||||||
|
@ -87,7 +87,6 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
|
|||||||
.then((value) => {
|
.then((value) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const result = transformVariableValue(value, { targetCollectionField: collectionFieldRef.current });
|
const result = transformVariableValue(value, { targetCollectionField: collectionFieldRef.current });
|
||||||
// fix https://tachybase.height.app/T-2608
|
|
||||||
if (_.isEmpty(result) && !_.isNumber(result)) {
|
if (_.isEmpty(result) && !_.isNumber(result)) {
|
||||||
field.value = null;
|
field.value = null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +82,7 @@ const useParseDefaultValue = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (value == null || value === '') {
|
if (value == null || value === '') {
|
||||||
// fix https://tachybase.height.app/T-2805
|
// fix
|
||||||
field.setInitialValue(null);
|
field.setInitialValue(null);
|
||||||
await field.reset({ forceClear: true });
|
await field.reset({ forceClear: true });
|
||||||
} else if (isSpecialCase()) {
|
} else if (isSpecialCase()) {
|
||||||
@ -122,7 +122,6 @@ const useParseDefaultValue = () => {
|
|||||||
const obj = { [variableName]: variable?.ctx || {} };
|
const obj = { [variableName]: variable?.ctx || {} };
|
||||||
const path = getPath(fieldSchema.default);
|
const path = getPath(fieldSchema.default);
|
||||||
const value = getValuesByPath(obj, path);
|
const value = getValuesByPath(obj, path);
|
||||||
// fix https://tachybase.height.app/T-2212
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
// 返回一个随机值,确保能触发 run 函数
|
// 返回一个随机值,确保能触发 run 函数
|
||||||
return Math.random();
|
return Math.random();
|
||||||
|
@ -47,7 +47,6 @@ export const useSpecialCase = () => {
|
|||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* 特殊情况指的是:当前字段是 `对一` 字段且存在于 `对多` 字段的 `子表格` 或 `子表单` 中
|
* 特殊情况指的是:当前字段是 `对一` 字段且存在于 `对多` 字段的 `子表格` 或 `子表单` 中
|
||||||
* 详细说明见:https://tachybase.feishu.cn/docx/EmNEdEBOnoQohUx2UmBcqIQ5nyh#CUdLdy6OpoPKjyx9DLPc3lqknVc
|
|
||||||
*/
|
*/
|
||||||
isSpecialCase,
|
isSpecialCase,
|
||||||
setDefaultValue,
|
setDefaultValue,
|
||||||
@ -72,7 +71,6 @@ export function getParentFieldSchema(fieldSchema: Schema) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 特殊情况指的是:当前字段是 `对一` 字段且存在于 `对多` 字段的 `子表格` 或 `子表单` 中
|
* 特殊情况指的是:当前字段是 `对一` 字段且存在于 `对多` 字段的 `子表格` 或 `子表单` 中
|
||||||
* 详细说明见:https://tachybase.feishu.cn/docx/EmNEdEBOnoQohUx2UmBcqIQ5nyh#CUdLdy6OpoPKjyx9DLPc3lqknVc
|
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function isSpecialCaseField({
|
export function isSpecialCaseField({
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Schema Components
|
|
||||||
order: 3
|
|
||||||
---
|
|
||||||
|
|
||||||
# FormItem
|
|
||||||
|
|
||||||
表单字段装饰器。除此之外,也继承了 BlockItem 的功能。
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"></code>
|
|
@ -332,7 +332,7 @@ function getFieldValuesInCondition({ linkageRules, formValues }) {
|
|||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
.map((condition) => {
|
.map((condition) => {
|
||||||
// fix https://tachybase.height.app/T-3251
|
// fix
|
||||||
if ('$and' in condition || '$or' in condition) {
|
if ('$and' in condition || '$or' in condition) {
|
||||||
return run(condition);
|
return run(condition);
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,6 @@ const SideMenu = ({
|
|||||||
const { Component, getMenuItems } = useMenuItem();
|
const { Component, getMenuItems } = useMenuItem();
|
||||||
const { styles } = useStyles();
|
const { styles } = useStyles();
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-3331/description
|
|
||||||
// 使用 ref 用来防止闭包问题
|
|
||||||
const sideMenuSchemaRef = useRef(sideMenuSchema);
|
const sideMenuSchemaRef = useRef(sideMenuSchema);
|
||||||
sideMenuSchemaRef.current = sideMenuSchema;
|
sideMenuSchemaRef.current = sideMenuSchema;
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import { Popover as AntdPopover, PopoverProps } from 'antd';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 参见:https://github.com/ant-design/ant-design/issues/44119
|
* 参见:https://github.com/ant-design/ant-design/issues/44119
|
||||||
* fix https://tachybase.height.app/T-1508
|
|
||||||
* @param props
|
* @param props
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
|
@ -119,7 +119,6 @@ const useTableColumns = () => {
|
|||||||
const index = field.value?.indexOf(record);
|
const index = field.value?.indexOf(record);
|
||||||
return (
|
return (
|
||||||
<RecordIndexProvider index={index}>
|
<RecordIndexProvider index={index}>
|
||||||
{/* fix https://tachybase.height.app/T-3232/description */}
|
|
||||||
{/* 如果作为关系表格区块,则 parentRecordData 应该有值;如果作为普通表格使用(如数据源管理页面的表格)则应该使用 recordData,且 parentRecordData 为空 */}
|
{/* 如果作为关系表格区块,则 parentRecordData 应该有值;如果作为普通表格使用(如数据源管理页面的表格)则应该使用 recordData,且 parentRecordData 为空 */}
|
||||||
<RecordProvider record={record} parent={parentRecordData || recordData}>
|
<RecordProvider record={record} parent={parentRecordData || recordData}>
|
||||||
<RecursionField schema={s} name={record.__index || index} onlyRenderProperties />
|
<RecursionField schema={s} name={record.__index || index} onlyRenderProperties />
|
||||||
|
@ -79,7 +79,7 @@ export const conditionAnalyses = async ({
|
|||||||
const conditions = ruleGroup[type];
|
const conditions = ruleGroup[type];
|
||||||
|
|
||||||
let results = conditions.map(async (condition) => {
|
let results = conditions.map(async (condition) => {
|
||||||
// fix https://tachybase.height.app/T-3152
|
// fix
|
||||||
if ('$and' in condition || '$or' in condition) {
|
if ('$and' in condition || '$or' in condition) {
|
||||||
return await conditionAnalyses({ ruleGroup: condition, variables, localVariables });
|
return await conditionAnalyses({ ruleGroup: condition, variables, localVariables });
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
import { ISchemaComponentContext } from './types';
|
import { ISchemaComponentContext } from './types';
|
||||||
|
|
||||||
export const SchemaComponentContext = createContext<ISchemaComponentContext>({});
|
export const SchemaComponentContext = createContext<ISchemaComponentContext>({});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { PropsWithChildren, useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { createForm, Schema } from '@tachybase/schema';
|
import { createForm, Schema } from '@tachybase/schema';
|
||||||
|
|
||||||
import { useRequest } from '../../api-client';
|
import { useRequest } from '../../api-client';
|
||||||
@ -16,11 +16,12 @@ export interface RemoteSchemaComponentProps {
|
|||||||
hidden?: any;
|
hidden?: any;
|
||||||
onlyRenderProperties?: boolean;
|
onlyRenderProperties?: boolean;
|
||||||
noForm?: boolean;
|
noForm?: boolean;
|
||||||
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultTransform = (s: Schema) => s;
|
const defaultTransform = (s: Schema) => s;
|
||||||
|
|
||||||
const RequestSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) => {
|
const RequestSchemaComponent = (props: RemoteSchemaComponentProps) => {
|
||||||
const {
|
const {
|
||||||
noForm,
|
noForm,
|
||||||
onlyRenderProperties,
|
onlyRenderProperties,
|
||||||
@ -45,18 +46,18 @@ const RequestSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) =>
|
|||||||
reset && reset();
|
reset && reset();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (loading || hidden) {
|
if (loading || hidden || !data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return noForm ? (
|
return noForm ? (
|
||||||
<SchemaComponent memoized components={components} scope={scope} schema={schemaTransform(data?.data || {})} />
|
<SchemaComponent components={components} scope={scope} schema={schemaTransform(data?.data || {})} />
|
||||||
) : (
|
) : (
|
||||||
<FormProvider form={form}>
|
<FormProvider form={form}>
|
||||||
<SchemaComponent memoized components={components} scope={scope} schema={schemaTransform(data?.data || {})} />
|
<SchemaComponent components={components} scope={scope} schema={schemaTransform(data?.data || {})} />
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RemoteSchemaComponent: React.FC<PropsWithChildren<RemoteSchemaComponentProps>> = (props) => {
|
export const RemoteSchemaComponent = (props: RemoteSchemaComponentProps) => {
|
||||||
return props.uid ? <RequestSchemaComponent {...props} /> : null;
|
return props.uid ? <RequestSchemaComponent {...props} /> : null;
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { memo, PropsWithChildren, useContext, useMemo } from 'react';
|
import React, { memo, useContext, useMemo } from 'react';
|
||||||
import { ExpressionScope, SchemaComponentsContext, SchemaOptionsContext } from '@tachybase/schema';
|
import { ExpressionScope, SchemaComponentsContext, SchemaOptionsContext } from '@tachybase/schema';
|
||||||
|
|
||||||
import { ISchemaComponentOptionsProps } from '../types';
|
import { ISchemaComponentOptionsProps } from '../types';
|
||||||
@ -8,7 +8,7 @@ export const useSchemaOptionsContext = () => {
|
|||||||
return options || {};
|
return options || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SchemaComponentOptions: React.FC<PropsWithChildren<ISchemaComponentOptionsProps>> = memo((props) => {
|
export const SchemaComponentOptions = memo((props: ISchemaComponentOptionsProps) => {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
const options = useSchemaOptionsContext();
|
const options = useSchemaOptionsContext();
|
||||||
const components = useMemo(() => {
|
const components = useMemo(() => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { PropsWithChildren, useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { createForm, FormProvider, Schema, uid } from '@tachybase/schema';
|
import { createForm, FormProvider, Schema, uid } from '@tachybase/schema';
|
||||||
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -42,10 +42,11 @@ const Registry = {
|
|||||||
|
|
||||||
Schema.registerCompiler(Registry.compile);
|
Schema.registerCompiler(Registry.compile);
|
||||||
|
|
||||||
export const SchemaComponentProvider: React.FC<PropsWithChildren<ISchemaComponentProvider>> = (props) => {
|
export const SchemaComponentProvider = (props: ISchemaComponentProvider) => {
|
||||||
const { designable, onDesignableChange, components, children } = props;
|
const { designable, onDesignableChange, components, children } = props;
|
||||||
const [uidValue, setUid] = useState(uid());
|
const [uidValue, setUid] = useState(uid());
|
||||||
const [formId, setFormId] = useState(uid());
|
const [formId, setFormId] = useState(uid());
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const form = useMemo(() => props.form || createForm(), [formId]);
|
const form = useMemo(() => props.form || createForm(), [formId]);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const scope = useMemo(() => {
|
const scope = useMemo(() => {
|
||||||
@ -69,12 +70,12 @@ export const SchemaComponentProvider: React.FC<PropsWithChildren<ISchemaComponen
|
|||||||
onDesignableChange?.(value);
|
onDesignableChange?.(value);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[uidValue, scope, components, designable, active],
|
[uidValue, scope, components, designable, active],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// TODO: 临时修复,处理模板类型的关联数据第一次进入无法加载
|
<SchemaComponentContext.Provider value={schemaComponentContextValue}>
|
||||||
<SchemaComponentContext.Provider value={{ ...schemaComponentContextValue }}>
|
|
||||||
<FormProvider form={form}>
|
<FormProvider form={form}>
|
||||||
<SchemaComponentOptions inherit scope={scope} components={components}>
|
<SchemaComponentOptions inherit scope={scope} components={components}>
|
||||||
{children}
|
{children}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { SchemaComponentContext } from '../context';
|
import { SchemaComponentContext } from '../context';
|
||||||
|
|
||||||
export function useSchemaComponentContext() {
|
export function useSchemaComponentContext() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Form } from '@tachybase/schema';
|
|
||||||
import { IRecursionFieldProps, ISchemaFieldProps, SchemaReactComponents } from '@tachybase/schema';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Form, IRecursionFieldProps, ISchemaFieldProps, SchemaReactComponents } from '@tachybase/schema';
|
||||||
|
|
||||||
export interface ISchemaComponentContext {
|
export interface ISchemaComponentContext {
|
||||||
scope?: any;
|
scope?: any;
|
||||||
@ -9,7 +8,7 @@ export interface ISchemaComponentContext {
|
|||||||
reset?: () => void;
|
reset?: () => void;
|
||||||
designable?: boolean;
|
designable?: boolean;
|
||||||
setDesignable?: (value: boolean) => void;
|
setDesignable?: (value: boolean) => void;
|
||||||
SchemaField?: React.FC<ISchemaFieldProps>;
|
SchemaField?: (props: ISchemaFieldProps) => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISchemaComponentProvider {
|
export interface ISchemaComponentProvider {
|
||||||
@ -18,6 +17,7 @@ export interface ISchemaComponentProvider {
|
|||||||
form?: Form;
|
form?: Form;
|
||||||
scope?: any;
|
scope?: any;
|
||||||
components?: SchemaReactComponents;
|
components?: SchemaReactComponents;
|
||||||
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRecursionComponentProps extends IRecursionFieldProps {
|
export interface IRecursionComponentProps extends IRecursionFieldProps {
|
||||||
@ -29,4 +29,5 @@ export interface ISchemaComponentOptionsProps {
|
|||||||
scope?: any;
|
scope?: any;
|
||||||
components?: SchemaReactComponents;
|
components?: SchemaReactComponents;
|
||||||
inherit?: boolean;
|
inherit?: boolean;
|
||||||
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ export const AssignedField = (props: AssignedFieldProps) => {
|
|||||||
const currentForm = scope.find((item) => item.value === '$nForm');
|
const currentForm = scope.find((item) => item.value === '$nForm');
|
||||||
const fields = getCollectionFields(name);
|
const fields = getCollectionFields(name);
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-1355
|
// fix
|
||||||
// 工作流人工节点的 `自定义表单` 区块,与其它表单区块不同,根据它的数据表名称,获取到的字段列表为空,所以需要在这里特殊处理一下
|
// 工作流人工节点的 `自定义表单` 区块,与其它表单区块不同,根据它的数据表名称,获取到的字段列表为空,所以需要在这里特殊处理一下
|
||||||
if (!fields?.length && currentForm) {
|
if (!fields?.length && currentForm) {
|
||||||
currentForm.children = formatVariableScop(currentFormFields);
|
currentForm.children = formatVariableScop(currentFormFields);
|
||||||
|
@ -890,7 +890,7 @@ export const useCollectionDataSourceItems = ({
|
|||||||
getTemplatesByCollection,
|
getTemplatesByCollection,
|
||||||
t,
|
t,
|
||||||
}).sort((item) => {
|
}).sort((item) => {
|
||||||
// fix https://tachybase.height.app/T-3551
|
// fix
|
||||||
const inherits = _.toArray(collection?.inherits || []);
|
const inherits = _.toArray(collection?.inherits || []);
|
||||||
if (item.name === collection?.name || inherits.some((inheritName) => inheritName === item.name)) return -1;
|
if (item.name === collection?.name || inherits.some((inheritName) => inheritName === item.name)) return -1;
|
||||||
}),
|
}),
|
||||||
@ -898,7 +898,7 @@ export const useCollectionDataSourceItems = ({
|
|||||||
}));
|
}));
|
||||||
}, [allCollections, collection?.inherits, collection?.name, componentName, getTemplatesByCollection, t]);
|
}, [allCollections, collection?.inherits, collection?.name, componentName, getTemplatesByCollection, t]);
|
||||||
|
|
||||||
// https://tachybase.height.app/T-3821
|
//
|
||||||
// showAssociationFields 的值是固定不变的,所以在 if 语句里使用 hooks 是安全的
|
// showAssociationFields 的值是固定不变的,所以在 if 语句里使用 hooks 是安全的
|
||||||
if (showAssociationFields) {
|
if (showAssociationFields) {
|
||||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
@ -81,7 +81,6 @@ export const SchemaSettingsDefaultValue = function DefaultValueConfigure(props:
|
|||||||
const currentForm = scope.find((item) => item.value === '$nForm');
|
const currentForm = scope.find((item) => item.value === '$nForm');
|
||||||
const fields = getCollectionFields(name);
|
const fields = getCollectionFields(name);
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-1355
|
|
||||||
// 工作流人工节点的 `自定义表单` 区块,与其它表单区块不同,根据它的数据表名称,获取到的字段列表为空,所以需要在这里特殊处理一下
|
// 工作流人工节点的 `自定义表单` 区块,与其它表单区块不同,根据它的数据表名称,获取到的字段列表为空,所以需要在这里特殊处理一下
|
||||||
if (!fields?.length && currentForm) {
|
if (!fields?.length && currentForm) {
|
||||||
currentForm.children = formatVariableScop(getFields());
|
currentForm.children = formatVariableScop(getFields());
|
||||||
|
@ -37,7 +37,7 @@ export const useFormVariable = ({ collectionName, collectionField, schema, noDis
|
|||||||
collectionName: collectionName,
|
collectionName: collectionName,
|
||||||
noDisabled,
|
noDisabled,
|
||||||
returnFields: (fields, option) => {
|
returnFields: (fields, option) => {
|
||||||
// fix https://tachybase.height.app/T-2277
|
// fix
|
||||||
return fields;
|
return fields;
|
||||||
// const activeFieldsName = getActiveFieldsName?.('form') || [];
|
// const activeFieldsName = getActiveFieldsName?.('form') || [];
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ export const useCurrentFormVariable = ({
|
|||||||
collectionName: collectionName,
|
collectionName: collectionName,
|
||||||
noDisabled,
|
noDisabled,
|
||||||
returnFields: (fields, option) => {
|
returnFields: (fields, option) => {
|
||||||
// fix https://tachybase.height.app/T-2277
|
// fix
|
||||||
return fields;
|
return fields;
|
||||||
// const activeFieldsName = getActiveFieldsName?.('form') || [];
|
// const activeFieldsName = getActiveFieldsName?.('form') || [];
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ export const useIterationVariable = ({
|
|||||||
collectionName: currentCollection,
|
collectionName: currentCollection,
|
||||||
noDisabled,
|
noDisabled,
|
||||||
returnFields: (fields, option) => {
|
returnFields: (fields, option) => {
|
||||||
// fix https://tachybase.height.app/T-2277
|
// fix
|
||||||
return fields;
|
return fields;
|
||||||
// const activeFieldsName = getActiveFieldsName?.('nester') || [];
|
// const activeFieldsName = getActiveFieldsName?.('nester') || [];
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ export const useCurrentObjectVariable = ({
|
|||||||
collectionName: collectionOfCurrentObject?.name || collection?.name,
|
collectionName: collectionOfCurrentObject?.name || collection?.name,
|
||||||
noDisabled,
|
noDisabled,
|
||||||
returnFields: (fields, option) => {
|
returnFields: (fields, option) => {
|
||||||
// fix https://tachybase.height.app/T-2277
|
// fix
|
||||||
return fields;
|
return fields;
|
||||||
// const activeFieldsName = getActiveFieldsName?.('nester') || [];
|
// const activeFieldsName = getActiveFieldsName?.('nester') || [];
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { observer, useField, useFieldSchema } from '@tachybase/schema';
|
import React, { createContext, useCallback, useContext, useMemo } from 'react';
|
||||||
import React, { createContext, useContext, useMemo } from 'react';
|
import { useField, useFieldSchema } from '@tachybase/schema';
|
||||||
import { RemoteSchemaComponent, useDesignable } from '..';
|
|
||||||
import { useSchemaTemplateManager } from './SchemaTemplateManagerProvider';
|
import { RemoteSchemaComponent, useDesignable, useSchemaComponentContext } from '..';
|
||||||
import { useTemplateBlockContext } from '../block-provider/TemplateBlockProvider';
|
import { useTemplateBlockContext } from '../block-provider/TemplateBlockProvider';
|
||||||
|
import { useSchemaTemplateManager } from './useSchemaTemplateManager';
|
||||||
|
|
||||||
const BlockTemplateContext = createContext<any>({});
|
const BlockTemplateContext = createContext<any>({});
|
||||||
BlockTemplateContext.displayName = 'BlockTemplateContext';
|
BlockTemplateContext.displayName = 'BlockTemplateContext';
|
||||||
@ -11,26 +12,31 @@ export const useBlockTemplateContext = () => {
|
|||||||
return useContext(BlockTemplateContext);
|
return useContext(BlockTemplateContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BlockTemplate = observer(
|
export const BlockTemplate = (props: any) => {
|
||||||
(props: any) => {
|
const { templateId } = props;
|
||||||
const { templateId } = props;
|
const { getTemplateById } = useSchemaTemplateManager();
|
||||||
const { getTemplateById } = useSchemaTemplateManager();
|
const field = useField();
|
||||||
const field = useField();
|
const fieldSchema = useFieldSchema();
|
||||||
const fieldSchema = useFieldSchema();
|
const { dn } = useDesignable();
|
||||||
const { dn } = useDesignable();
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const template = useMemo(() => getTemplateById(templateId), [templateId]);
|
const template = useMemo(() => getTemplateById(templateId), [templateId]);
|
||||||
const { onTemplateSuccess } = useTemplateBlockContext();
|
const { onTemplateSuccess } = useTemplateBlockContext();
|
||||||
|
const { refresh } = useSchemaComponentContext();
|
||||||
|
|
||||||
const onSuccess = (data) => {
|
const onSuccess = useCallback(
|
||||||
|
(data) => {
|
||||||
fieldSchema['x-linkage-rules'] = data?.data?.['x-linkage-rules'] || [];
|
fieldSchema['x-linkage-rules'] = data?.data?.['x-linkage-rules'] || [];
|
||||||
fieldSchema.setProperties(data?.data?.properties);
|
fieldSchema.setProperties(data?.data?.properties);
|
||||||
onTemplateSuccess?.();
|
onTemplateSuccess?.();
|
||||||
};
|
refresh();
|
||||||
return template ? (
|
},
|
||||||
<BlockTemplateContext.Provider value={{ dn, field, fieldSchema, template }}>
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
<RemoteSchemaComponent noForm uid={template?.uid} onSuccess={onSuccess} />
|
[template],
|
||||||
</BlockTemplateContext.Provider>
|
);
|
||||||
) : null;
|
|
||||||
},
|
return template ? (
|
||||||
{ displayName: 'BlockTemplate' },
|
<BlockTemplateContext.Provider value={{ dn, field, fieldSchema, template }}>
|
||||||
);
|
<RemoteSchemaComponent noForm uid={template?.uid} onSuccess={onSuccess} />
|
||||||
|
</BlockTemplateContext.Provider>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
@ -4,14 +4,13 @@ import { PageHeader as AntdPageHeader } from '@ant-design/pro-layout';
|
|||||||
import { Input, Spin } from 'antd';
|
import { Input, Spin } from 'antd';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { useAPIClient, useRequest, useSchemaTemplateManager } from '..';
|
import { useRequest, useSchemaTemplateManager } from '..';
|
||||||
import { RemoteSchemaComponent, SchemaComponentContext } from '../schema-component';
|
import { RemoteSchemaComponent, SchemaComponentContext } from '../schema-component';
|
||||||
|
|
||||||
const EditableTitle = (props) => {
|
const EditableTitle = (props) => {
|
||||||
const [title, setTitle] = useState(props.title);
|
const [title, setTitle] = useState(props.title);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const { refresh } = useSchemaTemplateManager();
|
const { refresh } = useSchemaTemplateManager();
|
||||||
const api = useAPIClient();
|
|
||||||
const { run } = useRequest(
|
const { run } = useRequest(
|
||||||
{
|
{
|
||||||
resource: 'uiSchemaTemplates',
|
resource: 'uiSchemaTemplates',
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { ISchema, useFieldSchema } from '@tachybase/schema';
|
import React, { createContext, useMemo } from 'react';
|
||||||
import { uid } from '@tachybase/schema';
|
import { ISchema, uid, useFieldSchema } from '@tachybase/schema';
|
||||||
import { cloneDeep } from 'lodash';
|
|
||||||
import React, { ReactNode, createContext, useContext, useMemo } from 'react';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { useAPIClient, useRequest } from '../api-client';
|
import { useAPIClient, useRequest } from '../api-client';
|
||||||
import { Plugin } from '../application/Plugin';
|
import { Plugin } from '../application/Plugin';
|
||||||
import { useAppSpin } from '../application/hooks/useAppSpin';
|
|
||||||
import { useCollectionManager_deprecated } from '../collection-manager';
|
|
||||||
import { BlockTemplate } from './BlockTemplate';
|
import { BlockTemplate } from './BlockTemplate';
|
||||||
import { DEFAULT_DATA_SOURCE_KEY } from '../data-source';
|
import { useSchemaTemplateManager } from './useSchemaTemplateManager';
|
||||||
|
|
||||||
export const SchemaTemplateManagerContext = createContext<any>({});
|
export const SchemaTemplateManagerContext = createContext<any>({});
|
||||||
SchemaTemplateManagerContext.displayName = 'SchemaTemplateManagerContext';
|
SchemaTemplateManagerContext.displayName = 'SchemaTemplateManagerContext';
|
||||||
@ -22,7 +18,7 @@ export const SchemaTemplateManagerProvider: React.FC<any> = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const regenerateUid = (s: ISchema) => {
|
export const regenerateUid = (s: ISchema) => {
|
||||||
s['name'] = s['x-uid'] = uid();
|
s['name'] = s['x-uid'] = uid();
|
||||||
Object.keys(s.properties || {}).forEach((key) => {
|
Object.keys(s.properties || {}).forEach((key) => {
|
||||||
regenerateUid(s.properties[key]);
|
regenerateUid(s.properties[key]);
|
||||||
@ -30,106 +26,21 @@ const regenerateUid = (s: ISchema) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useSchemaTemplate = () => {
|
export const useSchemaTemplate = () => {
|
||||||
const { getTemplateBySchema, templates } = useSchemaTemplateManager();
|
const { getTemplateBySchema } = useSchemaTemplateManager();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const schemaId = fieldSchema['x-uid'];
|
const schemaId = fieldSchema['x-uid'];
|
||||||
const templateKey = fieldSchema['x-template-key'];
|
const templateKey = fieldSchema['x-template-key'];
|
||||||
// console.log('templateKey', { schemaId, templateKey })
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
return useMemo(() => getTemplateBySchema(fieldSchema), [schemaId, templateKey]);
|
const result = useMemo(() => getTemplateBySchema(fieldSchema), [schemaId, templateKey]);
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSchemaTemplateManager = () => {
|
const InternalRemoteSchemaTemplateManagerProvider = (props) => {
|
||||||
const { getInheritCollections } = useCollectionManager_deprecated();
|
|
||||||
const { refresh, templates = [] } = useContext(SchemaTemplateManagerContext);
|
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
return {
|
|
||||||
templates,
|
|
||||||
refresh,
|
|
||||||
async getTemplateSchemaByMode(options) {
|
|
||||||
const { mode, template } = options;
|
|
||||||
if (mode === 'copy') {
|
|
||||||
const { data } = await api.request({
|
|
||||||
url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
|
|
||||||
});
|
|
||||||
const s = data?.data || {};
|
|
||||||
regenerateUid(s);
|
|
||||||
return cloneDeep(s);
|
|
||||||
} else if (mode === 'reference') {
|
|
||||||
return {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'BlockTemplate',
|
|
||||||
'x-component-props': {
|
|
||||||
templateId: template.key,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async copyTemplateSchema(template) {
|
|
||||||
const { data } = await api.request({
|
|
||||||
url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
|
|
||||||
});
|
|
||||||
const s = data?.data || {};
|
|
||||||
regenerateUid(s);
|
|
||||||
return cloneDeep(s);
|
|
||||||
},
|
|
||||||
async saveAsTemplate(values) {
|
|
||||||
const { uid: schemaId } = values;
|
|
||||||
const key = uid();
|
|
||||||
await api.resource('uiSchemas').saveAsTemplate({
|
|
||||||
filterByTk: schemaId,
|
|
||||||
values: {
|
|
||||||
key,
|
|
||||||
...values,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await refresh();
|
|
||||||
return { key };
|
|
||||||
},
|
|
||||||
getTemplateBySchema(schema) {
|
|
||||||
if (!schema) return;
|
|
||||||
const templateKey = schema['x-template-key'];
|
|
||||||
if (templateKey) {
|
|
||||||
return templates?.find((template) => template.key === templateKey);
|
|
||||||
}
|
|
||||||
const schemaId = schema['x-uid'];
|
|
||||||
if (schemaId) {
|
|
||||||
return templates?.find((template) => template.uid === schemaId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTemplateBySchemaId(schemaId) {
|
|
||||||
if (!schemaId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return templates?.find((template) => template.uid === schemaId);
|
|
||||||
},
|
|
||||||
getTemplateById(key) {
|
|
||||||
return templates?.find((template) => template.key === key);
|
|
||||||
},
|
|
||||||
getTemplatesByCollection(dataSource: string, collectionName: string) {
|
|
||||||
const parentCollections = getInheritCollections(collectionName, dataSource);
|
|
||||||
const totalCollections = parentCollections.concat([collectionName]);
|
|
||||||
const items = templates?.filter?.(
|
|
||||||
(template) =>
|
|
||||||
(template.dataSourceKey || DEFAULT_DATA_SOURCE_KEY) === dataSource &&
|
|
||||||
totalCollections.includes(template.collectionName),
|
|
||||||
);
|
|
||||||
return items || [];
|
|
||||||
},
|
|
||||||
getTemplatesByComponentName(componentName: string): Array<any> {
|
|
||||||
const items = templates?.filter?.((template) => template.componentName === componentName);
|
|
||||||
return items || [];
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const Internal = (props) => {
|
|
||||||
const api = useAPIClient();
|
|
||||||
const { render } = useAppSpin();
|
|
||||||
const options = {
|
const options = {
|
||||||
resource: 'uiSchemaTemplates',
|
resource: 'uiSchemaTemplates',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
params: {
|
params: {
|
||||||
// appends: ['collection'],
|
|
||||||
paginate: false,
|
paginate: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -137,9 +48,11 @@ const Internal = (props) => {
|
|||||||
const service = useRequest<{
|
const service = useRequest<{
|
||||||
data: any[];
|
data: any[];
|
||||||
}>(options);
|
}>(options);
|
||||||
if (service.loading) {
|
|
||||||
return render();
|
if (service.loading && !service.data) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaTemplateManagerProvider
|
<SchemaTemplateManagerProvider
|
||||||
refresh={async () => {
|
refresh={async () => {
|
||||||
@ -153,19 +66,14 @@ const Internal = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RemoteSchemaTemplateManagerProvider: React.FC<{ children?: ReactNode }> = (props) => {
|
export const RemoteSchemaTemplateManagerProvider = (props: { children?: React.ReactNode }) => {
|
||||||
const location = useLocation();
|
return <InternalRemoteSchemaTemplateManagerProvider>{props.children}</InternalRemoteSchemaTemplateManagerProvider>;
|
||||||
if (location.pathname.startsWith('/admin')) {
|
|
||||||
return <Internal {...props} />;
|
|
||||||
}
|
|
||||||
return <>{props.children}</>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class RemoteSchemaTemplateManagerPlugin extends Plugin {
|
export class RemoteSchemaTemplateManagerPlugin extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
this.addRoutes();
|
|
||||||
this.addComponents();
|
this.addComponents();
|
||||||
this.app.use(RemoteSchemaTemplateManagerProvider);
|
this.app.addProviders([RemoteSchemaTemplateManagerProvider]);
|
||||||
}
|
}
|
||||||
|
|
||||||
addComponents() {
|
addComponents() {
|
||||||
@ -173,11 +81,4 @@ export class RemoteSchemaTemplateManagerPlugin extends Plugin {
|
|||||||
BlockTemplate,
|
BlockTemplate,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addRoutes() {
|
|
||||||
this.app.router.add('admin.plugins.block-templates-key', {
|
|
||||||
path: '/admin/plugins/block-templates/:key',
|
|
||||||
Component: 'BlockTemplateDetails',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from './BlockTemplateDetails';
|
export * from './BlockTemplateDetails';
|
||||||
export * from './BlockTemplatePage';
|
export * from './BlockTemplatePage';
|
||||||
export * from './SchemaTemplateManagerProvider';
|
export * from './SchemaTemplateManagerProvider';
|
||||||
|
export * from './useSchemaTemplateManager';
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useDataSourceManager, useCollectionRecordData } from '../../data-source';
|
|
||||||
|
import { useCollectionRecordData, useDataSourceManager } from '../../data-source';
|
||||||
import { useCompile } from '../../schema-component';
|
import { useCompile } from '../../schema-component';
|
||||||
|
|
||||||
export const CollectionTitle = (props) => {
|
export const CollectionTitle = () => {
|
||||||
const { dataSourceKey = 'main', collectionName } = useCollectionRecordData();
|
const { dataSourceKey = 'main', collectionName } = useCollectionRecordData();
|
||||||
const dataSourceManager = useDataSourceManager();
|
const dataSourceManager = useDataSourceManager();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { ISchema } from '@tachybase/schema';
|
import { ISchema, uid } from '@tachybase/schema';
|
||||||
import { uid } from '@tachybase/schema';
|
|
||||||
import { useBulkDestroyActionProps, useDestroyActionProps, useUpdateActionProps } from '../../block-provider/hooks';
|
import { useBulkDestroyActionProps, useDestroyActionProps, useUpdateActionProps } from '../../block-provider/hooks';
|
||||||
import { useSchemaTemplateManager } from '../SchemaTemplateManagerProvider';
|
|
||||||
import { uiSchemaTemplatesCollection } from '../collections/uiSchemaTemplates';
|
import { uiSchemaTemplatesCollection } from '../collections/uiSchemaTemplates';
|
||||||
|
import { useSchemaTemplateManager } from '../useSchemaTemplateManager';
|
||||||
import { CollectionTitle } from './CollectionTitle';
|
import { CollectionTitle } from './CollectionTitle';
|
||||||
|
|
||||||
const useUpdateSchemaTemplateActionProps = () => {
|
const useUpdateSchemaTemplateActionProps = () => {
|
||||||
@ -50,7 +50,6 @@ export const uiSchemaTemplatesSchema: ISchema = {
|
|||||||
action: 'list',
|
action: 'list',
|
||||||
params: {
|
params: {
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
// appends: ['collection'],
|
|
||||||
sort: ['-createdAt'],
|
sort: ['-createdAt'],
|
||||||
},
|
},
|
||||||
rowKey: 'key',
|
rowKey: 'key',
|
||||||
@ -106,14 +105,6 @@ export const uiSchemaTemplatesSchema: ISchema = {
|
|||||||
split: '|',
|
split: '|',
|
||||||
},
|
},
|
||||||
properties: {
|
properties: {
|
||||||
// view: {
|
|
||||||
// title: '{{ t("View") }}',
|
|
||||||
// 'x-action': 'view',
|
|
||||||
// 'x-component': 'RecordLink',
|
|
||||||
// 'x-component-props': {
|
|
||||||
// to: '/admin/plugins/block-templates/${record.key}',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
edit: {
|
edit: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
title: '{{ t("Edit") }}',
|
title: '{{ t("Edit") }}',
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
import { useCallback, useContext } from 'react';
|
||||||
|
import { uid } from '@tachybase/schema';
|
||||||
|
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
|
import { useAPIClient } from '../api-client';
|
||||||
|
import { useCollectionManager_deprecated } from '../collection-manager';
|
||||||
|
import { DEFAULT_DATA_SOURCE_KEY } from '../data-source';
|
||||||
|
import { regenerateUid, SchemaTemplateManagerContext } from './SchemaTemplateManagerProvider';
|
||||||
|
|
||||||
|
export const useSchemaTemplateManager = () => {
|
||||||
|
const { getInheritCollections } = useCollectionManager_deprecated();
|
||||||
|
const { refresh, templates = [] } = useContext(SchemaTemplateManagerContext);
|
||||||
|
const api = useAPIClient();
|
||||||
|
return {
|
||||||
|
templates,
|
||||||
|
refresh,
|
||||||
|
async getTemplateSchemaByMode(options) {
|
||||||
|
const { mode, template } = options;
|
||||||
|
if (mode === 'copy') {
|
||||||
|
const { data } = await api.request({
|
||||||
|
url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
|
||||||
|
});
|
||||||
|
const s = data?.data || {};
|
||||||
|
regenerateUid(s);
|
||||||
|
return cloneDeep(s);
|
||||||
|
} else if (mode === 'reference') {
|
||||||
|
return {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'BlockTemplate',
|
||||||
|
'x-component-props': {
|
||||||
|
templateId: template.key,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async copyTemplateSchema(template) {
|
||||||
|
const { data } = await api.request({
|
||||||
|
url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
|
||||||
|
});
|
||||||
|
const s = data?.data || {};
|
||||||
|
regenerateUid(s);
|
||||||
|
return cloneDeep(s);
|
||||||
|
},
|
||||||
|
async saveAsTemplate(values) {
|
||||||
|
const { uid: schemaId } = values;
|
||||||
|
const key = uid();
|
||||||
|
await api.resource('uiSchemas').saveAsTemplate({
|
||||||
|
filterByTk: schemaId,
|
||||||
|
values: {
|
||||||
|
key,
|
||||||
|
...values,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await refresh();
|
||||||
|
return { key };
|
||||||
|
},
|
||||||
|
getTemplateBySchema: useCallback(
|
||||||
|
(schema) => {
|
||||||
|
if (!schema) return;
|
||||||
|
const templateKey = schema['x-template-key'];
|
||||||
|
if (templateKey) {
|
||||||
|
return templates?.find((template) => template.key === templateKey);
|
||||||
|
}
|
||||||
|
const schemaId = schema['x-uid'];
|
||||||
|
if (schemaId) {
|
||||||
|
return templates?.find((template) => template.uid === schemaId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[templates],
|
||||||
|
),
|
||||||
|
getTemplateBySchemaId(schemaId) {
|
||||||
|
if (!schemaId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return templates?.find((template) => template.uid === schemaId);
|
||||||
|
},
|
||||||
|
getTemplateById(key) {
|
||||||
|
return templates?.find((template) => template.key === key);
|
||||||
|
},
|
||||||
|
getTemplatesByCollection(dataSource: string, collectionName: string) {
|
||||||
|
const parentCollections = getInheritCollections(collectionName, dataSource);
|
||||||
|
const totalCollections = parentCollections.concat([collectionName]);
|
||||||
|
const items = templates?.filter?.(
|
||||||
|
(template) =>
|
||||||
|
(template.dataSourceKey || DEFAULT_DATA_SOURCE_KEY) === dataSource &&
|
||||||
|
totalCollections.includes(template.collectionName),
|
||||||
|
);
|
||||||
|
return items || [];
|
||||||
|
},
|
||||||
|
getTemplatesByComponentName(componentName: string): Array<any> {
|
||||||
|
const items = templates?.filter?.((template) => template.componentName === componentName);
|
||||||
|
return items || [];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
@ -136,7 +136,7 @@ const VariablesProvider = ({ children }) => {
|
|||||||
clearRequested(url);
|
clearRequested(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-3144,使用 `raw` 方法是为了避免触发 autorun,以修复 T-3144 的错误
|
// 使用 `raw` 方法是为了避免触发 autorun
|
||||||
if (!raw(current)[key]) {
|
if (!raw(current)[key]) {
|
||||||
// 把接口返回的数据保存起来,避免重复请求
|
// 把接口返回的数据保存起来,避免重复请求
|
||||||
raw(current)[key] = data.data.data;
|
raw(current)[key] = data.data.data;
|
||||||
@ -296,7 +296,7 @@ function shouldToRequest(value) {
|
|||||||
|
|
||||||
// value 有可能是一个响应式对象,使用 untracked 可以避免意外触发 autorun
|
// value 有可能是一个响应式对象,使用 untracked 可以避免意外触发 autorun
|
||||||
untracked(() => {
|
untracked(() => {
|
||||||
// fix https://tachybase.height.app/T-2502
|
// fix
|
||||||
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
||||||
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
|
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -195,7 +195,7 @@ describe('array field operator', function () {
|
|||||||
expect(filter3[0].get('name')).toEqual(t2.get('name'));
|
expect(filter3[0].get('name')).toEqual(t2.get('name'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2803
|
// fix
|
||||||
test('$anyOf with string', async () => {
|
test('$anyOf with string', async () => {
|
||||||
const filter3 = await Test.repository.find({
|
const filter3 = await Test.repository.find({
|
||||||
filter: {
|
filter: {
|
||||||
@ -228,7 +228,7 @@ describe('array field operator', function () {
|
|||||||
expect(filter[0].get('name')).toEqual(t1.get('name'));
|
expect(filter[0].get('name')).toEqual(t1.get('name'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// fix https://tachybase.height.app/T-2803
|
// fix
|
||||||
test('$noneOf with string', async () => {
|
test('$noneOf with string', async () => {
|
||||||
const filter = await Test.repository.find({
|
const filter = await Test.repository.find({
|
||||||
filter: {
|
filter: {
|
||||||
|
@ -477,7 +477,7 @@ test.describe('configure fields', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://tachybase.height.app/T-2868
|
//
|
||||||
test('sequence rules: z-index of configure drawer', async ({ page, mockCollections }) => {
|
test('sequence rules: z-index of configure drawer', async ({ page, mockCollections }) => {
|
||||||
const collectionManagerPage = new CollectionManagerPage(page);
|
const collectionManagerPage = new CollectionManagerPage(page);
|
||||||
await collectionManagerPage.goto();
|
await collectionManagerPage.goto();
|
||||||
|
@ -665,7 +665,7 @@ test.describe('table column & table', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.describe('table column & sub-table', () => {
|
test.describe('table column & sub-table', () => {
|
||||||
// https://tachybase.height.app/T-3377
|
//
|
||||||
test('title field', async ({ page, mockPage }) => {
|
test('title field', async ({ page, mockPage }) => {
|
||||||
await mockPage(T3377).goto();
|
await mockPage(T3377).goto();
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ export function RuleConfigForm() {
|
|||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// fix https://tachybase.height.app/T-2868
|
// fix
|
||||||
FormDrawer(
|
FormDrawer(
|
||||||
{
|
{
|
||||||
title: compile(ruleType.title),
|
title: compile(ruleType.title),
|
||||||
|
Loading…
Reference in New Issue
Block a user