import { TreeSelect } from '@formily/antd'; import { Field, onFieldChange } from '@formily/core'; import { ISchema, Schema, useField, useFieldSchema } from '@formily/react'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { findByUid } from '.'; import { createDesignable } from '../..'; import { GeneralSchemaDesigner, SchemaSettings, useAPIClient, useDesignable } from '../../../'; const toItems = (properties = {}) => { const items = []; for (const key in properties) { if (Object.prototype.hasOwnProperty.call(properties, key)) { const element = properties[key]; const item = { label: element.title, value: `${element['x-uid']}||${element['x-component']}`, }; if (element.properties) { const children = toItems(element.properties); if (children?.length) { item['children'] = children; } } items.push(item); } } return items; }; const findMenuSchema = (fieldSchema: Schema) => { let parent = fieldSchema.parent; while (parent) { if (parent['x-component'] === 'Menu') { return parent; } parent = parent.parent; } }; const InsertMenuItems = (props) => { const { eventKey, title, insertPosition } = props; const { t } = useTranslation(); const { dn } = useDesignable(); const fieldSchema = useFieldSchema(); const isSubMenu = fieldSchema['x-component'] === 'Menu.SubMenu'; if (!isSubMenu && insertPosition === 'beforeEnd') { return null; } return ( { dn.insertAdjacent(insertPosition, { type: 'void', title, 'x-component': 'Menu.SubMenu', 'x-decorator': 'ACLMenuItemProvider', 'x-component-props': { icon, }, 'x-server-hooks': [ { type: 'onSelfCreate', method: 'bindMenuToRole', }, ], }); }} /> { dn.insertAdjacent(insertPosition, { type: 'void', title, 'x-component': 'Menu.Item', 'x-decorator': 'ACLMenuItemProvider', 'x-component-props': { icon, }, 'x-server-hooks': [ { type: 'onSelfCreate', method: 'bindMenuToRole', }, ], properties: { page: { type: 'void', 'x-component': 'Page', 'x-async': true, properties: { grid: { type: 'void', 'x-component': 'Grid', 'x-initializer': 'BlockInitializers', properties: {}, }, }, }, }, }); }} /> { dn.insertAdjacent(insertPosition, { type: 'void', title, 'x-component': 'Menu.URL', 'x-decorator': 'ACLMenuItemProvider', 'x-component-props': { icon, href, }, 'x-server-hooks': [ { type: 'onSelfCreate', method: 'bindMenuToRole', }, ], }); }} /> ); }; export const MenuDesigner = () => { const field = useField(); const fieldSchema = useFieldSchema(); const api = useAPIClient(); const { dn, refresh } = useDesignable(); const { t } = useTranslation(); const menuSchema = findMenuSchema(fieldSchema); const items = toItems(menuSchema?.properties); const effects = (form) => { onFieldChange('target', (field: Field) => { const [, component] = field?.value?.split?.('||') || []; field.query('position').take((f: Field) => { f.dataSource = component === 'Menu.SubMenu' ? [ { label: t('Before'), value: 'beforeBegin' }, { label: t('After'), value: 'afterEnd' }, { label: t('Inner'), value: 'beforeEnd' }, ] : [ { label: t('Before'), value: 'beforeBegin' }, { label: t('After'), value: 'afterEnd' }, ]; }); }); }; const schema = { type: 'object', title: t('Edit menu item'), properties: { title: { title: t('Menu item title'), required: true, 'x-decorator': 'FormItem', 'x-component': 'Input', 'x-component-props': {}, }, icon: { title: t('Menu item icon'), 'x-component': 'IconPicker', 'x-decorator': 'FormItem', }, }, }; const initialValues = { title: field.title, icon: field.componentProps.icon, }; if (fieldSchema['x-component'] === 'Menu.URL') { schema.properties['href'] = { title: t('Link'), 'x-component': 'Input', 'x-decorator': 'FormItem', }; initialValues['href'] = field.componentProps.href; } return ( { const schema = { ['x-uid']: fieldSchema['x-uid'], }; if (title) { fieldSchema.title = title; field.title = title; schema['title'] = title; refresh(); } field.componentProps.icon = icon; field.componentProps.href = href; schema['x-component-props'] = { icon, href }; fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; fieldSchema['x-component-props']['icon'] = icon; fieldSchema['x-component-props']['href'] = href; dn.emit('patch', { schema, }); }} /> { const [uid] = target?.split?.('||') || []; if (!uid) { return; } const current = findByUid(menuSchema, uid); const dn = createDesignable({ t, api, refresh, current, }); dn.loadAPIClientEvents(); dn.insertAdjacent(position, fieldSchema); }} /> ); };