feat: resize grid columns with drag and drop (#748)
* feat: resize grid columns with drag and drop * fix: column resizing only in designable * fix: batch patch * fix: does not scroll when dragging to a blank block * fix: overflow-x auto
This commit is contained in:
		
							parent
							
								
									56bd996bd4
								
							
						
					
					
						commit
						259393f626
					
				| @ -1,3 +1,4 @@ | |||||||
|  | import { css } from '@emotion/css'; | ||||||
| import { observer, RecursionField, useFieldSchema } from '@formily/react'; | import { observer, RecursionField, useFieldSchema } from '@formily/react'; | ||||||
| import { Space } from 'antd'; | import { Space } from 'antd'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| @ -25,8 +26,15 @@ export const ActionBar = observer((props: any) => { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   return ( |   return ( | ||||||
|     <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', ...style }} {...others}> |     <div | ||||||
|       <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}> |       style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', overflowX: 'auto', ...style }} | ||||||
|  |       {...others} | ||||||
|  |     > | ||||||
|  |       <div className={css` | ||||||
|  |         .ant-space:last-child { | ||||||
|  |           margin-left: 8px; | ||||||
|  |         } | ||||||
|  |       `} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
 | ||||||
|         <DndContext> |         <DndContext> | ||||||
|           <Space> |           <Space> | ||||||
|             {fieldSchema.mapProperties((schema, key) => { |             {fieldSchema.mapProperties((schema, key) => { | ||||||
|  | |||||||
| @ -1,14 +1,14 @@ | |||||||
| import { useDndContext, useDndMonitor, useDroppable } from '@dnd-kit/core'; | import { useDndContext, useDndMonitor, useDraggable, useDroppable } from '@dnd-kit/core'; | ||||||
| import { css } from '@emotion/css'; | import { css } from '@emotion/css'; | ||||||
| import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; | import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; | ||||||
| import { uid } from '@formily/shared'; | import { uid } from '@formily/shared'; | ||||||
| import cls from 'classnames'; | import cls from 'classnames'; | ||||||
| import React, { createContext, useContext, useEffect, useRef, useState } from 'react'; | import React, { createContext, useContext, useEffect, useRef, useState } from 'react'; | ||||||
| import { useFormBlockContext, useSchemaInitializer } from '../../../'; | import { useDesignable, useFormBlockContext, useSchemaInitializer } from '../../../'; | ||||||
| import { DndContext } from '../../common/dnd-context'; | import { DndContext } from '../../common/dnd-context'; | ||||||
| 
 | 
 | ||||||
| const GridRowContext = createContext(null); | const GridRowContext = createContext<any>({}); | ||||||
| const GridColContext = createContext(null); | const GridColContext = createContext<any>({}); | ||||||
| const GridContext = createContext<any>({}); | const GridContext = createContext<any>({}); | ||||||
| 
 | 
 | ||||||
| const breakRemoveOnGrid = (s: Schema) => s['x-component'] === 'Grid'; | const breakRemoveOnGrid = (s: Schema) => s['x-component'] === 'Grid'; | ||||||
| @ -19,6 +19,8 @@ const ColDivider = (props) => { | |||||||
|     id: props.id, |     id: props.id, | ||||||
|     data: props.data, |     data: props.data, | ||||||
|   }); |   }); | ||||||
|  |   const { dn, designable } = useDesignable(); | ||||||
|  |   const dividerRef = useRef<HTMLElement>(); | ||||||
| 
 | 
 | ||||||
|   const droppableStyle = { |   const droppableStyle = { | ||||||
|     backgroundColor: isOver ? 'rgba(241, 139, 98, .1)' : undefined, |     backgroundColor: isOver ? 'rgba(241, 139, 98, .1)' : undefined, | ||||||
| @ -38,10 +40,89 @@ const ColDivider = (props) => { | |||||||
|       visible = activeSchema !== currentSchema && downSchema !== activeSchema; |       visible = activeSchema !== currentSchema && downSchema !== activeSchema; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   const prevSchema = props.cols[props.index]; | ||||||
|  |   const nextSchema = props.cols[props.index + 1]; | ||||||
|  |   const { | ||||||
|  |     attributes, | ||||||
|  |     listeners, | ||||||
|  |     setNodeRef: setDraggableNodeRef, | ||||||
|  |     isDragging, | ||||||
|  |   } = useDraggable({ | ||||||
|  |     disabled: props.first || props.last || !designable, | ||||||
|  |     id: props.id, | ||||||
|  |     data: { | ||||||
|  |       dividerRef, | ||||||
|  |       prevSchema, | ||||||
|  |       nextSchema, | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const [clientWidths, setClientWidths] = useState([0, 0]); | ||||||
|  | 
 | ||||||
|  |   useDndMonitor({ | ||||||
|  |     onDragStart(event) { | ||||||
|  |       if (!isDragging) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       const el = dividerRef.current; | ||||||
|  |       const prev = el.previousElementSibling as HTMLDivElement; | ||||||
|  |       const next = el.nextElementSibling as HTMLDivElement; | ||||||
|  |       setClientWidths([prev.clientWidth, next.clientWidth]); | ||||||
|  |     }, | ||||||
|  |     onDragMove(event) { | ||||||
|  |       if (!isDragging) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       const el = dividerRef.current; | ||||||
|  |       const prev = el.previousElementSibling as HTMLDivElement; | ||||||
|  |       const next = el.nextElementSibling as HTMLDivElement; | ||||||
|  |       prev.style.width = `calc(${clientWidths[0]}px + ${event.delta.x}px)`; | ||||||
|  |       next.style.width = `calc(${clientWidths[1]}px - ${event.delta.x}px)`; | ||||||
|  |     }, | ||||||
|  |     onDragEnd(event) { | ||||||
|  |       if (clientWidths[0] <= 0 || clientWidths[1] <= 0) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       setClientWidths([0, 0]); | ||||||
|  |       if (!prevSchema || !nextSchema) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       const el = dividerRef.current; | ||||||
|  |       const prev = el.previousElementSibling as HTMLDivElement; | ||||||
|  |       const next = el.nextElementSibling as HTMLDivElement; | ||||||
|  |       prevSchema['x-component-props'] = prevSchema['x-component-props'] || {}; | ||||||
|  |       nextSchema['x-component-props'] = nextSchema['x-component-props'] || {}; | ||||||
|  |       prevSchema['x-component-props']['width'] = | ||||||
|  |         (100 * (prev?.clientWidth + 24 + 24 / props.cols.length)) / el.parentElement.clientWidth; | ||||||
|  |       nextSchema['x-component-props']['width'] = | ||||||
|  |         (100 * (next?.clientWidth + 24 + 24 / props.cols.length)) / el.parentElement.clientWidth; | ||||||
|  |       dn.emit('batchPatch', { | ||||||
|  |         schemas: [ | ||||||
|  |           { | ||||||
|  |             ['x-uid']: prevSchema['x-uid'], | ||||||
|  |             'x-component-props': { | ||||||
|  |               ...prevSchema['x-component-props'], | ||||||
|  |             }, | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             ['x-uid']: nextSchema['x-uid'], | ||||||
|  |             'x-component-props': { | ||||||
|  |               ...nextSchema['x-component-props'], | ||||||
|  |             }, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div |     <div | ||||||
|       ref={visible ? setNodeRef : null} |       ref={(el) => { | ||||||
|  |         if (visible) { | ||||||
|  |           setNodeRef(el); | ||||||
|  |           dividerRef.current = el; | ||||||
|  |         } | ||||||
|  |       }} | ||||||
|       className={cls( |       className={cls( | ||||||
|         'nb-col-divider', |         'nb-col-divider', | ||||||
|         css` |         css` | ||||||
| @ -49,7 +130,36 @@ const ColDivider = (props) => { | |||||||
|         `,
 |         `,
 | ||||||
|       )} |       )} | ||||||
|       style={{ ...droppableStyle }} |       style={{ ...droppableStyle }} | ||||||
|  |     > | ||||||
|  |       <div | ||||||
|  |         ref={setDraggableNodeRef} | ||||||
|  |         {...listeners} | ||||||
|  |         {...attributes} | ||||||
|  |         className={ | ||||||
|  |           props.first || props.last || !designable | ||||||
|  |             ? null | ||||||
|  |             : css` | ||||||
|  |                 &::before { | ||||||
|  |                   content: ' '; | ||||||
|  |                   width: 12px; | ||||||
|  |                   height: 100%; | ||||||
|  |                   left: 6px; | ||||||
|  |                   position: absolute; | ||||||
|  |                   cursor: col-resize; | ||||||
|  |                 } | ||||||
|  |                 &:hover { | ||||||
|  |                   &::before { | ||||||
|  |                     background: rgba(241, 139, 98, 0.06) !important; | ||||||
|  |                   } | ||||||
|  |                 } | ||||||
|  |                 width: 24px; | ||||||
|  |                 height: 100%; | ||||||
|  |                 position: absolute; | ||||||
|  |                 cursor: col-resize; | ||||||
|  |               ` | ||||||
|  |         } | ||||||
|       ></div> |       ></div> | ||||||
|  |     </div> | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -255,7 +365,7 @@ Grid.Row = observer((props) => { | |||||||
|   const cols = useColProperties(); |   const cols = useColProperties(); | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <GridRowContext.Provider value={{ cols }}> |     <GridRowContext.Provider value={{ schema: fieldSchema, cols }}> | ||||||
|       <div |       <div | ||||||
|         className={cls( |         className={cls( | ||||||
|           'nb-grid-row', |           'nb-grid-row', | ||||||
| @ -285,6 +395,7 @@ Grid.Row = observer((props) => { | |||||||
|               <ColDivider |               <ColDivider | ||||||
|                 cols={cols} |                 cols={cols} | ||||||
|                 index={index} |                 index={index} | ||||||
|  |                 last={index === cols.length - 1} | ||||||
|                 id={`${addr}_${index + 1}`} |                 id={`${addr}_${index + 1}`} | ||||||
|                 data={{ |                 data={{ | ||||||
|                   breakRemoveOn: breakRemoveOnRow, |                   breakRemoveOn: breakRemoveOnRow, | ||||||
| @ -303,10 +414,22 @@ Grid.Row = observer((props) => { | |||||||
| 
 | 
 | ||||||
| Grid.Col = observer((props: any) => { | Grid.Col = observer((props: any) => { | ||||||
|   const { cols } = useContext(GridRowContext); |   const { cols } = useContext(GridRowContext); | ||||||
|   const w = props.width || 100 / cols.length; |   const schema = useFieldSchema(); | ||||||
|  |   const field = useField(); | ||||||
|  |   const w = schema?.['x-component-props']?.['width'] || 100 / cols.length; | ||||||
|   const width = `calc(${w}% - 24px - 24px / ${cols.length})`; |   const width = `calc(${w}% - 24px - 24px / ${cols.length})`; | ||||||
|  |   const { isOver, setNodeRef } = useDroppable({ | ||||||
|  |     id: field.address.toString(), | ||||||
|  |     data: { | ||||||
|  |       insertAdjacent: 'beforeEnd', | ||||||
|  |       schema, | ||||||
|  |       wrapSchema: (s) => s, | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|   return ( |   return ( | ||||||
|  |     <GridColContext.Provider value={{ cols, schema }}> | ||||||
|       <div |       <div | ||||||
|  |         ref={setNodeRef} | ||||||
|         style={{ width }} |         style={{ width }} | ||||||
|         className={cls( |         className={cls( | ||||||
|           'nb-grid-col', |           'nb-grid-col', | ||||||
| @ -318,5 +441,6 @@ Grid.Col = observer((props: any) => { | |||||||
|       > |       > | ||||||
|         {props.children} |         {props.children} | ||||||
|       </div> |       </div> | ||||||
|  |     </GridColContext.Provider> | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import { DndContext as DndKitContext, DragEndEvent, DragOverlay, rectIntersection } from '@dnd-kit/core'; | import { DndContext as DndKitContext, DragEndEvent, DragOverlay, rectIntersection } from '@dnd-kit/core'; | ||||||
| import { Props } from '@dnd-kit/core/dist/components/DndContext/DndContext'; | import { Props } from '@dnd-kit/core/dist/components/DndContext/DndContext'; | ||||||
| import { observer } from '@formily/react'; | import { observer } from '@formily/react'; | ||||||
| import React from 'react'; | import React, { useState } from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import { useAPIClient } from '../../../'; | import { useAPIClient } from '../../../'; | ||||||
| import { createDesignable, useDesignable } from '../../hooks'; | import { createDesignable, useDesignable } from '../../hooks'; | ||||||
| @ -18,6 +18,7 @@ const useDragEnd = (props?: any) => { | |||||||
|     const insertAdjacent = over?.data?.current?.insertAdjacent; |     const insertAdjacent = over?.data?.current?.insertAdjacent; | ||||||
|     const breakRemoveOn = over?.data?.current?.breakRemoveOn; |     const breakRemoveOn = over?.data?.current?.breakRemoveOn; | ||||||
|     const wrapSchema = over?.data?.current?.wrapSchema; |     const wrapSchema = over?.data?.current?.wrapSchema; | ||||||
|  |     const onSuccess = over?.data?.current?.onSuccess; | ||||||
| 
 | 
 | ||||||
|     if (!activeSchema || !overSchema) { |     if (!activeSchema || !overSchema) { | ||||||
|       props?.onDragEnd?.(event); |       props?.onDragEnd?.(event); | ||||||
| @ -49,6 +50,7 @@ const useDragEnd = (props?: any) => { | |||||||
|         wrap: wrapSchema, |         wrap: wrapSchema, | ||||||
|         breakRemoveOn, |         breakRemoveOn, | ||||||
|         removeParentsIfNoChildren: true, |         removeParentsIfNoChildren: true, | ||||||
|  |         onSuccess, | ||||||
|       }); |       }); | ||||||
|       props?.onDragEnd?.(event); |       props?.onDragEnd?.(event); | ||||||
|       return; |       return; | ||||||
| @ -58,15 +60,25 @@ const useDragEnd = (props?: any) => { | |||||||
| 
 | 
 | ||||||
| export const DndContext = observer((props: Props) => { | export const DndContext = observer((props: Props) => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|  |   const [visible, setVisible] = useState(true); | ||||||
|   return ( |   return ( | ||||||
|     <DndKitContext collisionDetection={rectIntersection} {...props} onDragEnd={useDragEnd(props)}> |     <DndKitContext | ||||||
|  |       collisionDetection={rectIntersection} | ||||||
|  |       {...props} | ||||||
|  |       onDragStart={(event) => { | ||||||
|  |         const { active } = event; | ||||||
|  |         const activeSchema = active?.data?.current?.schema; | ||||||
|  |         setVisible(!!activeSchema); | ||||||
|  |       }} | ||||||
|  |       onDragEnd={useDragEnd(props)} | ||||||
|  |     > | ||||||
|       <DragOverlay |       <DragOverlay | ||||||
|         dropAnimation={{ |         dropAnimation={{ | ||||||
|           duration: 10, |           duration: 10, | ||||||
|           easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)', |           easing: 'cubic-bezier(0.18, 0.67, 0.6, 1.22)', | ||||||
|         }} |         }} | ||||||
|       > |       > | ||||||
|         <span style={{ whiteSpace: 'nowrap' }}>{t('Dragging')}</span> |         {visible && <span style={{ whiteSpace: 'nowrap' }}>{t('Dragging')}</span>} | ||||||
|       </DragOverlay> |       </DragOverlay> | ||||||
|       {props.children} |       {props.children} | ||||||
|     </DndKitContext> |     </DndKitContext> | ||||||
|  | |||||||
| @ -111,7 +111,35 @@ export class Designable { | |||||||
|     if (!api) { |     if (!api) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     this.on('insertAdjacent', async ({ onSuccess, current, position, schema, wrap, removed }) => { |     const updateColumnSize = (parent: Schema) => { | ||||||
|  |       if (!parent) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       const len = Object.values(parent.properties).length; | ||||||
|  |       const schemas = []; | ||||||
|  |       parent.mapProperties((s) => { | ||||||
|  |         s['x-component-props'] = s['x-component-props'] || {}; | ||||||
|  |         s['x-component-props']['width'] = 100 / len; | ||||||
|  |         if (s['x-uid']) { | ||||||
|  |           schemas.push({ | ||||||
|  |             'x-uid': s['x-uid'], | ||||||
|  |             'x-component-props': s['x-component-props'], | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       if (parent['x-uid'] && schemas.length) { | ||||||
|  |         return schemas; | ||||||
|  |       } | ||||||
|  |       return []; | ||||||
|  |     }; | ||||||
|  |     this.on('insertAdjacent', async ({ onSuccess, current, position, schema, wrap, wrapped, removed }) => { | ||||||
|  |       let schemas = []; | ||||||
|  |       if (wrapped?.['x-component'] === 'Grid.Col') { | ||||||
|  |         schemas = updateColumnSize(wrapped.parent); | ||||||
|  |       } | ||||||
|  |       if (removed?.['x-component'] === 'Grid.Col') { | ||||||
|  |         schemas = updateColumnSize(removed.parent); | ||||||
|  |       } | ||||||
|       refresh(); |       refresh(); | ||||||
|       if (!current['x-uid']) { |       if (!current['x-uid']) { | ||||||
|         return; |         return; | ||||||
| @ -124,6 +152,13 @@ export class Designable { | |||||||
|           wrap, |           wrap, | ||||||
|         }, |         }, | ||||||
|       }); |       }); | ||||||
|  |       if (schemas.length) { | ||||||
|  |         await api.request({ | ||||||
|  |           url: `/uiSchemas:batchPatch`, | ||||||
|  |           method: 'post', | ||||||
|  |           data: schemas, | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|       if (removed?.['x-uid']) { |       if (removed?.['x-uid']) { | ||||||
|         await api.request({ |         await api.request({ | ||||||
|           url: `/uiSchemas:remove/${removed['x-uid']}`, |           url: `/uiSchemas:remove/${removed['x-uid']}`, | ||||||
| @ -147,7 +182,20 @@ export class Designable { | |||||||
|       }); |       }); | ||||||
|       message.success(t('Saved successfully'), 0.2); |       message.success(t('Saved successfully'), 0.2); | ||||||
|     }); |     }); | ||||||
|  |     this.on('batchPatch', async ({ schemas }) => { | ||||||
|  |       refresh(); | ||||||
|  |       await api.request({ | ||||||
|  |         url: `/uiSchemas:batchPatch`, | ||||||
|  |         method: 'post', | ||||||
|  |         data: schemas, | ||||||
|  |       }); | ||||||
|  |       message.success(t('Saved successfully'), 0.2); | ||||||
|  |     }); | ||||||
|     this.on('remove', async ({ removed }) => { |     this.on('remove', async ({ removed }) => { | ||||||
|  |       let schemas = []; | ||||||
|  |       if (removed?.['x-component'] === 'Grid.Col') { | ||||||
|  |         schemas = updateColumnSize(removed.parent); | ||||||
|  |       } | ||||||
|       refresh(); |       refresh(); | ||||||
|       if (!removed?.['x-uid']) { |       if (!removed?.['x-uid']) { | ||||||
|         return; |         return; | ||||||
| @ -156,6 +204,13 @@ export class Designable { | |||||||
|         url: `/uiSchemas:remove/${removed['x-uid']}`, |         url: `/uiSchemas:remove/${removed['x-uid']}`, | ||||||
|         method: 'post', |         method: 'post', | ||||||
|       }); |       }); | ||||||
|  |       if (schemas.length) { | ||||||
|  |         await api.request({ | ||||||
|  |           url: `/uiSchemas:batchPatch`, | ||||||
|  |           method: 'post', | ||||||
|  |           data: schemas, | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|       message.success(t('Saved successfully'), 0.2); |       message.success(t('Saved successfully'), 0.2); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @ -177,14 +232,14 @@ export class Designable { | |||||||
|     generateUid(schema); |     generateUid(schema); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   on(name: 'insertAdjacent' | 'remove' | 'error' | 'patch', listener: any) { |   on(name: 'insertAdjacent' | 'remove' | 'error' | 'patch' | 'batchPatch', listener: any) { | ||||||
|     if (!this.events[name]) { |     if (!this.events[name]) { | ||||||
|       this.events[name] = []; |       this.events[name] = []; | ||||||
|     } |     } | ||||||
|     this.events[name].push(listener); |     this.events[name].push(listener); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   emit(name: 'insertAdjacent' | 'remove' | 'error' | 'patch', ...args) { |   emit(name: 'insertAdjacent' | 'remove' | 'error' | 'patch' | 'batchPatch', ...args) { | ||||||
|     if (!this.events[name]) { |     if (!this.events[name]) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| @ -356,6 +411,7 @@ export class Designable { | |||||||
|     this.emit('insertAdjacent', { |     this.emit('insertAdjacent', { | ||||||
|       position: 'beforeBegin', |       position: 'beforeBegin', | ||||||
|       schema: schema2, |       schema: schema2, | ||||||
|  |       wrapped, | ||||||
|       wrap: schema1, |       wrap: schema1, | ||||||
|       ...opts, |       ...opts, | ||||||
|     }); |     }); | ||||||
| @ -407,6 +463,7 @@ export class Designable { | |||||||
|       position: 'afterBegin', |       position: 'afterBegin', | ||||||
|       schema: schema2, |       schema: schema2, | ||||||
|       wrap: schema1, |       wrap: schema1, | ||||||
|  |       wrapped, | ||||||
|       ...opts, |       ...opts, | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @ -421,6 +478,7 @@ export class Designable { | |||||||
|     if (!Schema.isSchemaInstance(this.current)) { |     if (!Schema.isSchemaInstance(this.current)) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |     delete schema['x-index']; | ||||||
|     const opts = { onSuccess: options.onSuccess }; |     const opts = { onSuccess: options.onSuccess }; | ||||||
|     const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options; |     const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options; | ||||||
|     if (Schema.isSchemaInstance(schema)) { |     if (Schema.isSchemaInstance(schema)) { | ||||||
| @ -447,6 +505,7 @@ export class Designable { | |||||||
|       position: 'beforeEnd', |       position: 'beforeEnd', | ||||||
|       schema: schema2, |       schema: schema2, | ||||||
|       wrap: schema1, |       wrap: schema1, | ||||||
|  |       wrapped, | ||||||
|       ...opts, |       ...opts, | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @ -508,6 +567,7 @@ export class Designable { | |||||||
|       position: 'afterEnd', |       position: 'afterEnd', | ||||||
|       schema: schema2, |       schema: schema2, | ||||||
|       wrap: schema1, |       wrap: schema1, | ||||||
|  |       wrapped, | ||||||
|       ...opts, |       ...opts, | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ export const uiSchemaActions = { | |||||||
|   insertNewSchema: callRepositoryMethod('insertNewSchema', 'values'), |   insertNewSchema: callRepositoryMethod('insertNewSchema', 'values'), | ||||||
|   remove: callRepositoryMethod('remove', 'resourceIndex'), |   remove: callRepositoryMethod('remove', 'resourceIndex'), | ||||||
|   patch: callRepositoryMethod('patch', 'values'), |   patch: callRepositoryMethod('patch', 'values'), | ||||||
|  |   batchPatch: callRepositoryMethod('batchPatch', 'values'), | ||||||
|   clearAncestor: callRepositoryMethod('clearAncestor', 'resourceIndex'), |   clearAncestor: callRepositoryMethod('clearAncestor', 'resourceIndex'), | ||||||
| 
 | 
 | ||||||
|   async insertAdjacent(ctx: Context, next) { |   async insertAdjacent(ctx: Context, next) { | ||||||
|  | |||||||
| @ -303,6 +303,14 @@ export class UiSchemaRepository extends Repository { | |||||||
|     await traverSchemaTree(newSchema); |     await traverSchemaTree(newSchema); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @transaction() | ||||||
|  |   async batchPatch(schemas: any[], options?) { | ||||||
|  |     const { transaction } = options; | ||||||
|  |     for (const schema of schemas) { | ||||||
|  |       await this.patch(schema, { ...options, transaction }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   async updateNode(uid: string, schema: any, transaction?: Transaction) { |   async updateNode(uid: string, schema: any, transaction?: Transaction) { | ||||||
|     const nodeModel = await this.findOne({ |     const nodeModel = await this.findOne({ | ||||||
|       filter: { |       filter: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user