From e4d843880185e9b418103e7b721397bc690e004e Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Mon, 28 Dec 2015 16:11:42 +0900 Subject: [PATCH] save ALL --- browser/main/HomePage/ArticleTopBar.js | 67 ++++++++++++++++--- browser/main/HomePage/index.js | 8 +-- browser/main/actions.js | 19 +++--- browser/main/reducer.js | 21 ++++-- .../components/ArticleTopBar.styl | 44 ++++++++++-- 5 files changed, 125 insertions(+), 34 deletions(-) diff --git a/browser/main/HomePage/ArticleTopBar.js b/browser/main/HomePage/ArticleTopBar.js index c84c401d..cbca3079 100644 --- a/browser/main/HomePage/ArticleTopBar.js +++ b/browser/main/HomePage/ArticleTopBar.js @@ -1,7 +1,35 @@ import React, { PropTypes } from 'react' import ReactDOM from 'react-dom' import ExternalLink from 'browser/components/ExternalLink' -import { setSearchFilter, clearSearch, toggleOnlyUnsavedFilter, toggleTutorial } from '../actions' +import { setSearchFilter, clearSearch, toggleOnlyUnsavedFilter, toggleTutorial, saveAllArticles, switchArticle } from '../actions' +import store from '../store' + +const electron = require('electron') +const remote = electron.remote +const Menu = remote.Menu +const MenuItem = remote.MenuItem + +var menu = new Menu() +var lastIndex = -1 +menu.append(new MenuItem({ + label: 'Show only unsaved', + click: function () { + store.dispatch(setSearchFilter('--unsaved')) + } +})) +menu.append(new MenuItem({ + label: 'Go to an unsaved article', + click: function () { + lastIndex++ + let state = store.getState() + let modified = state.articles.modified + if (modified.length === 0) return + if (modified.length <= lastIndex) { + lastIndex = 0 + } + store.dispatch(switchArticle(modified[lastIndex].key)) + } +})) const BRAND_COLOR = '#18AF90' @@ -111,19 +139,28 @@ export default class ArticleTopBar extends React.Component { dispatch(toggleOnlyUnsavedFilter()) } + handleSaveAllButtonClick (e) { + let { dispatch } = this.props + + dispatch(saveAllArticles()) + } + + handleSaveMenuButtonClick (e) { + menu.popup(590, 45) + } + handleTutorialButtonClick (e) { let { dispatch } = this.props - console.log(e.target.value) dispatch(toggleTutorial()) } render () { - let { status } = this.props + let { status, modified } = this.props return (
-
-
+
+
  • - Search by tag : #{'{string}'}
  • -
  • - Search by folder : /{'{folder_name}'}
  • -
  • exact match : //{'{folder_name}'}
  • +
  • - Search by folder : /{'{folder_name}'}
    exact match : //{'{folder_name}'}
  • +
  • - Only unsaved : --unsaved
{status.isTutorialOpen ? searchTutorialElement : null} - + +
+ + +
-
+ +
@@ -198,5 +244,6 @@ ArticleTopBar.propTypes = { dispatch: PropTypes.func, status: PropTypes.shape({ search: PropTypes.string - }) + }), + modified: PropTypes.array } diff --git a/browser/main/HomePage/index.js b/browser/main/HomePage/index.js index 6486bdc3..f747c5ca 100644 --- a/browser/main/HomePage/index.js +++ b/browser/main/HomePage/index.js @@ -84,6 +84,7 @@ class HomePage extends React.Component { ref='top' dispatch={dispatch} status={status} + modified={modified} /> 0 && !key.match(/^\/\/$/) && !key.match(/^\/$/) && !key.match(/^#$/) + return key.length > 0 && !key.match(/^\/\/$/) && !key.match(/^\/$/) && !key.match(/^#$/) && !key.match(/^--/) } // Build filter object by key @@ -144,10 +145,6 @@ function remap (state) { let articles = _articles != null ? _articles.data : [] let modified = _articles != null ? _articles.modified : [] - if (state.status.onlyUnsaved) { - articles = modified.map(modifiedArticle => _.findWhere(articles, {key: modifiedArticle.key})) - } - articles.sort((a, b) => { return new Date(b.updatedAt) - new Date(a.updatedAt) }) @@ -158,6 +155,7 @@ function remap (state) { return sum.concat(article.tags) }, [])) + if (status.search.split(' ').some(key => key === '--unsaved')) articles = articles.filter(article => _.findWhere(modified, {key: article.key})) // Filter articles let filters = status.search.split(' ') .map(key => key.trim()) diff --git a/browser/main/actions.js b/browser/main/actions.js index 99dc2a95..0f816416 100644 --- a/browser/main/actions.js +++ b/browser/main/actions.js @@ -5,6 +5,7 @@ export const CLEAR_NEW_ARTICLE = 'CLEAR_NEW_ARTICLE' export const ARTICLE_UPDATE = 'ARTICLE_UPDATE' export const ARTICLE_DESTROY = 'ARTICLE_DESTROY' export const ARTICLE_SAVE = 'ARTICLE_SAVE' +export const ARTICLE_SAVE_ALL = 'ARTICLE_SAVE_ALL' export const ARTICLE_CACHE = 'ARTICLE_CACHE' export const FOLDER_CREATE = 'FOLDER_CREATE' export const FOLDER_UPDATE = 'FOLDER_UPDATE' @@ -16,7 +17,6 @@ export const SWITCH_ARTICLE = 'SWITCH_ARTICLE' export const SET_SEARCH_FILTER = 'SET_SEARCH_FILTER' export const SET_TAG_FILTER = 'SET_TAG_FILTER' export const CLEAR_SEARCH = 'CLEAR_SEARCH' -export const TOGGLE_ONLY_UNSAVED_FILTER = 'TOGGLE_ONLY_UNSAVED_FILTER' export const TOGGLE_TUTORIAL = 'TOGGLE_TUTORIAL' @@ -51,6 +51,12 @@ export function saveArticle (key, article, forceSwitch) { } } +export function saveAllArticles () { + return { + type: ARTICLE_SAVE_ALL + } +} + export function updateArticle (article) { return { type: ARTICLE_UPDATE, @@ -132,12 +138,6 @@ export function clearSearch () { } } -export function toggleOnlyUnsavedFilter () { - return { - type: TOGGLE_ONLY_UNSAVED_FILTER - } -} - export function toggleTutorial () { return { type: TOGGLE_TUTORIAL @@ -146,20 +146,23 @@ export function toggleTutorial () { export default { updateUser, + clearNewArticle, updateArticle, destroyArticle, cacheArticle, saveArticle, + saveAllArticles, + createFolder, updateFolder, destroyFolder, replaceFolder, + switchFolder, switchArticle, setSearchFilter, setTagFilter, clearSearch, - toggleOnlyUnsavedFilter, toggleTutorial } diff --git a/browser/main/reducer.js b/browser/main/reducer.js index a6827344..c00d8f52 100644 --- a/browser/main/reducer.js +++ b/browser/main/reducer.js @@ -7,7 +7,6 @@ import { SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, - TOGGLE_ONLY_UNSAVED_FILTER, TOGGLE_TUTORIAL, // user @@ -18,6 +17,7 @@ import { ARTICLE_DESTROY, ARTICLE_CACHE, ARTICLE_SAVE, + ARTICLE_SAVE_ALL, // Folder action type FOLDER_CREATE, @@ -31,8 +31,7 @@ import activityRecord from 'browser/lib/activityRecord' const initialStatus = { search: '', - isTutorialOpen: false, - onlyUnsaved: false + isTutorialOpen: false } let data = dataStore.getData() @@ -195,6 +194,18 @@ function articles (state = initialArticles, action) { dataStore.setArticles(state.data) return state } + case ARTICLE_SAVE_ALL: + if (state.modified.length > 0) { + state.modified.forEach(modifiedArticle => { + let targetIndex = _.findIndex(state.data, _article => modifiedArticle.key === _article.key) + Object.assign(state.data[targetIndex], modifiedArticle, {key: modifiedArticle.key, updatedAt: new Date()}) + }) + } + + state.modified = [] + dataStore.setArticles(state.data) + + return state case ARTICLE_UPDATE: { let article = action.data.article @@ -265,10 +276,6 @@ function status (state = initialStatus, action) { case CLEAR_SEARCH: state.search = '' - return state - case TOGGLE_ONLY_UNSAVED_FILTER: - state.onlyUnsaved = !state.onlyUnsaved - return state default: return state diff --git a/browser/styles/main/HomeContainer/components/ArticleTopBar.styl b/browser/styles/main/HomeContainer/components/ArticleTopBar.styl index 81946814..42d46c00 100644 --- a/browser/styles/main/HomeContainer/components/ArticleTopBar.styl +++ b/browser/styles/main/HomeContainer/components/ArticleTopBar.styl @@ -36,14 +36,14 @@ infoBtnActiveBgColor = #3A3A3A fixed top left bottom right z-index 20 background-color transparentify(black, 80%) - &>.left + &>.ArticleTopBar-left float left &>.tutorial fixed top left 200px z-index 36 font-style italic - &>.search + &>.ArticleTopBar-left-search position relative float left height 33px @@ -63,11 +63,15 @@ infoBtnActiveBgColor = #3A3A3A &.hide opacity 0 ul + li + line-height 18px li:last-child line-height 10px margin-bottom 3px small font-size 10px + position relative + top -2px margin-left 15px input absolute top left @@ -122,13 +126,45 @@ infoBtnActiveBgColor = #3A3A3A transition 0.1s &:hover color refreshBtnActiveColor - .only-unsaved + .ArticleTopBar-left-unsaved line-height 33px float left height 33px margin-top 13.5px margin-left 10px - &>.right + button + background transparent + font-size 20px + border none + outline none + color inactiveTextColor + &:hover + color inherit + &.ArticleTopBar-left-unsaved-save-button + position relative + .ArticleTopBar-left-unsaved-save-button-count + position absolute + font-size 10px + background-color brandColor + color white + height 14px + width 14px + line-height 14px + border-radius 7px + top 16px + right -3px + transition 0.15s + &.hide + transform scale(0) + .ArticleTopBar-left-unsaved-save-button-tooltip + tooltip() + margin-top 30px + margin-left -100px + &:hover + .ArticleTopBar-left-unsaved-save-button-tooltip + opacity 1 + + &>.ArticleTopBar-right float right &>button display block