mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-03 19:12:41 +00:00
Merge branch 'v2.6'
This commit is contained in:
13
changelog.md
13
changelog.md
@@ -1,5 +1,18 @@
|
|||||||
# changelog
|
# changelog
|
||||||
|
|
||||||
|
### Saturday, 03/12/2016 - v2.6.0
|
||||||
|
- Added report back to the edit page
|
||||||
|
- Changed metaeditor icon
|
||||||
|
- Added a button to quickly share your brew to reddit :)
|
||||||
|
- Disabled Partial Page Rendering unless your brew hits 75 pages or longer
|
||||||
|
- The brew renderer will now try and use your first page to judge the page size of each of your brews. This allows you now to set landscape and other weird sizes and everthing should work fine :)
|
||||||
|
- UI on the user page improved (thanks u/PalaNolho)
|
||||||
|
- Fixed lists not breaking across columns (thanks u/tyson-nw)
|
||||||
|
- Added a table of contents snippet (thanks u/tullisar)
|
||||||
|
- Added a multicolumn snippet
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Thursday, 01/12/2016
|
### Thursday, 01/12/2016
|
||||||
- Added in a snippet for a split table
|
- Added in a snippet for a split table
|
||||||
- Added an account nav item to new page
|
- Added an account nav item to new page
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
var React = require('react');
|
const React = require('react');
|
||||||
var _ = require('lodash');
|
const _ = require('lodash');
|
||||||
var cx = require('classnames');
|
const cx = require('classnames');
|
||||||
|
|
||||||
var Markdown = require('naturalcrit/markdown.js');
|
const Markdown = require('naturalcrit/markdown.js');
|
||||||
var ErrorBar = require('./errorBar/errorBar.jsx');
|
const ErrorBar = require('./errorBar/errorBar.jsx');
|
||||||
|
|
||||||
var PAGE_HEIGHT = 1056 + 30;
|
const PAGE_HEIGHT = 1056;
|
||||||
|
const PPR_THRESHOLD = 50;
|
||||||
|
|
||||||
var BrewRenderer = React.createClass({
|
const BrewRenderer = React.createClass({
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
text : '',
|
text : '',
|
||||||
@@ -15,16 +16,23 @@ var BrewRenderer = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
const pages = this.props.text.split('\\page');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
viewablePageNumber: 0,
|
viewablePageNumber: 0,
|
||||||
height : 0,
|
height : 0,
|
||||||
isMounted : false,
|
isMounted : false,
|
||||||
|
|
||||||
|
usePPR : true,
|
||||||
|
|
||||||
|
pages : pages,
|
||||||
|
usePPR : pages.length >= PPR_THRESHOLD,
|
||||||
|
|
||||||
errors : []
|
errors : []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
totalPages : 0,
|
|
||||||
height : 0,
|
height : 0,
|
||||||
|
pageHeight : PAGE_HEIGHT,
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.updateSize();
|
this.updateSize();
|
||||||
@@ -34,7 +42,21 @@ var BrewRenderer = React.createClass({
|
|||||||
window.removeEventListener("resize", this.updateSize);
|
window.removeEventListener("resize", this.updateSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillReceiveProps: function(nextProps) {
|
||||||
|
if(this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight;
|
||||||
|
|
||||||
|
const pages = nextProps.text.split('\\page');
|
||||||
|
this.setState({
|
||||||
|
pages : pages,
|
||||||
|
usePPR : pages.length >= PPR_THRESHOLD
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
updateSize : function() {
|
updateSize : function() {
|
||||||
|
setTimeout(()=>{
|
||||||
|
if(this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight;
|
||||||
|
}, 1);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
height : this.refs.main.parentNode.clientHeight,
|
height : this.refs.main.parentNode.clientHeight,
|
||||||
isMounted : true
|
isMounted : true
|
||||||
@@ -43,12 +65,9 @@ var BrewRenderer = React.createClass({
|
|||||||
|
|
||||||
handleScroll : function(e){
|
handleScroll : function(e){
|
||||||
this.setState({
|
this.setState({
|
||||||
viewablePageNumber : Math.floor(e.target.scrollTop / PAGE_HEIGHT)
|
viewablePageNumber : Math.floor(e.target.scrollTop / this.pageHeight)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//Implement later
|
|
||||||
scrollToPage : function(pageNumber){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldRender : function(pageText, index){
|
shouldRender : function(pageText, index){
|
||||||
if(!this.state.isMounted) return false;
|
if(!this.state.isMounted) return false;
|
||||||
@@ -66,7 +85,15 @@ var BrewRenderer = React.createClass({
|
|||||||
|
|
||||||
renderPageInfo : function(){
|
renderPageInfo : function(){
|
||||||
return <div className='pageInfo'>
|
return <div className='pageInfo'>
|
||||||
{this.state.viewablePageNumber + 1} / {this.totalPages}
|
{this.state.viewablePageNumber + 1} / {this.state.pages.length}
|
||||||
|
</div>
|
||||||
|
},
|
||||||
|
|
||||||
|
renderPPRmsg : function(){
|
||||||
|
if(!this.state.usePPR) return;
|
||||||
|
|
||||||
|
return <div className='ppr_msg'>
|
||||||
|
Partial Page Renderer enabled, because your brew is so large. May effect rendering.
|
||||||
</div>
|
</div>
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -81,15 +108,18 @@ var BrewRenderer = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderPages : function(){
|
renderPages : function(){
|
||||||
var pages = this.props.text.split('\\page');
|
if(this.state.usePPR){
|
||||||
this.totalPages = pages.length;
|
return _.map(this.state.pages, (page, index)=>{
|
||||||
|
if(this.shouldRender(page, index)){
|
||||||
|
return this.renderPage(page, index);
|
||||||
|
}else{
|
||||||
|
return this.renderDummyPage(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return _.map(pages, (page, index)=>{
|
return _.map(this.state.pages, (page, index)=>{
|
||||||
if(this.shouldRender(page, index)){
|
return this.renderPage(page, index);
|
||||||
return this.renderPage(page, index);
|
|
||||||
}else{
|
|
||||||
return this.renderDummyPage(index);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -101,10 +131,11 @@ var BrewRenderer = React.createClass({
|
|||||||
|
|
||||||
<ErrorBar errors={this.props.errors} />
|
<ErrorBar errors={this.props.errors} />
|
||||||
|
|
||||||
<div className='pages'>
|
<div className='pages' ref='pages'>
|
||||||
{this.renderPages()}
|
{this.renderPages()}
|
||||||
</div>
|
</div>
|
||||||
{this.renderPageInfo()}
|
{this.renderPageInfo()}
|
||||||
|
{this.renderPPRmsg()}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,6 +16,17 @@
|
|||||||
font-weight : 800;
|
font-weight : 800;
|
||||||
color : white;
|
color : white;
|
||||||
}
|
}
|
||||||
|
.ppr_msg{
|
||||||
|
position : absolute;
|
||||||
|
left : 0px;
|
||||||
|
bottom : 0;
|
||||||
|
z-index : 1000;
|
||||||
|
padding : 8px 10px;
|
||||||
|
background-color : #333;
|
||||||
|
font-size : 10px;
|
||||||
|
font-weight : 800;
|
||||||
|
color : white;
|
||||||
|
}
|
||||||
.pages{
|
.pages{
|
||||||
margin : 30px 0px;
|
margin : 30px 0px;
|
||||||
&>.phb{
|
&>.phb{
|
||||||
|
|||||||
@@ -82,7 +82,11 @@ const Editor = React.createClass({
|
|||||||
render : function(){
|
render : function(){
|
||||||
return(
|
return(
|
||||||
<div className='editor' ref='main'>
|
<div className='editor' ref='main'>
|
||||||
<SnippetBar onInject={this.handleInject} onToggle={this.handgleToggle} showmeta={this.state.showMetadataEditor} />
|
<SnippetBar
|
||||||
|
brew={this.props.value}
|
||||||
|
onInject={this.handleInject}
|
||||||
|
onToggle={this.handgleToggle}
|
||||||
|
showmeta={this.state.showMetadataEditor} />
|
||||||
{this.renderMetadataEditor()}
|
{this.renderMetadataEditor()}
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
ref='codeEditor'
|
ref='codeEditor'
|
||||||
|
|||||||
@@ -51,6 +51,16 @@ const MetadataEditor = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getRedditLink : function(){
|
||||||
|
const meta = this.props.metadata;
|
||||||
|
const title = `${meta.title} [${meta.systems.join(' ')}]`;
|
||||||
|
const text = `Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out.
|
||||||
|
|
||||||
|
**[Homebrewery Link](http://homebrewery.naturalcrit.com/share/${meta.shareId})**`;
|
||||||
|
|
||||||
|
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title)}&text=${encodeURIComponent(text)}`;
|
||||||
|
},
|
||||||
|
|
||||||
renderSystems : function(){
|
renderSystems : function(){
|
||||||
return _.map(SYSTEMS, (val)=>{
|
return _.map(SYSTEMS, (val)=>{
|
||||||
return <label key={val}>
|
return <label key={val}>
|
||||||
@@ -101,8 +111,22 @@ const MetadataEditor = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderShareToReddit : function(){
|
||||||
|
if(!this.props.metadata.shareId) return;
|
||||||
|
|
||||||
|
return <div className='field reddit'>
|
||||||
|
<label>reddit</label>
|
||||||
|
<div className='value'>
|
||||||
|
<a href={this.getRedditLink()} target='_blank'>
|
||||||
|
<button className='publish'>
|
||||||
|
<i className='fa fa-reddit-alien' /> share to reddit
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
},
|
||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
console.log(this.props.metadata);
|
|
||||||
return <div className='metadataEditor'>
|
return <div className='metadataEditor'>
|
||||||
<div className='field title'>
|
<div className='field title'>
|
||||||
<label>title</label>
|
<label>title</label>
|
||||||
@@ -140,6 +164,8 @@ const MetadataEditor = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{this.renderShareToReddit()}
|
||||||
|
|
||||||
{this.renderDelete()}
|
{this.renderDelete()}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -67,6 +67,11 @@
|
|||||||
.button(@red);
|
.button(@red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.reddit.field .value{
|
||||||
|
button{
|
||||||
|
.button(@purple);
|
||||||
|
}
|
||||||
|
}
|
||||||
.authors.field .value{
|
.authors.field .value{
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
line-height : 1.5em;
|
line-height : 1.5em;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const cx = require('classnames');
|
|||||||
|
|
||||||
const Snippets = require('./snippets/snippets.js');
|
const Snippets = require('./snippets/snippets.js');
|
||||||
|
|
||||||
const execute = function(val){
|
const execute = function(val, brew){
|
||||||
if(_.isFunction(val)) return val();
|
if(_.isFunction(val)) return val(brew);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ const execute = function(val){
|
|||||||
const Snippetbar = React.createClass({
|
const Snippetbar = React.createClass({
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
|
brew : '',
|
||||||
onInject : ()=>{},
|
onInject : ()=>{},
|
||||||
onToggle : ()=>{},
|
onToggle : ()=>{},
|
||||||
showmeta : false
|
showmeta : false
|
||||||
@@ -28,6 +29,7 @@ const Snippetbar = React.createClass({
|
|||||||
renderSnippetGroups : function(){
|
renderSnippetGroups : function(){
|
||||||
return _.map(Snippets, (snippetGroup)=>{
|
return _.map(Snippets, (snippetGroup)=>{
|
||||||
return <SnippetGroup
|
return <SnippetGroup
|
||||||
|
brew={this.props.brew}
|
||||||
groupName={snippetGroup.groupName}
|
groupName={snippetGroup.groupName}
|
||||||
icon={snippetGroup.icon}
|
icon={snippetGroup.icon}
|
||||||
snippets={snippetGroup.snippets}
|
snippets={snippetGroup.snippets}
|
||||||
@@ -42,7 +44,7 @@ const Snippetbar = React.createClass({
|
|||||||
{this.renderSnippetGroups()}
|
{this.renderSnippetGroups()}
|
||||||
<div className={cx('toggleMeta', {selected: this.props.showmeta})}
|
<div className={cx('toggleMeta', {selected: this.props.showmeta})}
|
||||||
onClick={this.props.onToggle}>
|
onClick={this.props.onToggle}>
|
||||||
<i className='fa fa-database' />
|
<i className='fa fa-info-circle' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -58,6 +60,7 @@ module.exports = Snippetbar;
|
|||||||
const SnippetGroup = React.createClass({
|
const SnippetGroup = React.createClass({
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
|
brew : '',
|
||||||
groupName : '',
|
groupName : '',
|
||||||
icon : 'fa-rocket',
|
icon : 'fa-rocket',
|
||||||
snippets : [],
|
snippets : [],
|
||||||
@@ -65,7 +68,7 @@ const SnippetGroup = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
handleSnippetClick : function(snippet){
|
handleSnippetClick : function(snippet){
|
||||||
this.props.onSnippetClick(execute(snippet.gen));
|
this.props.onSnippetClick(execute(snippet.gen, this.props.brew));
|
||||||
},
|
},
|
||||||
renderSnippets : function(){
|
renderSnippets : function(){
|
||||||
return _.map(this.props.snippets, (snippet)=>{
|
return _.map(this.props.snippets, (snippet)=>{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ var MonsterBlockGen = require('./monsterblock.gen.js');
|
|||||||
var ClassFeatureGen = require('./classfeature.gen.js');
|
var ClassFeatureGen = require('./classfeature.gen.js');
|
||||||
var FullClassGen = require('./fullclass.gen.js');
|
var FullClassGen = require('./fullclass.gen.js');
|
||||||
var CoverPageGen = require('./coverpage.gen.js');
|
var CoverPageGen = require('./coverpage.gen.js');
|
||||||
|
var TableOfContentsGen = require('./tableOfContents.gen.js');
|
||||||
|
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
@@ -70,6 +71,12 @@ module.exports = [
|
|||||||
gen : "[Click here](#p3) to go to page 3\n"
|
gen : "[Click here](#p3) to go to page 3\n"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name : "Table of Contents",
|
||||||
|
icon : 'fa-book',
|
||||||
|
gen : TableOfContentsGen
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const getTOC = (pages) => {
|
||||||
|
const add1 = (title, page)=>{
|
||||||
|
res.push({
|
||||||
|
title : title,
|
||||||
|
page : page + 1,
|
||||||
|
children : []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const add2 = (title, page)=>{
|
||||||
|
if(!_.last(res)) add1('', page);
|
||||||
|
_.last(res).children.push({
|
||||||
|
title : title,
|
||||||
|
page : page + 1,
|
||||||
|
children : []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const add3 = (title, page)=>{
|
||||||
|
if(!_.last(res)) add1('', page);
|
||||||
|
if(!_.last(_.last(res).children)) add2('', page);
|
||||||
|
_.last(_.last(res).children).children.push({
|
||||||
|
title : title,
|
||||||
|
page : page + 1,
|
||||||
|
children : []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = [];
|
||||||
|
_.each(pages, (page, pageNum)=>{
|
||||||
|
const lines = page.split('\n');
|
||||||
|
_.each(lines, (line) => {
|
||||||
|
if(_.startsWith(line, '# ')){
|
||||||
|
const title = line.replace('# ', '');
|
||||||
|
add1(title, pageNum)
|
||||||
|
}
|
||||||
|
if(_.startsWith(line, '## ')){
|
||||||
|
const title = line.replace('## ', '');
|
||||||
|
add2(title, pageNum);
|
||||||
|
}
|
||||||
|
if(_.startsWith(line, '### ')){
|
||||||
|
const title = line.replace('### ', '');
|
||||||
|
add3(title, pageNum);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function(brew){
|
||||||
|
const pages = brew.split('\\page');
|
||||||
|
const TOC = getTOC(pages);
|
||||||
|
const markdown = _.reduce(TOC, (r, g1, idx1)=>{
|
||||||
|
r.push(`- **[${idx1 + 1} ${g1.title}](#p${g1.page})**`)
|
||||||
|
if(g1.children.length){
|
||||||
|
_.each(g1.children, (g2, idx2) => {
|
||||||
|
r.push(` - [${idx1 + 1}.${idx2 + 1} ${g2.title}](#p${g2.page})`);
|
||||||
|
if(g2.children.length){
|
||||||
|
_.each(g2.children, (g3, idx3) => {
|
||||||
|
r.push(` - [${idx1 + 1}.${idx2 + 1}.${idx3 + 1} ${g3.title}](#p${g3.page})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}, []).join('\n');
|
||||||
|
|
||||||
|
return `<div class='toc'>
|
||||||
|
##### Table Of Contents
|
||||||
|
${markdown}
|
||||||
|
</div>\n`;
|
||||||
|
}
|
||||||
@@ -193,6 +193,7 @@ const EditPage = React.createClass({
|
|||||||
<Nav.section>
|
<Nav.section>
|
||||||
{this.renderSaveButton()}
|
{this.renderSaveButton()}
|
||||||
{/*<RecentlyEdited brew={this.props.brew} />*/}
|
{/*<RecentlyEdited brew={this.props.brew} />*/}
|
||||||
|
<ReportIssue />
|
||||||
<Nav.item newTab={true} href={'/share/' + this.props.brew.shareId} color='teal' icon='fa-share-alt'>
|
<Nav.item newTab={true} href={'/share/' + this.props.brew.shareId} color='teal' icon='fa-share-alt'>
|
||||||
Share
|
Share
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const cx = require('classnames');
|
|||||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||||
const Navbar = require('../../navbar/navbar.jsx');
|
const Navbar = require('../../navbar/navbar.jsx');
|
||||||
const PrintLink = require('../../navbar/print.navitem.jsx');
|
const PrintLink = require('../../navbar/print.navitem.jsx');
|
||||||
|
const ReportIssue = require('../../navbar/issue.navitem.jsx');
|
||||||
//const RecentlyViewed = require('../../navbar/recent.navitem.jsx').viewed;
|
//const RecentlyViewed = require('../../navbar/recent.navitem.jsx').viewed;
|
||||||
const Account = require('../../navbar/account.navitem.jsx');
|
const Account = require('../../navbar/account.navitem.jsx');
|
||||||
|
|
||||||
@@ -34,10 +35,12 @@ const SharePage = React.createClass({
|
|||||||
},
|
},
|
||||||
handleControlKeys : function(e){
|
handleControlKeys : function(e){
|
||||||
if(!(e.ctrlKey || e.metaKey)) return;
|
if(!(e.ctrlKey || e.metaKey)) return;
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
const P_KEY = 80;
|
const P_KEY = 80;
|
||||||
if(e.keyCode == P_KEY) window.open(`/print/${this.props.brew.shareId}?dialog=true`, '_blank').focus();
|
if(e.keyCode == P_KEY){
|
||||||
|
window.open(`/print/${this.props.brew.shareId}?dialog=true`, '_blank').focus();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
@@ -48,6 +51,7 @@ const SharePage = React.createClass({
|
|||||||
</Nav.section>
|
</Nav.section>
|
||||||
|
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
|
<ReportIssue />
|
||||||
{/*<RecentlyViewed brew={this.props.brew} />*/}
|
{/*<RecentlyViewed brew={this.props.brew} />*/}
|
||||||
<PrintLink shareId={this.props.brew.shareId} />
|
<PrintLink shareId={this.props.brew.shareId} />
|
||||||
<Nav.item href={'/source/' + this.props.brew.shareId} color='teal' icon='fa-code'>
|
<Nav.item href={'/source/' + this.props.brew.shareId} color='teal' icon='fa-code'>
|
||||||
|
|||||||
@@ -15,23 +15,39 @@ const BrewItem = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderEditLink: function(){
|
||||||
|
if(!this.props.brew.editId) return;
|
||||||
|
|
||||||
|
return <a href={`/edit/${this.props.brew.editId}`} target='_blank'>
|
||||||
|
<i className='fa fa-pencil' />
|
||||||
|
</a>
|
||||||
|
},
|
||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
const brew = this.props.brew;
|
const brew = this.props.brew;
|
||||||
return <div className='brewItem'title={brew.description}>
|
return <div className='brewItem'>
|
||||||
<h4>{brew.title}</h4>
|
<h2>{brew.title}</h2>
|
||||||
<p className='description' ><em>{brew.description}</em></p>
|
<p className='description' >{brew.description}</p>
|
||||||
<hr />
|
<hr />
|
||||||
<ul>
|
|
||||||
<li><strong>Authors: </strong> {brew.authors.join(', ')}</li>
|
|
||||||
<li>
|
|
||||||
<strong>Last updated: </strong>
|
|
||||||
{moment(brew.updatedAt).fromNow()}
|
|
||||||
</li>
|
|
||||||
<li><strong>Views: </strong> {brew.views} </li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href={`/share/${brew.shareId}`} target='_blank'>Share link</a>
|
<div className='info'>
|
||||||
{(!!brew.editId ? <a href={`/edit/${brew.editId}`} target='_blank'>Edit link</a> : null)}
|
<span>
|
||||||
|
<i className='fa fa-user' /> {brew.authors.join(', ')}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<i className='fa fa-eye' /> {brew.views}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<i className='fa fa-refresh' /> {moment(brew.updatedAt).fromNow()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='links'>
|
||||||
|
<a href={`/share/${brew.shareId}`} target='_blank'>
|
||||||
|
<i className='fa fa-share-alt' />
|
||||||
|
</a>
|
||||||
|
{this.renderEditLink()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,60 @@
|
|||||||
|
|
||||||
.brewItem{
|
.brewItem{
|
||||||
|
position : relative;
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
vertical-align : top;
|
vertical-align : top;
|
||||||
width : 25%;
|
box-sizing : border-box;
|
||||||
|
box-sizing : border-box;
|
||||||
|
overflow : hidden;
|
||||||
|
width : 48%;
|
||||||
|
margin-right : 15px;
|
||||||
margin-bottom : 15px;
|
margin-bottom : 15px;
|
||||||
|
padding : 5px 15px 5px 8px;
|
||||||
|
padding-right : 15px;
|
||||||
|
border : 1px solid #c9ad6a;
|
||||||
|
border-radius : 5px;
|
||||||
-webkit-column-break-inside : avoid;
|
-webkit-column-break-inside : avoid;
|
||||||
page-break-inside : avoid;
|
page-break-inside : avoid;
|
||||||
break-inside : avoid;
|
break-inside : avoid;
|
||||||
p.description{
|
h4{
|
||||||
overflow : hidden;
|
margin-bottom : 5px;
|
||||||
width : 90%;
|
font-size : 2.2em;
|
||||||
text-overflow : ellipsis;
|
|
||||||
white-space : nowrap;
|
|
||||||
}
|
}
|
||||||
a{
|
.info{
|
||||||
margin-right : 10px;
|
font-family : ScalySans;
|
||||||
|
font-size : 1.2em;
|
||||||
|
&>span{
|
||||||
|
margin-right : 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.links{
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:nth-child(2n + 1){
|
||||||
|
margin-right : 0px;
|
||||||
|
}
|
||||||
|
.links{
|
||||||
|
.animate(opacity);
|
||||||
|
position : absolute;
|
||||||
|
top : 0px;
|
||||||
|
right : 0px;
|
||||||
|
height : 100%;
|
||||||
|
width : 2em;
|
||||||
|
opacity : 0;
|
||||||
|
background-color : fade(black, 60%);
|
||||||
|
text-align : center;
|
||||||
|
a{
|
||||||
|
.animate(opacity);
|
||||||
|
display : block;
|
||||||
|
margin : 8px 0px;
|
||||||
|
opacity : 0.6;
|
||||||
|
font-size : 1.3em;
|
||||||
|
color : white;
|
||||||
|
&:hover{
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,11 @@ const Account = require('../../navbar/account.navitem.jsx');
|
|||||||
const BrewItem = require('./brewItem/brewItem.jsx');
|
const BrewItem = require('./brewItem/brewItem.jsx');
|
||||||
|
|
||||||
const brew = {
|
const brew = {
|
||||||
title : 'test',
|
title : 'SUPER Long title woah now',
|
||||||
authors : []
|
authors : []
|
||||||
}
|
}
|
||||||
|
|
||||||
//const BREWS = _.times(25, ()=>{ return brew});
|
const BREWS = _.times(25, ()=>{ return brew});
|
||||||
|
|
||||||
|
|
||||||
const UserPage = React.createClass({
|
const UserPage = React.createClass({
|
||||||
@@ -26,9 +26,11 @@ const UserPage = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderBrews : function(brews){
|
renderBrews : function(brews){
|
||||||
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>
|
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>;
|
||||||
|
|
||||||
return _.map(brews, (brew, idx) => {
|
const sortedBrews = _.sortBy(brews, (brew)=>{ return brew.title; });
|
||||||
|
|
||||||
|
return _.map(sortedBrews, (brew, idx) => {
|
||||||
return <BrewItem brew={brew} key={idx}/>
|
return <BrewItem brew={brew} key={idx}/>
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
.phb{
|
.phb{
|
||||||
.noColumns();
|
.noColumns();
|
||||||
height : auto;
|
height : auto;
|
||||||
min-height : 350px;
|
min-height : 279.4mm;
|
||||||
margin : 20px auto;
|
margin : 20px auto;
|
||||||
&::after{
|
&::after{
|
||||||
display : none;
|
display : none;
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
font-size : 1.3em;
|
font-size : 1.3em;
|
||||||
font-style : italic;
|
font-style : italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ body {
|
|||||||
counter-reset : phb-page-numbers;
|
counter-reset : phb-page-numbers;
|
||||||
}
|
}
|
||||||
*{
|
*{
|
||||||
-webkit-print-color-adjust: exact;
|
-webkit-print-color-adjust : exact;
|
||||||
}
|
}
|
||||||
.useSansSerif(){
|
.useSansSerif(){
|
||||||
font-family : ScalySans;
|
font-family : ScalySans;
|
||||||
@@ -332,7 +332,7 @@ body {
|
|||||||
-moz-column-break-after : always;
|
-moz-column-break-after : always;
|
||||||
}
|
}
|
||||||
//Avoid breaking up
|
//Avoid breaking up
|
||||||
p,ul,blockquote,table{
|
p,blockquote,table{
|
||||||
z-index : 15;
|
z-index : 15;
|
||||||
-webkit-column-break-inside : avoid;
|
-webkit-column-break-inside : avoid;
|
||||||
column-break-inside : avoid;
|
column-break-inside : avoid;
|
||||||
@@ -351,6 +351,10 @@ body {
|
|||||||
margin-bottom : 0px;
|
margin-bottom : 0px;
|
||||||
margin-left : 1.5em;
|
margin-left : 1.5em;
|
||||||
}
|
}
|
||||||
|
li{
|
||||||
|
-webkit-column-break-inside : avoid;
|
||||||
|
column-break-inside : avoid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//*****************************
|
//*****************************
|
||||||
// * SPELL LIST
|
// * SPELL LIST
|
||||||
@@ -445,4 +449,25 @@ body {
|
|||||||
}
|
}
|
||||||
.phb pre+.descriptive{
|
.phb pre+.descriptive{
|
||||||
margin-top : 8px;
|
margin-top : 8px;
|
||||||
|
}
|
||||||
|
//*****************************
|
||||||
|
// * TABLE OF CONTENTS
|
||||||
|
// *****************************/
|
||||||
|
.phb .toc{
|
||||||
|
-webkit-column-break-inside : avoid;
|
||||||
|
column-break-inside : avoid;
|
||||||
|
a{
|
||||||
|
color : black;
|
||||||
|
text-decoration : none;
|
||||||
|
&:hover{
|
||||||
|
text-decoration : underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ul{
|
||||||
|
padding-left : 0;
|
||||||
|
list-style-type : none;
|
||||||
|
}
|
||||||
|
&>ul>li{
|
||||||
|
margin-bottom : 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "homebrewery",
|
"name": "homebrewery",
|
||||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||||
"version": "2.5.2",
|
"version": "2.6.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node_modules/.bin/gulp prod",
|
"build": "node_modules/.bin/gulp prod",
|
||||||
"watch": "node_modules/.bin/gulp",
|
"watch": "node_modules/.bin/gulp",
|
||||||
|
|||||||
@@ -518,7 +518,6 @@ body {
|
|||||||
-moz-column-break-after: always;
|
-moz-column-break-after: always;
|
||||||
}
|
}
|
||||||
.phb p,
|
.phb p,
|
||||||
.phb ul,
|
|
||||||
.phb blockquote,
|
.phb blockquote,
|
||||||
.phb table {
|
.phb table {
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
@@ -540,6 +539,10 @@ body {
|
|||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
}
|
}
|
||||||
|
.phb li {
|
||||||
|
-webkit-column-break-inside: avoid;
|
||||||
|
column-break-inside: avoid;
|
||||||
|
}
|
||||||
.phb .spellList {
|
.phb .spellList {
|
||||||
font-family: ScalySans;
|
font-family: ScalySans;
|
||||||
column-count: 4;
|
column-count: 4;
|
||||||
@@ -627,3 +630,21 @@ body {
|
|||||||
.phb pre + .descriptive {
|
.phb pre + .descriptive {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
.phb .toc {
|
||||||
|
-webkit-column-break-inside: avoid;
|
||||||
|
column-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.phb .toc a {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.phb .toc a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.phb .toc ul {
|
||||||
|
padding-left: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
.phb .toc > ul > li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,13 +50,15 @@ var Nav = {
|
|||||||
var icon;
|
var icon;
|
||||||
if(this.props.icon) icon = <i className={'fa ' + this.props.icon} />;
|
if(this.props.icon) icon = <i className={'fa ' + this.props.icon} />;
|
||||||
|
|
||||||
|
const props = _.omit(this.props, ['newTab']);
|
||||||
|
|
||||||
if(this.props.href){
|
if(this.props.href){
|
||||||
return <a {...this.props} className={classes} target={this.props.newTab ? '_blank' : '_self'} >
|
return <a {...props} className={classes} target={this.props.newTab ? '_blank' : '_self'} >
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
{icon}
|
{icon}
|
||||||
</a>
|
</a>
|
||||||
}else{
|
}else{
|
||||||
return <div {...this.props} className={classes} onClick={this.handleClick} >
|
return <div {...props} className={classes} onClick={this.handleClick} >
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
{icon}
|
{icon}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user