diff --git a/client/homebrew/navbar/continousSave.navitem.jsx b/client/homebrew/navbar/continousSave.navitem.jsx index 5ea9d36..1ffea69 100644 --- a/client/homebrew/navbar/continousSave.navitem.jsx +++ b/client/homebrew/navbar/continousSave.navitem.jsx @@ -33,7 +33,7 @@ const ContinousSave = React.createClass({ window.onbeforeunload = function(){}; }, actionHandler : function(actionType){ - if(actionType == 'UPDATE_BREW_TEXT' || actionType == 'UPDATE_META'){ + if(actionType == 'UPDATE_BREW_CODE' || actionType == 'UPDATE_META' || actionType == 'UPDATE_BREW_STYLE'){ Actions.pendingSave(); } }, @@ -51,6 +51,9 @@ const ContinousSave = React.createClass({ Oops!
Looks like there was a problem saving.
+ Back up your brew in a text file, just in case. +

+ Report the issue here . diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less index fdf3203..7c844bc 100644 --- a/client/homebrew/navbar/navbar.less +++ b/client/homebrew/navbar/navbar.less @@ -120,7 +120,7 @@ top : 29px; left : -20px; z-index : 1000; - width : 120px; + width : 170px; padding : 8px; background-color : #333; a{ diff --git a/scripts/project.json b/scripts/project.json index b39bc90..03fec02 100644 --- a/scripts/project.json +++ b/scripts/project.json @@ -10,6 +10,7 @@ "codemirror", "codemirror/mode/gfm/gfm.js", "codemirror/mode/javascript/javascript.js", + "codemirror/mode/css/css.js", "moment", "superagent", "marked", diff --git a/server/brew.data.js b/server/brew.data.js index a040468..c39adb6 100644 --- a/server/brew.data.js +++ b/server/brew.data.js @@ -10,6 +10,7 @@ const BrewSchema = mongoose.Schema({ editId : {type : String, default: shortid.generate, index: { unique: true }}, text : {type : String, default : ""}, + style : {type : String, default : ""}, title : {type : String, default : ""}, description : {type : String, default : ""}, @@ -23,7 +24,7 @@ const BrewSchema = mongoose.Schema({ updatedAt : { type: Date, default: Date.now}, lastViewed : { type: Date, default: Date.now}, views : {type:Number, default:0}, - version : {type: Number, default:1} + version : {type: Number, default:2} }, { versionKey: false, toJSON : { diff --git a/shared/homebrewery/brew.actions.js b/shared/homebrewery/brew.actions.js index 78a0546..5e0b41e 100644 --- a/shared/homebrewery/brew.actions.js +++ b/shared/homebrewery/brew.actions.js @@ -54,10 +54,13 @@ const Actions = { setBrew : (brew) => { dispatch('SET_BREW', brew); }, - updateBrewText : (brewText) => { - dispatch('UPDATE_BREW_TEXT', brewText) + updateBrewCode : (brewCode) => { + dispatch('UPDATE_BREW_CODE', brewCode) }, - updateMetaData : (meta) => { + updateBrewStyle : (style) => { + dispatch('UPDATE_BREW_STYLE', style) + }, + updateMetadata : (meta) => { dispatch('UPDATE_META', meta); }, pendingSave : () => { diff --git a/shared/homebrewery/brew.store.js b/shared/homebrewery/brew.store.js index 483eba5..472c7db 100644 --- a/shared/homebrewery/brew.store.js +++ b/shared/homebrewery/brew.store.js @@ -8,6 +8,7 @@ let State = { brew : { text : '', + style : '', shareId : undefined, editId : undefined, createdAt : undefined, @@ -29,9 +30,13 @@ const Store = flux.createStore({ SET_BREW : (brew) => { State.brew = brew; }, - UPDATE_BREW_TEXT : (brewText) => { - State.brew.text = brewText; - State.errors = Markdown.validate(brewText); + UPDATE_BREW_CODE : (brewCode) => { + State.brew.text = brewCode; + State.errors = Markdown.validate(brewCode); + }, + UPDATE_BREW_STYLE : (style) => { + //TODO: add in an error checker? + State.brew.style = style; }, UPDATE_META : (meta) => { State.brew = _.merge({}, State.brew, meta); @@ -50,11 +55,14 @@ Store.init = (state)=>{ Store.getBrew = ()=>{ return State.brew; }; -Store.getBrewText = ()=>{ +Store.getBrewCode = ()=>{ return State.brew.text; }; +Store.getBrewStyle = ()=>{ + return State.brew.style; +}; Store.getMetaData = ()=>{ - return _.omit(State.brew, ['text']); + return _.omit(State.brew, ['text', 'style']); }; Store.getErrors = ()=>{ return State.errors; diff --git a/shared/homebrewery/brewEditor/brewEditor.jsx b/shared/homebrewery/brewEditor/brewEditor.jsx index 1f1a2fc..d99e2e6 100644 --- a/shared/homebrewery/brewEditor/brewEditor.jsx +++ b/shared/homebrewery/brewEditor/brewEditor.jsx @@ -6,35 +6,36 @@ const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx'); const SnippetBar = require('./snippetbar/snippetbar.jsx'); const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); +const Menubar = require('./menubar/menubar.jsx'); + const splice = function(str, index, inject){ return str.slice(0, index) + inject + str.slice(index); }; -const SNIPPETBAR_HEIGHT = 25; +const MENUBAR_HEIGHT = 25; const BrewEditor = React.createClass({ getDefaultProps: function() { return { - value : '', - onChange : ()=>{}, + brew : { + text : '', + style : '', + }, - metadata : {}, - onMetadataChange : ()=>{}, + onCodeChange : ()=>{}, + onStyleChange : ()=>{}, + onMetaChange : ()=>{}, }; }, getInitialState: function() { return { - showMetadataEditor: false + view : 'code', //'code', 'style', 'meta' }; }, - cursorPosition : { - line : 0, - ch : 0 - }, componentDidMount: function() { this.updateEditorSize(); - this.highlightPageLines(); + //this.highlightPageLines(); window.addEventListener("resize", this.updateEditorSize); }, componentWillUnmount: function() { @@ -42,17 +43,15 @@ const BrewEditor = React.createClass({ }, updateEditorSize : function() { - let paneHeight = this.refs.main.parentNode.clientHeight; - paneHeight -= SNIPPETBAR_HEIGHT + 1; - this.refs.codeEditor.codeMirror.setSize(null, paneHeight); + if(this.refs.codeEditor){ + let paneHeight = this.refs.main.parentNode.clientHeight; + paneHeight -= MENUBAR_HEIGHT + 1; + this.refs.codeEditor.codeMirror.setSize(null, paneHeight); + } }, - handleTextChange : function(text){ - this.props.onChange(text); - }, - handleCursorActivty : function(curpos){ - this.cursorPosition = curpos; - }, + + handleInject : function(injectText){ const lines = this.props.value.split('\n'); lines[this.cursorPosition.line] = splice(lines[this.cursorPosition.line], this.cursorPosition.ch, injectText); @@ -60,23 +59,32 @@ const BrewEditor = React.createClass({ this.handleTextChange(lines.join('\n')); this.refs.codeEditor.setCursorPosition(this.cursorPosition.line, this.cursorPosition.ch + injectText.length); }, - handgleToggle : function(){ + + + + handleViewChange : function(newView){ this.setState({ - showMetadataEditor : !this.state.showMetadataEditor - }) + view : newView + }, this.updateEditorSize); }, + + + brewJump : function(){ const currentPage = this.getCurrentPage(); window.location.hash = 'p' + currentPage; }, //Called when there are changes to the editor's dimensions + /* update : function(){ - this.refs.codeEditor.updateSize(); + if(this.refs.codeEditor) this.refs.codeEditor.updateSize(); }, + */ //TODO: convert this into a generic function for columns and blocks + //MOve this to a util.sj file highlightPageLines : function(){ if(!this.refs.codeEditor) return; const codeMirror = this.refs.codeEditor.codeMirror; @@ -91,6 +99,7 @@ const BrewEditor = React.createClass({ return lineNumbers }, + /* renderMetadataEditor : function(){ if(!this.state.showMetadataEditor) return; return }, + */ + + + + renderEditor : function(){ + if(this.state.view == 'meta'){ + return + } + if(this.state.view == 'style'){ + return + } + if(this.state.view == 'code'){ + return + } + }, render : function(){ - - this.highlightPageLines(); - - return
+ return
+ {/* - {this.renderMetadataEditor()} - + */} + + + {this.renderEditor()} +
/* diff --git a/shared/homebrewery/brewEditor/brewEditor.smart.jsx b/shared/homebrewery/brewEditor/brewEditor.smart.jsx index 2dc647c..fe88648 100644 --- a/shared/homebrewery/brewEditor/brewEditor.smart.jsx +++ b/shared/homebrewery/brewEditor/brewEditor.smart.jsx @@ -5,9 +5,10 @@ const BrewEditor = require('./brewEditor.jsx') module.exports = Store.createSmartComponent(BrewEditor, ()=>{ return { - value : Store.getBrewText(), - onChange : Actions.updateBrewText, - metadata : Store.getMetaData(), - onMetadataChange : Actions.updateMetaData, + brew : Store.getBrew(), + + onCodeChange : Actions.updateBrewCode, + onStyleChange : Actions.updateBrewStyle, + onMetaChange : Actions.updateMetadata, }; }); \ No newline at end of file diff --git a/shared/homebrewery/brewEditor/menubar/menubar.jsx b/shared/homebrewery/brewEditor/menubar/menubar.jsx new file mode 100644 index 0000000..ed47e08 --- /dev/null +++ b/shared/homebrewery/brewEditor/menubar/menubar.jsx @@ -0,0 +1,35 @@ + +const React = require('react'); +const _ = require('lodash'); +const cx = require('classnames'); + +const Menubar = React.createClass({ + getDefaultProps: function() { + return { + view : '', + onViewChange : ()=>{}, + onSnippetInject : ()=>{}, + }; + }, + render: function(){ + return
+ +
+
+ +
+
+ +
+
+ +
+
+
+ } +}); + +module.exports = Menubar; diff --git a/shared/homebrewery/brewEditor/menubar/menubar.less b/shared/homebrewery/brewEditor/menubar/menubar.less new file mode 100644 index 0000000..653e82c --- /dev/null +++ b/shared/homebrewery/brewEditor/menubar/menubar.less @@ -0,0 +1,35 @@ + +.menubar{ + @menuHeight : 25px; + position : relative; + height : @menuHeight; + background-color : #ddd; + .editors{ + position : absolute; + display : flex; + top : 0px; + right : 0px; + height : @menuHeight; + width : 90px; + justify-content : space-between; + &>div{ + height : @menuHeight; + width : @menuHeight; + cursor : pointer; + line-height : @menuHeight; + text-align : center; + &:hover,&.selected{ + background-color : #999; + } + &.code{ + .tooltipLeft('Brew Editor'); + } + &.style{ + .tooltipLeft('Style Editor'); + } + &.meta{ + .tooltipLeft('Metadata'); + } + } + } +} \ No newline at end of file diff --git a/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less b/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less index 2f9812d..3b85ddd 100644 --- a/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less +++ b/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less @@ -1,11 +1,11 @@ .metadataEditor{ position : absolute; - z-index : 10000; box-sizing : border-box; width : 100%; padding : 25px; - background-color : #999; +// background-color : #999; + background-color: white; .field{ display : flex; width : 100%; diff --git a/shared/homebrewery/brewRenderer/brewRenderer.jsx b/shared/homebrewery/brewRenderer/brewRenderer.jsx index 2b3c893..ddcf424 100644 --- a/shared/homebrewery/brewRenderer/brewRenderer.jsx +++ b/shared/homebrewery/brewRenderer/brewRenderer.jsx @@ -15,12 +15,13 @@ const PPR_THRESHOLD = 50; const BrewRenderer = React.createClass({ getDefaultProps: function() { return { - brewText : '', + value : '', + style : '', errors : [] }; }, getInitialState: function() { - const pages = this.props.brewText.split('\\page'); + const pages = this.props.value.split('\\page'); return { viewablePageNumber: 0, @@ -45,7 +46,7 @@ const BrewRenderer = React.createClass({ componentWillReceiveProps: function(nextProps) { if(this.refs.pages && this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight; - const pages = nextProps.brewText.split('\\page'); + const pages = nextProps.value.split('\\page'); this.setState({ pages : pages, usePPR : pages.length >= PPR_THRESHOLD @@ -124,6 +125,10 @@ const BrewRenderer = React.createClass({ return this.lastRender; }, + renderStyle : function(){ + + }, + render : function(){ return
+ +
{this.renderPages()}
diff --git a/shared/homebrewery/brewRenderer/brewRenderer.smart.jsx b/shared/homebrewery/brewRenderer/brewRenderer.smart.jsx index 6f1d97d..bbe2ed1 100644 --- a/shared/homebrewery/brewRenderer/brewRenderer.smart.jsx +++ b/shared/homebrewery/brewRenderer/brewRenderer.smart.jsx @@ -4,7 +4,8 @@ const BrewRenderer = require('./brewRenderer.jsx'); module.exports = Store.createSmartComponent(BrewRenderer, () => { return { - brewText : Store.getBrewText(), + value : Store.getBrewCode(), + style : Store.getBrewStyle(), errors : Store.getErrors() } }); \ No newline at end of file diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index c03c7ad..cee2b9e 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -1,70 +1,70 @@ -var React = require('react'); -var _ = require('lodash'); -var cx = require('classnames'); +const React = require('react'); +const _ = require('lodash'); +const cx = require('classnames'); - -var CodeMirror; +let CodeMirror; if(typeof navigator !== 'undefined'){ - var CodeMirror = require('codemirror'); - + CodeMirror = require('codemirror'); //Language Modes require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown require('codemirror/mode/javascript/javascript.js'); + require('codemirror/mode/css/css.js'); } -var CodeEditor = React.createClass({ +const CodeEditor = React.createClass({ getDefaultProps: function() { return { + value : '', + language : '', - value : '', - wrap : false, - onChange : function(){}, - onCursorActivity : function(){}, + wrap : true, + onChange : ()=>{}, }; }, - - componentDidMount: function() { - this.codeMirror = CodeMirror(this.refs.editor,{ - value : this.props.value, - lineNumbers: true, - lineWrapping : this.props.wrap, - mode : this.props.language, - }); - - this.codeMirror.on('change', this.handleChange); - this.codeMirror.on('cursorActivity', this.handleCursorActivity); - this.updateSize(); - }, - componentWillReceiveProps: function(nextProps){ + if(this.props.language !== nextProps.language){ + this.buildEditor(); + } if(this.codeMirror && nextProps.value !== undefined && this.codeMirror.getValue() != nextProps.value) { this.codeMirror.setValue(nextProps.value); } }, - shouldComponentUpdate: function(nextProps, nextState) { return false; }, + componentDidMount: function() { + this.buildEditor(); + }, + buildEditor : function(){ + this.codeMirror = CodeMirror(this.refs.editor,{ + value : this.props.value, + lineNumbers : true, + lineWrapping : this.props.wrap, + mode : this.props.language, + indentWithTabs : true, + tabSize : 2 + }); + this.codeMirror.on('change', ()=>{ + this.props.onChange(this.codeMirror.getValue()); + }); + this.updateSize(); + }, + //Externally Used setCursorPosition : function(line, char){ setTimeout(()=>{ this.codeMirror.focus(); this.codeMirror.doc.setCursor(line, char); }, 10); }, - + getCursorPosition : function(){ + return this.codeMirror.getCursor(); + }, updateSize : function(){ this.codeMirror.refresh(); }, - handleChange : function(editor){ - this.props.onChange(editor.getValue()); - }, - handleCursorActivity : function(){ - this.props.onCursorActivity(this.codeMirror.doc.getCursor()); - }, - render : function(){ return
}