diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx
index d79ef4a..6b15eae 100644
--- a/client/homebrew/editor/editor.jsx
+++ b/client/homebrew/editor/editor.jsx
@@ -1,25 +1,31 @@
-var React = require('react');
-var _ = require('lodash');
-var cx = require('classnames');
+const React = require('react');
+const _ = require('lodash');
+const cx = require('classnames');
-var CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
-var Snippets = require('./snippets/snippets.js');
+const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
+const SnippetBar = require('./snippetbar/snippetbar.jsx');
+const MetadataEditor = require('./MetadataEditor/MetadataEditor.jsx');
-var splice = function(str, index, inject){
+const splice = function(str, index, inject){
return str.slice(0, index) + inject + str.slice(index);
};
-var execute = function(val){
- if(_.isFunction(val)) return val();
- return val;
-}
+const SNIPPETBAR_HEIGHT = 25;
-var Editor = React.createClass({
+const Editor = React.createClass({
getDefaultProps: function() {
return {
- value : "",
- onChange : function(){}
+ value : '',
+ onChange : ()=>{},
+
+ metadata : {},
+ onMetadataChange : ()=>{}
+ };
+ },
+ getInitialState: function() {
+ return {
+ showMetadataEditor: false
};
},
cursorPosition : {
@@ -27,7 +33,6 @@ var Editor = React.createClass({
ch : 0
},
-
componentDidMount: function() {
this.updateEditorSize();
window.addEventListener("resize", this.updateEditorSize);
@@ -37,8 +42,8 @@ var Editor = React.createClass({
},
updateEditorSize : function() {
- var paneHeight = this.refs.main.parentNode.clientHeight;
- paneHeight -= this.refs.snippetBar.clientHeight + 1;
+ let paneHeight = this.refs.main.parentNode.clientHeight;
+ paneHeight -= SNIPPETBAR_HEIGHT + 1;
this.refs.codeEditor.codeMirror.setSize(null, paneHeight);
},
@@ -48,38 +53,37 @@ var Editor = React.createClass({
handleCursorActivty : function(curpos){
this.cursorPosition = curpos;
},
-
- handleSnippetClick : function(injectText){
- var lines = this.props.value.split('\n');
+ handleInject : function(injectText){
+ const lines = this.props.value.split('\n');
lines[this.cursorPosition.line] = splice(lines[this.cursorPosition.line], this.cursorPosition.ch, injectText);
this.handleTextChange(lines.join('\n'));
this.refs.codeEditor.setCursorPosition(this.cursorPosition.line, this.cursorPosition.ch + injectText.length);
},
+ handgleToggle : function(){
+ this.setState({
+ showMetadataEditor : !this.state.showMetadataEditor
+ })
+ },
//Called when there are changes to the editor's dimensions
update : function(){
this.refs.codeEditor.updateSize();
},
- renderSnippetGroups : function(){
- return _.map(Snippets, (snippetGroup)=>{
- return
- })
+ renderMetadataEditor : function(){
+ if(!this.state.showMetadataEditor) return;
+ return
},
render : function(){
return(
-
- {this.renderSnippetGroups()}
-
+
+ {this.renderMetadataEditor()}
{
- return
-
- {snippet.name}
-
- })
- },
-
- render : function(){
- return
-
-
- {this.props.groupName}
-
-
- {this.renderSnippets()}
-
-
- },
-
-});
\ No newline at end of file
diff --git a/client/homebrew/editor/editor.less b/client/homebrew/editor/editor.less
index 611f44d..8678fd1 100644
--- a/client/homebrew/editor/editor.less
+++ b/client/homebrew/editor/editor.less
@@ -2,76 +2,10 @@
.editor{
position : relative;
width : 100%;
- .snippetBar{
- @height : 25px;
- position : relative;
- height : @height;
- background-color : #ddd;
- .snippetGroup{
- /*
- .animate(background-color);
- margin : 0px 8px;
- padding : 3px;
- font-size : 13px;
- border-radius : 5px;
- &:hover, &.selected{
- background-color : #999;
- }
- */
- display : inline-block;
- height : @height;
- padding : 0px 5px;
- cursor : pointer;
- font-size : 0.6em;
- font-weight : 800;
- line-height : @height;
- text-transform : uppercase;
- border-right : 1px solid black;
- i{
- vertical-align : middle;
- margin-right : 3px;
- font-size : 1.2em;
- }
- &:hover, &.selected{
- background-color : #999;
- }
- .text{
- line-height : @height;
- .groupName{
- margin-left : 6px;
- font-size : 10px;
- }
- }
- &:hover{
- .dropdown{
- visibility : visible;
- }
- }
- .dropdown{
- position : absolute;
- visibility : hidden;
- top : 100%;
- z-index : 1000;
- padding : 0px;
- margin-left: -5px;
- background-color : #ddd;
- .snippet{
- .animate(background-color);
- padding : 10px;
- cursor : pointer;
- font-size : 10px;
- i{
- margin-right: 8px;
- font-size : 13px;
- }
- &:hover{
- background-color : #999;
- }
- }
- }
- }
- }
+
.codeEditor{
height : 100%;
}
+
+
}
\ No newline at end of file
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.jsx b/client/homebrew/editor/metadataEditor/metadataEditor.jsx
new file mode 100644
index 0000000..4fd395f
--- /dev/null
+++ b/client/homebrew/editor/metadataEditor/metadataEditor.jsx
@@ -0,0 +1,106 @@
+const React = require('react');
+const _ = require('lodash');
+const cx = require('classnames');
+
+const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder']
+
+const MetadataEditor = React.createClass({
+ getDefaultProps: function() {
+ return {
+ metadata: {
+ title : '',
+ description : '',
+ tags : '',
+ published : false,
+ authors : [],
+ systems : []
+ },
+ onChange : ()=>{}
+ };
+ },
+
+ handleFieldChange : function(name, e){
+ this.props.onChange(_.merge({}, this.props.metadata, {
+ [name] : e.target.value
+ }))
+ },
+ handleSystem : function(system, e){
+ if(e.target.checked){
+ this.props.metadata.systems.push(system);
+ }else{
+ this.props.metadata.systems = _.without(this.props.metadata.systems, system);
+ }
+ this.props.onChange(this.props.metadata);
+ },
+ handlePublish : function(val){
+ this.props.onChange(_.merge({}, this.props.metadata, {
+ published : val
+ }));
+ },
+
+ renderSystems : function(){
+ return _.map(SYSTEMS, (val)=>{
+ return
+ });
+ },
+
+ renderPublish : function(){
+ if(this.props.metadata.published){
+ return
+ }else{
+ return
+ }
+ },
+
+ render : function(){
+ return
+
+
+
+
+
+
+
+
+
+ {/*}
+
+
+
+
+ */}
+
+
+
+
+ {this.renderSystems()}
+
+
+
+
+
+
+ {this.renderPublish()}
+ Published homebrews will be publicly searchable (eventually...)
+
+
+
+
+ }
+});
+
+module.exports = MetadataEditor;
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less
new file mode 100644
index 0000000..57728d5
--- /dev/null
+++ b/client/homebrew/editor/metadataEditor/metadataEditor.less
@@ -0,0 +1,63 @@
+
+.metadataEditor{
+ position : absolute;
+ z-index : 10000;
+ box-sizing : border-box;
+ width : 100%;
+ padding : 25px;
+ background-color : #999;
+ .field{
+ display : flex;
+ width : 100%;
+ margin-bottom : 10px;
+ &>label{
+ display : inline-block;
+ vertical-align : top;
+ width : 80px;
+ font-size : 0.7em;
+ font-weight : 800;
+ line-height : 1.8em;
+ text-transform : uppercase;
+ flex-grow : 0;
+ }
+ &>.value{
+ flex-grow : 1;
+ }
+ }
+ .description.field textarea.value{
+ resize : none;
+ height : 5em;
+ font-family : 'Open Sans', sans-serif;
+ font-size : 0.8em;
+ }
+ .systems.field .value{
+ label{
+ vertical-align : middle;
+ margin-right : 15px;
+ cursor : pointer;
+ font-size : 0.7em;
+ font-weight : 800;
+ user-select : none;
+ }
+ input{
+ vertical-align : middle;
+ cursor : pointer;
+ }
+ }
+ .publish.field .value{
+ position : relative;
+ button.publish{
+ .button(@blueLight);
+ }
+ button.unpublish{
+ .button(@silver);
+ }
+ small{
+ position : absolute;
+ bottom : -15px;
+ left : 0px;
+ font-size : 0.6em;
+ font-style : italic;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx
new file mode 100644
index 0000000..2f93fbe
--- /dev/null
+++ b/client/homebrew/editor/snippetbar/snippetbar.jsx
@@ -0,0 +1,91 @@
+const React = require('react');
+const _ = require('lodash');
+const cx = require('classnames');
+
+
+const Snippets = require('./snippets/snippets.js');
+
+const execute = function(val){
+ if(_.isFunction(val)) return val();
+ return val;
+}
+
+
+
+const Snippetbar = React.createClass({
+ getDefaultProps: function() {
+ return {
+ onInject : ()=>{},
+ onToggle : ()=>{},
+ showmeta : false
+ };
+ },
+
+ handleSnippetClick : function(injectedText){
+ this.props.onInject(injectedText)
+ },
+
+ renderSnippetGroups : function(){
+ return _.map(Snippets, (snippetGroup)=>{
+ return
+ })
+ },
+
+ render : function(){
+ return
+ {this.renderSnippetGroups()}
+
+
+
+
+ }
+});
+
+module.exports = Snippetbar;
+
+
+
+
+
+
+const SnippetGroup = React.createClass({
+ getDefaultProps: function() {
+ return {
+ groupName : '',
+ icon : 'fa-rocket',
+ snippets : [],
+ onSnippetClick : function(){},
+ };
+ },
+ handleSnippetClick : function(snippet){
+ this.props.onSnippetClick(execute(snippet.gen));
+ },
+ renderSnippets : function(){
+ return _.map(this.props.snippets, (snippet)=>{
+ return
+
+ {snippet.name}
+
+ })
+ },
+
+ render : function(){
+ return
+
+
+ {this.props.groupName}
+
+
+ {this.renderSnippets()}
+
+
+ },
+
+});
\ No newline at end of file
diff --git a/client/homebrew/editor/snippetbar/snippetbar.less b/client/homebrew/editor/snippetbar/snippetbar.less
new file mode 100644
index 0000000..a939fa5
--- /dev/null
+++ b/client/homebrew/editor/snippetbar/snippetbar.less
@@ -0,0 +1,72 @@
+
+.snippetBar{
+ @height : 25px;
+ position : relative;
+ height : @height;
+ background-color : #ddd;
+ .toggleMeta{
+ position : absolute;
+ top : 0px;
+ right : 0px;
+ height : @height;
+ width : @height;
+ cursor : pointer;
+ line-height : @height;
+ text-align : center;
+ &:hover, &.selected{
+ background-color : #999;
+ }
+ }
+ .snippetGroup{
+ display : inline-block;
+ height : @height;
+ padding : 0px 5px;
+ cursor : pointer;
+ font-size : 0.6em;
+ font-weight : 800;
+ line-height : @height;
+ text-transform : uppercase;
+ border-right : 1px solid black;
+ i{
+ vertical-align : middle;
+ margin-right : 3px;
+ font-size : 1.2em;
+ }
+ &:hover, &.selected{
+ background-color : #999;
+ }
+ .text{
+ line-height : @height;
+ .groupName{
+ font-size : 10px;
+ }
+ }
+ &:hover{
+ .dropdown{
+ visibility : visible;
+ }
+ }
+ .dropdown{
+ position : absolute;
+ top : 100%;
+ visibility : hidden;
+ z-index : 1000;
+ margin-left : -5px;
+ padding : 0px;
+ background-color : #ddd;
+ .snippet{
+ .animate(background-color);
+ padding : 10px;
+ cursor : pointer;
+ font-size : 10px;
+ i{
+ margin-right : 8px;
+ font-size : 13px;
+ }
+ &:hover{
+ background-color : #999;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/homebrew/editor/snippets/classfeature.gen.js b/client/homebrew/editor/snippetbar/snippets/classfeature.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/classfeature.gen.js
rename to client/homebrew/editor/snippetbar/snippets/classfeature.gen.js
diff --git a/client/homebrew/editor/snippets/classtable.gen.js b/client/homebrew/editor/snippetbar/snippets/classtable.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/classtable.gen.js
rename to client/homebrew/editor/snippetbar/snippets/classtable.gen.js
diff --git a/client/homebrew/editor/snippets/coverpage.gen.js b/client/homebrew/editor/snippetbar/snippets/coverpage.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/coverpage.gen.js
rename to client/homebrew/editor/snippetbar/snippets/coverpage.gen.js
diff --git a/client/homebrew/editor/snippets/fullclass.gen.js b/client/homebrew/editor/snippetbar/snippets/fullclass.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/fullclass.gen.js
rename to client/homebrew/editor/snippetbar/snippets/fullclass.gen.js
diff --git a/client/homebrew/editor/snippets/magic.gen.js b/client/homebrew/editor/snippetbar/snippets/magic.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/magic.gen.js
rename to client/homebrew/editor/snippetbar/snippets/magic.gen.js
diff --git a/client/homebrew/editor/snippets/monsterblock.gen.js b/client/homebrew/editor/snippetbar/snippets/monsterblock.gen.js
similarity index 100%
rename from client/homebrew/editor/snippets/monsterblock.gen.js
rename to client/homebrew/editor/snippetbar/snippets/monsterblock.gen.js
diff --git a/client/homebrew/editor/snippets/snippets.js b/client/homebrew/editor/snippetbar/snippets/snippets.js
similarity index 100%
rename from client/homebrew/editor/snippets/snippets.js
rename to client/homebrew/editor/snippetbar/snippets/snippets.js
diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less
index 6b9423d..b5995e3 100644
--- a/client/homebrew/homebrew.less
+++ b/client/homebrew/homebrew.less
@@ -13,4 +13,7 @@
flex : auto;
}
}
+
+
+
}
\ No newline at end of file
diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx
index a321cd8..790ee08 100644
--- a/client/homebrew/pages/editPage/editPage.jsx
+++ b/client/homebrew/pages/editPage/editPage.jsx
@@ -1,47 +1,52 @@
-var React = require('react');
-var _ = require('lodash');
-var cx = require('classnames');
-var request = require("superagent");
+const React = require('react');
+const _ = require('lodash');
+const cx = require('classnames');
+const request = require("superagent");
-var Nav = require('naturalcrit/nav/nav.jsx');
-var Navbar = require('../../navbar/navbar.jsx');
+const Nav = require('naturalcrit/nav/nav.jsx');
+const Navbar = require('../../navbar/navbar.jsx');
-var EditTitle = require('../../navbar/editTitle.navitem.jsx');
-var ReportIssue = require('../../navbar/issue.navitem.jsx');
-var PrintLink = require('../../navbar/print.navitem.jsx');
-var RecentlyEdited = require('../../navbar/recent.navitem.jsx').edited;
+const ReportIssue = require('../../navbar/issue.navitem.jsx');
+const PrintLink = require('../../navbar/print.navitem.jsx');
+const RecentlyEdited = require('../../navbar/recent.navitem.jsx').edited;
-var SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
-var Editor = require('../../editor/editor.jsx');
-var BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
+const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
+const Editor = require('../../editor/editor.jsx');
+const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
-var Markdown = require('naturalcrit/markdown.js');
+const Markdown = require('naturalcrit/markdown.js');
const SAVE_TIMEOUT = 3000;
-var EditPage = React.createClass({
+const EditPage = React.createClass({
getDefaultProps: function() {
return {
- id : null,
brew : {
- title : '',
text : '',
shareId : null,
editId : null,
createdAt : null,
updatedAt : null,
+
+ title : '',
+ description : '',
+ tags : '',
+ published : false,
+ authors : [],
+ systems : []
}
};
},
getInitialState: function() {
return {
- title : this.props.brew.title,
- text: this.props.brew.text,
+ brew : this.props.brew,
+
+
isSaving : false,
isPending : false,
errors : null,
@@ -60,7 +65,7 @@ var EditPage = React.createClass({
};
this.setState({
- htmlErrors : Markdown.validate(this.state.text)
+ htmlErrors : Markdown.validate(this.state.brew.text)
})
document.addEventListener('keydown', this.handleControlKeys);
@@ -85,13 +90,15 @@ var EditPage = React.createClass({
this.refs.editor.update();
},
- handleTitleChange : function(title){
+ handleMetadataChange : function(metadata){
this.setState({
- title : title,
- isPending : true
+ brew : _.merge({}, this.state.brew, metadata),
+ isPending : true,
+ }, ()=>{
+ console.log(this.hasChanges());
+ (this.hasChanges() ? this.debounceSave() : this.debounceSave.cancel());
});
- (this.hasChanges() ? this.debounceSave() : this.debounceSave.cancel());
},
handleTextChange : function(text){
@@ -101,7 +108,7 @@ var EditPage = React.createClass({
if(htmlErrors.length) htmlErrors = Markdown.validate(text);
this.setState({
- text : text,
+ brew : _.merge({}, this.state.brew, {text : text}),
isPending : true,
htmlErrors : htmlErrors
});
@@ -122,11 +129,9 @@ var EditPage = React.createClass({
hasChanges : function(){
if(this.savedBrew){
- if(this.state.text !== this.savedBrew.text) return true;
- if(this.state.title !== this.savedBrew.title) return true;
+ return !_.isEqual(this.state.brew, this.savedBrew)
}else{
- if(this.state.text !== this.props.brew.text) return true;
- if(this.state.title !== this.props.brew.title) return true;
+ return !_.isEqual(this.state.brew, this.props.brew)
}
return false;
},
@@ -136,15 +141,12 @@ var EditPage = React.createClass({
this.setState({
isSaving : true,
errors : null,
- htmlErrors : Markdown.validate(this.state.text)
+ htmlErrors : Markdown.validate(this.state.brew.text)
});
request
.put('/api/update/' + this.props.brew.editId)
- .send({
- text : this.state.text,
- title : this.state.title
- })
+ .send(this.state.brew)
.end((err, res) => {
if(err){
this.setState({
@@ -184,17 +186,17 @@ var EditPage = React.createClass({
if(this.state.isSaving){
return saving...
}
- if(!this.state.isPending && !this.state.isSaving){
- return saved.
- }
if(this.state.isPending && this.hasChanges()){
return Save Now
}
+ if(!this.state.isPending && !this.state.isSaving){
+ return saved.
+ }
},
renderNavbar : function(){
return
-
+ {this.state.brew.title}
{this.renderSaveButton()}
@@ -216,8 +218,14 @@ var EditPage = React.createClass({
-
-
+
+
diff --git a/client/homebrew/pages/editPage/editPage.less b/client/homebrew/pages/editPage/editPage.less
index 775013c..85890df 100644
--- a/client/homebrew/pages/editPage/editPage.less
+++ b/client/homebrew/pages/editPage/editPage.less
@@ -1,7 +1,7 @@
.editPage{
.navItem.save{
- width : 75px;
+ width : 105px;
text-align : center;
&.saved{
cursor : initial;
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx
index 47e5f95..d107b5d 100644
--- a/client/homebrew/pages/newPage/newPage.jsx
+++ b/client/homebrew/pages/newPage/newPage.jsx
@@ -20,7 +20,15 @@ const KEY = 'homebrewery-new';
const NewPage = React.createClass({
getInitialState: function() {
return {
- title : '',
+ metadata : {
+ title : '',
+ description : '',
+ tags : '',
+ published : false,
+ authors : [],
+ systems : []
+ },
+
text: '',
isSaving : false,
errors : []
@@ -53,9 +61,9 @@ const NewPage = React.createClass({
this.refs.editor.update();
},
- handleTitleChange : function(title){
+ handleMetadataChange : function(metadata){
this.setState({
- title : title
+ metadata : _.merge({}, this.state.metadata, metadata)
});
},
@@ -73,10 +81,9 @@ const NewPage = React.createClass({
});
request.post('/api')
- .send({
- title : this.state.title,
+ .send(_.merge({}, this.state.metadata, {
text : this.state.text
- })
+ }))
.end((err, res)=>{
if(err){
this.setState({
@@ -117,7 +124,7 @@ const NewPage = React.createClass({
renderNavbar : function(){
return
-
+ {this.state.metadata.title}
@@ -133,7 +140,13 @@ const NewPage = React.createClass({
{this.renderNavbar()}
-
+
diff --git a/server/homebrew.model.js b/server/homebrew.model.js
index abb9bf1..8b9ec79 100644
--- a/server/homebrew.model.js
+++ b/server/homebrew.model.js
@@ -7,7 +7,12 @@ var HomebrewSchema = mongoose.Schema({
editId : {type : String, default: shortid.generate, index: { unique: true }},
title : {type : String, default : ""},
text : {type : String, default : ""},
+
+ description : {type : String, default : ""},
+ tags : {type : String, default : ""},
+ systems : [String],
authors : [String],
+ published : {type : Boolean, default : false},
createdAt : { type: Date, default: Date.now },
updatedAt : { type: Date, default: Date.now},
diff --git a/shared/naturalcrit/styles/core.less b/shared/naturalcrit/styles/core.less
index 7b131f2..1f21dc6 100644
--- a/shared/naturalcrit/styles/core.less
+++ b/shared/naturalcrit/styles/core.less
@@ -1,9 +1,9 @@
+
@import 'naturalcrit/styles/reset.less';
//@import 'naturalcrit/styles/elements.less';
@import 'naturalcrit/styles/animations.less';
@import 'naturalcrit/styles/colors.less';
@import 'naturalcrit/styles/tooltip.less';
-
@font-face {
font-family : CodeLight;
src : url('/assets/naturalcrit/styles/CODE Light.otf');
@@ -13,8 +13,38 @@
src : url('/assets/naturalcrit/styles/CODE Bold.otf');
}
html,body, #reactContainer{
- min-height: 100vh;
- height: 100vh;
- margin: 0;
+ height : 100vh;
+ min-height : 100vh;
+ margin : 0;
+ font-family : 'Open Sans', sans-serif;
+}
+*{
+ box-sizing : border-box;
+}
+button{
+ .button();
+}
+.button(@backgroundColor : @green){
+ .animate(background-color);
+ display : inline-block;
+ padding : 0.6em 1.2em;
+ cursor : pointer;
+ background-color : @backgroundColor;
font-family : 'Open Sans', sans-serif;
+ font-size : 0.8em;
+ font-weight : 800;
+ color : white;
+ text-decoration : none;
+ text-transform : uppercase;
+ border : none;
+ outline : none;
+ &:hover{
+ background-color : darken(@backgroundColor, 5%);
+ }
+ &:active{
+ background-color : darken(@backgroundColor, 10%);
+ }
+ &:disabled{
+ background-color : @silver !important;
+ }
}
\ No newline at end of file