Add state for navigation

Currently selected navigation item is available under the navigation
variable so that the whole application has access to it.
This commit is contained in:
Joey Payne 2016-03-06 11:08:42 -07:00
commit d14eed9965
10 changed files with 154 additions and 45 deletions

View file

@ -0,0 +1,5 @@
import * as types from '../constants/navigation'
export function updateSelection(selection) {
return { type: types.UPDATE_SELECTION, selection }
}

View file

@ -39,7 +39,7 @@ export default class EntrySelector extends React.Component {
constructor(props){
super(props)
this.state = {entries: []}
this.state = {notes: []}
}
static get childContextTypes(){
@ -57,14 +57,7 @@ export default class EntrySelector extends React.Component {
}
addNoteTapped = () => {
this.createNewNote((note) => {
var notes = this.state.notes
notes.splice(0, 0, note)
this.setState({notes: notes}, () => {
//this.refs['textField0'].focus()
})
})
console.log(this.props.navigation)
};
render(){

View file

@ -54,32 +54,33 @@ export default class LibraryNav extends React.Component {
navItems: [
{
'name': 'Entries',
'isNotebook': true,
'icon': <img src="images/note.svg"/>,
'notes': 10,
'clicked': this.props.entriesTapped || this.entriesTapped
},
{
'name': 'Starred',
'notes': 0,
'icon': <ActionGrade color={colors.amberA700}/>,
'notes': 1,
'clicked': this.props.starredTapped || this.starredTapped
},
{
'name': 'Recents',
'notes': 0,
'icon': <History color="#4BAE4E"/>,
'notes': 10,
'clicked': this.props.recentsTapped || this.recentsTapped
},
{
'name': 'Trash',
'isNotebook': true,
'icon': <Delete color={colors.grey500}/>,
'notes': 0,
'clicked': this.props.trashTapped || this.trashTapped
},
{
'name': 'All Notes',
'icon': <Folder color="#FFCC5F" />,
'notes': 0,
'glob': '*.qvnotebook/*.qvnote',
'icon': <Folder color="#FFCC5F" />,
'clicked': this.props.allNotesTapped || this.allNotesTapped
},
@ -87,12 +88,44 @@ export default class LibraryNav extends React.Component {
notebooks: [
]
}
this.loadDefaultNotebooks()
this.getNotebooks()
}
loadDefaultNotebooks = () => {
var notebooks = this.state.navItems
for(var i=0; i<notebooks.length; i++){
var nb = notebooks[i]
if(nb.isNotebook){
var temp = {
title: nb.name,
uuid: nb.name,
notes: 0
}
this.initDefaultNotebookPath(temp)
var loaded = utils.loadNotebookByName(nb.name)
nb.title = loaded.title
nb.uuid = loaded.uuid
nb.path = loaded.path
nb.notes = loaded.notes
}
else if(nb.glob){
var dataPath = utils.getAppDataPath()
var notes = glob.sync(path.join(dataPath, nb.glob))
nb.title = nb.name
nb.uuid = nb.name
nb.notes = notes.length
}
}
};
getNotebooks = () => {
var dataPath = utils.getAppDataPath()
var notebooks = glob.sync(path.join(dataPath, '*.qvnotebook'))
var notebooks = glob.sync(path.join(dataPath, '!(Entries|Trash).qvnotebook'))
for(var i=0; i<notebooks.length; i++){
var nbFile = notebooks[i]
var obj = jsfile.readFileSync(path.join(nbFile, 'meta.json'))
@ -187,6 +220,39 @@ export default class LibraryNav extends React.Component {
};
initDefaultNotebookPath = (notebook) => {
var nbPath = utils.getNotebookPath(notebook)
var dir = mkdirp.sync(nbPath)
var notePath = utils.getNotebookPath(notebook)
var meta = {
'name': notebook.title,
'uuid': notebook.uuid
}
var metaPath = path.join(nbPath, 'meta.json')
var t = jsfile.writeFileSync(metaPath, meta)
};
createNotebookPath = (notebook, callback) => {
mkdirp(notebook.path, (err) => {
if(err){
console.log('There was an error creating the directory '+notebook.path)
console.log(err)
}
else{
var nbs = this.state.notebooks
nbs.splice(0, 0, notebook)
this.setState({notebooks: nbs}, () => {
this.createNotebookMeta(notebook, callback)
})
}
})
};
createNewNotebook = (callback) => {
var nbUuid = uuid.v4().toUpperCase()
@ -200,23 +266,7 @@ export default class LibraryNav extends React.Component {
'notes': 0
}
mkdirp(nbPath, (err) => {
if(err){
console.log('There was an error creating the directory '+notePath)
console.log(err)
}
else{
var nbs = this.state.notebooks
nbs.splice(0, 0, notebook)
this.setState({notebooks: nbs}, () => {
if(this.refs['textField0']){
this.refs['textField0'].focus()
}
this.createNotebookMeta(notebook, callback)
})
}
})
this.createNotebookPath(notebook, callback)
};
createNotebookMeta = (notebook, callback) => {
@ -230,7 +280,7 @@ export default class LibraryNav extends React.Component {
if(err){
console.log(err)
}
if(callback){
if(utils.isFunction(callback)){
callback(notebook, err)
}
})
@ -258,6 +308,14 @@ export default class LibraryNav extends React.Component {
};
addNotebookTapped = (callback) => {
if(!utils.isFunction(callback)){
callback = () => {
if(this.refs['textField0']){
this.refs['textField0'].focus()
}
}
}
this.createNewNotebook(callback)
};
@ -274,6 +332,15 @@ export default class LibraryNav extends React.Component {
//Right click
type = 'rightClick'
}
if (item.isNotebook){
var notebook = utils.loadNotebookByName(item.name)
this.props.updateSelection(notebook)
}
else if(item.glob){
this.props.updateSelection(item)
}
item.clicked(i, item, type, ev)
};
@ -295,7 +362,7 @@ export default class LibraryNav extends React.Component {
console.log(err)
}
this.setState({notebooks: nbs}, ()=>{
if(callback){
if(utils.isFunction(callback)){
callback(nb, err)
}
})
@ -331,7 +398,11 @@ export default class LibraryNav extends React.Component {
this.props.updateContextMenu(this.contextMenuItems(i))
this.props.openContextMenu(x, y)
}
else{
this.props.updateSelection(this.state.notebooks[i])
}
this.refs.mainList.setIndex(-1)
};
preventEventProp = (ev) => {
@ -343,7 +414,6 @@ export default class LibraryNav extends React.Component {
{this.state.notebooks.map((notebook, i) =>{
var l = null
if (notebook.state == 'editing'){
l = <ListItem
key={notebook.uuid || i}
@ -447,6 +517,7 @@ export default class LibraryNav extends React.Component {
}
LibraryNav.defaultProps = {
closeContextMenu: () => {}
closeContextMenu: () => {},
updateSelection: () => {}
};

View file

@ -12,6 +12,6 @@ describe('EntrySelector', () => {
var entrySelector = TestUtils.renderIntoDocument(
<EntrySelector id="entry-selector" className="left inline fill-height" />
)
expect(entrySelector.state.entries.length).toEqual(0)
expect(entrySelector.state.notes.length).toEqual(0)
})
})

View file

@ -0,0 +1 @@
export const UPDATE_SELECTION = 'UPDATE_SELECTION'

View file

@ -3,6 +3,7 @@ import getMuiTheme from 'material-ui/lib/styles/getMuiTheme'
import Styles from 'material-ui/lib/styles'
import mui from 'material-ui'
import * as ContextMenuActions from '../actions/contextMenu'
import * as NavigationActions from '../actions/navigation'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
@ -51,7 +52,13 @@ class App extends React.Component {
render() {
const { contextMenu, contextMenuActions } = this.props
const {
contextMenu,
contextMenuActions,
navigation,
navigationActions
} = this.props
return (
<div className="fill-height">
<div style={{position: 'absolute',
@ -77,11 +84,15 @@ class App extends React.Component {
ref="libraryNav"
entriesTapped={this.entriesTapped}
className="left inline fill-height"
navigation={navigation}
{...navigationActions}
{...contextMenuActions}
/>
<EntrySelector
id="entry-selector"
className="left inline fill-height"
navigation={navigation}
{...navigationActions}
/>
</div>
@ -91,18 +102,22 @@ class App extends React.Component {
App.propTypes = {
contextMenu: React.PropTypes.object.isRequired,
contextMenuActions: React.PropTypes.object.isRequired
contextMenuActions: React.PropTypes.object.isRequired,
navigation: React.PropTypes.object.isRequired,
navigationActions: React.PropTypes.object.isRequired
}
function mapStateToProps(state) {
return {
contextMenu: state.contextMenu
contextMenu: state.contextMenu,
navigation: state.navigation
}
}
function mapDispatchToProps(dispatch) {
return {
contextMenuActions: bindActionCreators(ContextMenuActions, dispatch)
contextMenuActions: bindActionCreators(ContextMenuActions, dispatch),
navigationActions: bindActionCreators(NavigationActions, dispatch)
}
}

View file

@ -1,13 +1,12 @@
import { UPDATE_CONTEXT_MENU, OPEN_CONTEXT_MENU, CLOSE_CONTEXT_MENU } from '../constants/contextMenu'
const initialState =
{
const initialState = {
opened: false,
x: 0,
y: 0,
items: []
}
}
export default function contextMenu(state = initialState, action){
switch (action.type) {

View file

@ -1,8 +1,10 @@
import { combineReducers } from 'redux'
import contextMenu from './contextMenu'
import navigation from './navigation'
const rootReducer = combineReducers({
contextMenu
contextMenu,
navigation
})
export default rootReducer

View file

@ -0,0 +1,18 @@
import { UPDATE_SELECTION } from '../constants/navigation'
const initialState =
{
selection: {
}
}
export default function navigation(state = initialState, action){
switch (action.type) {
case UPDATE_SELECTION:
return Object.assign({}, state, {
selection: action.selection
})
default:
return state
}
}

View file

@ -51,3 +51,8 @@ export function loadNotebookByName(nameOrUUID){
export function getNotebookPathFromUUID(uuid){
return getNotebookPath({uuid: uuid})
}
export function isFunction(functionToCheck) {
var getType = {}
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'
}