From ac7e08ae2c8c6c93a7ae30b514d2f62be6d8879b Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 18 Apr 2016 15:36:02 +0900 Subject: [PATCH] Redesign SideNav & implement add repo func --- browser/lib/RepositoryManager.js | 295 ++++++++++++++++++ browser/main/HomePage/ArticleNavigator.js | 202 ------------ browser/main/HomePage/SideNav/Repository.js | 75 +++++ browser/main/HomePage/SideNav/Repository.styl | 90 ++++++ browser/main/HomePage/SideNav/SideNav.styl | 63 ++++ browser/main/HomePage/SideNav/index.js | 156 +++++++++ browser/main/HomePage/index.js | 14 +- browser/main/actions.js | 16 +- browser/main/modal/NewRepositoryModal.js | 175 +++++++++++ browser/main/modal/NewRepositoryModal.styl | 133 ++++++++ browser/main/reducer.js | 54 +++- 11 files changed, 1062 insertions(+), 211 deletions(-) create mode 100644 browser/lib/RepositoryManager.js delete mode 100644 browser/main/HomePage/ArticleNavigator.js create mode 100644 browser/main/HomePage/SideNav/Repository.js create mode 100644 browser/main/HomePage/SideNav/Repository.styl create mode 100644 browser/main/HomePage/SideNav/SideNav.styl create mode 100644 browser/main/HomePage/SideNav/index.js create mode 100644 browser/main/modal/NewRepositoryModal.js create mode 100644 browser/main/modal/NewRepositoryModal.styl diff --git a/browser/lib/RepositoryManager.js b/browser/lib/RepositoryManager.js new file mode 100644 index 00000000..3aa39dde --- /dev/null +++ b/browser/lib/RepositoryManager.js @@ -0,0 +1,295 @@ +const keygen = require('browser/lib/keygen') +const fs = require('fs') +const path = require('path') +const CSON = require('season') +const _ = require('lodash') + +/** + * # Repo structure + * + * ``` + * root + * |- data + * |-note1.cson + * |-note2.cson + * |-note3.cson + * |- boostrepo.json + * ``` + * + * ## `boostrepo.json` + * + * ```js + * { + * name: String, + * author: String, // Same convention of package.json, `John Doe (http://example.com)` + * remotes: [{ + * name: String, + * url: String, // url of git remote + * branch: String // if branch isn't set, it will try to use `master` branch. + * }], + * folders: [{ + * key: String // Unique sha1 hash key to identify folder, + * name: String, + * color: String // All CSS color formats available. + * }] + * } + * ``` + * + * ## `data` directory + * + * Every note will be saved here as a single CSON file to `git diff` efficiently. + * > This is because CSON supports Multiline string. + * File name of each cson file will be used to identify note. + * Commonly, Boostnote will automatically generate sha1 key and use it as a file name when creating a new note. + * + * ### `note.cson` + * + * ```cson + * name: String + * tags: [String] // tags + * folder: String // hash key of folder + * mode: String // syntax mode + * title: String + * content: String + * createdAt: Date + * updatedAt: Date + * ``` + */ + +/** + * # Resolve directory. + * + * If directory doesn't exist, it will try to make a new one. + * If failed return rejected promise + * + * @param {String} targetPath Target path of directory + * @return {Promise} [description] + */ +function _resolveDirectory (targetPath) { + return new Promise(function (resolve, reject) { + // check the directory exists + fs.stat(targetPath, function (err, stat) { + // Reject errors except no suchfile + if (err != null && err.code !== 'ENOENT') { + return reject(err) + } + + // Handle no suchfile error only + // Make new Folder by given path + if (err != null) { + return fs.mkdir(targetPath, function (err, stat) { + // If failed to make a new directory, reject it. + if (err != null) { + return reject(err) + } + resolve(targetPath) + }) + } + + // Check the target is not a directory + if (!stat.isDirectory()) { + return reject(new Error(targetPath + ' path is not a directory')) + } + resolve(targetPath) + }) + }) +} + +function _generateDefaultRepoJSON (override) { + return Object.assign({ + name: 'default', + remotes: [], + folders: [{ + key: keygen(), + name: 'general', + color: 'green' + }] + }, override) +} + +/** + * # Resolve RepoJSON + * + * Every repository must have `boostrepo.json` + * + * If boostrepo.json doesn't exist, create new one. + * + * @param {[type]} targetPath [description] + * @return {[type]} [description] + */ +function _resolveRepoJSON (targetPath) { + return new Promise(function checkIfExists (resolve, reject) { + // If JSON doesn't exist, make a new one. + if (CSON.resolve(targetPath) == null) { + let newRepoJSON = _generateDefaultRepoJSON() + return CSON.writeFile(targetPath, newRepoJSON, function (err) { + if (err != null) return reject(err) + resolve(newRepoJSON) + }) + } + + CSON.readFile(targetPath, function (err, obj) { + if (err != null) return reject(err) + resolve(obj) + }) + }) +} + +/** + * Get all repository stats from localStorage + * it is stored to `repositories` key. + * if the data is corrupted, re-intialize it. + * + * @return {Array} registered repositories + * ``` + * [{ + * key: String, + * name: String, + * path: String // path of repository + * }] + * ``` + */ +function getAllRepoStats () { + let data + try { + data = JSON.parse(localStorage.getItem('repositories')) + if (!_.isArray(data)) { + throw new Error('Data is corrupted. it must be an array.') + } + } catch (err) { + console.log(err) + data = [] + _saveAllRepoStats(data) + } + return data +} + +/** + * Save All Repos + */ +function _saveAllRepoStats (repoStats) { + localStorage.setItem('repoStats', JSON.stringify(repoStats)) +} + +/** + * Add repository and return new Repo + * @param {Object} newRepo [description] + * ``` + * { + * key: String, + * name: String, + * path: String, + * status: String, + * folders: [{ + * key: String, + * color: String, + * name: String + * }], + * notes: [{ + * key: String, + * title: String, + * content: String, + * folder: String, + * tags: [String], + * createdAt: Date, + * updatedAt: Date + * }] + * } + * ``` + */ +function addRepo (newRepo) { + let { targetPath, name } = newRepo + targetPath = path.resolve(targetPath) + + let repoStat, repoJSON + return _resolveDirectory(targetPath) + .then(function initializeRepo () { + let resolveDataDirectory = _resolveDirectory(path.resolve(targetPath, 'data')) + let resolveBoostrepoJSON = _resolveRepoJSON(path.resolve(targetPath, 'boostrepo.json')) + return Promise.all([resolveDataDirectory, resolveBoostrepoJSON]) + }) + .then(function setLoalStorage (data) { + let dataPath = data[0] + repoJSON = data[1] + + let repoStats = getAllRepoStats() + + // generate unique key + let key = keygen() + while (repoStats.some((repoStat) => repoStat.key === key)) { + key = keygen() + } + + repoStat = { + key, + name: name, + path: targetPath + } + + repoStats.push(repoStat) + _saveAllRepoStats(repoStats) + + return dataPath + }) + .then(function fetchNotes (dataPath) { + let noteNames = fs.readdirSync(dataPath) + let notes = noteNames + .map((noteName) => { + let notePath = path.resolve(dataPath, noteNames) + + return new Promise(function (resolve, reject) { + CSON.readFile(notePath, function (err, obj) { + if (err != null) { + console.log(err) + return resolve(null) + } + obj.key = path.basename(noteName, '.cson') + return resolve(obj) + }) + }) + }) + .filter((note) => note != null) + + return Promise.all(notes) + }) + .then(function resolveRepo (notes) { + return Object.assign({}, repoJSON, repoStat, { + status: 'IDLE', + notes + }) + }) +} + +function getRepos () { + let repoStats + try { + repoStats = JSON.parse(localStorage.getItem('repoStats')) + if (repoStats == null) repoStats = [] + } catch (err) { + repoStats = [] + } + return repoStats + .map((repoStat) => { + let repoJSON, notes + try { + repoJSON = CSON.readFileSync(path.resolve(repoStat.path, 'boostrepo.json')) + let notePaths = fs.readdirSync(path.resolve(repoStat.path, 'data')) + notes = notePaths.map((notePath) => CSON.readFileSync(notePath)) + } catch (err) { + return Object.assign({}, repoStat, { + status: 'ERROR', + error: err + }) + } + return Object.assign({}, repoJSON, repoStat, { + status: 'IDLE', + notes + }) + }) +} + +export default { + getAllRepoStats, + addRepo, + getRepos +} diff --git a/browser/main/HomePage/ArticleNavigator.js b/browser/main/HomePage/ArticleNavigator.js deleted file mode 100644 index b8b69790..00000000 --- a/browser/main/HomePage/ArticleNavigator.js +++ /dev/null @@ -1,202 +0,0 @@ -import React, { PropTypes } from 'react' -import { findWhere } from 'lodash' -import { setSearchFilter, switchFolder, uncacheArticle, saveAllArticles, switchArticle, clearSearch } from '../actions' -import { openModal, isModalOpen } from 'browser/lib/modal' -import FolderMark from 'browser/components/FolderMark' -import Preferences from '../modal/Preferences' -import CreateNewFolder from '../modal/CreateNewFolder' -import _ from 'lodash' -import ModeIcon from 'browser/components/ModeIcon' - -const ipc = require('electron').ipcRenderer - -const BRAND_COLOR = '#18AF90' -const OSX = global.process.platform === 'darwin' - -const preferenceTutorialElement = ( - - Preference - - - - -) - -const newFolderTutorialElement = ( - - Create a new folder!! - {'press ' + (OSX ? '`⌘ + Shift + n`' : '`^ + Shift + n`')} - - - - - -) - -export default class ArticleNavigator extends React.Component { - constructor (props) { - super(props) - this.newFolderHandler = e => { - if (isModalOpen()) return true - this.handleNewFolderButton(e) - } - } - - componentDidMount () { - ipc.on('nav-new-folder', this.newFolderHandler) - } - - componentWillUnmount () { - ipc.removeListener('nav-new-folder', this.newFolderHandler) - } - - handlePreferencesButtonClick (e) { - openModal(Preferences) - } - - handleNewFolderButton (e) { - let { user } = this.props - openModal(CreateNewFolder, {user: user}) - } - - handleFolderButtonClick (name) { - return e => { - let { dispatch } = this.props - dispatch(switchFolder(name)) - } - } - - handleAllFoldersButtonClick (e) { - let { dispatch } = this.props - dispatch(setSearchFilter('')) - } - - handleUnsavedItemClick (article) { - let { dispatch } = this.props - return e => { - let { articles } = this.props - let isInArticleList = articles.some(_article => _article.key === article.key) - if (!isInArticleList) dispatch(clearSearch()) - dispatch(switchArticle(article.key)) - } - } - - handleUncacheButtonClick (article) { - let { dispatch } = this.props - return e => { - dispatch(uncacheArticle(article.key)) - } - } - - handleSaveAllClick (e) { - let { dispatch } = this.props - dispatch(saveAllArticles()) - } - - render () { - let { status, user, folders, allArticles, modified, activeArticle } = this.props - let { targetFolders } = status - if (targetFolders == null) targetFolders = [] - - let modifiedElements = modified.map(modifiedArticle => { - let originalArticle = _.findWhere(allArticles, {key: modifiedArticle.key}) - if (originalArticle == null) return false - let combinedArticle = Object.assign({}, originalArticle, modifiedArticle) - - let className = 'ArticleNavigator-unsaved-list-item' - if (activeArticle && activeArticle.key === combinedArticle.key) className += ' active' - - return ( -
this.handleUnsavedItemClick(combinedArticle)(e)} className={className}> -
-   - {combinedArticle.title.trim().length > 0 - ? combinedArticle.title - : (Untitled)} -
- -
- ) - }).filter(modifiedArticle => modifiedArticle).sort((a, b) => a.updatedAt - b.updatedAt) - let hasModified = modifiedElements.length > 0 - - let folderElememts = folders.map((folder, index) => { - let isActive = findWhere(targetFolders, {key: folder.key}) - let articleCount = allArticles.filter(article => article.FolderKey === folder.key && article.status !== 'NEW').length - - return ( - - ) - }) - - return ( -
-
-
{user.name}
-
localStorage
- - - {status.isTutorialOpen ? preferenceTutorialElement : null} - -
- - {/*
-
Work in progress
-
- {modifiedElements} -
-
- -
-
*/} - - - -
- {status.isTutorialOpen ? newFolderTutorialElement : null} -
-
Folders
- -
-
- - {folderElememts} -
-
-
- ) - } -} - -ArticleNavigator.propTypes = { - dispatch: PropTypes.func, - status: PropTypes.shape({ - folderId: PropTypes.number - }), - user: PropTypes.object, - folders: PropTypes.array, - allArticles: PropTypes.array, - articles: PropTypes.array, - modified: PropTypes.array, - activeArticle: PropTypes.shape({ - key: PropTypes.string - }) -} - diff --git a/browser/main/HomePage/SideNav/Repository.js b/browser/main/HomePage/SideNav/Repository.js new file mode 100644 index 00000000..2a849283 --- /dev/null +++ b/browser/main/HomePage/SideNav/Repository.js @@ -0,0 +1,75 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './Repository.styl' + +class Repository extends React.Component { + render () { + let { repository } = this.props + let folderElements = repository.folders.map((folder) => { + return ( +
+
+ {folder.name} +
+
+ + +
+
+ ) + }) + + return ( +
+
+
+ {repository.name} +
+ +
+ + + +
+
+ + {folderElements} + + +
+ ) + } +} + +Repository.propTypes = { + repository: PropTypes.shape({ + name: PropTypes.string, + folders: PropTypes.arrayOf(PropTypes.shape({ + name: PropTypes.string + })) + }) +} + +export default CSSModules(Repository, styles) diff --git a/browser/main/HomePage/SideNav/Repository.styl b/browser/main/HomePage/SideNav/Repository.styl new file mode 100644 index 00000000..c59997d2 --- /dev/null +++ b/browser/main/HomePage/SideNav/Repository.styl @@ -0,0 +1,90 @@ +.root + margin-top 15px + margin-bottom 15px + +.header + position relative + height 33px + &:hover + background-color alpha(white, 0.1) + +.header-name + position absolute + left 0 + top 0 + bottom 0 + right 72px + padding-left 10px + line-height 33px + color white + +.header-control + position absolute + top 0 + bottom 0 + right 5px + width 72px + +.header-control-button + width 24px + padding 0 + margin-top 4.5px + height 24px + border none + border-radius 5px + background-color transparent + color white + &:hover + background-color alpha(white, 0.1) + &:active + background-color $brand-color + +.folder + height 33px + width 100% + position relative + &:hover + background-color alpha(white 0.1) + +.folder-label + position absolute + left 0 + top 0 + bottom 0 + right 48px + padding-left 20px + line-height 33px + color white + +.folder-control + position absolute + top 0 + bottom 0 + right 0 + width 48px + +.folder-control-button + width 24px + height 24px + margin-top 4.5px + border none + border-radius 5px + background-color transparent + color white + &:hover + background-color alpha(white, 0.1) + &:active + background-color $brand-color + +.newFolderButton + height 33px + width 100% + border none + padding-left 20px + text-align left + background-color transparent + color white + &:hover + background-color alpha(white, 0.1) + &:active + background-color $brand-color diff --git a/browser/main/HomePage/SideNav/SideNav.styl b/browser/main/HomePage/SideNav/SideNav.styl new file mode 100644 index 00000000..b54462f5 --- /dev/null +++ b/browser/main/HomePage/SideNav/SideNav.styl @@ -0,0 +1,63 @@ +$nav-border-color = #838383 +$nav-background-color = #353535 + +.root + absolute top bottom left + width 200px + border-right solid 1px $nav-border-color + background-color $nav-background-color + +.menu + margin-top 30px + margin-bottom 15px + +.menu-button + height 33px + padding 0 10px + font-size 14px + width 100% + text-align left + border none + color white + background-color transparent + &:hover + background-color alph(white, 0.1) + &:active + background-color $brand-color + +.repositoryList + absolute left right + top 145px + border-top solid 1px $nav-border-color + +.control + absolute bottom left right + height 33px + border-top solid 1px $nav-border-color + +.control-newRepositoryButton + absolute top bottom left + width 167px + padding 0 10px + text-align left + border-width 0 1px 0 0 + border-color $nav-border-color + border-style solid + color white + background-color transparent + &:hover + background-color alph(white, 0.1) + &:active + background-color $brand-color + +.control-toggleButton + absolute top bottom right + width 33px + color white + background-color transparent + border none + &:hover + background-color alph(white, 0.1) + &:active + background-color $brand-color + diff --git a/browser/main/HomePage/SideNav/index.js b/browser/main/HomePage/SideNav/index.js new file mode 100644 index 00000000..e671ba20 --- /dev/null +++ b/browser/main/HomePage/SideNav/index.js @@ -0,0 +1,156 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './SideNav.styl' +import actions from 'browser/main/actions' +import { openModal, isModalOpen } from 'browser/lib/modal' +import Preferences from '../../modal/Preferences' +import CreateNewFolder from '../../modal/CreateNewFolder' +import Repository from './Repository' +import NewRepositoryModal from '../../modal/NewRepositoryModal' + +const ipc = require('electron').ipcRenderer + +const BRAND_COLOR = '#18AF90' +const OSX = global.process.platform === 'darwin' + +const preferenceTutorialElement = ( + + Preference + + + + +) + +const newFolderTutorialElement = ( + + Create a new folder!! + {'press ' + (OSX ? '`⌘ + Shift + n`' : '`^ + Shift + n`')} + + + + + +) + +class SideNav extends React.Component { + constructor (props) { + super(props) + this.newFolderHandler = e => { + if (isModalOpen()) return true + this.handleNewFolderButton(e) + } + } + + componentDidMount () { + ipc.on('nav-new-folder', this.newFolderHandler) + } + + componentWillUnmount () { + ipc.removeListener('nav-new-folder', this.newFolderHandler) + } + + handlePreferencesButtonClick (e) { + openModal(Preferences) + } + + handleNewFolderButton (e) { + let { user } = this.props + openModal(CreateNewFolder, {user: user}) + } + + handleFolderButtonClick (name) { + return e => { + let { dispatch } = this.props + dispatch(actions.switchFolder(name)) + } + } + + handleAllFoldersButtonClick (e) { + let { dispatch } = this.props + dispatch(actions.setSearchFilter('')) + } + + handleNewRepositoryButtonClick (e) { + openModal(NewRepositoryModal) + } + + render () { + let { repositories } = this.props + let repositorieElements = repositories.map((repo) => { + return + }) + + return ( +
+
+ + + +
+ +
+ {repositories.length > 0 ? repositorieElements : ( +
Empty
+ )} +
+ +
+ + +
+
+ ) + } +} + +SideNav.propTypes = { + dispatch: PropTypes.func, + status: PropTypes.shape({ + folderId: PropTypes.number + }), + user: PropTypes.object, + folders: PropTypes.array, + allArticles: PropTypes.array, + articles: PropTypes.array, + modified: PropTypes.array, + activeArticle: PropTypes.shape({ + key: PropTypes.string + }), + repositories: PropTypes.array +} + +export default CSSModules(SideNav, styles) diff --git a/browser/main/HomePage/index.js b/browser/main/HomePage/index.js index 54274a97..da4c3dfa 100644 --- a/browser/main/HomePage/index.js +++ b/browser/main/HomePage/index.js @@ -2,7 +2,7 @@ import React, { PropTypes} from 'react' import { connect } from 'react-redux' import ReactDOM from 'react-dom' import { toggleTutorial } from '../actions' -import ArticleNavigator from './ArticleNavigator' +import SideNav from './SideNav' import ArticleTopBar from './ArticleTopBar' import ArticleList from './ArticleList' import ArticleDetail from './ArticleDetail' @@ -73,12 +73,14 @@ class HomePage extends React.Component { render () { let { dispatch, status, user, articles, allArticles, modified, activeArticle, folders, tags } = this.props + let { repositories } = this.props return (
- { + dialog.showOpenDialog({ + title: 'Select Directory', + defaultPath, + properties: ['openDirectory', 'createDirectory'] + }, function (targetPaths) { + if (targetPaths == null) return resolve('') + resolve(targetPaths[0]) + }) + }) +} + +class NewRepositoryModal extends React.Component { + constructor (props) { + super(props) + + this.state = { + name: '', + path: '', + isPathSectionFocused: false, + error: null, + isBrowsingPath: false + } + } + + handleCloseButtonClick (e) { + this.props.close() + } + + handlePathFocus (e) { + this.setState({ + isPathSectionFocused: true + }) + } + + handlePathBlur (e) { + if (e.relatedTarget !== this.refs.pathInput && e.relatedTarget !== this.refs.browseButton) { + this.setState({ + isPathSectionFocused: false + }) + } + } + + handleBrowseButtonClick (e) { + this.setState({ + isBrowsingPath: true + }, () => { + browseFolder() + .then((targetPath) => { + this.setState({ + path: targetPath, + isBrowsingPath: false + }) + }) + .catch((err) => { + console.error('BrowseFAILED') + console.error(err) + this.setState({ + isBrowsingPath: false + }) + }) + }) + } + + handleConfirmButtonClick (e) { + let targetPath = this.state.path + let name = this.state.name + + RepositoryManager + .addRepo({ + targetPath, + name + }) + .then((newRepo) => { + store.dispatch(actions.addRepo(newRepo)) + this.props.close() + }) + .catch((err) => { + console.error(err) + this.setState({ + error: err.message + }) + }) + } + + render () { + return ( +
+
+
New Repository
+ +
+
+
+
Repository Name
+ +
+ +
+
Repository Path
+
+ this.handlePathFocus(e)} + onBlur={(e) => this.handlePathBlur(e)} + disabled={this.state.isBrowsingPath} + /> + +
+
+ { + this.state.error != null && ( +
+ {this.state.error} +
+ ) + } +
+ +
+ + +
+
+ ) + } +} + +NewRepositoryModal.propTypes = { + close: PropTypes.func +} + +NewRepositoryModal.prototype.linkState = linkState + +export default CSSModules(NewRepositoryModal, styles) diff --git a/browser/main/modal/NewRepositoryModal.styl b/browser/main/modal/NewRepositoryModal.styl new file mode 100644 index 00000000..9f555f9c --- /dev/null +++ b/browser/main/modal/NewRepositoryModal.styl @@ -0,0 +1,133 @@ +$modal-width = 550px +$modal-header-color = #F2F2F2 +$body-button-background-color = #2BAC8F + +.root + modal() + width $modal-width + height 310px + +.header + height 50px + background-color $modal-header-color + +.header-title + font-size 24px + line-height 50px + padding-left 15px + +.header-closeButton + position absolute + top 8.5px + right 8.5px + width 33px + height 33px + font-size 20px + background-color transparent + border none + color #AAA + &:hover + color #4D4D4D + +.body + absolute left right + top 50px + bottom 50px + padding 35px 0 + +.body-section + height 33px + margin-bottom 15px + position relative + +.body-section-label + absolute top bottom left + width 175px + text-align right + line-height 33px + padding-right 15px + +.body-section-input + absolute top bottom + left 175px + width 315px + padding 0 10px + border $default-border + border-radius 5px + outline none + &:focus + border $active-border + +.body-section-path + absolute top bottom + left 175px + width 315px + padding 0 10px + border $default-border + border-radius 5px + outline none + overflow hidden + +.body-section-path--focus + @extend .body-section-path + border $active-border + +.body-section-path-input + absolute top left bottom + width 265px + border none + outline none + padding 0 10px + +.body-section-path-button + absolute top right bottom + width 50px + border none + border-left $default-border + outline none + color white + background-color $body-button-background-color + transition 0.15s + &:hover + background-color lighten($body-button-background-color, 7%) + &:disabled + background-color lighten(gray, 15%) + +.body-error + height 33px + margin 35px auto 0 + width 320px + border-radius 5px + text-align center + line-height 33px + color $danger-color + background-color $danger-lighten-color + +.footer + absolute left right bottom + height 50px + +.footer-cancelButton + position absolute + height 33px + right 85.5px + width 72px + top 8.5px + border-radius 5px + border $default-border + background-color darken(white, 0.03) + &:hover + background-color white + +.footer-confirmButton + position absolute + height 33px + right 8.5px + width 72px + top 8.5px + color white + border-radius 5px + border none + background-color #2BAC8F + &:hover + background-color lighten($body-button-background-color, 7%) diff --git a/browser/main/reducer.js b/browser/main/reducer.js index 8f7afd10..9c3db1f7 100644 --- a/browser/main/reducer.js +++ b/browser/main/reducer.js @@ -36,14 +36,16 @@ const initialStatus = { isTutorialOpen: false } -dataStore.init() -let data = dataStore.getData() +let data = { + articles: [], + folders: [] +} let initialArticles = { data: data && data.articles ? data.articles : [], modified: [] } let initialFolders = data && data.folders ? data.folders : [] -let initialUser = dataStore.getUser().user +let initialUser = {} function user (state = initialUser, action) { switch (action.type) { @@ -298,9 +300,53 @@ function status (state = initialStatus, action) { } } +/** + * v0.6.* Reducers + */ + +/** + * Repositories + * ``` + * repositories = [{ + * key: String, + * name: String, + * path: String, // path of repository + * status: String, // status of repository [LOADING, IDLE, ERROR] + * folders: { + * name: String, + * color: String + * }, + * notes: [{ + * key: String, + * title: String, + * content: String, + * folder: String, + * tags: [String], + * createdAt: Date, + * updatedAt: Date + * }] + * }] + * ``` + */ +import RepositoryManager from 'browser/lib/RepositoryManager' +const initialRepositories = RepositoryManager.getRepos() + +function repositories (state = initialRepositories, action) { + console.log(state) + switch (action.type) { + case 'ADD_REPOSITORY': + let repos = state.slice() + repos.push(action.data) + return repos + } + return state +} +// v0.6 end + export default combineReducers({ user, folders, articles, - status + status, + repositories })