mirror of
https://github.com/nocobase/nocobase
synced 2024-11-16 03:45:10 +00:00
fix: improve code
This commit is contained in:
parent
2724521000
commit
d2d5532127
@ -13,6 +13,7 @@ export interface SchemaInitializerSubMenuProps {
|
||||
name: string;
|
||||
title?: string;
|
||||
onClick?: (args: any) => void;
|
||||
onOpenChange?: (openKeys: string[]) => void;
|
||||
icon?: string | ReactNode;
|
||||
children?: SchemaInitializerOptions['items'];
|
||||
}
|
||||
@ -66,9 +67,10 @@ export const SchemaInitializerMenu: FC<MenuProps> = (props) => {
|
||||
};
|
||||
|
||||
export const SchemaInitializerSubMenu: FC<SchemaInitializerSubMenuProps> = (props) => {
|
||||
const { children, title, name = uid(), icon, ...others } = props;
|
||||
const { children, title, name = uid(), onOpenChange, icon, ...others } = props;
|
||||
const compile = useCompile();
|
||||
const childrenItems = useSchemaInitializerMenuItems(children, name);
|
||||
|
||||
const items = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@ -80,7 +82,7 @@ export const SchemaInitializerSubMenu: FC<SchemaInitializerSubMenuProps> = (prop
|
||||
},
|
||||
];
|
||||
}, [childrenItems, compile, icon, name, others, title]);
|
||||
return <SchemaInitializerMenu items={items}></SchemaInitializerMenu>;
|
||||
return <SchemaInitializerMenu onOpenChange={onOpenChange} items={items}></SchemaInitializerMenu>;
|
||||
};
|
||||
|
||||
export const SchemaInitializerSubMenuInternal = () => {
|
||||
|
@ -5,87 +5,16 @@ import { useApp } from '../../hooks';
|
||||
import { SchemaInitializerChild, SchemaInitializerItems } from '../components';
|
||||
import { SchemaInitializerButton } from '../components/SchemaInitializerButton';
|
||||
import { withInitializer } from '../hoc';
|
||||
import { SchemaInitializerItemType, SchemaInitializerOptions } from '../types';
|
||||
import { SchemaInitializerOptions } from '../types';
|
||||
|
||||
export * from './useAriaAttributeOfMenuItem';
|
||||
|
||||
export function useSchemaInitializerMenuItems(items: any[], name?: string, onClick?: (args: any) => void) {
|
||||
const compile = useCompile();
|
||||
|
||||
const getMenuItems = useCallback(
|
||||
(items: SchemaInitializerItemType[], parentKey: string) => {
|
||||
if (!items?.length) {
|
||||
return [];
|
||||
}
|
||||
return items.map((item: any, indexA) => {
|
||||
const ItemComponent = item.component || item.Component;
|
||||
let element: ReactNode;
|
||||
const compiledTitle = item.title ? compile(item.title) : undefined;
|
||||
if (ItemComponent) {
|
||||
element = React.createElement(SchemaInitializerChild, { ...item, title: compiledTitle });
|
||||
if (!element) return;
|
||||
}
|
||||
|
||||
if (item.type === 'divider') {
|
||||
return { type: 'divider', key: `divider-${indexA}` };
|
||||
}
|
||||
if (item.type === 'item' && ItemComponent) {
|
||||
if (!item.key) {
|
||||
item.key = `${item.title}-${indexA}`;
|
||||
}
|
||||
return {
|
||||
key: item.key,
|
||||
label: element,
|
||||
};
|
||||
}
|
||||
if (item.type === 'itemGroup') {
|
||||
const label = typeof item.title === 'string' ? compiledTitle : item.title;
|
||||
const key = `${parentKey}-item-group-${indexA}`;
|
||||
return {
|
||||
type: 'group',
|
||||
key,
|
||||
label,
|
||||
// className: styles.nbMenuItemGroup,
|
||||
children: item?.children.length ? getMenuItems(item.children, key) : [],
|
||||
};
|
||||
}
|
||||
if (item.type === 'subMenu') {
|
||||
const label = compiledTitle;
|
||||
const key = `${parentKey}-sub-menu-${indexA}`;
|
||||
return {
|
||||
key,
|
||||
label,
|
||||
children: item?.children.length ? getMenuItems(item.children, key) : [],
|
||||
};
|
||||
}
|
||||
if (item.isMenuType) {
|
||||
const { isMenuType, ...menuData } = item;
|
||||
return menuData;
|
||||
}
|
||||
|
||||
const label = element || compiledTitle || item.label;
|
||||
const key = `${parentKey}-${item.title}-${indexA}`;
|
||||
return {
|
||||
key,
|
||||
label,
|
||||
onClick: (info) => {
|
||||
if (info.key !== key) return;
|
||||
if (item.onClick) {
|
||||
item.onClick({ ...info, item });
|
||||
} else {
|
||||
onClick?.({ ...info, item });
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
[compile, onClick],
|
||||
);
|
||||
|
||||
const getMenuItems = useGetSchemaInitializerMenuItems(onClick);
|
||||
return getMenuItems(items, name);
|
||||
}
|
||||
|
||||
export function useSchemaInitializerMenuItemsV2(onClick?: (args: any) => void) {
|
||||
export function useGetSchemaInitializerMenuItems(onClick?: (args: any) => void) {
|
||||
const compile = useCompile();
|
||||
|
||||
const getMenuItems = useCallback(
|
||||
|
@ -43,7 +43,6 @@ export {
|
||||
useAssociatedFormItemInitializerFields,
|
||||
useAssociatedTableColumnInitializerFields,
|
||||
useCollectionDataSourceItems,
|
||||
useCollectionDataSourceItemsV2,
|
||||
useCurrentSchema,
|
||||
useFormItemInitializerFields,
|
||||
useInheritsTableColumnInitializerFields,
|
||||
|
@ -7,12 +7,11 @@ import {
|
||||
SchemaInitializerItem,
|
||||
SchemaInitializerMenu,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerMenuItems,
|
||||
useSchemaInitializerMenuItemsV2,
|
||||
useGetSchemaInitializerMenuItems,
|
||||
} from '../../application';
|
||||
import { useCompile } from '../../schema-component';
|
||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||
import { useCollectionDataSourceItemsV2, useCollectionDataSourceItemsV3 } from '../utils';
|
||||
import { useCollectionDataSourceItems } from '../utils';
|
||||
|
||||
const MENU_ITEM_HEIGHT = 40;
|
||||
const STEP = 15;
|
||||
@ -110,109 +109,7 @@ const LoadingItem = ({ loadMore, maxHeight }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export function useMenuSearch(items: any[], isOpenSubMenu: boolean, showType?: boolean) {
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [count, setCount] = useState(STEP);
|
||||
useEffect(() => {
|
||||
if (isOpenSubMenu) {
|
||||
setSearchValue('');
|
||||
}
|
||||
}, [isOpenSubMenu]);
|
||||
|
||||
// 根据搜索的值进行处理
|
||||
const searchedItems = useMemo(() => {
|
||||
if (!searchValue) return items;
|
||||
const lowerSearchValue = searchValue.toLocaleLowerCase();
|
||||
return items.filter(
|
||||
(item) =>
|
||||
(item.label || item.title) &&
|
||||
String(item.label || item.title)
|
||||
.toLocaleLowerCase()
|
||||
.includes(lowerSearchValue),
|
||||
);
|
||||
}, [searchValue, items]);
|
||||
|
||||
const shouldLoadMore = useMemo(() => searchedItems.length > count, [count, searchedItems]);
|
||||
|
||||
// 根据 count 进行懒加载处理
|
||||
const limitedSearchedItems = useMemo(() => {
|
||||
return searchedItems.slice(0, count);
|
||||
}, [searchedItems, count]);
|
||||
|
||||
// 最终的返回结果
|
||||
const resultItems = useMemo<MenuProps['items']>(() => {
|
||||
// isMenuType 为了 `useSchemaInitializerMenuItems()` 里面处理判断标识的
|
||||
const res: any[] = [
|
||||
// 开头:搜索框
|
||||
Object.assign(
|
||||
{
|
||||
key: 'search',
|
||||
label: (
|
||||
<SearchCollections
|
||||
value={searchValue}
|
||||
onChange={(val: string) => {
|
||||
setCount(STEP);
|
||||
setSearchValue(val);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
onClick({ domEvent }) {
|
||||
domEvent.stopPropagation();
|
||||
},
|
||||
},
|
||||
showType ? { isMenuType: true } : {},
|
||||
),
|
||||
];
|
||||
|
||||
// 中间:搜索的数据
|
||||
if (limitedSearchedItems.length > 0) {
|
||||
// 有搜索结果
|
||||
res.push(...limitedSearchedItems);
|
||||
if (shouldLoadMore) {
|
||||
res.push(
|
||||
Object.assign(
|
||||
{
|
||||
key: 'load-more',
|
||||
label: (
|
||||
<LoadingItem
|
||||
maxHeight={STEP * MENU_ITEM_HEIGHT}
|
||||
loadMore={() => {
|
||||
setCount((count) => count + STEP);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
showType ? { isMenuType: true } : {},
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 搜索结果为空
|
||||
res.push(
|
||||
Object.assign(
|
||||
{
|
||||
key: 'empty',
|
||||
style: {
|
||||
height: 150,
|
||||
},
|
||||
label: (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
showType ? { isMenuType: true } : {},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return res;
|
||||
}, [limitedSearchedItems, searchValue, shouldLoadMore, showType]);
|
||||
|
||||
return resultItems;
|
||||
}
|
||||
|
||||
export function useMenuSearchV2(data: any, openKey: string, showType?: boolean) {
|
||||
export function useMenuSearch(data: any, openKey: string, showType?: boolean) {
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [count, setCount] = useState(STEP);
|
||||
|
||||
@ -390,17 +287,12 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
},
|
||||
[createBlockSchema, getTemplateSchemaByMode, insert, isCusomeizeCreate, onCreateBlockSchema, templateWrap],
|
||||
);
|
||||
// const defaultItems = useCollectionDataSourceItemsV2(componentType);
|
||||
const defaultItemsV2 = useCollectionDataSourceItemsV3(componentType, filter);
|
||||
// const menuChildren = useMemo(() => items || defaultItems, [items, defaultItems]);
|
||||
// const childItems = useSchemaInitializerMenuItems(menuChildren, name, onClick);
|
||||
const getMenuItems = useSchemaInitializerMenuItemsV2(onClick);
|
||||
const childItemsV2 = useMemo(() => getMenuItems(defaultItemsV2, name), [defaultItemsV2]);
|
||||
// const [isOpenSubMenu, setIsOpenSubMenu] = useState(false);
|
||||
const items = useCollectionDataSourceItems(componentType, filter);
|
||||
console.log('items', items);
|
||||
const getMenuItems = useGetSchemaInitializerMenuItems(onClick);
|
||||
const childItems = useMemo(() => getMenuItems(items, name), [items]);
|
||||
const [openMenuKey, setOpenMenuKey] = useState('');
|
||||
// const searchedChildren = useMenuSearch(childItems, isOpenSubMenu);
|
||||
const searchedChildrenV2 = useMenuSearchV2(childItemsV2, openMenuKey);
|
||||
|
||||
const searchedChildren = useMenuSearch(childItems, openMenuKey);
|
||||
const compiledMenuItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
@ -411,13 +303,12 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => {
|
||||
if (info.key !== name) return;
|
||||
onClick({ ...info, item: props });
|
||||
},
|
||||
children: searchedChildrenV2,
|
||||
// children: searchedChildren,
|
||||
children: searchedChildren,
|
||||
},
|
||||
],
|
||||
[name, compile, title, icon, childItemsV2, onClick, props],
|
||||
[name, compile, title, icon, childItems, onClick, props],
|
||||
);
|
||||
if (childItemsV2.length > 0) {
|
||||
if (childItems.length > 0) {
|
||||
return (
|
||||
<SchemaInitializerMenu
|
||||
onOpenChange={(keys) => {
|
||||
|
@ -864,50 +864,7 @@ export const useRecordCollectionDataSourceItems = (
|
||||
];
|
||||
};
|
||||
|
||||
export const useCollectionDataSourceItems = (componentName) => {
|
||||
const { t } = useTranslation();
|
||||
const { collections, getCollectionFields } = useCollectionManager();
|
||||
const { getTemplatesByCollection } = useSchemaTemplateManager();
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'itemGroup',
|
||||
title: null,
|
||||
children: [],
|
||||
loadChildren: ({ searchValue } = { searchValue: '' }) => {
|
||||
return getChildren({
|
||||
collections,
|
||||
getCollectionFields,
|
||||
componentName,
|
||||
searchValue,
|
||||
getTemplatesByCollection,
|
||||
t,
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const useCollectionDataSourceItemsV2 = (componentName) => {
|
||||
const { t } = useTranslation();
|
||||
const { collections, getCollectionFields } = useCollectionManager();
|
||||
const { getTemplatesByCollection } = useSchemaTemplateManager();
|
||||
|
||||
const res = useMemo(() => {
|
||||
return getChildren({
|
||||
collections,
|
||||
getCollectionFields,
|
||||
componentName,
|
||||
searchValue: '',
|
||||
getTemplatesByCollection,
|
||||
t,
|
||||
});
|
||||
}, [collections, componentName, getCollectionFields, getTemplatesByCollection, t]);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export const useCollectionDataSourceItemsV3 = (
|
||||
export const useCollectionDataSourceItems = (
|
||||
componentName,
|
||||
filter: (collection: CollectionV2) => boolean = () => true,
|
||||
) => {
|
||||
@ -1697,7 +1654,7 @@ const getChildrenV3 = ({
|
||||
}
|
||||
})
|
||||
?.map((item, index) => {
|
||||
const title = item.title || item.tableName;
|
||||
const title = item.title || item.tableName || item.label;
|
||||
const templates = getTemplatesByCollection(item.name).filter((template) => {
|
||||
return (
|
||||
componentName &&
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
css,
|
||||
gridRowColWrap,
|
||||
useCollectionManager,
|
||||
useCollectionManagerV2,
|
||||
useCompile,
|
||||
useFormActiveFields,
|
||||
useFormBlockContext,
|
||||
@ -68,7 +69,7 @@ export type FormType = {
|
||||
export type ManualFormType = {
|
||||
title: string;
|
||||
config: {
|
||||
useInitializer: ({ collections }?: { collections: any[] }) => SchemaInitializerItemType;
|
||||
useInitializer: ({ allCollections }?: { allCollections: any[] }) => SchemaInitializerItemType;
|
||||
initializers?: {
|
||||
[key: string]: React.FC;
|
||||
};
|
||||
@ -164,10 +165,11 @@ export const addBlockButton: SchemaInitializer = new SchemaInitializer({
|
||||
name: 'form',
|
||||
title: '{{t("Form")}}',
|
||||
useChildren() {
|
||||
const { collections } = useCollectionManager();
|
||||
const cm = useCollectionManagerV2();
|
||||
const allCollections = cm.getAllCollections((collection) => !collection.isLocal);
|
||||
return Array.from(manualFormTypes.getValues()).map((item: ManualFormType) => {
|
||||
const { useInitializer: getInitializer } = item.config;
|
||||
return getInitializer({ collections });
|
||||
return getInitializer({ allCollections });
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -412,11 +414,9 @@ export function SchemaConfig({ value, onChange }) {
|
||||
const form = useForm();
|
||||
const { workflow } = useFlowContext();
|
||||
|
||||
const nodeInitializers = {};
|
||||
const nodeComponents = {};
|
||||
nodes.forEach((item) => {
|
||||
const instruction = workflowPlugin.instructions.get(item.type);
|
||||
Object.assign(nodeInitializers, instruction.initializers);
|
||||
Object.assign(nodeComponents, instruction.components);
|
||||
});
|
||||
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
SchemaSettingsLinkageRules,
|
||||
SchemaSettingsRemove,
|
||||
useCollection,
|
||||
useGetSchemaInitializerMenuItems,
|
||||
useMenuSearch,
|
||||
} from '@nocobase/client';
|
||||
|
||||
@ -39,26 +40,34 @@ function CreateFormDesigner() {
|
||||
export default {
|
||||
title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
|
||||
config: {
|
||||
useInitializer({ collections }) {
|
||||
const childItems = useMemo(
|
||||
useInitializer({ allCollections }) {
|
||||
const items = useMemo(
|
||||
() =>
|
||||
collections.map((item) => ({
|
||||
name: _.camelCase(`createRecordForm-child-${item.name}`),
|
||||
type: 'item',
|
||||
title: item.title,
|
||||
label: item.label,
|
||||
schema: {
|
||||
collection: item.name,
|
||||
title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
|
||||
formType: 'create',
|
||||
'x-designer': 'CreateFormDesigner',
|
||||
},
|
||||
Component: FormBlockInitializer,
|
||||
allCollections.map(({ nsName, nsTitle, collections }) => ({
|
||||
name: nsName,
|
||||
label: nsTitle,
|
||||
type: 'subMenu',
|
||||
children: collections.map((item) => ({
|
||||
name: _.camelCase(`createRecordForm-child-${item.name}`),
|
||||
type: 'item',
|
||||
title: item.title || item.tableName,
|
||||
schema: {
|
||||
collection: item.name,
|
||||
namespace: nsName,
|
||||
title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
|
||||
formType: 'create',
|
||||
'x-designer': 'CreateFormDesigner',
|
||||
},
|
||||
Component: FormBlockInitializer,
|
||||
})),
|
||||
})),
|
||||
[collections],
|
||||
[allCollections],
|
||||
);
|
||||
const [isOpenSubMenu, setIsOpenSubMenu] = useState(false);
|
||||
const searchedChildren = useMenuSearch(childItems, isOpenSubMenu, true);
|
||||
const getMenuItems = useGetSchemaInitializerMenuItems();
|
||||
const childItems = useMemo(() => getMenuItems(items, 'createRecordForm'), [items]);
|
||||
const [openMenuKey, setOpenMenuKey] = useState('');
|
||||
const searchedChildren = useMenuSearch(childItems, openMenuKey);
|
||||
|
||||
return {
|
||||
name: 'createRecordForm',
|
||||
key: 'createRecordForm',
|
||||
@ -66,7 +75,11 @@ export default {
|
||||
title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
|
||||
componentProps: {
|
||||
onOpenChange(keys) {
|
||||
setIsOpenSubMenu(keys.length > 0);
|
||||
if (keys.length === 2) {
|
||||
setOpenMenuKey(keys[1]);
|
||||
} else if (keys.length === 0) {
|
||||
setOpenMenuKey('');
|
||||
}
|
||||
},
|
||||
},
|
||||
children: searchedChildren,
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
SchemaSettingsRemove,
|
||||
useCollection,
|
||||
useCollectionFilterOptions,
|
||||
useCollectionManagerV2,
|
||||
useDesignable,
|
||||
useMenuSearch,
|
||||
} from '@nocobase/client';
|
||||
@ -76,26 +77,31 @@ function UpdateFormDesigner() {
|
||||
export default {
|
||||
title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
|
||||
config: {
|
||||
useInitializer({ collections }) {
|
||||
useInitializer({ allCollections }) {
|
||||
const childItems = useMemo(
|
||||
() =>
|
||||
collections.map((item) => ({
|
||||
name: _.camelCase(`updateRecordForm-child-${item.name}`),
|
||||
type: 'item',
|
||||
title: item.title,
|
||||
label: item.label,
|
||||
schema: {
|
||||
collection: item.name,
|
||||
title: `{{t("Update record", { ns: "${NAMESPACE}" })}}`,
|
||||
formType: 'update',
|
||||
'x-designer': 'UpdateFormDesigner',
|
||||
},
|
||||
Component: FormBlockInitializer,
|
||||
allCollections.map(({ nsName, nsTitle, collections }) => ({
|
||||
name: nsName,
|
||||
label: nsTitle,
|
||||
type: 'subMenu',
|
||||
children: collections.map((item) => ({
|
||||
name: _.camelCase(`updateRecordForm-child-${item.name}`),
|
||||
type: 'item',
|
||||
title: item.title || item.tableName,
|
||||
schema: {
|
||||
collection: item.name,
|
||||
namespace: nsName,
|
||||
title: `{{t("Update record", { ns: "${NAMESPACE}" })}}`,
|
||||
formType: 'update',
|
||||
'x-designer': 'UpdateFormDesigner',
|
||||
},
|
||||
Component: FormBlockInitializer,
|
||||
})),
|
||||
})),
|
||||
[collections],
|
||||
[allCollections],
|
||||
);
|
||||
const [isOpenSubMenu, setIsOpenSubMenu] = useState(false);
|
||||
const searchedChildren = useMenuSearch(childItems, isOpenSubMenu, true);
|
||||
const [openMenuKey, setOpenMenuKey] = useState('');
|
||||
const searchedChildren = useMenuSearch(childItems, openMenuKey);
|
||||
return {
|
||||
name: 'updateRecordForm',
|
||||
key: 'updateRecordForm',
|
||||
@ -103,7 +109,11 @@ export default {
|
||||
title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
|
||||
componentProps: {
|
||||
onOpenChange(keys) {
|
||||
setIsOpenSubMenu(keys.length > 0);
|
||||
if (keys.length === 2) {
|
||||
setOpenMenuKey(keys[1]);
|
||||
} else if (keys.length === 0) {
|
||||
setOpenMenuKey('');
|
||||
}
|
||||
},
|
||||
},
|
||||
children: searchedChildren,
|
||||
|
@ -9,7 +9,7 @@ import { message } from 'antd';
|
||||
import { getWorkflowDetailPath } from '../constant';
|
||||
|
||||
export const executionCollection = {
|
||||
name: 'executions',
|
||||
name: 'executions-1',
|
||||
fields: [
|
||||
{
|
||||
interface: 'createdAt',
|
||||
|
@ -8,7 +8,7 @@ import React from 'react';
|
||||
import { executionSchema } from './executions';
|
||||
|
||||
const collection = {
|
||||
name: 'workflows',
|
||||
name: 'workflows-1',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
|
Loading…
Reference in New Issue
Block a user