feat: improve code

This commit is contained in:
chenos 2021-08-21 18:33:56 +08:00
parent 1012cb6401
commit 80f4635bb6
4 changed files with 167 additions and 28 deletions

View File

@ -48,7 +48,7 @@ export function DragHandle(props) {
<Icon <Icon
ref={setDraggableNodeRef} ref={setDraggableNodeRef}
{...others} {...others}
{...attributes} // {...attributes}
{...listeners} {...listeners}
/> />
) )
@ -104,6 +104,7 @@ export function SortableItem(props: SortableItemProps) {
className, className,
component, component,
children, children,
disabled,
...others ...others
} = props; } = props;
const previewRef = useRef<HTMLElement>(); const previewRef = useRef<HTMLElement>();
@ -113,6 +114,7 @@ export function SortableItem(props: SortableItemProps) {
...data, ...data,
previewRef, previewRef,
}, },
disabled,
}); });
const { const {
isDragging, isDragging,
@ -122,6 +124,7 @@ export function SortableItem(props: SortableItemProps) {
transform, transform,
} = useDraggable({ } = useDraggable({
id: `draggable-${id}`, id: `draggable-${id}`,
disabled,
data: { data: {
...data, ...data,
previewRef, previewRef,

View File

@ -272,7 +272,7 @@ function setKeys(schema: ISchema | FormilyISchema, parentKey = null) {
if (!schema['key']) { if (!schema['key']) {
schema['key'] = uid(); schema['key'] = uid();
} }
if (parentKey && !schema['parentKey']) { if (parentKey) {
schema['parentKey'] = parentKey; schema['parentKey'] = parentKey;
} }
Object.keys(schema.properties || {}).forEach((name) => { Object.keys(schema.properties || {}).forEach((name) => {
@ -429,6 +429,36 @@ export function useDesignable(path?: any) {
refresh(); refresh();
return target.parent.properties[property.name]; return target.parent.properties[property.name];
}, },
deepRemoveIfEmpty(targetPath) {
let target = currentSchema;
if (targetPath) {
target = findPropertyByPath(schema, targetPath);
}
if (!target) {
console.error('target schema does not exist.');
return;
}
const removed = [];
const remove = (s: Schema) => {
if (!s.parent) {
return;
}
s.parent.removeProperty(s.name);
removed.push(s);
if (s['x-component'] === 'Grid.Row') {
return;
}
if (Object.keys(s.parent.properties || {}).length === 0) {
remove(s.parent);
}
};
console.log({ removed });
if (Object.keys(target.properties || {}).length === 0) {
remove(target);
}
refresh();
return removed;
},
deepRemove(targetPath?: any) { deepRemove(targetPath?: any) {
let target = currentSchema; let target = currentSchema;
if (targetPath) { if (targetPath) {

View File

@ -0,0 +1,81 @@
import React, { useContext, useMemo, useRef, useState } from 'react';
import { createForm } from '@formily/core';
import {
SchemaOptionsContext,
Schema,
useFieldSchema,
observer,
SchemaExpressionScopeContext,
FormProvider,
ISchema,
useField,
useForm,
RecursionField,
} from '@formily/react';
import { useSchemaPath, SchemaField, useDesignable, removeSchema } from '../';
import get from 'lodash/get';
import { Button, Dropdown, Menu, Space } from 'antd';
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
import cls from 'classnames';
import { FormLayout } from '@formily/antd';
import './style.less';
import AddNew from '../add-new';
import { DraggableBlockContext } from '../../components/drag-and-drop';
import { isGridRowOrCol } from '../grid';
import constate from 'constate';
import { useEffect } from 'react';
import { uid } from '@formily/shared';
import { getSchemaPath } from '../../components/schema-renderer';
import { useCollection, useCollectionContext } from '../../constate';
import { useTable } from '../table';
import { DragHandle } from '../../components/Sortable';
export const DesignableBar = observer((props) => {
const field = useField();
const { designable, schema, refresh, deepRemove } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
const { props: tableProps } = useTable();
const collectionName = field.componentProps?.collectionName || tableProps?.collectionName;
const { collection } = useCollection({ collectionName });
return (
<div className={cls('designable-bar', { active: visible })}>
<div className={'designable-info'}>{collection?.title || collection?.name}</div>
<span
onClick={(e) => {
e.stopPropagation();
}}
className={cls('designable-bar-actions', { active: visible })}
>
<Space size={2}>
<AddNew.CardItem defaultAction={'appendChild'} ghost />
{/* <DragHandle /> */}
<Dropdown
trigger={['click']}
visible={visible}
onVisibleChange={(visible) => {
setVisible(visible);
}}
overlay={
<Menu>
<Menu.Item
key={'delete'}
onClick={async () => {
const removed = deepRemove();
// console.log({ removed })
const last = removed.pop();
await removeSchema(last);
}}
>
</Menu.Item>
</Menu>
}
>
<MenuOutlined />
</Dropdown>
</Space>
</span>
</div>
);
});

View File

@ -31,17 +31,29 @@ import {
removeSchema, removeSchema,
updateSchema, updateSchema,
} from '..'; } from '..';
import { createPortal } from 'react-dom'; import { DesignableBar } from './DesignableBar';
const GridRowContext = createContext<any>(null); const GridRowContext = createContext<any>(null);
const GridColContext = createContext<any>(null); const GridColContext = createContext<any>(null);
export function isGridRowOrCol(schema: ISchema | FormilyISchema) { export function isGridRowOrCol(schema: ISchema | FormilyISchema) {
return ['Grid.Row', 'Grid.Col'].includes(schema['x-component']); if (!schema) {
return;
}
return ['Grid.Row', 'Grid.Col'].includes(schema?.['x-component']);
} }
export const Grid: any = observer((props: any) => { export const Grid: any = observer((props: any) => {
const { designable, root, schema, deepRemove, ...methods } = useDesignable(); const {
designable,
root,
schema,
refresh,
deepRemove,
deepRemoveIfEmpty,
remove,
...methods
} = useDesignable();
const [dragOverlayContent, setDragOverlayContent] = useState(''); const [dragOverlayContent, setDragOverlayContent] = useState('');
const [style, setStyle] = useState({}); const [style, setStyle] = useState({});
const [active, setActive] = useState(false); const [active, setActive] = useState(false);
@ -157,15 +169,15 @@ export const Grid: any = observer((props: any) => {
} }
let data; let data;
if (['col-divider', 'col-resize'].includes(type)) { if (['col-divider', 'col-resize'].includes(type)) {
if (sourceSchema?.parent?.['x-component'] === 'Grid.Col') { // if (sourceSchema?.parent?.['x-component'] === 'Grid.Col') {
// console.log('datadata', sourcePath, targetPath); // // console.log('datadata', sourcePath, targetPath);
if ( // if (
sourcePath.join('.').startsWith(targetPath.join('.')) && // sourcePath.join('.').startsWith(targetPath.join('.')) &&
Object.keys(sourceSchema?.parent?.properties).length < 2 // Object.keys(sourceSchema?.parent?.properties).length < 2
) { // ) {
return; // return;
} // }
} // }
data = { data = {
type: 'void', type: 'void',
'x-component': 'Grid.Col', 'x-component': 'Grid.Col',
@ -192,17 +204,20 @@ export const Grid: any = observer((props: any) => {
} }
if (data) { if (data) {
console.log('datadata', data, type, method); console.log('datadata', data, type, method);
const removed = deepRemove(sourcePath); remove(sourcePath);
const last = removed.pop(); const ppath = [...sourcePath];
ppath.pop();
const s = fn(data, targetPath); const s = fn(data, targetPath);
if (isGridRowOrCol(last)) { const removed = deepRemoveIfEmpty(ppath);
await removeSchema(last); const last = removed.pop();
}
if (['block', 'col'].includes(type)) { if (['block', 'col'].includes(type)) {
await updateSchema(s); await updateSchema(s);
} else { } else {
await createSchema(s); await createSchema(s);
} }
if (isGridRowOrCol(last)) {
await removeSchema(last);
}
} }
}} }}
> >
@ -211,18 +226,22 @@ export const Grid: any = observer((props: any) => {
duration: 20, duration: 20,
easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)', easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)',
}} }}
style={{ whiteSpace: 'nowrap' }} // dropAnimation={null}
// style={{ ...style, pointerEvents: 'none' }} // style={{ whiteSpace: 'nowrap' }}
style={{
width: 40,
whiteSpace: 'nowrap',
// ...style,
// pointerEvents: 'none',
}}
> >
{dragOverlayContent} <div
{/* <div
className={'nb-grid-drag-overlay'} className={'nb-grid-drag-overlay'}
style={{ style={{
...style, ...style,
transform: 'translate(calc(-100% + 30px), 2px)',
}} }}
dangerouslySetInnerHTML={{ __html: dragOverlayContent }} dangerouslySetInnerHTML={{ __html: dragOverlayContent }}
/> */} />
</DragOverlay> </DragOverlay>
<Droppable <Droppable
id={`${schema.name}-row-divider`} id={`${schema.name}-row-divider`}
@ -267,7 +286,7 @@ export const Grid: any = observer((props: any) => {
}); });
Grid.Row = observer((props: any) => { Grid.Row = observer((props: any) => {
const { schema } = useDesignable(); const { designable, schema } = useDesignable();
const columns = Object.values(schema.properties || {}).filter((item) => { const columns = Object.values(schema.properties || {}).filter((item) => {
return !item['x-hidden']; return !item['x-hidden'];
}); });
@ -310,7 +329,10 @@ Grid.Row = observer((props: any) => {
parentPath: [...path], parentPath: [...path],
path: [...path, property.name], path: [...path, property.name],
}} }}
className={cls('nb-grid-col-divider', 'resizable')} disabled={!designable}
className={cls('nb-grid-col-divider', {
resizable: designable,
})}
/> />
)} )}
<GridColContext.Provider value={{ index, width: size[index] }}> <GridColContext.Provider value={{ index, width: size[index] }}>
@ -334,7 +356,7 @@ Grid.Row = observer((props: any) => {
}); });
Grid.Col = observer((props: any) => { Grid.Col = observer((props: any) => {
const { schema } = useDesignable(); const { schema, designable, DesignableBar } = useDesignable();
// const { width } = props; // const { width } = props;
const { columnCount } = useContext(GridRowContext); const { columnCount } = useContext(GridRowContext);
const { width } = useContext(GridColContext); const { width } = useContext(GridColContext);
@ -358,6 +380,9 @@ Grid.Col = observer((props: any) => {
className={'nb-grid-row-divider'} className={'nb-grid-row-divider'}
/> */} /> */}
{props.children} {props.children}
{/* <Grid.Col.DesignableBar /> */}
</Droppable> </Droppable>
); );
}); });
Grid.Col.DesignableBar = DesignableBar;