From f75f60aa1e4f53d974b053d7e90cbd8224f066d1 Mon Sep 17 00:00:00 2001 From: Scott Tolksdorf Date: Tue, 27 Dec 2016 17:24:27 -0500 Subject: [PATCH] Edit page finally converted over --- .../homebrew/navbar/continousSave.navitem.jsx | 93 +++++--- client/homebrew/navbar/navbar.less | 51 +++-- client/homebrew/pages/editPage/editPage.jsx | 206 +++--------------- client/homebrew/pages/editPage/editPage.less | 25 +-- shared/homebrewery/brew.actions.js | 16 +- shared/homebrewery/brew.store.js | 4 +- 6 files changed, 126 insertions(+), 269 deletions(-) diff --git a/client/homebrew/navbar/continousSave.navitem.jsx b/client/homebrew/navbar/continousSave.navitem.jsx index fe7e695..cd485b1 100644 --- a/client/homebrew/navbar/continousSave.navitem.jsx +++ b/client/homebrew/navbar/continousSave.navitem.jsx @@ -1,51 +1,76 @@ -var React = require('react'); -var _ = require('lodash'); -var cx = require('classnames'); +const flux = require('pico-flux') +const React = require('react'); +const _ = require('lodash'); +const cx = require('classnames'); -//var striptags = require('striptags'); +const Nav = require('naturalcrit/nav/nav.jsx'); -var Nav = require('naturalcrit/nav/nav.jsx'); +const Store = require('homebrewery/brew.store.js'); +const Actions = require('homebrewery/brew.actions.js'); -const MAX_URL_SIZE = 2083; -const MAIN_URL = "https://www.reddit.com/r/UnearthedArcana/submit?selftext=true" +const onStoreChange = () => { + return { + status : Store.getStatus(), + errors : Store.getErrors() + } +}; - -var RedditShare = React.createClass({ +const ContinousSave = React.createClass({ getDefaultProps: function() { return { - brew : { - title : '', - sharedId : '', - text : '' - } + status : 'ready', + errors : undefined }; }, - - getText : function(){ - + componentDidMount: function() { + flux.actionEmitter.on('dispatch', this.brewUpdate); + window.onbeforeunload = ()=>{ + if(this.props.status !== 'ready') return 'You have unsaved changes!'; + }; + }, + componentWillUnmount: function() { + flux.actionEmitter.removeListenr('dispatch', this.brewUpdate); + window.onbeforeunload = function(){}; + }, + brewUpdate : function(actionType){ + if(actionType == 'UPDATE_BREW_TEXT' || actionType == 'UPDATE_META'){ + Actions.pendingSave(); + } }, - - handleClick : function(){ - var url = [ - MAIN_URL, - 'title=' + encodeURIComponent(this.props.brew.title ? this.props.brew.title : 'Check out my brew!'), - - 'text=' + encodeURIComponent(this.props.brew.text) - - - ].join('&'); - - window.open(url, '_blank'); + Actions.save(); }, + renderError : function(){ + let errMsg = ''; + try{ + errMsg += this.state.errors.toString() + '\n\n'; + errMsg += '```\n' + JSON.stringify(this.state.errors.response.error, null, ' ') + '\n```'; + }catch(e){} - - render : function(){ - return - share on reddit + return + Oops! +
+ Looks like there was a problem saving.
+ Report the issue + here + . +
}, + render : function(){ + if(this.props.status == 'error') return this.renderError(); + + if(this.props.status == 'saving'){ + return saving... + } + if(this.props.status == 'pending'){ + return Save Now + } + if(this.props.status == 'ready'){ + return saved. + } + }, }); -module.exports = RedditShare; \ No newline at end of file +module.exports = Store.createSmartComponent(ContinousSave, onStoreChange); \ No newline at end of file diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less index 2370537..81a7782 100644 --- a/client/homebrew/navbar/navbar.less +++ b/client/homebrew/navbar/navbar.less @@ -13,32 +13,6 @@ color : @blue; } } - .editTitle.navItem{ - padding : 2px 12px; - input{ - width : 250px; - margin : 0; - padding : 2px; - background-color : #444; - font-family : 'Open Sans', sans-serif; - font-size : 12px; - font-weight : 800; - color : white; - text-align : center; - border : 1px solid @blue; - outline : none; - } - .charCount{ - display : inline-block; - vertical-align : bottom; - margin-left : 8px; - color : #666; - text-align : right; - &.max{ - color : @red; - } - } - } .brewTitle.navItem{ font-size : 12px; font-weight : 800; @@ -132,4 +106,29 @@ background-color: @green; } } + + .continousSave.navItem{ + width : 105px; + text-align : center; + &.saved{ + cursor : initial; + color : #666; + } + &.error{ + position : relative; + background-color : @red; + .errorContainer{ + position : absolute; + top : 29px; + left : -20px; + z-index : 1000; + width : 120px; + padding : 8px; + background-color : #333; + a{ + color : @teal; + } + } + } + } } \ No newline at end of file diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 9e94407..3d5666e 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -1,8 +1,6 @@ const React = require('react'); const _ = require('lodash'); const cx = require('classnames'); -const request = require("superagent"); - const Nav = require('naturalcrit/nav/nav.jsx'); const Navbar = require('../../navbar/navbar.jsx'); @@ -11,192 +9,48 @@ const ReportIssue = require('../../navbar/issue.navitem.jsx'); const PrintLink = require('../../navbar/print.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx'); const Save = require('../../navbar/continousSave.navitem.jsx'); -//const RecentlyEdited = require('../../navbar/recent.navitem.jsx').edited; - - - -const Markdown = require('homebrewery/markdown.js'); - -const SAVE_TIMEOUT = 3000; - const BrewInterface = require('homebrewery/brewInterface/brewInterface.jsx'); const Utils = require('homebrewery/utils.js'); - const Store = require('homebrewery/brew.store.js'); const Actions = require('homebrewery/brew.actions.js'); - - - const EditPage = React.createClass({ + componentDidMount: function(){ + document.addEventListener('keydown', this.handleControlKeys); + }, + componentWillUnmount: function() { + document.removeEventListener('keydown', this.handleControlKeys); + }, + handleControlKeys : Utils.controlKeys({ + s : Actions.save, + p : Actions.print + }), + render : function(){ + return
+ +
+ +
+
+ } +}); + +const SmartNav = Store.createSmartComponent(React.createClass({ getDefaultProps: function() { return { brew : {} }; }, - - getInitialState: function() { - return { - brew : this.props.brew, - - isSaving : false, - isPending : false, - errors : null, - htmlErrors : Markdown.validate(this.props.brew.text), - lastUpdated : this.props.brew.updatedAt - }; - }, - savedBrew : null, - - componentDidMount: function(){ - //this.trySave(); - window.onbeforeunload = ()=>{ - if(Store.getStatus() !== 'ready') return 'You have unsaved changes!'; - }; - - document.addEventListener('keydown', this.handleControlKeys); - }, - componentWillUnmount: function() { - window.onbeforeunload = function(){}; - document.removeEventListener('keydown', this.handleControlKeys); - }, - - - handleControlKeys : Utils.controlKeys({ - s : Actions.pendingSave, - p : ()=>{ - window.open(`/print/${this.props.brew.shareId}?dialog=true`, '_blank').focus(); - } - }), - -/* - handleControlKeys : function(e){ - if(!(e.ctrlKey || e.metaKey)) return; - const S_KEY = 83; - const P_KEY = 80; - if(e.keyCode == S_KEY) this.save(); - if(e.keyCode == P_KEY) - if(e.keyCode == P_KEY || e.keyCode == S_KEY){ - e.stopPropagation(); - e.preventDefault(); - } - }, - - handleSplitMove : function(){ - this.refs.editor.update(); - }, - - handleMetadataChange : function(metadata){ - this.setState({ - brew : _.merge({}, this.state.brew, metadata), - isPending : true, - }, ()=>{ - this.trySave(); - }); - - }, - - handleTextChange : function(text){ - - //If there are errors, run the validator on everychange to give quick feedback - var htmlErrors = this.state.htmlErrors; - if(htmlErrors.length) htmlErrors = Markdown.validate(text); - - this.setState({ - brew : _.merge({}, this.state.brew, {text : text}), - isPending : true, - htmlErrors : htmlErrors - }); - - this.trySave(); - }, -*/ - hasChanges : function(){ - if(this.savedBrew){ - return !_.isEqual(this.state.brew, this.savedBrew) - }else{ - return !_.isEqual(this.state.brew, this.props.brew) - } - return false; - }, - - trySave : function(){ - if(!this.debounceSave) this.debounceSave = _.debounce(this.save, SAVE_TIMEOUT); - if(this.hasChanges()){ - this.debounceSave(); - }else{ - this.debounceSave.cancel(); - } - }, - - save : function(){ - if(this.debounceSave && this.debounceSave.cancel) this.debounceSave.cancel(); - - this.setState({ - isSaving : true, - errors : null, - htmlErrors : Markdown.validate(this.state.brew.text) - }); - - request - .put('/api/update/' + this.props.brew.editId) - .send(this.state.brew) - .end((err, res) => { - if(err){ - this.setState({ - errors : err, - }) - }else{ - this.savedBrew = res.body; - this.setState({ - isPending : false, - isSaving : false, - lastUpdated : res.body.updatedAt - }) - } - }) - }, - - renderSaveButton : function(){ - if(this.state.errors){ - var errMsg = ''; - try{ - errMsg += this.state.errors.toString() + '\n\n'; - errMsg += '```\n' + JSON.stringify(this.state.errors.response.error, null, ' ') + '\n```'; - }catch(e){} - - return - Oops! -
- Looks like there was a problem saving.
- Report the issue - here - . -
-
- } - - if(this.state.isSaving){ - return saving... - } - if(this.state.isPending && this.hasChanges()){ - return Save Now - } - if(!this.state.isPending && !this.state.isSaving){ - return saved. - } - }, - renderNavbar : function(){ + render : function(){ return - {this.state.brew.title} + {this.props.brew.title} - {this.renderSaveButton()} - {/**/} + Share @@ -205,17 +59,9 @@ const EditPage = React.createClass({ - }, - - render : function(){ - return
- {this.renderNavbar()} - -
- -
-
} +}), ()=>{ + return {brew : Store.getBrew()} }); module.exports = EditPage; diff --git a/client/homebrew/pages/editPage/editPage.less b/client/homebrew/pages/editPage/editPage.less index 85890df..2d3115d 100644 --- a/client/homebrew/pages/editPage/editPage.less +++ b/client/homebrew/pages/editPage/editPage.less @@ -1,27 +1,4 @@ .editPage{ - .navItem.save{ - width : 105px; - text-align : center; - &.saved{ - cursor : initial; - color : #666; - } - &.error{ - position : relative; - background-color : @red; - .errorContainer{ - position : absolute; - top : 29px; - left : -20px; - z-index : 1000; - width : 120px; - padding : 8px; - background-color : #333; - a{ - color : @teal; - } - } - } - } + } \ No newline at end of file diff --git a/shared/homebrewery/brew.actions.js b/shared/homebrewery/brew.actions.js index e7aaedc..868e616 100644 --- a/shared/homebrewery/brew.actions.js +++ b/shared/homebrewery/brew.actions.js @@ -3,6 +3,9 @@ const dispatch = require('pico-flux').dispatch; const request = require('superagent'); const Store = require('./brew.store.js'); +let pendingTimer; +const PENDING_TIMEOUT = 3000; + const Actions = { init : (initState) => { Store.init(initState); @@ -17,9 +20,13 @@ const Actions = { dispatch('UPDATE_META', meta); }, - - + pendingSave : () => { + clearTimeout(pendingTimer); + pendingTimer = setTimeout(Actions.save, PENDING_TIMEOUT); + dispatch('SET_STATUS', 'pending'); + }, save : () => { + clearTimeout(pendingTimer); const brew = Store.getBrew(); dispatch('SET_STATUS', 'saving'); request @@ -27,8 +34,8 @@ const Actions = { .send(brew) .end((err, res) => { if(err) return dispatch('SET_STATUS', 'error', err); - dispatch('SET_STATUS', 'ready'); dispatch('SET_BREW', res.body); + dispatch('SET_STATUS', 'ready'); }); }, @@ -45,6 +52,9 @@ const Actions = { localPrint : ()=>{ localStorage.setItem('print', Store.getBrewText()); window.open('/print?dialog=true&local=print','_blank'); + }, + print : ()=>{ + window.open(`/print/${Store.getBrew().shareId}?dialog=true`, '_blank').focus(); } }; diff --git a/shared/homebrewery/brew.store.js b/shared/homebrewery/brew.store.js index 5879701..d4885aa 100644 --- a/shared/homebrewery/brew.store.js +++ b/shared/homebrewery/brew.store.js @@ -37,8 +37,9 @@ const Store = flux.createStore({ State.brew = _.merge({}, State.brew, meta); }, SET_STATUS : (status, error) => { - State.status = status; + if(status == State.status) return false; if(error) State.errors = error; + State.status = status; } }); @@ -65,5 +66,4 @@ Store.getStatus = ()=>{ return State.status; }; - module.exports = Store; \ No newline at end of file