TechNote/app/components/EntrySelector.jsx
2016-03-15 08:15:53 -06:00

269 lines
7.8 KiB
JavaScript

import React from 'react'
import mui from 'material-ui'
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme'
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'
import Item from 'Item'
import uuid from 'node-uuid'
import path from 'path-extra'
import * as utils from 'utils'
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,
Styles,
TextField,
Paper
} = mui
const colors = Styles.Colors
const DefaultRawTheme = Styles.LightRawTheme
export default class EntrySelector extends React.Component {
constructor(props, context){
super(props, context)
this.state = {notes: []}
this.loadNotes()
const { store } = this.context
store.subscribe(this.stateChanged)
this.oldSelection = this.props.navigation.selection
}
stateChanged = () => {
const { store } = this.context
var selection = store.getState().navigation.selection
var selectionDiffers = utils.differs(this.oldSelection, selection)
if(selectionDiffers){
this.reloadNotes(selection)
this.oldSelection = selection
}
};
static get childContextTypes(){
return {muiTheme: React.PropTypes.object}
}
getChildContext() {
return {
muiTheme: getMuiTheme(DefaultRawTheme)
}
}
loadNotes = () => {
var notebook = this.props.navigation.selection
if(!utils.isEmpty(notebook)){
var notes = utils.loadNotes(notebook)
notes.sort(utils.compareNotes())
this.state.notes = notes
}
}
reloadNotes = (selection) => {
this.setState({notes: []}, ()=>{
var notebook = selection || this.props.navigation.selection
utils.loadNotesAsync(notebook, (notes) => {
notes.sort(utils.compareNotes())
this.setState({notes: notes})
})
})
};
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 = () => {
this.createNewNote((note, err)=>{
this.props.refreshNavigation()
})
};
renderNoteTags = (note) => {
if (note.tags.length > 0){
return (
<div className="inline">
<IconButton
className="tag-icon inline"
style={{'zIndex': 1000}}
touch={true}
tooltip={note.tags.join(", ")}
>
<Tag color={colors.grey400}/>
</IconButton>
<div className="tag-list inline">
{utils.trunc(note.tags.join(", "), 30)}
</div>
</div>
)
}
};
renderNoteInfo = (note) => {
let noteInfoStyle = {
position: "absolute",
top: 70,
left: 20,
color: colors.grey400,
fontSize: 14
}
return (<div style={noteInfoStyle}>
<div className="note-date inline">
{moment.unix(note.created_at).format('MMM D, YYYY')}
</div>
{this.renderNoteTags(note)}
</div>)
};
render(){
return (
<Paper id={this.props.id} className={this.props.className+ " noselect"} zDepth={0}>
<SearchBar
id="entry-search-bar"
rightIconButton={
<IconButton
style={{'zIndex': 1000}}
touch={true}
onTouchTap={this.addNoteTapped}
tooltip="Add New Note">
<Add color={colors.grey600}/>
</IconButton>}
hintText="Filter by keyword, title or tag."
innerTextFieldWidth={210}
onKeyDown={()=>{}}
onEnterKeyDown={()=>{}}
/>
<SelectableList
id="entry-list"
ref="entryList"
selectedItemStyle={{backgroundColor: colors.grey300}}>
{this.state.notes.map((note, i) =>{
return (<ListItem
key={i}
value={i}
leftIcon={<Description color={colors.grey600}/>}
innerDivStyle={{paddingBottom: 40}}
style={{borderBottom: '1px solid #F1F1F1'}}
secondaryText={
<p>
{note.summary}
</p>
}
secondaryTextLines={2}
>
<div>
{note.title || "Untitled Note"}
</div>
{this.renderNoteInfo(note)}
</ListItem>
)
})
}
</SelectableList>
</Paper>
)
}
}
EntrySelector.contextTypes = {
store: React.PropTypes.object
}