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:
parent
c9b324c68b
commit
d14eed9965
10 changed files with 154 additions and 45 deletions
5
app/actions/navigation.jsx
Normal file
5
app/actions/navigation.jsx
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import * as types from '../constants/navigation'
|
||||||
|
|
||||||
|
export function updateSelection(selection) {
|
||||||
|
return { type: types.UPDATE_SELECTION, selection }
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ export default class EntrySelector extends React.Component {
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {entries: []}
|
this.state = {notes: []}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get childContextTypes(){
|
static get childContextTypes(){
|
||||||
|
|
@ -57,14 +57,7 @@ export default class EntrySelector extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
addNoteTapped = () => {
|
addNoteTapped = () => {
|
||||||
this.createNewNote((note) => {
|
console.log(this.props.navigation)
|
||||||
var notes = this.state.notes
|
|
||||||
notes.splice(0, 0, note)
|
|
||||||
this.setState({notes: notes}, () => {
|
|
||||||
//this.refs['textField0'].focus()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
|
|
|
||||||
|
|
@ -54,32 +54,33 @@ export default class LibraryNav extends React.Component {
|
||||||
navItems: [
|
navItems: [
|
||||||
{
|
{
|
||||||
'name': 'Entries',
|
'name': 'Entries',
|
||||||
|
'isNotebook': true,
|
||||||
'icon': <img src="images/note.svg"/>,
|
'icon': <img src="images/note.svg"/>,
|
||||||
'notes': 10,
|
|
||||||
'clicked': this.props.entriesTapped || this.entriesTapped
|
'clicked': this.props.entriesTapped || this.entriesTapped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Starred',
|
'name': 'Starred',
|
||||||
|
'notes': 0,
|
||||||
'icon': <ActionGrade color={colors.amberA700}/>,
|
'icon': <ActionGrade color={colors.amberA700}/>,
|
||||||
'notes': 1,
|
|
||||||
'clicked': this.props.starredTapped || this.starredTapped
|
'clicked': this.props.starredTapped || this.starredTapped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Recents',
|
'name': 'Recents',
|
||||||
|
'notes': 0,
|
||||||
'icon': <History color="#4BAE4E"/>,
|
'icon': <History color="#4BAE4E"/>,
|
||||||
'notes': 10,
|
|
||||||
'clicked': this.props.recentsTapped || this.recentsTapped
|
'clicked': this.props.recentsTapped || this.recentsTapped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Trash',
|
'name': 'Trash',
|
||||||
|
'isNotebook': true,
|
||||||
'icon': <Delete color={colors.grey500}/>,
|
'icon': <Delete color={colors.grey500}/>,
|
||||||
'notes': 0,
|
|
||||||
'clicked': this.props.trashTapped || this.trashTapped
|
'clicked': this.props.trashTapped || this.trashTapped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'All Notes',
|
'name': 'All Notes',
|
||||||
'icon': <Folder color="#FFCC5F" />,
|
|
||||||
'notes': 0,
|
'notes': 0,
|
||||||
|
'glob': '*.qvnotebook/*.qvnote',
|
||||||
|
'icon': <Folder color="#FFCC5F" />,
|
||||||
'clicked': this.props.allNotesTapped || this.allNotesTapped
|
'clicked': this.props.allNotesTapped || this.allNotesTapped
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -87,12 +88,44 @@ export default class LibraryNav extends React.Component {
|
||||||
notebooks: [
|
notebooks: [
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
this.loadDefaultNotebooks()
|
||||||
this.getNotebooks()
|
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 = () => {
|
getNotebooks = () => {
|
||||||
var dataPath = utils.getAppDataPath()
|
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++){
|
for(var i=0; i<notebooks.length; i++){
|
||||||
var nbFile = notebooks[i]
|
var nbFile = notebooks[i]
|
||||||
var obj = jsfile.readFileSync(path.join(nbFile, 'meta.json'))
|
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) => {
|
createNewNotebook = (callback) => {
|
||||||
var nbUuid = uuid.v4().toUpperCase()
|
var nbUuid = uuid.v4().toUpperCase()
|
||||||
|
|
@ -200,23 +266,7 @@ export default class LibraryNav extends React.Component {
|
||||||
'notes': 0
|
'notes': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdirp(nbPath, (err) => {
|
this.createNotebookPath(notebook, callback)
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
createNotebookMeta = (notebook, callback) => {
|
createNotebookMeta = (notebook, callback) => {
|
||||||
|
|
@ -230,7 +280,7 @@ export default class LibraryNav extends React.Component {
|
||||||
if(err){
|
if(err){
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
if(callback){
|
if(utils.isFunction(callback)){
|
||||||
callback(notebook, err)
|
callback(notebook, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -258,6 +308,14 @@ export default class LibraryNav extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
addNotebookTapped = (callback) => {
|
addNotebookTapped = (callback) => {
|
||||||
|
if(!utils.isFunction(callback)){
|
||||||
|
callback = () => {
|
||||||
|
if(this.refs['textField0']){
|
||||||
|
this.refs['textField0'].focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.createNewNotebook(callback)
|
this.createNewNotebook(callback)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -274,6 +332,15 @@ export default class LibraryNav extends React.Component {
|
||||||
//Right click
|
//Right click
|
||||||
type = 'rightClick'
|
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)
|
item.clicked(i, item, type, ev)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -295,7 +362,7 @@ export default class LibraryNav extends React.Component {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
this.setState({notebooks: nbs}, ()=>{
|
this.setState({notebooks: nbs}, ()=>{
|
||||||
if(callback){
|
if(utils.isFunction(callback)){
|
||||||
callback(nb, err)
|
callback(nb, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -331,7 +398,11 @@ export default class LibraryNav extends React.Component {
|
||||||
this.props.updateContextMenu(this.contextMenuItems(i))
|
this.props.updateContextMenu(this.contextMenuItems(i))
|
||||||
this.props.openContextMenu(x, y)
|
this.props.openContextMenu(x, y)
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
this.props.updateSelection(this.state.notebooks[i])
|
||||||
|
}
|
||||||
this.refs.mainList.setIndex(-1)
|
this.refs.mainList.setIndex(-1)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
preventEventProp = (ev) => {
|
preventEventProp = (ev) => {
|
||||||
|
|
@ -343,7 +414,6 @@ export default class LibraryNav extends React.Component {
|
||||||
|
|
||||||
{this.state.notebooks.map((notebook, i) =>{
|
{this.state.notebooks.map((notebook, i) =>{
|
||||||
var l = null
|
var l = null
|
||||||
|
|
||||||
if (notebook.state == 'editing'){
|
if (notebook.state == 'editing'){
|
||||||
l = <ListItem
|
l = <ListItem
|
||||||
key={notebook.uuid || i}
|
key={notebook.uuid || i}
|
||||||
|
|
@ -447,6 +517,7 @@ export default class LibraryNav extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryNav.defaultProps = {
|
LibraryNav.defaultProps = {
|
||||||
closeContextMenu: () => {}
|
closeContextMenu: () => {},
|
||||||
|
updateSelection: () => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@ describe('EntrySelector', () => {
|
||||||
var entrySelector = TestUtils.renderIntoDocument(
|
var entrySelector = TestUtils.renderIntoDocument(
|
||||||
<EntrySelector id="entry-selector" className="left inline fill-height" />
|
<EntrySelector id="entry-selector" className="left inline fill-height" />
|
||||||
)
|
)
|
||||||
expect(entrySelector.state.entries.length).toEqual(0)
|
expect(entrySelector.state.notes.length).toEqual(0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
1
app/constants/navigation.jsx
Normal file
1
app/constants/navigation.jsx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const UPDATE_SELECTION = 'UPDATE_SELECTION'
|
||||||
|
|
@ -3,6 +3,7 @@ import getMuiTheme from 'material-ui/lib/styles/getMuiTheme'
|
||||||
import Styles from 'material-ui/lib/styles'
|
import Styles from 'material-ui/lib/styles'
|
||||||
import mui from 'material-ui'
|
import mui from 'material-ui'
|
||||||
import * as ContextMenuActions from '../actions/contextMenu'
|
import * as ContextMenuActions from '../actions/contextMenu'
|
||||||
|
import * as NavigationActions from '../actions/navigation'
|
||||||
|
|
||||||
import { bindActionCreators } from 'redux'
|
import { bindActionCreators } from 'redux'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
|
@ -51,7 +52,13 @@ class App extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const { contextMenu, contextMenuActions } = this.props
|
const {
|
||||||
|
contextMenu,
|
||||||
|
contextMenuActions,
|
||||||
|
navigation,
|
||||||
|
navigationActions
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fill-height">
|
<div className="fill-height">
|
||||||
<div style={{position: 'absolute',
|
<div style={{position: 'absolute',
|
||||||
|
|
@ -77,11 +84,15 @@ class App extends React.Component {
|
||||||
ref="libraryNav"
|
ref="libraryNav"
|
||||||
entriesTapped={this.entriesTapped}
|
entriesTapped={this.entriesTapped}
|
||||||
className="left inline fill-height"
|
className="left inline fill-height"
|
||||||
|
navigation={navigation}
|
||||||
|
{...navigationActions}
|
||||||
{...contextMenuActions}
|
{...contextMenuActions}
|
||||||
/>
|
/>
|
||||||
<EntrySelector
|
<EntrySelector
|
||||||
id="entry-selector"
|
id="entry-selector"
|
||||||
className="left inline fill-height"
|
className="left inline fill-height"
|
||||||
|
navigation={navigation}
|
||||||
|
{...navigationActions}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -91,18 +102,22 @@ class App extends React.Component {
|
||||||
|
|
||||||
App.propTypes = {
|
App.propTypes = {
|
||||||
contextMenu: React.PropTypes.object.isRequired,
|
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) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
contextMenu: state.contextMenu
|
contextMenu: state.contextMenu,
|
||||||
|
navigation: state.navigation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
contextMenuActions: bindActionCreators(ContextMenuActions, dispatch)
|
contextMenuActions: bindActionCreators(ContextMenuActions, dispatch),
|
||||||
|
navigationActions: bindActionCreators(NavigationActions, dispatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import { UPDATE_CONTEXT_MENU, OPEN_CONTEXT_MENU, CLOSE_CONTEXT_MENU } from '../constants/contextMenu'
|
import { UPDATE_CONTEXT_MENU, OPEN_CONTEXT_MENU, CLOSE_CONTEXT_MENU } from '../constants/contextMenu'
|
||||||
|
|
||||||
|
|
||||||
const initialState =
|
const initialState = {
|
||||||
{
|
|
||||||
opened: false,
|
opened: false,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
items: []
|
items: []
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function contextMenu(state = initialState, action){
|
export default function contextMenu(state = initialState, action){
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { combineReducers } from 'redux'
|
import { combineReducers } from 'redux'
|
||||||
import contextMenu from './contextMenu'
|
import contextMenu from './contextMenu'
|
||||||
|
import navigation from './navigation'
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
contextMenu
|
contextMenu,
|
||||||
|
navigation
|
||||||
})
|
})
|
||||||
|
|
||||||
export default rootReducer
|
export default rootReducer
|
||||||
|
|
|
||||||
18
app/reducers/navigation.jsx
Normal file
18
app/reducers/navigation.jsx
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,3 +51,8 @@ export function loadNotebookByName(nameOrUUID){
|
||||||
export function getNotebookPathFromUUID(uuid){
|
export function getNotebookPathFromUUID(uuid){
|
||||||
return getNotebookPath({uuid: uuid})
|
return getNotebookPath({uuid: uuid})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFunction(functionToCheck) {
|
||||||
|
var getType = {}
|
||||||
|
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue