Эх сурвалжийг харах

Merge pull request #2 from dive2Pro/master

(feature):  添加记录操作的功能
ZhengFang 7 жил өмнө
parent
commit
58ea96a4a9

+ 1 - 0
.gitignore

@@ -1,3 +1,4 @@
 .DS_Store
 .DS_Store
 node_modules/
 node_modules/
 npm-debug.log
 npm-debug.log
+yarn.lock

+ 121 - 0
src/HistoryLayout/HistoryLayout.tsx

@@ -0,0 +1,121 @@
+import * as React from 'react';
+
+import { DragactProps, DragactLayoutItem, Dragact } from '../lib/dragact';
+import { GridItemEvent } from '../lib/GridItem';
+
+interface HistoryDragactState {
+  layout: DragactLayoutItem[]
+}
+
+export class HistoryDragact extends React.Component<DragactProps, HistoryDragactState > {
+  _actionsHistory : string[] = []
+  _cacheLayouts: string;
+  _activeItem: GridItemEvent
+  _dragact: Dragact | null
+  constructor(props: DragactProps) {
+      super(props);
+      this.state= {layout: props.layout} as any;
+  }
+
+  _cacheCurrentLayoutStart = (layoutItem: GridItemEvent) => {
+      this._activeItem = layoutItem
+      if (!this._dragact) {
+          return;
+      }
+      this._cachingLayouts(this._dragact);
+  }
+
+  _cacheCurrentLayoutEnd = (layoutItem: GridItemEvent) => {
+      const { GridY, GridX, h, w } = this._activeItem;
+      if (GridX === layoutItem.GridX && GridY === layoutItem.GridY && h === layoutItem.h && w === layoutItem.w) {
+          return;
+  }
+      this._storeLayoutToHistory(this._cacheLayouts)
+  }
+ 
+  _cachingLayouts = (d: Dragact) => {
+      const initiateSnapShot = JSON.stringify({
+          layout: d.getLayout(),
+      })
+      return this._cacheLayouts = initiateSnapShot;
+  }
+
+  goBack = () => {
+      const mapLayoutHistory = this._actionsHistory;
+      if (mapLayoutHistory.length > 1) {
+          const last = mapLayoutHistory.pop();
+          if(!last) {
+              return;
+          }
+          this._changeDragactLayouts(last);
+      }
+  }
+
+  reset = () => {
+      if (!this._dragact) {
+          return;
+      }
+      this._cachingLayouts(this._dragact);
+      this._storeLayoutToHistory(this._cacheLayouts);
+      const initiateSnapShot = this._actionsHistory[0];
+      this._changeDragactLayouts(initiateSnapShot);        
+  }
+  
+  clear = () => {
+      this._actionsHistory = this._actionsHistory.slice(0, 1);
+      this._changeDragactLayouts(this._actionsHistory[0]);
+  }
+
+  onDragStart = (event: GridItemEvent) => {
+      this._cacheCurrentLayoutStart(event)
+      this.props.onDragStart && this.props.onDragStart(event)
+  }
+
+  onDragEnd = (event: GridItemEvent) => {
+      this._cacheCurrentLayoutEnd(event);
+      this.props.onDragEnd && this.props.onDragEnd(event)
+  }
+
+  _changeDragactLayouts = (snapshot: string) => {
+      if(!this._dragact) {
+          return;
+      }
+      try {
+          const {layout} = JSON.parse(snapshot);
+          this.setState({
+              layout
+          })
+      }catch (e) {
+      }
+     
+  }
+
+  _storeLayoutToHistory = (layouts: string) => {
+      this._actionsHistory.push(layouts);
+  }
+
+  componentDidMount() {
+      if (this._dragact) {
+          const initiateSnapShot = this._cachingLayouts(this._dragact);
+          this._storeLayoutToHistory(initiateSnapShot)
+      }
+  }
+
+  componentWillReceiveProps(nextProps: DragactProps) {
+      this.setState({
+          layout: nextProps.layout
+      })
+  }
+  _dragactRefCallback = (d: Dragact) => {
+      this._dragact = d;
+  }
+
+  get getDragact() {
+      return this._dragact;
+  }
+
+  render () {
+      const layout = this.state.layout;
+      return <Dragact ref={this._dragactRefCallback} {...this.props} layout={layout} onDragStart={this.onDragStart} onDragEnd={this.onDragEnd} />
+    }
+}

+ 13 - 0
src/HistoryLayout/index.css

