diff --git a/browser/lib/Repository.js b/browser/lib/Repository.js index 40077966..3a72ec0c 100644 --- a/browser/lib/Repository.js +++ b/browser/lib/Repository.js @@ -3,6 +3,7 @@ const fs = require('fs') const path = require('path') const CSON = require('season') const _ = require('lodash') +const consts = require('browser/lib/consts') let repositories = [] @@ -19,10 +20,10 @@ let repositories = [] * .then(() => repo.load()) * * // Update Cached - * repo.updateCache({name: 'renamed'}) + * repo.saveCache({name: 'renamed'}) * * // Update JSON - * repo.updateJSON({author: 'Other user'}) + * repo.saveJSON({author: 'Other user'}) * * // Remove repository * repo.unmount() @@ -142,6 +143,7 @@ class Repository { return Promise.all([resolveDataDirectory, resolveBoostrepoJSON]) .then((data) => { this.json = data[1] + return true }) } @@ -167,6 +169,7 @@ class Repository { return Promise.all(notes) .then((notes) => { this.notes = notes + return true }) } @@ -178,10 +181,11 @@ class Repository { return this.getData() }) - .catch(function handleError (err) { + .catch((err) => { this.status = 'ERROR' this.error = err - return err + console.error(err) + return this }) } @@ -253,14 +257,23 @@ class Repository { * @return {Promise} all data of a repository */ getData () { - if (this.status !== 'READY') { + function carbonCopy (obj) { + return JSON.parse(JSON.stringify(obj)) + } + if (this.status === 'IDLE') { return this.load() } - return Promise.resolve(Object.assign({}, this.json, this.cached, { + if (this.status === 'ERROR') { + return Promise.resolve(carbonCopy(Object.assign({}, this.json, this.cached, { + status: this.status + }))) + } + + return Promise.resolve(carbonCopy(Object.assign({}, this.json, this.cached, { status: this.status, notes: this.notes - })) + }))) } /** @@ -287,11 +300,13 @@ class Repository { */ saveJSON (newJSON) { let jsonPath = path.join(this.cached.path, 'boostrepo.json') - Object.assign(this.json, newJSON) + if (_.isObject(newJSON)) { + Object.assign(this.json, newJSON) + } - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { CSON - .writeFile(jsonPath, this.json, function (err) { + .writeFile(jsonPath, this.json, (err) => { if (err != null) return reject(err) resolve(this.json) }) @@ -316,9 +331,9 @@ class Repository { newFolder = _.pick(newFolder, ['color', 'name']) if (!_.isString(newFolder.name) || newFolder.name.trim().length === 0) newFolder.name = 'unnamed' - else newFolder.name = newFolder.trim() + else newFolder.name = newFolder.name.trim() - if (!_.isString(newFolder.color)) newFolder.color = '' + if (!_.isString(newFolder.color)) newFolder.color = this.constructor.randomColor() newFolder.key = keygen() while (_.findIndex(folders, {key: newFolder.key}) > -1) { @@ -327,7 +342,7 @@ class Repository { folders.push(newFolder) - return this.updateJSON(this.json) + return this.saveJSON(this.json) .then(() => newFolder) } @@ -451,6 +466,10 @@ class Repository { return Promise.resolve(this.notes) } + /** + * Static Methods + */ + static generateDefaultJSON (override) { return Object.assign({ name: 'unnamed', @@ -458,7 +477,7 @@ class Repository { folders: [{ key: keygen(), name: 'general', - color: 'green' + color: this.randomColor() }] }, override) } @@ -474,21 +493,28 @@ class Repository { * @return {Promise} resolving parsed data */ static resolveJSON (targetPath, defaultOverrides) { - return new Promise(function checkIfExists (resolve, reject) { - // If JSON doesn't exist, make a new one. - if (CSON.resolve(targetPath) == null) { - let newRepoJSON = this.constructor.generateDefaultJSON(defaultOverrides) - CSON.writeFile(targetPath, newRepoJSON, function (err) { + return (new Promise((resolve, reject) => { + let writeNew = () => { + let newRepoJSON = this.generateDefaultJSON(defaultOverrides) + CSON.writeFile(targetPath, newRepoJSON, (err) => { if (err != null) return reject(err) resolve(newRepoJSON) }) + } + // If JSON doesn't exist, make a new one. + if (CSON.resolve(targetPath) == null) { + writeNew() } else { - CSON.readFile(targetPath, function (err, obj) { + CSON.readFile(targetPath, (err, obj) => { if (err != null) return reject(err) - resolve(obj) + if (obj == null) { + writeNew() + } else { + resolve(obj) + } }) } - }) + })) } /** @@ -553,7 +579,6 @@ class Repository { throw new Error('Data is corrupted. it must be an array.') } } catch (err) { - console.log(err) data = [] this.saveAllCached(data) } @@ -582,6 +607,10 @@ class Repository { let repository = _.find(repositories, {cached: {key: repoKey}}) return Promise.resolve(repository) } + + static randomColor () { + return consts.FOLDER_COLORS[Math.floor(Math.random() * consts.FOLDER_COLORS.length)] + } } export default Repository diff --git a/browser/lib/consts.js b/browser/lib/consts.js new file mode 100644 index 00000000..de75eaf1 --- /dev/null +++ b/browser/lib/consts.js @@ -0,0 +1,14 @@ +const consts = { + FOLDER_COLORS: [ + '#3460C7', + '#2BA5F7', + '#FF8E00', + '#E8D252', + '#3FD941', + '#1FAD85', + '#E10051', + '#B013A4' + ] +} + +module.exports = consts diff --git a/browser/main/HomePage/SideNav/RepositorySection.js b/browser/main/HomePage/SideNav/RepositorySection.js index 9b66ea40..04f77e81 100644 --- a/browser/main/HomePage/SideNav/RepositorySection.js +++ b/browser/main/HomePage/SideNav/RepositorySection.js @@ -9,10 +9,28 @@ const Menu = remote.Menu const MenuItem = remote.MenuItem class RepositorySection extends React.Component { + constructor (props) { + super(props) + + this.state = { + isOpen: true, + isCreatingFolder: false, + isSaving: false, + newFolder: { + name: '' + } + } + } + + getRepository () { + let { repository } = this.props + return Repository.find(repository.key) + } + handleUnlinkButtonClick () { let { dispatch, repository } = this.props - Repository.find(repository.key) + this.getRepository() .then((repositoryInstance) => { return repositoryInstance.unmount() }) @@ -25,16 +43,16 @@ class RepositorySection extends React.Component { } handleToggleButtonClick (e) { - + this.setState({ + isOpen: !this.state.isOpen + }) } handleContextButtonClick (e) { var menu = new Menu() menu.append(new MenuItem({ - label: 'New Note' - })) - menu.append(new MenuItem({ - label: 'New Folder' + label: 'New Folder', + click: () => this.handleNewFolderButtonClick() })) menu.append(new MenuItem({ type: 'separator' })) menu.append(new MenuItem({ @@ -45,17 +63,62 @@ class RepositorySection extends React.Component { menu.popup(remote.getCurrentWindow()) } + handleNewFolderButtonClick (e) { + this.setState({ + isCreatingFolder: true, + newFolder: { + name: 'New Folder' + } + }, () => { + this.refs.nameInput.select() + this.refs.nameInput.focus() + }) + } + + handleNewFolderFormChange (e) { + let newFolder = this.state.newFolder + newFolder.name = this.refs.nameInput.value + + this.setState({ + newFolder + }) + } + + handleNameInputBlur (e) { + let { dispatch, repository } = this.props + + this.getRepository() + .then((repositoryInstance) => { + return repositoryInstance.addFolder({ + name: this.state.newFolder.name + }) + }) + .then((folder) => { + console.log(folder) + dispatch({ + type: 'ADD_FOLDER', + key: repository.key, + folder: folder + }) + + this.setState({ + isCreatingFolder: false, + isSaving: false + }) + }) + } + render () { let { repository } = this.props let folderElements = repository.folders.map((folder) => { return (
- {folder.name} + {folder.name}
+ {this.state.isOpen &&
+ {folderElements} - {folderElements} - - + {this.state.isCreatingFolder + ?
+ this.handleNewFolderFormChange(e)} + onBlur={(e) => this.handleNameInputBlur(e)} + /> +
+ : + } +
} ) } diff --git a/browser/main/HomePage/SideNav/RepositorySection.styl b/browser/main/HomePage/SideNav/RepositorySection.styl index f509a31d..92539277 100644 --- a/browser/main/HomePage/SideNav/RepositorySection.styl +++ b/browser/main/HomePage/SideNav/RepositorySection.styl @@ -83,6 +83,21 @@ color white background-color $brand-color +.newFolderForm + width 100% + padding 0 15px + height 33px + +.newFolderForm-nameInput + width 100% + height 33px + padding 0 10px + border-radius 5px + border solid 1px $nav-border-color + outline none + &:focus + border-color $focus-border-color + .newFolderButton height 33px width 100% diff --git a/browser/main/HomePage/SideNav/index.js b/browser/main/HomePage/SideNav/index.js index dd85e3a0..171b1f0b 100644 --- a/browser/main/HomePage/SideNav/index.js +++ b/browser/main/HomePage/SideNav/index.js @@ -1,9 +1,8 @@ import React, { PropTypes } from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './SideNav.styl' -import { openModal, isModalOpen } from 'browser/lib/modal' +import { openModal } from 'browser/lib/modal' import Preferences from '../../modal/Preferences' -import CreateNewFolder from '../../modal/CreateNewFolder' import RepositorySection from './RepositorySection' import NewRepositoryModal from '../../modal/NewRepositoryModal' diff --git a/browser/main/store.js b/browser/main/store.js index 1b7842cb..adabd37a 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -35,16 +35,36 @@ function repositories (state = initialRepositories, action) { case 'ADD_REPOSITORY': { let repos = state.slice() + repos.push(action.repository) + return repos } case 'REMOVE_REPOSITORY': { let repos = state.slice() + let targetIndex = _.findIndex(repos, {key: action.key}) if (targetIndex > -1) { repos.splice(targetIndex, 1) } + + return repos + } + case 'ADD_FOLDER': + { + let repos = state.slice() + let targetRepo = _.find(repos, {key: action.key}) + + if (targetRepo == null) return state + + let targetFolderIndex = _.findIndex(targetRepo.folders, {key: action.folder.key}) + if (targetFolderIndex < 0) { + targetRepo.folders.push(action.folder) + } else { + targetRepo.folders.splice(targetFolderIndex, 1, action.folder) + } + return repos } } diff --git a/browser/styles/index.styl b/browser/styles/index.styl index 566cbfa8..e2e64b02 100644 --- a/browser/styles/index.styl +++ b/browser/styles/index.styl @@ -9,6 +9,7 @@ $danger-lighten-color = #FFE5E6 */ $border-color = #D0D0D0 $active-border-color = #369DCD +$focus-border-color = #369DCD $default-border = solid 1px $border-color $active-border = solid 1px $active-border-color