mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-26 22:32:45 +00:00
Merge branch 'master' into update-Marked-renderer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,4 +10,3 @@ config/local.*
|
||||
todo.md
|
||||
startDB.bat
|
||||
startMViewer.bat
|
||||
*.xlsx
|
||||
|
||||
17
Dockerfile
17
Dockerfile
@@ -1,14 +1,19 @@
|
||||
FROM node:8
|
||||
|
||||
ENV NODE_ENV=docker
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Bundle app source
|
||||
# Copy package.json into the image, then run yarn install
|
||||
# This improves caching so we don't have to download the dependencies every time the code changes
|
||||
COPY package.json ./
|
||||
# --ignore-scripts tells yarn not to run postbuild. We run it explicitly later
|
||||
RUN yarn install --ignore-scripts
|
||||
|
||||
# Bundle app source and build application
|
||||
COPY . .
|
||||
|
||||
ENV NODE_ENV=docker
|
||||
|
||||
RUN yarn
|
||||
RUN yarn build
|
||||
|
||||
EXPOSE 8000
|
||||
CMD [ "yarn", "start" ]
|
||||
CMD [ "yarn", "start" ]
|
||||
|
||||
12
README.DOCKER.md
Normal file
12
README.DOCKER.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Running Homebrewery via Docker
|
||||
|
||||
The repo includes a Dockerfile and a docker-compose.yml file.
|
||||
|
||||
To run the application via docker-compose.yml:
|
||||
`docker-compose up -d`
|
||||
|
||||
To stop the application:
|
||||
`docker-compose down`
|
||||
|
||||
To stop the application and remove all data:
|
||||
`docker-compose down -v`
|
||||
@@ -29,6 +29,10 @@ Fourth, you will need to install the program and run it using the two commands:
|
||||
|
||||
You should now be able to go to [http://localhost:8000](http://localhost:8000) in your browser and use the Homebrewery offline.
|
||||
|
||||
### Running the application via Docker
|
||||
|
||||
Please see the docs here: [README.DOCKER.md](./README.DOCKER.md)
|
||||
|
||||
### Standalone PHB Stylesheet
|
||||
If you just want the stylesheet that is generated to make pages look like they are from the Player's Handbook, you will find it in the [phb.standalone.css](./phb.standalone.css) file.
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# changelog
|
||||
|
||||
### Wednesday, 11/03/2020 - v2.8.2
|
||||
- Fixed delete button removing everyone's copy for brews with multiple authors
|
||||
- Compressed homebrew text in database
|
||||
|
||||
### Monday, 26/11/2018 - v2.8.1
|
||||
- Fixed some SSL issues with images in the example page so they appear now
|
||||
- Fixed duplicate scrollbars in Edit Page
|
||||
|
||||
@@ -50,7 +50,7 @@ const MetadataEditor = createClass({
|
||||
if(!confirm('Are you REALLY sure? You will lose editor access to this document.')) return;
|
||||
}
|
||||
|
||||
request.get(`/api/remove/${this.props.metadata.editId}`)
|
||||
request.delete(`/api/${this.props.metadata.editId}`)
|
||||
.send()
|
||||
.end(function(err, res){
|
||||
window.location.href = '/';
|
||||
|
||||
@@ -3,6 +3,7 @@ const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const cx = require('classnames');
|
||||
const request = require('superagent');
|
||||
const Meta = require('vitreum/meta');
|
||||
|
||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const Navbar = require('../../navbar/navbar.jsx');
|
||||
@@ -134,7 +135,7 @@ const EditPage = createClass({
|
||||
}));
|
||||
|
||||
request
|
||||
.put(`/api/update/${this.props.brew.editId}`)
|
||||
.put(`/api/${this.props.brew.editId}`)
|
||||
.send(this.state.brew)
|
||||
.end((err, res)=>{
|
||||
if(err){
|
||||
@@ -202,6 +203,7 @@ const EditPage = createClass({
|
||||
|
||||
render : function(){
|
||||
return <div className='editPage page'>
|
||||
<Meta name='robots' content='noindex, nofollow' />
|
||||
{this.renderNavbar()}
|
||||
|
||||
<div className='content'>
|
||||
|
||||
@@ -3,6 +3,7 @@ const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const cx = require('classnames');
|
||||
const request = require('superagent');
|
||||
const Meta = require('vitreum/meta');
|
||||
|
||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const Navbar = require('../../navbar/navbar.jsx');
|
||||
@@ -72,6 +73,7 @@ const HomePage = createClass({
|
||||
|
||||
render : function(){
|
||||
return <div className='homePage page'>
|
||||
<Meta name='google-site-verification' content='NwnAQSSJZzAT7N-p5MY6ydQ7Njm67dtbu73ZSyE5Fy4' />
|
||||
{this.renderNavbar()}
|
||||
|
||||
<div className='content'>
|
||||
|
||||
@@ -2,6 +2,7 @@ const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const cx = require('classnames');
|
||||
const Meta = require('vitreum/meta');
|
||||
const Markdown = require('naturalcrit/markdown.js');
|
||||
|
||||
const PrintPage = createClass({
|
||||
@@ -42,6 +43,7 @@ const PrintPage = createClass({
|
||||
|
||||
render : function(){
|
||||
return <div>
|
||||
<Meta name='robots' content='noindex, nofollow' />
|
||||
{this.renderPages()}
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const cx = require('classnames');
|
||||
const Meta = require('vitreum/meta');
|
||||
|
||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const Navbar = require('../../navbar/navbar.jsx');
|
||||
@@ -45,6 +46,7 @@ const SharePage = createClass({
|
||||
|
||||
render : function(){
|
||||
return <div className='sharePage page'>
|
||||
<Meta name='robots' content='noindex, nofollow' />
|
||||
<Navbar>
|
||||
<Nav.section>
|
||||
<Nav.item className='brewTitle'>{this.props.brew.title}</Nav.item>
|
||||
|
||||
@@ -26,7 +26,7 @@ const BrewItem = createClass({
|
||||
if(!confirm('Are you REALLY sure? You will lose editor access to this document.')) return;
|
||||
}
|
||||
|
||||
request.get(`/api/remove/${this.props.brew.editId}`)
|
||||
request.delete(`/api/${this.props.brew.editId}`)
|
||||
.send()
|
||||
.end(function(err, res){
|
||||
location.reload();
|
||||
|
||||
@@ -42,15 +42,6 @@ const UserPage = createClass({
|
||||
});
|
||||
},
|
||||
|
||||
renderPrivateBrews : function(privateBrews){
|
||||
if(!privateBrews || !privateBrews.length) return;
|
||||
|
||||
return [
|
||||
<h1>{this.props.username}'s unpublished brews</h1>,
|
||||
this.renderBrews(privateBrews)
|
||||
];
|
||||
},
|
||||
|
||||
render : function(){
|
||||
const brews = this.getSortedBrews();
|
||||
|
||||
@@ -64,9 +55,14 @@ const UserPage = createClass({
|
||||
|
||||
<div className='content'>
|
||||
<div className='phb'>
|
||||
<h1>{this.props.username}'s brews</h1>
|
||||
{this.renderBrews(brews.published)}
|
||||
{this.renderPrivateBrews(brews.private)}
|
||||
<div>
|
||||
<h1>{this.props.username}'s brews</h1>
|
||||
{this.renderBrews(brews.published)}
|
||||
</div>
|
||||
<div>
|
||||
<h1>{this.props.username}'s unpublished brews</h1>
|
||||
{this.renderBrews(brews.private)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.phb{
|
||||
.noColumns();
|
||||
height : auto;
|
||||
min-height : 279.4mm;
|
||||
min-height : 279.4mm;
|
||||
margin : 20px auto;
|
||||
&::after{
|
||||
display : none;
|
||||
@@ -30,4 +30,4 @@
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3078
package-lock.json
generated
3078
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -40,19 +40,19 @@
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"classnames": "^2.2.6",
|
||||
"codemirror": "^5.52.0",
|
||||
"cookie-parser": "^1.4.4",
|
||||
"codemirror": "^5.52.2",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"create-react-class": "^15.6.3",
|
||||
"express": "^4.17.1",
|
||||
"jwt-simple": "^0.5.6",
|
||||
"lodash": "^4.17.15",
|
||||
"marked": "^0.8.2",
|
||||
"moment": "^2.24.0",
|
||||
"mongoose": "^5.9.2",
|
||||
"mongoose": "^5.9.9",
|
||||
"nconf": "^0.10.0",
|
||||
"pico-router": "^2.1.0",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"shortid": "^2.2.15",
|
||||
"superagent": "^5.2.2",
|
||||
"vitreum": "^4.10.1"
|
||||
|
||||
5
robots.txt
Normal file
5
robots.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
# Disallow crawling brew edit and share pages
|
||||
User-agent: *
|
||||
Disallow: /edit/
|
||||
Disallow: /share/
|
||||
Disallow: /print/
|
||||
13
server.js
13
server.js
@@ -44,9 +44,14 @@ const HomebrewModel = require('./server/homebrew.model.js').model;
|
||||
const welcomeText = require('fs').readFileSync('./client/homebrew/pages/homePage/welcome_msg.md', 'utf8');
|
||||
const changelogText = require('fs').readFileSync('./changelog.md', 'utf8');
|
||||
|
||||
String.prototype.replaceAll = function(s, r){return this.split(s).join(r);};
|
||||
|
||||
//Robots.txt
|
||||
app.get('/robots.txt', (req, res)=>{
|
||||
return res.sendFile(`${__dirname}/robots.txt`);
|
||||
});
|
||||
|
||||
//Source page
|
||||
String.prototype.replaceAll = function(s, r){return this.split(s).join(r);};
|
||||
app.get('/source/:id', (req, res)=>{
|
||||
HomebrewModel.get({ shareId: req.params.id })
|
||||
.then((brew)=>{
|
||||
@@ -59,7 +64,7 @@ app.get('/source/:id', (req, res)=>{
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//User Page
|
||||
app.get('/user/:username', (req, res, next)=>{
|
||||
const fullAccess = req.account && (req.account.username == req.params.username);
|
||||
HomebrewModel.getByUser(req.params.username, fullAccess)
|
||||
@@ -72,7 +77,7 @@ app.get('/user/:username', (req, res, next)=>{
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//Edit Page
|
||||
app.get('/edit/:id', (req, res, next)=>{
|
||||
HomebrewModel.get({ editId: req.params.id })
|
||||
.then((brew)=>{
|
||||
@@ -115,7 +120,7 @@ app.get('/print/:id', (req, res, next)=>{
|
||||
});
|
||||
|
||||
|
||||
//Render Page
|
||||
//Render the page
|
||||
const render = require('vitreum/steps/render');
|
||||
const templateFn = require('./client/template.js');
|
||||
app.use((req, res)=>{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = (req, res, next)=>{
|
||||
if(process.env.NODE_ENV === 'local') return next();
|
||||
if(process.env.NODE_ENV === 'local' || process.env.NODE_ENV === 'docker') return next();
|
||||
if(req.header('x-forwarded-proto') !== 'https') {
|
||||
return res.redirect(302, `https://${req.get('Host')}${req.url}`);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ const HomebrewModel = require('./homebrew.model.js').model;
|
||||
const router = require('express').Router();
|
||||
const zlib = require('zlib');
|
||||
|
||||
// const getTopBrews = (cb)=>{
|
||||
// const getTopBrews = (cb) => {
|
||||
// HomebrewModel.find().sort({ views: -1 }).limit(5).exec(function(err, brews) {
|
||||
// cb(brews);
|
||||
// });
|
||||
@@ -11,53 +11,53 @@ const zlib = require('zlib');
|
||||
|
||||
const getGoodBrewTitle = (text)=>{
|
||||
const titlePos = text.indexOf('# ');
|
||||
if(titlePos !== -1){
|
||||
if(titlePos !== -1) {
|
||||
const ending = text.indexOf('\n', titlePos);
|
||||
return text.substring(titlePos + 2, ending);
|
||||
} else {
|
||||
return _.find(text.split('\n'), (line)=>{
|
||||
return line;
|
||||
});
|
||||
return _.find(text.split('\n'), (line)=>line);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
router.post('/api', (req, res)=>{
|
||||
|
||||
let authors = [];
|
||||
if(req.account) authors = [req.account.username];
|
||||
const newBrew = (req, res)=>{
|
||||
const authors = (req.account) ? [req.account.username] : [];
|
||||
|
||||
const newHomebrew = new HomebrewModel(_.merge({},
|
||||
req.body,
|
||||
{ authors: authors }
|
||||
));
|
||||
|
||||
if(!newHomebrew.title){
|
||||
if(!newHomebrew.title) {
|
||||
newHomebrew.title = getGoodBrewTitle(newHomebrew.text);
|
||||
}
|
||||
|
||||
newHomebrew.textBin = zlib.deflateRawSync(newHomebrew.text); // Compress brew text to binary before saving
|
||||
newHomebrew.text = undefined; // Delete the non-binary text field since it's not needed anymore
|
||||
// Compress brew text to binary before saving
|
||||
newHomebrew.textBin = zlib.deflateRawSync(newHomebrew.text);
|
||||
// Delete the non-binary text field since it's not needed anymore
|
||||
newHomebrew.text = undefined;
|
||||
|
||||
newHomebrew.save((err, obj)=>{
|
||||
if(err){
|
||||
if(err) {
|
||||
console.error(err, err.toString(), err.stack);
|
||||
return res.status(500).send(`Error while creating new brew, ${err.toString()}`);
|
||||
}
|
||||
return res.json(obj);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
router.put('/api/update/:id', (req, res)=>{
|
||||
const updateBrew = (req, res)=>{
|
||||
HomebrewModel.get({ editId: req.params.id })
|
||||
.then((brew)=>{
|
||||
brew = _.merge(brew, req.body);
|
||||
brew.textBin = zlib.deflateRawSync(req.body.text); // Compress brew text to binary before saving
|
||||
brew.text = undefined; // Delete the non-binary text field since it's not needed anymore
|
||||
// Compress brew text to binary before saving
|
||||
brew.textBin = zlib.deflateRawSync(req.body.text);
|
||||
// Delete the non-binary text field since it's not needed anymore
|
||||
brew.text = undefined;
|
||||
brew.updatedAt = new Date();
|
||||
|
||||
if(req.account) brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
|
||||
if(req.account) {
|
||||
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
|
||||
}
|
||||
|
||||
brew.markModified('authors');
|
||||
brew.markModified('systems');
|
||||
@@ -68,62 +68,63 @@ router.put('/api/update/:id', (req, res)=>{
|
||||
});
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
return res.status(500).send('Error while saving');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
router.get('/api/remove/:id', (req, res)=>{
|
||||
const deleteBrew = (req, res)=>{
|
||||
HomebrewModel.find({ editId: req.params.id }, (err, objs)=>{
|
||||
if(!objs.length || err) return res.status(404).send('Can not find homebrew with that id');
|
||||
if(!objs.length || err) {
|
||||
return res.status(404).send('Can not find homebrew with that id');
|
||||
}
|
||||
|
||||
const brew = objs[0];
|
||||
|
||||
// Remove current user as author
|
||||
if(req.account){
|
||||
if(req.account) {
|
||||
// Remove current user as author
|
||||
brew.authors = _.pull(brew.authors, req.account.username);
|
||||
brew.markModified('authors');
|
||||
}
|
||||
|
||||
// Delete brew if there are no authors left
|
||||
if(!brew.authors.length)
|
||||
if(brew.authors.length === 0) {
|
||||
// Delete brew if there are no authors left
|
||||
brew.remove((err)=>{
|
||||
if(err) return res.status(500).send('Error while removing');
|
||||
return res.status(200).send();
|
||||
});
|
||||
// Otherwise, save the brew with updated author list
|
||||
else
|
||||
} else {
|
||||
// Otherwise, save the brew with updated author list
|
||||
brew.save((err, savedBrew)=>{
|
||||
if(err) throw err;
|
||||
return res.status(200).send(savedBrew);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
router.post('/api', newBrew);
|
||||
router.put('/api/:id', updateBrew);
|
||||
router.put('/api/update/:id', updateBrew);
|
||||
router.delete('/api/:id', deleteBrew);
|
||||
router.get('/api/remove/:id', deleteBrew);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
module.exports = function(app){
|
||||
|
||||
module.exports = function(app) {
|
||||
app;
|
||||
|
||||
|
||||
|
||||
|
||||
app.get('/api/search', mw.adminOnly, function(req, res){
|
||||
|
||||
app.get('/api/search', mw.adminOnly, function(req, res) {
|
||||
var page = req.query.page || 0;
|
||||
var count = req.query.count || 20;
|
||||
|
||||
var query = {};
|
||||
if(req.query && req.query.id){
|
||||
if (req.query && req.query.id) {
|
||||
query = {
|
||||
"$or" : [{
|
||||
"$or": [{
|
||||
editId : req.query.id
|
||||
},{
|
||||
}, {
|
||||
shareId : req.query.id
|
||||
}]
|
||||
};
|
||||
@@ -134,21 +135,17 @@ module.exports = function(app){
|
||||
}, {
|
||||
skip: page*count,
|
||||
limit: count*1
|
||||
}, function(err, objs){
|
||||
if(err) console.log(err);
|
||||
}, function(err, objs) {
|
||||
if (err) console.error(err);
|
||||
return res.json({
|
||||
page : page,
|
||||
count : count,
|
||||
total : homebrewTotal,
|
||||
brews : objs
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
return app;
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user