mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-23 16:33:05 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9a9804517 | ||
|
|
0bde44ec2f | ||
|
|
13ad179a1b | ||
|
|
b72acd9e59 | ||
|
|
d0a1ef9571 | ||
|
|
d1f049871f | ||
|
|
070184b309 | ||
|
|
cbb41676e0 | ||
|
|
81130dd514 | ||
|
|
61d3edca17 | ||
|
|
248b56a706 | ||
|
|
90f8d1d6da | ||
|
|
8f08b71475 | ||
|
|
cc6527029c | ||
|
|
8a110567fc | ||
|
|
4e2f6b1d26 | ||
|
|
208593d203 | ||
|
|
99019be152 | ||
|
|
fa73e1707d | ||
|
|
d7de2e3d21 | ||
|
|
903ff4fd09 | ||
|
|
feaabacc94 | ||
|
|
bc0846c190 | ||
|
|
ecdcaadfa9 | ||
|
|
db2478f73d | ||
|
|
5d6a7e692f | ||
|
|
0fbeca1536 | ||
|
|
31d58f9075 | ||
|
|
89e6bada56 | ||
|
|
fec1766e26 | ||
|
|
f26e3d6cd1 | ||
|
|
13b43e8902 | ||
|
|
2e305d5636 | ||
|
|
f9711de634 | ||
|
|
2c6779bb1c | ||
|
|
0867b142da |
17
changelog.md
17
changelog.md
@@ -44,6 +44,23 @@ pre {
|
||||
## changelog
|
||||
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
||||
|
||||
### Saturday 10/12/2022 - v3.4.2
|
||||
{{taskList
|
||||
|
||||
##### Jeddai
|
||||
|
||||
* [x] Fix broken tags editor
|
||||
|
||||
* [x] Reduce server load to fix some saving issues
|
||||
|
||||
Fixes issues [#2322](https://github.com/naturalcrit/homebrewery/issues/2322)
|
||||
|
||||
##### Gazook
|
||||
|
||||
* [x] Account page help link for Google Drive errors
|
||||
|
||||
Fixes issues [#2520](https://github.com/naturalcrit/homebrewery/issues/2520)
|
||||
}}
|
||||
|
||||
### Monday 05/12/2022 - v3.4.1
|
||||
{{taskList
|
||||
|
||||
@@ -139,10 +139,10 @@ const Editor = createClass({
|
||||
|
||||
// Highlight injectors {style}
|
||||
if(line.includes('{') && line.includes('}')){
|
||||
const regex = /(?<!{){(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/g;
|
||||
const regex = /(?:^|[^{\n])({(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\2})/gm;
|
||||
let match;
|
||||
while ((match = regex.exec(line)) != null) {
|
||||
codeMirror.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: 'injection' });
|
||||
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' });
|
||||
}
|
||||
}
|
||||
// Highlight inline spans {{content}}
|
||||
|
||||
@@ -9,12 +9,18 @@ const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
|
||||
|
||||
const Themes = require('themes/themes.json');
|
||||
const validations = require('./validations.js')
|
||||
const validations = require('./validations.js');
|
||||
|
||||
const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder'];
|
||||
|
||||
const homebreweryThumbnail = require('../../thumbnail.png');
|
||||
|
||||
const callIfExists = (val, fn, ...args)=>{
|
||||
if(val[fn]) {
|
||||
val[fn](...args);
|
||||
}
|
||||
};
|
||||
|
||||
const MetadataEditor = createClass({
|
||||
displayName : 'MetadataEditor',
|
||||
getDefaultProps : function() {
|
||||
@@ -53,28 +59,25 @@ const MetadataEditor = createClass({
|
||||
},
|
||||
|
||||
handleFieldChange : function(name, e){
|
||||
e.persist();
|
||||
|
||||
// load validation rules, and check input value against them
|
||||
const inputRules = validations[name] ?? [];
|
||||
const validationErr = inputRules.map((rule)=>rule(e.target.value)).filter(Boolean);
|
||||
|
||||
// if no validation rules, save to props
|
||||
if(validationErr.length === 0){
|
||||
e.target.setCustomValidity('');
|
||||
callIfExists(e.target, 'setCustomValidity', '');
|
||||
this.props.onChange({
|
||||
...this.props.metadata,
|
||||
[name] : e.target.value
|
||||
});
|
||||
} else {
|
||||
// if validation issues, display built-in browser error popup with each error.
|
||||
console.log(validationErr);
|
||||
const errMessage = validationErr.map((err)=>{
|
||||
return `- ${err}`;
|
||||
}).join('\n');
|
||||
e.target.setCustomValidity(errMessage);
|
||||
e.target.reportValidity();
|
||||
};
|
||||
callIfExists(e.target, 'setCustomValidity', errMessage);
|
||||
callIfExists(e.target, 'reportValidity');
|
||||
}
|
||||
},
|
||||
|
||||
handleSystem : function(system, e){
|
||||
|
||||
@@ -42,7 +42,6 @@ const AccountPage = createClass({
|
||||
},
|
||||
|
||||
renderUiItems : function() {
|
||||
// console.log(this.props.uiItems);
|
||||
return <>
|
||||
<div className='dataGroup'>
|
||||
<h1>Account Information <i className='fas fa-user'></i></h1>
|
||||
@@ -51,12 +50,16 @@ const AccountPage = createClass({
|
||||
</div>
|
||||
<div className='dataGroup'>
|
||||
<h3>Homebrewery Information <NaturalCritIcon /></h3>
|
||||
<p><strong>Brews on Homebrewery: </strong> {this.props.uiItems.mongoCount || '-'}</p>
|
||||
<p><strong>Brews on Homebrewery: </strong> {this.props.uiItems.mongoCount}</p>
|
||||
</div>
|
||||
<div className='dataGroup'>
|
||||
<h3>Google Information <i className='fab fa-google-drive'></i></h3>
|
||||
<p><strong>Linked to Google: </strong> {this.props.uiItems.googleId ? 'YES' : 'NO'}</p>
|
||||
{this.props.uiItems.googleId ? <p><strong>Brews on Google Drive: </strong> {this.props.uiItems.fileCount || '-'}</p> : '' }
|
||||
{this.props.uiItems.googleId &&
|
||||
<p>
|
||||
<strong>Brews on Google Drive: </strong> {this.props.uiItems.googleCount ?? <>Unable to retrieve files - <a href='https://github.com/naturalcrit/homebrewery/discussions/1580'>follow these steps to renew your Google credentials.</a></>}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</>;
|
||||
},
|
||||
|
||||
1803
package-lock.json
generated
1803
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "homebrewery",
|
||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||
"version": "3.4.1",
|
||||
"version": "3.4.2",
|
||||
"engines": {
|
||||
"node": "16.11.x"
|
||||
},
|
||||
@@ -70,26 +70,26 @@
|
||||
"jwt-simple": "^0.5.6",
|
||||
"less": "^3.13.1",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "4.2.3",
|
||||
"marked": "4.2.4",
|
||||
"marked-extended-tables": "^1.0.5",
|
||||
"markedLegacy": "npm:marked@^0.3.19",
|
||||
"moment": "^2.29.4",
|
||||
"mongoose": "^6.7.5",
|
||||
"mongoose": "^6.8.0",
|
||||
"nanoid": "3.3.4",
|
||||
"nconf": "^0.12.0",
|
||||
"npm": "^8.10.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-frame-component": "4.1.3",
|
||||
"react-router-dom": "6.4.4",
|
||||
"react-router-dom": "6.4.5",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"superagent": "^6.1.0",
|
||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.28.0",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"jest": "^29.2.2",
|
||||
"supertest": "^6.3.1"
|
||||
"supertest": "^6.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +280,6 @@ app.get('/edit/:id', asyncHandler(getBrew('edit')), (req, res, next)=>{
|
||||
title : req.brew.title || 'Untitled Brew',
|
||||
description : req.brew.description || 'No description.',
|
||||
image : req.brew.thumbnail || defaultMetaTags.image,
|
||||
|
||||
type : 'article'
|
||||
};
|
||||
|
||||
@@ -341,7 +340,7 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
data.title = 'Account Information Page';
|
||||
|
||||
let auth;
|
||||
let files;
|
||||
let googleCount = [];
|
||||
if(req.account) {
|
||||
if(req.account.googleId) {
|
||||
try {
|
||||
@@ -353,9 +352,9 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
}
|
||||
if(auth.credentials.access_token) {
|
||||
try {
|
||||
files = await GoogleActions.listGoogleBrews(auth);
|
||||
googleCount = await GoogleActions.listGoogleBrews(auth);
|
||||
} catch (e) {
|
||||
files = undefined;
|
||||
googleCount = undefined;
|
||||
console.log('List Google files failed!');
|
||||
console.log(e);
|
||||
}
|
||||
@@ -363,18 +362,19 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
}
|
||||
|
||||
const query = { authors: req.account.username, googleId: { $exists: false } };
|
||||
const brews = await HomebrewModel.find(query, 'id')
|
||||
const mongoCount = await HomebrewModel.countDocuments(query)
|
||||
.catch((err)=>{
|
||||
mongoCount = 0;
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
data.uiItems = {
|
||||
username : req.account.username,
|
||||
issued : req.account.issued,
|
||||
mongoCount : brews.length,
|
||||
googleId : Boolean(req.account.googleId),
|
||||
authCheck : Boolean(req.account.googleId && auth.credentials.access_token),
|
||||
fileCount : files?.length || '-'
|
||||
username : req.account.username,
|
||||
issued : req.account.issued,
|
||||
googleId : Boolean(req.account.googleId),
|
||||
authCheck : Boolean(req.account.googleId && auth.credentials.access_token),
|
||||
mongoCount : mongoCount,
|
||||
googleCount : googleCount?.length
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ const GoogleActions = {
|
||||
text : file.data,
|
||||
|
||||
description : obj.data.description,
|
||||
tags : obj.data.properties.tags ? obj.data.properties.tags : '',
|
||||
systems : obj.data.properties.systems ? obj.data.properties.systems.split(',') : [],
|
||||
authors : [],
|
||||
published : obj.data.properties.published ? obj.data.properties.published == 'true' : false,
|
||||
|
||||
@@ -27,7 +27,7 @@ const getId = (req)=>{
|
||||
return { id, googleId };
|
||||
};
|
||||
|
||||
const getBrew = (accessType)=>{
|
||||
const getBrew = (accessType, stubOnly = false)=>{
|
||||
// Create middleware with the accessType passed in as part of the scope
|
||||
return async (req, res, next)=>{
|
||||
// Get relevant IDs for the brew
|
||||
@@ -45,7 +45,7 @@ const getBrew = (accessType)=>{
|
||||
stub = stub?.toObject();
|
||||
|
||||
// If there is a google id, try to find the google brew
|
||||
if(googleId || stub?.googleId) {
|
||||
if(!stubOnly && (googleId || stub?.googleId)) {
|
||||
let googleError;
|
||||
const googleBrew = await GoogleActions.getGoogleBrew(googleId || stub?.googleId, id, accessType)
|
||||
.catch((err)=>{
|
||||
@@ -59,14 +59,14 @@ const getBrew = (accessType)=>{
|
||||
}
|
||||
|
||||
// If after all of that we still don't have a brew, throw an exception
|
||||
if(!stub) {
|
||||
if(!stub && !stubOnly) {
|
||||
throw 'Brew not found in Homebrewery database or Google Drive';
|
||||
}
|
||||
|
||||
if(typeof stub.tags === 'string') {
|
||||
if(typeof stub?.tags === 'string') {
|
||||
stub.tags = [];
|
||||
}
|
||||
req.brew = stub;
|
||||
req.brew = stub || {};
|
||||
|
||||
next();
|
||||
};
|
||||
@@ -235,23 +235,22 @@ const updateBrew = async (req, res)=>{
|
||||
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
|
||||
}
|
||||
|
||||
// Fetch the brew from the database again (if it existed there to begin with), and assign the existing brew to it
|
||||
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
|
||||
|
||||
if(!brew.markModified) {
|
||||
// If it wasn't in the database, create a new db brew
|
||||
brew = new HomebrewModel(brew);
|
||||
// define a function to catch our save errors
|
||||
const saveError = (err)=>{
|
||||
console.error(err);
|
||||
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
|
||||
};
|
||||
let saved;
|
||||
if(!brew._id) {
|
||||
// if the brew does not have a stub id, create and save it, then write the new value back to the brew.
|
||||
saved = await new HomebrewModel(brew).save().catch(saveError);
|
||||
brew = saved?.toObject();
|
||||
} else {
|
||||
// if the brew does have a stub id, update it using the stub id as the key.
|
||||
saved = await HomebrewModel.findOneAndUpdate({ _id: brew._id }, brew, {
|
||||
returnOriginal : false
|
||||
}).catch(saveError);
|
||||
}
|
||||
|
||||
brew.markModified('authors');
|
||||
brew.markModified('systems');
|
||||
|
||||
// Save the database brew
|
||||
const saved = await brew.save()
|
||||
.catch((err)=>{
|
||||
console.error(err);
|
||||
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
|
||||
});
|
||||
if(!saved) return;
|
||||
// Call and wait for afterSave to complete
|
||||
const after = await afterSave();
|
||||
@@ -327,8 +326,8 @@ const deleteBrew = async (req, res, next)=>{
|
||||
};
|
||||
|
||||
router.post('/api', asyncHandler(newBrew));
|
||||
router.put('/api/:id', asyncHandler(getBrew('edit')), asyncHandler(updateBrew));
|
||||
router.put('/api/update/:id', asyncHandler(getBrew('edit')), asyncHandler(updateBrew));
|
||||
router.put('/api/:id', asyncHandler(getBrew('edit', true)), asyncHandler(updateBrew));
|
||||
router.put('/api/update/:id', asyncHandler(getBrew('edit', true)), asyncHandler(updateBrew));
|
||||
router.delete('/api/:id', asyncHandler(deleteBrew));
|
||||
router.get('/api/remove/:id', asyncHandler(deleteBrew));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user