@@ -0,0 +1,13 @@
+.layout-Item {
+    background: white;
+    height: 100%;
+    border-radius: 3px;
+}
+
+.layout-item:hover {
+    cursor: -webkit-grab;
+}
+
+.normal-layout {
+    background: #d9d9d9;
+}

+ 106 - 0
src/HistoryLayout/index.tsx

@@ -0,0 +1,106 @@
+import *as React from 'react';
+import { DragactLayoutItem, GridItemProvided} from '../../src/lib/dragact'
+import { HistoryDragact } from './HistoryLayout'
+import { Words } from './largedata';
+import './index.css';
+
+const fakeData = () => {
+    var Y = 0;
+    return Words.map((item, index) => {
+        if (index % 4 === 0) Y++;
+
+        return { ...item, GridX: index % 4 * 4, GridY: Y * 4, w: 4, h: 3, key: index + '' }
+    })
+}
+
+
+export const Card: (any: any) => any = ({ item, provided }) => {
+    return (
+        <div
+            className='layout-Item'
+            {...provided.props}
+            {...provided.dragHandle}
+            style={{
+                ...provided.props.style,
+                background: `${provided.isDragging ? '#eaff8f' : 'white'}`
+            }}
+        >
+            <div
+                style={{ padding: 5, textAlign: 'center', color: '#595959' }}
+            >
+                <span>title</span>
+                <div style={{ borderBottom: '1px solid rgba(120,120,120,0.1)' }} />
+                {item.content}
+            </div>
+            <span
+                {...provided.resizeHandle}
+                style={{
+                    position: 'absolute',
+                    width: 10, height: 10, right: 2, bottom: 2, cursor: 'se-resize',
+                    borderRight: '2px solid rgba(15,15,15,0.2)',
+                    borderBottom: '2px solid rgba(15,15,15,0.2)'
+                }}
+            />
+        </div>
+    )
+}
+
+
+export class HistoryDemo extends React.Component<{}, {}> {
+    drag: HistoryDragact | null
+    render() {
+        const margin: [number, number] = [5, 5];
+        const dragactInit = {
+            width: 600,
+            col: 16,
+            rowHeight: 40,
+            margin: margin,
+            className: 'normal-layout',
+            layout: fakeData()
+        }
+        return (
+            <div
+                style={{
+                    display: 'flex',
+                    justifyContent: 'center'
+                }}
+            >
+                <div>
+                    <h1 style={{ textAlign: 'center' }}>
+                        复原操作demo
+                    </h1>
+                    <button onClick={ () => {
+                        if (this.drag) {
+                            this.drag.goBack();
+                        }
+                    }}>back</button>
+                    <button onClick={ () => {
+                        if (this.drag) {
+                            this.drag.reset();
+                        }
+                    }}>reset</button>
+                    <button onClick={ () => {
+                        if (this.drag) {
+                            this.drag.clear();
+                        }
+                    }}>clear</button>
+                    <HistoryDragact
+                        {...dragactInit}
+                        placeholder={true}
+                        ref={n => this.drag = n}
+                        style={{
+                            background: '#003A8C'
+                        }}
+                    >
+                        {(item: DragactLayoutItem, provided: GridItemProvided) => {
+                            return <Card
+                                item={item}
+                                provided={provided}
+                            />
+                        }}
+                    </HistoryDragact>
+                </div>
+            </div>
+        )
+    }
+}

+ 31 - 0
src/HistoryLayout/largedata.ts

@@ -0,0 +1,31 @@
+export const Words = [
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' },
+    { content: 'I’d rather live with a good question than a bad answer.' },
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' },
+    { content: 'I’d rather live with a good question than a bad answer.' },
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' },
+    { content: 'I’d rather live with a good question than a bad answer.' },
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' },
+    { content: 'I’d rather live with a good question than a bad answer.' },
+    { content: 'You can do anything, but not everything.' },
+    { content: 'Those who dare to fail miserably can achieve greatly.' },
+    { content: 'You miss 100 percent of the shots you never take.' },
+    { content: 'Those who believe in telekinetics, raise my hand.' }
+]

+ 4 - 1
src/index.tsx

@@ -5,6 +5,7 @@ import { SortedTableWithStatic } from "./StaticWidget/index";
 import { LayoutRestore } from "./LayoutRestore/index";
 import { LayoutRestore } from "./LayoutRestore/index";
 import { HandleLayout } from "./HandleLayout/index";
 import { HandleLayout } from "./HandleLayout/index";
 import { AddRemove } from "./AddRemove/index";
 import { AddRemove } from "./AddRemove/index";
