diff --git a/app/components/EntrySelector.jsx b/app/components/EntrySelector.jsx index e1a3fd4..4a46806 100644 --- a/app/components/EntrySelector.jsx +++ b/app/components/EntrySelector.jsx @@ -7,6 +7,7 @@ import List from 'material-ui/lib/lists/list' import ListItem from 'material-ui/lib/lists/list-item' import Description from 'material-ui/lib/svg-icons/action/description' import Add from 'material-ui/lib/svg-icons/content/add' +import Tag from 'material-ui/lib/svg-icons/maps/local-offer' import SearchBar from 'SearchBar' import SelectableList from 'SelectableList' @@ -16,13 +17,19 @@ import uuid from 'node-uuid' import path from 'path-extra' import * as utils from 'utils' -import glob from 'glob' +import glob from 'glob' +import moment from 'moment' import fs from 'fs' import mkdirp from 'mkdirp' import jsfile from 'jsonfile' import rmdir from 'rimraf' +import { + NOTEBOOK_TYPE, + MENU_TYPE +} from '../constants/navigation' + const { IconButton, AutoComplete, @@ -37,11 +44,20 @@ const DefaultRawTheme = Styles.LightRawTheme export default class EntrySelector extends React.Component { - constructor(props){ - super(props) + constructor(props, context){ + super(props, context) this.state = {notes: []} + this.loadNotes() + const { store } = this.context + store.subscribe(this.stateChanged) } + stateChanged = () => { + const { store } = this.context + var selection = store.getState().navigation.selection + this.reloadNotes(selection) + }; + static get childContextTypes(){ return {muiTheme: React.PropTypes.object} } @@ -52,18 +68,146 @@ export default class EntrySelector extends React.Component { } } + loadNotes = () => { + var notebook = this.props.navigation.selection + var notes = utils.loadNotes(notebook) + this.state.notes = notes + } + + reloadNotes = (selection) => { + var notebook = selection || this.props.navigation.selection + + var notes = utils.loadNotes(notebook) + this.setState({notes: notes}) + }; + blank(){ } - + + createNotePath = (note, callback) => { + mkdirp(path.join(note.path, 'resources'), (err) => { + if(err){ + console.log('There was an error creating the directory '+note.path) + console.log(err) + } + else{ + var notes = this.state.notes + notes.splice(0, 0, note) + + this.setState({notes: notes}, () => { + this.createNoteFiles(note, callback) + }) + } + }) + }; + + createNoteFiles = (note, callback) => { + var noteMeta = { + 'created_at': note.created_at, + 'updated_at': note.updated_at, + 'tags': note.tags, + 'title': note.title, + 'uuid': note.uuid + } + + var content = { + 'title': note.title, + 'cells': [] + } + + var metaPath = path.join(note.path, 'meta.json') + var contentPath = path.join(note.path, 'content.json') + + jsfile.writeFile(metaPath, noteMeta, (err) => { + if(err){ + console.log(err) + } + + jsfile.writeFile(contentPath, content, (err) => { + if(err){ + console.log(err) + } + + if(utils.isFunction(callback)){ + callback(note, err) + } + }) + }) + + }; + + createNewNote = (callback) => { + var notebook = this.props.navigation.selection + var noteUUID = uuid.v4().toUpperCase() + var notePath = utils.getNotePathFromUUID(notebook, noteUUID) + + var noteCreation = moment.utc().valueOf()/1000 + var noteUpdated = noteCreation + + var note = { + 'created_at': noteCreation, + 'updated_at': noteUpdated, + 'tags': [], + 'title': '', + 'path': notePath, + 'uuid': noteUUID, + 'summary': '', + 'notebook': notebook + } + + this.createNotePath(note, callback) + + }; + addNoteTapped = () => { - console.log(this.props.navigation) + this.createNewNote((note, err)=>{ + this.props.refreshNavigation() + }) + }; + + renderNoteTags = (note) => { + if (note.tags.length > 0){ + return ( +
+ + + +
+ {utils.trunc(note.tags.join(", "), 30)} +
+
+ ) + } + }; + + renderNoteInfo = (note) => { + let noteInfoStyle = { + position: "absolute", + top: 70, + left: 20, + color: colors.grey400, + fontSize: 14 + } + + return (
+
+ {moment.unix(note.created_at).format('MMM D, YYYY')} +
+ {this.renderNoteTags(note)} +
) }; render(){ return ( - } - primaryText="Today's Notes" - secondaryText={ -

- I did things -- - I did so many things today, it's not even funny. You think it's funny? - Well it's not! -

- } - secondaryTextLines={2} - /> + + {this.state.notes.map((note, i) =>{ + return (} + innerDivStyle={{paddingBottom: 40}} + style={{borderBottom: '1px solid #F1F1F1'}} + secondaryText={ +

+ {note.summary} +

+ } + secondaryTextLines={2} + > +
+ {note.title || "Untitled Note"} +
+ + {this.renderNoteInfo(note)} + +
+ ) + }) + }
) } } +EntrySelector.contextTypes = { + store: React.PropTypes.object +} diff --git a/app/components/LibraryNav.jsx b/app/components/LibraryNav.jsx index efb77a6..4d8e03e 100644 --- a/app/components/LibraryNav.jsx +++ b/app/components/LibraryNav.jsx @@ -23,7 +23,6 @@ import path from 'path-extra' import * as utils from 'utils' import glob from 'glob' -import fs from 'fs' import mkdirp from 'mkdirp' import jsfile from 'jsonfile' import rmdir from 'rimraf' @@ -51,49 +50,51 @@ export default class LibraryNav extends React.Component { super(props, context) this.state = { open: true, - navItems: [ - { - 'name': 'Entries', - 'isNotebook': true, - 'icon': , - 'clicked': this.props.entriesTapped || this.entriesTapped - }, - { - 'name': 'Starred', - 'notes': 0, - 'icon': , - 'clicked': this.props.starredTapped || this.starredTapped - }, - { - 'name': 'Recents', - 'notes': 0, - 'icon': , - 'clicked': this.props.recentsTapped || this.recentsTapped - }, - { - 'name': 'Trash', - 'isNotebook': true, - 'icon': , - 'clicked': this.props.trashTapped || this.trashTapped - }, - { - 'name': 'All Notes', - 'notes': 0, - 'glob': '*.qvnotebook/*.qvnote', - 'icon': , - 'clicked': this.props.allNotesTapped || this.allNotesTapped - }, - - ], - notebooks: [ - ] } + this.navItems = [ + { + 'name': 'Entries', + 'isNotebook': true, + 'icon': , + 'clicked': this.props.entriesTapped || this.entriesTapped + }, + { + 'name': 'Starred', + 'notes': 0, + 'icon': , + 'clicked': this.props.starredTapped || this.starredTapped + }, + { + 'name': 'Recents', + 'notes': 0, + 'icon': , + 'clicked': this.props.recentsTapped || this.recentsTapped + }, + { + 'name': 'Trash', + 'isNotebook': true, + 'icon': , + 'clicked': this.props.trashTapped || this.trashTapped + }, + { + 'name': 'All Notes', + 'notes': 0, + 'glob': '*.qvnotebook/*.qvnote', + 'icon': , + 'clicked': this.props.allNotesTapped || this.allNotesTapped + } + + ] + this.loadDefaultNotebooks() this.getNotebooks() + + const { store } = this.context + store.subscribe(this.stateChanged) } loadDefaultNotebooks = () => { - var notebooks = this.state.navItems + var notebooks = this.navItems for(var i=0; i { - let atitle = a.title.toLowerCase() - let btitle = b.title.toLowerCase() - - if(atitle > btitle) - return 1 - if(atitle < btitle) - return -1 - return 0 - }; - - sortNotebooks = (dontSet, func) => { - this.state.notebooks.sort(this.compareNotebooks) - if (!dontSet){ - this.setState({notebooks: this.state.notebooks}, func) + this.props.addNotebook(nb) } + this.props.sortNotebooks(utils.compareNotebooks) }; static get childContextTypes(){ @@ -203,14 +190,17 @@ export default class LibraryNav extends React.Component { scrollToRenamedNotebook = (original) => { var newIndex = 0 - for (var j = 0; j < this.state.notebooks.length; j++){ - var n = this.state.notebooks[j] + for (var j = 0; j < this.props.navigation.notebooks.length; j++){ + var n = this.props.navigation.notebooks[j] if (n == original){ newIndex = j this.refs.notebookList.setIndex(j, () => { var nbitem = $(ReactDOM.findDOMNode(this.refs[n.title+newIndex])) var cont = $('#notebook-list') - var newPos = nbitem.offset().top - cont.offset().top + cont.scrollTop() - cont.height()/2; + var newPos = 0 + if(typeof nbitem.offset() != 'undefined'){ + newPos = nbitem.offset().top - cont.offset().top + cont.scrollTop() - cont.height()/2; + } $('#notebook-list').animate({ scrollTop: newPos }) @@ -243,12 +233,8 @@ export default class LibraryNav extends React.Component { console.log(err) } else{ - var nbs = this.state.notebooks - nbs.splice(0, 0, notebook) - - this.setState({notebooks: nbs}, () => { - this.createNotebookMeta(notebook, callback) - }) + this.props.addNotebook(notebook) + this.createNotebookMeta(notebook, callback) } }) @@ -288,22 +274,24 @@ export default class LibraryNav extends React.Component { }; newNotebookUnfocus = (i) => { - var nb = this.state.notebooks[i] + var nb = this.props.navigation.notebooks[i] var tf = this.refs["textField"+i] var notebookName = tf.getValue() if (notebookName){ + this.refs.mainList.setIndex(-1) nb.title = notebookName nb.state = 'displaying' - this.setState({notebooks: this.state.notebooks}) - this.sortNotebooks(false, ()=>{ - this.scrollToRenamedNotebook(nb) + this.props.updateNotebook(nb, i, () => { + this.props.sortNotebooks(this.compareNotebooks, ()=>{ + this.scrollToRenamedNotebook(nb) + }) }) this.createNotebookMeta(nb) } else if(nb.title){ nb.state = 'displaying' - this.setState({notebooks: this.state.notebooks}) + this.props.updateNotebook(nb, i) } }; @@ -325,7 +313,7 @@ export default class LibraryNav extends React.Component { menuItemClicked = (i, ev) => { this.refs.notebookList.setIndex(-1) - var item = this.state.navItems[i] + var item = this.props.navigation.menuItems[i] var type = 'leftClick' var nativeEvent = ev.nativeEvent if(nativeEvent.button == 2){ @@ -335,6 +323,7 @@ export default class LibraryNav extends React.Component { if (item.isNotebook){ var notebook = utils.loadNotebookByName(item.name) + notebook = utils.updateObject(item, notebook) this.props.updateSelection(notebook) } else if(item.glob){ @@ -345,23 +334,23 @@ export default class LibraryNav extends React.Component { }; renameTapped = (i) => { - var nbs = this.state.notebooks + var nbs = this.props.navigation.notebooks nbs[i].state = 'editing' - this.setState({notebooks: nbs}, () => { + this.props.updateNotebook(nbs[i], i, () => { this.refs['textField'+i].focus() }) this.props.closeContextMenu() } deleteTapped = (i, callback) => { - var nbs = this.state.notebooks - var nb = nbs.splice(i, 1)[0] + var nbs = this.props.navigation.notebooks + var nb = nbs.slice(i, 1)[0] rmdir(nb.path, (err)=>{ if(err){ console.log(err) } - this.setState({notebooks: nbs}, ()=>{ + this.props.removeNotebook(i, () =>{ if(utils.isFunction(callback)){ callback(nb, err) } @@ -399,7 +388,7 @@ export default class LibraryNav extends React.Component { this.props.openContextMenu(x, y) } else{ - this.props.updateSelection(this.state.notebooks[i]) + this.props.updateSelection(this.props.navigation.notebooks[i]) } this.refs.mainList.setIndex(-1) @@ -412,7 +401,7 @@ export default class LibraryNav extends React.Component { notebookList = () => { return (
- {this.state.notebooks.map((notebook, i) =>{ + {this.props.navigation.notebooks.map((notebook, i) =>{ var l = null if (notebook.state == 'editing'){ l = @@ -470,16 +461,26 @@ export default class LibraryNav extends React.Component { ev.stopPropagation() }; + stateChanged = () => { + const { store } = this.context + const state = store.getState() + if(utils.isFunction(state.navigation.callback)){ + state.navigation.callback(state) + } + }; + render(){ + return (
- {this.state.navItems.map((item, i) => { + {this.props.navigation.menuItems.map((item, i) => { return {}, updateSelection: () => {}