refactor: add blocks in a unified way (#3668)
* refactor: rename filterMenuItemChildren to filterCollections * refactor: revert parameters to destructured object * refactor(Details): unify details block between page and popup * refactor(Form): refactor(Details): unify form block between page and popup * refactor: table & list & grid card * refactor: form * refactor: association details * chore: useVisible * refactor: calendar * chore: remove relationshipBlocks * refactor: unify Details schema * fix: avoid error * chore: add translate * chore: add tag to association fields * fix: add block useChildren and children merge * test: fix e2e * test: fix e2e * fix: fix Calendar * fix: fix search * test: add e2e for search * fix: fix T-3554 * fix: fix T-3551 * feat: add no data for details block * chore: fix unit test * chore: fix unit test * chore: change text * chore: optimize text * chore: add translation * style: fix memu item style * refactor: rename * test: fix e2e * test: fix e2e --------- Co-authored-by: dream2023 <1098626505@qq.com>
This commit is contained in:
parent
ba1e44c527
commit
286af35ff8
@ -49,7 +49,10 @@ export const SchemaInitializerChild: FC<SchemaInitializerItemType> = memo((props
|
|||||||
const componentVal = Component || component;
|
const componentVal = Component || component;
|
||||||
const isBuiltType = !componentVal && type && typeComponentMap[type];
|
const isBuiltType = !componentVal && type && typeComponentMap[type];
|
||||||
|
|
||||||
const componentChildren = useChildrenRes || children;
|
const componentChildren = useMemo(() => {
|
||||||
|
const res = [...(useChildrenRes || []), ...(children || [])];
|
||||||
|
return res.length === 0 ? undefined : res;
|
||||||
|
}, [useChildrenRes, children]);
|
||||||
const contextValue = useMemo(() => {
|
const contextValue = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
...others,
|
...others,
|
||||||
|
@ -50,6 +50,9 @@ export const SchemaInitializerMenu: FC<MenuProps> = (props) => {
|
|||||||
.ant-menu-sub {
|
.ant-menu-sub {
|
||||||
max-height: 50vh !important;
|
max-height: 50vh !important;
|
||||||
}
|
}
|
||||||
|
.ant-menu-item {
|
||||||
|
margin-block: 0;
|
||||||
|
}
|
||||||
.ant-menu-root {
|
.ant-menu-root {
|
||||||
margin: 0 -${token.margin}px;
|
margin: 0 -${token.margin}px;
|
||||||
.ant-menu-submenu-title {
|
.ant-menu-submenu-title {
|
||||||
|
@ -41,6 +41,7 @@ export function useGetSchemaInitializerMenuItems(onClick?: (args: any) => void)
|
|||||||
return {
|
return {
|
||||||
key: item.key,
|
key: item.key,
|
||||||
label: element,
|
label: element,
|
||||||
|
associationField: item.associationField,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (item.type === 'itemGroup') {
|
if (item.type === 'itemGroup') {
|
||||||
@ -73,6 +74,7 @@ export function useGetSchemaInitializerMenuItems(onClick?: (args: any) => void)
|
|||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
label,
|
label,
|
||||||
|
associationField: item.associationField,
|
||||||
onClick: (info) => {
|
onClick: (info) => {
|
||||||
if (info.key !== key) return;
|
if (info.key !== key) return;
|
||||||
if (item.onClick) {
|
if (item.onClick) {
|
||||||
|
@ -84,7 +84,10 @@ export const SchemaSettingsChild: FC<SchemaSettingsItemType> = memo((props) => {
|
|||||||
const useChildrenRes = useChildren();
|
const useChildrenRes = useChildren();
|
||||||
const useComponentPropsRes = useComponentProps();
|
const useComponentPropsRes = useComponentProps();
|
||||||
const findComponent = useFindComponent();
|
const findComponent = useFindComponent();
|
||||||
const componentChildren = useChildrenRes || children;
|
const componentChildren = useMemo(() => {
|
||||||
|
const res = [...(useChildrenRes || []), ...(children || [])];
|
||||||
|
return res.length === 0 ? undefined : res;
|
||||||
|
}, [useChildrenRes, children]);
|
||||||
const visibleResult = useVisible();
|
const visibleResult = useVisible();
|
||||||
const ComponentValue = useMemo(() => {
|
const ComponentValue = useMemo(() => {
|
||||||
return !Component && type && typeComponentMap[type] ? typeComponentMap[type] : Component;
|
return !Component && type && typeComponentMap[type] ? typeComponentMap[type] : Component;
|
||||||
|
@ -346,7 +346,7 @@ export const useParamsFromRecord = () => {
|
|||||||
const obj = {
|
const obj = {
|
||||||
filterByTk: filterByTk,
|
filterByTk: filterByTk,
|
||||||
};
|
};
|
||||||
if (record.__collection && !['oho', 'm2o', 'obo'].includes(collectionField?.interface)) {
|
if (record.__collection && collectionField && !['oho', 'm2o', 'obo'].includes(collectionField.interface)) {
|
||||||
obj['targetCollection'] = record.__collection;
|
obj['targetCollection'] = record.__collection;
|
||||||
}
|
}
|
||||||
if (!filterByTk) {
|
if (!filterByTk) {
|
||||||
|
@ -19,11 +19,11 @@ const InternalDetailsBlockProvider = (props) => {
|
|||||||
createForm({
|
createForm({
|
||||||
readPretty,
|
readPretty,
|
||||||
}),
|
}),
|
||||||
[],
|
[readPretty],
|
||||||
);
|
);
|
||||||
const { resource, service } = useBlockRequestContext();
|
const { resource, service } = useBlockRequestContext();
|
||||||
const parentRecord = useCollectionParentRecord();
|
const parentRecord = useCollectionParentRecord();
|
||||||
const currentRecord = service?.data?.data?.[0] || {};
|
const currentRecord = (action === 'list' ? service?.data?.data?.[0] : service?.data?.data) || {};
|
||||||
const detailsBLockValue = useMemo(() => {
|
const detailsBLockValue = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
action,
|
action,
|
||||||
@ -65,6 +65,9 @@ export const DetailsBlockProvider = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const useDetailsBlockContext = () => {
|
export const useDetailsBlockContext = () => {
|
||||||
return useContext(DetailsBlockContext);
|
return useContext(DetailsBlockContext);
|
||||||
};
|
};
|
||||||
@ -73,14 +76,15 @@ export const useDetailsBlockProps = () => {
|
|||||||
const ctx = useDetailsBlockContext();
|
const ctx = useDetailsBlockContext();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ctx.service.loading) {
|
if (!ctx.service.loading) {
|
||||||
|
const data = ctx.action === 'list' ? ctx.service?.data?.data?.[0] : ctx.service?.data?.data;
|
||||||
ctx.form
|
ctx.form
|
||||||
.reset()
|
.reset()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ctx.form.setValues(ctx.service?.data?.data?.[0] || {});
|
ctx.form.setValues(data || {});
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
}, [ctx.form, ctx.service?.data?.data, ctx.service.loading]);
|
}, [ctx.action, ctx.form, ctx.service?.data?.data, ctx.service.loading]);
|
||||||
return {
|
return {
|
||||||
form: ctx.form,
|
form: ctx.form,
|
||||||
};
|
};
|
||||||
|
@ -133,9 +133,5 @@ export const BlockRequestProvider: FC = ({ children }) => {
|
|||||||
|
|
||||||
export const useDataBlockRequest = <T extends {}>(): UseRequestResult<{ data: T }> => {
|
export const useDataBlockRequest = <T extends {}>(): UseRequestResult<{ data: T }> => {
|
||||||
const context = useContext(BlockRequestContext);
|
const context = useContext(BlockRequestContext);
|
||||||
if (!context) {
|
|
||||||
throw new Error('useDataBlockRequest() must be used within a DataBlockRequestProvider');
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
@ -358,6 +358,10 @@
|
|||||||
"Add tab": "Add tab",
|
"Add tab": "Add tab",
|
||||||
"Disable tabs": "Disable tabs",
|
"Disable tabs": "Disable tabs",
|
||||||
"Details": "Details",
|
"Details": "Details",
|
||||||
|
"Edit form": "Edit form",
|
||||||
|
"Create form": "Create form",
|
||||||
|
"Form (Edit)": "Form (Edit)",
|
||||||
|
"Form (Add new)": "Form (Add new)",
|
||||||
"Edit tab": "Edit tab",
|
"Edit tab": "Edit tab",
|
||||||
"Relationship blocks": "Relationship blocks",
|
"Relationship blocks": "Relationship blocks",
|
||||||
"Select record": "Select record",
|
"Select record": "Select record",
|
||||||
|
@ -331,6 +331,10 @@
|
|||||||
"Add tab": "Añadir pestaña",
|
"Add tab": "Añadir pestaña",
|
||||||
"Disable tabs": "Desactivar pestañas",
|
"Disable tabs": "Desactivar pestañas",
|
||||||
"Details": "Detalles",
|
"Details": "Detalles",
|
||||||
|
"Edit form": "Editar formulario",
|
||||||
|
"Create form": "Crear formulario",
|
||||||
|
"Form (Edit)": "Formulario (Editar)",
|
||||||
|
"Form (Add new)": "Formulario (Añadir nuevo)",
|
||||||
"Edit tab": "Editar pestaña",
|
"Edit tab": "Editar pestaña",
|
||||||
"Relationship blocks": "Bloques de relación",
|
"Relationship blocks": "Bloques de relación",
|
||||||
"Select record": "Seleccionar registro",
|
"Select record": "Seleccionar registro",
|
||||||
|
@ -346,6 +346,10 @@
|
|||||||
"Add tab": "Ajouter un onglet",
|
"Add tab": "Ajouter un onglet",
|
||||||
"Disable tabs": "Désactiver les onglets",
|
"Disable tabs": "Désactiver les onglets",
|
||||||
"Details": "Détails",
|
"Details": "Détails",
|
||||||
|
"Edit form": "Modifier le formulaire",
|
||||||
|
"Create form": "Créer un formulaire",
|
||||||
|
"Form (Edit)": "Formulaire (Modifier)",
|
||||||
|
"Form (Add new)": "Formulaire (Ajouter nouveau)",
|
||||||
"Edit tab": "Modifier l'onglet",
|
"Edit tab": "Modifier l'onglet",
|
||||||
"Relationship blocks": "Blocs de relations",
|
"Relationship blocks": "Blocs de relations",
|
||||||
"Select record": "Sélectionner un enregistrement",
|
"Select record": "Sélectionner un enregistrement",
|
||||||
|
@ -293,6 +293,10 @@
|
|||||||
"Add tab": "タブを追加",
|
"Add tab": "タブを追加",
|
||||||
"Disable tabs": "タブを無効にする",
|
"Disable tabs": "タブを無効にする",
|
||||||
"Details": "詳細",
|
"Details": "詳細",
|
||||||
|
"Edit form": "フォームを編集",
|
||||||
|
"Create form": "フォームを作成",
|
||||||
|
"Form (Edit)": "フォーム (編集)",
|
||||||
|
"Form (Add new)": "フォーム (新規追加)",
|
||||||
"Edit tab": "タブを編集",
|
"Edit tab": "タブを編集",
|
||||||
"Relationship blocks": "関連付けされたブロック",
|
"Relationship blocks": "関連付けされたブロック",
|
||||||
"Select record": "レコードを選択",
|
"Select record": "レコードを選択",
|
||||||
|
@ -378,6 +378,10 @@
|
|||||||
"Add tab": "탭 추가",
|
"Add tab": "탭 추가",
|
||||||
"Disable tabs": "탭 비활성화",
|
"Disable tabs": "탭 비활성화",
|
||||||
"Details": "세부 정보",
|
"Details": "세부 정보",
|
||||||
|
"Edit form": "폼 편집",
|
||||||
|
"Create form": "폼 생성",
|
||||||
|
"Form (Edit)": "폼 (편집)",
|
||||||
|
"Form (Add new)": "폼 (새로 추가)",
|
||||||
"Edit tab": "탭 편집",
|
"Edit tab": "탭 편집",
|
||||||
"Relationship blocks": "관계 데이터 블록",
|
"Relationship blocks": "관계 데이터 블록",
|
||||||
"Select record": "레코드 선택",
|
"Select record": "레코드 선택",
|
||||||
|
@ -295,6 +295,10 @@
|
|||||||
"Add tab": "Adicionar guia",
|
"Add tab": "Adicionar guia",
|
||||||
"Disable tabs": "Desativar guias",
|
"Disable tabs": "Desativar guias",
|
||||||
"Details": "Detalhes",
|
"Details": "Detalhes",
|
||||||
|
"Edit form": "Editar formulário",
|
||||||
|
"Create form": "Criar formulário",
|
||||||
|
"Form (Edit)": "Formulário (Editar)",
|
||||||
|
"Form (Add new)": "Formulário (Adicionar novo)",
|
||||||
"Edit tab": "Editar guia",
|
"Edit tab": "Editar guia",
|
||||||
"Relationship blocks": "Blocos de relacionamento",
|
"Relationship blocks": "Blocos de relacionamento",
|
||||||
"Select record": "Selecionar registro",
|
"Select record": "Selecionar registro",
|
||||||
|
@ -233,6 +233,10 @@
|
|||||||
"Add tab": "Добавить вкладку",
|
"Add tab": "Добавить вкладку",
|
||||||
"Disable tabs": "Запретить вкладки",
|
"Disable tabs": "Запретить вкладки",
|
||||||
"Details": "Подробности",
|
"Details": "Подробности",
|
||||||
|
"Edit form": "Изменить форму",
|
||||||
|
"Create form": "Создать форму",
|
||||||
|
"Form (Edit)": "Форма (Изменить)",
|
||||||
|
"Form (Add new)": "Форма (Добавить новый)",
|
||||||
"Edit tab": "Изменить вкладку",
|
"Edit tab": "Изменить вкладку",
|
||||||
"Relationship blocks": "Блоки отношений",
|
"Relationship blocks": "Блоки отношений",
|
||||||
"Select record": "Выбрать запись",
|
"Select record": "Выбрать запись",
|
||||||
|
@ -233,6 +233,10 @@
|
|||||||
"Add tab": "Sekme ekle",
|
"Add tab": "Sekme ekle",
|
||||||
"Disable tabs": "Sekmeleri pasifleştir",
|
"Disable tabs": "Sekmeleri pasifleştir",
|
||||||
"Details": "Detaylar",
|
"Details": "Detaylar",
|
||||||
|
"Edit form": "Formu düzenle",
|
||||||
|
"Create form": "Form oluştur",
|
||||||
|
"Form (Edit)": "Form (Düzenle)",
|
||||||
|
"Form (Add new)": "Form (Yeni ekle)",
|
||||||
"Edit tab": "Sekme düzenle",
|
"Edit tab": "Sekme düzenle",
|
||||||
"Relationship blocks": "İlişki blokları",
|
"Relationship blocks": "İlişki blokları",
|
||||||
"Select record": "Kayıt seç",
|
"Select record": "Kayıt seç",
|
||||||
|
@ -348,6 +348,10 @@
|
|||||||
"Add tab": "Додати вкладку",
|
"Add tab": "Додати вкладку",
|
||||||
"Disable tabs": "Вимкнути вкладки",
|
"Disable tabs": "Вимкнути вкладки",
|
||||||
"Details": "Деталі",
|
"Details": "Деталі",
|
||||||
|
"Edit form": "Редагувати форму",
|
||||||
|
"Create form": "Створити форму",
|
||||||
|
"Form (Edit)": "Форма (Редагувати)",
|
||||||
|
"Form (Add new)": "Форма (Додати новий)",
|
||||||
"Edit tab": "Редагувати вкладку",
|
"Edit tab": "Редагувати вкладку",
|
||||||
"Relationship blocks": "Блоки відношень",
|
"Relationship blocks": "Блоки відношень",
|
||||||
"Select record": "Вибрати запис",
|
"Select record": "Вибрати запис",
|
||||||
|
@ -379,6 +379,10 @@
|
|||||||
"Add tab": "添加标签页",
|
"Add tab": "添加标签页",
|
||||||
"Disable tabs": "禁用标签页",
|
"Disable tabs": "禁用标签页",
|
||||||
"Details": "详情",
|
"Details": "详情",
|
||||||
|
"Edit form": "编辑表单",
|
||||||
|
"Create form": "创建表单",
|
||||||
|
"Form (Edit)": "表单(编辑)",
|
||||||
|
"Form (Add new)": "表单(添加)",
|
||||||
"Edit tab": "编辑标签页",
|
"Edit tab": "编辑标签页",
|
||||||
"Relationship blocks": "关系数据区块",
|
"Relationship blocks": "关系数据区块",
|
||||||
"Select record": "选择数据",
|
"Select record": "选择数据",
|
||||||
|
@ -378,6 +378,10 @@
|
|||||||
"Add tab": "新增標籤頁",
|
"Add tab": "新增標籤頁",
|
||||||
"Disable tabs": "停用標籤頁",
|
"Disable tabs": "停用標籤頁",
|
||||||
"Details": "詳情",
|
"Details": "詳情",
|
||||||
|
"Edit form": "編輯表單",
|
||||||
|
"Create form": "建立表單",
|
||||||
|
"Form (Edit)": "表單(編輯)",
|
||||||
|
"Form (Add new)": "表單(添加)",
|
||||||
"Edit tab": "編輯標籤頁",
|
"Edit tab": "編輯標籤頁",
|
||||||
"Relationship blocks": "關聯資料區塊",
|
"Relationship blocks": "關聯資料區塊",
|
||||||
"Select record": "選擇資料",
|
"Select record": "選擇資料",
|
||||||
|
@ -4,8 +4,36 @@ import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../appl
|
|||||||
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
||||||
import { createDetailsBlockSchema } from '../../../../schema-initializer/utils';
|
import { createDetailsBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
|
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||||
|
|
||||||
export const DetailsBlockInitializer = () => {
|
export const DetailsBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
componentType = 'Details',
|
||||||
|
createBlockSchema,
|
||||||
|
templateWrap,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
/**
|
||||||
|
* 页面中的详情区块类型是 Details,弹窗中的详情区块类型是 ReadPrettyFormItem;
|
||||||
|
* 虽然这里的命名现在看起来比较奇怪,但为了兼容旧版本的 template,暂时保留这个命名。
|
||||||
|
*/
|
||||||
|
componentType?: 'Details' | 'ReadPrettyFormItem';
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
templateWrap?: (
|
||||||
|
templateSchema: any,
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const { getCollection } = useCollectionManager_deprecated();
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
@ -13,8 +41,13 @@ export const DetailsBlockInitializer = () => {
|
|||||||
<DataBlockInitializer
|
<DataBlockInitializer
|
||||||
{...itemConfig}
|
{...itemConfig}
|
||||||
icon={<TableOutlined />}
|
icon={<TableOutlined />}
|
||||||
componentType={'Details'}
|
componentType={componentType}
|
||||||
onCreateBlockSchema={async ({ item }) => {
|
onCreateBlockSchema={async (options) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { item } = options;
|
||||||
const collection = getCollection(item.name, item.dataSource);
|
const collection = getCollection(item.name, item.dataSource);
|
||||||
const schema = createDetailsBlockSchema({
|
const schema = createDetailsBlockSchema({
|
||||||
collection: item.name,
|
collection: item.name,
|
||||||
@ -28,6 +61,11 @@ export const DetailsBlockInitializer = () => {
|
|||||||
});
|
});
|
||||||
insert(schema);
|
insert(schema);
|
||||||
}}
|
}}
|
||||||
|
onlyCurrentDataSource={!!onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
filter={filterCollections}
|
||||||
|
templateWrap={templateWrap}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,8 +10,9 @@ test.describe('where multi data details block can be added', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.describe('configure fields', () => {
|
test.describe('configure fields', () => {
|
||||||
test('display collection fields & display association fields & add text', async ({ page, mockPage }) => {
|
test('display collection fields & display association fields & add text', async ({ page, mockPage, mockRecord }) => {
|
||||||
await mockPage(oneEmptyDetailsBlock).goto();
|
await mockPage(oneEmptyDetailsBlock).goto();
|
||||||
|
await mockRecord('general');
|
||||||
|
|
||||||
const formItemInitializer = page.getByLabel('schema-initializer-Grid-details:configureFields-general');
|
const formItemInitializer = page.getByLabel('schema-initializer-Grid-details:configureFields-general');
|
||||||
|
|
||||||
@ -60,8 +61,9 @@ test.describe('configure fields', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.describe('configure actions', () => {
|
test.describe('configure actions', () => {
|
||||||
test('edit & delete & duplicate', async ({ page, mockPage }) => {
|
test('edit & delete & duplicate', async ({ page, mockPage, mockRecord }) => {
|
||||||
await mockPage(oneEmptyDetailsBlock).goto();
|
await mockPage(oneEmptyDetailsBlock).goto();
|
||||||
|
await mockRecord('general');
|
||||||
|
|
||||||
await page.getByLabel('schema-initializer-ActionBar-detailsWithPaging:configureActions-general').hover();
|
await page.getByLabel('schema-initializer-ActionBar-detailsWithPaging:configureActions-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Edit' }).click();
|
await page.getByRole('menuitem', { name: 'Edit' }).click();
|
||||||
|
@ -29,8 +29,9 @@ test.describe('multi data details block schema settings', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.describe('actions schema settings', () => {
|
test.describe('actions schema settings', () => {
|
||||||
test('edit & delete & duplicate', async ({ page, mockPage }) => {
|
test('edit & delete & duplicate', async ({ page, mockPage, mockRecord }) => {
|
||||||
await mockPage(oneEmptyDetailsBlock).goto();
|
await mockPage(oneEmptyDetailsBlock).goto();
|
||||||
|
await mockRecord('general');
|
||||||
|
|
||||||
// 创建 Edit & Delete 两个按钮
|
// 创建 Edit & Delete 两个按钮
|
||||||
await page.getByLabel('schema-initializer-ActionBar-detailsWithPaging:configureActions-general').hover();
|
await page.getByLabel('schema-initializer-ActionBar-detailsWithPaging:configureActions-general').hover();
|
||||||
|
@ -1,66 +1,75 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
import { useBlockAssociationContext, useBlockRequestContext } from '../../../../block-provider';
|
import { useBlockAssociationContext, useBlockRequestContext } from '../../../../block-provider';
|
||||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||||
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
||||||
import {
|
import { createDetailsBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||||
createReadPrettyFormBlockSchema,
|
|
||||||
useRecordCollectionDataSourceItems,
|
|
||||||
} from '../../../../schema-initializer/utils';
|
|
||||||
|
|
||||||
export const RecordReadPrettyFormBlockInitializer = () => {
|
export const RecordReadPrettyFormBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const {
|
const { icon = true, targetCollection, ...others } = itemConfig;
|
||||||
onCreateBlockSchema,
|
|
||||||
componentType,
|
|
||||||
createBlockSchema,
|
|
||||||
icon = true,
|
|
||||||
targetCollection,
|
|
||||||
...others
|
|
||||||
} = itemConfig;
|
|
||||||
const { insert } = useSchemaInitializer();
|
|
||||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
|
||||||
const currentCollection = useCollection_deprecated();
|
const currentCollection = useCollection_deprecated();
|
||||||
const collection = targetCollection || currentCollection;
|
const collection = targetCollection || currentCollection;
|
||||||
const association = useBlockAssociationContext();
|
const { createSingleDetailsSchema } = useCreateSingleDetailsSchema();
|
||||||
const { block } = useBlockRequestContext();
|
|
||||||
const actionInitializers =
|
|
||||||
block !== 'TableField' ? itemConfig.actionInitializers || 'details:configureActions' : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaInitializerItem
|
<SchemaInitializerItem
|
||||||
icon={icon && <FormOutlined />}
|
icon={icon && <FormOutlined />}
|
||||||
{...others}
|
{...others}
|
||||||
onClick={async ({ item }) => {
|
onClick={(options) => createSingleDetailsSchema(options)}
|
||||||
if (item.template) {
|
items={useRecordCollectionDataSourceItems('ReadPrettyFormItem', null, collection?.name)}
|
||||||
const s = await getTemplateSchemaByMode(item);
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useCreateSingleDetailsSchema() {
|
||||||
|
const itemConfig = useSchemaInitializerItem();
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||||
|
const association = useBlockAssociationContext();
|
||||||
|
const { block } = useBlockRequestContext();
|
||||||
|
const actionInitializers =
|
||||||
|
block !== 'TableField' ? itemConfig.actionInitializers || 'details:configureActions' : null;
|
||||||
|
|
||||||
|
const templateWrap = useCallback(
|
||||||
|
(templateSchema, options) => {
|
||||||
|
const { item } = options;
|
||||||
if (item.template.componentName === 'ReadPrettyFormItem') {
|
if (item.template.componentName === 'ReadPrettyFormItem') {
|
||||||
const blockSchema = createReadPrettyFormBlockSchema({
|
const blockSchema = createDetailsBlockSchema({
|
||||||
actionInitializers,
|
actionInitializers,
|
||||||
association,
|
association,
|
||||||
collection: collection.name,
|
collection: item.collectionName || item.name,
|
||||||
dataSource: collection.dataSource,
|
dataSource: item.dataSource,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
useParams: '{{ useParamsFromRecord }}',
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
template: s,
|
template: templateSchema,
|
||||||
settings: 'blockSettings:singleDataDetails',
|
settings: 'blockSettings:singleDataDetails',
|
||||||
});
|
});
|
||||||
if (item.mode === 'reference') {
|
if (item.mode === 'reference') {
|
||||||
blockSchema['x-template-key'] = item.template.key;
|
blockSchema['x-template-key'] = item.template.key;
|
||||||
}
|
}
|
||||||
insert(blockSchema);
|
return blockSchema;
|
||||||
} else {
|
} else {
|
||||||
insert(s);
|
return templateSchema;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[actionInitializers, association],
|
||||||
|
);
|
||||||
|
|
||||||
|
const createSingleDetailsSchema = useCallback(
|
||||||
|
async ({ item }) => {
|
||||||
|
if (item.template) {
|
||||||
|
const template = await getTemplateSchemaByMode(item);
|
||||||
|
insert(templateWrap(template, { item }));
|
||||||
} else {
|
} else {
|
||||||
insert(
|
insert(
|
||||||
createReadPrettyFormBlockSchema({
|
createDetailsBlockSchema({
|
||||||
actionInitializers,
|
actionInitializers,
|
||||||
association,
|
association,
|
||||||
collection: collection.name,
|
collection: item.collectionName || item.name,
|
||||||
dataSource: collection.dataSource,
|
dataSource: item.dataSource,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
useParams: '{{ useParamsFromRecord }}',
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
@ -68,8 +77,9 @@ export const RecordReadPrettyFormBlockInitializer = () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
},
|
||||||
items={useRecordCollectionDataSourceItems('ReadPrettyFormItem', null, collection?.name)}
|
[actionInitializers, association, getTemplateSchemaByMode, insert, templateWrap],
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
return { createSingleDetailsSchema, templateWrap };
|
||||||
|
}
|
||||||
|
@ -8,10 +8,11 @@ test.describe('where single data details block can be added', () => {
|
|||||||
|
|
||||||
await page.getByLabel('action-Action.Link-View-view-general-table-0').click();
|
await page.getByLabel('action-Action.Link-View-view-general-table-0').click();
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
await page.getByRole('menuitem', { name: 'Details' }).hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'General' }).click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
|
||||||
await expect(page.getByLabel('block-item-CardItem-general-form')).toBeVisible();
|
await expect(page.getByLabel('block-item-CardItem-general-details')).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -23,38 +24,39 @@ test.describe('configure actions', () => {
|
|||||||
|
|
||||||
await page.getByLabel('action-Action.Link-View-view-general-table-0').click();
|
await page.getByLabel('action-Action.Link-View-view-general-table-0').click();
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
await page.getByRole('menuitem', { name: 'Details' }).hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'General' }).click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
|
||||||
// create edit ------------------------------------------------------------------------------------
|
// create edit ------------------------------------------------------------------------------------
|
||||||
await createAction(page, 'Edit');
|
await createAction(page, 'Edit');
|
||||||
await expect(page.getByLabel('action-Action-Edit-update-general-form-0')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Edit-update-')).toBeVisible();
|
||||||
await expectSettingsMenu({
|
await expectSettingsMenu({
|
||||||
page,
|
page,
|
||||||
showMenu: async () => {
|
showMenu: async () => {
|
||||||
await page.getByLabel('action-Action-Edit-update-general-form-0').hover();
|
await page.getByLabel('action-Action-Edit-update-').hover();
|
||||||
await page.getByRole('button', { name: 'designer-schema-settings-Action-actionSettings:edit-general' }).hover();
|
await page.getByRole('button', { name: 'designer-schema-settings-Action-actionSettings:edit-general' }).hover();
|
||||||
},
|
},
|
||||||
supportedOptions: ['Edit button', 'Linkage rules', 'Open mode', 'Popup size', 'Delete'],
|
supportedOptions: ['Edit button', 'Linkage rules', 'Open mode', 'Popup size', 'Delete'],
|
||||||
});
|
});
|
||||||
await deleteAction(page, 'action-Action-Edit-update-general-form-0');
|
await deleteAction(page, 'action-Action-Edit-update-');
|
||||||
|
|
||||||
// create delete ------------------------------------------------------------------------------------
|
// create delete ------------------------------------------------------------------------------------
|
||||||
await createAction(page, 'Delete');
|
await createAction(page, 'Delete');
|
||||||
await expect(page.getByLabel('action-Action-Delete-destroy-general-form-0')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Delete-destroy-general-details-')).toBeVisible();
|
||||||
|
|
||||||
// create print
|
// create print
|
||||||
await createAction(page, 'Print');
|
await createAction(page, 'Print');
|
||||||
await expect(page.getByLabel('action-Action-Print-print-general-form-0')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Print-print-')).toBeVisible();
|
||||||
|
|
||||||
// create customize actions ----------------------------------------------------------------------------
|
// create customize actions ----------------------------------------------------------------------------
|
||||||
// Popup
|
// Popup
|
||||||
await createCustomAction(page, 'Popup');
|
await createCustomAction(page, 'Popup');
|
||||||
await expect(page.getByLabel('action-Action-Popup-customize:popup-general-form-0')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Popup-customize')).toBeVisible();
|
||||||
|
|
||||||
// Update record
|
// Update record
|
||||||
await createCustomAction(page, 'Update record');
|
await createCustomAction(page, 'Update record');
|
||||||
await expect(page.getByLabel('action-Action-Update record-customize:update-general-form-0')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Update record-')).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,19 +1,69 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { useSchemaInitializerItem } from '../../../../application';
|
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
import { createFormBlockSchema } from '../../../../schema-initializer/utils';
|
import { createFormBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
|
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||||
|
|
||||||
export const FormBlockInitializer = () => {
|
export const FormBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
createBlockSchema,
|
||||||
|
componentType = 'FormItem',
|
||||||
|
templateWrap,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
/**
|
||||||
|
* 虽然这里的命名现在看起来比较奇怪,但为了兼容旧版本的 template,暂时保留这个命名。
|
||||||
|
*/
|
||||||
|
componentType?: 'FormItem';
|
||||||
|
templateWrap?: (
|
||||||
|
templateSchema: any,
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { isCusomeizeCreate } = itemConfig;
|
const { isCusomeizeCreate } = itemConfig;
|
||||||
|
const onCreateFormBlockSchema = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema({ item });
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createFormBlockSchema({
|
||||||
|
collection: item.collectionName || item.name,
|
||||||
|
dataSource: item.dataSource,
|
||||||
|
isCusomeizeCreate,
|
||||||
|
settings: 'blockSettings:createForm',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[createBlockSchema, insert, isCusomeizeCreate],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataBlockInitializer
|
<DataBlockInitializer
|
||||||
{...itemConfig}
|
{...itemConfig}
|
||||||
icon={<FormOutlined />}
|
icon={<FormOutlined />}
|
||||||
componentType={'FormItem'}
|
componentType={componentType}
|
||||||
templateWrap={(templateSchema, { item }) => {
|
templateWrap={(templateSchema, { item }) => {
|
||||||
const s = createFormBlockSchema({
|
if (templateWrap) {
|
||||||
|
return templateWrap(templateSchema, { item });
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema = createFormBlockSchema({
|
||||||
isCusomeizeCreate,
|
isCusomeizeCreate,
|
||||||
dataSource: item.dataSource,
|
dataSource: item.dataSource,
|
||||||
template: templateSchema,
|
template: templateSchema,
|
||||||
@ -21,11 +71,15 @@ export const FormBlockInitializer = () => {
|
|||||||
settings: 'blockSettings:createForm',
|
settings: 'blockSettings:createForm',
|
||||||
});
|
});
|
||||||
if (item.template && item.mode === 'reference') {
|
if (item.template && item.mode === 'reference') {
|
||||||
s['x-template-key'] = item.template.key;
|
schema['x-template-key'] = item.template.key;
|
||||||
}
|
}
|
||||||
return s;
|
return schema;
|
||||||
}}
|
}}
|
||||||
createBlockSchema={createFormBlockSchema}
|
onCreateBlockSchema={onCreateFormBlockSchema}
|
||||||
|
filter={filterCollections}
|
||||||
|
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,51 +1,52 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
import { useBlockAssociationContext } from '../../../../block-provider';
|
import { useBlockAssociationContext } from '../../../../block-provider';
|
||||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||||
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
||||||
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const RecordFormBlockInitializer = () => {
|
export const RecordFormBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { onCreateBlockSchema, componentType, createBlockSchema, targetCollection, ...others } = itemConfig;
|
const { targetCollection, ...others } = itemConfig;
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||||
const currentCollection = useCollection_deprecated();
|
const currentCollection = useCollection_deprecated();
|
||||||
const collection = targetCollection || currentCollection;
|
const collection = targetCollection || currentCollection;
|
||||||
const association = useBlockAssociationContext();
|
|
||||||
|
const { createEditFormBlock, templateWrap } = useCreateEditFormBlock();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaInitializerItem
|
<SchemaInitializerItem
|
||||||
icon={<FormOutlined />}
|
icon={<FormOutlined />}
|
||||||
{...others}
|
{...others}
|
||||||
onClick={async ({ item }) => {
|
onClick={async ({ item }) => {
|
||||||
if (item.template) {
|
if (item.template) {
|
||||||
const s = await getTemplateSchemaByMode(item);
|
const template = await getTemplateSchemaByMode(item);
|
||||||
if (item.template.componentName === 'FormItem') {
|
insert(templateWrap(template, { item }));
|
||||||
const blockSchema = createFormBlockSchema({
|
|
||||||
association,
|
|
||||||
collection: collection.name,
|
|
||||||
dataSource: collection.dataSource,
|
|
||||||
action: 'get',
|
|
||||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
|
||||||
useParams: '{{ useParamsFromRecord }}',
|
|
||||||
actionInitializers: 'editForm:configureActions',
|
|
||||||
template: s,
|
|
||||||
settings: 'blockSettings:editForm',
|
|
||||||
});
|
|
||||||
if (item.mode === 'reference') {
|
|
||||||
blockSchema['x-template-key'] = item.template.key;
|
|
||||||
}
|
|
||||||
insert(blockSchema);
|
|
||||||
} else {
|
} else {
|
||||||
insert(s);
|
createEditFormBlock({ item });
|
||||||
}
|
}
|
||||||
} else {
|
}}
|
||||||
|
items={useRecordCollectionDataSourceItems('FormItem', null, collection?.name)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useCreateEditFormBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const association = useBlockAssociationContext();
|
||||||
|
|
||||||
|
const createEditFormBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
insert(
|
insert(
|
||||||
createFormBlockSchema({
|
createFormBlockSchema({
|
||||||
association,
|
association,
|
||||||
collection: collection.name,
|
collection: item.collectionName || item.name,
|
||||||
dataSource: collection.dataSource,
|
dataSource: item.dataSource,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
useParams: '{{ useParamsFromRecord }}',
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
@ -53,9 +54,34 @@ export const RecordFormBlockInitializer = () => {
|
|||||||
settings: 'blockSettings:editForm',
|
settings: 'blockSettings:editForm',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}}
|
[association, insert],
|
||||||
items={useRecordCollectionDataSourceItems('FormItem', null, collection?.name)}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
const templateWrap = useCallback(
|
||||||
|
(templateSchema, { item }) => {
|
||||||
|
if (item.template.componentName === 'FormItem') {
|
||||||
|
const blockSchema = createFormBlockSchema({
|
||||||
|
association,
|
||||||
|
collection: item.collectionName || item.name,
|
||||||
|
dataSource: item.dataSource,
|
||||||
|
action: 'get',
|
||||||
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
|
actionInitializers: 'editForm:configureActions',
|
||||||
|
template: templateSchema,
|
||||||
|
settings: 'blockSettings:editForm',
|
||||||
|
});
|
||||||
|
if (item.mode === 'reference') {
|
||||||
|
blockSchema['x-template-key'] = item.template.key;
|
||||||
|
}
|
||||||
|
return blockSchema;
|
||||||
|
} else {
|
||||||
|
return templateSchema;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[association],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createEditFormBlock, templateWrap };
|
||||||
|
}
|
||||||
|
@ -1183,7 +1183,7 @@ test.describe('creation form block schema settings', () => {
|
|||||||
//在编辑操作中使用引用模板
|
//在编辑操作中使用引用模板
|
||||||
await page.getByLabel('action-Action.Link-Edit-update-users-table-0').click();
|
await page.getByLabel('action-Action.Link-Edit-update-users-table-0').click();
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-users').click();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-users').click();
|
||||||
await page.getByRole('menuitem', { name: 'form Form' }).first().hover();
|
await page.getByRole('menuitem', { name: 'form Form (Edit)' }).first().hover();
|
||||||
await page.getByRole('menuitem', { name: 'Reference template' }).hover();
|
await page.getByRole('menuitem', { name: 'Reference template' }).hover();
|
||||||
await page.getByRole('menuitem', { name: 'Users_Form (Fields only)' }).first().click();
|
await page.getByRole('menuitem', { name: 'Users_Form (Fields only)' }).first().click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
@ -5499,7 +5499,7 @@ export const T3469: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'BlockInitializers',
|
'x-initializer': 'page:addBlock',
|
||||||
'x-index': 1,
|
'x-index': 1,
|
||||||
properties: {
|
properties: {
|
||||||
isaxpp1w32b: {
|
isaxpp1w32b: {
|
||||||
@ -5551,7 +5551,7 @@ export const T3469: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'FormItemInitializers',
|
'x-initializer': 'form:configureFields',
|
||||||
'x-index': 1,
|
'x-index': 1,
|
||||||
properties: {
|
properties: {
|
||||||
e4ke3wqxm2o: {
|
e4ke3wqxm2o: {
|
||||||
@ -5710,7 +5710,7 @@ export const T3529: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'BlockInitializers',
|
'x-initializer': 'page:addBlock',
|
||||||
properties: {
|
properties: {
|
||||||
l62athlwjbe: {
|
l62athlwjbe: {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -5752,7 +5752,7 @@ export const T3529: PageConfig = {
|
|||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-initializer': 'TableActionInitializers',
|
'x-initializer': 'table:configureActions',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
style: {
|
style: {
|
||||||
@ -5767,7 +5767,7 @@ export const T3529: PageConfig = {
|
|||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'array',
|
type: 'array',
|
||||||
'x-initializer': 'TableColumnInitializers',
|
'x-initializer': 'table:configureColumns',
|
||||||
'x-component': 'TableV2',
|
'x-component': 'TableV2',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
@ -5786,7 +5786,7 @@ export const T3529: PageConfig = {
|
|||||||
'x-decorator': 'TableV2.Column.ActionBar',
|
'x-decorator': 'TableV2.Column.ActionBar',
|
||||||
'x-component': 'TableV2.Column',
|
'x-component': 'TableV2.Column',
|
||||||
'x-designer': 'TableV2.ActionColumnDesigner',
|
'x-designer': 'TableV2.ActionColumnDesigner',
|
||||||
'x-initializer': 'TableActionColumnInitializers',
|
'x-initializer': 'table:configureItemActions',
|
||||||
properties: {
|
properties: {
|
||||||
'7glkmum3znh': {
|
'7glkmum3znh': {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -5847,7 +5847,7 @@ export const T3529: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'RecordBlockInitializers',
|
'x-initializer': 'popup:common:addBlock',
|
||||||
properties: {
|
properties: {
|
||||||
'5ubuvb82lbu': {
|
'5ubuvb82lbu': {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -5898,7 +5898,7 @@ export const T3529: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'FormItemInitializers',
|
'x-initializer': 'form:configureFields',
|
||||||
'x-uid': 'aigmsbzdyeb',
|
'x-uid': 'aigmsbzdyeb',
|
||||||
'x-async': false,
|
'x-async': false,
|
||||||
'x-index': 1,
|
'x-index': 1,
|
||||||
@ -5907,7 +5907,7 @@ export const T3529: PageConfig = {
|
|||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-initializer': 'CreateFormActionInitializers',
|
'x-initializer': 'createForm:configureActions',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
layout: 'one-column',
|
layout: 'one-column',
|
||||||
|
@ -4,8 +4,35 @@ import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../appl
|
|||||||
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
||||||
import { createGridCardBlockSchema } from '../../../../schema-initializer/utils';
|
import { createGridCardBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
|
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||||
|
|
||||||
export const GridCardBlockInitializer = () => {
|
export const GridCardBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
createBlockSchema,
|
||||||
|
componentType = 'FormItem',
|
||||||
|
templateWrap,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
/**
|
||||||
|
* 虽然这里的命名现在看起来比较奇怪,但为了兼容旧版本的 template,暂时保留这个命名。
|
||||||
|
*/
|
||||||
|
componentType?: 'FormItem';
|
||||||
|
templateWrap?: (
|
||||||
|
templateSchema: any,
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const { getCollection } = useCollectionManager_deprecated();
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
@ -15,6 +42,10 @@ export const GridCardBlockInitializer = () => {
|
|||||||
icon={<OrderedListOutlined />}
|
icon={<OrderedListOutlined />}
|
||||||
componentType={'GridCard'}
|
componentType={'GridCard'}
|
||||||
onCreateBlockSchema={async ({ item }) => {
|
onCreateBlockSchema={async ({ item }) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema({ item });
|
||||||
|
}
|
||||||
|
|
||||||
const collection = getCollection(item.name, item.dataSource);
|
const collection = getCollection(item.name, item.dataSource);
|
||||||
const schema = createGridCardBlockSchema({
|
const schema = createGridCardBlockSchema({
|
||||||
collection: item.name,
|
collection: item.name,
|
||||||
@ -24,6 +55,10 @@ export const GridCardBlockInitializer = () => {
|
|||||||
});
|
});
|
||||||
insert(schema);
|
insert(schema);
|
||||||
}}
|
}}
|
||||||
|
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
filter={filterCollections}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,35 @@ import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../appl
|
|||||||
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../../../collection-manager';
|
||||||
import { createListBlockSchema } from '../../../../schema-initializer/utils';
|
import { createListBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
|
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||||
|
|
||||||
export const ListBlockInitializer = () => {
|
export const ListBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
createBlockSchema,
|
||||||
|
componentType = 'FormItem',
|
||||||
|
templateWrap,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
/**
|
||||||
|
* 虽然这里的命名现在看起来比较奇怪,但为了兼容旧版本的 template,暂时保留这个命名。
|
||||||
|
*/
|
||||||
|
componentType?: 'FormItem';
|
||||||
|
templateWrap?: (
|
||||||
|
templateSchema: any,
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { getCollection } = useCollectionManager_deprecated();
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
@ -15,6 +42,10 @@ export const ListBlockInitializer = () => {
|
|||||||
icon={<OrderedListOutlined />}
|
icon={<OrderedListOutlined />}
|
||||||
componentType={'List'}
|
componentType={'List'}
|
||||||
onCreateBlockSchema={async ({ item }) => {
|
onCreateBlockSchema={async ({ item }) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema({ item });
|
||||||
|
}
|
||||||
|
|
||||||
const collection = getCollection(item.name, item.dataSource);
|
const collection = getCollection(item.name, item.dataSource);
|
||||||
const schema = createListBlockSchema({
|
const schema = createListBlockSchema({
|
||||||
collection: item.name,
|
collection: item.name,
|
||||||
@ -24,6 +55,10 @@ export const ListBlockInitializer = () => {
|
|||||||
});
|
});
|
||||||
insert(schema);
|
insert(schema);
|
||||||
}}
|
}}
|
||||||
|
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
filter={filterCollections}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,30 @@ import { useCollectionManager_deprecated } from '../../../../collection-manager/
|
|||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
import { createTableBlockSchema } from '../../../../schema-initializer/utils';
|
import { createTableBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||||
|
|
||||||
export const TableBlockInitializer = () => {
|
export const TableBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
createBlockSchema,
|
||||||
|
templateWrap,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
templateWrap?: (
|
||||||
|
templateSchema: any,
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const { getCollection } = useCollectionManager_deprecated();
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
@ -15,6 +37,10 @@ export const TableBlockInitializer = () => {
|
|||||||
icon={<TableOutlined />}
|
icon={<TableOutlined />}
|
||||||
componentType={'Table'}
|
componentType={'Table'}
|
||||||
onCreateBlockSchema={async ({ item }) => {
|
onCreateBlockSchema={async ({ item }) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema({ item });
|
||||||
|
}
|
||||||
|
|
||||||
const collection = getCollection(item.name, item.dataSource);
|
const collection = getCollection(item.name, item.dataSource);
|
||||||
const schema = createTableBlockSchema({
|
const schema = createTableBlockSchema({
|
||||||
collection: item.name,
|
collection: item.name,
|
||||||
@ -23,6 +49,10 @@ export const TableBlockInitializer = () => {
|
|||||||
});
|
});
|
||||||
insert(schema);
|
insert(schema);
|
||||||
}}
|
}}
|
||||||
|
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
filter={filterCollections}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,14 +4,16 @@ import React from 'react';
|
|||||||
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
import { createCollapseBlockSchema } from '../../../../schema-initializer/utils';
|
import { createCollapseBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||||
import { Collection } from '../../../../data-source';
|
import { Collection, CollectionFieldOptions } from '../../../../data-source';
|
||||||
|
|
||||||
export const FilterCollapseBlockInitializer = ({
|
export const FilterCollapseBlockInitializer = ({
|
||||||
filterMenuItemChildren,
|
filterCollections,
|
||||||
onlyCurrentDataSource,
|
onlyCurrentDataSource,
|
||||||
|
showChildren,
|
||||||
}: {
|
}: {
|
||||||
filterMenuItemChildren: (collection: Collection) => boolean;
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
onlyCurrentDataSource: boolean;
|
onlyCurrentDataSource: boolean;
|
||||||
|
showChildren?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
@ -31,7 +33,8 @@ export const FilterCollapseBlockInitializer = ({
|
|||||||
});
|
});
|
||||||
insert(schema);
|
insert(schema);
|
||||||
}}
|
}}
|
||||||
filter={filterMenuItemChildren}
|
filter={filterCollections}
|
||||||
|
showChildren={showChildren}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSchemaInitializerItem } from '../../../../application';
|
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
import { createFilterFormBlockSchema } from '../../../../schema-initializer/utils';
|
import { createFilterFormBlockSchema } from '../../../../schema-initializer/utils';
|
||||||
import { FilterBlockInitializer } from '../../../../schema-initializer/items/FilterBlockInitializer';
|
import { FilterBlockInitializer } from '../../../../schema-initializer/items/FilterBlockInitializer';
|
||||||
import { Collection } from '../../../../data-source';
|
import { Collection, CollectionFieldOptions } from '../../../../data-source';
|
||||||
|
|
||||||
export const FilterFormBlockInitializer = ({
|
export const FilterFormBlockInitializer = ({
|
||||||
filterMenuItemChildren,
|
filterCollections,
|
||||||
onlyCurrentDataSource,
|
onlyCurrentDataSource,
|
||||||
|
showChildren,
|
||||||
}: {
|
}: {
|
||||||
filterMenuItemChildren: (collection: Collection) => boolean;
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
onlyCurrentDataSource: boolean;
|
onlyCurrentDataSource: boolean;
|
||||||
|
showChildren?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterBlockInitializer
|
<FilterBlockInitializer
|
||||||
@ -32,11 +35,17 @@ export const FilterFormBlockInitializer = ({
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}}
|
}}
|
||||||
createBlockSchema={(options) => {
|
onCreateBlockSchema={({ item }) => {
|
||||||
options = { ...options, settings: 'blockSettings:filterForm' };
|
return insert(
|
||||||
return createFilterFormBlockSchema(options);
|
createFilterFormBlockSchema({
|
||||||
|
collection: item.collectionName || item.name,
|
||||||
|
dataSource: item.dataSource,
|
||||||
|
settings: 'blockSettings:filterForm',
|
||||||
|
}),
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
filter={filterMenuItemChildren}
|
filter={filterCollections}
|
||||||
|
showChildren={showChildren}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -77,10 +77,9 @@ test.describe('where to open a popup and what can be added to it', () => {
|
|||||||
await expect(page.getByText('test8')).toBeVisible();
|
await expect(page.getByText('test8')).toBeVisible();
|
||||||
|
|
||||||
// add blocks
|
// add blocks
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
await addBlock(['table Details right', 'General']);
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
await addBlock(['form Form (Edit)']);
|
||||||
await page.getByText('Form').first().click();
|
await addBlock(['Markdown']);
|
||||||
await page.getByRole('menuitem', { name: 'Markdown' }).click();
|
|
||||||
|
|
||||||
await expect(page.getByText('GeneralConfigure actionsConfigure fields')).toBeVisible();
|
await expect(page.getByText('GeneralConfigure actionsConfigure fields')).toBeVisible();
|
||||||
await expect(page.getByText('GeneralConfigure fieldsConfigure actions')).toBeVisible();
|
await expect(page.getByText('GeneralConfigure fieldsConfigure actions')).toBeVisible();
|
||||||
@ -106,26 +105,18 @@ test.describe('where to open a popup and what can be added to it', () => {
|
|||||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
|
||||||
// add relationship blocks
|
// add relationship blocks
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
await addBlock(['table Details right', 'Many to one']);
|
||||||
await page.getByRole('menuitem', { name: 'Many to one' }).hover();
|
await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible();
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
await addBlock(['table Table right', 'One to many']);
|
||||||
|
|
||||||
await page.mouse.move(300, 0);
|
|
||||||
|
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
|
||||||
await page.getByRole('menuitem', { name: 'One to many' }).hover();
|
|
||||||
|
|
||||||
// 下拉列表中,可选择以下区块进行创建
|
|
||||||
await expect(page.getByText('Table')).toBeVisible();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'Details' }).nth(1)).toBeVisible();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'List' })).toBeVisible();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'Grid Card' })).toBeVisible();
|
|
||||||
await expect(page.getByText('Form').nth(1)).toBeVisible();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'Calendar' })).toBeVisible();
|
|
||||||
|
|
||||||
await page.getByText('Table').click();
|
|
||||||
await page.mouse.move(300, 0);
|
|
||||||
await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible();
|
await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible();
|
||||||
|
|
||||||
|
async function addBlock(names: string[]) {
|
||||||
|
await page.getByLabel('schema-initializer-Grid-popup').hover();
|
||||||
|
for (const name of names) {
|
||||||
|
await page.getByRole('menuitem', { name }).click();
|
||||||
|
}
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('bulk edit', async ({ page, mockPage }) => {
|
test('bulk edit', async ({ page, mockPage }) => {
|
||||||
@ -171,8 +162,11 @@ test.describe('where to open a popup and what can be added to it', () => {
|
|||||||
|
|
||||||
// add blocks
|
// add blocks
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
await page.getByRole('menuitem', { name: 'Details' }).hover();
|
||||||
await page.getByText('Form').first().click();
|
await page.getByRole('menuitem', { name: 'General' }).click();
|
||||||
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'form Form (Edit)' }).first().click();
|
||||||
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Markdown' }).click();
|
await page.getByRole('menuitem', { name: 'Markdown' }).click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
|
||||||
@ -181,27 +175,27 @@ test.describe('where to open a popup and what can be added to it', () => {
|
|||||||
await expect(page.getByLabel('block-item-Markdown.Void-general-markdown')).toBeVisible();
|
await expect(page.getByLabel('block-item-Markdown.Void-general-markdown')).toBeVisible();
|
||||||
|
|
||||||
// add relationship blocks
|
// add relationship blocks
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
|
||||||
await page.getByRole('menuitem', { name: 'Many to one' }).hover();
|
|
||||||
await page.getByRole('menuitem', { name: 'Details' }).click();
|
|
||||||
await page.mouse.move(300, 0);
|
|
||||||
|
|
||||||
await expect(page.getByLabel('block-item-CardItem-general-').nth(2)).toBeVisible();
|
|
||||||
|
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
|
||||||
await page.getByRole('menuitem', { name: 'One to many' }).hover();
|
|
||||||
|
|
||||||
// 下拉列表中,可选择以下区块进行创建
|
// 下拉列表中,可选择以下区块进行创建
|
||||||
await expect(page.getByText('Table')).toBeVisible();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
await expect(page.getByRole('menuitem', { name: 'Details' }).nth(1)).toBeVisible();
|
await expect(page.getByRole('menuitem', { name: 'table Details right' })).toBeVisible();
|
||||||
await expect(page.getByRole('menuitem', { name: 'List' })).toBeVisible();
|
await expect(page.getByRole('menuitem', { name: 'form Form (Edit)' })).toBeVisible();
|
||||||
await expect(page.getByRole('menuitem', { name: 'Grid Card' })).toBeVisible();
|
await expect(page.getByRole('menuitem', { name: 'form Form (Add new) right' })).toBeVisible();
|
||||||
await expect(page.getByText('Form').nth(1)).toBeVisible();
|
await expect(page.getByRole('menuitem', { name: 'form Form (Add new) right' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'table Table right' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'ordered-list List right' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'ordered-list Grid Card right' })).toBeVisible();
|
||||||
await expect(page.getByRole('menuitem', { name: 'Calendar' })).toBeVisible();
|
await expect(page.getByRole('menuitem', { name: 'Calendar' })).toBeVisible();
|
||||||
|
|
||||||
await page.getByText('Table').click();
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'Details' }).hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'Many to one' }).click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'table Table right' }).hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'One to many' }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible();
|
await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible();
|
||||||
// 屏幕上没有显示错误提示
|
// 屏幕上没有显示错误提示
|
||||||
await expect(page.locator('.ant-notification-notice').first()).toBeHidden({ timeout: 1000 });
|
await expect(page.locator('.ant-notification-notice').first()).toBeHidden({ timeout: 1000 });
|
||||||
|
@ -16,7 +16,7 @@ export const oneTableBlockWithDatetimeFields: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'BlockInitializers',
|
'x-initializer': 'page:addBlock',
|
||||||
properties: {
|
properties: {
|
||||||
irc4mhtog83: {
|
irc4mhtog83: {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -58,7 +58,7 @@ export const oneTableBlockWithDatetimeFields: PageConfig = {
|
|||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-initializer': 'TableActionInitializers',
|
'x-initializer': 'table:configureActions',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
style: {
|
style: {
|
||||||
@ -73,7 +73,7 @@ export const oneTableBlockWithDatetimeFields: PageConfig = {
|
|||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'array',
|
type: 'array',
|
||||||
'x-initializer': 'TableColumnInitializers',
|
'x-initializer': 'table:configureColumns',
|
||||||
'x-component': 'TableV2',
|
'x-component': 'TableV2',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
@ -92,7 +92,7 @@ export const oneTableBlockWithDatetimeFields: PageConfig = {
|
|||||||
'x-decorator': 'TableV2.Column.ActionBar',
|
'x-decorator': 'TableV2.Column.ActionBar',
|
||||||
'x-component': 'TableV2.Column',
|
'x-component': 'TableV2.Column',
|
||||||
'x-designer': 'TableV2.ActionColumnDesigner',
|
'x-designer': 'TableV2.ActionColumnDesigner',
|
||||||
'x-initializer': 'TableActionColumnInitializers',
|
'x-initializer': 'table:configureItemActions',
|
||||||
properties: {
|
properties: {
|
||||||
gk4b4e4wp8b: {
|
gk4b4e4wp8b: {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -192,7 +192,7 @@ export const oneFormBlockWithDatetimeFields: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'BlockInitializers',
|
'x-initializer': 'page:addBlock',
|
||||||
properties: {
|
properties: {
|
||||||
annx4g65mtu: {
|
annx4g65mtu: {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -239,7 +239,7 @@ export const oneFormBlockWithDatetimeFields: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'FormItemInitializers',
|
'x-initializer': 'form:configureFields',
|
||||||
properties: {
|
properties: {
|
||||||
'269bdhc35j2': {
|
'269bdhc35j2': {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
|
@ -35,7 +35,7 @@ export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitiali
|
|||||||
title: '{{t("Form")}}',
|
title: '{{t("Form")}}',
|
||||||
Component: 'FilterFormBlockInitializer',
|
Component: 'FilterFormBlockInitializer',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
filterMenuItemChildren() {
|
filterCollections() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
@ -48,7 +48,7 @@ export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitiali
|
|||||||
title: '{{t("Collapse")}}',
|
title: '{{t("Collapse")}}',
|
||||||
Component: 'FilterCollapseBlockInitializer',
|
Component: 'FilterCollapseBlockInitializer',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
filterMenuItemChildren() {
|
filterCollections() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
@ -117,7 +117,7 @@ export const tableSelectorInitializers = new CompatibleSchemaInitializer(
|
|||||||
title: '{{t("Form")}}',
|
title: '{{t("Form")}}',
|
||||||
Component: 'FilterFormBlockInitializer',
|
Component: 'FilterFormBlockInitializer',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
filterMenuItemChildren() {
|
filterCollections() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
@ -130,7 +130,7 @@ export const tableSelectorInitializers = new CompatibleSchemaInitializer(
|
|||||||
title: '{{t("Collapse")}}',
|
title: '{{t("Collapse")}}',
|
||||||
Component: 'FilterCollapseBlockInitializer',
|
Component: 'FilterCollapseBlockInitializer',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
filterMenuItemChildren() {
|
filterCollections() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
import { test, expect } from '@nocobase/test/e2e';
|
||||||
|
|
||||||
|
test.describe('page:addBlock', () => {
|
||||||
|
test('当搜索不到数据时显示空状态', async ({ page, mockPage }) => {
|
||||||
|
await mockPage().goto();
|
||||||
|
await page.getByLabel('schema-initializer-Grid-').hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'table Table right' }).hover();
|
||||||
|
await page.getByRole('textbox', { name: 'Search and select collection' }).fill('no match');
|
||||||
|
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'No data' })).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
@ -1,3 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
import { FormV2 } from '../form-v2';
|
import { FormV2 } from '../form-v2';
|
||||||
|
import { useDetailsBlockContext } from '../../../block-provider/DetailsBlockProvider';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { Empty } from 'antd';
|
||||||
|
import { useDataBlockRequest } from '../../../data-source';
|
||||||
|
|
||||||
export const Details = FormV2;
|
export const Details = (props) => {
|
||||||
|
const request = useDataBlockRequest();
|
||||||
|
|
||||||
|
if (!request?.loading && _.isEmpty(request?.data?.data)) {
|
||||||
|
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <FormV2 {...props} />;
|
||||||
|
};
|
||||||
|
@ -6,7 +6,6 @@ describe('Details', () => {
|
|||||||
it('should render correctly', () => {
|
it('should render correctly', () => {
|
||||||
render(<App1 />);
|
render(<App1 />);
|
||||||
|
|
||||||
expect(screen.getByText('this is name')).toBeInTheDocument();
|
expect(screen.getByText('No data')).toBeInTheDocument();
|
||||||
expect(screen.getByText('this is age')).toBeInTheDocument();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
import { Schema, useFieldSchema } from '@formily/react';
|
import { Schema } from '@formily/react';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useCollectionManager_deprecated, useCollection_deprecated } from '../..';
|
import {
|
||||||
import { SchemaInitializerItemType, useSchemaInitializer } from '../../application';
|
useCollection,
|
||||||
|
useCollectionManager_deprecated,
|
||||||
|
useCollection_deprecated,
|
||||||
|
useCreateAssociationDetailsBlock,
|
||||||
|
useCreateAssociationDetailsWithoutPagination,
|
||||||
|
useCreateAssociationFormBlock,
|
||||||
|
useCreateAssociationGridCardBlock,
|
||||||
|
useCreateAssociationListBlock,
|
||||||
|
useCreateAssociationTableBlock,
|
||||||
|
useCreateEditFormBlock,
|
||||||
|
} from '../..';
|
||||||
import { CompatibleSchemaInitializer } from '../../application/schema-initializer/CompatibleSchemaInitializer';
|
import { CompatibleSchemaInitializer } from '../../application/schema-initializer/CompatibleSchemaInitializer';
|
||||||
import { gridRowColWrap } from '../utils';
|
import { gridRowColWrap } from '../utils';
|
||||||
|
import { useCreateSingleDetailsSchema } from '../../modules/blocks/data-blocks/details-single/RecordReadPrettyFormBlockInitializer';
|
||||||
|
|
||||||
const recursiveParent = (schema: Schema) => {
|
const recursiveParent = (schema: Schema) => {
|
||||||
if (!schema) return null;
|
if (!schema) return null;
|
||||||
@ -15,223 +26,233 @@ const recursiveParent = (schema: Schema) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const useRelationFields = () => {
|
export const canMakeAssociationBlock = (field) => {
|
||||||
const fieldSchema = useFieldSchema();
|
return ['linkTo', 'subTable', 'o2m', 'm2m', 'obo', 'oho', 'o2o', 'm2o'].includes(field.interface);
|
||||||
const { getCollectionFields } = useCollectionManager_deprecated();
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
let fields = [];
|
|
||||||
|
|
||||||
if (fieldSchema['x-initializer']) {
|
|
||||||
fields = collection.fields;
|
|
||||||
} else {
|
|
||||||
const collection = recursiveParent(fieldSchema.parent);
|
|
||||||
if (collection) {
|
|
||||||
fields = getCollectionFields(collection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const relationFields = fields
|
|
||||||
.filter((field) => ['linkTo', 'subTable', 'o2m', 'm2m', 'obo', 'oho', 'o2o', 'm2o'].includes(field.interface))
|
|
||||||
.map((field) => {
|
|
||||||
if (['hasOne', 'belongsTo'].includes(field.type)) {
|
|
||||||
return {
|
|
||||||
name: field.name,
|
|
||||||
type: 'subMenu',
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: `${field.name}_details`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Details")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordReadPrettyAssociationFormBlockInitializer',
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: `${field.name}_form`,
|
|
||||||
// type: 'item',
|
|
||||||
// title: '{{t("Form")}}',
|
|
||||||
// field,
|
|
||||||
// component: 'RecordAssociationFormBlockInitializer',
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (['hasMany', 'belongsToMany'].includes(field.type)) {
|
|
||||||
return {
|
|
||||||
name: field.name,
|
|
||||||
type: 'subMenu',
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: `${field.name}_table`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Table")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationBlockInitializer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `${field.name}_details`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Details")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationDetailsBlockInitializer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `${field.name}_list`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("List")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationListBlockInitializer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `${field.name}_grid_card`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Grid Card")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationGridCardBlockInitializer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `${field.name}_form`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Form")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationFormBlockInitializer',
|
|
||||||
},
|
|
||||||
// TODO: This one should be append in the calendar plugin
|
|
||||||
{
|
|
||||||
name: `${field.name}_calendar`,
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Calendar")}}',
|
|
||||||
field,
|
|
||||||
Component: 'RecordAssociationCalendarBlockInitializer',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: field.name,
|
|
||||||
type: 'item',
|
|
||||||
field,
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
Component: 'RecordAssociationBlockInitializer',
|
|
||||||
};
|
|
||||||
}) as any;
|
|
||||||
|
|
||||||
return relationFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useDetailCollections = (props) => {
|
|
||||||
const { actionInitializers, childrenCollections, collection } = props;
|
|
||||||
const detailCollections = [
|
|
||||||
{
|
|
||||||
name: collection.name,
|
|
||||||
type: 'item',
|
|
||||||
title: collection?.title || collection.name,
|
|
||||||
Component: 'RecordReadPrettyFormBlockInitializer',
|
|
||||||
icon: false,
|
|
||||||
targetCollection: collection,
|
|
||||||
actionInitializers,
|
|
||||||
},
|
|
||||||
].concat(
|
|
||||||
childrenCollections.map((c) => {
|
|
||||||
return {
|
|
||||||
name: c.name,
|
|
||||||
type: 'item',
|
|
||||||
title: c?.title || c.name,
|
|
||||||
Component: 'RecordReadPrettyFormBlockInitializer',
|
|
||||||
icon: false,
|
|
||||||
targetCollection: c,
|
|
||||||
actionInitializers,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
) as SchemaInitializerItemType[];
|
|
||||||
return detailCollections;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useFormCollections = (props) => {
|
|
||||||
const { actionInitializers, childrenCollections, collection } = props;
|
|
||||||
const formCollections = [
|
|
||||||
{
|
|
||||||
name: collection.name,
|
|
||||||
type: 'item',
|
|
||||||
title: collection?.title || collection.name,
|
|
||||||
Component: 'RecordFormBlockInitializer',
|
|
||||||
icon: false,
|
|
||||||
targetCollection: collection,
|
|
||||||
actionInitializers,
|
|
||||||
},
|
|
||||||
].concat(
|
|
||||||
childrenCollections.map((c) => {
|
|
||||||
return {
|
|
||||||
name: c.name,
|
|
||||||
type: 'item',
|
|
||||||
title: c?.title || c.name,
|
|
||||||
Component: 'RecordFormBlockInitializer',
|
|
||||||
icon: false,
|
|
||||||
targetCollection: c,
|
|
||||||
actionInitializers,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
) as SchemaInitializerItemType[];
|
|
||||||
|
|
||||||
return formCollections;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function useRecordBlocks() {
|
function useRecordBlocks() {
|
||||||
const { options } = useSchemaInitializer();
|
|
||||||
const { actionInitializers } = options;
|
|
||||||
const collection = useCollection_deprecated();
|
const collection = useCollection_deprecated();
|
||||||
const { getChildrenCollections } = useCollectionManager_deprecated();
|
const { getChildrenCollections } = useCollectionManager_deprecated();
|
||||||
const collectionsWithView = getChildrenCollections(collection.name, true, collection.dataSource).filter(
|
const collectionsWithView = getChildrenCollections(collection.name, true, collection.dataSource).filter(
|
||||||
(v) => v?.filterTargetKey,
|
(v) => v?.filterTargetKey,
|
||||||
);
|
);
|
||||||
const hasChildCollection = collectionsWithView?.length > 0;
|
|
||||||
const modifyFlag = (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
|
||||||
const detailChildren = useDetailCollections({
|
|
||||||
...options,
|
|
||||||
childrenCollections: collectionsWithView,
|
|
||||||
collection,
|
|
||||||
});
|
|
||||||
const formChildren = useFormCollections({
|
|
||||||
...options,
|
|
||||||
childrenCollections: collectionsWithView,
|
|
||||||
collection,
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = [];
|
const res: any[] = [
|
||||||
if (hasChildCollection) {
|
{
|
||||||
res.push({
|
|
||||||
name: 'details',
|
|
||||||
type: 'subMenu',
|
|
||||||
title: '{{t("Details")}}',
|
|
||||||
children: detailChildren,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.push({
|
|
||||||
name: 'details',
|
name: 'details',
|
||||||
title: '{{t("Details")}}',
|
title: '{{t("Details")}}',
|
||||||
Component: 'RecordReadPrettyFormBlockInitializer',
|
Component: 'DetailsBlockInitializer',
|
||||||
actionInitializers,
|
collectionName: collection.name,
|
||||||
});
|
dataSource: collection.dataSource,
|
||||||
|
useComponentProps() {
|
||||||
|
const currentCollection = useCollection_deprecated();
|
||||||
|
const { createSingleDetailsSchema, templateWrap } = useCreateSingleDetailsSchema();
|
||||||
|
const { createAssociationDetailsBlock } = useCreateAssociationDetailsBlock();
|
||||||
|
const {
|
||||||
|
createAssociationDetailsWithoutPagination,
|
||||||
|
templateWrap: templateWrapOfAssociationDetailsWithoutPagination,
|
||||||
|
} = useCreateAssociationDetailsWithoutPagination();
|
||||||
|
const collectionsNeedToDisplay = [currentCollection, ...collectionsWithView];
|
||||||
|
const createBlockSchema = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
if (item.associationField) {
|
||||||
|
if (['hasOne', 'belongsTo'].includes(item.associationField.type)) {
|
||||||
|
return createAssociationDetailsWithoutPagination({ item });
|
||||||
}
|
}
|
||||||
|
return createAssociationDetailsBlock({ item });
|
||||||
|
}
|
||||||
|
return createSingleDetailsSchema({ item });
|
||||||
|
},
|
||||||
|
[createAssociationDetailsBlock, createAssociationDetailsWithoutPagination, createSingleDetailsSchema],
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
filterCollections({ collection, associationField }) {
|
||||||
|
if (collection) {
|
||||||
|
return collectionsNeedToDisplay.some((c) => c.name === collection.name);
|
||||||
|
}
|
||||||
|
if (associationField) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
// hideSearch: true,
|
||||||
|
componentType: 'ReadPrettyFormItem',
|
||||||
|
createBlockSchema,
|
||||||
|
templateWrap: useCallback(
|
||||||
|
(templateSchema, { item }) => {
|
||||||
|
if (item.associationField) {
|
||||||
|
if (['hasOne', 'belongsTo'].includes(item.associationField.type)) {
|
||||||
|
return templateWrapOfAssociationDetailsWithoutPagination(templateSchema, { item });
|
||||||
|
}
|
||||||
|
return templateSchema;
|
||||||
|
}
|
||||||
|
return templateWrap(templateSchema, { item });
|
||||||
|
},
|
||||||
|
[templateWrap, templateWrapOfAssociationDetailsWithoutPagination],
|
||||||
|
),
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'editForm',
|
||||||
|
title: '{{t("Form (Edit)")}}',
|
||||||
|
Component: 'FormBlockInitializer',
|
||||||
|
collectionName: collection.name,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
useComponentProps() {
|
||||||
|
const currentCollection = useCollection_deprecated();
|
||||||
|
const { createEditFormBlock, templateWrap } = useCreateEditFormBlock();
|
||||||
|
const collectionsNeedToDisplay = [currentCollection, ...collectionsWithView];
|
||||||
|
|
||||||
if (hasChildCollection) {
|
return {
|
||||||
res.push({
|
filterCollections({ collection }) {
|
||||||
name: 'form',
|
if (collection) {
|
||||||
type: 'subMenu',
|
return collectionsNeedToDisplay.some((c) => c.name === collection.name);
|
||||||
title: '{{t("Form")}}',
|
|
||||||
children: formChildren,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
modifyFlag &&
|
|
||||||
res.push({
|
|
||||||
name: 'form',
|
|
||||||
title: '{{t("Form")}}',
|
|
||||||
Component: 'RecordFormBlockInitializer',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
// hideSearch: true,
|
||||||
|
componentType: 'FormItem',
|
||||||
|
createBlockSchema: createEditFormBlock,
|
||||||
|
templateWrap: templateWrap,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
useVisible() {
|
||||||
|
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'createForm',
|
||||||
|
title: '{{t("Form (Add new)")}}',
|
||||||
|
Component: 'FormBlockInitializer',
|
||||||
|
collectionName: collection.name,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
useComponentProps() {
|
||||||
|
const { createAssociationFormBlock, templateWrap } = useCreateAssociationFormBlock();
|
||||||
|
return {
|
||||||
|
filterCollections({ collection, associationField }) {
|
||||||
|
if (associationField) {
|
||||||
|
return ['hasMany', 'belongsToMany'].includes(associationField.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
// hideSearch: true,
|
||||||
|
componentType: 'FormItem',
|
||||||
|
createBlockSchema: createAssociationFormBlock,
|
||||||
|
templateWrap: templateWrap,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
useVisible() {
|
||||||
|
const collection = useCollection();
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'table',
|
||||||
|
title: '{{t("Table")}}',
|
||||||
|
Component: 'TableBlockInitializer',
|
||||||
|
useVisible() {
|
||||||
|
const collection = useCollection();
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { createAssociationTableBlock } = useCreateAssociationTableBlock();
|
||||||
|
|
||||||
|
return {
|
||||||
|
// hideSearch: true,
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
filterCollections({ associationField }) {
|
||||||
|
if (associationField) {
|
||||||
|
return ['hasMany', 'belongsToMany'].includes(associationField.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
createBlockSchema: createAssociationTableBlock,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'list',
|
||||||
|
title: '{{t("List")}}',
|
||||||
|
Component: 'ListBlockInitializer',
|
||||||
|
useVisible() {
|
||||||
|
const collection = useCollection();
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { createAssociationListBlock } = useCreateAssociationListBlock();
|
||||||
|
|
||||||
|
return {
|
||||||
|
// hideSearch: true,
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
filterCollections({ associationField }) {
|
||||||
|
if (associationField) {
|
||||||
|
return ['hasMany', 'belongsToMany'].includes(associationField.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
createBlockSchema: createAssociationListBlock,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'gridCard',
|
||||||
|
title: '{{t("Grid Card")}}',
|
||||||
|
Component: 'GridCardBlockInitializer',
|
||||||
|
useVisible() {
|
||||||
|
const collection = useCollection();
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { createAssociationGridCardBlock } = useCreateAssociationGridCardBlock();
|
||||||
|
|
||||||
|
return {
|
||||||
|
// hideSearch: true,
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
filterCollections({ associationField }) {
|
||||||
|
if (associationField) {
|
||||||
|
return ['hasMany', 'belongsToMany'].includes(associationField.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
createBlockSchema: createAssociationGridCardBlock,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -247,8 +268,8 @@ export const recordBlockInitializers_deprecated = new CompatibleSchemaInitialize
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
name: 'currentRecordBlocks',
|
name: 'dataBlocks',
|
||||||
title: '{{t("Current record blocks")}}',
|
title: '{{t("Data blocks")}}',
|
||||||
useChildren: useRecordBlocks,
|
useChildren: useRecordBlocks,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -256,8 +277,14 @@ export const recordBlockInitializers_deprecated = new CompatibleSchemaInitialize
|
|||||||
title: '{{t("Filter blocks")}}',
|
title: '{{t("Filter blocks")}}',
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
useVisible() {
|
useVisible() {
|
||||||
const collection = useCollection_deprecated();
|
const collection = useCollection();
|
||||||
return collection.fields.some((field) => ['hasMany', 'belongsToMany'].includes(field.type));
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@ -272,10 +299,13 @@ export const recordBlockInitializers_deprecated = new CompatibleSchemaInitialize
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filterMenuItemChildren(collection) {
|
filterCollections({ collection }) {
|
||||||
|
if (collection) {
|
||||||
return toManyField.some((field) => field.target === collection.name);
|
return toManyField.some((field) => field.target === collection.name);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
|
showChildren: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -284,32 +314,35 @@ export const recordBlockInitializers_deprecated = new CompatibleSchemaInitialize
|
|||||||
title: '{{t("Collapse")}}',
|
title: '{{t("Collapse")}}',
|
||||||
Component: 'FilterCollapseBlockInitializer',
|
Component: 'FilterCollapseBlockInitializer',
|
||||||
useComponentProps() {
|
useComponentProps() {
|
||||||
const collection = useCollection_deprecated();
|
const collection = useCollection();
|
||||||
const toManyField = useMemo(
|
const toManyField = useMemo(
|
||||||
() => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)),
|
() => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)),
|
||||||
[collection.fields],
|
[collection.fields],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filterMenuItemChildren(collection) {
|
filterCollections({ collection }) {
|
||||||
|
if (collection) {
|
||||||
return toManyField.some((field) => field.target === collection.name);
|
return toManyField.some((field) => field.target === collection.name);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
|
showChildren: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
type: 'itemGroup',
|
// type: 'itemGroup',
|
||||||
name: 'relationshipBlocks',
|
// name: 'relationshipBlocks',
|
||||||
title: '{{t("Relationship blocks")}}',
|
// title: '{{t("Relationship blocks")}}',
|
||||||
useChildren: useRelationFields,
|
// useChildren: useRelationFields,
|
||||||
useVisible() {
|
// useVisible() {
|
||||||
const res = useRelationFields();
|
// const res = useRelationFields();
|
||||||
return res.length > 0;
|
// return res.length > 0;
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
name: 'otherBlocks',
|
name: 'otherBlocks',
|
||||||
@ -334,8 +367,8 @@ export const recordBlockInitializers = new CompatibleSchemaInitializer(
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
name: 'currentRecordBlocks',
|
name: 'dataBlocks',
|
||||||
title: '{{t("Current record blocks")}}',
|
title: '{{t("Data blocks")}}',
|
||||||
useChildren: useRecordBlocks,
|
useChildren: useRecordBlocks,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -343,8 +376,14 @@ export const recordBlockInitializers = new CompatibleSchemaInitializer(
|
|||||||
title: '{{t("Filter blocks")}}',
|
title: '{{t("Filter blocks")}}',
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
useVisible() {
|
useVisible() {
|
||||||
const collection = useCollection_deprecated();
|
const collection = useCollection();
|
||||||
return collection.fields.some((field) => ['hasMany', 'belongsToMany'].includes(field.type));
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@ -359,10 +398,13 @@ export const recordBlockInitializers = new CompatibleSchemaInitializer(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filterMenuItemChildren(collection) {
|
filterCollections({ collection }) {
|
||||||
|
if (collection) {
|
||||||
return toManyField.some((field) => field.target === collection.name);
|
return toManyField.some((field) => field.target === collection.name);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
|
showChildren: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -371,32 +413,35 @@ export const recordBlockInitializers = new CompatibleSchemaInitializer(
|
|||||||
title: '{{t("Collapse")}}',
|
title: '{{t("Collapse")}}',
|
||||||
Component: 'FilterCollapseBlockInitializer',
|
Component: 'FilterCollapseBlockInitializer',
|
||||||
useComponentProps() {
|
useComponentProps() {
|
||||||
const collection = useCollection_deprecated();
|
const collection = useCollection();
|
||||||
const toManyField = useMemo(
|
const toManyField = useMemo(
|
||||||
() => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)),
|
() => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)),
|
||||||
[collection.fields],
|
[collection.fields],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filterMenuItemChildren(collection) {
|
filterCollections({ collection }) {
|
||||||
|
if (collection) {
|
||||||
return toManyField.some((field) => field.target === collection.name);
|
return toManyField.some((field) => field.target === collection.name);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onlyCurrentDataSource: true,
|
onlyCurrentDataSource: true,
|
||||||
|
showChildren: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
type: 'itemGroup',
|
// type: 'itemGroup',
|
||||||
name: 'relationshipBlocks',
|
// name: 'relationshipBlocks',
|
||||||
title: '{{t("Relationship blocks")}}',
|
// title: '{{t("Relationship blocks")}}',
|
||||||
useChildren: useRelationFields,
|
// useChildren: useRelationFields,
|
||||||
useVisible() {
|
// useVisible() {
|
||||||
const res = useRelationFields();
|
// const res = useRelationFields();
|
||||||
return res.length > 0;
|
// return res.length > 0;
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
name: 'otherBlocks',
|
name: 'otherBlocks',
|
||||||
|
@ -124,6 +124,7 @@ export {
|
|||||||
createFilterFormBlockSchema,
|
createFilterFormBlockSchema,
|
||||||
createFormBlockSchema,
|
createFormBlockSchema,
|
||||||
createReadPrettyFormBlockSchema,
|
createReadPrettyFormBlockSchema,
|
||||||
|
createDetailsBlockSchema,
|
||||||
createTableBlockSchema,
|
createTableBlockSchema,
|
||||||
gridRowColWrap,
|
gridRowColWrap,
|
||||||
itemsMerge,
|
itemsMerge,
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
useGetSchemaInitializerMenuItems,
|
useGetSchemaInitializerMenuItems,
|
||||||
useSchemaInitializer,
|
useSchemaInitializer,
|
||||||
} from '../../application';
|
} from '../../application';
|
||||||
import { Collection } from '../../data-source/collection/Collection';
|
import { Collection, CollectionFieldOptions } from '../../data-source/collection/Collection';
|
||||||
import { useCompile } from '../../schema-component';
|
import { useCompile } from '../../schema-component';
|
||||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||||
import { useCollectionDataSourceItems } from '../utils';
|
import { useCollectionDataSourceItems } from '../utils';
|
||||||
@ -109,7 +109,17 @@ const LoadingItem = ({ loadMore, maxHeight }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useMenuSearch(data: any[], openKeys: string[], showType?: boolean) {
|
export function useMenuSearch({
|
||||||
|
data,
|
||||||
|
openKeys,
|
||||||
|
showType,
|
||||||
|
hideSearch,
|
||||||
|
}: {
|
||||||
|
data: any[];
|
||||||
|
openKeys: string[];
|
||||||
|
showType?: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
}) {
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [count, setCount] = useState(STEP);
|
const [count, setCount] = useState(STEP);
|
||||||
|
|
||||||
@ -154,9 +164,10 @@ export function useMenuSearch(data: any[], openKeys: string[], showType?: boolea
|
|||||||
|
|
||||||
// 最终的返回结果
|
// 最终的返回结果
|
||||||
const resultItems = useMemo<MenuProps['items']>(() => {
|
const resultItems = useMemo<MenuProps['items']>(() => {
|
||||||
// isMenuType 为了 `useSchemaInitializerMenuItems()` 里面处理判断标识的
|
const res = [];
|
||||||
const res: any[] = [
|
if (!hideSearch) {
|
||||||
// 开头:搜索框
|
// 开头:搜索框
|
||||||
|
res.push(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{
|
{
|
||||||
key: 'search',
|
key: 'search',
|
||||||
@ -173,9 +184,11 @@ export function useMenuSearch(data: any[], openKeys: string[], showType?: boolea
|
|||||||
domEvent.stopPropagation();
|
domEvent.stopPropagation();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// isMenuType 为了 `useSchemaInitializerMenuItems()` 里面处理判断标识的
|
||||||
showType ? { isMenuType: true } : {},
|
showType ? { isMenuType: true } : {},
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 中间:搜索的数据
|
// 中间:搜索的数据
|
||||||
if (limitedSearchedItems.length > 0) {
|
if (limitedSearchedItems.length > 0) {
|
||||||
@ -220,7 +233,7 @@ export function useMenuSearch(data: any[], openKeys: string[], showType?: boolea
|
|||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}, [limitedSearchedItems, searchValue, shouldLoadMore, showType]);
|
}, [hideSearch, limitedSearchedItems, searchValue, shouldLoadMore, showType]);
|
||||||
|
|
||||||
const res = useMemo(() => {
|
const res = useMemo(() => {
|
||||||
if (!isMuliSource) return resultItems;
|
if (!isMuliSource) return resultItems;
|
||||||
@ -237,7 +250,7 @@ export function useMenuSearch(data: any[], openKeys: string[], showType?: boolea
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [data, openKey, resultItems]);
|
}, [data, isMuliSource, openKey, resultItems]);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,13 +265,16 @@ export interface DataBlockInitializerProps {
|
|||||||
) => any;
|
) => any;
|
||||||
onCreateBlockSchema?: (args: any) => void;
|
onCreateBlockSchema?: (args: any) => void;
|
||||||
createBlockSchema?: (args: any) => any;
|
createBlockSchema?: (args: any) => any;
|
||||||
isCusomeizeCreate?: boolean;
|
|
||||||
icon?: string | React.ReactNode;
|
icon?: string | React.ReactNode;
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
filter?: (collection: Collection) => boolean;
|
filter?: (options: { collection: Collection; associationField: CollectionFieldOptions }) => boolean;
|
||||||
componentType: string;
|
componentType: string;
|
||||||
onlyCurrentDataSource?: boolean;
|
onlyCurrentDataSource?: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
/** 即使 children 只有一个时,也显示出来 */
|
||||||
|
showChildren?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||||
@ -266,13 +282,14 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
|||||||
templateWrap,
|
templateWrap,
|
||||||
onCreateBlockSchema,
|
onCreateBlockSchema,
|
||||||
componentType,
|
componentType,
|
||||||
createBlockSchema,
|
|
||||||
isCusomeizeCreate,
|
|
||||||
icon = TableOutlined,
|
icon = TableOutlined,
|
||||||
name,
|
name,
|
||||||
title,
|
title,
|
||||||
filter,
|
filter,
|
||||||
onlyCurrentDataSource,
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
showAssociationFields,
|
||||||
|
showChildren,
|
||||||
} = props;
|
} = props;
|
||||||
const { insert, setVisible } = useSchemaInitializer();
|
const { insert, setVisible } = useSchemaInitializer();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
@ -285,30 +302,34 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
|||||||
} else {
|
} else {
|
||||||
if (onCreateBlockSchema) {
|
if (onCreateBlockSchema) {
|
||||||
onCreateBlockSchema({ item });
|
onCreateBlockSchema({ item });
|
||||||
} else if (createBlockSchema) {
|
|
||||||
insert(
|
|
||||||
createBlockSchema({
|
|
||||||
collection: item.collectionName || item.name,
|
|
||||||
dataSource: item.dataSource,
|
|
||||||
isCusomeizeCreate,
|
|
||||||
settings: 'blockSettings:createForm',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
},
|
},
|
||||||
[createBlockSchema, getTemplateSchemaByMode, insert, isCusomeizeCreate, onCreateBlockSchema, templateWrap],
|
[getTemplateSchemaByMode, insert, onCreateBlockSchema, setVisible, templateWrap],
|
||||||
);
|
);
|
||||||
const items = useCollectionDataSourceItems(componentType, filter, onlyCurrentDataSource);
|
const items = useCollectionDataSourceItems({
|
||||||
|
componentName: componentType,
|
||||||
|
filter,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
showAssociationFields,
|
||||||
|
});
|
||||||
const getMenuItems = useGetSchemaInitializerMenuItems(onClick);
|
const getMenuItems = useGetSchemaInitializerMenuItems(onClick);
|
||||||
const childItems = useMemo(() => {
|
const childItems = useMemo(() => {
|
||||||
return getMenuItems(items, name);
|
return getMenuItems(items, name);
|
||||||
}, [getMenuItems, items, name]);
|
}, [getMenuItems, items, name]);
|
||||||
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
||||||
const searchedChildren = useMenuSearch(childItems, openMenuKeys);
|
const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys, hideSearch });
|
||||||
const compiledMenuItems = useMemo(
|
const compiledMenuItems = useMemo(() => {
|
||||||
() => [
|
let children = searchedChildren.filter((item) => item.key !== 'search' && item.key !== 'empty');
|
||||||
|
const hasAssociationField = children.some((item) => item.associationField);
|
||||||
|
if (!showChildren && !hasAssociationField && children.length === 1) {
|
||||||
|
// 只有一项可选时,直接展开
|
||||||
|
children = children[0].children;
|
||||||
|
} else {
|
||||||
|
children = searchedChildren;
|
||||||
|
}
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
key: name,
|
key: name,
|
||||||
label: compile(title),
|
label: compile(title),
|
||||||
@ -317,11 +338,10 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
|||||||
if (info.key !== name) return;
|
if (info.key !== name) return;
|
||||||
onClick({ ...info, item: props });
|
onClick({ ...info, item: props });
|
||||||
},
|
},
|
||||||
children: searchedChildren,
|
children,
|
||||||
},
|
},
|
||||||
],
|
];
|
||||||
[name, compile, title, icon, childItems, onClick, props],
|
}, [name, compile, title, icon, searchedChildren, onClick, props]);
|
||||||
);
|
|
||||||
|
|
||||||
if (childItems.length > 1 || (childItems.length === 1 && childItems[0].children?.length > 0)) {
|
if (childItems.length > 1 || (childItems.length === 1 && childItems[0].children?.length > 0)) {
|
||||||
return (
|
return (
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { TableOutlined } from '@ant-design/icons';
|
import { TableOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
@ -6,6 +6,9 @@ import { useSchemaTemplateManager } from '../../schema-templates';
|
|||||||
import { createTableBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
import { createTableBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const RecordAssociationBlockInitializer = () => {
|
export const RecordAssociationBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
||||||
@ -39,3 +42,27 @@ export const RecordAssociationBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationTableBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
|
||||||
|
const createAssociationTableBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createTableBlockSchema({
|
||||||
|
rowKey: collection.filterTargetKey,
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationTableBlock };
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
@ -40,3 +40,28 @@ export const RecordAssociationDetailsBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationDetailsBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
|
||||||
|
const createAssociationDetailsBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createDetailsBlockSchema({
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
rowKey: collection.filterTargetKey || 'id',
|
||||||
|
settings: 'blockSettings:multiDataDetails',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationDetailsBlock };
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
@ -6,6 +6,9 @@ import { useSchemaTemplateManager } from '../../schema-templates';
|
|||||||
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const RecordAssociationFormBlockInitializer = () => {
|
export const RecordAssociationFormBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
||||||
@ -27,7 +30,7 @@ export const RecordAssociationFormBlockInitializer = () => {
|
|||||||
: 'createForm:configureActions';
|
: 'createForm:configureActions';
|
||||||
|
|
||||||
if (item.template) {
|
if (item.template) {
|
||||||
const s = await getTemplateSchemaByMode(item);
|
const template = await getTemplateSchemaByMode(item);
|
||||||
if (item.template.componentName === 'FormItem') {
|
if (item.template.componentName === 'FormItem') {
|
||||||
const blockSchema = createFormBlockSchema({
|
const blockSchema = createFormBlockSchema({
|
||||||
collection: collectionName,
|
collection: collectionName,
|
||||||
@ -38,7 +41,7 @@ export const RecordAssociationFormBlockInitializer = () => {
|
|||||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
useParams: '{{ useParamsFromRecord }}',
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
actionInitializers,
|
actionInitializers,
|
||||||
template: s,
|
template: template,
|
||||||
settings: 'blockSettings:createForm',
|
settings: 'blockSettings:createForm',
|
||||||
});
|
});
|
||||||
if (item.mode === 'reference') {
|
if (item.mode === 'reference') {
|
||||||
@ -46,7 +49,7 @@ export const RecordAssociationFormBlockInitializer = () => {
|
|||||||
}
|
}
|
||||||
insert(blockSchema);
|
insert(blockSchema);
|
||||||
} else {
|
} else {
|
||||||
insert(s);
|
insert(template);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
insert(
|
insert(
|
||||||
@ -68,3 +71,67 @@ export const RecordAssociationFormBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationFormBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
|
||||||
|
const createAssociationFormBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
const action = ['hasOne', 'belongsTo'].includes(field.type) ? 'get' : null;
|
||||||
|
const actionInitializers = ['hasOne', 'belongsTo'].includes(field.type)
|
||||||
|
? 'editForm:configureActions'
|
||||||
|
: 'createForm:configureActions';
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createFormBlockSchema({
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
action,
|
||||||
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
|
actionInitializers,
|
||||||
|
settings: 'blockSettings:createForm',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
const templateWrap = useCallback(
|
||||||
|
(templateSchema, { item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const action = ['hasOne', 'belongsTo'].includes(field.type) ? 'get' : null;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
const actionInitializers = ['hasOne', 'belongsTo'].includes(field.type)
|
||||||
|
? 'editForm:configureActions'
|
||||||
|
: 'createForm:configureActions';
|
||||||
|
|
||||||
|
if (item.template.componentName === 'FormItem') {
|
||||||
|
const blockSchema = createFormBlockSchema({
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
action,
|
||||||
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
|
actionInitializers,
|
||||||
|
template: templateSchema,
|
||||||
|
settings: 'blockSettings:createForm',
|
||||||
|
});
|
||||||
|
if (item.mode === 'reference') {
|
||||||
|
blockSchema['x-template-key'] = item.template.key;
|
||||||
|
}
|
||||||
|
return blockSchema;
|
||||||
|
} else {
|
||||||
|
return templateSchema;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[getCollection],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationFormBlock, templateWrap };
|
||||||
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { TableOutlined } from '@ant-design/icons';
|
import { TableOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||||
import { createGridCardBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
import { createGridCardBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const RecordAssociationGridCardBlockInitializer = () => {
|
export const RecordAssociationGridCardBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
||||||
@ -41,3 +44,28 @@ export const RecordAssociationGridCardBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationGridCardBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
|
||||||
|
const createAssociationGridCardBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createGridCardBlockSchema({
|
||||||
|
rowKey: collection.filterTargetKey,
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
settings: 'blockSettings:gridCard',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationGridCardBlock };
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { TableOutlined } from '@ant-design/icons';
|
import { TableOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
@ -41,3 +41,28 @@ export const RecordAssociationListBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationListBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
|
||||||
|
const createAssociationListBlock = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createListBlockSchema({
|
||||||
|
rowKey: collection.filterTargetKey,
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
settings: 'blockSettings:list',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationListBlock };
|
||||||
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
import { FormOutlined } from '@ant-design/icons';
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||||
import { useBlockRequestContext } from '../../block-provider';
|
import { useBlockRequestContext } from '../../block-provider';
|
||||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||||
import { createReadPrettyFormBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
import { createDetailsBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
||||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const RecordReadPrettyAssociationFormBlockInitializer = () => {
|
export const RecordReadPrettyAssociationFormBlockInitializer = () => {
|
||||||
const itemConfig = useSchemaInitializerItem();
|
const itemConfig = useSchemaInitializerItem();
|
||||||
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
const { onCreateBlockSchema, componentType, createBlockSchema, ...others } = itemConfig;
|
||||||
@ -30,7 +33,7 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
|
|||||||
if (item.template) {
|
if (item.template) {
|
||||||
const s = await getTemplateSchemaByMode(item);
|
const s = await getTemplateSchemaByMode(item);
|
||||||
if (item.template.componentName === 'ReadPrettyFormItem') {
|
if (item.template.componentName === 'ReadPrettyFormItem') {
|
||||||
const blockSchema = createReadPrettyFormBlockSchema({
|
const blockSchema = createDetailsBlockSchema({
|
||||||
actionInitializers,
|
actionInitializers,
|
||||||
collection: collectionName,
|
collection: collectionName,
|
||||||
dataSource: collection.dataSource,
|
dataSource: collection.dataSource,
|
||||||
@ -51,7 +54,7 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
insert(
|
insert(
|
||||||
createReadPrettyFormBlockSchema({
|
createDetailsBlockSchema({
|
||||||
actionInitializers,
|
actionInitializers,
|
||||||
collection: collectionName,
|
collection: collectionName,
|
||||||
resource,
|
resource,
|
||||||
@ -69,3 +72,61 @@ export const RecordReadPrettyAssociationFormBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationDetailsWithoutPagination() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
const { block } = useBlockRequestContext();
|
||||||
|
const actionInitializers = block !== 'TableField' ? 'details:configureActions' : null;
|
||||||
|
|
||||||
|
const createAssociationDetailsWithoutPagination = useCallback(
|
||||||
|
({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
insert(
|
||||||
|
createDetailsBlockSchema({
|
||||||
|
actionInitializers,
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
action: 'get',
|
||||||
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
|
settings: 'blockSettings:singleDataDetails',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[actionInitializers, getCollection, insert],
|
||||||
|
);
|
||||||
|
|
||||||
|
const templateWrap = useCallback(
|
||||||
|
(templateSchema, { item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
if (item.template.componentName === 'ReadPrettyFormItem') {
|
||||||
|
const blockSchema = createDetailsBlockSchema({
|
||||||
|
actionInitializers,
|
||||||
|
collection: field.target,
|
||||||
|
dataSource: collection.dataSource,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
action: 'get',
|
||||||
|
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||||
|
useParams: '{{ useParamsFromRecord }}',
|
||||||
|
template: templateSchema,
|
||||||
|
settings: 'blockSettings:singleDataDetails',
|
||||||
|
});
|
||||||
|
if (item.mode === 'reference') {
|
||||||
|
blockSchema['x-template-key'] = item.template.key;
|
||||||
|
}
|
||||||
|
return blockSchema;
|
||||||
|
} else {
|
||||||
|
return templateSchema;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[actionInitializers, getCollection],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { createAssociationDetailsWithoutPagination, templateWrap };
|
||||||
|
}
|
||||||
|
@ -3,14 +3,21 @@ import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SchemaInitializerItemType, useDataSourceKey, useFormActiveFields, useFormBlockContext } from '../';
|
import {
|
||||||
|
SchemaInitializerItemType,
|
||||||
|
useCollection,
|
||||||
|
useCollectionManager,
|
||||||
|
useDataSourceKey,
|
||||||
|
useFormActiveFields,
|
||||||
|
useFormBlockContext,
|
||||||
|
} from '../';
|
||||||
import { FieldOptions, useCollection_deprecated, useCollectionManager_deprecated } from '../collection-manager';
|
import { FieldOptions, useCollection_deprecated, useCollectionManager_deprecated } from '../collection-manager';
|
||||||
import { isAssocField } from '../filter-provider/utils';
|
import { isAssocField } from '../filter-provider/utils';
|
||||||
import { useActionContext, useDesignable } from '../schema-component';
|
import { useActionContext, useCompile, useDesignable } from '../schema-component';
|
||||||
import { useSchemaTemplateManager } from '../schema-templates';
|
import { useSchemaTemplateManager } from '../schema-templates';
|
||||||
import { Collection } from '../data-source/collection/Collection';
|
import { Collection, CollectionFieldOptions } from '../data-source/collection/Collection';
|
||||||
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
|
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
|
||||||
import { DataSourceManager } from '../data-source/data-source/DataSourceManager';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export const itemsMerge = (items1) => {
|
export const itemsMerge = (items1) => {
|
||||||
return items1;
|
return items1;
|
||||||
@ -750,6 +757,10 @@ export const useCurrentSchema = (action: string, key: string, find = findSchema,
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* 待统一区块的创建之后,将废弃该方法
|
||||||
|
*/
|
||||||
export const useRecordCollectionDataSourceItems = (
|
export const useRecordCollectionDataSourceItems = (
|
||||||
componentName,
|
componentName,
|
||||||
item = null,
|
item = null,
|
||||||
@ -822,15 +833,29 @@ export const useRecordCollectionDataSourceItems = (
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCollectionDataSourceItems = (
|
export const useCollectionDataSourceItems = ({
|
||||||
componentName,
|
componentName,
|
||||||
filter: (collection: Collection) => boolean = () => true,
|
filter = () => true,
|
||||||
onlyCurrentDataSource = false,
|
onlyCurrentDataSource = false,
|
||||||
) => {
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
componentName;
|
||||||
|
filter?: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource?: boolean;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dm = useDataSourceManager();
|
const dm = useDataSourceManager();
|
||||||
const dataSourceKey = useDataSourceKey();
|
const dataSourceKey = useDataSourceKey();
|
||||||
let allCollections = dm.getAllCollections(filter);
|
const collection = useCollection();
|
||||||
|
const associationFields = useAssociationFields({ componentName, filterCollections: filter, showAssociationFields });
|
||||||
|
|
||||||
|
let allCollections = dm.getAllCollections((collection) => {
|
||||||
|
if (onlyCurrentDataSource && collection.dataSource !== dataSourceKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return filter({ collection });
|
||||||
|
});
|
||||||
if (onlyCurrentDataSource) {
|
if (onlyCurrentDataSource) {
|
||||||
allCollections = allCollections.filter((collection) => collection.key === dataSourceKey);
|
allCollections = allCollections.filter((collection) => collection.key === dataSourceKey);
|
||||||
}
|
}
|
||||||
@ -841,16 +866,23 @@ export const useCollectionDataSourceItems = (
|
|||||||
name: key,
|
name: key,
|
||||||
label: displayName,
|
label: displayName,
|
||||||
type: 'subMenu',
|
type: 'subMenu',
|
||||||
children: getChildren({
|
children: [
|
||||||
|
...getChildren({
|
||||||
collections,
|
collections,
|
||||||
componentName,
|
componentName,
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
dataSource: key,
|
dataSource: key,
|
||||||
getTemplatesByCollection,
|
getTemplatesByCollection,
|
||||||
t,
|
t,
|
||||||
|
}).sort((item) => {
|
||||||
|
// fix https://nocobase.height.app/T-3551
|
||||||
|
const inherits = _.toArray(collection?.inherits || []);
|
||||||
|
if (item.name === collection?.name || inherits.some((inheritName) => inheritName === item.name)) return -1;
|
||||||
}),
|
}),
|
||||||
|
...associationFields,
|
||||||
|
],
|
||||||
}));
|
}));
|
||||||
}, [allCollections, componentName, dm, getTemplatesByCollection, t]);
|
}, [allCollections, associationFields, componentName, getTemplatesByCollection, t]);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
@ -862,27 +894,29 @@ export const createDetailsBlockSchema = (options) => {
|
|||||||
collection,
|
collection,
|
||||||
dataSource,
|
dataSource,
|
||||||
association,
|
association,
|
||||||
resource,
|
|
||||||
template,
|
template,
|
||||||
settings,
|
settings,
|
||||||
|
action = 'list',
|
||||||
...others
|
...others
|
||||||
} = options;
|
} = options;
|
||||||
const resourceName = resource || association || collection;
|
const resourceName = association || collection;
|
||||||
const schema: ISchema = {
|
const schema: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-acl-action': `${resourceName}:view`,
|
'x-acl-action': action === 'get' ? `${resourceName}:get` : `${resourceName}:view`,
|
||||||
'x-decorator': 'DetailsBlockProvider',
|
'x-decorator': 'DetailsBlockProvider',
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
resource: resourceName,
|
|
||||||
dataSource,
|
dataSource,
|
||||||
collection,
|
collection,
|
||||||
association,
|
association,
|
||||||
readPretty: true,
|
readPretty: true,
|
||||||
action: 'list',
|
action,
|
||||||
|
...(action === 'list'
|
||||||
|
? {
|
||||||
params: {
|
params: {
|
||||||
pageSize: 1,
|
pageSize: 1,
|
||||||
},
|
},
|
||||||
// useParams: '{{ useParamsFromRecord }}',
|
}
|
||||||
|
: {}),
|
||||||
...others,
|
...others,
|
||||||
},
|
},
|
||||||
'x-toolbar': 'BlockSchemaToolbar',
|
'x-toolbar': 'BlockSchemaToolbar',
|
||||||
@ -914,6 +948,8 @@ export const createDetailsBlockSchema = (options) => {
|
|||||||
'x-initializer': formItemInitializers,
|
'x-initializer': formItemInitializers,
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
|
...(action === 'list'
|
||||||
|
? {
|
||||||
pagination: {
|
pagination: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Pagination',
|
'x-component': 'Pagination',
|
||||||
@ -921,6 +957,8 @@ export const createDetailsBlockSchema = (options) => {
|
|||||||
useProps: '{{ useDetailsPaginationProps }}',
|
useProps: '{{ useDetailsPaginationProps }}',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -936,18 +974,16 @@ export const createListBlockSchema = (options) => {
|
|||||||
collection,
|
collection,
|
||||||
dataSource,
|
dataSource,
|
||||||
association,
|
association,
|
||||||
resource,
|
|
||||||
template,
|
template,
|
||||||
settings,
|
settings,
|
||||||
...others
|
...others
|
||||||
} = options;
|
} = options;
|
||||||
const resourceName = resource || association || collection;
|
const resourceName = association || collection;
|
||||||
const schema: ISchema = {
|
const schema: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-acl-action': `${resourceName}:view`,
|
'x-acl-action': `${resourceName}:view`,
|
||||||
'x-decorator': 'List.Decorator',
|
'x-decorator': 'List.Decorator',
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
resource: resourceName,
|
|
||||||
collection,
|
collection,
|
||||||
dataSource,
|
dataSource,
|
||||||
association,
|
association,
|
||||||
@ -1025,19 +1061,17 @@ export const createGridCardBlockSchema = (options) => {
|
|||||||
itemActionInitializers = 'gridCard:configureItemActions',
|
itemActionInitializers = 'gridCard:configureItemActions',
|
||||||
collection,
|
collection,
|
||||||
association,
|
association,
|
||||||
resource,
|
|
||||||
template,
|
template,
|
||||||
dataSource,
|
dataSource,
|
||||||
settings,
|
settings,
|
||||||
...others
|
...others
|
||||||
} = options;
|
} = options;
|
||||||
const resourceName = resource || association || collection;
|
const resourceName = association || collection;
|
||||||
const schema: ISchema = {
|
const schema: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-acl-action': `${resourceName}:view`,
|
'x-acl-action': `${resourceName}:view`,
|
||||||
'x-decorator': 'GridCard.Decorator',
|
'x-decorator': 'GridCard.Decorator',
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
resource: resourceName,
|
|
||||||
collection,
|
collection,
|
||||||
association,
|
association,
|
||||||
dataSource,
|
dataSource,
|
||||||
@ -1248,6 +1282,12 @@ export const createFilterFormBlockSchema = (options) => {
|
|||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* 已弃用,可以使用 createDetailsBlockSchema 替换
|
||||||
|
* @param options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const createReadPrettyFormBlockSchema = (options) => {
|
export const createReadPrettyFormBlockSchema = (options) => {
|
||||||
const {
|
const {
|
||||||
formItemInitializers = 'details:configureFields',
|
formItemInitializers = 'details:configureFields',
|
||||||
@ -1315,7 +1355,6 @@ export const createReadPrettyFormBlockSchema = (options) => {
|
|||||||
export const createTableBlockSchema = (options) => {
|
export const createTableBlockSchema = (options) => {
|
||||||
const {
|
const {
|
||||||
collection,
|
collection,
|
||||||
resource,
|
|
||||||
rowKey,
|
rowKey,
|
||||||
tableActionInitializers,
|
tableActionInitializers,
|
||||||
tableColumnInitializers,
|
tableColumnInitializers,
|
||||||
@ -1330,11 +1369,10 @@ export const createTableBlockSchema = (options) => {
|
|||||||
const schema: ISchema = {
|
const schema: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-decorator': tableBlockProvider ?? 'TableBlockProvider',
|
'x-decorator': tableBlockProvider ?? 'TableBlockProvider',
|
||||||
'x-acl-action': `${resource || collection}:list`,
|
'x-acl-action': `${collection}:list`,
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
collection,
|
collection,
|
||||||
dataSource,
|
dataSource,
|
||||||
resource: resource || collection,
|
|
||||||
action: 'list',
|
action: 'list',
|
||||||
params: {
|
params: {
|
||||||
pageSize,
|
pageSize,
|
||||||
@ -1526,7 +1564,9 @@ const getChildren = ({
|
|||||||
return (
|
return (
|
||||||
componentName &&
|
componentName &&
|
||||||
template.componentName === componentName &&
|
template.componentName === componentName &&
|
||||||
(!template.resourceName || template.resourceName === item.name)
|
(['FormItem', 'ReadPrettyFormItem'].includes(componentName) ||
|
||||||
|
!template.resourceName ||
|
||||||
|
template.resourceName === item.name)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (!templates.length) {
|
if (!templates.length) {
|
||||||
@ -1560,8 +1600,9 @@ const getChildren = ({
|
|||||||
dataSource,
|
dataSource,
|
||||||
title: t('Duplicate template'),
|
title: t('Duplicate template'),
|
||||||
children: templates.map((template) => {
|
children: templates.map((template) => {
|
||||||
const templateName =
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
||||||
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
|
? `${template?.name} ${t('(Fields only)')}`
|
||||||
|
: template?.name;
|
||||||
return {
|
return {
|
||||||
type: 'item',
|
type: 'item',
|
||||||
mode: 'copy',
|
mode: 'copy',
|
||||||
@ -1579,8 +1620,9 @@ const getChildren = ({
|
|||||||
dataSource,
|
dataSource,
|
||||||
title: t('Reference template'),
|
title: t('Reference template'),
|
||||||
children: templates.map((template) => {
|
children: templates.map((template) => {
|
||||||
const templateName =
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
||||||
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
|
? `${template?.name} ${t('(Fields only)')}`
|
||||||
|
: template?.name;
|
||||||
return {
|
return {
|
||||||
type: 'item',
|
type: 'item',
|
||||||
mode: 'reference',
|
mode: 'reference',
|
||||||
@ -1595,3 +1637,142 @@ const getChildren = ({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function useAssociationFields({
|
||||||
|
componentName,
|
||||||
|
filterCollections,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
componentName: string;
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { getCollectionFields } = useCollectionManager_deprecated();
|
||||||
|
const collection = useCollection_deprecated();
|
||||||
|
const cm = useCollectionManager();
|
||||||
|
const dataSource = useDataSourceKey();
|
||||||
|
const { getTemplatesByCollection } = useSchemaTemplateManager();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const compile = useCompile();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!showAssociationFields) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let fields: CollectionFieldOptions[] = [];
|
||||||
|
|
||||||
|
if (fieldSchema['x-initializer']) {
|
||||||
|
fields = collection.fields;
|
||||||
|
} else {
|
||||||
|
const collection = recursiveParent(fieldSchema.parent);
|
||||||
|
if (collection) {
|
||||||
|
fields = getCollectionFields(collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields
|
||||||
|
.filter((field) => ['linkTo', 'subTable', 'o2m', 'm2m', 'obo', 'oho', 'o2o', 'm2o'].includes(field.interface))
|
||||||
|
.filter((field) => filterCollections({ associationField: field }))
|
||||||
|
.map((field, index) => {
|
||||||
|
const targetCollection = cm.getCollection(field.target);
|
||||||
|
const title = `${compile(field.uiSchema.title || field.name)} -> ${compile(targetCollection.title)}`;
|
||||||
|
const templates = getTemplatesByCollection(dataSource, field.target).filter((template) => {
|
||||||
|
return (
|
||||||
|
componentName &&
|
||||||
|
template.componentName === componentName &&
|
||||||
|
(['FormItem', 'ReadPrettyFormItem'].includes(componentName) ||
|
||||||
|
!template.resourceName ||
|
||||||
|
template.resourceName === `${field.collectionName}.${field.name}`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (!templates.length) {
|
||||||
|
return {
|
||||||
|
type: 'item',
|
||||||
|
name: `${field.collectionName}.${field.name}`,
|
||||||
|
collectionName: field.target,
|
||||||
|
title,
|
||||||
|
dataSource,
|
||||||
|
associationField: field,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: `${componentName}_table_subMenu_${index}`,
|
||||||
|
type: 'subMenu',
|
||||||
|
name: `${field.target}_${index}`,
|
||||||
|
title,
|
||||||
|
dataSource,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
name: `${field.collectionName}.${field.name}`,
|
||||||
|
collectionName: field.target,
|
||||||
|
dataSource,
|
||||||
|
title: t('Blank block'),
|
||||||
|
associationField: field,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: `${componentName}_table_subMenu_${index}_copy`,
|
||||||
|
type: 'subMenu',
|
||||||
|
name: 'copy',
|
||||||
|
dataSource,
|
||||||
|
title: t('Duplicate template'),
|
||||||
|
children: templates.map((template) => {
|
||||||
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
||||||
|
? `${template?.name} ${t('(Fields only)')}`
|
||||||
|
: template?.name;
|
||||||
|
return {
|
||||||
|
type: 'item',
|
||||||
|
mode: 'copy',
|
||||||
|
name: `${field.collectionName}.${field.name}`,
|
||||||
|
collectionName: field.target,
|
||||||
|
template,
|
||||||
|
dataSource,
|
||||||
|
title: templateName || t('Untitled'),
|
||||||
|
associationField: field,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: `${componentName}_table_subMenu_${index}_ref`,
|
||||||
|
type: 'subMenu',
|
||||||
|
name: 'ref',
|
||||||
|
dataSource,
|
||||||
|
title: t('Reference template'),
|
||||||
|
children: templates.map((template) => {
|
||||||
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
||||||
|
? `${template?.name} ${t('(Fields only)')}`
|
||||||
|
: template?.name;
|
||||||
|
return {
|
||||||
|
type: 'item',
|
||||||
|
mode: 'reference',
|
||||||
|
name: `${field.collectionName}.${field.name}`,
|
||||||
|
collectionName: field.target,
|
||||||
|
template,
|
||||||
|
dataSource,
|
||||||
|
title: templateName || t('Untitled'),
|
||||||
|
associationField: field,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, [
|
||||||
|
cm,
|
||||||
|
collection.fields,
|
||||||
|
compile,
|
||||||
|
componentName,
|
||||||
|
dataSource,
|
||||||
|
fieldSchema,
|
||||||
|
filterCollections,
|
||||||
|
getCollectionFields,
|
||||||
|
getTemplatesByCollection,
|
||||||
|
showAssociationFields,
|
||||||
|
t,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Plugin } from '@nocobase/client';
|
import { Plugin, canMakeAssociationBlock, useCollection } from '@nocobase/client';
|
||||||
import { generateNTemplate } from '../locale';
|
import { generateNTemplate } from '../locale';
|
||||||
import { CalendarV2 } from './calendar';
|
import { CalendarV2 } from './calendar';
|
||||||
import { calendarBlockSettings } from './calendar/Calender.Settings';
|
import { calendarBlockSettings } from './calendar/Calender.Settings';
|
||||||
@ -10,7 +10,12 @@ import {
|
|||||||
calendarActionInitializers,
|
calendarActionInitializers,
|
||||||
deleteEventActionInitializer,
|
deleteEventActionInitializer,
|
||||||
} from './schema-initializer/initializers';
|
} from './schema-initializer/initializers';
|
||||||
import { CalendarBlockInitializer, RecordAssociationCalendarBlockInitializer } from './schema-initializer/items';
|
import {
|
||||||
|
CalendarBlockInitializer,
|
||||||
|
RecordAssociationCalendarBlockInitializer,
|
||||||
|
useCreateAssociationCalendarBlock,
|
||||||
|
} from './schema-initializer/items';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export class PluginCalendarClient extends Plugin {
|
export class PluginCalendarClient extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
@ -19,9 +24,39 @@ export class PluginCalendarClient extends Plugin {
|
|||||||
title: generateNTemplate('Calendar'),
|
title: generateNTemplate('Calendar'),
|
||||||
Component: 'CalendarBlockInitializer',
|
Component: 'CalendarBlockInitializer',
|
||||||
});
|
});
|
||||||
|
this.app.schemaInitializerManager.addItem('popup:common:addBlock', 'dataBlocks.calendar', {
|
||||||
|
title: generateNTemplate('Calendar'),
|
||||||
|
Component: 'CalendarBlockInitializer',
|
||||||
|
useVisible() {
|
||||||
|
const collection = useCollection();
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
collection.fields.some(
|
||||||
|
(field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type),
|
||||||
|
),
|
||||||
|
[collection.fields],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { createAssociationCalendarBlock } = useCreateAssociationCalendarBlock();
|
||||||
|
|
||||||
|
return {
|
||||||
|
onlyCurrentDataSource: true,
|
||||||
|
filterCollections({ associationField }) {
|
||||||
|
if (associationField) {
|
||||||
|
return ['hasMany', 'belongsToMany'].includes(associationField.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
createBlockSchema: createAssociationCalendarBlock,
|
||||||
|
showAssociationFields: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.app.addComponents({
|
this.app.addComponents({
|
||||||
CalendarBlockProvider,
|
CalendarBlockProvider,
|
||||||
CalendarBlockInitializer,
|
CalendarBlockInitializer: CalendarBlockInitializer as any,
|
||||||
RecordAssociationCalendarBlockInitializer,
|
RecordAssociationCalendarBlockInitializer,
|
||||||
CalendarV2,
|
CalendarV2,
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,8 @@ import { FormOutlined } from '@ant-design/icons';
|
|||||||
import { FormLayout } from '@formily/antd-v5';
|
import { FormLayout } from '@formily/antd-v5';
|
||||||
import { SchemaOptionsContext } from '@formily/react';
|
import { SchemaOptionsContext } from '@formily/react';
|
||||||
import {
|
import {
|
||||||
|
Collection,
|
||||||
|
CollectionFieldOptions,
|
||||||
DataBlockInitializer,
|
DataBlockInitializer,
|
||||||
FormDialog,
|
FormDialog,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
@ -15,7 +17,19 @@ import React, { useContext } from 'react';
|
|||||||
import { createCalendarBlockSchema } from '../utils';
|
import { createCalendarBlockSchema } from '../utils';
|
||||||
import { useTranslation } from '../../../locale';
|
import { useTranslation } from '../../../locale';
|
||||||
|
|
||||||
export const CalendarBlockInitializer = () => {
|
export const CalendarBlockInitializer = ({
|
||||||
|
filterCollections,
|
||||||
|
onlyCurrentDataSource,
|
||||||
|
hideSearch,
|
||||||
|
createBlockSchema,
|
||||||
|
showAssociationFields,
|
||||||
|
}: {
|
||||||
|
filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean;
|
||||||
|
onlyCurrentDataSource: boolean;
|
||||||
|
hideSearch?: boolean;
|
||||||
|
createBlockSchema?: (options: any) => any;
|
||||||
|
showAssociationFields?: boolean;
|
||||||
|
}) => {
|
||||||
const { insert } = useSchemaInitializer();
|
const { insert } = useSchemaInitializer();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { getCollectionField, getCollectionFieldsOptions } = useCollectionManager_deprecated();
|
const { getCollectionField, getCollectionFieldsOptions } = useCollectionManager_deprecated();
|
||||||
@ -29,6 +43,10 @@ export const CalendarBlockInitializer = () => {
|
|||||||
componentType={'Calendar'}
|
componentType={'Calendar'}
|
||||||
icon={<FormOutlined />}
|
icon={<FormOutlined />}
|
||||||
onCreateBlockSchema={async ({ item }) => {
|
onCreateBlockSchema={async ({ item }) => {
|
||||||
|
if (createBlockSchema) {
|
||||||
|
return createBlockSchema({ item });
|
||||||
|
}
|
||||||
|
|
||||||
const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { dataSource: item.dataSource });
|
const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { dataSource: item.dataSource });
|
||||||
const dateFieldsOptions = getCollectionFieldsOptions(item.name, 'date', {
|
const dateFieldsOptions = getCollectionFieldsOptions(item.name, 'date', {
|
||||||
association: ['o2o', 'obo', 'oho', 'm2o'],
|
association: ['o2o', 'obo', 'oho', 'm2o'],
|
||||||
@ -87,6 +105,10 @@ export const CalendarBlockInitializer = () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
onlyCurrentDataSource={onlyCurrentDataSource}
|
||||||
|
hideSearch={hideSearch}
|
||||||
|
filter={filterCollections}
|
||||||
|
showAssociationFields={showAssociationFields}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -113,3 +113,86 @@ export const RecordAssociationCalendarBlockInitializer = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function useCreateAssociationCalendarBlock() {
|
||||||
|
const { insert } = useSchemaInitializer();
|
||||||
|
const { getCollection } = useCollectionManager_deprecated();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const options = useContext(SchemaOptionsContext);
|
||||||
|
const { theme } = useGlobalTheme();
|
||||||
|
|
||||||
|
const createAssociationCalendarBlock = async ({ item }) => {
|
||||||
|
const field = item.associationField;
|
||||||
|
const collection = getCollection(field.target);
|
||||||
|
|
||||||
|
const stringFields = collection?.fields
|
||||||
|
?.filter((field) => field.type === 'string')
|
||||||
|
?.map((field) => {
|
||||||
|
return {
|
||||||
|
label: field?.uiSchema?.title,
|
||||||
|
value: field.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const dateFields = collection?.fields
|
||||||
|
?.filter((field) => field.type === 'date')
|
||||||
|
?.map((field) => {
|
||||||
|
return {
|
||||||
|
label: field?.uiSchema?.title,
|
||||||
|
value: field.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const values = await FormDialog(
|
||||||
|
t('Create calendar block'),
|
||||||
|
() => {
|
||||||
|
return (
|
||||||
|
<SchemaComponentOptions scope={options.scope} components={{ ...options.components }}>
|
||||||
|
<FormLayout layout={'vertical'}>
|
||||||
|
<SchemaComponent
|
||||||
|
schema={{
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
title: t('Title field'),
|
||||||
|
enum: stringFields,
|
||||||
|
required: true,
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
title: t('Start date field'),
|
||||||
|
enum: dateFields,
|
||||||
|
required: true,
|
||||||
|
default: 'createdAt',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
title: t('End date field'),
|
||||||
|
enum: dateFields,
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormLayout>
|
||||||
|
</SchemaComponentOptions>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
theme,
|
||||||
|
).open({
|
||||||
|
initialValues: {},
|
||||||
|
});
|
||||||
|
insert(
|
||||||
|
createCalendarBlockSchema({
|
||||||
|
collection: field.target,
|
||||||
|
association: `${field.collectionName}.${field.name}`,
|
||||||
|
fieldNames: {
|
||||||
|
...values,
|
||||||
|
},
|
||||||
|
settings: 'blockSettings:calendar',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { createAssociationCalendarBlock };
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ export const T3377: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'BlockInitializers',
|
'x-initializer': 'page:addBlock',
|
||||||
properties: {
|
properties: {
|
||||||
dtuo84w9hyg: {
|
dtuo84w9hyg: {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -60,7 +60,7 @@ export const T3377: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-initializer': 'FormItemInitializers',
|
'x-initializer': 'form:configureFields',
|
||||||
properties: {
|
properties: {
|
||||||
'729znsrntep': {
|
'729znsrntep': {
|
||||||
_isJSONSchemaObject: true,
|
_isJSONSchemaObject: true,
|
||||||
@ -98,7 +98,7 @@ export const T3377: PageConfig = {
|
|||||||
version: '2.0',
|
version: '2.0',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'AssociationField.SubTable',
|
'x-component': 'AssociationField.SubTable',
|
||||||
'x-initializer': 'TableColumnInitializers',
|
'x-initializer': 'table:configureColumns',
|
||||||
'x-initializer-props': {
|
'x-initializer-props': {
|
||||||
action: false,
|
action: false,
|
||||||
},
|
},
|
||||||
|
@ -76,25 +76,25 @@ export default class extends Plugin {
|
|||||||
const FormActionInitializers = this.app.schemaInitializerManager.get('FormActionInitializers');
|
const FormActionInitializers = this.app.schemaInitializerManager.get('FormActionInitializers');
|
||||||
FormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
FormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
||||||
|
|
||||||
const CreateFormActionInitializers = this.app.schemaInitializerManager.get('CreateFormActionInitializers');
|
const CreateFormActionInitializers = this.app.schemaInitializerManager.get('createForm:configureActions');
|
||||||
CreateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
CreateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
||||||
|
|
||||||
const UpdateFormActionInitializers = this.app.schemaInitializerManager.get('UpdateFormActionInitializers');
|
const UpdateFormActionInitializers = this.app.schemaInitializerManager.get('editForm:configureActions');
|
||||||
UpdateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
UpdateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
||||||
|
|
||||||
const DetailsActionInitializers = this.app.schemaInitializerManager.get('DetailsActionInitializers');
|
const DetailsActionInitializers = this.app.schemaInitializerManager.get('detailsWithPaging:configureActions');
|
||||||
DetailsActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
DetailsActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
||||||
|
|
||||||
const ReadPrettyFormActionInitializers = this.app.schemaInitializerManager.get('ReadPrettyFormActionInitializers');
|
const ReadPrettyFormActionInitializers = this.app.schemaInitializerManager.get('details:configureActions');
|
||||||
ReadPrettyFormActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
ReadPrettyFormActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
||||||
|
|
||||||
const TableActionColumnInitializers = this.app.schemaInitializerManager.get('TableActionColumnInitializers');
|
const TableActionColumnInitializers = this.app.schemaInitializerManager.get('table:configureItemActions');
|
||||||
TableActionColumnInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
TableActionColumnInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
||||||
|
|
||||||
const GridCardItemActionInitializers = this.app.schemaInitializerManager.get('GridCardItemActionInitializers');
|
const GridCardItemActionInitializers = this.app.schemaInitializerManager.get('gridCard:configureItemActions');
|
||||||
GridCardItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
GridCardItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
||||||
|
|
||||||
const ListItemActionInitializers = this.app.schemaInitializerManager.get('ListItemActionInitializers');
|
const ListItemActionInitializers = this.app.schemaInitializerManager.get('list:configureItemActions');
|
||||||
ListItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
ListItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export default {
|
|||||||
[allCollections],
|
[allCollections],
|
||||||
);
|
);
|
||||||
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
||||||
const searchedChildren = useMenuSearch(childItems, openMenuKeys);
|
const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'createRecordForm',
|
name: 'createRecordForm',
|
||||||
|
@ -101,7 +101,7 @@ export default {
|
|||||||
[allCollections],
|
[allCollections],
|
||||||
);
|
);
|
||||||
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
||||||
const searchedChildren = useMenuSearch(childItems, openMenuKeys);
|
const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys });
|
||||||
return {
|
return {
|
||||||
name: 'updateRecordForm',
|
name: 'updateRecordForm',
|
||||||
key: 'updateRecordForm',
|
key: 'updateRecordForm',
|
||||||
|
Loading…
Reference in New Issue
Block a user