+import { HistoryDemo } from "./HistoryLayout/index";
 import { Mobile } from "./mobileLayout/index";
 import { Mobile } from "./mobileLayout/index";
 import './index.css'
 import './index.css'
 // import { Dragact } from "./lib/dragact";
 // import { Dragact } from "./lib/dragact";
@@ -18,7 +19,8 @@ const DemoMap: any = {
     LayoutRestore: <LayoutRestore />,
     LayoutRestore: <LayoutRestore />,
     HandleLayout: <HandleLayout />,
     HandleLayout: <HandleLayout />,
     AddRemove: <AddRemove />,
     AddRemove: <AddRemove />,
-    Mobile: <Mobile />
+    Mobile: <Mobile />,
+    HistoryLayout: <HistoryDemo />
 }
 }
 
 
 class DemoDispatcher extends React.Component<{}, {}> {
 class DemoDispatcher extends React.Component<{}, {}> {
@@ -45,6 +47,7 @@ class DemoDispatcher extends React.Component<{}, {}> {
                     <button onClick={() => this.handleLayoutChange('normalLayout')}>普通布局</button>
                     <button onClick={() => this.handleLayoutChange('normalLayout')}>普通布局</button>
                     <button onClick={() => this.handleLayoutChange('StaticHeader')}>静态组件</button>
                     <button onClick={() => this.handleLayoutChange('StaticHeader')}>静态组件</button>
                     <button onClick={() => this.handleLayoutChange('LayoutRestore')}>存储布局</button>
                     <button onClick={() => this.handleLayoutChange('LayoutRestore')}>存储布局</button>
+                    <button onClick={() => this.handleLayoutChange('HistoryLayout')}>记忆操作布局</button>
                     <button onClick={() => this.handleLayoutChange('HandleLayout')}>拖拽把手</button>
                     <button onClick={() => this.handleLayoutChange('HandleLayout')}>拖拽把手</button>
                     <button onClick={() => this.handleLayoutChange('AddRemove')}>增加和删除</button>
                     <button onClick={() => this.handleLayoutChange('AddRemove')}>增加和删除</button>
                     <button onClick={() => this.handleLayoutChange('Mobile')}>移动端</button>
                     <button onClick={() => this.handleLayoutChange('Mobile')}>移动端</button>

+ 21 - 18
src/lib/dragact.tsx

@@ -87,7 +87,6 @@ export interface DragactProps {
     placeholder?: Boolean
     placeholder?: Boolean
 
 
     style?: React.CSSProperties
     style?: React.CSSProperties
-
 }
 }
 
 
 export interface mapLayout {
 export interface mapLayout {
@@ -115,6 +114,7 @@ export interface GridItemProvided {
 }
 }
 
 
 export class Dragact extends React.Component<DragactProps, DragactState> {
 export class Dragact extends React.Component<DragactProps, DragactState> {
+   
     constructor(props: DragactProps) {
     constructor(props: DragactProps) {
         super(props)
         super(props)
         this.onDrag = this.onDrag.bind(this)
         this.onDrag = this.onDrag.bind(this)
@@ -122,7 +122,6 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
         this.onDragEnd = this.onDragEnd.bind(this)
         this.onDragEnd = this.onDragEnd.bind(this)
 
 
         const layout = props.layout;
         const layout = props.layout;
-
         this.state = {
         this.state = {
             GridXMoving: 0,
             GridXMoving: 0,
             GridYMoving: 0,
             GridYMoving: 0,
@@ -136,6 +135,7 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
             mapLayout: undefined
             mapLayout: undefined
         }
         }
     }
     }
+
     onResizeStart = (layoutItem: GridItemEvent) => {
     onResizeStart = (layoutItem: GridItemEvent) => {
         const { GridX, GridY, w, h } = layoutItem
         const { GridX, GridY, w, h } = layoutItem
         if (this.state.mapLayout) {
         if (this.state.mapLayout) {
@@ -151,6 +151,7 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
                 dragType: 'resize'
                 dragType: 'resize'
             })
             })
         }
         }
+        this.props.onDragStart && this.props.onDragStart(layoutItem);
     }
     }
 
 
     onResizing = (layoutItem: GridItemEvent) => {
     onResizing = (layoutItem: GridItemEvent) => {
@@ -181,7 +182,6 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
 
 
     onDragStart(bundles: GridItemEvent) {
     onDragStart(bundles: GridItemEvent) {
         const { GridX, GridY, w, h } = bundles
         const { GridX, GridY, w, h } = bundles
-
         if (this.state.mapLayout) {
         if (this.state.mapLayout) {
             this.setState({
             this.setState({
                 GridXMoving: GridX,
                 GridXMoving: GridX,
@@ -194,12 +194,10 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
                 dragType: 'drag'
                 dragType: 'drag'
             })
             })
         }
         }
-
-        this.props.onDragStart && this.props.onDragStart(bundles)
+        this.props.onDragStart && this.props.onDragStart(bundles);
     }
     }
 
 
     onDrag(layoutItem: GridItemEvent) {
     onDrag(layoutItem: GridItemEvent) {
-
         const { GridY, UniqueKey } = layoutItem;
         const { GridY, UniqueKey } = layoutItem;
         const moving = GridY - this.state.GridYMoving;
         const moving = GridY - this.state.GridYMoving;
 
 
@@ -216,18 +214,16 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
     }
     }
 
 
     onDragEnd(layoutItem: GridItemEvent) {
     onDragEnd(layoutItem: GridItemEvent) {
-
         const { compacted, mapLayout } = compactLayout(this.state.layout, undefined, this.state.mapLayout)
         const { compacted, mapLayout } = compactLayout(this.state.layout, undefined, this.state.mapLayout)
-
         this.setState({
         this.setState({
             placeholderShow: false,
             placeholderShow: false,
             layout: compacted,
             layout: compacted,
             mapLayout: mapLayout,
             mapLayout: mapLayout,
             containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
             containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
         })
         })
-
         this.props.onDragEnd && this.props.onDragEnd(layoutItem);
         this.props.onDragEnd && this.props.onDragEnd(layoutItem);
     }
     }
+
     renderPlaceholder() {
     renderPlaceholder() {
         if (!this.state.placeholderShow) return null
         if (!this.state.placeholderShow) return null
         var { col, width, padding, rowHeight, margin, placeholder } = this.props
         var { col, width, padding, rowHeight, margin, placeholder } = this.props
@@ -276,8 +272,7 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
                     mapLayout
                     mapLayout
                 })
                 })
             }
             }
