moveTo for menu & table & tabs

This commit is contained in:
chenos 2021-08-02 16:17:27 +08:00
parent cf2d3fcdaf
commit 0ca3fef9d3
3 changed files with 94 additions and 9 deletions

View File

@ -107,7 +107,18 @@ export const Menu: any = observer((props: any) => {
defaultSelectedKeys = [], defaultSelectedKeys = [],
...others ...others
} = props; } = props;
const { designable, schema } = useDesignable(); const { root, schema, insertAfter, remove } = useDesignable();
const moveToAfter = (path1, path2) => {
if (!path1 || !path2) {
return;
}
const data = findPropertyByPath(root, path1);
if (!data) {
return;
}
remove(path1);
return insertAfter(data.toJSON(), path2);
}
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
console.log('Menu.schema', schema, fieldSchema); console.log('Menu.schema', schema, fieldSchema);
const [selectedKey, setSelectedKey] = useState( const [selectedKey, setSelectedKey] = useState(
@ -140,9 +151,18 @@ export const Menu: any = observer((props: any) => {
const [dragOverlayContent, setDragOverlayContent] = useState(''); const [dragOverlayContent, setDragOverlayContent] = useState('');
return ( return (
<DndContext onDragStart={(event) => { <DndContext
setDragOverlayContent(event.active.data?.current?.title || ''); onDragStart={(event) => {
}}> console.log({ event });
setDragOverlayContent(event.active.data?.current?.title || '');
}}
onDragEnd={async (event) => {
const path1 = event.active?.data?.current?.path;
const path2 = event.over?.data?.current?.path;
const data = moveToAfter(path1, path2);
await updateSchema(data);
}}
>
{createPortal( {createPortal(
<DragOverlay <DragOverlay
style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }} style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}
@ -221,10 +241,13 @@ Menu.Item = observer((props: any) => {
id={schema.name} id={schema.name}
data={{ data={{
title: schema.title, title: schema.title,
path: getSchemaPath(schema),
}} }}
> >
{icon && ( {icon && (
<span style={{ marginRight: 10 }}><IconPicker type={icon} /></span> <span style={{ marginRight: 10 }}>
<IconPicker type={icon} />
</span>
)} )}
{schema.title} {schema.title}
<DesignableBar /> <DesignableBar />
@ -247,10 +270,13 @@ Menu.Link = observer((props: any) => {
id={schema.name} id={schema.name}
data={{ data={{
title: schema.title, title: schema.title,
path: getSchemaPath(schema),
}} }}
> >
{icon && ( {icon && (
<span style={{ marginRight: 10 }}><IconPicker type={icon} /></span> <span style={{ marginRight: 10 }}>
<IconPicker type={icon} />
</span>
)} )}
{schema.title} {schema.title}
<DesignableBar /> <DesignableBar />

View File

@ -29,6 +29,13 @@ import {
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { useRef } from 'react'; import { useRef } from 'react';
import { SortableItem } from '../../components/Sortable'; import { SortableItem } from '../../components/Sortable';
import {
findPropertyByPath,
getSchemaPath,
useDesignable,
} from '../../components/schema-renderer';
import { updateSchema } from '..';
import { Schema } from '@formily/react';
export const RowDraggableContext = createContext({}); export const RowDraggableContext = createContext({});
export const ColDraggableContext = createContext(null); export const ColDraggableContext = createContext(null);
@ -131,6 +138,18 @@ export function SortableBodyRow(props: any) {
} }
export function SortableHeaderRow(props) { export function SortableHeaderRow(props) {
const { root, remove, insertAfter } = useDesignable();
const moveToAfter = (path1, path2) => {
if (!path1 || !path2) {
return;
}
const data = findPropertyByPath(root, path1);
if (!data) {
return;
}
remove(path1);
return insertAfter(data.toJSON(), path2);
};
const [dragOverlayContent, setDragOverlayContent] = useState(''); const [dragOverlayContent, setDragOverlayContent] = useState('');
return ( return (
<tr {...props}> <tr {...props}>
@ -143,6 +162,12 @@ export function SortableHeaderRow(props) {
setDragOverlayContent(previewRef.current.textContent || ''); setDragOverlayContent(previewRef.current.textContent || '');
} }
}} }}
onDragEnd={async (event) => {
const path1 = event.active?.data?.current?.path;
const path2 = event.over?.data?.current?.path;
const data = moveToAfter(path1, path2);
await updateSchema(data);
}}
> >
{createPortal( {createPortal(
<DragOverlay style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}> <DragOverlay style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}>
@ -163,10 +188,25 @@ export function SortableHeaderCell(props) {
if (['RC_TABLE_KEY', 'addnew'].includes(id)) { if (['RC_TABLE_KEY', 'addnew'].includes(id)) {
return <th {...props} />; return <th {...props} />;
} }
const { schema } = useDesignable();
const columns: Schema[] = schema.reduceProperties((columns, current) => {
if (current['x-component'] === 'Table.Column' && current.name === id) {
return [...columns, current];
}
return [...columns];
}, []);
const column = columns.shift();
if (!column) {
return <th {...props} />;
}
return ( return (
<SortableItem <SortableItem
{...props} {...props}
id={id} id={id}
data={{
title: column.title,
path: getSchemaPath(column),
}}
component={forwardRef<any>((props, ref) => ( component={forwardRef<any>((props, ref) => (
<th ref={ref} {...props} /> <th ref={ref} {...props} />
))} ))}

View File

@ -1,12 +1,12 @@
import { observer, connect, useField, RecursionField } from '@formily/react'; import { observer, connect, useField, RecursionField } from '@formily/react';
import React from 'react'; import React from 'react';
import { Button, Tabs as AntdTabs, Dropdown, Menu, Switch } from 'antd'; import { Button, Tabs as AntdTabs, Dropdown, Menu, Switch } from 'antd';
import { useDesignable } from '../../components/schema-renderer'; import { findPropertyByPath, getSchemaPath, useDesignable } from '../../components/schema-renderer';
import { Schema, SchemaKey } from '@formily/react'; import { Schema, SchemaKey } from '@formily/react';
import { PlusOutlined, MenuOutlined } from '@ant-design/icons'; import { PlusOutlined, MenuOutlined } from '@ant-design/icons';
import { useState } from 'react'; import { useState } from 'react';
import cls from 'classnames'; import cls from 'classnames';
import { createSchema, removeSchema } from '..'; import { createSchema, removeSchema, updateSchema } from '..';
import './style.less'; import './style.less';
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
import { DragHandle, SortableItem } from '../../components/Sortable'; import { DragHandle, SortableItem } from '../../components/Sortable';
@ -35,10 +35,22 @@ const useTabs = () => {
export const Tabs: any = observer((props: any) => { export const Tabs: any = observer((props: any) => {
const { singleton, ...others } = props; const { singleton, ...others } = props;
const { schema, DesignableBar, appendChild } = useDesignable(); const { schema, DesignableBar, appendChild, root, remove, insertAfter } = useDesignable();
const tabs = useTabs(); const tabs = useTabs();
const [dragOverlayContent, setDragOverlayContent] = useState(''); const [dragOverlayContent, setDragOverlayContent] = useState('');
const moveToAfter = (path1, path2) => {
if (!path1 || !path2) {
return;
}
const data = findPropertyByPath(root, path1);
if (!data) {
return;
}
remove(path1);
return insertAfter(data.toJSON(), path2);
};
if (singleton) { if (singleton) {
return ( return (
<div className={'nb-tabs'}> <div className={'nb-tabs'}>
@ -57,6 +69,12 @@ export const Tabs: any = observer((props: any) => {
onDragStart={(event) => { onDragStart={(event) => {
setDragOverlayContent(event.active.data?.current?.title || ''); setDragOverlayContent(event.active.data?.current?.title || '');
}} }}
onDragEnd={async (event) => {
const path1 = event.active?.data?.current?.path;
const path2 = event.over?.data?.current?.path;
const data = moveToAfter(path1, path2);
await updateSchema(data);
}}
> >
<DragOverlay style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}> <DragOverlay style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}>
{dragOverlayContent} {dragOverlayContent}
@ -123,6 +141,7 @@ Tabs.TabPane = observer((props: any) => {
id={schema.name} id={schema.name}
data={{ data={{
title: schema.title, title: schema.title,
path: getSchemaPath(schema),
}} }}
> >
<div className={'nb-tab-pane'}> <div className={'nb-tab-pane'}>