Persist collapsed nodes

This commit is contained in:
Jori Lallo
2016-07-07 00:27:11 -07:00
parent 4f86ea0a59
commit b8da23556e
3 changed files with 67 additions and 15 deletions

View File

@ -10,7 +10,8 @@ module.exports = React.createClass({
propTypes: { propTypes: {
tree: React.PropTypes.object.isRequired, tree: React.PropTypes.object.isRequired,
paddingLeft: React.PropTypes.number, paddingLeft: React.PropTypes.number,
renderNode: React.PropTypes.func.isRequired renderNode: React.PropTypes.func.isRequired,
onCollapse: React.PropTypes.func,
}, },
getDefaultProps() { getDefaultProps() {
@ -230,8 +231,7 @@ module.exports = React.createClass({
tree: tree tree: tree
}); });
// Don't push updates as collapsing is separated from store state if(this.props.onCollapse) this.props.onCollapse(node.id, node.collapsed);
// this.change(tree);
}, },
// buildTreeNumbering(tree) { // buildTreeNumbering(tree) {

View File

@ -3,7 +3,9 @@ import { toJS } from 'mobx';
import { Link, browserHistory } from 'react-router'; import { Link, browserHistory } from 'react-router';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import DocumentSceneStore from './DocumentSceneStore'; import DocumentSceneStore, {
DOCUMENT_PREFERENCES
} from './DocumentSceneStore';
import Layout, { HeaderAction } from 'components/Layout'; import Layout, { HeaderAction } from 'components/Layout';
import AtlasPreviewLoading from 'components/AtlasPreviewLoading'; import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
@ -29,7 +31,7 @@ class DocumentScene extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.store = new DocumentSceneStore(); this.store = new DocumentSceneStore(JSON.parse(localStorage[DOCUMENT_PREFERENCES]));
} }
componentDidMount = () => { componentDidMount = () => {
@ -77,10 +79,6 @@ class DocumentScene extends React.Component {
); );
} }
handleChange = (tree) => {
this.store.updateNavigationTree(tree);
}
render() { render() {
const doc = this.store.document; const doc = this.store.document;
const allowDelete = doc && doc.atlas.type === 'atlas' && const allowDelete = doc && doc.atlas.type === 'atlas' &&
@ -127,11 +125,12 @@ class DocumentScene extends React.Component {
{ this.store.isAtlas ? ( { this.store.isAtlas ? (
<div className={ styles.sidebar }> <div className={ styles.sidebar }>
<Tree <Tree
paddingLeft={10} paddingLeft={ 10 }
tree={ toJS(doc.atlas.navigationTree) } tree={ toJS(this.store.atlasTree) }
onChange={this.handleChange} onChange={ this.store.updateNavigationTree }
isNodeCollapsed={this.isNodeCollapsed} onCollapse={ this.store.onNodeCollapse }
renderNode={this.renderNode} isNodeCollapsed={ this.isNodeCollapsed }
renderNode={ this.renderNode }
/> />
</div> </div>
) : null } ) : null }

View File

@ -1,10 +1,15 @@
import _isEqual from 'lodash/isEqual'; import _isEqual from 'lodash/isEqual';
import { observable, action, computed, runInAction, toJS } from 'mobx'; import _indexOf from 'lodash/indexOf';
import _without from 'lodash/without';
import { observable, action, computed, runInAction, toJS, autorun } from 'mobx';
import { client } from 'utils/ApiClient'; import { client } from 'utils/ApiClient';
import { browserHistory } from 'react-router'; import { browserHistory } from 'react-router';
const DOCUMENT_PREFERENCES = 'DOCUMENT_PREFERENCES';
class DocumentSceneStore { class DocumentSceneStore {
@observable document; @observable document;
@observable collapsedNodes = [];
@observable isFetching = true; @observable isFetching = true;
@observable updatingContent = false; @observable updatingContent = false;
@ -18,6 +23,24 @@ class DocumentSceneStore {
this.document.atlas.type === 'atlas'; this.document.atlas.type === 'atlas';
} }
@computed get atlasTree() {
if (this.document.atlas.type !== 'atlas') return;
let tree = this.document.atlas.navigationTree;
const collapseNodes = (node) => {
if (this.collapsedNodes.includes(node.id)) {
node.collapsed = true;
}
node.children = node.children.map(childNode => {
return collapseNodes(childNode);
})
return node;
};
return collapseNodes(toJS(tree));
}
/* Actions */ /* Actions */
@action fetchDocument = async (id, softLoad) => { @action fetchDocument = async (id, softLoad) => {
@ -71,6 +94,36 @@ class DocumentSceneStore {
} }
this.updatingStructure = false; this.updatingStructure = false;
} }
@action onNodeCollapse = (nodeId, collapsed) => {
if (_indexOf(this.collapsedNodes, nodeId) >= 0) {
this.collapsedNodes = _without(this.collapsedNodes, nodeId);
} else {
this.collapsedNodes.push(nodeId);
}
}
// General
persistSettings = () => {
localStorage[DOCUMENT_PREFERENCES] = JSON.stringify({
collapsedNodes: toJS(this.collapsedNodes),
});
}
constructor(settings) {
// Rehydrate settings
this.collapsedNodes = settings.collapsedNodes;
// Persist settings to localStorage
// TODO: This could be done more selectively
autorun(() => {
this.persistSettings();
});
}
}; };
export default DocumentSceneStore; export default DocumentSceneStore;
export {
DOCUMENT_PREFERENCES,
};