From ef84c4e3da762757f5350875be9bfffa3bf64325 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sat, 14 Nov 2015 23:49:49 +0900 Subject: [PATCH 01/16] =?UTF-8?q?Intro=E3=81=AEFinder=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/styles/main/HomeContainer/lib/Tutorial.styl | 2 ++ lib/components/modal/Tutorial.js | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/browser/styles/main/HomeContainer/lib/Tutorial.styl b/browser/styles/main/HomeContainer/lib/Tutorial.styl index 913bfbe5..309c785a 100644 --- a/browser/styles/main/HomeContainer/lib/Tutorial.styl +++ b/browser/styles/main/HomeContainer/lib/Tutorial.styl @@ -108,6 +108,8 @@ slideBgColor4 = #00B493 height 140px .slide3 background-color slideBgColor3 + .title + margin-bottom 15px .content font-size 18px &>img diff --git a/lib/components/modal/Tutorial.js b/lib/components/modal/Tutorial.js index cb2f2ed4..cc927d92 100644 --- a/lib/components/modal/Tutorial.js +++ b/lib/components/modal/Tutorial.js @@ -88,10 +88,11 @@ export default class Tutorial extends React.Component { return (
Easy to access with Finder
- With Finder, You can search your articles faster.
- You can open Finder by pressing Control + shift + tab
- To put the content of an article in the clipboard, press Enter.
- So you can paste it with Cmd(⌘) + V + The Finder helps you organize all of the files and documents.
+ There is a short-cut key [control + shift + tab] to open the Finder.
+ It is available to save your articles on the Clipboard
+ by selecting your file with pressing Enter key,
+ and to paste the contents of the Clipboard with [Command-V]
From 41e1630aaca05682d7f0f92cd232ce7da7676b33 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 00:57:29 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80?= =?UTF-8?q?=E3=83=BC=E3=81=A7=E6=A4=9C=E7=B4=A2=E3=81=99=E3=82=8B=E3=81=A8?= =?UTF-8?q?=E3=81=8D=E3=81=AB=20in:=E3=81=98=E3=82=83=E3=81=AA=E3=81=8F?= =?UTF-8?q?=E3=81=A6=20/=E3=81=AB=E3=81=99=E3=82=8B=20=EF=BC=8B=E3=83=90?= =?UTF-8?q?=E3=82=B0=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/finder/index.js | 9 +++++---- browser/finder/reducer.js | 4 ++-- browser/main/HomePage.js | 10 +++++----- browser/main/HomePage/ArticleTopBar.js | 4 ++-- lib/reducer.js | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/browser/finder/index.js b/browser/finder/index.js index 7fef8c7d..36521d1c 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -119,9 +119,9 @@ FinderMain.propTypes = { function remap (state) { let { articles, folders, status } = state - let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^#$/)).map(key => { - if (key.match(/^in:.+$/)) { - return {type: FOLDER_FILTER, value: key.match(/^in:(.+)$/)[1]} + let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^\/$/) && !key.match(/^#$/)).map(key => { + if (key.match(/^\/.+$/)) { + return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} } if (key.match(/^#(.+)/)) { return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} @@ -134,7 +134,7 @@ function remap (state) { if (folders != null) { let targetFolders = folders.filter(folder => { - return _.findWhere(folderFilters, {value: folder.name}) + return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`))) }) status.targetFolders = targetFolders @@ -164,6 +164,7 @@ function remap (state) { let activeArticle = _.findWhere(articles, {key: status.articleKey}) if (activeArticle == null) activeArticle = articles[0] + console.log(status.search) return { articles, activeArticle, diff --git a/browser/finder/reducer.js b/browser/finder/reducer.js index 72b087c3..76ddde7f 100644 --- a/browser/finder/reducer.js +++ b/browser/finder/reducer.js @@ -14,10 +14,10 @@ function status (state = initialStatus, action) { switch (action.type) { case SELECT_ARTICLE: state.articleKey = action.data.key - return state + return Object.assign({}, state) case SEARCH_ARTICLE: state.search = action.data.input - return state + return Object.assign({}, state) default: return state } diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index 57094068..e3fe68be 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -143,9 +143,9 @@ function remap (state) { }) // Filter articles - let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^#$/)).map(key => { - if (key.match(/^in:.+$/)) { - return {type: FOLDER_FILTER, value: key.match(/^in:(.+)$/)[1]} + let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^\/$/) && !key.match(/^#$/)).map(key => { + if (key.match(/^\/.+/)) { + return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} } if (key.match(/^#(.+)/)) { return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} @@ -158,7 +158,7 @@ function remap (state) { if (folders != null) { let targetFolders = folders.filter(folder => { - return _.findWhere(folderFilters, {value: folder.name}) + return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`))) }) status.targetFolders = targetFolders @@ -204,7 +204,7 @@ function remap (state) { let newArticle = _.findWhere(articles, {status: 'NEW'}) let FolderKey = folders[0].key if (folderFilters.length > 0) { - let targetFolder = _.findWhere(folders, {name: folderFilters[0].value}) + let targetFolder = _.find(folders, folder => folder.name.match(new RegExp(`^${folderFilters[0].value}`))) if (targetFolder != null) FolderKey = targetFolder.key } diff --git a/browser/main/HomePage/ArticleTopBar.js b/browser/main/HomePage/ArticleTopBar.js index bfa38cae..285b95de 100644 --- a/browser/main/HomePage/ArticleTopBar.js +++ b/browser/main/HomePage/ArticleTopBar.js @@ -10,7 +10,7 @@ const searchTutorialElement = ( Search some posts!! {'- Search by tag : #{string}'} - {'- Search by folder : in:{folder_name}\n'} + {'- Search by folder : /{folder_name}\n'} - Search by tag : #{'{string}'}
- - Search by folder : in:{'{folder_name}'} + - Search by folder : /{'{folder_name}'}
diff --git a/lib/reducer.js b/lib/reducer.js index 52cd5916..0d28efb1 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -131,7 +131,7 @@ function status (state = initialStatus, action) { return state case SWITCH_FOLDER: state.mode = IDLE_MODE - state.search = `in:${action.data} ` + state.search = `/${action.data} ` return state case SWITCH_MODE: From fb1462f669afc6085807aa49653bc25c8077b20d Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 01:07:46 +0900 Subject: [PATCH 03/16] =?UTF-8?q?Folder=20=E3=83=AA=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=AB=20article=E3=81=AE=E6=95=B0=E3=82=92=E3=81=A0?= =?UTF-8?q?=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/main/HomePage.js | 6 +++++- browser/main/HomePage/ArticleNavigator.js | 6 ++++-- .../main/HomeContainer/components/ArticleNavigator.styl | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index e3fe68be..1504cda9 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -98,7 +98,7 @@ class HomePage extends React.Component { } render () { - let { dispatch, status, articles, activeArticle, folders, filters } = this.props + let { dispatch, status, articles, allArticles, activeArticle, folders, filters } = this.props return (
@@ -107,6 +107,7 @@ class HomePage extends React.Component { dispatch={dispatch} folders={folders} status={status} + allArticles={allArticles} /> { return new Date(b.updatedAt) - new Date(a.updatedAt) }) + let allArticles = articles.slice() // Filter articles let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^\/$/) && !key.match(/^#$/)).map(key => { @@ -229,6 +231,7 @@ function remap (state) { return { folders, status, + allArticles, articles, activeArticle, filters: { @@ -247,6 +250,7 @@ HomePage.propTypes = { userId: PropTypes.string }), articles: PropTypes.array, + allArticles: PropTypes.array, activeArticle: PropTypes.shape(), dispatch: PropTypes.func, folders: PropTypes.array, diff --git a/browser/main/HomePage/ArticleNavigator.js b/browser/main/HomePage/ArticleNavigator.js index 17e37c45..d4c21131 100644 --- a/browser/main/HomePage/ArticleNavigator.js +++ b/browser/main/HomePage/ArticleNavigator.js @@ -88,16 +88,17 @@ export default class ArticleNavigator extends React.Component { } render () { - let { status, folders } = this.props + let { status, folders, allArticles } = this.props let { targetFolders } = status if (targetFolders == null) targetFolders = [] let folderElememts = folders.map((folder, index) => { let isActive = findWhere(targetFolders, {key: folder.key}) + let articleCount = allArticles.filter(article => article.FolderKey === folder.key).length return ( ) }) @@ -150,6 +151,7 @@ export default class ArticleNavigator extends React.Component { ArticleNavigator.propTypes = { activeUser: PropTypes.object, folders: PropTypes.array, + allArticles: PropTypes.array, status: PropTypes.shape({ folderId: PropTypes.number }), diff --git a/browser/styles/main/HomeContainer/components/ArticleNavigator.styl b/browser/styles/main/HomeContainer/components/ArticleNavigator.styl index 77b19b03..68c798cf 100644 --- a/browser/styles/main/HomeContainer/components/ArticleNavigator.styl +++ b/browser/styles/main/HomeContainer/components/ArticleNavigator.styl @@ -1,4 +1,5 @@ articleNavBgColor = #353535 +articleCount = #999 .ArticleNavigator background-color articleNavBgColor @@ -150,6 +151,9 @@ articleNavBgColor = #353535 background-color transparentify(white, 5%) &.active, &:active background-color brandColor + .articleCount + color articleCount + font-size 12px .members .memberList>div height 33px From 3e980fd2d45f57215910c0939771bf57eab9dfc7 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 01:22:56 +0900 Subject: [PATCH 04/16] =?UTF-8?q?Finder=E3=81=ABCopy=20to=20clipboard=20bu?= =?UTF-8?q?tton=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/finder/FinderDetail.js | 14 ++++++++++++-- browser/finder/index.html | 2 +- browser/finder/index.js | 18 +++++++++++++----- browser/styles/finder/index.styl | 25 +++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/browser/finder/FinderDetail.js b/browser/finder/FinderDetail.js index b50392fa..7d3ad12e 100644 --- a/browser/finder/FinderDetail.js +++ b/browser/finder/FinderDetail.js @@ -11,7 +11,16 @@ export default class FinderDetail extends React.Component { return (
- {activeArticle.title}
+
+ {activeArticle.title} +
+
+ +
+
{activeArticle.mode === 'markdown' ? @@ -30,5 +39,6 @@ export default class FinderDetail extends React.Component { } FinderDetail.propTypes = { - activeArticle: PropTypes.shape() + activeArticle: PropTypes.shape(), + saveToClipboard: PropTypes.func } diff --git a/browser/finder/index.html b/browser/finder/index.html index 0a058ce7..8e3928ac 100644 --- a/browser/finder/index.html +++ b/browser/finder/index.html @@ -2,7 +2,7 @@ - CodeXen Popup + Boost Finder diff --git a/browser/finder/index.js b/browser/finder/index.js index 36521d1c..ace7bae1 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -45,10 +45,7 @@ class FinderMain extends React.Component { } if (e.keyCode === 13) { - let { activeArticle } = this.props - clipboard.writeText(activeArticle.content) - activityRecord.emit('FINDER_COPY') - hideFinder() + this.saveToClipboard() e.preventDefault() } if (e.keyCode === 27) { @@ -57,6 +54,13 @@ class FinderMain extends React.Component { } } + saveToClipboard () { + let { activeArticle } = this.props + clipboard.writeText(activeArticle.content) + activityRecord.emit('FINDER_COPY') + hideFinder() + } + handleSearchChange (e) { let { dispatch } = this.props @@ -83,6 +87,7 @@ class FinderMain extends React.Component { render () { let { articles, activeArticle, status, dispatch } = this.props + let saveToClipboard = () => this.saveToClipboard() return (
this.handleClick(e)} onKeyDown={e => this.handleKeyDown(e)} className='Finder'> this.selectArticle(article)} /> - +
) } diff --git a/browser/styles/finder/index.styl b/browser/styles/finder/index.styl index ca2a9111..d91383c5 100644 --- a/browser/styles/finder/index.styl +++ b/browser/styles/finder/index.styl @@ -79,6 +79,31 @@ body white-space nowrap text-overflow ellipsis overflow-x hidden + clearfix() + .left + float left + .right + float right + button + border-radius 16.5px + cursor pointer + height 33px + width 33px + border none + margin-right 5px + font-size 18px + color inactiveTextColor + background-color transparent + padding 0 + .tooltip + tooltip() + &.clipboardBtn .tooltip + margin-left -160px + margin-top 25px + &:hover + color textColor + .tooltip + opacity 1 .content position absolute top 55px From 46c6555f9408b580f2bd041c157db8e8c8f305d1 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 01:39:40 +0900 Subject: [PATCH 05/16] =?UTF-8?q?Finder=E3=81=8B=E3=82=89Copy=E3=81=97?= =?UTF-8?q?=E3=81=9F=E6=99=82=E3=80=81=E9=80=9A=E7=9F=A5=E3=82=92=E5=87=BA?= =?UTF-8?q?=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/finder/index.js | 12 ++++++++++++ webpack.config.js | 3 ++- webpack.config.production.js | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/browser/finder/index.js b/browser/finder/index.js index ace7bae1..921abf1d 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -14,6 +14,12 @@ import remote from 'remote' var hideFinder = remote.getGlobal('hideFinder') import clipboard from 'clipboard' +var notifier = require('node-notifier') +var path = require('path') +function getIconPath () { + return path.resolve(global.__dirname, '../../resources/favicon-230x230.png') +} + require('../styles/finder/index.styl') const FOLDER_FILTER = 'FOLDER_FILTER' @@ -58,6 +64,12 @@ class FinderMain extends React.Component { let { activeArticle } = this.props clipboard.writeText(activeArticle.content) activityRecord.emit('FINDER_COPY') + + notifier.notify({ + icon: getIconPath(), + 'title': 'Saved to Clipboard!', + 'message': 'Paste it wherever you want!' + }) hideFinder() } diff --git a/webpack.config.js b/webpack.config.js index b9492ffb..ce7cdf5d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -68,7 +68,8 @@ var config = { 'superagent-promise', 'lodash', 'markdown-it', - 'moment' + 'moment', + 'node-notifier' ] } diff --git a/webpack.config.production.js b/webpack.config.production.js index 737e0d13..8eda4cc5 100644 --- a/webpack.config.production.js +++ b/webpack.config.production.js @@ -45,7 +45,8 @@ module.exports = { 'superagent-promise', 'lodash', 'markdown-it', - 'moment' + 'moment', + 'node-notifier' ], resolve: { extensions: ['', '.js', '.jsx', 'styl'] From da9d7a4336ae061e46dd7d97d236dedfb5df52b6 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 03:52:34 +0900 Subject: [PATCH 06/16] =?UTF-8?q?auto=20update=E7=A2=BA=E8=AA=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atom-lib/updater.js | 21 +++++++++++++-------- browser/main/index.js | 4 ++++ main.js | 12 ++++++++++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/atom-lib/updater.js b/atom-lib/updater.js index d506b643..38a112fb 100644 --- a/atom-lib/updater.js +++ b/atom-lib/updater.js @@ -5,33 +5,38 @@ var path = require('path') var version = app.getVersion() var versionText = (version == null || version.length === 0) ? 'DEV version' : 'v' + version - +var versionNotified = false autoUpdater .on('error', function (err, message) { console.error(err) console.error(message) + console.log(path.resolve(__dirname, '../resources/favicon-230x230.png')) nn.notify({ title: 'Error! ' + versionText, - icon: path.join(__dirname, 'browser/main/resources/favicon-230x230.png'), + icon: path.resolve(__dirname, '../resources/favicon-230x230.png'), message: message }) }) // .on('checking-for-update', function () { // // Connecting + // console.log('checking...') // }) .on('update-available', function () { nn.notify({ title: 'Update is available!! ' + versionText, - icon: path.join(__dirname, 'browser/main/resources/favicon-230x230.png'), + icon: path.resolve(__dirname, '../resources/favicon-230x230.png'), message: 'Download started.. wait for the update ready.' }) }) .on('update-not-available', function () { - nn.notify({ - title: 'Latest Build!! ' + versionText, - icon: path.join(__dirname, 'browser/main/resources/favicon-230x230.png'), - message: 'Hope you to enjoy our app :D' - }) + if (!versionNotified) { + nn.notify({ + title: 'Latest Build!! ' + versionText, + icon: path.resolve(__dirname, '../resources/favicon-230x230.png'), + message: 'Hope you to enjoy our app :D' + }) + versionNotified = true + } }) module.exports = autoUpdater diff --git a/browser/main/index.js b/browser/main/index.js index a749bdbe..028a2180 100644 --- a/browser/main/index.js +++ b/browser/main/index.js @@ -11,8 +11,12 @@ require('../styles/main/index.styl') import { openModal } from 'boost/modal' import Tutorial from 'boost/components/modal/Tutorial' import activityRecord from 'boost/activityRecord' +import ipc from 'ipc' activityRecord.init() +window.addEventListener('online', function () { + ipc.send('check-update', 'check-update') +}) let routes = ( diff --git a/main.js b/main.js index d3b9bd7d..1d63eb1c 100644 --- a/main.js +++ b/main.js @@ -30,8 +30,8 @@ updater .on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) { nn.notify({ title: 'Ready to Update!! ' + versionText, - icon: path.join(__dirname, 'browser/main/resources/favicon-230x230.png'), - message: 'Click tray icon to update app: ' + releaseName + icon: path.join(__dirname, '/resources/favicon-230x230.png'), + message: 'Click update button on Main window: ' + releaseName }) update = quitAndUpdate @@ -50,6 +50,14 @@ app.on('ready', function () { // menu start var template = require('./atom-lib/menu-template') + setInterval(function () { + updater.checkForUpdates() + }, 1000 * 60 * 60 * 24) + + ipc.on('check-update', function (event, msg) { + updater.checkForUpdates() + }) + ipc.on('update-app', function (event, msg) { if (update != null) { appQuit = true From 26a08fac06ba7349f230aa65632ad4eb12167896 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 20:32:02 +0900 Subject: [PATCH 07/16] =?UTF-8?q?new=20folder=20modal=E3=81=ABcolor=20sele?= =?UTF-8?q?ct=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ArticleNavigator.styl | 2 +- .../HomeContainer/lib/CreateNewFolder.styl | 24 +++++++++++-- lib/components/FolderMark.js | 25 ++++++++------ lib/components/modal/CreateNewFolder.js | 34 +++++++++++++++++-- lib/reducer.js | 4 +-- 5 files changed, 71 insertions(+), 18 deletions(-) diff --git a/browser/styles/main/HomeContainer/components/ArticleNavigator.styl b/browser/styles/main/HomeContainer/components/ArticleNavigator.styl index 68c798cf..af61cf3d 100644 --- a/browser/styles/main/HomeContainer/components/ArticleNavigator.styl +++ b/browser/styles/main/HomeContainer/components/ArticleNavigator.styl @@ -150,7 +150,7 @@ articleCount = #999 &:hover background-color transparentify(white, 5%) &.active, &:active - background-color brandColor + background-color transparentify(lighten(brandColor, 25%), 70%) .articleCount color articleCount font-size 12px diff --git a/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl b/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl index 2e1c6507..b813f983 100644 --- a/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl +++ b/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl @@ -34,9 +34,29 @@ iptFocusBorderColor = #369DCD border-radius 5px border solid 1px borderColor outline none - margin 100px auto 25px + margin 100px auto 15px &:focus border-color iptFocusBorderColor + .colorSelect + text-align center + .option + cursor pointer + .FolderMark + padding 5px + font-size 22px + height 33px + width 33px + overflow hidden + line-height 33px + transition 0.1s + border 1px solid transparent + border-radius 5px + margin 0 2px + &:hover + border-color borderColor + &.active + font-size 28px + border-color iptFocusBorderColor .alert color infoTextColor background-color infoBackgroundColor @@ -44,7 +64,7 @@ iptFocusBorderColor = #369DCD padding 15px 15px width 330px border-radius 5px - margin 0 auto + margin 15px auto 0 &.error color errorTextColor background-color errorBackgroundColor diff --git a/lib/components/FolderMark.js b/lib/components/FolderMark.js index ef258bb1..dd6708b9 100644 --- a/lib/components/FolderMark.js +++ b/lib/components/FolderMark.js @@ -3,45 +3,50 @@ import React, { PropTypes } from 'react' const BLUE = '#3460C7' const LIGHTBLUE = '#2BA5F7' const ORANGE = '#FF8E00' -const YELLOW = '#EAEF31' -const GREEN = '#02FF26' -const DARKGREEN = '#008A59' +const YELLOW = '#E8D252' +const GREEN = '#3FD941' +const DARKGREEN = '#1FAD85' const RED = '#E10051' const PURPLE = '#B013A4' -const BRAND_COLOR = '#2BAC8F' function getColorByIndex (index) { switch (index % 8) { case 0: - return LIGHTBLUE + return RED case 1: return ORANGE case 2: - return RED + return YELLOW case 3: return GREEN case 4: return DARKGREEN case 5: - return YELLOW + return LIGHTBLUE case 6: return BLUE case 7: return PURPLE default: - return BRAND_COLOR + return DARKGREEN } } export default class FolderMark extends React.Component { render () { let color = getColorByIndex(this.props.color) + let className = 'FolderMark fa fa-square fa-fw' + if (this.props.className != null) { + className += ' active' + } + return ( - + ) } } FolderMark.propTypes = { - color: PropTypes.number + color: PropTypes.number, + className: PropTypes.string } diff --git a/lib/components/modal/CreateNewFolder.js b/lib/components/modal/CreateNewFolder.js index 0934e219..de064b5a 100644 --- a/lib/components/modal/CreateNewFolder.js +++ b/lib/components/modal/CreateNewFolder.js @@ -2,6 +2,7 @@ import React, { PropTypes } from 'react' import linkState from 'boost/linkState' import { createFolder } from 'boost/actions' import store from 'boost/store' +import FolderMark from 'boost/components/FolderMark' export default class CreateNewFolder extends React.Component { constructor (props) { @@ -9,6 +10,7 @@ export default class CreateNewFolder extends React.Component { this.state = { name: '', + color: Math.round(Math.random() * 7), alert: null } } @@ -20,9 +22,11 @@ export default class CreateNewFolder extends React.Component { handleConfirmButton (e) { this.setState({alert: null}, () => { let { close } = this.props - let name = this.state.name + let { name, color } = this.state + let input = { - name + name, + color } try { @@ -38,6 +42,14 @@ export default class CreateNewFolder extends React.Component { }) } + handleColorClick (colorIndex) { + return e => { + this.setState({ + color: colorIndex + }) + } + } + render () { let alert = this.state.alert let alertElement = alert != null ? ( @@ -45,6 +57,21 @@ export default class CreateNewFolder extends React.Component { {alert.message}

) : null + let colorIndexes = [] + for (let i = 0; i < 8; i++) { + colorIndexes.push(i) + } + let colorElements = colorIndexes.map(index => { + let className = index === this.state.color + ? 'active' + : null + + return ( + this.handleColorClick(index)(e)}> + + + ) + }) return (
@@ -53,6 +80,9 @@ export default class CreateNewFolder extends React.Component {
Create new folder
+
+ {colorElements} +
{alertElement} diff --git a/lib/reducer.js b/lib/reducer.js index 0d28efb1..1c937100 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -26,9 +26,7 @@ function folders (state = initialFolders, action) { Object.assign(newFolder, { key: keygen(), createdAt: new Date(), - updatedAt: new Date(), - // random number (0-7) - color: Math.round(Math.random() * 7) + updatedAt: new Date() }) if (newFolder.length === 0) throw new Error('Folder name is required') From bbc3c852129f1a56ad7fb6b2481bf609172f5409 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 20:40:43 +0900 Subject: [PATCH 08/16] fix style --- .../HomeContainer/lib/CreateNewFolder.styl | 35 ++++++++++--------- lib/components/modal/CreateNewFolder.js | 9 +++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl b/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl index b813f983..af3ec002 100644 --- a/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl +++ b/browser/styles/main/HomeContainer/lib/CreateNewFolder.styl @@ -34,29 +34,30 @@ iptFocusBorderColor = #369DCD border-radius 5px border solid 1px borderColor outline none - margin 100px auto 15px + margin 75px auto 20px &:focus border-color iptFocusBorderColor .colorSelect text-align center .option cursor pointer - .FolderMark - padding 5px - font-size 22px - height 33px - width 33px - overflow hidden - line-height 33px - transition 0.1s - border 1px solid transparent - border-radius 5px - margin 0 2px - &:hover - border-color borderColor - &.active - font-size 28px - border-color iptFocusBorderColor + font-size 22px + height 48px + width 48px + margin 0 2px + border 1px solid transparent + border-radius 5px + overflow hidden + line-height 45px + text-align center + transition 0.1s + display inline-block + &:hover + border-color borderColor + font-size 28px + &.active + font-size 28px + border-color iptFocusBorderColor .alert color infoTextColor background-color infoBackgroundColor diff --git a/lib/components/modal/CreateNewFolder.js b/lib/components/modal/CreateNewFolder.js index de064b5a..bee88582 100644 --- a/lib/components/modal/CreateNewFolder.js +++ b/lib/components/modal/CreateNewFolder.js @@ -62,13 +62,12 @@ export default class CreateNewFolder extends React.Component { colorIndexes.push(i) } let colorElements = colorIndexes.map(index => { - let className = index === this.state.color - ? 'active' - : null + let className = 'option' + if (index === this.state.color) className += ' active' return ( - this.handleColorClick(index)(e)}> - + this.handleColorClick(index)(e)}> + ) }) From b28b18a19a16ab979f0444eb724f28dfa2837ef4 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Sun, 15 Nov 2015 23:20:06 +0900 Subject: [PATCH 09/16] =?UTF-8?q?//=20filter=E3=82=92=E4=BD=BF=E3=81=86?= =?UTF-8?q?=E3=81=A8=E7=A2=BA=E5=AE=9F=E3=81=ABFolder=E5=90=8D=E3=81=8C?= =?UTF-8?q?=E4=B8=80=E8=87=B4=E3=81=99=E3=82=8B=E3=82=82=E3=81=AE=E3=81=AE?= =?UTF-8?q?=E3=81=BF=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/finder/index.js | 43 +++++++++++++++------ browser/main/HomePage.js | 52 ++++++++++++++++++-------- browser/main/HomePage/ArticleTopBar.js | 2 + lib/reducer.js | 5 ++- 4 files changed, 73 insertions(+), 29 deletions(-) diff --git a/browser/finder/index.js b/browser/finder/index.js index 921abf1d..8ef40501 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -23,6 +23,7 @@ function getIconPath () { require('../styles/finder/index.styl') const FOLDER_FILTER = 'FOLDER_FILTER' +const FOLDER_EXACT_FILTER = 'FOLDER_EXACT_FILTER' const TEXT_FILTER = 'TEXT_FILTER' const TAG_FILTER = 'TAG_FILTER' @@ -136,27 +137,47 @@ FinderMain.propTypes = { dispatch: PropTypes.func } +// Ignore invalid key +function ignoreInvalidKey (key) { + return key.length > 0 && !key.match(/^\/\/$/) && !key.match(/^\/$/) && !key.match(/^#$/) +} + +// Build filter object by key +function buildFilter (key) { + if (key.match(/^\/\/.+/)) { + return {type: FOLDER_EXACT_FILTER, value: key.match(/^\/\/(.+)$/)[1]} + } + if (key.match(/^\/.+/)) { + return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} + } + if (key.match(/^#(.+)/)) { + return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} + } + return {type: TEXT_FILTER, value: key} +} + function remap (state) { let { articles, folders, status } = state - let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^\/$/) && !key.match(/^#$/)).map(key => { - if (key.match(/^\/.+$/)) { - return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} - } - if (key.match(/^#(.+)/)) { - return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} - } - return {type: TEXT_FILTER, value: key} - }) + let filters = status.search.split(' ') + .map(key => key.trim()) + .filter(ignoreInvalidKey) + .map(buildFilter) + + let folderExactFilters = filters.filter(filter => filter.type === FOLDER_EXACT_FILTER) let folderFilters = filters.filter(filter => filter.type === FOLDER_FILTER) let textFilters = filters.filter(filter => filter.type === TEXT_FILTER) let tagFilters = filters.filter(filter => filter.type === TAG_FILTER) + let targetFolders if (folders != null) { - let targetFolders = folders.filter(folder => { + let exactTargetFolders = folders.filter(folder => { + return _.find(folderExactFilters, filter => folder.name.match(new RegExp(`^${filter.value}$`))) + }) + let fuzzyTargetFolders = folders.filter(folder => { return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`))) }) - status.targetFolders = targetFolders + targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders) if (targetFolders.length > 0) { articles = articles.filter(article => { diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index 1504cda9..beb312ee 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -12,6 +12,7 @@ import { isModalOpen, closeModal } from 'boost/modal' const TEXT_FILTER = 'TEXT_FILTER' const FOLDER_FILTER = 'FOLDER_FILTER' +const FOLDER_EXACT_FILTER = 'FOLDER_EXACT_FILTER' const TAG_FILTER = 'TAG_FILTER' class HomePage extends React.Component { @@ -135,6 +136,25 @@ class HomePage extends React.Component { } } +// Ignore invalid key +function ignoreInvalidKey (key) { + return key.length > 0 && !key.match(/^\/\/$/) && !key.match(/^\/$/) && !key.match(/^#$/) +} + +// Build filter object by key +function buildFilter (key) { + if (key.match(/^\/\/.+/)) { + return {type: FOLDER_EXACT_FILTER, value: key.match(/^\/\/(.+)$/)[1]} + } + if (key.match(/^\/.+/)) { + return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} + } + if (key.match(/^#(.+)/)) { + return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} + } + return {type: TEXT_FILTER, value: key} +} + function remap (state) { let { folders, articles, status } = state @@ -145,24 +165,25 @@ function remap (state) { let allArticles = articles.slice() // Filter articles - let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0 && !key.match(/^\/$/) && !key.match(/^#$/)).map(key => { - if (key.match(/^\/.+/)) { - return {type: FOLDER_FILTER, value: key.match(/^\/(.+)$/)[1]} - } - if (key.match(/^#(.+)/)) { - return {type: TAG_FILTER, value: key.match(/^#(.+)$/)[1]} - } - return {type: TEXT_FILTER, value: key} - }) + let filters = status.search.split(' ') + .map(key => key.trim()) + .filter(ignoreInvalidKey) + .map(buildFilter) + + let folderExactFilters = filters.filter(filter => filter.type === FOLDER_EXACT_FILTER) let folderFilters = filters.filter(filter => filter.type === FOLDER_FILTER) let textFilters = filters.filter(filter => filter.type === TEXT_FILTER) let tagFilters = filters.filter(filter => filter.type === TAG_FILTER) + let targetFolders if (folders != null) { - let targetFolders = folders.filter(folder => { + let exactTargetFolders = folders.filter(folder => { + return _.find(folderExactFilters, filter => folder.name.match(new RegExp(`^${filter.value}$`))) + }) + let fuzzyTargetFolders = folders.filter(folder => { return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`))) }) - status.targetFolders = targetFolders + targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders) if (targetFolders.length > 0) { articles = articles.filter(article => { @@ -204,11 +225,10 @@ function remap (state) { // or Change IDLE MODE if (status.mode === CREATE_MODE) { let newArticle = _.findWhere(articles, {status: 'NEW'}) - let FolderKey = folders[0].key - if (folderFilters.length > 0) { - let targetFolder = _.find(folders, folder => folder.name.match(new RegExp(`^${folderFilters[0].value}`))) - if (targetFolder != null) FolderKey = targetFolder.key - } + console.log('targetFolders') + let FolderKey = targetFolders.length > 0 + ? targetFolders[0].key + : folders[0].key if (newArticle == null) { newArticle = { diff --git a/browser/main/HomePage/ArticleTopBar.js b/browser/main/HomePage/ArticleTopBar.js index 285b95de..62880bc7 100644 --- a/browser/main/HomePage/ArticleTopBar.js +++ b/browser/main/HomePage/ArticleTopBar.js @@ -11,6 +11,8 @@ const searchTutorialElement = ( {'- Search by tag : #{string}'} {'- Search by folder : /{folder_name}\n'} + + {'exact match : //{folder_name}'} Date: Mon, 16 Nov 2015 01:22:22 +0900 Subject: [PATCH 10/16] =?UTF-8?q?Preference=E3=81=8B=E3=82=89=E3=82=82?= =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80=E3=83=BC=E3=81=AE=E8=89=B2?= =?UTF-8?q?=E3=81=AE=E9=81=B8=E6=8A=9E=E3=81=8C=E3=81=A7=E3=81=8D=E3=82=8B?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/HomeContainer/lib/Preferences.styl | 66 ++++++++++++++----- lib/components/modal/Preference/FolderRow.js | 55 +++++++++++++++- .../modal/Preference/FolderSettingTab.js | 3 +- lib/reducer.js | 3 +- 4 files changed, 107 insertions(+), 20 deletions(-) diff --git a/browser/styles/main/HomeContainer/lib/Preferences.styl b/browser/styles/main/HomeContainer/lib/Preferences.styl index 79fe0e56..104948d8 100644 --- a/browser/styles/main/HomeContainer/lib/Preferences.styl +++ b/browser/styles/main/HomeContainer/lib/Preferences.styl @@ -440,15 +440,15 @@ iptFocusBorderColor = #369DCD padding 5px 0 &:last-child border-color transparent + .folderColor + float left + margin-left 10px + text-align center + width 44px .folderName float left width 175px overflow ellipsis - padding-left 15px - .folderPublic - float left - text-align center - width 100px .folderControl float right width 145px @@ -512,16 +512,52 @@ iptFocusBorderColor = #369DCD width 150px &:focus border-color iptFocusBorderColor - .folderPublic select - height 33px - border 1px solid borderColor - background-color white - outline none - display block - margin 0 auto - font-size 14px - &:focus - border-color iptFocusBorderColor + .folderColor + .select + height 33px + width 33px + border 1px solid borderColor + background-color white + outline none + display block + margin 0 auto + font-size 14px + border-radius 5px + &:focus + border-color iptFocusBorderColor + .options + position absolute + background-color white + text-align left + border 1px solid borderColor + border-radius 5px + padding 0 5px 5px + margin-left 5px + margin-top -34px + clearfix() + .label + margin-left 5px + line-height 22px + font-size 12px + button + float left + border none + width 33px + height 33px + margin-right 5px + border 1px solid transparent + line-height 29px + overflow hidden + border-radius 5px + background-color transparent + outline none + transition 0.1s + &:hover + border-color borderColor + &.active + .FolderMark + transform scale(1.4) + border-color iptFocusBorderColor .folderControl button border none diff --git a/lib/components/modal/Preference/FolderRow.js b/lib/components/modal/Preference/FolderRow.js index 336a0d6c..d19388d5 100644 --- a/lib/components/modal/Preference/FolderRow.js +++ b/lib/components/modal/Preference/FolderRow.js @@ -26,7 +26,9 @@ export default class FolderRow extends React.Component { handleEditButtonClick (e) { this.setState({ mode: EDIT, - name: this.props.folder.name + name: this.props.folder.name, + color: this.props.folder.color, + isColorEditing: false }) } @@ -34,12 +36,28 @@ export default class FolderRow extends React.Component { this.setState({mode: DELETE}) } + handleColorSelectClick (e) { + this.setState({ + isColorEditing: true + }) + } + + handleColorButtonClick (index) { + return e => { + this.setState({ + color: index, + isColorEditing: false + }) + } + } + handleSaveButtonClick (e) { let { folder, setAlert } = this.props setAlert(null, () => { let input = { - name: this.state.name + name: this.state.name, + color: this.state.color } folder = Object.assign({}, folder, input) @@ -68,8 +86,38 @@ export default class FolderRow extends React.Component { switch (this.state.mode) { case EDIT: + let colorIndexes = [] + for (let i = 0; i < 8; i++) { + colorIndexes.push(i) + } + + let colorOptions = colorIndexes.map(index => { + let className = this.state.color === index + ? 'active' + : null + return ( + + ) + }) + return (
+
+ + {this.state.isColorEditing + ? ( +
+
Color select
+ {colorOptions} +
+ ) + : null + } +
@@ -93,7 +141,8 @@ export default class FolderRow extends React.Component { default: return (
-
{folder.name}
+
+
{folder.name}
diff --git a/lib/components/modal/Preference/FolderSettingTab.js b/lib/components/modal/Preference/FolderSettingTab.js index ff1e8229..b75e368a 100644 --- a/lib/components/modal/Preference/FolderSettingTab.js +++ b/lib/components/modal/Preference/FolderSettingTab.js @@ -59,7 +59,8 @@ export default class FolderSettingTab extends React.Component {
Manage folder
-
Folder name
+
+
Folder
Edit/Delete
{folderElements} diff --git a/lib/reducer.js b/lib/reducer.js index 5b234722..cba759ce 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -47,7 +47,8 @@ function folders (state = initialFolders, action) { if (!_.isString(folder.name)) throw new Error('Folder name must be a string') folder.name = folder.name.trim().replace(/\s/, '_') - if (folder.length === 0) throw new Error('Folder name is required') + if (folder.name.length === 0) throw new Error('Folder name is required') + if (folder.name.match(/\//)) throw new Error('`/` is not available for folder name') // Folder existence check if (targetFolder == null) throw new Error('Folder doesnt exist') From 1fe15bc6a5f5a1b9807a5ed6037ad6f6c7c7566f Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 02:38:36 +0900 Subject: [PATCH 11/16] =?UTF-8?q?Folder=E3=81=AE=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E3=82=92=E5=A4=89=E3=81=88=E3=82=8B=E3=81=93=E3=81=A8=E3=81=8C?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/HomeContainer/lib/Preferences.styl | 31 +++++++++++++++++-- lib/actions.js | 11 +++++++ lib/components/modal/Preference/FolderRow.js | 22 ++++++++++++- .../modal/Preference/FolderSettingTab.js | 13 +++++--- lib/reducer.js | 11 ++++++- 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/browser/styles/main/HomeContainer/lib/Preferences.styl b/browser/styles/main/HomeContainer/lib/Preferences.styl index 104948d8..cb74597a 100644 --- a/browser/styles/main/HomeContainer/lib/Preferences.styl +++ b/browser/styles/main/HomeContainer/lib/Preferences.styl @@ -451,8 +451,11 @@ iptFocusBorderColor = #369DCD overflow ellipsis .folderControl float right - width 145px + width 125px text-align center + &.folderHeader + .folderName + padding-left 25px &.newFolder .alert display block @@ -502,6 +505,30 @@ iptFocusBorderColor = #369DCD &:hover color lighten(brandColor, 10%) &.FolderRow + .sortBtns + float left + display block + height 30px + width 30px + margin-top 1.5px + position absolute + button + absolute left + background-color transparent + border none + height 15px + padding 0 + margin 0 + color stripBtnColor + &:first-child + top 0 + &:last-child + top 15px + &:hover + color stripHoverBtnColor + &:disabled + color lighten(stripBtnColor, 10%) + cursor not-allowed .folderName input height 33px border 1px solid borderColor @@ -555,9 +582,9 @@ iptFocusBorderColor = #369DCD &:hover border-color borderColor &.active + border-color iptFocusBorderColor .FolderMark transform scale(1.4) - border-color iptFocusBorderColor .folderControl button border none diff --git a/lib/actions.js b/lib/actions.js index d99aa2e4..ebbc47ac 100644 --- a/lib/actions.js +++ b/lib/actions.js @@ -4,6 +4,7 @@ export const ARTICLE_DESTROY = 'ARTICLE_DESTROY' export const FOLDER_CREATE = 'FOLDER_CREATE' export const FOLDER_UPDATE = 'FOLDER_UPDATE' export const FOLDER_DESTROY = 'FOLDER_DESTROY' +export const FOLDER_REPLACE = 'FOLDER_REPLACE' export const SWITCH_FOLDER = 'SWITCH_FOLDER' export const SWITCH_MODE = 'SWITCH_MODE' @@ -57,6 +58,16 @@ export function destroyFolder (key) { } } +export function replaceFolder (a, b) { + return { + type: FOLDER_REPLACE, + data: { + a, + b + } + } +} + export function switchFolder (folderName) { return { type: SWITCH_FOLDER, diff --git a/lib/components/modal/Preference/FolderRow.js b/lib/components/modal/Preference/FolderRow.js index d19388d5..8fba0d37 100644 --- a/lib/components/modal/Preference/FolderRow.js +++ b/lib/components/modal/Preference/FolderRow.js @@ -2,7 +2,7 @@ import React, { PropTypes } from 'react' import linkState from 'boost/linkState' import FolderMark from 'boost/components/FolderMark' import store from 'boost/store' -import { updateFolder, destroyFolder } from 'boost/actions' +import { updateFolder, destroyFolder, replaceFolder } from 'boost/actions' const IDLE = 'IDLE' const EDIT = 'EDIT' @@ -17,6 +17,20 @@ export default class FolderRow extends React.Component { } } + handleUpClick (e) { + let { index } = this.props + if (index > 0) { + store.dispatch(replaceFolder(index, index - 1)) + } + } + + handleDownClick (e) { + let { index, count } = this.props + if (index < count - 1) { + store.dispatch(replaceFolder(index, index + 1)) + } + } + handleCancelButtonClick (e) { this.setState({ mode: IDLE @@ -141,6 +155,10 @@ export default class FolderRow extends React.Component { default: return (
+
+ + +
{folder.name}
@@ -155,6 +173,8 @@ export default class FolderRow extends React.Component { FolderRow.propTypes = { folder: PropTypes.shape(), + index: PropTypes.number, + count: PropTypes.number, setAlert: PropTypes.func } diff --git a/lib/components/modal/Preference/FolderSettingTab.js b/lib/components/modal/Preference/FolderSettingTab.js index b75e368a..0072b0ed 100644 --- a/lib/components/modal/Preference/FolderSettingTab.js +++ b/lib/components/modal/Preference/FolderSettingTab.js @@ -40,10 +40,16 @@ export default class FolderSettingTab extends React.Component { render () { let { folders } = this.props - let folderElements = folders.map(folder => { + let folderElements = folders.map((folder, index) => { return ( - this.setAlert(alert, cb)}/> - ) + this.setAlert(alert, cb)} + /> + ) }) let alert = this.state.alert @@ -59,7 +65,6 @@ export default class FolderSettingTab extends React.Component {
Manage folder
-
Folder
Edit/Delete
diff --git a/lib/reducer.js b/lib/reducer.js index cba759ce..5b091872 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -1,6 +1,6 @@ import { combineReducers } from 'redux' import _ from 'lodash' -import { SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, TOGGLE_TUTORIAL, ARTICLE_UPDATE, ARTICLE_DESTROY, FOLDER_CREATE, FOLDER_UPDATE, FOLDER_DESTROY, IDLE_MODE, CREATE_MODE } from './actions' +import { SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, TOGGLE_TUTORIAL, ARTICLE_UPDATE, ARTICLE_DESTROY, FOLDER_CREATE, FOLDER_UPDATE, FOLDER_DESTROY, FOLDER_REPLACE, IDLE_MODE, CREATE_MODE } from './actions' import dataStore from 'boost/dataStore' import keygen from 'boost/keygen' import activityRecord from 'boost/activityRecord' @@ -80,6 +80,15 @@ function folders (state = initialFolders, action) { activityRecord.emit('FOLDER_DESTROY') return state } + case FOLDER_REPLACE: + { + let { a, b } = action.data + let folderA = state[a] + let folderB = state[b] + state.splice(a, 1, folderB) + state.splice(b, 1, folderA) + } + return state default: return state } From 7e04fd342c8f58fc51694ece32c89c064dc706f9 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 02:45:46 +0900 Subject: [PATCH 12/16] =?UTF-8?q?Enter=E3=81=A7Submit=E3=81=8C=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=82=8B=20-=20Hotkey,=20folder=20edit,=20folder=20cr?= =?UTF-8?q?eate(preference/create=20new=20folder=20modal=E4=B8=A1=E6=96=B9?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/components/modal/CreateNewFolder.js | 8 +++++++- lib/components/modal/Preference/AppSettingTab.js | 12 ++++++++++-- lib/components/modal/Preference/FolderRow.js | 8 +++++++- lib/components/modal/Preference/FolderSettingTab.js | 8 +++++++- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/components/modal/CreateNewFolder.js b/lib/components/modal/CreateNewFolder.js index bee88582..2686dafe 100644 --- a/lib/components/modal/CreateNewFolder.js +++ b/lib/components/modal/CreateNewFolder.js @@ -50,6 +50,12 @@ export default class CreateNewFolder extends React.Component { } } + handleKeyDown (e) { + if (e.keyCode === 13) { + this.handleConfirmButton() + } + } + render () { let alert = this.state.alert let alertElement = alert != null ? ( @@ -78,7 +84,7 @@ export default class CreateNewFolder extends React.Component {
Create new folder
- + this.handleKeyDown(e)} className='ipt' type='text' valueLink={this.linkState('name')} placeholder='Enter folder name'/>
{colorElements}
diff --git a/lib/components/modal/Preference/AppSettingTab.js b/lib/components/modal/Preference/AppSettingTab.js index 77bec059..fbf5cadc 100644 --- a/lib/components/modal/Preference/AppSettingTab.js +++ b/lib/components/modal/Preference/AppSettingTab.js @@ -36,12 +36,20 @@ export default class AppSettingTab extends React.Component { ipc.removeListener('APP_SETTING_ERROR', this.handleSettingError) } - handleSaveButtonClick (e) { + submitHotKey () { ipc.send('hotkeyUpdated', { toggleFinder: this.state.toggleFinder }) } + handleSaveButtonClick (e) { + this.submitHotKey() + } + + handleKeyDown (e) { + this.submitHotKey() + } + render () { let alert = this.state.alert let alertElement = alert != null ? ( @@ -56,7 +64,7 @@ export default class AppSettingTab extends React.Component {
Hotkey
- + this.handleKeyDown(e)} valueLink={this.linkState('toggleFinder')} type='text'/>
diff --git a/lib/components/modal/Preference/FolderRow.js b/lib/components/modal/Preference/FolderRow.js index 8fba0d37..44e56b82 100644 --- a/lib/components/modal/Preference/FolderRow.js +++ b/lib/components/modal/Preference/FolderRow.js @@ -50,6 +50,12 @@ export default class FolderRow extends React.Component { this.setState({mode: DELETE}) } + handleNameInputKeyDown (e) { + if (e.keyCode === 13) { + this.handleSaveButtonClick() + } + } + handleColorSelectClick (e) { this.setState({ isColorEditing: true @@ -133,7 +139,7 @@ export default class FolderRow extends React.Component { }
- + this.handleNameInputKeyDown(e)} valueLink={this.linkState('name')} type='text'/>
diff --git a/lib/components/modal/Preference/FolderSettingTab.js b/lib/components/modal/Preference/FolderSettingTab.js index 0072b0ed..09a8ba7d 100644 --- a/lib/components/modal/Preference/FolderSettingTab.js +++ b/lib/components/modal/Preference/FolderSettingTab.js @@ -12,6 +12,12 @@ export default class FolderSettingTab extends React.Component { } } + handleNewFolderNameKeyDown (e) { + if (e.keyCode === 13) { + this.handleSaveButtonClick() + } + } + handleSaveButtonClick (e) { this.setState({alert: null}, () => { if (this.state.name.trim().length === 0) return false @@ -71,7 +77,7 @@ export default class FolderSettingTab extends React.Component { {folderElements}
- + this.handleNewFolderNameKeyDown(e)} valueLink={this.linkState('name')} type='text' placeholder='New Folder'/>
From 409eaf54c1a08499a475ca3ca0e9b61e2e3fbf69 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 04:06:14 +0900 Subject: [PATCH 13/16] Tag suggest --- browser/main/HomePage.js | 9 +- browser/main/HomePage/ArticleDetail.js | 3 +- .../components/ArticleDetail.styl | 91 +++++++------ lib/components/ModeSelect.js | 4 +- lib/components/TagSelect.js | 120 +++++++++++++++--- 5 files changed, 170 insertions(+), 57 deletions(-) diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index beb312ee..c40b4dfb 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -99,7 +99,7 @@ class HomePage extends React.Component { } render () { - let { dispatch, status, articles, allArticles, activeArticle, folders, filters } = this.props + let { dispatch, status, articles, allArticles, activeArticle, folders, tags, filters } = this.props return (
@@ -129,6 +129,7 @@ class HomePage extends React.Component { activeArticle={activeArticle} folders={folders} status={status} + tags={tags} filters={filters} />
@@ -164,6 +165,11 @@ function remap (state) { }) let allArticles = articles.slice() + let tags = _.uniq(allArticles.reduce((sum, article) => { + if (!_.isArray(article.tags)) return sum + return sum.concat(article.tags) + }, [])) + // Filter articles let filters = status.search.split(' ') .map(key => key.trim()) @@ -254,6 +260,7 @@ function remap (state) { allArticles, articles, activeArticle, + tags, filters: { folder: folderFilters, tag: tagFilters, diff --git a/browser/main/HomePage/ArticleDetail.js b/browser/main/HomePage/ArticleDetail.js index 10c702c5..6ae52e7d 100644 --- a/browser/main/HomePage/ArticleDetail.js +++ b/browser/main/HomePage/ArticleDetail.js @@ -303,7 +303,7 @@ export default class ArticleDetail extends React.Component { } renderEdit () { - let { folders, status } = this.props + let { folders, status, tags } = this.props let folderOptions = folders.map(folder => { return ( @@ -326,6 +326,7 @@ export default class ArticleDetail extends React.Component { this.handleTagsChange(tags, tag)} + suggestTags={tags} /> {status.isTutorialOpen ? tagSelectTutorialElement : null} diff --git a/browser/styles/main/HomeContainer/components/ArticleDetail.styl b/browser/styles/main/HomeContainer/components/ArticleDetail.styl index 0a3182f4..2f4ae10c 100644 --- a/browser/styles/main/HomeContainer/components/ArticleDetail.styl +++ b/browser/styles/main/HomeContainer/components/ArticleDetail.styl @@ -98,44 +98,66 @@ iptFocusBorderColor = #369DCD &:hover background-color white .TagSelect - white-space nowrap - overflow-x auto - position relative - margin-top 5px - noSelect() - z-index 30 - background-color #E6E6E6 - .tagItem - background-color brandColor - border-radius 2px - color white - margin 0 2px - padding 0 - border 1px solid darken(brandColor, 10%) - button.tagRemoveBtn + .tags + white-space nowrap + overflow-x auto + position relative + max-width 350px + margin-top 5px + noSelect() + z-index 30 + background-color #E6E6E6 + .tagItem + background-color brandColor + border-radius 2px color white + margin 0 2px + padding 0 + border 1px solid darken(brandColor, 10%) + button.tagRemoveBtn + color white + border-radius 2px + border none + background-color transparent + padding 4px 2px + border-right 1px solid #E6E6E6 + font-size 8px + line-height 12px + transition 0.1s + &:hover + background-color lighten(brandColor, 10%) + .tagLabel + padding 4px 4px + font-size 12px + line-height 12px + input.tagInput + background-color transparent + outline none + margin 0 2px border-radius 2px border none - background-color transparent - padding 4px 2px - border-right 1px solid #E6E6E6 - font-size 8px - line-height 12px transition 0.1s + height 18px + .suggestTags + position fixed + width 150px + max-height 150px + background-color white + z-index 5 + border 1px solid borderColor + border-radius 5px + button + width 100% + display block + padding 0 15px + height 33px + line-height 33px + background-color transparent + border none + text-align left + font-size 14px &:hover - background-color lighten(brandColor, 10%) - .tagLabel - padding 4px 4px - font-size 12px - line-height 12px - input.tagInput - background-color transparent - outline none - margin 0 2px - border-radius 2px - border none - transition 0.1s - height 18px + background-color darken(white, 10%) .right button cursor pointer @@ -222,9 +244,6 @@ iptFocusBorderColor = #369DCD display inline-block &:hover background-color darken(white, 10%) - - - .title absolute left top bottom right 150px diff --git a/lib/components/ModeSelect.js b/lib/components/ModeSelect.js index 554e361c..28404d20 100644 --- a/lib/components/ModeSelect.js +++ b/lib/components/ModeSelect.js @@ -18,7 +18,7 @@ export default class ModeSelect extends React.Component { } } - componentDidMount (e) { + componentDidMount () { this.blurHandler = e => { let searchElement = ReactDOM.findDOMNode(this.refs.search) if (this.state.mode === EDIT_MODE && document.activeElement !== searchElement) { @@ -28,7 +28,7 @@ export default class ModeSelect extends React.Component { window.addEventListener('click', this.blurHandler) } - componentWillUnmount (e) { + componentWillUnmount () { window.removeEventListener('click', this.blurHandler) let searchElement = ReactDOM.findDOMNode(this.refs.search) if (searchElement != null && this.searchKeyDownListener != null) { diff --git a/lib/components/TagSelect.js b/lib/components/TagSelect.js index b7fbead8..f000d32d 100644 --- a/lib/components/TagSelect.js +++ b/lib/components/TagSelect.js @@ -3,23 +3,54 @@ import ReactDOM from 'react-dom' import _ from 'lodash' import linkState from 'boost/linkState' +function isNotEmptyString (str) { + return _.isString(str) && str.length > 0 +} + export default class TagSelect extends React.Component { constructor (props) { super(props) this.state = { - input: '' + input: '', + isInputFocused: false } } - handleKeyDown (e) { - if (e.keyCode !== 13) return false - e.preventDefault() + componentDidMount () { + this.blurInputBlurHandler = e => { + if (ReactDOM.findDOMNode(this.refs.tagInput) !== document.activeElement) { + this.setState({isInputFocused: false}) + } + } + window.addEventListener('click', this.blurInputBlurHandler) + } + componentWillUnmount (e) { + window.removeEventListener('click', this.blurInputBlurHandler) + } + + // Suggestは必ずInputの下に位置するようにする + componentDidUpdate () { + if (this.shouldShowSuggest()) { + let inputRect = ReactDOM.findDOMNode(this.refs.tagInput).getBoundingClientRect() + let suggestElement = ReactDOM.findDOMNode(this.refs.suggestTags) + if (suggestElement != null) { + suggestElement.style.top = inputRect.top + 20 + 'px' + suggestElement.style.left = inputRect.left + 'px' + } + } + } + + shouldShowSuggest () { + return this.state.isInputFocused && isNotEmptyString(this.state.input) + } + + addTag (tag, clearInput = true) { let tags = this.props.tags.slice(0) - let newTag = this.state.input.trim() + let newTag = tag.trim() - if (newTag.length === 0) { + if (newTag.length === 0 && clearInput) { this.setState({input: ''}) return } @@ -30,13 +61,38 @@ export default class TagSelect extends React.Component { if (_.isFunction(this.props.onChange)) { this.props.onChange(newTag, tags) } - this.setState({input: ''}) + if (clearInput) this.setState({input: ''}) + } + + handleKeyDown (e) { + switch (e.keyCode) { + case 8: + { + if (this.state.input.length > 0) break + e.preventDefault() + + let tags = this.props.tags.slice(0) + tags.pop() + + this.props.onChange(null, tags) + } + break + case 13: + { + e.preventDefault() + this.addTag(this.state.input) + } + } } handleThisClick (e) { ReactDOM.findDOMNode(this.refs.tagInput).focus() } + handleInputFocus (e) { + this.setState({isInputFocused: true}) + } + handleItemRemoveButton (tag) { return e => { e.stopPropagation() @@ -50,8 +106,16 @@ export default class TagSelect extends React.Component { } } + handleSuggestClick (tag) { + return e => { + this.addTag(tag) + } + } + render () { - var tagElements = _.isArray(this.props.tags) + let { tags, suggestTags } = this.props + + let tagElements = _.isArray(tags) ? this.props.tags.map(tag => ( @@ -59,16 +123,37 @@ export default class TagSelect extends React.Component { )) : null + let suggestElements = this.shouldShowSuggest() ? suggestTags + .filter(tag => { + return tag.match(this.state.input) + }) + .map(tag => { + return + }) + : null + return (
this.handleThisClick(e)}> - {tagElements} - this.handleKeyDown(e)} - ref='tagInput' - valueLink={this.linkState('input')} - placeholder='Click here to add tags' - className='tagInput'/> +
+ {tagElements} + this.handleKeyDown(e)} + ref='tagInput' + valueLink={this.linkState('input')} + placeholder='Click here to add tags' + className='tagInput' + onFocus={e => this.handleInputFocus(e)} + /> +
+ {suggestElements != null && suggestElements.length > 0 + ? ( +
+ {suggestElements} +
+ ) + : null + }
) } @@ -76,7 +161,8 @@ export default class TagSelect extends React.Component { TagSelect.propTypes = { tags: PropTypes.arrayOf(PropTypes.string), - onChange: PropTypes.func + onChange: PropTypes.func, + suggestTags: PropTypes.array } TagSelect.prototype.linkState = linkState From df6a018fb69f596734d4a935445806c0dbd1c70d Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 04:17:56 +0900 Subject: [PATCH 14/16] =?UTF-8?q?update=E3=81=8C=E6=BA=96=E5=82=99?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=9F=E3=82=89=E3=80=81=E5=86=8D=E8=B5=B7?= =?UTF-8?q?=E5=8B=95=E3=81=95=E3=82=8C=E3=82=8B=E3=81=BE=E3=81=A7=E6=94=B9?= =?UTF-8?q?=E3=82=81=E3=81=A6Update=E3=81=AE=E7=A2=BA=E8=AA=8D=E3=82=92?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index 1d63eb1c..e0b65c68 100644 --- a/main.js +++ b/main.js @@ -51,11 +51,11 @@ app.on('ready', function () { var template = require('./atom-lib/menu-template') setInterval(function () { - updater.checkForUpdates() + if (update == null) updater.checkForUpdates() }, 1000 * 60 * 60 * 24) ipc.on('check-update', function (event, msg) { - updater.checkForUpdates() + if (update == null) updater.checkForUpdates() }) ipc.on('update-app', function (event, msg) { From 013f96a754d3c0d80d69fede24ef7c29c37c40ee Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 05:34:37 +0900 Subject: [PATCH 15/16] =?UTF-8?q?=E8=A8=98=E4=BA=8B=E3=81=8C=E7=B7=A8?= =?UTF-8?q?=E9=9B=86=E3=81=95=E3=82=8C=E3=81=9F=E7=8A=B6=E6=85=8B=E3=81=A7?= =?UTF-8?q?=E4=BB=96=E3=81=AE=E8=A8=98=E4=BA=8B=E3=82=92=E8=A6=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=A8=E3=81=99=E3=82=8B=E3=81=A8=E8=AD=A6=E5=91=8A?= =?UTF-8?q?=E3=82=92=E3=81=A0=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/main/HomePage/ArticleDetail.js | 134 ++++++++++++++++-- browser/styles/main/HomeContainer/index.styl | 1 + .../main/HomeContainer/lib/EditedAlert.styl | 28 ++++ lib/actions.js | 16 ++- lib/components/modal/EditedAlert.js | 35 +++++ lib/reducer.js | 47 +++++- 6 files changed, 248 insertions(+), 13 deletions(-) create mode 100644 browser/styles/main/HomeContainer/lib/EditedAlert.styl create mode 100644 lib/components/modal/EditedAlert.js diff --git a/browser/main/HomePage/ArticleDetail.js b/browser/main/HomePage/ArticleDetail.js index 6ae52e7d..12fbe9a2 100644 --- a/browser/main/HomePage/ArticleDetail.js +++ b/browser/main/HomePage/ArticleDetail.js @@ -5,7 +5,20 @@ import _ from 'lodash' import ModeIcon from 'boost/components/ModeIcon' import MarkdownPreview from 'boost/components/MarkdownPreview' import CodeEditor from 'boost/components/CodeEditor' -import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode, switchArticle, switchFolder, clearSearch, updateArticle, destroyArticle, NEW } from 'boost/actions' +import { + IDLE_MODE, + CREATE_MODE, + EDIT_MODE, + switchMode, + switchArticle, + switchFolder, + clearSearch, + lockStatus, + unlockStatus, + updateArticle, + destroyArticle, + NEW +} from 'boost/actions' import linkState from 'boost/linkState' import FolderMark from 'boost/components/FolderMark' import TagLink from 'boost/components/TagLink' @@ -82,7 +95,12 @@ export default class ArticleDetail extends React.Component { this.state = { article: makeInstantArticle(props.activeArticle), - previewMode: false + previewMode: false, + isArticleEdited: false, + isTagChanged: false, + isTitleChanged: false, + isContentChanged: false, + isModeChanged: false } } @@ -117,7 +135,11 @@ export default class ArticleDetail extends React.Component { if (isModeChanged) { Object.assign(nextState, { openDeleteConfirmMenu: false, - previewMode: false + previewMode: false, + isArticleEdited: false, + isTagChanged: false, + isTitleChanged: false, + isContentChanged: false }) } @@ -224,6 +246,8 @@ export default class ArticleDetail extends React.Component { handleCancelButtonClick (e) { let { activeArticle, dispatch } = this.props + + dispatch(unlockStatus()) if (activeArticle.status === NEW) dispatch(switchArticle(null)) dispatch(switchMode(IDLE_MODE)) } @@ -236,6 +260,8 @@ export default class ArticleDetail extends React.Component { let folder = _.findWhere(folders, {key: article.FolderKey}) if (folder == null) return false + dispatch(unlockStatus()) + delete newArticle.status newArticle.updatedAt = new Date() if (newArticle.createdAt == null) { @@ -263,19 +289,85 @@ export default class ArticleDetail extends React.Component { this.setState({article: article}) } + handleTitleChange (e) { + let { article } = this.state + article.title = e.target.value + let _isTitleChanged = article.title !== this.props.activeArticle.title + + let { isTagChanged, isContentChanged, isArticleEdited, isModeChanged } = this.state + let _isArticleEdited = _isTitleChanged || isTagChanged || isContentChanged || isModeChanged + + this.setState({ + article, + isTitleChanged: _isTitleChanged, + isArticleEdited: _isArticleEdited + }, () => { + if (isArticleEdited !== _isArticleEdited) { + let { dispatch } = this.props + if (_isArticleEdited) { + console.log('lockit') + dispatch(lockStatus()) + } else { + console.log('unlockit') + dispatch(unlockStatus()) + } + } + }) + } + handleTagsChange (newTag, tags) { let article = this.state.article article.tags = tags this.setState({article: article}) + + let _isTagChanged = _.difference(article.tags, this.props.activeArticle.tags).length > 0 || _.difference(this.props.activeArticle.tags, article.tags).length > 0 + + let { isTitleChanged, isContentChanged, isArticleEdited, isModeChanged } = this.state + let _isArticleEdited = _isTagChanged || isTitleChanged || isContentChanged || isModeChanged + + this.setState({ + article, + isTagChanged: _isTagChanged, + isArticleEdited: _isArticleEdited + }, () => { + if (isArticleEdited !== _isArticleEdited) { + let { dispatch } = this.props + if (_isArticleEdited) { + console.log('lockit') + dispatch(lockStatus()) + } else { + console.log('unlockit') + dispatch(unlockStatus()) + } + } + }) } handleModeChange (value) { - let article = this.state.article + let { article } = this.state article.mode = value + let _isModeChanged = article.mode !== this.props.activeArticle.mode + + let { isTagChanged, isContentChanged, isArticleEdited, isTitleChanged } = this.state + let _isArticleEdited = _isModeChanged || isTagChanged || isContentChanged || isTitleChanged + this.setState({ - article: article, - previewMode: false + article, + previewMode: false, + isModeChanged: _isModeChanged, + isArticleEdited: _isArticleEdited + }, () => { + if (isArticleEdited !== _isArticleEdited) { + let { dispatch } = this.props + if (_isArticleEdited) { + console.log('lockit') + dispatch(lockStatus()) + } else { + console.log('unlockit') + dispatch(unlockStatus()) + } + } }) } @@ -286,9 +378,29 @@ export default class ArticleDetail extends React.Component { } handleContentChange (e, value) { - let article = this.state.article + let { article } = this.state article.content = value - this.setState({article: article}) + let _isContentChanged = article.content !== this.props.activeArticle.content + + let { isTagChanged, isModeChanged, isArticleEdited, isTitleChanged } = this.state + let _isArticleEdited = _isContentChanged || isTagChanged || isModeChanged || isTitleChanged + + this.setState({ + article, + isContentChanged: _isContentChanged, + isArticleEdited: _isArticleEdited + }, () => { + if (isArticleEdited !== _isArticleEdited) { + let { dispatch } = this.props + if (_isArticleEdited) { + console.log('lockit') + dispatch(lockStatus()) + } else { + console.log('unlockit') + dispatch(unlockStatus()) + } + } + }) } handleTogglePreviewButtonClick (e) { @@ -322,6 +434,7 @@ export default class ArticleDetail extends React.Component { > {folderOptions} + {this.state.isArticleEdited ? ' (edited)' : ''}
- this.handleTitleKeyDown(e)} placeholder='Title' ref='title' valueLink={this.linkState('article.title')}/> + this.handleTitleKeyDown(e)} placeholder='Title' ref='title' value={this.state.article.title} onChange={e => this.handleTitleChange(e)}/>
+
Your article is still editing!
+ +
Do you really want to leave without finishing?
+ +
+ + +
+
+ ) + } +} + +EditedAlert.propTypes = { + action: PropTypes.object, + close: PropTypes.func +} diff --git a/lib/reducer.js b/lib/reducer.js index 5b091872..baff2d55 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -1,14 +1,42 @@ import { combineReducers } from 'redux' import _ from 'lodash' -import { SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, TOGGLE_TUTORIAL, ARTICLE_UPDATE, ARTICLE_DESTROY, FOLDER_CREATE, FOLDER_UPDATE, FOLDER_DESTROY, FOLDER_REPLACE, IDLE_MODE, CREATE_MODE } from './actions' +import { + // Status action type + SWITCH_FOLDER, + SWITCH_MODE, + SWITCH_ARTICLE, + SET_SEARCH_FILTER, + SET_TAG_FILTER, + CLEAR_SEARCH, + LOCK_STATUS, + UNLOCK_STATUS, + TOGGLE_TUTORIAL, + + // Article action type + ARTICLE_UPDATE, + ARTICLE_DESTROY, + + // Folder action type + FOLDER_CREATE, + FOLDER_UPDATE, + FOLDER_DESTROY, + FOLDER_REPLACE, + + // view mode + IDLE_MODE, + CREATE_MODE +} from './actions' import dataStore from 'boost/dataStore' import keygen from 'boost/keygen' import activityRecord from 'boost/activityRecord' +import { openModal } from 'boost/modal' +import EditedAlert from 'boost/components/modal/EditedAlert' const initialStatus = { mode: IDLE_MODE, search: '', - isTutorialOpen: false + isTutorialOpen: false, + isStatusLocked: false } let data = dataStore.getData() @@ -134,10 +162,25 @@ function articles (state = initialArticles, action) { function status (state = initialStatus, action) { state = Object.assign({}, state) + switch (action.type) { case TOGGLE_TUTORIAL: state.isTutorialOpen = !state.isTutorialOpen return state + case LOCK_STATUS: + state.isStatusLocked = true + return state + case UNLOCK_STATUS: + state.isStatusLocked = false + return state + } + + // if status locked, status become unmutable + if (state.isStatusLocked) { + openModal(EditedAlert, {action}) + return state + } + switch (action.type) { case SWITCH_FOLDER: state.mode = IDLE_MODE state.search = `//${action.data} ` From 51f530ffbe8b917e22d82317e3fbcbb6fdac2c4b Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 16 Nov 2015 05:36:37 +0900 Subject: [PATCH 16/16] bump up version 0.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ef93709..95f50f69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "boost", - "version": "0.4.0-beta.2", + "version": "0.4.1-beta", "description": "Boost App", "main": "main.js", "scripts": {