From 97d2e9ec1ddcb2d58702290960bcb858cae3dce4 Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Tue, 23 Aug 2016 20:28:07 +0300 Subject: [PATCH] feat(tabs, sortables): add tabs reordering feature --- package.json | 1 + .../styles/components/TabsItem.scss | 3 + src/client/editor/components/TabsItem.jsx | 4 +- src/client/editor/containers/Tabs.jsx | 79 ++++++++++++++++--- src/client/utils/array.js | 19 +++++ 5 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 src/client/utils/array.js diff --git a/package.json b/package.json index 7c14bdfe..9720fbb0 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react-hotkeys": "git+https://github.com/brusherru/react-hotkeys.git#npm", "react-redux": "^4.0.6", "react-skylight": "^0.4.0", + "react-sortable-hoc": "0.0.7", "react-ui-tree": "^2.5.0", "redux": "^3.0.5", "redux-thunk": "^2.1.0", diff --git a/src/client/app-browser/styles/components/TabsItem.scss b/src/client/app-browser/styles/components/TabsItem.scss index ba9b527c..394ede11 100644 --- a/src/client/app-browser/styles/components/TabsItem.scss +++ b/src/client/app-browser/styles/components/TabsItem.scss @@ -5,6 +5,8 @@ padding: 0 10px 0 14px; height: 26px; + box-sizing: border-box; + background: $color-tabs-unactive-background; color: $color-tabs-unactive-text; line-height: 30px; @@ -13,6 +15,7 @@ border-top-left-radius: 4px; text-shadow: 0 1px 0 rgba(0,0,0, .5); cursor: default; + white-space: nowrap; transition: 0.1s ease-out all; diff --git a/src/client/editor/components/TabsItem.jsx b/src/client/editor/components/TabsItem.jsx index 5070106c..3f7e5372 100644 --- a/src/client/editor/components/TabsItem.jsx +++ b/src/client/editor/components/TabsItem.jsx @@ -15,14 +15,14 @@ const TabsItem = ({ data, onClick, onClose }) => { return (
  • {data.name} × diff --git a/src/client/editor/containers/Tabs.jsx b/src/client/editor/containers/Tabs.jsx index bd51c376..19786eee 100644 --- a/src/client/editor/containers/Tabs.jsx +++ b/src/client/editor/containers/Tabs.jsx @@ -5,15 +5,65 @@ import { bindActionCreators } from 'redux'; import * as Actions from '../actions'; import * as EditorSelectors from '../selectors'; +import { arrayMoveIndex, arrayUpdateIndex, arrayIndexById } from 'xod/client/utils/array'; + +import { + SortableContainer as sortableContainer, + SortableElement as sortableElement, +} from 'react-sortable-hoc'; + import TabsContainer from '../components/TabsContainer'; import TabsItem from '../components/TabsItem'; +const SortableItem = sortableElement( + ({ value }) => { + return ( + + ); + } +); + +const SortableList = sortableContainer( + ({ items, onClick, onClose }) => ( + + {items.map((value, index) => { + const item = R.merge( + value, + { + onClick, + onClose, + } + ); + + return ( + + ); + } + )} + + ) +); + + class Tabs extends React.Component { constructor(props) { super(props); this.onSwitchPatch = this.onSwitchPatch.bind(this); this.onCloseTab = this.onCloseTab.bind(this); + this.onSortEnd = this.onSortEnd.bind(this); } onSwitchPatch(patchId) { @@ -24,6 +74,14 @@ class Tabs extends React.Component { return this.props.actions.closeTab(patchId); } + onSortEnd(changes) { + const sortedTabs = arrayMoveIndex(changes.oldIndex, changes.newIndex, this.getTabs()); + const newTabs = arrayUpdateIndex(sortedTabs); + const indexedTabs = arrayIndexById(newTabs); + + this.props.actions.sortTabs(indexedTabs); + } + getTabs() { return R.sortBy( R.prop('index') @@ -33,16 +91,17 @@ class Tabs extends React.Component { render() { const tabs = this.getTabs(); return ( - - {tabs.map(tab => - - )} - + ); } } diff --git a/src/client/utils/array.js b/src/client/utils/array.js new file mode 100644 index 00000000..9f10f3a2 --- /dev/null +++ b/src/client/utils/array.js @@ -0,0 +1,19 @@ +import R from 'ramda'; + +const mapIndexed = R.addIndex(R.map); + +export const arrayMoveIndex = R.curry( + (oldIndex, newIndex, array) => { + const oldItem = R.nth(oldIndex, array); + const newItem = R.nth(newIndex, array); + + return R.pipe( + R.update(oldIndex, newItem), + R.update(newIndex, oldItem) + )(array); + } +); + +export const arrayUpdateIndex = mapIndexed((item, index) => R.assoc('index', index, item)); + +export const arrayIndexById = R.indexBy(R.prop('id'));