From eb719e34a8b42672dfebf59564a0c4c6681bc618 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 21 Apr 2024 14:35:51 +1200 Subject: [PATCH 01/89] Add aggregate query to HB model --- server/homebrew.model.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/homebrew.model.js b/server/homebrew.model.js index 36c9aa192..57e57d9e8 100644 --- a/server/homebrew.model.js +++ b/server/homebrew.model.js @@ -60,6 +60,12 @@ HomebrewSchema.statics.getByUser = async function(username, allowAccess=false, f return brews; }; +HomebrewSchema.statics.getAggregate = async function(aggregate, options={}){ + const output = await Homebrew.aggregate(aggregate, options) + .catch((error)=>{throw 'Can not get aggregate';}); + return output; +}; + const Homebrew = mongoose.model('Homebrew', HomebrewSchema); module.exports = { From 770025da0473aadd15bf450b1112e5c8cc50480b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 21 Apr 2024 14:42:20 +1200 Subject: [PATCH 02/89] Add lock count route, update pipelines --- server/admin.api.js | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 5363ecc08..93c7771a7 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -27,10 +27,12 @@ const mw = { }; const junkBrewPipeline = [ - { $match : { - updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, - lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } - }}, + { $match : + { + updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, + lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } + } + }, { $project: { textBinSize: { $binarySize: '$textBin' } } }, { $match: { textBinSize: { $lt: 140 } } }, { $limit: 100 } @@ -138,6 +140,31 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ } }); +router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ + try { + const countLocksPipeline = [ + { + $match : + { + 'lock.locked' : true, + }, + }, + { + $count : + 'count', + } + ]; + const totalLockCount = await HomebrewModel.getAggregate(countLocksPipeline); + const count = totalLockCount[0].count; + return res.json({ + count + }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Unable to get lock count' }); + } +}); + router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl From 8c5f2ff61cb12f44d00399f19fdd6e97b024b24e Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 21 Apr 2024 22:17:10 +1200 Subject: [PATCH 03/89] Add route to get locked documents with review requested --- server/admin.api.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 93c7771a7..b6f72efa1 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -165,6 +165,27 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ } }); +router.get('/admin/lockreviews', mw.adminOnly, async (req, res)=>{ + try { + const countReviewsPipeline = [ + { + $match : + { + 'lock.locked' : true, + 'lock.reviewRequested' : { '$exists': 1 } + }, + } + ]; + const reviewDocuments = await HomebrewModel.getAggregate(countReviewsPipeline); + return res.json({ + reviewDocuments + }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Unable to get lock count' }); + } +}); + router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl From b4a7dc0cbd13bf9145e4398ecad89bed08f5c1b6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 21 Apr 2024 22:48:11 +1200 Subject: [PATCH 04/89] Update lock review route --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index b6f72efa1..552b8a30f 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -165,7 +165,7 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/lockreviews', mw.adminOnly, async (req, res)=>{ +router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ try { const countReviewsPipeline = [ { From 14c7a1152802da1e8eba5570efeb2495cab18be3 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 21 Apr 2024 22:51:53 +1200 Subject: [PATCH 05/89] Fix error message --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 552b8a30f..48a05438d 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -182,7 +182,7 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ }); } catch (error) { console.error(error); - return res.status(500).json({ error: 'Unable to get lock count' }); + return res.status(500).json({ error: 'Unable to get review collection' }); } }); From 874cbe1da43d9da27e732249b92fd2ed2bf32213 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 22 Apr 2024 00:26:34 +1200 Subject: [PATCH 06/89] Don't forget to update the schema! --- server/homebrew.model.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/homebrew.model.js b/server/homebrew.model.js index 57e57d9e8..81f31f1eb 100644 --- a/server/homebrew.model.js +++ b/server/homebrew.model.js @@ -26,7 +26,9 @@ const HomebrewSchema = 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: 1 }, + + lock : { type: Object } }, { versionKey: false }); HomebrewSchema.statics.increaseView = async function(query) { From 8feae7efb622f1e2727bead01e83e7951244339b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 22 Apr 2024 00:32:32 +1200 Subject: [PATCH 07/89] Function request review route --- server/admin.api.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 48a05438d..846757f23 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -186,6 +186,33 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ } }); +router.get('/admin/lock/requestreview/:id', mw.adminOnly, async (req, res)=>{ + try { + const filter = { + shareId : req.params.id, + 'lock.locked' : true + }; + + const brew = await HomebrewModel.findOne(filter).exec(); + if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} is not locked!` }); }; + + brew.lock.reviewRequested = new Date(); + brew.markModified('lock'); + + console.log(brew); + + await brew.save() + .catch((err)=>{ + return err; + }); + + return res.json(brew); + } catch (error) { + console.error(error); + return res.status(500).json({ error: `Unable to set request for review on brew ID ${req.params.id}` }); + } +}); + router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl From 99f5aad94238030207bd0a349bb4ea902aefd822 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 14:32:04 +1200 Subject: [PATCH 08/89] Stop review request if it has already been logged --- server/admin.api.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 846757f23..dfaa6d03f 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -193,19 +193,20 @@ router.get('/admin/lock/requestreview/:id', mw.adminOnly, async (req, res)=>{ 'lock.locked' : true }; - const brew = await HomebrewModel.findOne(filter).exec(); + const brew = await HomebrewModel.findOne(filter); if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} is not locked!` }); }; + if(brew.lock.reviewRequested){ return res.status(500).json({ error: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; + brew.lock.reviewRequested = new Date(); brew.markModified('lock'); - console.log(brew); - await brew.save() .catch((err)=>{ return err; }); + console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); return res.json(brew); } catch (error) { console.error(error); From 71b84e1aba73c38bce5d08348747aa7e7e813ccd Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 14:33:29 +1200 Subject: [PATCH 09/89] Log message when review already requested --- server/admin.api.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index dfaa6d03f..e28b2fff8 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -196,7 +196,10 @@ router.get('/admin/lock/requestreview/:id', mw.adminOnly, async (req, res)=>{ const brew = await HomebrewModel.findOne(filter); if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} is not locked!` }); }; - if(brew.lock.reviewRequested){ return res.status(500).json({ error: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; + if(brew.lock.reviewRequested){ + console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); + return res.status(500).json({ error: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + }; brew.lock.reviewRequested = new Date(); brew.markModified('lock'); From e8b9b3d583b2496bd42a2b547854be4d6bc4faaa Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 15:27:40 +1200 Subject: [PATCH 10/89] Add lock route --- server/admin.api.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index e28b2fff8..cbde256f7 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -165,6 +165,27 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ } }); +router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ + const lock = req.body; + + try { + const filter = { + shareId : req.params.id + }; + + const brew = await HomebrewModel.findOne(filter); + + brew.lock = lock; + brew.markModified('lock'); + + await brew.save(); + + console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); + } catch {} + + return; +}); + router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ try { const countReviewsPipeline = [ From 1c2ae8392c56a79598ec2b7519382ca8cad9c719 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 15:32:26 +1200 Subject: [PATCH 11/89] Increase max lines in Linter --- server/admin.api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/admin.api.js b/server/admin.api.js index cbde256f7..2034a0e68 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -1,3 +1,4 @@ +/*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/ const HomebrewModel = require('./homebrew.model.js').model; const router = require('express').Router(); const Moment = require('moment'); From e9db7d1bb92014bc14b69209f30f4911ccdab048 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 15:37:50 +1200 Subject: [PATCH 12/89] Add return on success to lock route --- server/admin.api.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 2034a0e68..5a8b19acb 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -182,9 +182,12 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); - } catch {} + } catch (error) { + console.error(error); + return res.status(500).json({ error: `Unable to set lock on brew ${req.params.id}` }); + } - return; + return res.status(200).json({ status: 'SUCCESS', lock }); }); router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ From 4b1d6ebd7c6537ad700b42078772f0595368c186 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 15:58:43 +1200 Subject: [PATCH 13/89] Rename review request route --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 5a8b19acb..620ddebae 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -211,7 +211,7 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/lock/requestreview/:id', mw.adminOnly, async (req, res)=>{ +router.get('/admin/lock/review/request/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id, From 20d48d7dc2d74def10e3e760cedf2f3b544661bd Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Apr 2024 15:59:11 +1200 Subject: [PATCH 14/89] Add review removal route --- server/admin.api.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 620ddebae..9f72a5ea2 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -242,6 +242,30 @@ router.get('/admin/lock/review/request/:id', mw.adminOnly, async (req, res)=>{ } }); +router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ + try { + const filter = { + shareId : req.params.id, + 'lock.locked' : true, + 'lock.reviewRequested' : { '$exists': 1 } + }; + + const brew = await HomebrewModel.findOne(filter); + if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} does not have a review pending!` }); }; + + delete brew.lock.reviewRequested; + brew.markModified('lock'); + + await brew.save(); + + console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); + return res.json(brew); + } catch (error) { + console.error(error); + return res.status(500).json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); + } +}); + router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl From b4ce621630c39e03be9f1737ba83a287d473d470 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 9 May 2024 07:37:37 +1200 Subject: [PATCH 15/89] Request review no longer Admin only --- server/admin.api.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 9f72a5ea2..455258555 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -211,7 +211,9 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/lock/review/request/:id', mw.adminOnly, async (req, res)=>{ +router.get('/admin/lock/review/request/:id', async (req, res)=>{ + // === This route is NOT Admin only === + // Any user can request a review of their document try { const filter = { shareId : req.params.id, From 1fe2a26e8336a03b5730e7b03441e8cd52411296 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Fri, 10 May 2024 12:38:31 +1200 Subject: [PATCH 16/89] Tabify Admin page --- client/admin/admin.jsx | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 92e0b2aee..c20b6abed 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -8,11 +8,38 @@ const BrewLookup = require('./brewLookup/brewLookup.jsx'); const BrewCompress = require ('./brewCompress/brewCompress.jsx'); const Stats = require('./stats/stats.jsx'); +const tabGroups = ['brews']; + const Admin = createClass({ getDefaultProps : function() { return {}; }, + getInitialState : function() { + return { + currentTab : 'brews' + }; + }, + + handleClick : function(newTab) { + if(this.state.currentTab === newTab) return; + this.setState({ + currentTab : newTab + }); + }, + + renderBrewTools : function(){ + return <> + +
+ +
+ +
+ + ; + }, + render : function(){ return
@@ -23,13 +50,12 @@ const Admin = createClass({
- -
- -
- -
- +
+ {tabGroups.map((name, idx)=>{ + return ; + })} +
+ {this.state.currentTab == 'brews' && this.renderBrewTools()}
; } From e7dc757293f00d7f78c21b4aad4a3f22d5447051 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 11 May 2024 23:58:37 +1200 Subject: [PATCH 17/89] Initial UI functionality for most Lock functions --- client/admin/admin.jsx | 7 +- client/admin/admin.less | 18 +++ client/admin/lockTools/lockTools.jsx | 176 ++++++++++++++++++++++++++ client/admin/lockTools/lockTools.less | 3 + server/admin.api.js | 48 +++++-- 5 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 client/admin/lockTools/lockTools.jsx create mode 100644 client/admin/lockTools/lockTools.less diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index c20b6abed..088847a66 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -8,7 +8,9 @@ const BrewLookup = require('./brewLookup/brewLookup.jsx'); const BrewCompress = require ('./brewCompress/brewCompress.jsx'); const Stats = require('./stats/stats.jsx'); -const tabGroups = ['brews']; +const LockTools = require('./lockTools/lockTools.jsx'); + +const tabGroups = ['brews', 'locks']; const Admin = createClass({ getDefaultProps : function() { @@ -52,10 +54,11 @@ const Admin = createClass({
{tabGroups.map((name, idx)=>{ - return ; + return ; })}
{this.state.currentTab == 'brews' && this.renderBrewTools()} + {this.state.currentTab == 'locks' && }
; } diff --git a/client/admin/admin.less b/client/admin/admin.less index a61335835..39a66bd54 100644 --- a/client/admin/admin.less +++ b/client/admin/admin.less @@ -40,5 +40,23 @@ body{ margin : 30px 0px; } + .tabs { + border-bottom: 1px solid black; + } + + button.tab { + margin: 2px 2px 0px; + border-width: 1px 1px 0px; + border-style: solid; + border-color: black; + border-radius: 5px 5px 0px 0px; + color: black; + background-color: transparent; + &.active { + background-color: #000000a0; + color: white; + text-decoration: underline; + } + } } diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx new file mode 100644 index 000000000..710a29681 --- /dev/null +++ b/client/admin/lockTools/lockTools.jsx @@ -0,0 +1,176 @@ +require('./lockTools.less'); +const React = require('react'); +const createClass = require('create-react-class'); + +const request = require('superagent'); + +const LockTools = createClass({ + getInitialState : function() { + return { + fetching : false, + reviewCount : 0 + }; + }, + + componentDidMount : function() { + this.updateReviewCount(); + }, + + updateReviewCount : async function() { + const newCount = await request.get('/admin/lock') + .then((res)=>{return res.body?.count || 'Unknown';}); + if(newCount != this.state.reviewCount){ + this.setState({ + reviewCount : newCount + }); + } + }, + + render : function() { + return
+

Lock Count

+

Number of brews currently locked: {this.state.reviewCount}

+ +
+ +
+

Lock Brew

+ NYI +
+ +
+ +
; + } +}); + +const LockTable = createClass({ + getDefaultProps : function() { + return { + title : '', + fetchURL : '/admin/locks', + resultName : '', + propertyNames : ['shareId'] + }; + }, + + getInitialState : function() { + return { + result : '', + error : '', + searching : false + }; + }, + + clickFn(){ + this.setState({ searching: true, error: null }); + + request.get(this.props.fetchURL) + .then((res)=>this.setState({ result: res.body })) + .catch((err)=>this.setState({ error: err })) + .finally(()=>{ + this.setState({ searching: false }); + }); + }, + + render : function () { + return <> +

{this.props.title}

+ + {this.state.result[this.props.resultName] && + <> +

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

+ + + + {this.props.propertyNames.map((name, idx)=>{ + return ; + })} + + + + {this.state.result[this.props.resultName].map((result, resultIdx)=>{ + return {navigator.clipboard.writeText(result.shareId.toString());}}> + {this.props.propertyNames.map((name, nameIdx)=>{ + return ; + })} + ; + })} + +
{name}
+ {result[name].toString()} +
+ + } + ; + } +}); + +const LockLookup = createClass({ + getDefaultProps : function() { + return { + fetchURL : '/admin/lookup' + }; + }, + + getInitialState : function() { + return { + query : '', + result : '', + error : '', + searching : false + }; + }, + + handleChange(e){ + this.setState({ query: e.target.value }); + }, + + clickFn(){ + this.setState({ searching: true, error: null }); + + request.get(`${this.props.fetchURL}/${this.state.query}`) + .then((res)=>this.setState({ result: res.body })) + .catch((err)=>this.setState({ error: err })) + .finally(()=>{ + this.setState({ searching: false }); + }); + }, + + renderResult : function(){ + return <> +

Result:

+ + + {Object.keys(this.state.result).map((key, idx)=>{ + return + + + ; + })} + +
{key}{this.state.result[key].toString()} +
+ ; + }, + + render : function() { + return
+

{this.props.title}

+ + + + {this.state.error + &&
{this.state.error.toString()}
+ } + + {this.state.result && this.renderResult()} +
; + } +}); + +module.exports = LockTools; \ No newline at end of file diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less new file mode 100644 index 000000000..8f0ec04bd --- /dev/null +++ b/client/admin/lockTools/lockTools.less @@ -0,0 +1,3 @@ +.lockTools { + display: block; +} \ No newline at end of file diff --git a/server/admin.api.js b/server/admin.api.js index 455258555..e1d33f029 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -162,12 +162,13 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ }); } catch (error) { console.error(error); - return res.status(500).json({ error: 'Unable to get lock count' }); + return res.json({ status: 'ERROR', detail: 'Unable to get lock count', error }); } }); router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ const lock = req.body; + lock.applied = new Date; try { const filter = { @@ -176,6 +177,8 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ const brew = await HomebrewModel.findOne(filter); + if(brew.lock) return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); + brew.lock = lock; brew.markModified('lock'); @@ -184,10 +187,34 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); } catch (error) { console.error(error); - return res.status(500).json({ error: `Unable to set lock on brew ${req.params.id}` }); + return res.json({ error, message: `Unable to set lock on brew ${req.params.id}` }); } - return res.status(200).json({ status: 'SUCCESS', lock }); + return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); +}); + +router.get('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ + try { + const filter = { + shareId : req.params.id + }; + + const brew = await HomebrewModel.findOne(filter); + + if(!brew.lock) return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); + + brew.lock = undefined; + brew.markModified('lock'); + + await brew.save(); + + console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); + } catch (error) { + console.error(error); + return res.json({ status: 'ERROR', detail: `Unable to clear lock on brew ${req.params.id}`, error }); + } + + return res.json({ status: 'UNLOCKED', detail: `Lock removed from brew ID ${req.params.id}` }); }); router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ @@ -202,12 +229,13 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ } ]; const reviewDocuments = await HomebrewModel.getAggregate(countReviewsPipeline); + console.log(reviewDocuments); return res.json({ reviewDocuments }); } catch (error) { console.error(error); - return res.status(500).json({ error: 'Unable to get review collection' }); + return res.json({ status: 'ERROR', detail: 'Unable to get review collection', error }); } }); @@ -221,11 +249,11 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ }; const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} is not locked!` }); }; + if(!brew) { return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); }; if(brew.lock.reviewRequested){ console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.status(500).json({ error: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + return res.json({ status: 'NOT REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; brew.lock.reviewRequested = new Date(); @@ -237,10 +265,10 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ }); console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json(brew); + return res.json({ status: 'REVIEW REQUESTED', brew }); } catch (error) { console.error(error); - return res.status(500).json({ error: `Unable to set request for review on brew ID ${req.params.id}` }); + return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); } }); @@ -253,7 +281,7 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ }; const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.status(500).json({ error: `Brew ID ${req.params.id} does not have a review pending!` }); }; + if(!brew) { return res.json({ status: 'NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; delete brew.lock.reviewRequested; brew.markModified('lock'); @@ -264,7 +292,7 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ return res.json(brew); } catch (error) { console.error(error); - return res.status(500).json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); + return res.json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); } }); From 2a91d3ddbdaab7387d7c5c07a0eb356173f5edbc Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 16:07:28 +1200 Subject: [PATCH 18/89] Additional styling --- client/admin/lockTools/lockTools.less | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 8f0ec04bd..9554ffa19 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -1,3 +1,13 @@ .lockTools { - display: block; + .lockBrew label { + width: 50%; + display: inline-block; + text-align: right; + line-height: 1.5em; + input { + float: right; + width: 70%; + margin-left: 10px; + } + } } \ No newline at end of file From 2502c0e87ca04e35f01987ffb3a60d969488b383 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 16:08:26 +1200 Subject: [PATCH 19/89] Add missing return status messages --- server/admin.api.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index e1d33f029..eb025a686 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -170,14 +170,18 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ const lock = req.body; lock.applied = new Date; + let brew; try { const filter = { shareId : req.params.id }; - const brew = await HomebrewModel.findOne(filter); + brew = await HomebrewModel.findOne(filter); - if(brew.lock) return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); + if(brew.lock) { + console.log('ALREADY LOCKED'); + return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); + } brew.lock = lock; brew.markModified('lock'); @@ -187,7 +191,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); } catch (error) { console.error(error); - return res.json({ error, message: `Unable to set lock on brew ${req.params.id}` }); + return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); } return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); @@ -244,8 +248,8 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ // Any user can request a review of their document try { const filter = { - shareId : req.params.id, - 'lock.locked' : true + shareId : req.params.id, + lock : { $exists: 1 } }; const brew = await HomebrewModel.findOne(filter); @@ -283,7 +287,7 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ const brew = await HomebrewModel.findOne(filter); if(!brew) { return res.json({ status: 'NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; - delete brew.lock.reviewRequested; + brew.lock.reviewRequested = undefined; brew.markModified('lock'); await brew.save(); From 65f1c19721b9a8f9eeeb930253a17c026a28674b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 16:14:09 +1200 Subject: [PATCH 20/89] Add functional Lock Brew component --- client/admin/lockTools/lockTools.jsx | 75 +++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 710a29681..6e5d7f90e 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -34,8 +34,7 @@ const LockTools = createClass({

-

Lock Brew

- NYI +

@@ -44,6 +43,77 @@ const LockTools = createClass({ } }); +const LockBrew = createClass({ + getInitialState : function() { + return { + brewId : '', + code : 1000, + editMessage : '', + shareMessage : '' + }; + }, + + handleChange : function(e, varName) { + const output = {}; + output[varName] = e.target.value; + this.setState(output); + }, + + submit : function(e){ + e.preventDefault(); + if(!this.state.editMessage) return; + const newLock = { + code : parseInt(this.state.code) || 100, + editMessage : this.state.editMessage, + shareMessage : this.state.shareMessage, + applied : new Date, + locked : true + }; + + request.post(`/admin/lock/${this.state.brewId}`) + .send(newLock) + .set('Content-Type', 'application/json') + .then((response)=>{ + console.log(response.body); + }); + }, + + renderInput : function (name) { + return this.handleChange(e, name)} autoComplete='off' required/>; + }, + + render : function() { + return
+

Lock Brew

+
+ +
+ +
+ +
+ +
+ +
+
; + } +}); + const LockTable = createClass({ getDefaultProps : function() { return { @@ -140,6 +210,7 @@ const LockLookup = createClass({ }, renderResult : function(){ + console.log(this.state.result); return <>

Result:

From b093be52a25321e2f0148c148b8c830371839d20 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 16:57:28 +1200 Subject: [PATCH 21/89] Update esLint rules --- client/admin/lockTools/lockTools.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 6e5d7f90e..9e53e31fd 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -1,3 +1,4 @@ +/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ require('./lockTools.less'); const React = require('react'); const createClass = require('create-react-class'); From 7c4721932dcd6c1adea242aa0bf80fca77b5e4a3 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 19:50:27 +1200 Subject: [PATCH 22/89] Remove unnecessary function from HB.model --- server/admin.api.js | 45 ++++++++++++++++++---------------------- server/homebrew.model.js | 6 ------ 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index eb025a686..625e44f22 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -147,16 +147,16 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ { $match : { - 'lock.locked' : true, - }, + lock : { $exists: 1 } + } }, { - $count : - 'count', + $count : 'count' } ]; - const totalLockCount = await HomebrewModel.getAggregate(countLocksPipeline); + const totalLockCount = await HomebrewModel.aggregate(countLocksPipeline); const count = totalLockCount[0].count; + console.log(totalLockCount); return res.json({ count }); @@ -188,10 +188,10 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); - console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); + // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); } catch (error) { console.error(error); - return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); + return res.json({ status: 'ERROR', error, detail: `Unable to set lock on brew ${req.params.id}` }); } return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); @@ -212,7 +212,7 @@ router.get('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); - console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); + // console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to clear lock on brew ${req.params.id}`, error }); @@ -227,13 +227,11 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ { $match : { - 'lock.locked' : true, 'lock.reviewRequested' : { '$exists': 1 } }, } ]; - const reviewDocuments = await HomebrewModel.getAggregate(countReviewsPipeline); - console.log(reviewDocuments); + const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline); return res.json({ reviewDocuments }); @@ -256,20 +254,17 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ if(!brew) { return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); }; if(brew.lock.reviewRequested){ - console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'NOT REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; brew.lock.reviewRequested = new Date(); brew.markModified('lock'); - await brew.save() - .catch((err)=>{ - return err; - }); + await brew.save(); - console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUESTED', brew }); + // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested for ${brew.shareId} - ${brew.title}` }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); @@ -277,14 +272,14 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ }); router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ + let brew; try { const filter = { shareId : req.params.id, - 'lock.locked' : true, - 'lock.reviewRequested' : { '$exists': 1 } + 'lock.reviewRequested' : { $exists: 1 } }; - const brew = await HomebrewModel.findOne(filter); + brew = await HomebrewModel.findOne(filter); if(!brew) { return res.json({ status: 'NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; brew.lock.reviewRequested = undefined; @@ -292,11 +287,11 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); - console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json(brew); + // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Request for Review removed from brew ID ${brew.shareId} - ${brew.title}` }); } catch (error) { console.error(error); - return res.json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); + return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); } }); diff --git a/server/homebrew.model.js b/server/homebrew.model.js index 81f31f1eb..ea32265ff 100644 --- a/server/homebrew.model.js +++ b/server/homebrew.model.js @@ -62,12 +62,6 @@ HomebrewSchema.statics.getByUser = async function(username, allowAccess=false, f return brews; }; -HomebrewSchema.statics.getAggregate = async function(aggregate, options={}){ - const output = await Homebrew.aggregate(aggregate, options) - .catch((error)=>{throw 'Can not get aggregate';}); - return output; -}; - const Homebrew = mongoose.model('Homebrew', HomebrewSchema); module.exports = { From c0c674d8626abcc74169e2f4f548327831e73966 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 19:52:08 +1200 Subject: [PATCH 23/89] Comment out debug logging --- server/admin.api.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 625e44f22..8c29791ce 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -147,16 +147,16 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ { $match : { - lock : { $exists: 1 } + lock : true } }, { - $count : 'count' + $count : + 'count' } ]; const totalLockCount = await HomebrewModel.aggregate(countLocksPipeline); const count = totalLockCount[0].count; - console.log(totalLockCount); return res.json({ count }); @@ -179,7 +179,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ brew = await HomebrewModel.findOne(filter); if(brew.lock) { - console.log('ALREADY LOCKED'); + // console.log('ALREADY LOCKED'); return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); } @@ -191,7 +191,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); } catch (error) { console.error(error); - return res.json({ status: 'ERROR', error, detail: `Unable to set lock on brew ${req.params.id}` }); + return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); } return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); @@ -227,6 +227,7 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ { $match : { + 'lock.locked' : true, 'lock.reviewRequested' : { '$exists': 1 } }, } @@ -255,16 +256,19 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ if(brew.lock.reviewRequested){ // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + return res.json({ status: 'NOT REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; brew.lock.reviewRequested = new Date(); brew.markModified('lock'); - await brew.save(); + await brew.save() + .catch((err)=>{ + return err; + }); // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested for ${brew.shareId} - ${brew.title}` }); + return res.json({ status: 'REVIEW REQUESTED', brew }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); @@ -272,14 +276,14 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ }); router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ - let brew; try { const filter = { shareId : req.params.id, - 'lock.reviewRequested' : { $exists: 1 } + 'lock.locked' : true, + 'lock.reviewRequested' : { '$exists': 1 } }; - brew = await HomebrewModel.findOne(filter); + const brew = await HomebrewModel.findOne(filter); if(!brew) { return res.json({ status: 'NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; brew.lock.reviewRequested = undefined; @@ -288,10 +292,10 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Request for Review removed from brew ID ${brew.shareId} - ${brew.title}` }); + return res.json(brew); } catch (error) { console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); + return res.json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); } }); From b237f29636bea20f7486915e0883b62ed8a3da2b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 19:58:29 +1200 Subject: [PATCH 24/89] Clean up API functions --- server/admin.api.js | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 8c29791ce..13d3cb78c 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -155,8 +155,7 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ 'count' } ]; - const totalLockCount = await HomebrewModel.aggregate(countLocksPipeline); - const count = totalLockCount[0].count; + const count = await HomebrewModel.aggregate(countLocksPipeline); return res.json({ count }); @@ -167,16 +166,15 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ }); router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ - const lock = req.body; - lock.applied = new Date; - - let brew; try { + const lock = req.body; + lock.applied = new Date; + const filter = { shareId : req.params.id }; - brew = await HomebrewModel.findOne(filter); + const brew = await HomebrewModel.findOne(filter); if(brew.lock) { // console.log('ALREADY LOCKED'); @@ -189,12 +187,11 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); } - - return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); }); router.get('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ @@ -256,19 +253,16 @@ router.get('/admin/lock/review/request/:id', async (req, res)=>{ if(brew.lock.reviewRequested){ // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'NOT REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); }; brew.lock.reviewRequested = new Date(); brew.markModified('lock'); - await brew.save() - .catch((err)=>{ - return err; - }); + await brew.save(); // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUESTED', brew }); + return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); @@ -279,12 +273,11 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id, - 'lock.locked' : true, - 'lock.reviewRequested' : { '$exists': 1 } + 'lock.reviewRequested' : { $exists: 1 } }; const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.json({ status: 'NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; + if(!brew) { return res.json({ status: 'REVIEW REQUEST NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; brew.lock.reviewRequested = undefined; brew.markModified('lock'); @@ -292,10 +285,10 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json(brew); + return res.json({status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); } catch (error) { console.error(error); - return res.json({ error: `Unable to remove request for review on brew ID ${req.params.id}` }); + return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); } }); From f5014f29c3973c1442c76d497fa78c4cad01b5ad Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 15 May 2024 23:13:53 +1200 Subject: [PATCH 25/89] Linter fix --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 13d3cb78c..f0714f1ce 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -285,7 +285,7 @@ router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json({status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); + return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); From 96b955f2fe5b885cabb4e73b96b6c03422d6f55d Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 16 May 2024 17:00:26 +1200 Subject: [PATCH 26/89] Change lock check to stub.lock from stub.lock.locked --- server/homebrew.api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index e73a704a8..ef3af9a21 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -54,7 +54,7 @@ const api = { }); stub = stub?.toObject(); - if(stub?.lock?.locked && accessType != 'edit') { + if(stub?.lock && accessType != 'edit') { throw { HBErrorCode: '100', code: stub.lock.code, message: stub.lock.message, brewId: stub.shareId, brewTitle: stub.title }; } @@ -83,9 +83,9 @@ const api = { if(accessType === 'edit' && (authorsExist && !(isAuthor || isInvited))) { const accessError = { name: 'Access Error', status: 401 }; if(req.account){ - throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId}; + throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId }; } - throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId}; + throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId }; } // If after all of that we still don't have a brew, throw an exception From 4e11a0c737e0ad3332ba7dba6effae7a455d01c3 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 16 May 2024 17:02:00 +1200 Subject: [PATCH 27/89] Fix error message --- server/homebrew.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index ef3af9a21..4baab48ce 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -55,7 +55,7 @@ const api = { stub = stub?.toObject(); if(stub?.lock && accessType != 'edit') { - throw { HBErrorCode: '100', code: stub.lock.code, message: stub.lock.message, brewId: stub.shareId, brewTitle: stub.title }; + throw { HBErrorCode: '100', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title }; } // If there is a google id, try to find the google brew From 7b287fb0f438b5d16e0a670a497a46048bb6f42a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 16 May 2024 17:04:37 +1200 Subject: [PATCH 28/89] Fix test --- server/homebrew.api.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/homebrew.api.spec.js b/server/homebrew.api.spec.js index 8a4748e38..c8539bf63 100644 --- a/server/homebrew.api.spec.js +++ b/server/homebrew.api.spec.js @@ -300,7 +300,7 @@ describe('Tests for api', ()=>{ }); it('access is denied to a locked brew', async()=>{ - const lockBrew = { title: 'test brew', shareId: '1', lock: { locked: true, code: 404, message: 'brew locked' } }; + const lockBrew = { title: 'test brew', shareId: '1', lock: { locked: true, code: 404, shareMessage: 'brew locked' } }; model.get = jest.fn(()=>toBrewPromise(lockBrew)); api.getId = jest.fn(()=>({ id: '1', googleId: undefined })); From d751addf9d8224be02f56d661ef1c7661f6fe344 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 16 May 2024 17:18:50 +1200 Subject: [PATCH 29/89] Change lock static error message --- client/homebrew/pages/errorPage/errors/errorIndex.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index f9d52c109..85df6d286 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -140,7 +140,7 @@ const errorIndex = (props)=>{ '100' : dedent` ## This brew has been locked. - Please contact the Administrators to unlock this document. + Once the author has taken corrective action, they may request an administrative review to have this document unlocked. : From 6314672109a4fdf9e2b16dce32fc08e3c0b7cf5c Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 14:59:08 +1200 Subject: [PATCH 30/89] Pass the entire lock object to LockNotification --- client/homebrew/pages/editPage/editPage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 48d0f3fe5..a9652a3ad 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -396,7 +396,7 @@ const EditPage = createClass({ {this.renderNavbar()}
- {this.props.brew.lock && } + {this.props.brew.lock && } Date: Sat, 8 Jun 2024 15:31:46 +1200 Subject: [PATCH 31/89] Shift API call for REQUEST REVIEW to PUT --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index bc4f1fe73..9f25d74c8 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -237,7 +237,7 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/lock/review/request/:id', async (req, res)=>{ +router.put('/admin/lock/review/request/:id', async (req, res)=>{ // === This route is NOT Admin only === // Any user can request a review of their document try { From f81d16309c872cffb4b91310abdc0a3d2e35a16c Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 15:53:01 +1200 Subject: [PATCH 32/89] Add functionality to REQUEST REVIEW button --- .../lockNotification/lockNotification.jsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx index c5eeaee47..da79ff265 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx @@ -1,17 +1,28 @@ require('./lockNotification.less'); const React = require('react'); +const request = require('../../../utils/request-middleware.js'); import Dialog from '../../../../components/dialog.jsx'; function LockNotification(props) { props = { shareId : 0, disableLock : ()=>{}, - message : '', + lock : {}, ...props }; - const removeLock = ()=>{ - alert(`Not yet implemented - ID ${props.shareId}`); + const [reviewState, setReviewState] = React.useState(false); + + const removeLock = async ()=>{ + await request.put(`/admin/lock/review/request/${props.shareId}`) + .then(()=>{ + setReviewState(true); + }); + }; + + const renderReviewButton = function(){ + if(reviewState || props.lock.reviewRequested){ return ; }; + return ; }; return @@ -19,11 +30,11 @@ function LockNotification(props) {

This brew been locked by the Administrators. It will not be accessible by any method other than the Editor until the lock is removed.


LOCK REASON

-

{props.message || 'Unable to retrieve Lock Message'}

+

{props.lock.editMessage || 'Unable to retrieve Lock Message'}


Once you have resolved this issue, click REQUEST LOCK REMOVAL to notify the Administrators for review.

Click CONTINUE TO EDITOR to temporarily hide this notification; it will reappear the next time the page is reloaded.

- + {renderReviewButton()}
; }; From 00fd1e415c8ac350f30759f4ecceb57894321d16 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 15:53:28 +1200 Subject: [PATCH 33/89] Change styling for inactive REQUEST REVIEW button --- .../pages/editPage/lockNotification/lockNotification.less | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.less b/client/homebrew/pages/editPage/lockNotification/lockNotification.less index 54f1a9569..de2692ec0 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.less +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.less @@ -15,7 +15,10 @@ color : white; background-color : #333333; - &:hover { background-color : #777777; } + &.inactive, + &:hover { + background-color : #777777; + } } h1, h3 { From bc7731b819b9e7d5e8534e739a007043b00c6372 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 16:08:18 +1200 Subject: [PATCH 34/89] Fix review requested aggregation pipeline --- server/admin.api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 9f25d74c8..498c1bff3 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -222,7 +222,6 @@ router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ { $match : { - 'lock.locked' : true, 'lock.reviewRequested' : { '$exists': 1 } }, } From 240342007b955c269b1e092614963e3429a120bd Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 16:36:20 +1200 Subject: [PATCH 35/89] Fix lock count function --- server/admin.api.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 498c1bff3..8559143c2 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -141,19 +141,13 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ try { - const countLocksPipeline = [ - { - $match : - { - lock : true - } - }, - { - $count : - 'count' - } - ]; - const count = await HomebrewModel.aggregate(countLocksPipeline); + const countLocksQuery = { + lock : { $exists: true } + }; + const count = await HomebrewModel.countDocuments(countLocksQuery) + .then((result)=>{ + return result; + }); return res.json({ count }); From 634b099ade26c18e122c83e9d25a0c024f6883ce Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 16:48:16 +1200 Subject: [PATCH 36/89] Add styling to LockTable --- client/admin/lockTools/lockTools.jsx | 2 +- client/admin/lockTools/lockTools.less | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 9e53e31fd..808f9058e 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -153,7 +153,7 @@ const LockTable = createClass({ {this.state.result[this.props.resultName] && <>

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

-
+
{this.props.propertyNames.map((name, idx)=>{ diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 9554ffa19..765c3cc5d 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -10,4 +10,16 @@ margin-left: 10px; } } + + .lockTable{ + td{ + border: 1px solid #333333; + padding: 4px 10px; + text-align: center; + + &:hover { + cursor: pointer; + } + } + } } \ No newline at end of file From 01ae858a1461a068eedbb10077ec6407190dc5b1 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 17:08:05 +1200 Subject: [PATCH 37/89] Update LockLookup placeholder value --- client/admin/lockTools/lockTools.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 808f9058e..d9448fc14 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -231,7 +231,7 @@ const LockLookup = createClass({ render : function() { return

{this.props.title}

- + From deef5998c54199ade997cb06e0629c6a49262d4a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 18:55:14 +1200 Subject: [PATCH 38/89] Update LockBrew text and styling --- client/admin/lockTools/lockTools.jsx | 80 ++++++++++++++++++--------- client/admin/lockTools/lockTools.less | 45 ++++++++++++--- 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index d9448fc14..58829eacf 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -85,32 +85,60 @@ const LockBrew = createClass({ render : function() { return
-

Lock Brew

-
- -
- -
- -
- -
- - +
+

Lock Brew

+
+ +
+ +
+ +
+ +
+ + +
+
+

Suggestions

+
+

Codes

+
    +
  • 455 - Generic Lock
  • +
  • 456 - Copyright issues
  • +
  • 457 - Confidential Information Leakage
  • +
  • 458 - Sensitive Personal Information
  • +
  • 459 - Defamation or Libel
  • +
  • 460 - Hate Speech or Discrimination
  • +
  • 461 - Illegal Activities
  • +
  • 462 - Malware or Phishing
  • +
  • 463 - Plagiarism
  • +
  • 465 - Misrepresentation
  • +
  • 466 - Inappropriate Content
  • +
+
+
+

Messages

+
    +
  • Edit Message: This is the private message that is ONLY displayed to the authors of the locked brew. This message MUST specify exactly what actions must be taken in order to have the brew unlocked.
  • +
  • Share Message: This is the public message that is displayed to the EVERYONE that attempts to view the locked brew.
  • +
+
+
; } }); diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 765c3cc5d..c34a69485 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -1,13 +1,40 @@ .lockTools { - .lockBrew label { - width: 50%; - display: inline-block; - text-align: right; - line-height: 1.5em; - input { - float: right; - width: 70%; - margin-left: 10px; + .lockBrew { + columns: 2; + + .lockForm { + break-inside: avoid; + + label { + width: 100%; + display: inline-block; + text-align: right; + line-height: 1.5em; + input { + float: right; + width: 70%; + margin-left: 10px; + } + } + } + + .lockSuggestions { + break-inside: avoid; + columns: 2; + line-height: 1.2em; + h2 { + column-span: all; + } + h3 { + margin-top: 0px; + } + b { + font-weight: 600; + } + + .lockCodes { + break-inside: avoid; + } } } From 7830c7e2eb6bd0fc4e6af5cdac23eee4e5cfc15a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 19:59:01 +1200 Subject: [PATCH 39/89] Add divs for styling of brewsAwaitingReview --- client/admin/lockTools/lockTools.jsx | 65 +++++++++++++++------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 58829eacf..7f92cdd0e 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -174,35 +174,42 @@ const LockTable = createClass({ render : function () { return <> -

{this.props.title}

- - {this.state.result[this.props.resultName] && - <> -

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

-
- - - {this.props.propertyNames.map((name, idx)=>{ - return ; - })} - - - - {this.state.result[this.props.resultName].map((result, resultIdx)=>{ - return {navigator.clipboard.writeText(result.shareId.toString());}}> - {this.props.propertyNames.map((name, nameIdx)=>{ - return ; - })} - ; - })} - -
{name}
- {result[name].toString()} -
- - } +
+
+

{this.props.title}

+ +
+ {this.state.result[this.props.resultName] && + <> +

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

+
+

Click a row to copy the Share ID to the clipboard

+ + + + {this.props.propertyNames.map((name, idx)=>{ + return ; + })} + + + + {this.state.result[this.props.resultName].map((result, resultIdx)=>{ + return {navigator.clipboard.writeText(result.shareId.toString());}}> + {this.props.propertyNames.map((name, nameIdx)=>{ + return ; + })} + ; + })} + +
{name}
+ {result[name].toString()} +
+ + } +
; } }); From 44f2e3838735868203129b142f93298c79cb3d17 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 20:00:10 +1200 Subject: [PATCH 40/89] Shift unlock and removeReview functions to use PUT --- client/admin/lockTools/lockTools.jsx | 2 +- server/admin.api.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 7f92cdd0e..710d08ff2 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -237,7 +237,7 @@ const LockLookup = createClass({ clickFn(){ this.setState({ searching: true, error: null }); - request.get(`${this.props.fetchURL}/${this.state.query}`) + request.put(`${this.props.fetchURL}/${this.state.query}`) .then((res)=>this.setState({ result: res.body })) .catch((err)=>this.setState({ error: err })) .finally(()=>{ diff --git a/server/admin.api.js b/server/admin.api.js index 8559143c2..d02cdb67b 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -186,7 +186,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ +router.put('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id @@ -260,7 +260,7 @@ router.put('/admin/lock/review/request/:id', async (req, res)=>{ } }); -router.get('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ +router.put('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id, From 7d37602d433895c063857df733c0ae2dbdce8e30 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 20:01:53 +1200 Subject: [PATCH 41/89] Remove debugging line --- client/admin/lockTools/lockTools.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 710d08ff2..9a1d1d0ce 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -246,7 +246,6 @@ const LockLookup = createClass({ }, renderResult : function(){ - console.log(this.state.result); return <>

Result:

From 17aa564c57c27174d847676efc86f83efb7e5f24 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 8 Jun 2024 21:05:44 +1200 Subject: [PATCH 42/89] Add styling for result tables --- client/admin/lockTools/lockTools.less | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index c34a69485..272646ce2 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -39,14 +39,14 @@ } .lockTable{ - td{ - border: 1px solid #333333; - padding: 4px 10px; - text-align: center; - - &:hover { - cursor: pointer; - } + td:hover { + cursor: pointer; } } + + td { + border: 1px solid #333333; + padding: 4px 10px; + text-align: center; + } } \ No newline at end of file From 24cf78bc033b565ccde43b78c3837d2c132cbfdf Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Jun 2024 20:44:55 +1200 Subject: [PATCH 43/89] Add lock result --- client/admin/lockTools/lockTools.jsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 9a1d1d0ce..bf77be018 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -50,7 +50,8 @@ const LockBrew = createClass({ brewId : '', code : 1000, editMessage : '', - shareMessage : '' + shareMessage : '', + result : {} }; }, @@ -75,7 +76,7 @@ const LockBrew = createClass({ .send(newLock) .set('Content-Type', 'application/json') .then((response)=>{ - console.log(response.body); + this.setState({ result: response.body }); }); }, @@ -83,6 +84,23 @@ const LockBrew = createClass({ return this.handleChange(e, name)} autoComplete='off' required/>; }, + renderResult : function(){ + return <> +

Result:

+
+ + {Object.keys(this.state.result).map((key, idx)=>{ + return + + + ; + })} + +
{key}{this.state.result[key].toString()} +
+ ; + }, + render : function() { return
@@ -112,6 +130,7 @@ const LockBrew = createClass({ + {this.state.result && this.renderResult()}

Suggestions

From c594fc58b35ee76d00770e1a8d885523d29246fa Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Jun 2024 21:47:52 +1200 Subject: [PATCH 44/89] Spread lock object in /lock response --- server/admin.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index d02cdb67b..8f997aed9 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -179,7 +179,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ await brew.save(); // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, lock }); + return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); } catch (error) { console.error(error); return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); From fc99328459b1aec2df0aa90cb8890a23a112faa4 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Jun 2024 21:48:55 +1200 Subject: [PATCH 45/89] Tweak styling, remove obsolete locked property --- client/admin/lockTools/lockTools.jsx | 10 +++++----- client/admin/lockTools/lockTools.less | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index bf77be018..2135425eb 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -37,9 +37,11 @@ const LockTools = createClass({

- +
+ + +

-
; } }); @@ -68,8 +70,7 @@ const LockBrew = createClass({ code : parseInt(this.state.code) || 100, editMessage : this.state.editMessage, shareMessage : this.state.shareMessage, - applied : new Date, - locked : true + applied : new Date }; request.post(`/admin/lock/${this.state.brewId}`) @@ -204,7 +205,6 @@ const LockTable = createClass({ {this.state.result[this.props.resultName] && <>

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

-

Click a row to copy the Share ID to the clipboard

diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 272646ce2..d78462d35 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -49,4 +49,10 @@ padding: 4px 10px; text-align: center; } + + .brewLookup{ + h2 { + margin-top: 0px; + } + } } \ No newline at end of file From 7e8078767982710bd05285ff2138a0abd60b793d Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Jun 2024 22:18:12 +1200 Subject: [PATCH 46/89] Tweak styling --- client/admin/lockTools/lockTools.less | 1 + 1 file changed, 1 insertion(+) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index d78462d35..9bf2b39ef 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -51,6 +51,7 @@ } .brewLookup{ + min-height: 175px; h2 { margin-top: 0px; } From 0803362a504e5c2c4bacc8d58533cd598e8a54e0 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Jun 2024 22:29:47 +1200 Subject: [PATCH 47/89] More styling tweaks --- client/admin/lockTools/lockTools.less | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 9bf2b39ef..82341eddb 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -44,11 +44,13 @@ } } - td { - border: 1px solid #333333; + th, td { padding: 4px 10px; text-align: center; } + td{ + border: 1px solid #333333; + } .brewLookup{ min-height: 175px; From 7094d43ee5169d725b48e74a64cb8e9a821bbc1a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 29 Jun 2024 15:29:02 +1200 Subject: [PATCH 48/89] Shift API calls to /api from /admin --- client/admin/lockTools/lockTools.jsx | 22 +++++++++++---------- client/homebrew/utils/request-middleware.js | 3 ++- server/admin.api.js | 10 +++++----- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 2135425eb..31520b88c 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -3,7 +3,8 @@ require('./lockTools.less'); const React = require('react'); const createClass = require('create-react-class'); -const request = require('superagent'); +// const request = require('superagent'); +const request = require('../../homebrew/utils/request-middleware.js'); const LockTools = createClass({ getInitialState : function() { @@ -18,7 +19,7 @@ const LockTools = createClass({ }, updateReviewCount : async function() { - const newCount = await request.get('/admin/lock') + const newCount = await request.get('/api/lock/count') .then((res)=>{return res.body?.count || 'Unknown';}); if(newCount != this.state.reviewCount){ this.setState({ @@ -33,13 +34,13 @@ const LockTools = createClass({

Number of brews currently locked: {this.state.reviewCount}


- +

- - + +

; @@ -48,11 +49,12 @@ const LockTools = createClass({ const LockBrew = createClass({ getInitialState : function() { + // Default values return { brewId : '', - code : 1000, + code : 455, editMessage : '', - shareMessage : '', + shareMessage : 'This Brew has been locked.', result : {} }; }, @@ -73,7 +75,7 @@ const LockBrew = createClass({ applied : new Date }; - request.post(`/admin/lock/${this.state.brewId}`) + request.post(`/api/lock/${this.state.brewId}`) .send(newLock) .set('Content-Type', 'application/json') .then((response)=>{ @@ -167,7 +169,7 @@ const LockTable = createClass({ getDefaultProps : function() { return { title : '', - fetchURL : '/admin/locks', + fetchURL : '/api/locks', resultName : '', propertyNames : ['shareId'] }; @@ -236,7 +238,7 @@ const LockTable = createClass({ const LockLookup = createClass({ getDefaultProps : function() { return { - fetchURL : '/admin/lookup' + fetchURL : '/api/lookup' }; }, diff --git a/client/homebrew/utils/request-middleware.js b/client/homebrew/utils/request-middleware.js index f6bc2571b..80ee58f5d 100644 --- a/client/homebrew/utils/request-middleware.js +++ b/client/homebrew/utils/request-middleware.js @@ -1,6 +1,7 @@ const request = require('superagent'); +const version = require('../../../package.json').version; -const addHeader = (request)=>request.set('Homebrewery-Version', global.version); +const addHeader = (request)=>request.set('Homebrewery-Version', version); const requestMiddleware = { get : (path)=>addHeader(request.get(path)), diff --git a/server/admin.api.js b/server/admin.api.js index 8f997aed9..1bf597bb4 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -139,7 +139,7 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ } }); -router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ +router.get('/api/lock/count', mw.adminOnly, async (req, res)=>{ try { const countLocksQuery = { lock : { $exists: true } @@ -157,7 +157,7 @@ router.get('/admin/lock', mw.adminOnly, async (req, res)=>{ } }); -router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ +router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ try { const lock = req.body; lock.applied = new Date; @@ -186,7 +186,7 @@ router.post('/admin/lock/:id', mw.adminOnly, async (req, res)=>{ } }); -router.put('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ +router.put('/api/unlock/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id @@ -210,7 +210,7 @@ router.put('/admin/unlock/:id', mw.adminOnly, async (req, res)=>{ return res.json({ status: 'UNLOCKED', detail: `Lock removed from brew ID ${req.params.id}` }); }); -router.get('/admin/lock/reviews', mw.adminOnly, async (req, res)=>{ +router.get('/api/lock/reviews', mw.adminOnly, async (req, res)=>{ try { const countReviewsPipeline = [ { @@ -260,7 +260,7 @@ router.put('/admin/lock/review/request/:id', async (req, res)=>{ } }); -router.put('/admin/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ +router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ try { const filter = { shareId : req.params.id, From b0687493803eda0e8500a8223c2d34ec01b141ec Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 25 Jul 2024 22:11:14 +1200 Subject: [PATCH 49/89] Move copy ID to clipboard to separate button --- client/admin/lockTools/lockTools.jsx | 7 +++++-- client/admin/lockTools/lockTools.less | 10 +++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 31520b88c..b5c94399a 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -207,23 +207,26 @@ const LockTable = createClass({ {this.state.result[this.props.resultName] && <>

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

-

Click a row to copy the Share ID to the clipboard

{this.props.propertyNames.map((name, idx)=>{ return ; })} + + {this.state.result[this.props.resultName].map((result, resultIdx)=>{ - return {navigator.clipboard.writeText(result.shareId.toString());}}> + return {this.props.propertyNames.map((name, nameIdx)=>{ return ; })} + + ; })} diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 82341eddb..5737a32e0 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -39,8 +39,16 @@ } .lockTable{ - td:hover { + cursor: default; + .row:hover { + background-color: #ccc; + color: #000; + } + .icon { cursor: pointer; + &:hover{ + text-shadow: 0px 0px 6px black; + } } } From ac89f428b2824425a0ee9e3106d7d6127c167ac8 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 27 Mar 2025 18:25:56 +1300 Subject: [PATCH 50/89] Post merge fixes --- client/admin/admin.jsx | 6 +++--- client/admin/lockTools/lockTools.jsx | 4 ++-- client/homebrew/utils/request-middleware.js | 4 ++-- server/admin.api.js | 2 ++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 025d78abf..f59162e1d 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -3,9 +3,9 @@ import React, { useEffect, useState } from 'react'; const BrewUtils = require('./brewUtils/brewUtils.jsx'); const NotificationUtils = require('./notificationUtils/notificationUtils.jsx'); import AuthorUtils from './authorUtils/authorUtils.jsx'; -const LockTools = require('./lockTools/lockTools.jsx'); +import LockTools from './lockTools/lockTools.jsx'; -const tabGroups = ['brew', 'notifications', 'authors']; +const tabGroups = ['brew', 'notifications', 'authors', 'locks']; const Admin = ()=>{ const [currentTab, setCurrentTab] = useState('brew'); @@ -41,7 +41,7 @@ const Admin = ()=>{ {currentTab === 'brew' && } {currentTab === 'notifications' && } {currentTab === 'authors' && } - {currentTab === 'locks' && } + {currentTab === 'locks' && } ); diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index b5c94399a..5f8a4ba39 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -4,7 +4,7 @@ const React = require('react'); const createClass = require('create-react-class'); // const request = require('superagent'); -const request = require('../../homebrew/utils/request-middleware.js'); +import request from '../../homebrew/utils/request-middleware.js'; const LockTools = createClass({ getInitialState : function() { @@ -226,7 +226,7 @@ const LockTable = createClass({ ; })} - + ; })} diff --git a/client/homebrew/utils/request-middleware.js b/client/homebrew/utils/request-middleware.js index 22609dadb..deb08d265 100644 --- a/client/homebrew/utils/request-middleware.js +++ b/client/homebrew/utils/request-middleware.js @@ -1,8 +1,8 @@ -const version = require('../../../package.json').version; +import packageJSON from '../../../package.json' with { type: 'json' }; import request from 'superagent'; -const addHeader = (request)=>request.set('Homebrewery-Version', version); +const addHeader = (request)=>request.set('Homebrewery-Version', packageJSON.version); const requestMiddleware = { get : (path)=>addHeader(request.get(path)), diff --git a/server/admin.api.js b/server/admin.api.js index 3685492d5..96a21c8a7 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -305,6 +305,8 @@ router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ } catch (error) { console.error(error); return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); + }; +}); // ####################### NOTIFICATIONS From 82e711a344e0b5f3463bfdf51ebd6897dbcc99bf Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 6 Apr 2025 19:09:11 +1200 Subject: [PATCH 51/89] Shift request calls to import --- .../pages/editPage/lockNotification/lockNotification.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx index da79ff265..ed3802c4c 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx @@ -1,6 +1,6 @@ -require('./lockNotification.less'); -const React = require('react'); -const request = require('../../../utils/request-middleware.js'); +import './lockNotification.less'; +import * as React from 'react'; +import request from '../../../utils/request-middleware.js'; import Dialog from '../../../../components/dialog.jsx'; function LockNotification(props) { From cb060ae8b11525db420053f1cfb964458096917b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 6 Apr 2025 19:26:39 +1200 Subject: [PATCH 52/89] Fix state of "Request Review" button on page load --- client/homebrew/pages/editPage/editPage.jsx | 2 +- .../pages/editPage/lockNotification/lockNotification.jsx | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index dc2520373..856a0e347 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -443,7 +443,7 @@ const EditPage = createClass({ {this.renderNavbar()} - {this.props.brew.lock && } + {this.props.brew.lock && }
{}, - lock : {}, + shareId : 0, + disableLock : ()=>{}, + lock : {}, + reviewRequested : false, ...props }; - const [reviewState, setReviewState] = React.useState(false); + const [reviewState, setReviewState] = React.useState(props.reviewRequested); const removeLock = async ()=>{ await request.put(`/admin/lock/review/request/${props.shareId}`) From 0a4ac7a35a01acd47b545167a1e3dbff40fac137 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 6 Apr 2025 19:48:32 +1200 Subject: [PATCH 53/89] Adjust location of package.json --- server/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/app.js b/server/app.js index 6bd0c7c9a..fc0954efd 100644 --- a/server/app.js +++ b/server/app.js @@ -2,10 +2,11 @@ // Set working directory to project root import { dirname } from 'path'; import { fileURLToPath } from 'url'; -import packageJSON from './../package.json' with { type: 'json' }; const __dirname = dirname(fileURLToPath(import.meta.url)); process.chdir(`${__dirname}/..`); + +import packageJSON from '../package.json' with { type: 'json' }; const version = packageJSON.version; import _ from 'lodash'; From e2b38829f2ac7db54b551f5019cd63a8f4ed87bf Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:25:42 +1200 Subject: [PATCH 54/89] Refactor /api/lock/count --- server/admin.api.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 96a21c8a7..9207daf71 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -165,21 +165,18 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ }); router.get('/api/lock/count', mw.adminOnly, async (req, res)=>{ - try { - const countLocksQuery = { - lock : { $exists: true } - }; - const count = await HomebrewModel.countDocuments(countLocksQuery) - .then((result)=>{ - return result; - }); - return res.json({ - count + + const countLocksQuery = { + lock : { $exists: true } + }; + const count = await HomebrewModel.countDocuments(countLocksQuery) + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', detail: 'Unable to get lock count', error }); }); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', detail: 'Unable to get lock count', error }); - } + + return res.json({ count }); + }); router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ From fa4b2ae0e362895b888337da96a9b6775aa41c38 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:27:32 +1200 Subject: [PATCH 55/89] Refactor /api/lock --- server/admin.api.js | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 9207daf71..30396d1db 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -180,32 +180,33 @@ router.get('/api/lock/count', mw.adminOnly, async (req, res)=>{ }); router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ - try { - const lock = req.body; - lock.applied = new Date; - const filter = { - shareId : req.params.id - }; + const lock = req.body; + lock.applied = new Date; - const brew = await HomebrewModel.findOne(filter); + const filter = { + shareId : req.params.id + }; - if(brew.lock) { - // console.log('ALREADY LOCKED'); - return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); - } + const brew = await HomebrewModel.findOne(filter); - brew.lock = lock; - brew.markModified('lock'); - - await brew.save(); - - // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); + if(brew.lock) { + // console.log('ALREADY LOCKED'); + return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); } + + brew.lock = lock; + brew.markModified('lock'); + + await brew.save() + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); + }); + + // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); + }); router.put('/api/unlock/:id', mw.adminOnly, async (req, res)=>{ From 3cf98617f5b8ee0f4a1c82f5f8a8b247ba19ed82 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:33:39 +1200 Subject: [PATCH 56/89] Refactor /api/lock/reviews --- server/admin.api.js | 53 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 30396d1db..45e8ecc57 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -210,47 +210,48 @@ router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ }); router.put('/api/unlock/:id', mw.adminOnly, async (req, res)=>{ - try { - const filter = { - shareId : req.params.id - }; - const brew = await HomebrewModel.findOne(filter); + const filter = { + shareId : req.params.id + }; - if(!brew.lock) return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); + const brew = await HomebrewModel.findOne(filter); - brew.lock = undefined; - brew.markModified('lock'); + if(!brew.lock) return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); - await brew.save(); + brew.lock = undefined; + brew.markModified('lock'); + + await brew.save() + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', detail: `Unable to clear lock on brew ${req.params.id}`, error }); + }); + + // console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); - // console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to clear lock on brew ${req.params.id}`, error }); - } return res.json({ status: 'UNLOCKED', detail: `Lock removed from brew ID ${req.params.id}` }); }); router.get('/api/lock/reviews', mw.adminOnly, async (req, res)=>{ - try { - const countReviewsPipeline = [ - { + const countReviewsPipeline = [ + { $match : { 'lock.reviewRequested' : { '$exists': 1 } }, - } - ]; - const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline); - return res.json({ - reviewDocuments + } + ]; + const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline) + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', detail: 'Unable to get review collection', error }); }); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', detail: 'Unable to get review collection', error }); - } + return res.json({ + reviewDocuments + }); + }); router.put('/admin/lock/review/request/:id', async (req, res)=>{ From 30430cb8cbcf43032df3a14b9c6283f647d9f339 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:36:33 +1200 Subject: [PATCH 57/89] Refactor /admin/lock/review/request --- server/admin.api.js | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 45e8ecc57..dbfe4bc5c 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -257,31 +257,31 @@ router.get('/api/lock/reviews', mw.adminOnly, async (req, res)=>{ router.put('/admin/lock/review/request/:id', async (req, res)=>{ // === This route is NOT Admin only === // Any user can request a review of their document - try { - const filter = { - shareId : req.params.id, - lock : { $exists: 1 } - }; + const filter = { + shareId : req.params.id, + lock : { $exists: 1 } + }; - const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); }; + const brew = await HomebrewModel.findOne(filter); + if(!brew) { return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); }; - if(brew.lock.reviewRequested){ - // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); - }; + if(brew.lock.reviewRequested){ + // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + }; - brew.lock.reviewRequested = new Date(); - brew.markModified('lock'); + brew.lock.reviewRequested = new Date(); + brew.markModified('lock'); - await brew.save(); + await brew.save() + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); + }); + + // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); - // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); - } }); router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ From 41bd27b573d25b3dda910b1fca95646eaf271b31 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:37:35 +1200 Subject: [PATCH 58/89] Refactor /api/lock/review/remove --- server/admin.api.js | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index dbfe4bc5c..2526a5951 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -285,26 +285,27 @@ router.put('/admin/lock/review/request/:id', async (req, res)=>{ }); router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ - try { - const filter = { - shareId : req.params.id, - 'lock.reviewRequested' : { $exists: 1 } - }; - const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.json({ status: 'REVIEW REQUEST NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; - - brew.lock.reviewRequested = undefined; - brew.markModified('lock'); - - await brew.save(); - - // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); - } catch (error) { - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); + const filter = { + shareId : req.params.id, + 'lock.reviewRequested' : { $exists: 1 } }; + + const brew = await HomebrewModel.findOne(filter); + if(!brew) { return res.json({ status: 'REVIEW REQUEST NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; + + brew.lock.reviewRequested = undefined; + brew.markModified('lock'); + + await brew.save() + .catch((error)=>{ + console.error(error); + return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); + }); + + // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); + return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); + }); // ####################### NOTIFICATIONS From 0bca3393d4f70cfd8caa080372e31771dd41d362 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 08:39:33 +1200 Subject: [PATCH 59/89] Add LOCK header in comment --- server/admin.api.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 2526a5951..a2dc76498 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -164,6 +164,8 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ } }); +// ####################### LOCKS + router.get('/api/lock/count', mw.adminOnly, async (req, res)=>{ const countLocksQuery = { From 99c342f19b89c777875c725f2fabd54024e2a479 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 14:38:25 +1200 Subject: [PATCH 60/89] Use throw in Lock API calls --- client/admin/lockTools/lockTools.jsx | 15 ++++-- .../pages/errorPage/errors/errorIndex.js | 22 ++++++++ server/admin.api.js | 52 ++++++++++--------- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 5f8a4ba39..a1cffce24 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -7,6 +7,7 @@ const createClass = require('create-react-class'); import request from '../../homebrew/utils/request-middleware.js'; const LockTools = createClass({ + displayName : 'LockTools', getInitialState : function() { return { fetching : false, @@ -48,6 +49,7 @@ const LockTools = createClass({ }); const LockBrew = createClass({ + displayName : 'LockBrew', getInitialState : function() { // Default values return { @@ -80,6 +82,9 @@ const LockBrew = createClass({ .set('Content-Type', 'application/json') .then((response)=>{ this.setState({ result: response.body }); + }) + .catch((err)=>{ + this.setState({ result: err.response.body }); }); }, @@ -166,6 +171,7 @@ const LockBrew = createClass({ }); const LockTable = createClass({ + displayName : 'LockTable', getDefaultProps : function() { return { title : '', @@ -188,7 +194,7 @@ const LockTable = createClass({ request.get(this.props.fetchURL) .then((res)=>this.setState({ result: res.body })) - .catch((err)=>this.setState({ error: err })) + .catch((err)=>this.setState({ result: err.response.body })) .finally(()=>{ this.setState({ searching: false }); }); @@ -239,6 +245,7 @@ const LockTable = createClass({ }); const LockLookup = createClass({ + displayName : 'LockLookup', getDefaultProps : function() { return { fetchURL : '/api/lookup' @@ -263,14 +270,14 @@ const LockLookup = createClass({ request.put(`${this.props.fetchURL}/${this.state.query}`) .then((res)=>this.setState({ result: res.body })) - .catch((err)=>this.setState({ error: err })) + .catch((err)=>this.setState({ result: err.response.body })) .finally(()=>{ this.setState({ searching: false }); }); }, renderResult : function(){ - return <> + return

Result:

{name}clipview
{result[name].toString()} {navigator.clipboard.writeText(result.shareId.toString());}}>
{navigator.clipboard.writeText(result.shareId.toString());}}>
@@ -283,7 +290,7 @@ const LockLookup = createClass({ })}
- ; +
; }, render : function() { diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index 9584a14b9..d00aec8d5 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -201,6 +201,28 @@ const errorIndex = (props)=>{ ## Access Denied You need to provide correct administrator credentials to access this page.`, + // ####### Lock Errors + + '60' : dedent`General Lock Error`, + + '61' : dedent`Lock Error: Unable to get lock count`, + + '62' : dedent`Lock Error: Cannot lock`, + + '63' : dedent`Lock Error: Cannot lock - brew not found`, + + '64' : dedent`Lock Error: Cannot lock - already locked`, + + '65' : dedent`Lock Error: Cannot unlock`, + + '66' : dedent`Lock Error: Cannot unlock - brew not found`, + + '67' : dedent`Lock Error: Cannot unlock - not locked`, + + '68' : dedent`Lock Error: Cannot get pending reviews`, + + // ####### Other Errors + '90' : dedent` An unexpected error occurred while looking for these brews. Try again in a few minutes.`, diff --git a/server/admin.api.js b/server/admin.api.js index a2dc76498..12a35cf89 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -166,22 +166,25 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ // ####################### LOCKS -router.get('/api/lock/count', mw.adminOnly, async (req, res)=>{ +router.get('/api/lock/throw', asyncHandler(async ()=>{ + throw { HBErrorCode: '60', code: 500, message: 'Thrown deliberately' }; +})); + +router.get('/api/lock/count', mw.adminOnly, asyncHandler(async (req, res)=>{ const countLocksQuery = { lock : { $exists: true } }; const count = await HomebrewModel.countDocuments(countLocksQuery) .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', detail: 'Unable to get lock count', error }); + throw { name: 'Lock Count Error', message: 'Unable to get lock count', status: 500, HBErrorCode: '61', error }; }); return res.json({ count }); -}); +})); -router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ +router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const lock = req.body; lock.applied = new Date; @@ -192,9 +195,11 @@ router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ const brew = await HomebrewModel.findOne(filter); + if(!brew) throw { name: 'Brew Not Found', message: 'Cannot find brew to lock', shareId: req.params.id, status: 500, HBErrorCode: '63' }; + if(brew.lock) { // console.log('ALREADY LOCKED'); - return res.json({ status: 'ALREADY LOCKED', detail: `Lock already exists on brew ${req.params.id} - ${brew.title}` }); + throw { name: 'Already Locked', message: 'Lock already exists on brew', shareId: req.params.id, title: brew.title, status: 500, HBErrorCode: '64' }; } brew.lock = lock; @@ -202,16 +207,15 @@ router.post('/api/lock/:id', mw.adminOnly, async (req, res)=>{ await brew.save() .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', error, message: `Unable to set lock on brew ${req.params.id}` }); + throw { name: 'Already Locked', message: 'Unable to set lock', shareId: req.params.id, status: 500, HBErrorCode: '62', error }; }); // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'LOCKED', detail: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); + return res.json({ name: 'LOCKED', message: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); -}); +})); -router.put('/api/unlock/:id', mw.adminOnly, async (req, res)=>{ +router.put('/api/unlock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const filter = { shareId : req.params.id @@ -219,24 +223,25 @@ router.put('/api/unlock/:id', mw.adminOnly, async (req, res)=>{ const brew = await HomebrewModel.findOne(filter); - if(!brew.lock) return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); + if(!brew) throw { name: 'Brew Not Found', message: 'Cannot find brew to unlock', shareId: req.params.id, status: 500, HBErrorCode: '66' }; + + if(!brew.lock) throw { name: 'Not Locked', message: 'Cannot unlock as brew is not locked', shareId: req.params.id, status: 500, HBErrorCode: '67' }; brew.lock = undefined; brew.markModified('lock'); await brew.save() .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to clear lock on brew ${req.params.id}`, error }); + throw { name: 'Cannot Unlock', message: 'Unable to clear lock', shareId: req.params.id, status: 500, HBErrorCode: '65', error }; }); // console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'UNLOCKED', detail: `Lock removed from brew ID ${req.params.id}` }); -}); + return res.json({ name: 'Unlocked', message: `Lock removed from brew ID ${req.params.id}` }); +})); -router.get('/api/lock/reviews', mw.adminOnly, async (req, res)=>{ +router.get('/api/lock/reviews', mw.adminOnly, asyncHandler(async (req, res)=>{ const countReviewsPipeline = [ { $match : @@ -247,16 +252,15 @@ router.get('/api/lock/reviews', mw.adminOnly, async (req, res)=>{ ]; const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline) .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', detail: 'Unable to get review collection', error }); + throw { name: 'Unable to get reviews', message: 'Unable to get review collection', status: 500, HBErrorCode: '68', error }; }); return res.json({ reviewDocuments }); -}); +})); -router.put('/admin/lock/review/request/:id', async (req, res)=>{ +router.put('/admin/lock/review/request/:id', asyncHandler(async (req, res)=>{ // === This route is NOT Admin only === // Any user can request a review of their document const filter = { @@ -284,9 +288,9 @@ router.put('/admin/lock/review/request/:id', async (req, res)=>{ // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); -}); +})); -router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ +router.put('/api/lock/review/remove/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const filter = { shareId : req.params.id, @@ -308,7 +312,7 @@ router.put('/api/lock/review/remove/:id', mw.adminOnly, async (req, res)=>{ // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); -}); +})); // ####################### NOTIFICATIONS From bd145f17da5b7af3cfd0106e8d38a0e1c2cfb8f8 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 14:38:37 +1200 Subject: [PATCH 61/89] Tweak styling --- client/admin/lockTools/lockTools.less | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 5737a32e0..0b6cb615d 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -39,6 +39,7 @@ } .lockTable{ + break-inside: avoid; cursor: default; .row:hover { background-color: #ccc; @@ -56,11 +57,12 @@ padding: 4px 10px; text-align: center; } - td{ + table, td{ border: 1px solid #333333; } .brewLookup{ + break-inside: avoid; min-height: 175px; h2 { margin-top: 0px; From 1e35e1096fd426197b712b84faec82e9d049eba0 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 14:39:33 +1200 Subject: [PATCH 62/89] Reduce data retrieved for brews with requested reviews --- server/admin.api.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 12a35cf89..6a3a943d5 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -248,6 +248,12 @@ router.get('/api/lock/reviews', mw.adminOnly, asyncHandler(async (req, res)=>{ { 'lock.reviewRequested' : { '$exists': 1 } }, + }, + { + $project : { + shareId : 1, + title : 1 + } } ]; const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline) From 4c4a023f34305073f8677331aca0fe6e475ac7a6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 15:59:06 +1200 Subject: [PATCH 63/89] Fix lock notification message --- .../pages/editPage/lockNotification/lockNotification.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx index cc77e6204..9c8bb2c47 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx @@ -8,6 +8,7 @@ function LockNotification(props) { shareId : 0, disableLock : ()=>{}, lock : {}, + message : 'Unable to retrieve Lock Message', reviewRequested : false, ...props }; @@ -31,7 +32,7 @@ function LockNotification(props) {

This brew been locked by the Administrators. It will not be accessible by any method other than the Editor until the lock is removed.


LOCK REASON

-

{props.lock.editMessage || 'Unable to retrieve Lock Message'}

+

{props.message}


Once you have resolved this issue, click REQUEST LOCK REMOVAL to notify the Administrators for review.

Click CONTINUE TO EDITOR to temporarily hide this notification; it will reappear the next time the page is reloaded.

From a594d456116dfb069ae9c750605884c072474fc0 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 15:59:34 +1200 Subject: [PATCH 64/89] Remove unnecessary default option --- .../pages/editPage/lockNotification/lockNotification.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx index 9c8bb2c47..0750a599c 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.jsx @@ -23,7 +23,7 @@ function LockNotification(props) { }; const renderReviewButton = function(){ - if(reviewState || props.lock.reviewRequested){ return ; }; + if(reviewState){ return ; }; return ; }; From ef6f022ea3fb6781488c6a8aed311a8ca008aa72 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 15:59:54 +1200 Subject: [PATCH 65/89] Tweak lock notification styling --- .../pages/editPage/lockNotification/lockNotification.less | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.less b/client/homebrew/pages/editPage/lockNotification/lockNotification.less index de2692ec0..88133ea98 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.less +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.less @@ -14,6 +14,7 @@ margin : 10px; color : white; background-color : #333333; + padding : 2px 15px; &.inactive, &:hover { From a218b87215305e4828454191859f0eda63796cf7 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 16:32:33 +1200 Subject: [PATCH 66/89] Shift remaining lock API functions to use throw --- .../pages/errorPage/errors/errorIndex.js | 28 +++++++++++++------ server/admin.api.js | 18 ++++++------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index d00aec8d5..2f0d4599b 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -203,23 +203,33 @@ const errorIndex = (props)=>{ // ####### Lock Errors - '60' : dedent`General Lock Error`, + '60' : dedent`Lock Error: General`, - '61' : dedent`Lock Error: Unable to get lock count`, + '61' : dedent`Lock Get Error: Unable to get lock count`, - '62' : dedent`Lock Error: Cannot lock`, + '62' : dedent`Lock Set Error: Cannot lock`, - '63' : dedent`Lock Error: Cannot lock - brew not found`, + '63' : dedent`Lock Set Error: Brew not found`, - '64' : dedent`Lock Error: Cannot lock - already locked`, + '64' : dedent`Lock Set Error: Already locked`, - '65' : dedent`Lock Error: Cannot unlock`, + '65' : dedent`Lock Remove Error: Cannot unlock`, - '66' : dedent`Lock Error: Cannot unlock - brew not found`, + '66' : dedent`Lock Remove Error: Brew not found`, - '67' : dedent`Lock Error: Cannot unlock - not locked`, + '67' : dedent`Lock Remove Error: Not locked`, - '68' : dedent`Lock Error: Cannot get pending reviews`, + '68' : dedent`Lock Get Review Error: Cannot get review requests`, + + '69' : dedent`Lock Set Review Error: Cannot set review request`, + + '70' : dedent`Lock Set Review Error: Brew not found`, + + '71' : dedent`Lock Set Review Error: Review already requested`, + + '72' : dedent`Lock Remove Review Error: Cannot clear review request`, + + '73' : dedent`Lock Remove Review Error: Brew not found`, // ####### Other Errors diff --git a/server/admin.api.js b/server/admin.api.js index 6a3a943d5..77de3fd52 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -258,7 +258,7 @@ router.get('/api/lock/reviews', mw.adminOnly, asyncHandler(async (req, res)=>{ ]; const reviewDocuments = await HomebrewModel.aggregate(countReviewsPipeline) .catch((error)=>{ - throw { name: 'Unable to get reviews', message: 'Unable to get review collection', status: 500, HBErrorCode: '68', error }; + throw { name: 'Can Not Get Reviews', message: 'Unable to get review collection', status: 500, HBErrorCode: '68', error }; }); return res.json({ reviewDocuments @@ -275,11 +275,11 @@ router.put('/admin/lock/review/request/:id', asyncHandler(async (req, res)=>{ }; const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.json({ status: 'NOT LOCKED', detail: `Brew ID ${req.params.id} is not locked!` }); }; + if(!brew) { throw { name: 'Brew Not Found', message: `Cannot find a locked brew with ID ${req.params.id}`, code: 500, HBErrorCode: '70' }; }; if(brew.lock.reviewRequested){ // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'ALREADY REQUESTED', detail: `Review already requested for brew ${brew.shareId} - ${brew.title}` }); + throw { name: 'Review Already Requested', message: `Review already requested for brew ${brew.shareId} - ${brew.title}`, code: 500, HBErrorCode: '71' }; }; brew.lock.reviewRequested = new Date(); @@ -287,12 +287,11 @@ router.put('/admin/lock/review/request/:id', asyncHandler(async (req, res)=>{ await brew.save() .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to set request for review on brew ID ${req.params.id}`, error }); + throw { name: 'Can Not Set Review Request', message: `Unable to set request for review on brew ID ${req.params.id}`, code: 500, HBErrorCode: '69', error }; }); // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUESTED', detail: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); + return res.json({ name: 'Review Requested', message: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); })); @@ -304,19 +303,18 @@ router.put('/api/lock/review/remove/:id', mw.adminOnly, asyncHandler(async (req, }; const brew = await HomebrewModel.findOne(filter); - if(!brew) { return res.json({ status: 'REVIEW REQUEST NOT REMOVED', detail: `Brew ID ${req.params.id} does not have a review pending!` }); }; + if(!brew) { throw { name: 'Can Not Clear Review Request', message: `Brew ID ${req.params.id} does not have a review pending!`, HBErrorCode: '73' }; }; brew.lock.reviewRequested = undefined; brew.markModified('lock'); await brew.save() .catch((error)=>{ - console.error(error); - return res.json({ status: 'ERROR', detail: `Unable to remove request for review on brew ID ${req.params.id}`, error }); + throw { name: 'Can Not Clear Review Request', message: `Unable to remove request for review on brew ID ${req.params.id}`, HBErrorCode: '72', error }; }); // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); - return res.json({ status: 'REVIEW REQUEST REMOVED', detail: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); + return res.json({ name: 'Review Request Cleared', message: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); })); From e2f2b2962f47532df8079e2294718f0b62a0cc27 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 17:34:31 +1200 Subject: [PATCH 67/89] Revert request middleware change as it is no longer necessary --- client/homebrew/utils/request-middleware.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/homebrew/utils/request-middleware.js b/client/homebrew/utils/request-middleware.js index deb08d265..01a9d2571 100644 --- a/client/homebrew/utils/request-middleware.js +++ b/client/homebrew/utils/request-middleware.js @@ -1,8 +1,6 @@ -import packageJSON from '../../../package.json' with { type: 'json' }; import request from 'superagent'; - -const addHeader = (request)=>request.set('Homebrewery-Version', packageJSON.version); +const addHeader = (request)=>request.set('Homebrewery-Version', global.version); const requestMiddleware = { get : (path)=>addHeader(request.get(path)), From 26aa302714ad9364ee34008741543f1e6a1f9399 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 20:04:45 +1200 Subject: [PATCH 68/89] Remove debugging test route --- server/admin.api.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 77de3fd52..8d8500c37 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -166,10 +166,6 @@ router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ // ####################### LOCKS -router.get('/api/lock/throw', asyncHandler(async ()=>{ - throw { HBErrorCode: '60', code: 500, message: 'Thrown deliberately' }; -})); - router.get('/api/lock/count', mw.adminOnly, asyncHandler(async (req, res)=>{ const countLocksQuery = { From ab9b151b8a583e85806b2ebde33b17c99335f0e3 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 20:52:35 +1200 Subject: [PATCH 69/89] Add API route to return all locked brews --- server/admin.api.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index 8d8500c37..f770e4adf 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -180,6 +180,31 @@ router.get('/api/lock/count', mw.adminOnly, asyncHandler(async (req, res)=>{ })); +router.get('/api/locks', mw.adminOnly, asyncHandler(async (req, res)=>{ + const countLocksPipeline = [ + { + $match : + { + 'lock' : { '$exists': 1 } + }, + }, + { + $project : { + shareId : 1, + title : 1 + } + } + ]; + const lockedDocuments = await HomebrewModel.aggregate(countLocksPipeline) + .catch((error)=>{ + throw { name: 'Can Not Get Locked Brews', message: 'Unable to get locked brew collection', status: 500, HBErrorCode: '68', error }; + }); + return res.json({ + lockedDocuments + }); + +})); + router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const lock = req.body; From 7451dda632415a875360d4ca6ba0e9fc29eca1cf Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 20:54:21 +1200 Subject: [PATCH 70/89] Add locked brews table --- client/admin/lockTools/lockTools.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index a1cffce24..253d5f006 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -35,7 +35,9 @@ const LockTools = createClass({

Number of brews currently locked: {this.state.reviewCount}


- + +
+

@@ -175,6 +177,7 @@ const LockTable = createClass({ getDefaultProps : function() { return { title : '', + text : '', fetchURL : '/api/locks', resultName : '', propertyNames : ['shareId'] @@ -212,7 +215,7 @@ const LockTable = createClass({ {this.state.result[this.props.resultName] && <> -

Total Reviews Waiting: {this.state.result[this.props.resultName].length}

+

{this.props.text}: {this.state.result[this.props.resultName].length}

From f74c2049a767e4d751b9f279c7a93e37bf9b5609 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 20:54:44 +1200 Subject: [PATCH 71/89] Rename Edit and Share page message fields --- client/admin/lockTools/lockTools.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 253d5f006..7c7580edf 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -127,12 +127,12 @@ const LockBrew = createClass({


From 61efc2d1522aba1fa24118a68bf431f3d7a86f23 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 21:12:37 +1200 Subject: [PATCH 72/89] Tweak styling --- client/admin/lockTools/lockTools.less | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 0b6cb615d..2666b4bb0 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -12,7 +12,7 @@ line-height: 1.5em; input { float: right; - width: 70%; + width: 65%; margin-left: 10px; } } @@ -68,4 +68,8 @@ margin-top: 0px; } } + + button i { + padding-left: 5px; + } } \ No newline at end of file From 7a1042fedd7abec5161783bb668d14a3d87f7fef Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 22:02:08 +1200 Subject: [PATCH 73/89] Stylelint fixes --- client/admin/lockTools/lockTools.less | 118 ++++++++---------- .../lockNotification/lockNotification.less | 6 +- 2 files changed, 55 insertions(+), 69 deletions(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index 2666b4bb0..f6e7ea9dd 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -1,75 +1,63 @@ .lockTools { - .lockBrew { - columns: 2; + .lockBrew { + columns : 2; - .lockForm { - break-inside: avoid; + .lockForm { + break-inside : avoid; - label { - width: 100%; - display: inline-block; - text-align: right; - line-height: 1.5em; - input { - float: right; - width: 65%; - margin-left: 10px; - } - } - } + label { + display : inline-block; + width : 100%; + line-height : 1.5em; + text-align : right; + input { + float : right; + width : 65%; + margin-left : 10px; + } + input.checkbox { + width : 1.5em; + height : 1.5em; + } + } + } - .lockSuggestions { - break-inside: avoid; - columns: 2; - line-height: 1.2em; - h2 { - column-span: all; - } - h3 { - margin-top: 0px; - } - b { - font-weight: 600; - } + .lockSuggestions { + line-height : 1.2em; + break-inside : avoid; + columns : 2; + h2 { column-span : all; } + h3 { margin-top : 0px; } + b { font-weight : 600; } - .lockCodes { - break-inside: avoid; - } - } - } + .lockCodes { break-inside : avoid; } + } + } - .lockTable{ - break-inside: avoid; - cursor: default; - .row:hover { - background-color: #ccc; - color: #000; - } - .icon { - cursor: pointer; - &:hover{ - text-shadow: 0px 0px 6px black; - } - } - } + .lockTable { + cursor : default; + break-inside : avoid; + .row:hover { + color : #000000; + background-color : #CCCCCC; + } + .icon { + cursor : pointer; + &:hover { text-shadow : 0px 0px 6px black; } + } + } - th, td { - padding: 4px 10px; - text-align: center; - } - table, td{ - border: 1px solid #333333; - } + th, td { + padding : 4px 10px; + text-align : center; + } + table, td { border : 1px solid #333333; } - .brewLookup{ - break-inside: avoid; - min-height: 175px; - h2 { - margin-top: 0px; - } - } + .brewLookup { + min-height : 175px; + break-inside : avoid; + h2 { margin-top : 0px; } + } - button i { - padding-left: 5px; - } + button i { padding-left : 5px; } } \ No newline at end of file diff --git a/client/homebrew/pages/editPage/lockNotification/lockNotification.less b/client/homebrew/pages/editPage/lockNotification/lockNotification.less index 88133ea98..930b070c4 100644 --- a/client/homebrew/pages/editPage/lockNotification/lockNotification.less +++ b/client/homebrew/pages/editPage/lockNotification/lockNotification.less @@ -11,15 +11,13 @@ &::backdrop { background-color : #000000AA; } button { + padding : 2px 15px; margin : 10px; color : white; background-color : #333333; - padding : 2px 15px; &.inactive, - &:hover { - background-color : #777777; - } + &:hover { background-color : #777777; } } h1, h3 { From f8566392f6ec9fcf8e12cfb07eefbfd7693cd747 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 22:02:28 +1200 Subject: [PATCH 74/89] Add overwrite option for updating locks --- client/admin/lockTools/lockTools.jsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index 7c7580edf..c528fb13d 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -59,7 +59,8 @@ const LockBrew = createClass({ code : 455, editMessage : '', shareMessage : 'This Brew has been locked.', - result : {} + result : {}, + overwrite : false }; }, @@ -73,6 +74,7 @@ const LockBrew = createClass({ e.preventDefault(); if(!this.state.editMessage) return; const newLock = { + overwrite : this.state.overwrite, code : parseInt(this.state.code) || 100, editMessage : this.state.editMessage, shareMessage : this.state.shareMessage, @@ -136,6 +138,10 @@ const LockBrew = createClass({ {this.renderInput('shareMessage')}
+ @@ -163,8 +169,8 @@ const LockBrew = createClass({

Messages

    -
  • Edit Message: This is the private message that is ONLY displayed to the authors of the locked brew. This message MUST specify exactly what actions must be taken in order to have the brew unlocked.
  • -
  • Share Message: This is the public message that is displayed to the EVERYONE that attempts to view the locked brew.
  • +
  • Private Message: This is the private message that is ONLY displayed to the authors of the locked brew. This message MUST specify exactly what actions must be taken in order to have the brew unlocked.
  • +
  • Public Message: This is the public message that is displayed to the EVERYONE that attempts to view the locked brew.
From ec6258a2a5b219f518f2bc4b4672431e64391fff Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 7 Apr 2025 22:02:53 +1200 Subject: [PATCH 75/89] Add overwrite option to API function --- server/admin.api.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index f770e4adf..8942a4675 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -208,6 +208,10 @@ router.get('/api/locks', mw.adminOnly, asyncHandler(async (req, res)=>{ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const lock = req.body; + + const overwrite = lock.overwrite || false; + lock.overwrite = undefined; + lock.applied = new Date; const filter = { @@ -218,7 +222,7 @@ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ if(!brew) throw { name: 'Brew Not Found', message: 'Cannot find brew to lock', shareId: req.params.id, status: 500, HBErrorCode: '63' }; - if(brew.lock) { + if(brew.lock && !overwrite) { // console.log('ALREADY LOCKED'); throw { name: 'Already Locked', message: 'Lock already exists on brew', shareId: req.params.id, title: brew.title, status: 500, HBErrorCode: '64' }; } From 1ded1cad5a123ac7fb4f74a7a89eadba21e293b0 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 8 Apr 2025 09:28:54 +1200 Subject: [PATCH 76/89] Change accessType check --- server/homebrew.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 055d72eba..c59c6c4d7 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -118,7 +118,7 @@ const api = { throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04' }; } - if(stub?.lock && accessType != 'edit') { + if(stub?.lock && accessType === 'share') { throw { HBErrorCode: '51', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title }; } From be2f1786b59a23621e6c1058d1fb8fa96662298f Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 09:59:34 +1200 Subject: [PATCH 77/89] Add authors to locked brew error message --- client/homebrew/pages/errorPage/errors/errorIndex.js | 4 +++- server/homebrew.api.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index 2f0d4599b..0315c021c 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -194,7 +194,9 @@ const errorIndex = (props)=>{ **Brew ID:** ${props.brew.brewId} - **Brew Title:** ${escape(props.brew.brewTitle)}`, + **Brew Title:** ${escape(props.brew.brewTitle)} + + **Brew Authors:** ${escape(props.brew.brewAuthors.length ? props.brew.brewAuthors.join(',') : 'No listed authors')}`, // ####### Admin page error ####### '52' : dedent` diff --git a/server/homebrew.api.js b/server/homebrew.api.js index c59c6c4d7..3c7566af7 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -119,7 +119,7 @@ const api = { } if(stub?.lock && accessType === 'share') { - throw { HBErrorCode: '51', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title }; + throw { HBErrorCode: '51', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title, brewAuthors: stub.authors }; } // If there's a google id, get it if requesting the full brew or if no stub found yet From e3de7b9f012770719aaf9933d2bcab1cfda540e6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 10:17:35 +1200 Subject: [PATCH 78/89] Tweak lock styling --- client/admin/lockTools/lockTools.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/lockTools/lockTools.less b/client/admin/lockTools/lockTools.less index f6e7ea9dd..94a27ac8e 100644 --- a/client/admin/lockTools/lockTools.less +++ b/client/admin/lockTools/lockTools.less @@ -8,7 +8,7 @@ label { display : inline-block; width : 100%; - line-height : 1.5em; + line-height : 2.25em; text-align : right; input { float : right; From dc724492efbf6debebbf6ae3584846fdf1c3c9b6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 10:26:10 +1200 Subject: [PATCH 79/89] Prevent BrewUtils from loading when it is not the current Admin tab --- client/admin/admin.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index f59162e1d..29973d221 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -8,10 +8,10 @@ import LockTools from './lockTools/lockTools.jsx'; const tabGroups = ['brew', 'notifications', 'authors', 'locks']; const Admin = ()=>{ - const [currentTab, setCurrentTab] = useState('brew'); + const [currentTab, setCurrentTab] = useState(''); useEffect(()=>{ - setCurrentTab(localStorage.getItem('hbAdminTab')); + setCurrentTab(localStorage.getItem('hbAdminTab') || 'brew'); }, []); useEffect(()=>{ From b19d05fbf78d08955ccfa3a82ed79918e2303ad7 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 10:41:58 +1200 Subject: [PATCH 80/89] Remove commented out console.logs --- server/admin.api.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 8942a4675..bced73c83 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -223,7 +223,6 @@ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ if(!brew) throw { name: 'Brew Not Found', message: 'Cannot find brew to lock', shareId: req.params.id, status: 500, HBErrorCode: '63' }; if(brew.lock && !overwrite) { - // console.log('ALREADY LOCKED'); throw { name: 'Already Locked', message: 'Lock already exists on brew', shareId: req.params.id, title: brew.title, status: 500, HBErrorCode: '64' }; } @@ -235,7 +234,6 @@ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ throw { name: 'Already Locked', message: 'Unable to set lock', shareId: req.params.id, status: 500, HBErrorCode: '62', error }; }); - // console.log(`Lock applied to brew ID ${brew.shareId} - ${brew.title}`); return res.json({ name: 'LOCKED', message: `Lock applied to brew ID ${brew.shareId} - ${brew.title}`, ...lock }); })); @@ -260,9 +258,6 @@ router.put('/api/unlock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ throw { name: 'Cannot Unlock', message: 'Unable to clear lock', shareId: req.params.id, status: 500, HBErrorCode: '65', error }; }); - // console.log(`Lock removed from brew ID ${brew.shareId} - ${brew.title}`); - - return res.json({ name: 'Unlocked', message: `Lock removed from brew ID ${req.params.id}` }); })); @@ -303,7 +298,6 @@ router.put('/admin/lock/review/request/:id', asyncHandler(async (req, res)=>{ if(!brew) { throw { name: 'Brew Not Found', message: `Cannot find a locked brew with ID ${req.params.id}`, code: 500, HBErrorCode: '70' }; }; if(brew.lock.reviewRequested){ - // console.log(`Review already requested for brew ${brew.shareId} - ${brew.title}`); throw { name: 'Review Already Requested', message: `Review already requested for brew ${brew.shareId} - ${brew.title}`, code: 500, HBErrorCode: '71' }; }; @@ -315,7 +309,6 @@ router.put('/admin/lock/review/request/:id', asyncHandler(async (req, res)=>{ throw { name: 'Can Not Set Review Request', message: `Unable to set request for review on brew ID ${req.params.id}`, code: 500, HBErrorCode: '69', error }; }); - // console.log(`Review requested on brew ${brew.shareId} - ${brew.title}`); return res.json({ name: 'Review Requested', message: `Review requested on brew ID ${brew.shareId} - ${brew.title}` }); })); @@ -338,7 +331,6 @@ router.put('/api/lock/review/remove/:id', mw.adminOnly, asyncHandler(async (req, throw { name: 'Can Not Clear Review Request', message: `Unable to remove request for review on brew ID ${req.params.id}`, HBErrorCode: '72', error }; }); - // console.log(`Review request removed on brew ID ${brew.shareId} - ${brew.title}`); return res.json({ name: 'Review Request Cleared', message: `Review request removed for brew ID ${brew.shareId} - ${brew.title}` }); })); From bd68b9c0cb376f83e56960b5c60ac2de5fd9e0e9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 10:48:02 +1200 Subject: [PATCH 81/89] Remove unnecessary variable --- server/admin.api.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index bced73c83..8327dfd49 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -209,9 +209,6 @@ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ const lock = req.body; - const overwrite = lock.overwrite || false; - lock.overwrite = undefined; - lock.applied = new Date; const filter = { @@ -222,10 +219,12 @@ router.post('/api/lock/:id', mw.adminOnly, asyncHandler(async (req, res)=>{ if(!brew) throw { name: 'Brew Not Found', message: 'Cannot find brew to lock', shareId: req.params.id, status: 500, HBErrorCode: '63' }; - if(brew.lock && !overwrite) { + if(brew.lock && !lock.overwrite) { throw { name: 'Already Locked', message: 'Lock already exists on brew', shareId: req.params.id, title: brew.title, status: 500, HBErrorCode: '64' }; } + lock.overwrite = undefined; + brew.lock = lock; brew.markModified('lock'); From 95f44f446036f9f182d9d63e315d660d223e3f98 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 11:04:57 +1200 Subject: [PATCH 82/89] Revert unnecessary change in app.js --- server/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/app.js b/server/app.js index fc0954efd..b7d990baf 100644 --- a/server/app.js +++ b/server/app.js @@ -2,11 +2,10 @@ // Set working directory to project root import { dirname } from 'path'; import { fileURLToPath } from 'url'; +import packageJSON from './../package.json' with { type: 'json' }; const __dirname = dirname(fileURLToPath(import.meta.url)); process.chdir(`${__dirname}/..`); - -import packageJSON from '../package.json' with { type: 'json' }; const version = packageJSON.version; import _ from 'lodash'; From 5e7e314baacd437685ae8b31050da8ac288b7dd9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 11:38:57 +1200 Subject: [PATCH 83/89] Update fields returned for Lock and Review Tables --- server/admin.api.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 8327dfd49..ee859a3e0 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -191,7 +191,9 @@ router.get('/api/locks', mw.adminOnly, asyncHandler(async (req, res)=>{ { $project : { shareId : 1, - title : 1 + editId : 1, + title : 1, + lock : 1 } } ]; @@ -271,7 +273,9 @@ router.get('/api/lock/reviews', mw.adminOnly, asyncHandler(async (req, res)=>{ { $project : { shareId : 1, - title : 1 + editId : 1, + title : 1, + lock : 1 } } ]; From da4f6c9307d8e2853713529b7e6c5c729372de1e Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 17:54:51 +1200 Subject: [PATCH 84/89] Load lock details to the Lock Brew form --- client/admin/lockTools/lockTools.jsx | 50 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index c528fb13d..c639adaca 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -1,9 +1,8 @@ -/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ +/*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/ require('./lockTools.less'); const React = require('react'); const createClass = require('create-react-class'); -// const request = require('superagent'); import request from '../../homebrew/utils/request-middleware.js'; const LockTools = createClass({ @@ -29,17 +28,23 @@ const LockTools = createClass({ } }, + updateLockData : function(lock){ + this.setState({ + lock : lock + }); + }, + render : function() { return

Lock Count

Number of brews currently locked: {this.state.reviewCount}


- +
- +
- +
@@ -55,12 +60,12 @@ const LockBrew = createClass({ getInitialState : function() { // Default values return { - brewId : '', - code : 455, - editMessage : '', - shareMessage : 'This Brew has been locked.', + brewId : this.props.lock?.shareId || '', + code : this.props.lock?.code || 455, + editMessage : this.props.lock?.editMessage || '', + shareMessage : this.props.lock?.shareMessage || 'This Brew has been locked.', result : {}, - overwrite : false + overwrite : false, }; }, @@ -186,7 +191,8 @@ const LockTable = createClass({ text : '', fetchURL : '/api/locks', resultName : '', - propertyNames : ['shareId'] + propertyNames : ['shareId'], + loadBrew : ()=>{} }; }, @@ -198,7 +204,9 @@ const LockTable = createClass({ }; }, - clickFn(){ + lockKey : React.createRef(0), + + clickFn : function (){ this.setState({ searching: true, error: null }); request.get(this.props.fetchURL) @@ -209,6 +217,18 @@ const LockTable = createClass({ }); }, + updateBrewLockData : function (lockData){ + this.lockKey.current++; + const brewData = { + key : this.lockKey.current, + shareId : lockData.shareId, + code : lockData.lock.code, + editMessage : lockData.lock.editMessage, + shareMessage : lockData.lock.shareMessage + }; + this.props.loadBrew(brewData); + }, + render : function () { return <>
@@ -229,7 +249,7 @@ const LockTable = createClass({ return
; })} - + @@ -240,8 +260,8 @@ const LockTable = createClass({ {result[name].toString()} ; })} - - + + ; })} From 04defb97b09e99def4a56e35b1f154cf71e89b92 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 9 Apr 2025 20:10:48 +1200 Subject: [PATCH 85/89] Tweak styling for Overwrite checkbox --- client/admin/lockTools/lockTools.jsx | 2 +- client/admin/lockTools/lockTools.less | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx index c639adaca..9a28d330f 100644 --- a/client/admin/lockTools/lockTools.jsx +++ b/client/admin/lockTools/lockTools.jsx @@ -143,7 +143,7 @@ const LockBrew = createClass({ {this.renderInput('shareMessage')}
-
{name}clipviewload
{navigator.clipboard.writeText(result.shareId.toString());}}>{navigator.clipboard.writeText(result.shareId.toString());}}>{this.updateBrewLockData(result);}}>