-        }
-        if (this.props.layout.length < nextProps.layout.length) {//add
+        }  else  if (this.props.layout.length < nextProps.layout.length) {//add
             var item;
             var item;
             for (const idx in nextProps.layout) {
             for (const idx in nextProps.layout) {
                 const i = nextProps.layout[idx];
                 const i = nextProps.layout[idx];
@@ -300,18 +295,24 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
                     mapLayout
                     mapLayout
                 })
                 })
             }
             }
+        } else {
+            this.recalculateLayout(nextProps.layout, nextProps.col);
         }
         }
     }
     }
 
 
+    recalculateLayout = (layout: DragactLayoutItem[], col: number) => {
+        const corrected = correctLayout(layout, col)
+        const { compacted, mapLayout } = compactLayout(corrected, undefined, undefined);
+        this.setState({
+            layout: compacted,
+            mapLayout: mapLayout,
+            containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight, false)
+        })
+    }
+
     componentDidMount() {
     componentDidMount() {
         setTimeout(() => {
         setTimeout(() => {
-            let layout = correctLayout(this.state.layout, this.props.col)
-            const { compacted, mapLayout } = compactLayout(layout, undefined, this.state.mapLayout);
-            this.setState({
-                layout: compacted,
-                mapLayout: mapLayout,
-                containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight, false)
-            })
+            this.recalculateLayout(this.state.layout, this.props.col)
         }, 1);
         }, 1);
     }
     }
 
 
@@ -350,6 +351,7 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
             )
             )
         }
         }
     }
     }
+
     render() {
     render() {
         const {
         const {
             width,
             width,
@@ -361,6 +363,7 @@ export class Dragact extends React.Component<DragactProps, DragactState> {
 
 
         return (
         return (
             <div
             <div
+
                 className={stringJoin('DraggerLayout', className + '')}
                 className={stringJoin('DraggerLayout', className + '')}
                 style={{
                 style={{
                     ...style,
                     ...style,

+ 1 - 1
src/lib/util/compact.ts

@@ -39,7 +39,7 @@ export const compactLayout = function () {
     var _cache: any = {
     var _cache: any = {
     };
     };
 
 
-    return function (layout: DragactLayoutItem[], movingItem: GridItemEvent | undefined, mapedLayout: any) {
+    return function (layout: DragactLayoutItem[], movingItem: GridItemEvent | undefined, mapedLayout: mapLayout | undefined) {
         if (movingItem) {
         if (movingItem) {
             if (_cache.GridX === movingItem.GridX
             if (_cache.GridX === movingItem.GridX
                 && _cache.GridY === movingItem.GridY &&
                 && _cache.GridY === movingItem.GridY &&