feat: support onRemove event for the menu component
This commit is contained in:
		
							parent
							
								
									85c052ba59
								
							
						
					
					
						commit
						3966c7f0f3
					
				| @ -10,5 +10,6 @@ export const menu = { | ||||
|     defaultSelectedKeys: '{{ selectedKeys }}', | ||||
|     sideMenuRef: '{{ sideMenuRef }}', | ||||
|     onSelect: '{{ onSelect }}', | ||||
|     onRemove: '{{ onMenuItemRemove }}', | ||||
|   }, | ||||
| }; | ||||
|  | ||||
| @ -33,6 +33,7 @@ import { | ||||
|   CollectionsProvider, | ||||
|   useCollectionsContext, | ||||
| } from '../../constate'; | ||||
| import { uid } from '@formily/shared'; | ||||
| 
 | ||||
| function DesignableToggle() { | ||||
|   const { designable, setDesignable } = useDesignableSwitchContext(); | ||||
| @ -58,7 +59,6 @@ interface LayoutWithMenuProps { | ||||
| function LayoutWithMenu(props: LayoutWithMenuProps) { | ||||
|   const { schema, defaultSelectedKeys } = props; | ||||
|   const match = useRouteMatch<any>(); | ||||
|   const location = useLocation(); | ||||
|   const sideMenuRef = useRef(); | ||||
|   const history = useHistory(); | ||||
|   const [activeKey, setActiveKey] = useState(match.params.name); | ||||
| @ -77,7 +77,12 @@ function LayoutWithMenu(props: LayoutWithMenuProps) { | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     setActiveKey(match.params.name); | ||||
|   }, [match.params.name]); | ||||
|   const onMenuItemRemove = () => { | ||||
|     history.push(`/admin`); | ||||
|   }; | ||||
|   return ( | ||||
|     <Layout> | ||||
|       <Layout.Header style={{ display: 'flex' }}> | ||||
| @ -86,6 +91,7 @@ function LayoutWithMenu(props: LayoutWithMenuProps) { | ||||
|           scope={{ | ||||
|             sideMenuRef, | ||||
|             onSelect, | ||||
|             onMenuItemRemove, | ||||
|             selectedKeys: defaultSelectedKeys.filter(Boolean), | ||||
|           }} | ||||
|         /> | ||||
| @ -109,13 +115,13 @@ function LayoutWithMenu(props: LayoutWithMenuProps) { | ||||
| function Content({ activeKey }) { | ||||
|   const { designable } = useDesignableSwitchContext(); | ||||
|   const { collections } = useCollectionsContext(); | ||||
|   const { data = {}, loading, run } = useRequest( | ||||
|     `ui_schemas:getTree?filter[parentKey]=${activeKey}`, | ||||
|     { | ||||
|       refreshDeps: [activeKey, collections, designable], | ||||
|       formatResult: (result) => result?.data, | ||||
|     }, | ||||
|   ); | ||||
|   const { | ||||
|     data = {}, | ||||
|     loading, | ||||
|   } = useRequest(`ui_schemas:getTree?filter[parentKey]=${activeKey}`, { | ||||
|     refreshDeps: [activeKey, collections, designable], | ||||
|     formatResult: (result) => result?.data, | ||||
|   }); | ||||
| 
 | ||||
|   if (loading) { | ||||
|     return <Spin />; | ||||
| @ -124,7 +130,8 @@ function Content({ activeKey }) { | ||||
|   return <SchemaRenderer schema={data} />; | ||||
| } | ||||
| 
 | ||||
| export function AdminLayout({ route }: any) { | ||||
| export function AdminLayout({ route, ...others }: any) { | ||||
|   const match = useRouteMatch<any>(); | ||||
|   const { data = {}, loading } = useRequest( | ||||
|     `ui_schemas:getTree/${route.uiSchemaKey}`, | ||||
|     { | ||||
| @ -132,7 +139,6 @@ export function AdminLayout({ route }: any) { | ||||
|       formatResult: (result) => result?.data, | ||||
|     }, | ||||
|   ); | ||||
|   const match = useRouteMatch<any>(); | ||||
| 
 | ||||
|   if (loading) { | ||||
|     return <Spin />; | ||||
|  | ||||
| @ -68,7 +68,13 @@ import { | ||||
| import { DndContext, DragOverlay } from '@dnd-kit/core'; | ||||
| import { createPortal } from 'react-dom'; | ||||
| 
 | ||||
| export interface MenuContextProps { | ||||
|   schema?: Schema; | ||||
|   onRemove?: any; | ||||
| } | ||||
| 
 | ||||
| export const MenuModeContext = createContext(null); | ||||
| export const MenuContext = createContext<MenuContextProps>(null); | ||||
| 
 | ||||
| const SideMenu = (props: any) => { | ||||
|   const { selectedKey, defaultSelectedKeys, onSelect, path } = props; | ||||
| @ -105,6 +111,7 @@ export const Menu: any = observer((props: any) => { | ||||
|     onSelect, | ||||
|     sideMenuRef, | ||||
|     defaultSelectedKeys = [], | ||||
|     onRemove, | ||||
|     ...others | ||||
|   } = props; | ||||
|   const { root, schema, insertAfter, remove } = useDesignable(); | ||||
| @ -152,80 +159,82 @@ export const Menu: any = observer((props: any) => { | ||||
|   }, [selectedKey]); | ||||
| 
 | ||||
|   const [dragOverlayContent, setDragOverlayContent] = useState(''); | ||||
| 
 | ||||
|   console.log('onRemove', onRemove) | ||||
|   return ( | ||||
|     <DndContext | ||||
|       onDragStart={(event) => { | ||||
|         console.log({ event }); | ||||
|         setDragOverlayContent(event.active.data?.current?.title || ''); | ||||
|       }} | ||||
|       onDragEnd={async (event) => { | ||||
|         console.log({ event }); | ||||
|         const path1 = event.active?.data?.current?.path; | ||||
|         const path2 = event.over?.data?.current?.path; | ||||
|         const data = moveToAfter(path1, path2); | ||||
|         await updateSchema(data); | ||||
|       }} | ||||
|     > | ||||
|       {createPortal( | ||||
|         <DragOverlay | ||||
|           style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }} | ||||
|           dropAnimation={{ | ||||
|             duration: 10, | ||||
|             easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)', | ||||
|           }} | ||||
|         > | ||||
|           {dragOverlayContent} | ||||
|         </DragOverlay>, | ||||
|         document.body, | ||||
|       )} | ||||
|       <MenuModeContext.Provider value={mode}> | ||||
|         <AntdMenu | ||||
|           defaultSelectedKeys={defaultSelectedKeys} | ||||
|           {...others} | ||||
|           mode={mode === 'mix' ? 'horizontal' : mode} | ||||
|           onSelect={(info) => { | ||||
|             if (mode === 'mix') { | ||||
|               setSelectedKey(info.key); | ||||
|             } | ||||
|             const selectedSchema = schema.properties[info.key]; | ||||
|             console.log({ selectedSchema }); | ||||
|             onSelect && onSelect({ ...info, schema: selectedSchema }); | ||||
|           }} | ||||
|         > | ||||
|           <RecursionField schema={schema} onlyRenderProperties /> | ||||
|           <Menu.AddNew key={uid()} path={path}> | ||||
|             {/* <PlusOutlined className={'nb-add-new-icon'} /> */} | ||||
|             <Button | ||||
|               className={`nb-add-new-menu-item menu-mode-${ | ||||
|                 mode === 'mix' ? 'horizontal' : mode | ||||
|               }`}
 | ||||
|               block | ||||
|               type={mode == 'inline' ? 'dashed' : 'primary'} | ||||
|             > | ||||
|               <PlusOutlined /> | ||||
|             </Button> | ||||
|           </Menu.AddNew> | ||||
|         </AntdMenu> | ||||
|         {mode === 'mix' && ( | ||||
|           <div ref={ref}> | ||||
|             <SideMenu | ||||
|               path={path} | ||||
|               onSelect={(info) => { | ||||
|                 const keyPath = [selectedKey, ...[...info.keyPath].reverse()]; | ||||
|                 const selectedSchema = findPropertyByPath(schema, keyPath); | ||||
|                 console.log('keyPath', keyPath, selectedSchema); | ||||
|                 onSelect && | ||||
|                   onSelect({ ...info, keyPath, schema: selectedSchema }); | ||||
|               }} | ||||
|               defaultSelectedKeys={defaultSelectedKeys || []} | ||||
|               selectedKey={selectedKey} | ||||
|               sideMenuRef={sideMenuRef} | ||||
|             /> | ||||
|           </div> | ||||
|     <MenuContext.Provider value={{ schema, onRemove }}> | ||||
|       <DndContext | ||||
|         onDragStart={(event) => { | ||||
|           console.log({ event }); | ||||
|           setDragOverlayContent(event.active.data?.current?.title || ''); | ||||
|         }} | ||||
|         onDragEnd={async (event) => { | ||||
|           console.log({ event }); | ||||
|           const path1 = event.active?.data?.current?.path; | ||||
|           const path2 = event.over?.data?.current?.path; | ||||
|           const data = moveToAfter(path1, path2); | ||||
|           await updateSchema(data); | ||||
|         }} | ||||
|       > | ||||
|         {createPortal( | ||||
|           <DragOverlay | ||||
|             style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }} | ||||
|             dropAnimation={{ | ||||
|               duration: 10, | ||||
|               easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)', | ||||
|             }} | ||||
|           > | ||||
|             {dragOverlayContent} | ||||
|           </DragOverlay>, | ||||
|           document.body, | ||||
|         )} | ||||
|       </MenuModeContext.Provider> | ||||
|     </DndContext> | ||||
|         <MenuModeContext.Provider value={mode}> | ||||
|           <AntdMenu | ||||
|             defaultSelectedKeys={defaultSelectedKeys} | ||||
|             {...others} | ||||
|             mode={mode === 'mix' ? 'horizontal' : mode} | ||||
|             onSelect={(info) => { | ||||
|               if (mode === 'mix') { | ||||
|                 setSelectedKey(info.key); | ||||
|               } | ||||
|               const selectedSchema = schema.properties[info.key]; | ||||
|               console.log({ selectedSchema }); | ||||
|               onSelect && onSelect({ ...info, schema: selectedSchema }); | ||||
|             }} | ||||
|           > | ||||
|             <RecursionField schema={schema} onlyRenderProperties /> | ||||
|             <Menu.AddNew key={uid()} path={path}> | ||||
|               {/* <PlusOutlined className={'nb-add-new-icon'} /> */} | ||||
|               <Button | ||||
|                 className={`nb-add-new-menu-item menu-mode-${ | ||||
|                   mode === 'mix' ? 'horizontal' : mode | ||||
|                 }`}
 | ||||
|                 block | ||||
|                 type={mode == 'inline' ? 'dashed' : 'primary'} | ||||
|               > | ||||
|                 <PlusOutlined /> | ||||
|               </Button> | ||||
|             </Menu.AddNew> | ||||
|           </AntdMenu> | ||||
|           {mode === 'mix' && ( | ||||
|             <div ref={ref}> | ||||
|               <SideMenu | ||||
|                 path={path} | ||||
|                 onSelect={(info) => { | ||||
|                   const keyPath = [selectedKey, ...[...info.keyPath].reverse()]; | ||||
|                   const selectedSchema = findPropertyByPath(schema, keyPath); | ||||
|                   console.log('keyPath', keyPath, selectedSchema); | ||||
|                   onSelect && | ||||
|                     onSelect({ ...info, keyPath, schema: selectedSchema }); | ||||
|                 }} | ||||
|                 defaultSelectedKeys={defaultSelectedKeys || []} | ||||
|                 selectedKey={selectedKey} | ||||
|                 sideMenuRef={sideMenuRef} | ||||
|               /> | ||||
|             </div> | ||||
|           )} | ||||
|         </MenuModeContext.Provider> | ||||
|       </DndContext> | ||||
|     </MenuContext.Provider> | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
| @ -638,10 +647,7 @@ Menu.DesignableBar = (props) => { | ||||
|   } = useDesignable(); | ||||
|   const formConfig = schemas[schema['x-component']]; | ||||
|   const isSubMenu = schema['x-component'] === 'Menu.SubMenu'; | ||||
| 
 | ||||
|   if (!designable) { | ||||
|     return null; | ||||
|   } | ||||
|   const ctx = useContext(MenuContext); | ||||
| 
 | ||||
|   return ( | ||||
|     <div className={cls('designable-bar', { active: visible })}> | ||||
| @ -927,6 +933,7 @@ Menu.DesignableBar = (props) => { | ||||
|                     onOk: async () => { | ||||
|                       const target = remove(); | ||||
|                       await removeSchema(target); | ||||
|                       ctx.onRemove && ctx.onRemove(target); | ||||
|                     }, | ||||
|                   }); | ||||
|                 }} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user