From 4a449c7895b0eca1fc71bd01201f9693ccf62818 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 22:08:22 +1300 Subject: [PATCH 001/730] Update Buffer method --- 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 8570ea1bc..b9b2afbd7 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -16,7 +16,7 @@ const mw = { .status(401) .send('Authorization Required'); } - const [username, password] = new Buffer(req.get('authorization').split(' ').pop(), 'base64') + const [username, password] = Buffer.from(req.get('authorization').split(' ').pop(), 'base64') .toString('ascii') .split(':'); if(process.env.ADMIN_USER === username && process.env.ADMIN_PASS === password){ From d7ee004127bcff65d94556746cbbb8ca96162027 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 22:08:44 +1300 Subject: [PATCH 002/730] Update Admin pages --- client/admin/admin.jsx | 14 ++--------- .../brewCleanup/brewCleanup.jsx | 0 .../brewCleanup/brewCleanup.less | 0 .../brewCompress/brewCompress.jsx | 0 .../brewCompress/brewCompress.less | 0 .../{ => brewUtils}/brewLookup/brewLookup.jsx | 0 .../brewLookup/brewLookup.less | 0 client/admin/brewUtils/brewUtils.jsx | 24 +++++++++++++++++++ client/admin/{ => brewUtils}/stats/stats.jsx | 0 client/admin/{ => brewUtils}/stats/stats.less | 0 10 files changed, 26 insertions(+), 12 deletions(-) rename client/admin/{ => brewUtils}/brewCleanup/brewCleanup.jsx (100%) rename client/admin/{ => brewUtils}/brewCleanup/brewCleanup.less (100%) rename client/admin/{ => brewUtils}/brewCompress/brewCompress.jsx (100%) rename client/admin/{ => brewUtils}/brewCompress/brewCompress.less (100%) rename client/admin/{ => brewUtils}/brewLookup/brewLookup.jsx (100%) rename client/admin/{ => brewUtils}/brewLookup/brewLookup.less (100%) create mode 100644 client/admin/brewUtils/brewUtils.jsx rename client/admin/{ => brewUtils}/stats/stats.jsx (100%) rename client/admin/{ => brewUtils}/stats/stats.less (100%) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 92e0b2aee..a84af6f44 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -2,11 +2,7 @@ require('./admin.less'); const React = require('react'); const createClass = require('create-react-class'); - -const BrewCleanup = require('./brewCleanup/brewCleanup.jsx'); -const BrewLookup = require('./brewLookup/brewLookup.jsx'); -const BrewCompress = require ('./brewCompress/brewCompress.jsx'); -const Stats = require('./stats/stats.jsx'); +const BrewUtils = require('./brewUtils/brewUtils.jsx'); const Admin = createClass({ getDefaultProps : function() { @@ -23,13 +19,7 @@ const Admin = createClass({
- -
- -
- -
- +
; } diff --git a/client/admin/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx similarity index 100% rename from client/admin/brewCleanup/brewCleanup.jsx rename to client/admin/brewUtils/brewCleanup/brewCleanup.jsx diff --git a/client/admin/brewCleanup/brewCleanup.less b/client/admin/brewUtils/brewCleanup/brewCleanup.less similarity index 100% rename from client/admin/brewCleanup/brewCleanup.less rename to client/admin/brewUtils/brewCleanup/brewCleanup.less diff --git a/client/admin/brewCompress/brewCompress.jsx b/client/admin/brewUtils/brewCompress/brewCompress.jsx similarity index 100% rename from client/admin/brewCompress/brewCompress.jsx rename to client/admin/brewUtils/brewCompress/brewCompress.jsx diff --git a/client/admin/brewCompress/brewCompress.less b/client/admin/brewUtils/brewCompress/brewCompress.less similarity index 100% rename from client/admin/brewCompress/brewCompress.less rename to client/admin/brewUtils/brewCompress/brewCompress.less diff --git a/client/admin/brewLookup/brewLookup.jsx b/client/admin/brewUtils/brewLookup/brewLookup.jsx similarity index 100% rename from client/admin/brewLookup/brewLookup.jsx rename to client/admin/brewUtils/brewLookup/brewLookup.jsx diff --git a/client/admin/brewLookup/brewLookup.less b/client/admin/brewUtils/brewLookup/brewLookup.less similarity index 100% rename from client/admin/brewLookup/brewLookup.less rename to client/admin/brewUtils/brewLookup/brewLookup.less diff --git a/client/admin/brewUtils/brewUtils.jsx b/client/admin/brewUtils/brewUtils.jsx new file mode 100644 index 000000000..de8c29895 --- /dev/null +++ b/client/admin/brewUtils/brewUtils.jsx @@ -0,0 +1,24 @@ +const React = require('react'); +const createClass = require('create-react-class'); + + +const BrewCleanup = require('./brewCleanup/brewCleanup.jsx'); +const BrewLookup = require('./brewLookup/brewLookup.jsx'); +const BrewCompress = require ('./brewCompress/brewCompress.jsx'); +const Stats = require('./stats/stats.jsx'); + +const BrewUtils = createClass({ + render : function(){ + return <> + +
+ +
+ +
+ + ; + } +}); + +module.exports = BrewUtils; diff --git a/client/admin/stats/stats.jsx b/client/admin/brewUtils/stats/stats.jsx similarity index 100% rename from client/admin/stats/stats.jsx rename to client/admin/brewUtils/stats/stats.jsx diff --git a/client/admin/stats/stats.less b/client/admin/brewUtils/stats/stats.less similarity index 100% rename from client/admin/stats/stats.less rename to client/admin/brewUtils/stats/stats.less From f66664a3e2b6d065dd5107c73e1282d9ae99cf5b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 22:49:38 +1300 Subject: [PATCH 003/730] Tabify Admin page, add Notification tab --- client/admin/admin.jsx | 22 ++++++++++++++++++- .../notificationUtils/notificationUtils.jsx | 12 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 client/admin/notificationUtils/notificationUtils.jsx diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index a84af6f44..f2ee241f2 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -3,12 +3,28 @@ const React = require('react'); const createClass = require('create-react-class'); const BrewUtils = require('./brewUtils/brewUtils.jsx'); +const NotificationUtils = require('./notificationUtils/notificationUtils.jsx'); + +const tabGroups = ['brew', 'notifications']; const Admin = createClass({ getDefaultProps : function() { return {}; }, + getInitialState : function(){ + return ({ + currentTab : 'brew' + }); + }, + + handleClick : function(newTab){ + if(this.state.currentTab === newTab) return; + this.setState({ + currentTab : newTab + }); + }, + render : function(){ return
@@ -19,7 +35,11 @@ const Admin = createClass({
- +
+ {tabGroups.map((tab)=>{ return ; })} +
+ {this.state.currentTab==='brew' && } + {this.state.currentTab==='notifications' && }
; } diff --git a/client/admin/notificationUtils/notificationUtils.jsx b/client/admin/notificationUtils/notificationUtils.jsx new file mode 100644 index 000000000..9c7b4cbe3 --- /dev/null +++ b/client/admin/notificationUtils/notificationUtils.jsx @@ -0,0 +1,12 @@ +const React = require('react'); +const createClass = require('create-react-class'); + +const NotificationUtils = createClass({ + render : function(){ + return <> +
Notifications
+ ; + } +}); + +module.exports = NotificationUtils; From 620cb95ae89f6e3f961abc0e69ccdc092dff6a72 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 22:50:24 +1300 Subject: [PATCH 004/730] Initial pass at Notification Mongoose model --- server/notifications.model.js | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 server/notifications.model.js diff --git a/server/notifications.model.js b/server/notifications.model.js new file mode 100644 index 000000000..12fecb3fa --- /dev/null +++ b/server/notifications.model.js @@ -0,0 +1,72 @@ +const mongoose = require('mongoose'); +const { nanoid } = require('nanoid'); +const _ = require('lodash'); + +const NotificationSchema = mongoose.Schema({ + dissmissKey : { type: String, default: ()=>{return nanoid(12);}, index: { unique: true } }, + title : { type: String, default: '' }, + text : { type: String, default: '' }, + + createdAt : { type: Date, default: Date.now }, + startAt : { type: Date, default: Date.now }, + stopAt : { type: Date, default: Date.now }, +}, { versionKey: false }); + +NotificationSchema.statics.get = function(query, fields=null){ + return new Promise((resolve, reject)=>{ + Notification.find(query, fields, null, (err, notifications)=>{ + if(err || !notifications.length) return reject('Can not find notification'); + return resolve(notifications[0]); + }); + }); +}; + +NotificationSchema.statics.getByKey = function(key, fields=null){ + return new Promise((resolve, reject)=>{ + const query = { dissmissKey: key }; + Notification.findOne(query, fields).lean().exec((err, notifications)=>{ //lean() converts results to JSObjects + if(err) return reject('Can not find notification'); + return resolve(notifications); + }); + }); +}; + +NotificationSchema.statics.addNotification = async function(title, text, startAt=new Date, stopAt=new Date){ + const data = { + title : title, + text : text, + startAt : startAt, + stopAt : stopAt + }; + const newNotification = new Notification(data); + await newNotification.save(); + + return newNotification; +}; + +NotificationSchema.statics.updateNotification = async function(dismissKey, title=null, text=null, startAt=null, stopAt=null){ + if(!dismissKey) return 'No key!'; + if(!title && !text && !startAt && !stopAt) return 'No data!'; + const data = { + title : title, + text : text, + startAt : startAt, + stopAt : stopAt + }; + for (const [key, value] of Object.entries(data)){ + if(value === null) delete data[key]; + } + + await Notification.updateOne(data) + .exec((err, notifications)=>{ + if(err) return reject('Can not find notification'); + return resolve(notifications); + }); +}; + +const Notification = mongoose.model('Notification', NotificationSchema); + +module.exports = { + schema : NotificationSchema, + model : Notification, +}; From b8fd8a7a868a6674f971eb187578bc19fe7cd8b9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 22:52:37 +1300 Subject: [PATCH 005/730] Add Notification lookup to Admin API --- server/admin.api.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/admin.api.js b/server/admin.api.js index b9b2afbd7..7190f7076 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -1,4 +1,5 @@ const HomebrewModel = require('./homebrew.model.js').model; +const NotificationModel = require('./notifications.model.js').model; const router = require('express').Router(); const Moment = require('moment'); //const render = require('vitreum/steps/render'); @@ -99,6 +100,15 @@ router.get('/admin/stats', mw.adminOnly, (req, res)=>{ }); }); +/* Searches for matching edit or share id, also attempts to partial match */ +router.get('/admin/notification/lookup/:id', mw.adminOnly, (req, res, next)=>{ + NotificationModel.findOne({ $or : [ + { dismissKey: { '$regex': req.params.id } }, + ] }).exec((err, notification)=>{ + return res.json(notification); + }); +}); + router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl From 35b4c354f22143f66ea15cc27f0a9f738ca3d008 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 23:20:11 +1300 Subject: [PATCH 006/730] Add key prop to Admin tabs --- client/admin/admin.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index f2ee241f2..6ebfe6ca8 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -36,7 +36,7 @@ const Admin = createClass({
- {tabGroups.map((tab)=>{ return ; })} + {tabGroups.map((tab, idx)=>{ return ; })}
{this.state.currentTab==='brew' && } {this.state.currentTab==='notifications' && } From a499bb3a54e719f075beab4e950b0af3e489da0b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 4 Jan 2023 23:32:35 +1300 Subject: [PATCH 007/730] Add basic Notification Lookup functionality --- .../notificationLookup/notificationLookup.jsx | 82 +++++++++++++++++++ .../notificationLookup.less | 30 +++++++ .../notificationUtils/notificationUtils.jsx | 4 +- 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 client/admin/notificationUtils/notificationLookup/notificationLookup.jsx create mode 100644 client/admin/notificationUtils/notificationLookup/notificationLookup.less diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx new file mode 100644 index 000000000..3ed0410ee --- /dev/null +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx @@ -0,0 +1,82 @@ +require('./notificationLookup.less'); +const React = require('react'); +const createClass = require('create-react-class'); +const cx = require('classnames'); + +const request = require('superagent'); +const Moment = require('moment'); + + +const NotificationLookup = createClass({ + getDefaultProps() { + return {}; + }, + getInitialState() { + return { + query : '', + foundNotification : null, + searching : false, + error : null + }; + }, + handleChange(e){ + this.setState({ query: e.target.value }); + }, + lookup(){ + this.setState({ searching: true, error: null }); + + request.get(`/admin/notification/lookup/${this.state.query}`) + .then((res)=>this.setState({ foundNotification: res.body })) + .catch((err)=>this.setState({ error: err })) + .finally(()=>this.setState({ searching: false })); + }, + + renderFoundNotification(){ + const notification = this.state.foundnotification; + return
+
+
Key
+
{notification.dismissKey}
+ +
Title
+
{notification.title || 'No Title'}
+ +
Text
+
{notification.text || 'No Text'}
+ +
Created
+
{Moment(notification.createdAt).fromNow()}
+ +
Start
+
{Moment(notification.startAt).fromNow() || 'No Start Time'}
+ +
Created
+
{Moment(notification.stopAt).fromNow() || 'No End Time'}
+
+
; + }, + + render(){ + return
+

Notification Lookup

+ + + + {this.state.error + &&
{this.state.error.toString()}
+ } + + {this.state.foundNotification + ? this.renderFoundNotification() + :
No notification found.
+ } +
; + } +}); + +module.exports = NotificationLookup; diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.less b/client/admin/notificationUtils/notificationLookup/notificationLookup.less new file mode 100644 index 000000000..720b4e044 --- /dev/null +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.less @@ -0,0 +1,30 @@ + +.notificationLookup{ + input{ + height : 33px; + margin-bottom : 20px; + padding : 0px 10px; + font-family : monospace; + } + button{ + vertical-align : middle; + height : 37px; + } + dl{ + @maxItemWidth : 132px; + dt{ + float : left; + clear : left; + width : @maxItemWidth; + text-align : right; + &::after { + content: " : "; + } + } + dd{ + height : 1em; + margin-left : @maxItemWidth + 6px; + padding : 0 0 0.5em 0; + } + } +} \ No newline at end of file diff --git a/client/admin/notificationUtils/notificationUtils.jsx b/client/admin/notificationUtils/notificationUtils.jsx index 9c7b4cbe3..f68462377 100644 --- a/client/admin/notificationUtils/notificationUtils.jsx +++ b/client/admin/notificationUtils/notificationUtils.jsx @@ -1,10 +1,12 @@ const React = require('react'); const createClass = require('create-react-class'); +const NotificationLookup = require('./notificationLookup/notificationLookup.jsx'); + const NotificationUtils = createClass({ render : function(){ return <> -
Notifications
+ ; } }); From 42125f404101d6bb080d5919081911beadbda9eb Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 5 Jan 2023 09:03:51 +1300 Subject: [PATCH 008/730] Update Notification schema --- server/notifications.model.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/notifications.model.js b/server/notifications.model.js index 12fecb3fa..d09b80ce6 100644 --- a/server/notifications.model.js +++ b/server/notifications.model.js @@ -1,9 +1,8 @@ const mongoose = require('mongoose'); -const { nanoid } = require('nanoid'); const _ = require('lodash'); const NotificationSchema = mongoose.Schema({ - dissmissKey : { type: String, default: ()=>{return nanoid(12);}, index: { unique: true } }, + dissmissKey : { type: String, index: { unique: true } }, title : { type: String, default: '' }, text : { type: String, default: '' }, From ec040cc2bb0bd059ad34fb22ac7acaf5d07322e9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 5 Jan 2023 10:04:45 +1300 Subject: [PATCH 009/730] Add DisplayNames --- .../notificationLookup/notificationLookup.jsx | 1 + client/admin/notificationUtils/notificationUtils.jsx | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx index 3ed0410ee..317f2679c 100644 --- a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx @@ -8,6 +8,7 @@ const Moment = require('moment'); const NotificationLookup = createClass({ + displayName : 'NotificationLookup', getDefaultProps() { return {}; }, diff --git a/client/admin/notificationUtils/notificationUtils.jsx b/client/admin/notificationUtils/notificationUtils.jsx index f68462377..3e595265b 100644 --- a/client/admin/notificationUtils/notificationUtils.jsx +++ b/client/admin/notificationUtils/notificationUtils.jsx @@ -2,10 +2,15 @@ const React = require('react'); const createClass = require('create-react-class'); const NotificationLookup = require('./notificationLookup/notificationLookup.jsx'); +const NotificationAdd = require('./notificationAdd/notificationAdd.jsx'); const NotificationUtils = createClass({ + displayName : 'NotificationUtils', + render : function(){ return <> + +
; } From f5c7761c61b1fe981c3316920383ddc9b844abcf Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 5 Jan 2023 10:52:24 +1300 Subject: [PATCH 010/730] Add styling to active tab --- client/admin/admin.jsx | 3 +-- client/admin/admin.less | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 6ebfe6ca8..f675ff37a 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -27,7 +27,6 @@ const Admin = createClass({ render : function(){ return
-
@@ -36,7 +35,7 @@ const Admin = createClass({
- {tabGroups.map((tab, idx)=>{ return ; })} + {tabGroups.map((tab, idx)=>{ return ; })}
{this.state.currentTab==='brew' && } {this.state.currentTab==='notifications' && } diff --git a/client/admin/admin.less b/client/admin/admin.less index a61335835..8d3d70763 100644 --- a/client/admin/admin.less +++ b/client/admin/admin.less @@ -40,5 +40,25 @@ body{ margin : 30px 0px; } - + .container{ + .tabs button{ + background-color: #eee; + margin-left: 3px; + margin-right: 3px; + border: 1px solid #444; + border-radius: 5px; + color: black; + &:hover{ + background-color: #444; + color: #eee; + } + &.active{ + border: 2px solid #444; + text-decoration: underline; + margin-left: 2px; + margin-right: 2px; + background-color: #ccc; + } + } + } } From 9e169aba919ab297e93c3549828debf433a698ee Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 5 Jan 2023 10:56:50 +1300 Subject: [PATCH 011/730] Tweak LookUp title --- .../notificationUtils/notificationLookup/notificationLookup.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx index 317f2679c..973212e85 100644 --- a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx @@ -59,7 +59,7 @@ const NotificationLookup = createClass({ render(){ return
-

Notification Lookup

+

Lookup

+ + {this.state.error + &&
{this.state.error.toString()}
+ } +
; + } +}); + +module.exports = NotificationAdd; diff --git a/client/admin/notificationUtils/notificationAdd/notificationAdd.less b/client/admin/notificationUtils/notificationAdd/notificationAdd.less new file mode 100644 index 000000000..32cd61d25 --- /dev/null +++ b/client/admin/notificationUtils/notificationAdd/notificationAdd.less @@ -0,0 +1,20 @@ + +.notificationAdd{ + input{ + height : 33px; + margin-bottom : 20px; + padding : 0px 10px; + font-family : monospace; + } + button{ + vertical-align : middle; + height : 37px; + } + .fieldLabel{ + display: inline-block; + width: 10%; + } + .fieldInput{ + margin-bottom: 5px; + } +} \ No newline at end of file diff --git a/server/admin.api.js b/server/admin.api.js index 7190f7076..906bfdcae 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -100,13 +100,18 @@ router.get('/admin/stats', mw.adminOnly, (req, res)=>{ }); }); -/* Searches for matching edit or share id, also attempts to partial match */ +/* Searches for notification with matching key */ router.get('/admin/notification/lookup/:id', mw.adminOnly, (req, res, next)=>{ - NotificationModel.findOne({ $or : [ - { dismissKey: { '$regex': req.params.id } }, - ] }).exec((err, notification)=>{ - return res.json(notification); - }); + NotificationModel.findOne({ dismissKey: req.params.id }) + .exec((err, notification)=>{ + return res.json(notification); + }); +}); + +/* Add new notification */ +router.post('/admin/notification/add', mw.adminOnly, async (req, res, next)=>{ + const notification = await NotificationModel.addNotification(req.body); + return res.json(notification); }); router.get('/admin', mw.adminOnly, (req, res)=>{ diff --git a/server/notifications.model.js b/server/notifications.model.js index 0465822d5..721c4a89d 100644 --- a/server/notifications.model.js +++ b/server/notifications.model.js @@ -2,9 +2,9 @@ const mongoose = require('mongoose'); const _ = require('lodash'); const NotificationSchema = mongoose.Schema({ - dissmissKey : { type: String, index: { unique: true } }, - title : { type: String, default: '' }, - text : { type: String, default: '' }, + dismissKey : { type: String, unique: true, required: true }, + title : { type: String, default: '' }, + text : { type: String, default: '' }, createdAt : { type: Date, default: Date.now }, startAt : { type: Date, default: Date.now }, @@ -30,19 +30,23 @@ NotificationSchema.statics.getByKey = function(key, fields=null){ }); }; -NotificationSchema.statics.addNotification = async function(dismissKey, text, title=null, startAt=new Date, stopAt=new Date){ - const data = { - dismissKey : dismissKey, - title : title, - text : text, - startAt : startAt, - stopAt : stopAt +NotificationSchema.statics.addNotification = async function(data){ + // console.log('add notification'); + if(!data.dismissKey) return 'Dismiss key is required!'; + const defaults = { + title : '', + text : '', + startAt : new Date, + stopAt : new Date }; + _.mergeWith(data, defaults, (item)=>{ if(!item) return undefined; }); const newNotification = new Notification(data); - await newNotification.save() - .catch((err)=>{return err;}); + const savedNotification = await newNotification.save() + .catch((err)=>{ + return { err: err }; + }); - return newNotification; + return savedNotification; }; NotificationSchema.statics.updateNotification = async function(dismissKey, title=null, text=null, startAt=null, stopAt=null){ From b00a962e77ec1456e5450559ec03b4136ccb6da9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 15 Jan 2023 20:44:41 +1300 Subject: [PATCH 014/730] Fix typo --- .../notificationUtils/notificationLookup/notificationLookup.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx index 973212e85..0ed9398c5 100644 --- a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx @@ -33,7 +33,7 @@ const NotificationLookup = createClass({ }, renderFoundNotification(){ - const notification = this.state.foundnotification; + const notification = this.state.foundNotification; return
Key
From 5e2171ceb12c71cc7f3d43075f649771f9451c17 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 15 Jan 2023 22:21:06 +1300 Subject: [PATCH 015/730] Remove debugging console.log calls --- .../notificationUtils/notificationAdd/notificationAdd.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx index 78438644a..51fbecfb4 100644 --- a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx +++ b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx @@ -47,7 +47,6 @@ const NotificationAdd = createClass({ .then((response)=>{ return response.body; }); - console.log(notification); const update = { notificationResult : `Created notification: ${JSON.stringify(notification, null, 2)}` @@ -63,8 +62,6 @@ const NotificationAdd = createClass({ update.stopAt = ''; } - console.log(update); - this.setState(update); }, From ccd5cacb0c1d91a33f0cf218b4747c08742cdf4e Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 15 Jan 2023 23:25:17 +1300 Subject: [PATCH 016/730] Stub notification deletion function --- .../notificationLookup/notificationLookup.jsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx index 0ed9398c5..4f7c0b3d7 100644 --- a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx +++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx @@ -32,6 +32,16 @@ const NotificationLookup = createClass({ .finally(()=>this.setState({ searching: false })); }, + deleteNotification : function(){ + console.log('DELETE'); + if(!confirm(`Really delete notification ${this.state.foundNotification.dismissKey} : ${this.state.foundNotification.title}?`)) { + console.log('CANCELLED'); + return; + } + console.log('CONFIRMED'); + return; + }, + renderFoundNotification(){ const notification = this.state.foundNotification; return
@@ -46,14 +56,15 @@ const NotificationLookup = createClass({
{notification.text || 'No Text'}
Created
-
{Moment(notification.createdAt).fromNow()}
+
{Moment(notification.createdAt).toLocaleString()}
Start
-
{Moment(notification.startAt).fromNow() || 'No Start Time'}
+
{Moment(notification.startAt).toLocaleString() || 'No Start Time'}
-
Created
-
{Moment(notification.stopAt).fromNow() || 'No End Time'}
+
Stop
+
{Moment(notification.stopAt).toLocaleString() || 'No End Time'}
+
; }, From 24adbdc429f8127d125f779effaf183baec35771 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 15 Jan 2023 23:28:54 +1300 Subject: [PATCH 017/730] Change model to use defaults rather than mergeWith --- server/notifications.model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/notifications.model.js b/server/notifications.model.js index 721c4a89d..bd74ad5b7 100644 --- a/server/notifications.model.js +++ b/server/notifications.model.js @@ -39,7 +39,7 @@ NotificationSchema.statics.addNotification = async function(data){ startAt : new Date, stopAt : new Date }; - _.mergeWith(data, defaults, (item)=>{ if(!item) return undefined; }); + _.defaults(data, defaults); const newNotification = new Notification(data); const savedNotification = await newNotification.save() .catch((err)=>{ From da0372e44cb4094c594449858f0af980296ae563 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 23 Jan 2023 15:18:50 +1300 Subject: [PATCH 018/730] WIP commit --- .../notificationAdd/notificationAdd.jsx | 13 +++++++++---- server/admin.api.js | 1 + server/notifications.model.js | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx index 51fbecfb4..a1480c0a9 100644 --- a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx +++ b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx @@ -38,8 +38,8 @@ const NotificationAdd = createClass({ dismissKey : this.state.dismissKey, title : this.state.title, text : this.state.text, - startAt : this.state.startAt, - stopAt : this.state.stopAt + startAt : Date.parse(this.state.startAt), + stopAt : Date.parse(this.state.stopAt) }; const notification = await request.post('/admin/notification/add') @@ -52,7 +52,10 @@ const NotificationAdd = createClass({ notificationResult : `Created notification: ${JSON.stringify(notification, null, 2)}` }; if(notification.err) { - update.notificationResult = err; + update.notificationResult = JSON.stringify(notification.err); + if(notification.err.code == 11000) { + update.notificationResult = `Duplicate dismissKey error! ${this.state.dismissKey} already exists.`; + } }; if(!notification.err) { update.dismissKey = ''; @@ -62,6 +65,8 @@ const NotificationAdd = createClass({ update.stopAt = ''; } + console.log(update); + this.setState(update); }, @@ -74,7 +79,7 @@ const NotificationAdd = createClass({ this.handleChange(e, field)} placeholder={field} />
; })} - {this.state.notificationResult} +
{this.state.notificationResult}
{/* diff --git a/server/admin.api.js b/server/admin.api.js index 906bfdcae..53b08faaf 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -110,6 +110,7 @@ router.get('/admin/notification/lookup/:id', mw.adminOnly, (req, res, next)=>{ /* Add new notification */ router.post('/admin/notification/add', mw.adminOnly, async (req, res, next)=>{ + console.log(req.body); const notification = await NotificationModel.addNotification(req.body); return res.json(notification); }); diff --git a/server/notifications.model.js b/server/notifications.model.js index bd74ad5b7..6cf4b9c8d 100644 --- a/server/notifications.model.js +++ b/server/notifications.model.js @@ -43,7 +43,7 @@ NotificationSchema.statics.addNotification = async function(data){ const newNotification = new Notification(data); const savedNotification = await newNotification.save() .catch((err)=>{ - return { err: err }; + return { err }; }); return savedNotification; From 52b0ae0400c12e9222a027d87a628da6f760634e Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 1 Oct 2023 21:35:50 +1300 Subject: [PATCH 019/730] Basic functionality pass --- server/app.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/app.js b/server/app.js index f10b6ff5e..6b273e076 100644 --- a/server/app.js +++ b/server/app.js @@ -208,6 +208,20 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ res.status(200).send(brew.text); }); +//Serve brew styling +app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{ + const { brew } = req; + splitTextStyleAndMetadata(brew); + + console.log(brew); + + res.set({ + 'Cache-Control' : 'no-cache', + 'Content-Type' : 'text/css' + }); + res.status(200).send(brew.style); +}); + //User Page app.get('/user/:username', async (req, res, next)=>{ const ownAccount = req.account && (req.account.username == req.params.username); From 0a309ad0e17185d0d2c7b252468702cdab39ddf4 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 1 Oct 2023 21:46:52 +1300 Subject: [PATCH 020/730] Remove debugging console.log --- server/app.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/app.js b/server/app.js index 6b273e076..85ac459f5 100644 --- a/server/app.js +++ b/server/app.js @@ -213,8 +213,6 @@ app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{ const { brew } = req; splitTextStyleAndMetadata(brew); - console.log(brew); - res.set({ 'Cache-Control' : 'no-cache', 'Content-Type' : 'text/css' From ffe12ebee76e289352ec29b367606ae26f1cbbbc Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 7 Nov 2023 20:21:19 -0600 Subject: [PATCH 021/730] Add local statics for images and typefaces This solves issue #1958. Add static paths /staticImages and /staticFonts If a local environment is detected ( per existing loginc for login ) paths are added using the values in HB_IMAGES and HB_FONTS or the default values of /staticImages and /staticFonts respectively. --- package-lock.json | 6 ++++++ package.json | 3 ++- server/app.js | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index eac72a7c5..67b44cbf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "express": "^4.18.2", "express-async-handler": "^1.2.0", "express-static-gzip": "2.1.7", + "fs": "^0.0.1-security", "fs-extra": "11.1.1", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", @@ -6466,6 +6467,11 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", diff --git a/package.json b/package.json index 08992aff4..5e5d263eb 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Create authentic looking D&D homebrews using only markdown", "version": "3.10.0", "engines": { - "npm": "^10.2.x", + "npm": "^10.2.x", "node": ">=20.8.x" }, "repository": { @@ -93,6 +93,7 @@ "express": "^4.18.2", "express-async-handler": "^1.2.0", "express-static-gzip": "2.1.7", + "fs": "^0.0.1-security", "fs-extra": "11.1.1", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", diff --git a/server/app.js b/server/app.js index a19030b3a..9ef4518bc 100644 --- a/server/app.js +++ b/server/app.js @@ -8,6 +8,7 @@ const express = require('express'); const yaml = require('js-yaml'); const app = express(); const config = require('./config.js'); +const fs = require('fs'); const { homebrewApi, getBrew } = require('./homebrew.api.js'); const GoogleActions = require('./googleActions.js'); @@ -416,6 +417,9 @@ if(isLocalEnvironment){ const payload = jwt.encode({ username: username, issued: new Date }, config.get('secret')); return res.json(payload); }); + // Add Static Local Paths + app.use('/staticImages', express.static(config.get('hb_images') && fs.existsSync(config.get('hb_images')) ? config.get('hb_images') :'staticImages')); + app.use(express.static(config.get('hb_fonts') && fs.existsSync(config.get('hb_fonts')) ? config.get('hb_fonts'):'staticFonts')); } //Render the page From 1b855108bf5a634ee9d269c0973de9d8b8852bc2 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 7 Nov 2023 21:26:11 -0600 Subject: [PATCH 022/730] Correct omitted static path --- server/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/app.js b/server/app.js index 9ef4518bc..6ee2d5da0 100644 --- a/server/app.js +++ b/server/app.js @@ -419,7 +419,7 @@ if(isLocalEnvironment){ }); // Add Static Local Paths app.use('/staticImages', express.static(config.get('hb_images') && fs.existsSync(config.get('hb_images')) ? config.get('hb_images') :'staticImages')); - app.use(express.static(config.get('hb_fonts') && fs.existsSync(config.get('hb_fonts')) ? config.get('hb_fonts'):'staticFonts')); + app.use('/staticFonts', express.static(config.get('hb_fonts') && fs.existsSync(config.get('hb_fonts')) ? config.get('hb_fonts'):'staticFonts')); } //Render the page From e9a76dd018f9a11a47f5f2e193e380ce7c1bb39d Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 4 Dec 2023 22:28:48 -0500 Subject: [PATCH 023/730] Use existing dependency fs-extra instead of adding new one --- server/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/app.js b/server/app.js index 6ee2d5da0..4c9899d80 100644 --- a/server/app.js +++ b/server/app.js @@ -8,7 +8,7 @@ const express = require('express'); const yaml = require('js-yaml'); const app = express(); const config = require('./config.js'); -const fs = require('fs'); +const fs = require('fs-extra'); const { homebrewApi, getBrew } = require('./homebrew.api.js'); const GoogleActions = require('./googleActions.js'); From 74c7395ab982197fe97075686a1fd4dd5748a61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 22 Jan 2024 16:59:45 +0100 Subject: [PATCH 024/730] admin look by title --- client/admin/brewLookup/brewLookup.jsx | 8 +++++ client/admin/stats/stats.jsx | 2 ++ server/admin.api.js | 42 ++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/client/admin/brewLookup/brewLookup.jsx b/client/admin/brewLookup/brewLookup.jsx index c9212d990..427c05915 100644 --- a/client/admin/brewLookup/brewLookup.jsx +++ b/client/admin/brewLookup/brewLookup.jsx @@ -66,6 +66,14 @@ const BrewLookup = createClass({ 'fa-spin fa-spinner' : this.state.searching, })} /> + + + {this.state.error &&
{this.state.error.toString()}
diff --git a/client/admin/stats/stats.jsx b/client/admin/stats/stats.jsx index 85ce10610..609d7fe43 100644 --- a/client/admin/stats/stats.jsx +++ b/client/admin/stats/stats.jsx @@ -34,6 +34,8 @@ const Stats = createClass({
Total Brew Count
{this.state.stats.totalBrews}
+
Total Brews Published Count
+
{this.state.stats.totalPublishedBrews || 'no published brews'}
{this.state.fetching diff --git a/server/admin.api.js b/server/admin.api.js index b9b2afbd7..4835411d6 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -64,6 +64,13 @@ router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{ }); }); +/* Searches for matching title, also attempts to partial match */ +router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{ + HomebrewModel.findOne({ $or : { title: { '$regex': /./, '$options': 'i' } } }).exec((err, brew)=>{ + return res.json(brew); + }); +}); + /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ uncompressedBrewQuery.exec((err, objs)=>{ @@ -91,13 +98,36 @@ router.put('/admin/compress/:id', (req, res)=>{ }); }); -router.get('/admin/stats', mw.adminOnly, (req, res)=>{ - HomebrewModel.count({}, (err, count)=>{ - return res.json({ - totalBrews : count - }); - }); +router.get('/admin/stats', mw.adminOnly, async (req, res) => { + try { + const totalBrewsCount = await HomebrewModel.countDocuments({}); + const publishedBrewsCount = await HomebrewModel.countDocuments({ published: true }); + + return res.json({ + totalBrews: totalBrewsCount, + totalPublishedBrews: publishedBrewsCount + }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } }); + + + +/* +router.get('/admin/stats', mw.adminOnly, async (req, res) => { + try { + const count = await HomebrewModel.countDocuments({}); + return res.json({ + totalBrews: count + }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } +}); +*/ router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { From c6a5f50c76ad887dd540df383c880c5175eca7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 22 Jan 2024 17:22:54 +0100 Subject: [PATCH 025/730] admin page fix --- client/admin/brewLookup/brewLookup.jsx | 8 ------ server/admin.api.js | 35 ++++++++++++++++---------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/client/admin/brewLookup/brewLookup.jsx b/client/admin/brewLookup/brewLookup.jsx index 427c05915..c9212d990 100644 --- a/client/admin/brewLookup/brewLookup.jsx +++ b/client/admin/brewLookup/brewLookup.jsx @@ -66,14 +66,6 @@ const BrewLookup = createClass({ 'fa-spin fa-spinner' : this.state.searching, })} /> - - - {this.state.error &&
{this.state.error.toString()}
diff --git a/server/admin.api.js b/server/admin.api.js index 4835411d6..c0615de1b 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -55,22 +55,31 @@ router.post('/admin/cleanup', mw.adminOnly, (req, res)=>{ }); /* Searches for matching edit or share id, also attempts to partial match */ -router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{ - HomebrewModel.findOne({ $or : [ - { editId: { '$regex': req.params.id, '$options': 'i' } }, - { shareId: { '$regex': req.params.id, '$options': 'i' } }, - ] }).exec((err, brew)=>{ - return res.json(brew); - }); + +router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next) => { + try { + const brew = await HomebrewModel.findOne({ + $or: [ + { editId: { $regex: req.params.id, $options: 'i' } }, + { shareId: { $regex: req.params.id, $options: 'i' } }, + ] + }).exec(); + + if (!brew) { + // No document found + return res.status(404).json({ error: 'Document not found' }); + } + + return res.json(brew); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } }); -/* Searches for matching title, also attempts to partial match */ -router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{ - HomebrewModel.findOne({ $or : { title: { '$regex': /./, '$options': 'i' } } }).exec((err, brew)=>{ - return res.json(brew); - }); -}); + + /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ uncompressedBrewQuery.exec((err, objs)=>{ From da699e999f6513c65b0e63fd8d5ee765fd004e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 22 Jan 2024 23:20:36 +0100 Subject: [PATCH 026/730] basic looks --- client/homebrew/homebrew.jsx | 2 + .../pages/archivePage/archivePage.jsx | 133 ++++++++++++++++++ .../pages/archivePage/archivePage.less | 74 ++++++++++ 3 files changed, 209 insertions(+) create mode 100644 client/homebrew/pages/archivePage/archivePage.jsx create mode 100644 client/homebrew/pages/archivePage/archivePage.less diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a08a39ea0..257128766 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -11,6 +11,7 @@ const SharePage = require('./pages/sharePage/sharePage.jsx'); const NewPage = require('./pages/newPage/newPage.jsx'); const ErrorPage = require('./pages/errorPage/errorPage.jsx'); const PrintPage = require('./pages/printPage/printPage.jsx'); +const ArchivePage = require('./pages/archivePage/archivePage.jsx'); const AccountPage = require('./pages/accountPage/accountPage.jsx'); const WithRoute = (props)=>{ @@ -74,6 +75,7 @@ const Homebrew = createClass({ } /> } /> } /> + }/> } /> } /> } /> diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx new file mode 100644 index 000000000..29243eeb9 --- /dev/null +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -0,0 +1,133 @@ +require('./archivePage.less'); +const React = require('react'); +const createClass = require('create-react-class'); +const _ = require('lodash'); +const cx = require('classnames'); +const moment = require('moment'); + +const Nav = require('naturalcrit/nav/nav.jsx'); +const Navbar = require('../../navbar/navbar.jsx'); + +const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; +const Account = require('../../navbar/account.navitem.jsx'); +const NewBrew = require('../../navbar/newbrew.navitem.jsx'); +const HelpNavItem = require('../../navbar/help.navitem.jsx'); + +const NaturalCritIcon = require('naturalcrit/svg/naturalcrit.svg.jsx'); + +const ArchivePage = createClass({ + displayName : 'ArchivePage', + getDefaultProps : function() { + return { + query : '', + foundBrew : null, + searching : false, + error : null + }; + }, + getInitialState : function() { + return { + uiItems : this.props.uiItems + }; + }, + handleChange(e){ + this.setState({ query: e.target.value }); + }, + lookup(){ + this.setState({ searching: true, error: null }); + + request.get(`/admin/lookup/${this.state.query}`) + .then((res)=>this.setState({ foundBrew: res.body })) + .catch((err)=>this.setState({ error: err })) + .finally(()=>this.setState({ searching: false })); + }, + renderFoundBrew(){ + const brew = this.state.foundBrew; + return
+
+
Title
+
{brew.title}
+ +
Authors
+
{brew.authors.join(', ')}
+ +
Edit Link
+
/edit/{brew.editId}
+ +
Share Link
+
/share/{brew.shareId}
+ +
Last Updated
+
{Moment(brew.updatedAt).fromNow()}
+ +
Num of Views
+
{brew.views}
+
+
; + }, + + renderForm: function() { + return
+

Brew Lookup

+ + {/* In the future, we should be able to filter the results by adding tags. + + */} + + + {this.state.error + &&
{this.state.error.toString()}
+ } + + {this.state.foundBrew + ? this.renderFoundBrew() + :
No brew found.
+ } +
; + }, + + renderResults : function() { + + }, + + renderNavItems : function() { + return + + + + + + + ; + }, + + render : function() { + return
+ {this.renderNavItems()} + +
+
+

Welcome to the Archive

+
+
+
+ {this.renderForm()} +
+
+
+

Your results, my lordship

+ {this.renderResults()} +
+
+
+
+
+ } +}); + +module.exports = ArchivePage; \ No newline at end of file diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less new file mode 100644 index 000000000..50ddf4de1 --- /dev/null +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -0,0 +1,74 @@ + + +.archivePage { + height:100%; + background-color: #2C3E50; + .content { + display:grid; + grid-template-rows: 20vh 1fr; + + .welcome { + background: url('https://i.imgur.com/MJ4YHu7.jpg'); + background-size:100%; + background-position:center; + height:20vh; + + h1 { + font-size:40px; + font-weight:900; + color:white; + filter: drop-shadow(0 0 5px black); + } + } + + .flexGroup { + height:100%; + display:grid; + grid-template-columns:1fr 2fr; + + .dataGroup { + width:100%; + height:100%; + background:white; + + &.form .brewLookup { + padding:100px; + + h2 { + font-size:20px; + font-weight: 900; + border-bottom:2px solid; + margin-block: 20px; + } + + label { + margin-right:10px; + } + input+button { + margin-left:20px; + } + } + + &.resultsContainer { + display:flex; + flex-direction: column; + border-left:2px solid; + height:76.8vh; + + .title { + height:20%; + background-color: #333; + display:grid; + place-items: center; + + h2 { + font-size:20px; + color:white; + font-weight:900; + } + } + } + } + } + } +} \ No newline at end of file From 66fd56fccbfd2a0b5a11854f21f56f51d33a97e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 22 Jan 2024 23:52:42 +0100 Subject: [PATCH 027/730] basic functionality --- .../pages/archivePage/archivePage.jsx | 87 +++++++++---------- .../pages/archivePage/archivePage.less | 38 ++++++-- server/admin.api.js | 21 ++++- 3 files changed, 94 insertions(+), 52 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 29243eeb9..31c04c5b4 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -3,7 +3,7 @@ const React = require('react'); const createClass = require('create-react-class'); const _ = require('lodash'); const cx = require('classnames'); -const moment = require('moment'); +const Moment = require('moment'); const Nav = require('naturalcrit/nav/nav.jsx'); const Navbar = require('../../navbar/navbar.jsx'); @@ -13,21 +13,19 @@ const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); -const NaturalCritIcon = require('naturalcrit/svg/naturalcrit.svg.jsx'); +const request = require('superagent'); const ArchivePage = createClass({ displayName : 'ArchivePage', getDefaultProps : function() { - return { - query : '', - foundBrew : null, - searching : false, - error : null - }; + return {}; }, getInitialState : function() { return { - uiItems : this.props.uiItems + query : '', + foundBrews : null, + searching : false, + error : null }; }, handleChange(e){ @@ -36,35 +34,42 @@ const ArchivePage = createClass({ lookup(){ this.setState({ searching: true, error: null }); - request.get(`/admin/lookup/${this.state.query}`) - .then((res)=>this.setState({ foundBrew: res.body })) + request.get(`/admin/archive/${this.state.query}`) + .then((res)=>this.setState({ foundBrews: res.body })) .catch((err)=>this.setState({ error: err })) .finally(()=>this.setState({ searching: false })); }, - renderFoundBrew(){ - const brew = this.state.foundBrew; - return
-
-
Title
-
{brew.title}
- -
Authors
-
{brew.authors.join(', ')}
- -
Edit Link
-
/edit/{brew.editId}
- -
Share Link
-
/share/{brew.shareId}
- -
Last Updated
-
{Moment(brew.updatedAt).fromNow()}
- -
Num of Views
-
{brew.views}
-
-
; - }, + renderFoundBrews() { + const brews = this.state.foundBrews; + + if (!brews || brews.length === 0) { + return
No brews found.
; + } + + return ( +
+ {brews.map((brew, index) => ( +
+
+
Title:
+
{brew.title}
+ +
Authors:
+
{brew.authors.join(', ')}
+ + Check the brew + +
Last Updated
+
{Moment(brew.updatedAt).fromNow()}
+ +
Num of Views
+
{brew.views}
+
+
+ ))} +
+ ); + }, renderForm: function() { return
@@ -79,15 +84,6 @@ const ArchivePage = createClass({ 'fa-spin fa-spinner' : this.state.searching, })} /> - - {this.state.error - &&
{this.state.error.toString()}
- } - - {this.state.foundBrew - ? this.renderFoundBrew() - :
No brew found.
- }
; }, @@ -121,8 +117,9 @@ const ArchivePage = createClass({

Your results, my lordship

- {this.renderResults()} +
+ {this.renderFoundBrews()}
diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 50ddf4de1..d9d069789 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -1,5 +1,3 @@ - - .archivePage { height:100%; background-color: #2C3E50; @@ -8,10 +6,13 @@ grid-template-rows: 20vh 1fr; .welcome { + display:grid; + place-items: center; background: url('https://i.imgur.com/MJ4YHu7.jpg'); background-size:100%; background-position:center; height:20vh; + border-bottom:5px solid #333; h1 { font-size:40px; @@ -32,10 +33,10 @@ background:white; &.form .brewLookup { - padding:100px; + padding:50px; h2 { - font-size:20px; + font-size:30px; font-weight: 900; border-bottom:2px solid; margin-block: 20px; @@ -62,13 +63,38 @@ place-items: center; h2 { - font-size:20px; + font-size:30px; color:white; font-weight:900; } } + + .foundBrews { + display:flex; + flex-direction: column; + width:100%; + + .brewItem { + width:200px; + + dt { + font-size:20px; + font-weight:900; + } + } + } } } } } -} \ No newline at end of file +} + + + + + + + + + + diff --git a/server/admin.api.js b/server/admin.api.js index c0615de1b..0c6fe1fc7 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -78,7 +78,26 @@ router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next) => { }); - +/* Searches for matching title, also attempts to partial match */ +router.get('/admin/archive/:title', mw.adminOnly, async (req, res, next) => { + try { + const brews = await HomebrewModel.find({ + title: { $regex: req.params.title, $options: 'i' }, + published: true + }).exec(); + + if (!brews || brews.length === 0) { + // No published documents found with the given title + return res.status(404).json({ error: 'Published documents not found' }); + } + + return res.json(brews); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } + }); + /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ From 7951c4a03ab60d319c9805354d987d06d4190bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 00:20:18 +0100 Subject: [PATCH 028/730] basic ui and small changes --- .../pages/archivePage/archivePage.jsx | 11 ++++++++++- .../pages/archivePage/archivePage.less | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 31c04c5b4..7a5da8916 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -55,7 +55,16 @@ const ArchivePage = createClass({
{brew.title}
Authors:
-
{brew.authors.join(', ')}
+
+ {brew.authors.map((author, index) => ( + + + {author} + + {index < brew.authors.length - 1 && ', '} + + ))} +
Check the brew diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index d9d069789..f4cc75ab1 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -57,7 +57,7 @@ height:76.8vh; .title { - height:20%; + height:100px; background-color: #333; display:grid; place-items: center; @@ -70,12 +70,25 @@ } .foundBrews { + background-color: #2C3E50; display:flex; - flex-direction: column; + flex-direction: row; + flex-wrap:wrap; width:100%; + min-height:500px; + height:max-content; + padding:50px; + padding-bottom:unset; + overflow-y:scroll; .brewItem { - width:200px; + background-image: url('/assets/parchmentBackground.jpg'); + width:500px; + height:auto; + min-height:unset; + overflow:visible; + margin-right:50px; + dt { font-size:20px; From 0dff59d793ec4b33a85e1b7babfef5fd901c1576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 08:07:51 +0100 Subject: [PATCH 029/730] linting and space issues --- .../pages/archivePage/archivePage.jsx | 275 ++++++++++-------- .../pages/archivePage/archivePage.less | 2 +- 2 files changed, 158 insertions(+), 119 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 7a5da8916..9926de3a8 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -1,139 +1,178 @@ require('./archivePage.less'); -const React = require('react'); +const React = require('react'); const createClass = require('create-react-class'); -const _ = require('lodash'); -const cx = require('classnames'); -const Moment = require('moment'); - -const Nav = require('naturalcrit/nav/nav.jsx'); -const Navbar = require('../../navbar/navbar.jsx'); +const _ = require('lodash'); +const cx = require('classnames'); +const Moment = require('moment'); +const Nav = require('naturalcrit/nav/nav.jsx'); +const Navbar = require('../../navbar/navbar.jsx'); const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; -const Account = require('../../navbar/account.navitem.jsx'); -const NewBrew = require('../../navbar/newbrew.navitem.jsx'); -const HelpNavItem = require('../../navbar/help.navitem.jsx'); +const Account = require('../../navbar/account.navitem.jsx'); +const NewBrew = require('../../navbar/newbrew.navitem.jsx'); +const HelpNavItem = require('../../navbar/help.navitem.jsx'); const request = require('superagent'); const ArchivePage = createClass({ - displayName : 'ArchivePage', - getDefaultProps : function() { - return {}; - }, - getInitialState : function() { - return { - query : '', - foundBrews : null, - searching : false, - error : null - }; - }, - handleChange(e){ - this.setState({ query: e.target.value }); - }, - lookup(){ - this.setState({ searching: true, error: null }); + displayName: 'ArchivePage', + getDefaultProps: function () { + return {}; + }, + getInitialState: function () { + return { + query : '', + foundBrews : null, + searching : false, + error : null, + }; + }, + handleChange(e) { + this.setState({ query: e.target.value }); + }, + lookup() { + this.setState({ searching: true, error: null }); - request.get(`/admin/archive/${this.state.query}`) - .then((res)=>this.setState({ foundBrews: res.body })) - .catch((err)=>this.setState({ error: err })) - .finally(()=>this.setState({ searching: false })); - }, - renderFoundBrews() { - const brews = this.state.foundBrews; - - if (!brews || brews.length === 0) { - return
No brews found.
; - } - - return ( -
- {brews.map((brew, index) => ( -
-
-
Title:
-
{brew.title}
- -
Authors:
-
- {brew.authors.map((author, index) => ( - - - {author} - - {index < brew.authors.length - 1 && ', '} + request + .get(`/admin/archive/${this.state.query}`) + .then((res) => this.setState({ foundBrews: res.body })) + .catch((err) => this.setState({ error: err })) + .finally(() => this.setState({ searching: false })); + }, + renderFoundBrews() { + const brews = this.state.foundBrews; + + if (!brews || brews.length === 0) { + return
No brews found.
; + } + + return ( +
+ {brews.map((brew, index) => ( +
+
+
Title:
+
{brew.title}
+ +
Authors:
+
+ {brew.authors.map((author, index) => ( + + + {author} + + {index < brew.authors.length - 1 && ', '} + + ))} +
+ + + Check the brew + + +
Systems:
+
{brew.systems.join(', ')}
+ + {brew.tags?.length ? ( + <> +
+ + {brew.tags.map((tag, idx) => { + const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); + return ( + + {matches[2]} - ))} -
- - Check the brew - -
Last Updated
-
{Moment(brew.updatedAt).fromNow()}
- -
Num of Views
-
{brew.views}
-
-
- ))} + ); + })} +
+ + ) : ( + <> + )} + +
Last Updated:
+
{Moment(brew.updatedAt).fromNow()}
+ +
Num of Views:
+
{brew.views}
+ - ); - }, + ))} + + ); + }, - renderForm: function() { - return
-

Brew Lookup

- - {/* In the future, we should be able to filter the results by adding tags. - + renderForm: function () { + return ( +
+

Brew Lookup

+ + + {/* In the future, we should be able to filter the results by adding tags. + */} - -
; - }, + +
+ ); + }, - renderResults : function() { + renderResults: function () {}, - }, - - renderNavItems : function() { - return - - - - - - - ; - }, + renderNavItems: function () { + return ( + + + + + + + + + ); + }, - render : function() { - return
- {this.renderNavItems()} + render: function () { + return ( +
+ {this.renderNavItems()} -
-
-

Welcome to the Archive

-
-
-
- {this.renderForm()} -
-
-
-

Your results, my lordship

- -
- {this.renderFoundBrews()} -
-
+
+
+

Welcome to the Archive

+
+
+
{this.renderForm()}
+
+
+

Your results, my lordship

+
+ {this.renderFoundBrews()}
+
- } +
+ ); + }, }); -module.exports = ArchivePage; \ No newline at end of file +module.exports = ArchivePage; diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index f4cc75ab1..08b10d86d 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -83,7 +83,7 @@ .brewItem { background-image: url('/assets/parchmentBackground.jpg'); - width:500px; + width:450px; height:auto; min-height:unset; overflow:visible; From 54a2f6940c264466267b3f7072adf0dc8f8c7398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 10:40:53 +0100 Subject: [PATCH 030/730] from admin to archive api --- .../pages/archivePage/archivePage.jsx | 74 ++----------------- server/admin.api.js | 22 ------ server/app.js | 8 ++ server/archive.api.js | 31 ++++++++ 4 files changed, 46 insertions(+), 89 deletions(-) create mode 100644 server/archive.api.js diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 9926de3a8..b413056b5 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -3,7 +3,6 @@ const React = require('react'); const createClass = require('create-react-class'); const _ = require('lodash'); const cx = require('classnames'); -const Moment = require('moment'); const Nav = require('naturalcrit/nav/nav.jsx'); const Navbar = require('../../navbar/navbar.jsx'); @@ -11,6 +10,7 @@ const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); +const ListPage = require('../basePages/listPage/listPage.jsx'); const request = require('superagent'); @@ -22,7 +22,7 @@ const ArchivePage = createClass({ getInitialState: function () { return { query : '', - foundBrews : null, + brewCollection : null, searching : false, error : null, }; @@ -34,80 +34,20 @@ const ArchivePage = createClass({ this.setState({ searching: true, error: null }); request - .get(`/admin/archive/${this.state.query}`) - .then((res) => this.setState({ foundBrews: res.body })) + .get(`/archive/${this.state.query}`) + .then((res) => this.setState({ brewCollection: res.body })) .catch((err) => this.setState({ error: err })) .finally(() => this.setState({ searching: false })); }, renderFoundBrews() { - const brews = this.state.foundBrews; + const brews = this.state.brewCollection; if (!brews || brews.length === 0) { return
No brews found.
; } - return ( -
- {brews.map((brew, index) => ( -
-
-
Title:
-
{brew.title}
- -
Authors:
-
- {brew.authors.map((author, index) => ( - - - {author} - - {index < brew.authors.length - 1 && ', '} - - ))} -
- - - Check the brew - - -
Systems:
-
{brew.systems.join(', ')}
- - {brew.tags?.length ? ( - <> -
- - {brew.tags.map((tag, idx) => { - const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); - return ( - - {matches[2]} - - ); - })} -
- - ) : ( - <> - )} - -
Last Updated:
-
{Moment(brew.updatedAt).fromNow()}
- -
Num of Views:
-
{brew.views}
-
-
- ))} -
- ); + return ; + }, renderForm: function () { diff --git a/server/admin.api.js b/server/admin.api.js index 0c6fe1fc7..0884ca03f 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -76,28 +76,6 @@ router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next) => { return res.status(500).json({ error: 'Internal Server Error' }); } }); - - -/* Searches for matching title, also attempts to partial match */ -router.get('/admin/archive/:title', mw.adminOnly, async (req, res, next) => { - try { - const brews = await HomebrewModel.find({ - title: { $regex: req.params.title, $options: 'i' }, - published: true - }).exec(); - - if (!brews || brews.length === 0) { - // No published documents found with the given title - return res.status(404).json({ error: 'Published documents not found' }); - } - - return res.json(brews); - } catch (error) { - console.error(error); - return res.status(500).json({ error: 'Internal Server Error' }); - } - }); - /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ diff --git a/server/app.js b/server/app.js index 970c2cd9c..84ea4662b 100644 --- a/server/app.js +++ b/server/app.js @@ -67,6 +67,7 @@ app.use((req, res, next)=>{ app.use(homebrewApi); app.use(require('./admin.api.js')); +app.use(require('./archive.api.js')); const HomebrewModel = require('./homebrew.model.js').model; const welcomeText = require('fs').readFileSync('client/homebrew/pages/homePage/welcome_msg.md', 'utf8'); @@ -480,6 +481,11 @@ app.use(async (err, req, res, next)=>{ res.status(err.status || err.response?.status || 500).send(err); return; } + if(err.originalUrl?.startsWith('/archive/')) { + // console.log('archive error'); + res.status(err.status || err.response?.status || 500).send(err); + return; + } // console.log('non-API error'); const status = err.status || err.code || 500; @@ -503,6 +509,8 @@ app.use(async (err, req, res, next)=>{ res.send(page); }); + + app.use((req, res)=>{ if(!res.headersSent) { console.error('Headers have not been sent, responding with a server error.', req.url); diff --git a/server/archive.api.js b/server/archive.api.js new file mode 100644 index 000000000..e4c6b704b --- /dev/null +++ b/server/archive.api.js @@ -0,0 +1,31 @@ +const HomebrewModel = require('./homebrew.model.js').model; +const router = require('express').Router(); +const asyncHandler = require('express-async-handler'); + + +const archive = { + archiveApi : router, + /* Searches for matching title, also attempts to partial match */ + findBrews : async (req, res, next) => { + try { + const brews = await HomebrewModel.find({ + title: { $regex: req.params.query, $options: 'i' }, + published: true + }).exec(); + + if (!brews || brews.length === 0) { + // No published documents found with the given title + return res.status(404).json({ error: 'Published documents not found' }); + } + + return res.json(brews); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } + } +} +router.get('/archive/:query', asyncHandler(archive.findBrews)); + + +module.exports = archive; \ No newline at end of file From 162929bdcaeb67f8ad77660ac1b23ff7662a2298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 14:02:27 +0100 Subject: [PATCH 031/730] trying to catch url with query --- client/homebrew/homebrew.jsx | 1 + .../pages/archivePage/archivePage.jsx | 33 +++++++++++++++++-- server/archive.api.js | 3 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 257128766..039d81e2c 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -76,6 +76,7 @@ const Homebrew = createClass({ } /> } /> }/> + }/> } /> } /> } /> diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index b413056b5..e79b8bf34 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -27,6 +27,20 @@ const ArchivePage = createClass({ error : null, }; }, + componentDidMount: function () { + const url = new URL(window.location.href); + const pathSegments = url.pathname.split('/'); + + // Check if there's a path parameter after /archive/ + if (pathSegments.length > 2 && pathSegments[1] === 'archive') { + const pathQuery = pathSegments[2]; + console.log(pathQuery); + this.setState({ query: pathQuery }, () => { + this.lookup(); + }); + } + }, + handleChange(e) { this.setState({ query: e.target.value }); }, @@ -39,13 +53,28 @@ const ArchivePage = createClass({ .catch((err) => this.setState({ error: err })) .finally(() => this.setState({ searching: false })); }, + updateUrl: function(query) { + const url = new URL(window.location.href); + const urlParams = new URLSearchParams(url.search); + // Clear existing parameters + urlParams.delete('sort'); + urlParams.delete('dir'); + urlParams.delete('filter'); + + // Set the pathname to '/archive/query' + url.pathname = `/archive/${this.state.query}`; + + url.search = urlParams; + window.history.replaceState(null, null, url); +}, renderFoundBrews() { const brews = this.state.brewCollection; if (!brews || brews.length === 0) { return
No brews found.
; } - + console.table(brews); + this.updateUrl(); return ; }, @@ -76,7 +105,7 @@ const ArchivePage = createClass({ ); }, - renderResults: function () {}, + renderNavItems: function () { return ( diff --git a/server/archive.api.js b/server/archive.api.js index e4c6b704b..6302e3041 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -17,7 +17,6 @@ const archive = { // No published documents found with the given title return res.status(404).json({ error: 'Published documents not found' }); } - return res.json(brews); } catch (error) { console.error(error); @@ -28,4 +27,4 @@ const archive = { router.get('/archive/:query', asyncHandler(archive.findBrews)); -module.exports = archive; \ No newline at end of file +module.exports = router; \ No newline at end of file From 4ed9fc7d0e4a3a6aaa3453e36f71d1e905323e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 18:35:09 +0100 Subject: [PATCH 032/730] fix url params --- client/homebrew/homebrew.jsx | 1 - .../pages/archivePage/archivePage.jsx | 38 +++++++++---------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 039d81e2c..257128766 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -76,7 +76,6 @@ const Homebrew = createClass({ } /> } /> }/> - }/> } /> } /> } /> diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index e79b8bf34..10c1afb03 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -10,7 +10,7 @@ const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); -const ListPage = require('../basePages/listPage/listPage.jsx'); +const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); const request = require('superagent'); @@ -21,34 +21,26 @@ const ArchivePage = createClass({ }, getInitialState: function () { return { - query : '', + title : this.props.query.title || '', brewCollection : null, searching : false, error : null, }; }, - componentDidMount: function () { - const url = new URL(window.location.href); - const pathSegments = url.pathname.split('/'); - - // Check if there's a path parameter after /archive/ - if (pathSegments.length > 2 && pathSegments[1] === 'archive') { - const pathQuery = pathSegments[2]; - console.log(pathQuery); - this.setState({ query: pathQuery }, () => { - this.lookup(); - }); - } + componentDidMount : function() { + console.log(this.state.title); + this.lookup(); }, + handleChange(e) { - this.setState({ query: e.target.value }); + this.setState({ title: e.target.value }); }, lookup() { this.setState({ searching: true, error: null }); request - .get(`/archive/${this.state.query}`) + .get(`/archive/${this.state.title}`) .then((res) => this.setState({ brewCollection: res.body })) .catch((err) => this.setState({ error: err })) .finally(() => this.setState({ searching: false })); @@ -61,8 +53,8 @@ const ArchivePage = createClass({ urlParams.delete('dir'); urlParams.delete('filter'); - // Set the pathname to '/archive/query' - url.pathname = `/archive/${this.state.query}`; + // Set the pathname to '/archive/?query' + urlParams.set('title', this.state.title); url.search = urlParams; window.history.replaceState(null, null, url); @@ -73,9 +65,13 @@ const ArchivePage = createClass({ if (!brews || brews.length === 0) { return
No brews found.
; } - console.table(brews); this.updateUrl(); - return ; + return
+ {brews.map((brew, index) => ( + + ))} +
+ }, @@ -86,7 +82,7 @@ const ArchivePage = createClass({ From 0dc1b46466c04ac594d73af0c1e68e42411769c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 19:08:57 +0100 Subject: [PATCH 033/730] stying updates, agnostic theme --- .../pages/archivePage/archivePage.less | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 08b10d86d..227ab619f 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -72,27 +72,50 @@ .foundBrews { background-color: #2C3E50; display:flex; - flex-direction: row; - flex-wrap:wrap; + flex-direction:column; width:100%; min-height:500px; height:max-content; padding:50px; padding-bottom:unset; - overflow-y:scroll; .brewItem { - background-image: url('/assets/parchmentBackground.jpg'); - width:450px; - height:auto; + height:50px; min-height:unset; - overflow:visible; - margin-right:50px; - - - dt { - font-size:20px; - font-weight:900; + width:100%; + display:flex; + color:white; + background:#707070; + .text { + min-height:unset; + width:20vw; + text-overflow: ellipsis; + overflow:hidden; + white-space: nowrap; + display:grid; + align-content:center; + h2 { + font-size: 20px; + font-weight:900; + + } + } + hr { + display:none; + } + .info { + width:100%; + display:grid; + grid-template-columns: 3fr 1fr 70px 70px 150px 50px; + align-items:center; + + br { + display:none; + } + &:not(:has(.brewTags)) { + grid-template-columns:3fr 70px 70px 150px 50px; + } + } } } @@ -107,7 +130,5 @@ - - From c50042c1e7e72893077196534444fa4f95d9e012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 23 Jan 2024 22:55:36 +0100 Subject: [PATCH 034/730] i love grid template area --- .../pages/archivePage/archivePage.less | 280 ++++++++++++------ 1 file changed, 197 insertions(+), 83 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 227ab619f..1bc5bcfbd 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -1,121 +1,243 @@ -.archivePage { - height:100%; - background-color: #2C3E50; +body { + height: 100vh; + .content { - display:grid; + height: 100%; + } +} + +.archivePage { + overflow-y: hidden; + height: 100%; + background-color: #2C3E50; + + .content { + display: grid; grid-template-rows: 20vh 1fr; - + .welcome { - display:grid; + display: grid; place-items: center; background: url('https://i.imgur.com/MJ4YHu7.jpg'); - background-size:100%; - background-position:center; - height:20vh; - border-bottom:5px solid #333; - + background-size: 100%; + background-position: center; + height: 20vh; + border-bottom: 5px solid #333; + h1 { - font-size:40px; - font-weight:900; - color:white; + font-size: 40px; + font-weight: 900; + color: white; filter: drop-shadow(0 0 5px black); } } - + .flexGroup { - height:100%; - display:grid; - grid-template-columns:1fr 2fr; - + height: 100%; + display: grid; + grid-template-columns: 1fr 2fr; + .dataGroup { - width:100%; - height:100%; - background:white; - + width: 100%; + height: 100%; + background: white; + &.form .brewLookup { - padding:50px; - + padding: 50px; + h2 { - font-size:30px; + font-size: 30px; font-weight: 900; - border-bottom:2px solid; + border-bottom: 2px solid; margin-block: 20px; } - + label { - margin-right:10px; + margin-right: 10px; } + input+button { - margin-left:20px; + margin-left: 20px; } } - + &.resultsContainer { - display:flex; + display: flex; flex-direction: column; - border-left:2px solid; - height:76.8vh; - + border-left: 2px solid; + height: 100%; + .title { - height:100px; + height: 100px; background-color: #333; - display:grid; + display: grid; place-items: center; - + h2 { - font-size:30px; - color:white; - font-weight:900; + font-size: 30px; + color: white; + font-weight: 900; } } - + .foundBrews { background-color: #2C3E50; - display:flex; - flex-direction:column; - width:100%; - min-height:500px; - height:max-content; - padding:50px; - padding-bottom:unset; - + display: flex; + flex-direction: column; + width: 100%; + min-height: 500px; + height: 100%; + padding: 50px; + padding-bottom: unset; + .brewItem { - height:50px; - min-height:unset; - width:100%; - display:flex; - color:white; - background:#707070; + height: 50px; + min-height: unset; + width: 100%; + display: flex; + color: white; + background: #707070; + overflow: visible; + .text { - min-height:unset; - width:20vw; - text-overflow: ellipsis; - overflow:hidden; - white-space: nowrap; - display:grid; - align-content:center; + min-height: unset; + width: 20vw; + padding-inline:10px; + + display: grid; + align-content: center; + h2 { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; font-size: 20px; - font-weight:900; - + font-weight: 900; + } } + hr { - display:none; + display: none; } + .info { - width:100%; - display:grid; - grid-template-columns: 3fr 1fr 70px 70px 150px 50px; - align-items:center; - + width: 100%; + display: grid; + grid-template-areas: "tags authors views pages update storage"; + justify-content: end; + align-content: space-around; + grid-template-columns: 3fr 150px 70px 70px 200px 50px; br { - display:none; + display: none; } - &:not(:has(.brewTags)) { - grid-template-columns:3fr 70px 70px 150px 50px; + .brewTags{ + display:inline-block; + grid-area: tags; + } + [title*="Authors:"] { + display:inline-block; + grid-area: authors; + } + [title*="Last"] { + display:inline-block; + grid-area: views; + } + [title*="Page"] { + display:inline-block; + grid-area: pages; + } + [title*="Created"] { + display:inline-block; + grid-area: update; } + [title*="Storage"] { + display:inline-block; + grid-area: storage; + filter:drop-shadow(0 0 10px white); + } + + .brewTags { + padding-left: 10px; + } + + .brewTags:has(span:nth-of-type(4)) { + position: relative; + overflow: hidden; + display: flex; + flex-wrap: wrap; + + + span:nth-of-type(n+2) { + display: none; + } + + &:hover { + overflow: visible; + position: absolute; + top: 0; + background:#707070; + height: max-content; + z-index: 100; + width:min-content; + + span:nth-of-type(n+4) { + display: block; + } + + &:after { + position: absolute; + top: 48px; + right: 0; + left:0; + bottom:0; + content: ''; + display: block; + height: calc(100% - 48px); + background: #707070; + border-inline: 1px solid gold; + border-bottom: 1px solid gold; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + z-index: -1; + } + } + } + + + + } + + .links { + opacity: 1; + background: none; + position: relative; + display: grid; + grid-template-columns: 1fr 1fr; + height: 100%; + width: 100px; + + .editLink, + .deleteLink { + display: none; + } + + >a { + opacity: .8; + + &:hover { + opacity: 1; + } + } + + .shareLink { + color: deepskyblue; + } + + .downloadLink { + color: coral; + } } } } @@ -123,12 +245,4 @@ } } } -} - - - - - - - - +} \ No newline at end of file From 0c167d803c180c5953a0206c063b39ba8ffad0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 24 Jan 2024 21:15:00 +0100 Subject: [PATCH 035/730] limit the search --- server/archive.api.js | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index 6302e3041..73ec2f170 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -2,29 +2,38 @@ const HomebrewModel = require('./homebrew.model.js').model; const router = require('express').Router(); const asyncHandler = require('express-async-handler'); - const archive = { - archiveApi : router, + archiveApi: router, /* Searches for matching title, also attempts to partial match */ - findBrews : async (req, res, next) => { + findBrews: async (req, res, next) => { try { - const brews = await HomebrewModel.find({ - title: { $regex: req.params.query, $options: 'i' }, - published: true - }).exec(); - - if (!brews || brews.length === 0) { - // No published documents found with the given title - return res.status(404).json({ error: 'Published documents not found' }); - } - return res.json(brews); + const limit = 3; + const brews = await HomebrewModel.find({ + title: { $regex: req.params.query, $options: 'i' }, + published: true + }) + .limit(limit) + .exec(); + + if (!brews || brews.length === 0) { + // No published documents found with the given title + return res.status(404).json({ error: 'Published documents not found' }); + } + + let message = ''; + if (brews.length === limit) { + // If the limit has been reached, include a message in the response + message = `You've reached the limit of ${limit} documents, you can try being more specific in your search.`; + } + + return res.json({ brews, message }); } catch (error) { - console.error(error); - return res.status(500).json({ error: 'Internal Server Error' }); + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); } } } + router.get('/archive/:query', asyncHandler(archive.findBrews)); - -module.exports = router; \ No newline at end of file +module.exports = router; From 89fddd02101e0a1873ee30a66bc5200b22fb4221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 24 Jan 2024 21:15:26 +0100 Subject: [PATCH 036/730] limit search and adapt ui --- .../pages/archivePage/archivePage.jsx | 10 ++++++-- .../pages/archivePage/archivePage.less | 25 ++++++++++++++++--- server/archive.api.js | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 10c1afb03..80bab8619 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -25,6 +25,7 @@ const ArchivePage = createClass({ brewCollection : null, searching : false, error : null, + limit : '', }; }, componentDidMount : function() { @@ -38,10 +39,9 @@ const ArchivePage = createClass({ }, lookup() { this.setState({ searching: true, error: null }); - request .get(`/archive/${this.state.title}`) - .then((res) => this.setState({ brewCollection: res.body })) + .then((res) => this.setState({ brewCollection: res.body.brews }, this.setState({ limit: res.body.message}))) .catch((err) => this.setState({ error: err })) .finally(() => this.setState({ searching: false })); }, @@ -67,6 +67,9 @@ const ArchivePage = createClass({ } this.updateUrl(); return
+
+

{this.state.limit}

+
{brews.map((brew, index) => ( ))} @@ -84,11 +87,14 @@ const ArchivePage = createClass({ type='text' value={this.state.title} onChange={this.handleChange} + onKeyDown={(e) => e.key === 'Enter' && this.lookup()} placeholder='v3 Reference Document' /> {/* In the future, we should be able to filter the results by adding tags. + */} + + )} + Page {page} + {page < totalPages && ( + + )}
- ); - } - - if (!brews || brews.length === 0) { - return( -
-

We haven't found brews meeting your request.

-
- - ); - } - this.updateUrl(); - return
- {brews.length} Brews Found - {this.state.limit} - {brews.map((brew, index) => ( - - ))} -
- - + ); }, + renderForm: function () { return (
@@ -115,7 +125,7 @@ const ArchivePage = createClass({ onKeyDown={(e) => { if (e.key === 'Enter') { this.handleChange(e); - this.lookup(); + this.loadPage(1); } }} placeholder='v3 Reference Document' @@ -125,7 +135,7 @@ const ArchivePage = createClass({ */} - - )} - Page {page} - {page < totalPages && ( - - )} -
-
- ); - }, + try { + //this.updateUrl(); + this.setState({ searching: true, error: null }); + const title = encodeURIComponent(this.state.title); + const response = await fetch(`/archive?title=${title}&page=${page}`); - renderForm: function () { - return ( -
-

Brew Lookup

- - { - if (e.key === 'Enter') { - this.handleChange(e); - this.loadPage(1); - } - }} - placeholder='v3 Reference Document' - /> - {/* In the future, we should be able to filter the results by adding tags. + if(response.ok) { + const res = await response.json(); + this.updateStateWithBrews(res.brews, page, res.totalPages); + } + + } catch (error) { + console.log(`LoadPage error: ${error}`); + } + } + }, + updateUrl : function() { + const url = new URL(window.location.href); + const urlParams = new URLSearchParams(url.search); + + // Set the title and page parameters + urlParams.set('title', this.state.title); + urlParams.set('page', this.state.page); + + url.search = urlParams.toString(); // Convert URLSearchParams to string + window.history.replaceState(null, null, url); + }, + + renderFoundBrews() { + const { title, brewCollection, page, totalPages, error } = this.state; + + if(title === '') {return (

Whenever you want, just start typing...

);} + + if(error !== null) { + return ( +
+

I'm sorry, your request didn't work

+

Your search is not specific enough. Too many brews meet this criteria for us to display them.

+
+ ); + } + + if(!brewCollection || brewCollection.length === 0) { + return ( +
+

We haven't found brews meeting your request.

+
+ ); + } + + return ( +
+ {`Brews Found: ${brewCollection.length}`} + + {brewCollection.map((brew, index)=>( + + ))} +
+ {page > 1 && ( + + )} + Page {page} + {page < totalPages && ( + + )} +
+
+ ); + }, + + + renderForm : function () { + return ( +
+

Brew Lookup

+ + { + if(e.key === 'Enter') { + this.handleChange(e); + this.loadPage(1); + } + }} + placeholder='v3 Reference Document' + /> + {/* In the future, we should be able to filter the results by adding tags. */} - - -
- ); - }, - + +
+ ); + }, - renderNavItems: function () { - return ( - - + + + renderNavItems : function () { + return ( + + Archive: Search for brews - - - - - - - - ); - }, + + + + + + + + ); + }, - render: function () { - return ( -
- + render : function () { + return ( +
+ - {this.renderNavItems()} + {this.renderNavItems()} -
-
-

Welcome to the Archive

-
-
-
{this.renderForm()}
-
-
-

Your results, my lordship

-
- {this.renderFoundBrews()} -
-
-
-
- ); - }, +
+
+

Welcome to the Archive

+
+
+
{this.renderForm()}
+
+
+

Your results, my lordship

+
+ {this.renderFoundBrews()} +
+
+
+
+ ); + }, }); module.exports = ArchivePage; diff --git a/server/archive.api.js b/server/archive.api.js index 4166bf80a..d959b27b8 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -3,49 +3,49 @@ const router = require('express').Router(); const asyncHandler = require('express-async-handler'); const archive = { - archiveApi: router, - /* Searches for matching title, also attempts to partial match */ - findBrews: async (req, res, next) => { - try { - const title = req.query.title || ''; - const page = parseInt(req.query.page) || 1; - console.log('try:',page); - const pageSize = 10; // Set a default page size - const skip = (page - 1) * pageSize; + archiveApi : router, + /* Searches for matching title, also attempts to partial match */ + findBrews : async (req, res, next)=>{ + try { + const title = req.query.title || ''; + const page = parseInt(req.query.page) || 1; + console.log('try:', page); + const pageSize = 10; // Set a default page size + const skip = (page - 1) * pageSize; - const titleQuery = { - title: { $regex: decodeURIComponent(title), $options: 'i' }, - published: true - }; + const titleQuery = { + title : { $regex: decodeURIComponent(title), $options: 'i' }, + published : true + }; - const projection = { - editId: 0, - googleId: 0, - text: 0, - textBin: 0, - }; + const projection = { + editId : 0, + googleId : 0, + text : 0, + textBin : 0, + }; - const brews = await HomebrewModel.find(titleQuery, projection) + const brews = await HomebrewModel.find(titleQuery, projection) .skip(skip) .limit(pageSize) .maxTimeMS(5000) .exec(); - if (!brews || brews.length === 0) { - // No published documents found with the given title - return res.status(404).json({ error: 'Published documents not found' }); - } + if(!brews || brews.length === 0) { + // No published documents found with the given title + return res.status(404).json({ error: 'Published documents not found' }); + } - const totalDocuments = await HomebrewModel.countDocuments(title); + const totalDocuments = await HomebrewModel.countDocuments(title); - const totalPages = Math.ceil(totalDocuments / pageSize); + const totalPages = Math.ceil(totalDocuments / pageSize); - return res.json({ brews, page, totalPages}); - } catch (error) { - console.error(error); - return res.status(500).json({ error: 'Internal Server Error' }); - } - } + return res.json({ brews, page, totalPages }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } + } }; router.get('/archive', asyncHandler(archive.findBrews)); From 1d778e3249d79789920daaabf7d63bd1c3352ba2 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 13 Feb 2024 09:13:47 +1300 Subject: [PATCH 061/730] Update API route --- server/archive.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/archive.api.js b/server/archive.api.js index d959b27b8..196b634a5 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -48,6 +48,6 @@ const archive = { } }; -router.get('/archive', asyncHandler(archive.findBrews)); +router.get('/api/archive', asyncHandler(archive.findBrews)); module.exports = router; \ No newline at end of file From eeec24ae78fb54f7549cc93a8315a70f2aa36040 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 13 Feb 2024 09:14:31 +1300 Subject: [PATCH 062/730] Change fetch to use request-middleware instead --- .../pages/archivePage/archivePage.jsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index aae1b6631..49025bf30 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -13,7 +13,7 @@ const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); -const request = require('superagent'); +const request = require('../../utils/request-middleware.js'); const ArchivePage = createClass({ displayName : 'ArchivePage', @@ -37,14 +37,15 @@ const ArchivePage = createClass({ this.setState({ title: e.target.value }); }, - updateStateWithBrews : (brews, page, totalPages)=>{ + updateStateWithBrews : function (brews, page, totalPages) { this.setState({ - brewCollection : brews, - page : page, - totalPages : totalPages, + brewCollection : brews || null, + page : page || 1, + totalPages : totalPages || 1, searching : false }); }, + loadPage : async function(page) { if(this.state.title == '') {} else { @@ -52,19 +53,18 @@ const ArchivePage = createClass({ //this.updateUrl(); this.setState({ searching: true, error: null }); const title = encodeURIComponent(this.state.title); - const response = await fetch(`/archive?title=${title}&page=${page}`); - - - if(response.ok) { - const res = await response.json(); - this.updateStateWithBrews(res.brews, page, res.totalPages); - } - + await request.get(`/api/archive?title=${title}&page=${page}`) + .then((response)=>{ + if(response.ok) { + this.updateStateWithBrews(response.body.brews, page, response.body.totalPages); + } + }); } catch (error) { console.log(`LoadPage error: ${error}`); } } }, + updateUrl : function() { const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); From 05a7defcb82a639eb3fb661c1b5f83e1eb77cb66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 12 Feb 2024 23:18:24 +0100 Subject: [PATCH 063/730] remove brewCount useless element --- client/homebrew/pages/archivePage/archivePage.jsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 49025bf30..c05ce3bec 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -101,18 +101,16 @@ const ArchivePage = createClass({ return (
- {`Brews Found: ${brewCollection.length}`} - {brewCollection.map((brew, index)=>( ))}
{page > 1 && ( - + )} Page {page} {page < totalPages && ( - + )}
From d233e2b4a5f2a91da4e5463033623abe510f29d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 12 Feb 2024 23:18:37 +0100 Subject: [PATCH 064/730] css fix, pagination controls basic look --- .../pages/archivePage/archivePage.less | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index e0ae9460e..ec0460958 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -140,7 +140,7 @@ body { margin-right: 40px; color: black; - &:nth-child(even) { + &:nth-child(even of .brewItem) { margin-right: 0; } h2 { @@ -162,6 +162,34 @@ body { } } + .paginationControls { + position: absolute; + left: 50%; + translate: -50%; + width: 500px; + display: grid; + grid-template-areas: "previousPage currentPage nextPage"; + + .currentPage { + grid-area: currentPage; + height: 100%; + width: 100%; + display: block; + text-align: center; + color: white; + font-family: Open Sans; + font-weight: 900; + padding: 5px 8px; + } + + button.previousPage { + grid-area: previousPage; + } + button.nextPage { + grid-area: nextPage; + } + } + hr { visibility: hidden; } From 534131d994fc0540e4886510fdb053cc54296e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 12 Feb 2024 23:54:00 +0100 Subject: [PATCH 065/730] edit console logs and change totalDocs logic to count correctly --- server/archive.api.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index 196b634a5..fe3d9609c 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -9,7 +9,7 @@ const archive = { try { const title = req.query.title || ''; const page = parseInt(req.query.page) || 1; - console.log('try:', page); + console.log('trying page ', page); const pageSize = 10; // Set a default page size const skip = (page - 1) * pageSize; @@ -17,29 +17,28 @@ const archive = { title : { $regex: decodeURIComponent(title), $options: 'i' }, published : true }; - const projection = { editId : 0, googleId : 0, text : 0, textBin : 0, }; - const brews = await HomebrewModel.find(titleQuery, projection) .skip(skip) .limit(pageSize) .maxTimeMS(5000) .exec(); + console.log(brews.length); if(!brews || brews.length === 0) { // No published documents found with the given title return res.status(404).json({ error: 'Published documents not found' }); } - - const totalDocuments = await HomebrewModel.countDocuments(title); - + const totalDocuments = await HomebrewModel.countDocuments(titleQuery, projection); + const totalPages = Math.ceil(totalDocuments / pageSize); - + console.log('Total brews: ', totalDocuments); + console.log('Total pages: ', totalPages); return res.json({ brews, page, totalPages }); } catch (error) { console.error(error); From 2f323cde8aa784a1a88fd3b5b52d461607bd8c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 12 Feb 2024 23:54:15 +0100 Subject: [PATCH 066/730] remove unused logic from loadpage --- .../pages/archivePage/archivePage.jsx | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index c05ce3bec..84a26f84c 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -47,21 +47,19 @@ const ArchivePage = createClass({ }, loadPage : async function(page) { - if(this.state.title == '') {} else { - - try { - //this.updateUrl(); - this.setState({ searching: true, error: null }); - const title = encodeURIComponent(this.state.title); - await request.get(`/api/archive?title=${title}&page=${page}`) - .then((response)=>{ - if(response.ok) { - this.updateStateWithBrews(response.body.brews, page, response.body.totalPages); - } - }); - } catch (error) { - console.log(`LoadPage error: ${error}`); - } + this.updateUrl(); + try { + //this.updateUrl(); + this.setState({ searching: true, error: null }); + const title = encodeURIComponent(this.state.title); + await request.get(`/api/archive?title=${title}&page=${page}`) + .then((response)=>{ + if(response.ok) { + this.updateStateWithBrews(response.body.brews, page, response.body.totalPages); + } + }); + } catch (error) { + console.log(`LoadPage error: ${error}`); } }, From 7ffc02c3e54b7caa3e80e3646e2ffd92c9fa81ba Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 13 Feb 2024 13:25:45 +1300 Subject: [PATCH 067/730] Reset searching state on error --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 84a26f84c..73fc90af2 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -60,6 +60,7 @@ const ArchivePage = createClass({ }); } catch (error) { console.log(`LoadPage error: ${error}`); + this.updateStateWithBrews([], 1, 1); } }, From 9fc8af65536f5f0fe80b429c63ab3ab555d04a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 13 Feb 2024 10:48:19 +0100 Subject: [PATCH 068/730] pagination controls render separately --- .../pages/archivePage/archivePage.jsx | 36 +++++++++++---- .../pages/archivePage/archivePage.less | 45 ++++++++++++++----- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 84a26f84c..a29824202 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -75,6 +75,32 @@ const ArchivePage = createClass({ window.history.replaceState(null, null, url); }, + renderPaginationControls() { + const { title, brewCollection, page, totalPages, error } = this.state; + const pages = new Array(totalPages).fill().map((_, index) => ( +
  • this.loadPage(index+1)}>{index + 1}
  • + )); + + return ( +
    + {page > 1 && ( + + )} +
      {pages}
    + {page < totalPages && ( + + )} +
    + ); + }, + renderFoundBrews() { const { title, brewCollection, page, totalPages, error } = this.state; @@ -102,15 +128,7 @@ const ArchivePage = createClass({ {brewCollection.map((brew, index)=>( ))} -
    - {page > 1 && ( - - )} - Page {page} - {page < totalPages && ( - - )} -
    + {this.renderPagination()} ); }, diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index ec0460958..7e10c2ef3 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -166,28 +166,49 @@ body { position: absolute; left: 50%; translate: -50%; - width: 500px; + width: auto; display: grid; + place-items: center; grid-template-areas: "previousPage currentPage nextPage"; + grid-template-columns: 50px 1fr 50px; - .currentPage { + .pages { grid-area: currentPage; height: 100%; width: 100%; - display: block; + display: flex; + justify-content:space-evenly; text-align: center; - color: white; - font-family: Open Sans; - font-weight: 900; padding: 5px 8px; + + .pageNumber { + color: white; + font-family: Open Sans; + font-weight: 900; + text-underline-position: under; + margin-inline:10px; + cursor: pointer; + + &.currentPage { + color:gold; + text-decoration:underline; + pointer-events:none; + } + } + } + button { + width:max-content; + border-radius:5px; + + &.previousPage { + grid-area: previousPage; + } + + &.nextPage { + grid-area: nextPage; + } } - button.previousPage { - grid-area: previousPage; - } - button.nextPage { - grid-area: nextPage; - } } hr { From 74ac8f9ffa9a71c47176a0efc69ba105e8795833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 13 Feb 2024 10:52:12 +0100 Subject: [PATCH 069/730] quickfix --- client/homebrew/pages/archivePage/archivePage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index c7f7b4d93..5bbee10b8 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -129,7 +129,7 @@ const ArchivePage = createClass({ {brewCollection.map((brew, index)=>( ))} - {this.renderPagination()} + {this.renderPaginationControls()} ); }, From 3482d92ab631903b6127faf03ace8e04e7c38fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 01:10:28 +0100 Subject: [PATCH 070/730] catch 503 error --- client/homebrew/pages/archivePage/archivePage.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 5bbee10b8..ebe24f7bc 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -60,6 +60,7 @@ const ArchivePage = createClass({ }); } catch (error) { console.log(`LoadPage error: ${error}`); + this.setState({ error: {error} }); this.updateStateWithBrews([], 1, 1); } }, @@ -67,8 +68,7 @@ const ArchivePage = createClass({ updateUrl : function() { const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); - - // Set the title and page parameters + urlParams.set('title', this.state.title); urlParams.set('page', this.state.page); @@ -107,7 +107,7 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} - if(error !== null) { + if(error === 'Error: Service Unavailable') { return (

    I'm sorry, your request didn't work

    @@ -116,7 +116,7 @@ const ArchivePage = createClass({ ); } - if(!brewCollection || brewCollection.length === 0) { + if(!brewCollection || brewCollection.length === 0 || error === 'Error: Not found') { return (

    We haven't found brews meeting your request.

    From 46262c56dbb2ad375d1b46a1d82c57425fe93c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 01:15:00 +0100 Subject: [PATCH 071/730] 503 catch 2 --- client/homebrew/pages/archivePage/archivePage.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index ebe24f7bc..3fc85c162 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -47,9 +47,8 @@ const ArchivePage = createClass({ }, loadPage : async function(page) { - this.updateUrl(); + this.updateUrl(); try { - //this.updateUrl(); this.setState({ searching: true, error: null }); const title = encodeURIComponent(this.state.title); await request.get(`/api/archive?title=${title}&page=${page}`) @@ -60,7 +59,7 @@ const ArchivePage = createClass({ }); } catch (error) { console.log(`LoadPage error: ${error}`); - this.setState({ error: {error} }); + this.setState({ error: `${error}` }); this.updateStateWithBrews([], 1, 1); } }, From 3427fa1e94ffeca923b0328f697a265b90a69bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 01:26:54 +0100 Subject: [PATCH 072/730] total brews found --- client/homebrew/pages/archivePage/archivePage.jsx | 7 +++++-- server/archive.api.js | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 3fc85c162..f82488af3 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -26,6 +26,7 @@ const ArchivePage = createClass({ brewCollection : null, page : 1, totalPages : 1, + totalBrews : 0, searching : false, error : null, }; @@ -37,11 +38,12 @@ const ArchivePage = createClass({ this.setState({ title: e.target.value }); }, - updateStateWithBrews : function (brews, page, totalPages) { + updateStateWithBrews : function (brews, page, totalPages, totalBrews) { this.setState({ brewCollection : brews || null, page : page || 1, totalPages : totalPages || 1, + totalBrews : totalBrews, searching : false }); }, @@ -54,7 +56,7 @@ const ArchivePage = createClass({ await request.get(`/api/archive?title=${title}&page=${page}`) .then((response)=>{ if(response.ok) { - this.updateStateWithBrews(response.body.brews, page, response.body.totalPages); + this.updateStateWithBrews(response.body.brews, page, response.body.totalPages, response.body.totalBrews); } }); } catch (error) { @@ -125,6 +127,7 @@ const ArchivePage = createClass({ return (
    + Brews found: {this.state.totalBrews} {brewCollection.map((brew, index)=>( ))} diff --git a/server/archive.api.js b/server/archive.api.js index fe3d9609c..2e2ecb711 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -34,12 +34,12 @@ const archive = { // No published documents found with the given title return res.status(404).json({ error: 'Published documents not found' }); } - const totalDocuments = await HomebrewModel.countDocuments(titleQuery, projection); + const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection); - const totalPages = Math.ceil(totalDocuments / pageSize); - console.log('Total brews: ', totalDocuments); + const totalPages = Math.ceil(totalBrews / pageSize); + console.log('Total brews: ', totalBrews); console.log('Total pages: ', totalPages); - return res.json({ brews, page, totalPages }); + return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); return res.status(500).json({ error: 'Internal Server Error' }); From ea1855485c12f2542f7c45fc513b60151faf7610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 01:27:05 +0100 Subject: [PATCH 073/730] css fixes --- .../pages/archivePage/archivePage.less | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 7e10c2ef3..0f51d3a4a 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -97,11 +97,12 @@ body { } &.noBrews { - display:grid; - place-items:center; + display: grid; + place-items: center; + color: white; } - .brewCount { + .totalBrews { position: fixed; bottom: 0; right: 17px; @@ -112,27 +113,6 @@ body { padding: 8px 10px; z-index: 1000; font-family: 'Open Sans'; - - &:empty { - display: none; - } - } - - .limit { - position: fixed; - bottom: 0; - left: 502px; - font-size: 11px; - font-weight: 800; - color: white; - background-color: #333; - padding: 8px 10px; - z-index: 1000; - font-family: 'Open Sans'; - - &:empty { - display: none; - } } .brewItem { background-image: url('/assets/parchmentBackground.jpg'); From 153ab6339396b21747efff97c985613ea7a4d192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 08:48:47 +0100 Subject: [PATCH 074/730] pagesize as input --- .../pages/archivePage/archivePage.jsx | 78 ++++++++++++------- .../pages/archivePage/archivePage.less | 25 ++++-- server/archive.api.js | 5 +- 3 files changed, 74 insertions(+), 34 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index f82488af3..07496f244 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -25,6 +25,7 @@ const ArchivePage = createClass({ title : this.props.query.title || '', brewCollection : null, page : 1, + pageSize : 10, totalPages : 1, totalBrews : 0, searching : false, @@ -34,8 +35,9 @@ const ArchivePage = createClass({ componentDidMount : function() { }, - handleChange(e) { - this.setState({ title: e.target.value }); + handleChange(inputName, e) { + + this.setState({ [inputName]: e.target.value }); }, updateStateWithBrews : function (brews, page, totalPages, totalBrews) { @@ -53,7 +55,8 @@ const ArchivePage = createClass({ try { this.setState({ searching: true, error: null }); const title = encodeURIComponent(this.state.title); - await request.get(`/api/archive?title=${title}&page=${page}`) + const size = parseInt(this.state.pageSize); + await request.get(`/api/archive?title=${title}&page=${page}&size=${size}`) .then((response)=>{ if(response.ok) { this.updateStateWithBrews(response.body.brews, page, response.body.totalPages, response.body.totalBrews); @@ -140,33 +143,54 @@ const ArchivePage = createClass({ renderForm : function () { return (
    -

    Brew Lookup

    - - { - if(e.key === 'Enter') { - this.handleChange(e); - this.loadPage(1); - } - }} - placeholder='v3 Reference Document' - /> - {/* In the future, we should be able to filter the results by adding tags. - - - */} +

    Brew Lookup

    +
    + + + + {/* In the future, we should be able to filter the results by adding tags. + + + */} - + })} + /> + +
    ); }, diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 0f51d3a4a..cfe085662 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -48,20 +48,35 @@ body { background: white; &.form .brewLookup { + position: relative; padding: 50px; - h2 { + .formTitle { + color:black; font-size: 30px; border-bottom: 2px solid; - margin-block: 20px; + margin: 20px 0; + text-align: center; } + .formContents { + display: flex; + flex-direction: column; + } label { - margin-right: 10px; + margin: 10px 0; } + input { + margin: 0 10px; + } + .search { + position:absolute; + right:10px; + bottom:20px; - input+button { - margin-left: 20px; + i { + margin-left: 10px; + } } } diff --git a/server/archive.api.js b/server/archive.api.js index 2e2ecb711..dcc45a977 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -8,9 +8,10 @@ const archive = { findBrews : async (req, res, next)=>{ try { const title = req.query.title || ''; - const page = parseInt(req.query.page) || 1; + const page = Math.max(parseInt(req.query.page) || 1, 1); console.log('trying page ', page); - const pageSize = 10; // Set a default page size + const minPageSize = 6; + const pageSize = Math.max(parseInt(req.query.size) || 10, minPageSize); const skip = (page - 1) * pageSize; const titleQuery = { From 6a11cd0e28f5531bd48febd57a217d7cfdd5f081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 10:34:39 +0100 Subject: [PATCH 075/730] renderer filter query --- .../pages/archivePage/archivePage.jsx | 58 ++++++++++++++++--- server/archive.api.js | 21 +++++-- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 07496f244..5c5e5a2ab 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -12,6 +12,7 @@ const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); +//const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx'); const request = require('../../utils/request-middleware.js'); @@ -22,12 +23,20 @@ const ArchivePage = createClass({ }, getInitialState : function () { return { + //request title : this.props.query.title || '', - brewCollection : null, - page : 1, + //tags : {}, + legacy : true, + v3 : true, pageSize : 10, - totalPages : 1, - totalBrews : 0, + page : 1, + + //response + brewCollection : null, + totalPages : null, + totalBrews : null, + + searching : false, error : null, }; @@ -36,7 +45,6 @@ const ArchivePage = createClass({ }, handleChange(inputName, e) { - this.setState({ [inputName]: e.target.value }); }, @@ -54,9 +62,11 @@ const ArchivePage = createClass({ this.updateUrl(); try { this.setState({ searching: true, error: null }); + const title = encodeURIComponent(this.state.title); const size = parseInt(this.state.pageSize); - await request.get(`/api/archive?title=${title}&page=${page}&size=${size}`) + const {legacy, v3} = this.state; + await request.get(`/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}`) .then((response)=>{ if(response.ok) { this.updateStateWithBrews(response.body.brews, page, response.body.totalPages, response.body.totalBrews); @@ -75,16 +85,22 @@ const ArchivePage = createClass({ urlParams.set('title', this.state.title); urlParams.set('page', this.state.page); + urlParams.set('pageSize', this.state.pageSize); + urlParams.set('v3', this.state.v3); + urlParams.set('legacy', this.state.legacy); + url.search = urlParams.toString(); // Convert URLSearchParams to string window.history.replaceState(null, null, url); }, renderPaginationControls() { - const { title, brewCollection, page, totalPages, error } = this.state; + const { page, totalPages,} = this.state; const pages = new Array(totalPages).fill().map((_, index) => (
  • this.loadPage(index+1)}>{index + 1}
  • )); + + if(totalPages === null) {return;} return (
    @@ -171,9 +187,33 @@ const ArchivePage = createClass({ onChange={(e) => this.handleChange('pageSize', e)} /> + + + + + + {/* In the future, we should be able to filter the results by adding tags. - - + <this.handleChange('tags', e)}/> + + check metadataEditor.jsx L65 */} )}
      {pages}
    {page < totalPages && ( - )} @@ -123,26 +133,34 @@ const ArchivePage = createClass({ }, renderFoundBrews() { - const { title, brewCollection, page, totalPages, error } = this.state; + const { title, brewCollection, page, totalPages, error, searching } = this.state; + console.log(searching === false && !brewCollection); + if(searching === false && title === '' && error === null) {return (

    Whenever you want, just start typing...

    );} - if(title === '' && error === null) {return (

    Whenever you want, just start typing...

    );} - - if(error === 'Error: Service Unavailable') { + if(searching === false && error === 'Error: Service Unavailable') { return (

    I'm sorry, your request didn't work


    Your search is not specific enough. Too many brews meet this criteria for us to display them.

    ); - } - - if(!brewCollection || brewCollection.length === 0 || error === 'Error: Not found') { + }; + + if(searching === false && (!brewCollection || error === 'Error: Not found')) { return (

    We haven't found brews meeting your request.

    ); - } + }; + + if(searching === true) { + return ( +
    +

    Searching

    ...

    +
    + ); + }; return (
    @@ -157,6 +175,9 @@ const ArchivePage = createClass({ renderForm : function () { + const v3 = (this.state.v3 === 'true'); + const legacy = (this.state.legacy === 'true'); + return (

    Brew Lookup

    @@ -164,14 +185,13 @@ const ArchivePage = createClass({
    +
    + ); }, renderPaginationControls() { - const { page, totalPages} = this.state; + const title = encodeURIComponent(this.state.title); + const size = parseInt(this.state.pageSize); + const {page, totalPages, legacy, v3} = this.state; + console.log('page: ', page); const pages = new Array(totalPages).fill().map((_, index) => ( -
  • this.loadPage(index + 1, false)}>{index + 1}
  • + {index + 1} )); - + if(totalPages === null) {return;} return ( @@ -173,105 +282,6 @@ const ArchivePage = createClass({ ); }, - - renderForm : function () { - const v3 = (this.state.v3 === 'true'); - const legacy = (this.state.legacy === 'true'); - - return ( -
    -

    Brew Lookup

    -
    - - - - - - - - - - {/* In the future, we should be able to filter the results by adding tags. - <this.handleChange('tags', e)}/> - - check metadataEditor.jsx L65 - */} - - -
    -
    - ); - }, - - - - renderNavItems : function () { - return ( - - - Archive: Search for brews - - - - - - - - - ); - }, - render : function () { return (
    From fcb4c722c653ca20270d1658f6f47e24850c5ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 15:28:36 +0100 Subject: [PATCH 079/730] test 404 error --- client/homebrew/pages/archivePage/archivePage.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 88fbc05aa..d3ea65545 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -243,7 +243,6 @@ const ArchivePage = createClass({ renderFoundBrews() { const { title, brewCollection, page, totalPages, error, searching } = this.state; - console.log(searching === false && !brewCollection); if(searching === false && title === '' && error === null) {return (

    Whenever you want, just start typing...

    );} if(searching === false && error === 'Error: Service Unavailable') { @@ -254,7 +253,7 @@ const ArchivePage = createClass({
    ); }; - + console.log('404: ', searching === false && (!brewCollection || error === 'Error: Not found')) if(searching === false && (!brewCollection || error === 'Error: Not found')) { return (
    From d7c9ab43bcb211f59fb38b6f2972290e79ab6278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 15:34:10 +0100 Subject: [PATCH 080/730] more tests --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index d3ea65545..365bb5f2a 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -253,6 +253,7 @@ const ArchivePage = createClass({
    ); }; + console.log(searching, !brewCollection, error); console.log('404: ', searching === false && (!brewCollection || error === 'Error: Not found')) if(searching === false && (!brewCollection || error === 'Error: Not found')) { return ( From 62db3939692cfee996d7f4389a0f821c64d5ce96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 15:50:27 +0100 Subject: [PATCH 081/730] proper error handling(i think) --- .../pages/archivePage/archivePage.jsx | 54 +++++++++++-------- server/archive.api.js | 10 +++- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 365bb5f2a..07eae0311 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -243,27 +243,8 @@ const ArchivePage = createClass({ renderFoundBrews() { const { title, brewCollection, page, totalPages, error, searching } = this.state; - if(searching === false && title === '' && error === null) {return (

    Whenever you want, just start typing...

    );} - - if(searching === false && error === 'Error: Service Unavailable') { - return ( -
    -

    I'm sorry, your request didn't work

    -

    Your search is not specific enough. Too many brews meet this criteria for us to display them.

    -
    - ); - }; - console.log(searching, !brewCollection, error); - console.log('404: ', searching === false && (!brewCollection || error === 'Error: Not found')) - if(searching === false && (!brewCollection || error === 'Error: Not found')) { - return ( -
    -

    We haven't found brews meeting your request.

    -
    - ); - }; - - if(searching === true) { + + if(searching) { return (

    Searching

    ...

    @@ -271,6 +252,37 @@ const ArchivePage = createClass({ ); }; + if(title === '') {return (

    Whenever you want, just start typing...

    );} + + if (error) { + let errorMessage; + switch (error.errorCode) { + case '404': + errorMessage = "We didn't find any brew"; + break; + case '503': + errorMessage = 'Your search is not specific enough. Too many brews meet this criteria for us to display them.'; + break; + case '500': + default: + errorMessage = 'An unexpected error occurred'; + } + + return ( +
    +

    Error: {errorMessage}

    +
    + ); + }; + + if (!brewCollection || brewCollection.length === 0) { + return ( +
    +

    No brews found

    +
    + ); + }; + return (
    Brews found: {this.state.totalBrews} diff --git a/server/archive.api.js b/server/archive.api.js index 1c00d7f0a..3a8dd41b2 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -46,6 +46,10 @@ const archive = { // No published documents found with the given title return res.status(404).json({ error: 'Published documents not found' }); } + if (!brews || brews.length === 0) { + return res.status(404).json({ errorCode: '404', message: 'Published documents not found' }); + } + const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection); const totalPages = Math.ceil(totalBrews / pageSize); @@ -54,7 +58,11 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); - return res.status(500).json({ error: 'Internal Server Error' }); + if (error.response && error.response.status === 503) { + return res.status(503).json({ errorCode: '503', message: 'Service Unavailable' }); + } else { + return res.status(500).json({ errorCode: '500', message: 'Internal Server Error' }); + } } } }; From 9c53541cbde0cee6563cbce867599269610f0911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 15:53:26 +0100 Subject: [PATCH 082/730] searching animation --- .../homebrew/pages/archivePage/archivePage.jsx | 2 +- .../homebrew/pages/archivePage/archivePage.less | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 07eae0311..539abc65b 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -247,7 +247,7 @@ const ArchivePage = createClass({ if(searching) { return (
    -

    Searching

    ...

    +

    Searching

    ); }; diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 665c94a94..251b3ce52 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -122,7 +122,15 @@ body { place-items: center; color: white; - h3.searchAnim { + h3 { position: relative;} + h3.searchAnim::after { + content: ""; + width: max-content; + height: 1em; + position: absolute; + right: 0; + top: 50%; + translate: 100% -50%; animation: trailingDots 2s ease infinite; } } @@ -229,13 +237,13 @@ body { @keyframes trailingDots { 0%,32% { - clip-path:inset(0 66% 0 0); + content:'.'; } 33%, 65% { - clip-path:inset(0 33% 0 0); + content:'..'; } 66%,100% { - clip-path:inset(0 0% 0 0); + content:'...'; } } \ No newline at end of file From 1a80a74d4fb5fdf53e11380a3f26ef8532565dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:15:38 +0100 Subject: [PATCH 083/730] more error handling --- client/homebrew/pages/archivePage/archivePage.jsx | 1 - server/archive.api.js | 12 +++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 539abc65b..52c35586a 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -214,7 +214,6 @@ const ArchivePage = createClass({ const title = encodeURIComponent(this.state.title); const size = parseInt(this.state.pageSize); const {page, totalPages, legacy, v3} = this.state; - console.log('page: ', page); const pages = new Array(totalPages).fill().map((_, index) => ( {index + 1} )); diff --git a/server/archive.api.js b/server/archive.api.js index 3a8dd41b2..33ce01014 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -40,15 +40,6 @@ const archive = { .limit(pageSize) .maxTimeMS(5000) .exec(); - //console.log(brews.length); - - if(!brews || brews.length === 0) { - // No published documents found with the given title - return res.status(404).json({ error: 'Published documents not found' }); - } - if (!brews || brews.length === 0) { - return res.status(404).json({ errorCode: '404', message: 'Published documents not found' }); - } const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection); @@ -58,6 +49,9 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); + if (error.response && error.response.status === 404) { + return res.status(404).json({ errorCode: '404', message: 'Brews not found' }); + } if (error.response && error.response.status === 503) { return res.status(503).json({ errorCode: '503', message: 'Service Unavailable' }); } else { From e08435568cb19e331c4457c8335da25de15a892f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:20:08 +0100 Subject: [PATCH 084/730] don't search on reload without title --- client/homebrew/pages/archivePage/archivePage.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 52c35586a..cdccb4652 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -41,7 +41,10 @@ const ArchivePage = createClass({ }; }, componentDidMount : function() { - this.loadPage(this.state.page, false); + if (this.state.title !== '') { + this.loadPage(this.state.page, false); + } + }, updateStateWithBrews : function (brews, page, totalPages, totalBrews) { From 3afc9f83d9b5a8793f7e0411f2d0366b1af0f63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:23:37 +0100 Subject: [PATCH 085/730] where the hell did i lose the error handling --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index cdccb4652..3bdf44289 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -257,6 +257,7 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} if (error) { + console.log(error.errorCode); let errorMessage; switch (error.errorCode) { case '404': From 04844a4422ce84d2f1f79e68d498bb5c91172b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:27:50 +0100 Subject: [PATCH 086/730] you know the deal --- server/archive.api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/archive.api.js b/server/archive.api.js index 33ce01014..fbc26f20d 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -49,6 +49,7 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); + console.log(error.response.status); if (error.response && error.response.status === 404) { return res.status(404).json({ errorCode: '404', message: 'Brews not found' }); } From f61b664687548af9e90b83ebd419199689a55a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:32:50 +0100 Subject: [PATCH 087/730] 503 log --- server/archive.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/archive.api.js b/server/archive.api.js index fbc26f20d..7caa7f07c 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -49,7 +49,7 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); - console.log(error.response.status); + console.log(error.response); if (error.response && error.response.status === 404) { return res.status(404).json({ errorCode: '404', message: 'Brews not found' }); } From 2a780bc48240aa51c4267174ef57b9c29842b14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:36:10 +0100 Subject: [PATCH 088/730] 503 --- server/archive.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/archive.api.js b/server/archive.api.js index 7caa7f07c..a7f545e79 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -49,7 +49,7 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); - console.log(error.response); + console.log(error); if (error.response && error.response.status === 404) { return res.status(404).json({ errorCode: '404', message: 'Brews not found' }); } From 0fdb5e83cfa10eefd19881a2222be4bcaeb5c013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:44:03 +0100 Subject: [PATCH 089/730] if this renders null i don't understand anything --- client/homebrew/pages/archivePage/archivePage.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 3bdf44289..3e69b034b 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -114,7 +114,9 @@ const ArchivePage = createClass({ } }); } catch (error) { - console.log(`LoadPage error: ${error}`); + if (error.response && error.response.status === 503) { + console.log('loadPage 503'); + } this.setState({ error: `${error}` }); this.updateStateWithBrews([], 1, 1, 0); } @@ -257,7 +259,7 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} if (error) { - console.log(error.errorCode); + console.log('render Error: ', error); let errorMessage; switch (error.errorCode) { case '404': From eb404b8e5b9a710cadf7509e1b6aca73dac06173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:51:20 +0100 Subject: [PATCH 090/730] where is my 503 error code --- client/homebrew/pages/archivePage/archivePage.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 3e69b034b..7517927e8 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -117,7 +117,7 @@ const ArchivePage = createClass({ if (error.response && error.response.status === 503) { console.log('loadPage 503'); } - this.setState({ error: `${error}` }); + this.setState({ error: `${error}` }) this.updateStateWithBrews([], 1, 1, 0); } }, @@ -259,7 +259,7 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} if (error) { - console.log('render Error: ', error); + console.log('render Error: ', error.errorCode); let errorMessage; switch (error.errorCode) { case '404': From 8c07b12bb0f971d1ef1b65e7ba8987dccd7ecb80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:56:09 +0100 Subject: [PATCH 091/730] catch error codes --- client/homebrew/pages/archivePage/archivePage.jsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 7517927e8..fb587bdad 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -114,10 +114,7 @@ const ArchivePage = createClass({ } }); } catch (error) { - if (error.response && error.response.status === 503) { - console.log('loadPage 503'); - } - this.setState({ error: `${error}` }) + this.setState({ error: `${error.response.status}` }) this.updateStateWithBrews([], 1, 1, 0); } }, From fd6109099ade59f0ae51edf2c94536ac7b2ea191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 16:59:17 +0100 Subject: [PATCH 092/730] catch catch catch --- client/homebrew/pages/archivePage/archivePage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index fb587bdad..31e2684b8 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -256,7 +256,7 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} if (error) { - console.log('render Error: ', error.errorCode); + console.log('render Error: ', error); let errorMessage; switch (error.errorCode) { case '404': From 01e3cd0296bba0ff4215ee7cb42c2411b64c50b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 15 Feb 2024 17:22:20 +0100 Subject: [PATCH 093/730] fix notitle search and catch 404? --- .../pages/archivePage/archivePage.jsx | 28 ++++++++++++------- server/archive.api.js | 6 +--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 31e2684b8..9228d1a33 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -100,8 +100,8 @@ const ArchivePage = createClass({ if(update === true) { this.updateStateWithForm(); }; - - try { + if (title !== '') { + try { this.setState({ searching: true, error: null }); const title = encodeURIComponent(this.state.title); @@ -117,6 +117,12 @@ const ArchivePage = createClass({ this.setState({ error: `${error.response.status}` }) this.updateStateWithBrews([], 1, 1, 0); } + console.log(!this.state.brewCollection || brewCollection.length === 0); + if(!this.state.brewCollection) { + this.setState({ error: '404'}); + } + } + }, renderNavItems : function () { @@ -253,8 +259,16 @@ const ArchivePage = createClass({ ); }; - if(title === '') {return (

    Whenever you want, just start typing...

    );} + + if(title === '') {return (

    Whenever you want, just start typing...

    );} + if (!brewCollection || brewCollection.length === 0) { + return ( +
    +

    No brews found

    +
    + ); + }; if (error) { console.log('render Error: ', error); let errorMessage; @@ -277,13 +291,7 @@ const ArchivePage = createClass({ ); }; - if (!brewCollection || brewCollection.length === 0) { - return ( -
    -

    No brews found

    -
    - ); - }; + return (
    diff --git a/server/archive.api.js b/server/archive.api.js index a7f545e79..fffe24497 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -41,7 +41,7 @@ const archive = { .maxTimeMS(5000) .exec(); - const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection); + const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection).maxTimeMS(5000); const totalPages = Math.ceil(totalBrews / pageSize); //console.log('Total brews: ', totalBrews); @@ -49,10 +49,6 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews}); } catch (error) { console.error(error); - console.log(error); - if (error.response && error.response.status === 404) { - return res.status(404).json({ errorCode: '404', message: 'Brews not found' }); - } if (error.response && error.response.status === 503) { return res.status(503).json({ errorCode: '503', message: 'Service Unavailable' }); } else { From 094ad3bd59d99a34e49a9e1e2d35f77361d0981b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 21 Feb 2024 08:07:46 +0100 Subject: [PATCH 094/730] -proj in countdocs --- server/archive.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/archive.api.js b/server/archive.api.js index fffe24497..6779526e2 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -41,7 +41,7 @@ const archive = { .maxTimeMS(5000) .exec(); - const totalBrews = await HomebrewModel.countDocuments(titleQuery, projection).maxTimeMS(5000); + const totalBrews = await HomebrewModel.countDocuments(titleQuery).maxTimeMS(5000); const totalPages = Math.ceil(totalBrews / pageSize); //console.log('Total brews: ', totalBrews); From e75c556443c7821335c96e20cf2595caba7f8307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 6 May 2024 22:59:09 +0200 Subject: [PATCH 095/730] use $text instead --- server/archive.api.js | 122 ++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index 6779526e2..578004fc0 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -3,61 +3,105 @@ const router = require('express').Router(); const asyncHandler = require('express-async-handler'); const archive = { - archiveApi : router, - /* Searches for matching title, also attempts to partial match */ - findBrews : async (req, res, next)=>{ - try { - console.table(req.query); + archiveApi: router, + /* Searches for matching title, also attempts to partial match */ + findBrews: async (req, res, next) => { + try { + /* + const dbName = HomebrewModel.db.name; + console.log("Database Name:", dbName); + const collectionName = HomebrewModel.collection.name; + console.log("Collection Name:", collectionName); + + */ + console.table(req.query); - const title = req.query.title || ''; - const page = Math.max(parseInt(req.query.page) || 1, 1); - const minPageSize = 6; - const pageSize = Math.max(parseInt(req.query.size) || 10, minPageSize); - const skip = (page - 1) * pageSize; - - const titleQuery = { - title : { $regex: decodeURIComponent(title), $options: 'i' }, - $or: [], - published : true - }; + const title = req.query.title || ''; + const page = Math.max(parseInt(req.query.page) || 1, 1); + const minPageSize = 6; + const pageSize = Math.max( + parseInt(req.query.size) || 10, + minPageSize + ); + const skip = (page - 1) * pageSize; - if (req.query.legacy === 'true') { - titleQuery.$or.push({ renderer: 'legacy' }); + const brewsQuery = { + $or: [], + published: true, }; + if (req.query.legacy === 'true') { + brewsQuery.$or.push({ renderer: 'legacy' }); + } + if (req.query.v3 === 'true') { - titleQuery.$or.push({ renderer: 'V3' }); + brewsQuery.$or.push({ renderer: 'V3' }); + } + + // If user wants to use RegEx it needs to format like /text/ + const titleConditionsArray = + title.startsWith('/') && title.endsWith('/') + ? [ + { + 'title': { + $regex: title.slice(1, -1), + $options: 'i', + }, + }, + ] + : buildTitleConditions(title); + + function buildTitleConditions(inputString) { + return [ + { + $text: { + $search: inputString, + $caseSensitive: false, + }, + }, + ]; + } + + const titleQuery = { + $and: [brewsQuery, ...titleConditionsArray], }; - const projection = { - editId : 0, - googleId : 0, - text : 0, - textBin : 0, - }; - const brews = await HomebrewModel.find(titleQuery, projection) + const projection = { + editId: 0, + googleId: 0, + text: 0, + textBin: 0, + }; + const brews = await HomebrewModel.find(titleQuery, projection) .skip(skip) .limit(pageSize) .maxTimeMS(5000) .exec(); - const totalBrews = await HomebrewModel.countDocuments(titleQuery).maxTimeMS(5000); - - const totalPages = Math.ceil(totalBrews / pageSize); - //console.log('Total brews: ', totalBrews); - //console.log('Total pages: ', totalPages); - return res.json({ brews, page, totalPages, totalBrews}); - } catch (error) { - console.error(error); + const totalBrews = await HomebrewModel.countDocuments( + titleQuery + ).maxTimeMS(5000); + + const totalPages = Math.ceil(totalBrews / pageSize); + console.log('Total brews: ', totalBrews); + console.log('Total pages: ', totalPages); + return res.json({ brews, page, totalPages, totalBrews }); + } catch (error) { + console.error(error); if (error.response && error.response.status === 503) { - return res.status(503).json({ errorCode: '503', message: 'Service Unavailable' }); + return res + .status(503) + .json({ errorCode: '503', message: 'Service Unavailable' }); } else { - return res.status(500).json({ errorCode: '500', message: 'Internal Server Error' }); + return res.status(500).json({ + errorCode: '500', + message: 'Internal Server Error', + }); } - } - } + } + }, }; router.get('/api/archive', asyncHandler(archive.findBrews)); -module.exports = router; \ No newline at end of file +module.exports = router; From 51fcb59f095eae8722052d2c9ed711c85e150b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 6 May 2024 23:26:02 +0200 Subject: [PATCH 096/730] debugging 500 errir catching --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + server/archive.api.js | 1 + 2 files changed, 2 insertions(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 9228d1a33..90d9104a0 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -249,6 +249,7 @@ const ArchivePage = createClass({ }, renderFoundBrews() { + console.table(this.state); const { title, brewCollection, page, totalPages, error, searching } = this.state; if(searching) { diff --git a/server/archive.api.js b/server/archive.api.js index 578004fc0..9fa87eb80 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -88,6 +88,7 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews }); } catch (error) { console.error(error); + console.log('error status number: ', error.response.status); if (error.response && error.response.status === 503) { return res .status(503) From ded78c66399b473843e771dacff096d0b1b8059b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 6 May 2024 23:32:18 +0200 Subject: [PATCH 097/730] better error handling in jsx --- .../pages/archivePage/archivePage.jsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 90d9104a0..4dc921fd3 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -263,24 +263,19 @@ const ArchivePage = createClass({ if(title === '') {return (

    Whenever you want, just start typing...

    );} - if (!brewCollection || brewCollection.length === 0) { - return ( -
    -

    No brews found

    -
    - ); - }; + if (error) { console.log('render Error: ', error); let errorMessage; switch (error.errorCode) { case '404': - errorMessage = "We didn't find any brew"; + errorMessage = "404 - We didn't find any brew"; break; case '503': - errorMessage = 'Your search is not specific enough. Too many brews meet this criteria for us to display them.'; + errorMessage = ' 503 - Your search is not specific enough. Too many brews meet this criteria for us to display them.'; break; case '500': + errorMessage = "500 - We don't know what happened." default: errorMessage = 'An unexpected error occurred'; } @@ -291,6 +286,15 @@ const ArchivePage = createClass({
    ); }; + + if (!brewCollection || brewCollection.length === 0) { + return ( +
    +

    No brews found

    +
    + ); + }; + From f1a2037bca76c89f48ea1e5fff81e2b3ff378317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 6 May 2024 23:40:31 +0200 Subject: [PATCH 098/730] page is sometimes a string?? --- client/homebrew/pages/archivePage/archivePage.jsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 4dc921fd3..37923dd5d 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -29,7 +29,7 @@ const ArchivePage = createClass({ legacy : `${this.props.query.legacy === 'false' ? false : true }`, v3 : `${this.props.query.v3 === 'false' ? false : true }`, pageSize : this.props.query.size || 10, - page : this.props.query.page || 1, + page : parseInt(this.props.query.page) || 1, //response brewCollection : null, @@ -50,7 +50,7 @@ const ArchivePage = createClass({ updateStateWithBrews : function (brews, page, totalPages, totalBrews) { this.setState({ brewCollection : brews || null, - page : page || 1, + page : parseInt(page) || 1, totalPages : totalPages || 1, totalBrews : totalBrews, searching : false @@ -293,10 +293,7 @@ const ArchivePage = createClass({

    No brews found

    ); - }; - - - + }; return (
    From f9f2e604c07e536811f01bb957ecaaa1a5865cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 7 May 2024 10:14:46 +0200 Subject: [PATCH 099/730] linting and remove async conflict --- .../pages/archivePage/archivePage.jsx | 617 ++++++++++-------- server/archive.api.js | 31 +- 2 files changed, 353 insertions(+), 295 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 37923dd5d..9f5068a28 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -1,197 +1,203 @@ require('./archivePage.less'); -const React = require('react'); +const React = require('react'); const createClass = require('create-react-class'); -const _ = require('lodash'); -const cx = require('classnames'); +const _ = require('lodash'); +const cx = require('classnames'); -const Nav = require('naturalcrit/nav/nav.jsx'); -const Navbar = require('../../navbar/navbar.jsx'); +const Nav = require('naturalcrit/nav/nav.jsx'); +const Navbar = require('../../navbar/navbar.jsx'); const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; -const Account = require('../../navbar/account.navitem.jsx'); -const NewBrew = require('../../navbar/newbrew.navitem.jsx'); -const HelpNavItem = require('../../navbar/help.navitem.jsx'); -const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); +const Account = require('../../navbar/account.navitem.jsx'); +const NewBrew = require('../../navbar/newbrew.navitem.jsx'); +const HelpNavItem = require('../../navbar/help.navitem.jsx'); +const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); //const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx'); const request = require('../../utils/request-middleware.js'); const ArchivePage = createClass({ - displayName : 'ArchivePage', - getDefaultProps : function () { - return {}; - }, - getInitialState : function () { - return { - //request - title : this.props.query.title || '', - //tags : {}, - legacy : `${this.props.query.legacy === 'false' ? false : true }`, - v3 : `${this.props.query.v3 === 'false' ? false : true }`, - pageSize : this.props.query.size || 10, - page : parseInt(this.props.query.page) || 1, + displayName: 'ArchivePage', + getDefaultProps: function () { + return {}; + }, + getInitialState: function () { + return { + //request + title: this.props.query.title || '', + //tags : {}, + legacy: `${this.props.query.legacy === 'false' ? false : true}`, + v3: `${this.props.query.v3 === 'false' ? false : true}`, + pageSize: this.props.query.size || 10, + page: parseInt(this.props.query.page) || 1, - //response - brewCollection : null, - totalPages : null, - totalBrews : null, + //response + brewCollection: null, + totalPages: null, + totalBrews: null, - searching : false, - error : null, - }; - }, - componentDidMount : function() { - if (this.state.title !== '') { - this.loadPage(this.state.page, false); - } - - }, + searching: false, + error: null, + }; + }, + componentDidMount: function () { + if (this.state.title !== '') { + this.loadPage(this.state.page, false); + } + }, - updateStateWithBrews : function (brews, page, totalPages, totalBrews) { - this.setState({ - brewCollection : brews || null, - page : parseInt(page) || 1, - totalPages : totalPages || 1, - totalBrews : totalBrews, - searching : false - }); - }, + updateStateWithBrews: function (brews, page, totalPages, totalBrews) { + this.setState({ + brewCollection: brews || null, + page: parseInt(page) || 1, + totalPages: totalPages || 1, + totalBrews: totalBrews, + searching: false, + }); + }, - updateStateWithForm : function() { - const title = document.getElementById( 'title' ).value || ""; - const size = document.getElementById( 'size' ).value || 10; - const page = 1; - const v3 = document.getElementById('v3').checked; - const legacy = document.getElementById('legacy').checked; + updateUrl: function (title, page, size, v3, legacy) { + const url = new URL(window.location.href); + const urlParams = new URLSearchParams(url.search); - this.setState({ - title: title, - pageSize: size, - v3: v3, - legacy: legacy - }); - this.updateUrl(title, page, size, v3, legacy); - }, + //clean all params + urlParams.delete('title'); + urlParams.delete('page'); + urlParams.delete('size'); + urlParams.delete('v3'); + urlParams.delete('legacy'); + urlParams.set('title', title); + urlParams.set('page', page); + urlParams.set('size', size); + urlParams.set('v3', v3); + urlParams.set('legacy', legacy); - updateUrl : function(title, page, size, v3, legacy) { - const url = new URL(window.location.href); - const urlParams = new URLSearchParams(url.search); + url.search = urlParams.toString(); // Convert URLSearchParams to string + window.history.replaceState(null, null, url); + }, - //clean all params - urlParams.delete('title'); - urlParams.delete('page'); - urlParams.delete('size'); - urlParams.delete('v3'); - urlParams.delete('legacy'); - - urlParams.set('title', title); - urlParams.set('page', page); - urlParams.set('size', size); - urlParams.set('v3', v3); - urlParams.set('legacy', legacy); - + loadPage: async function (page, update) { + //load form data directly + const title = document.getElementById('title').value || ''; + const size = document.getElementById('size').value || 10; + const v3 = document.getElementById('v3').checked; + const legacy = document.getElementById('legacy').checked; - url.search = urlParams.toString(); // Convert URLSearchParams to string - window.history.replaceState(null, null, url); - }, + // Update state with form data for later, only when first page + if (update === true) { + this.setState({ + title: title, + pageSize: size, + v3: v3, + legacy: legacy, + }); + this.updateUrl(title, page, size, v3, legacy); + } - loadPage : async function(page, update) { - if(update === true) { - this.updateStateWithForm(); - }; - if (title !== '') { - try { - this.setState({ searching: true, error: null }); - - const title = encodeURIComponent(this.state.title); - const size = parseInt(this.state.pageSize); - const {legacy, v3} = this.state; - await request.get(`/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}`) - .then((response)=>{ - if(response.ok) { - this.updateStateWithBrews(response.body.brews, page, response.body.totalPages, response.body.totalBrews); - } - }); - } catch (error) { - this.setState({ error: `${error.response.status}` }) - this.updateStateWithBrews([], 1, 1, 0); - } - console.log(!this.state.brewCollection || brewCollection.length === 0); - if(!this.state.brewCollection) { - this.setState({ error: '404'}); - } - } - - }, + if (title !== '') { + try { + this.setState({ searching: true, error: null }); - renderNavItems : function () { - return ( - - - Archive: Search for brews - - - - - - - - - ); - }, + await request + .get( + `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` + ) + .then((response) => { + if (response.ok) { + this.updateStateWithBrews( + response.body.brews, + page, + response.body.totalPages, + response.body.totalBrews + ); + } + }); + } catch (error) { + this.setState({ error: `${error.response.status}` }); + this.updateStateWithBrews([], 1, 1, 0); + } + console.log('a', + !this.state.brewCollection || brewCollection.length === 0 + ); + if (!this.state.brewCollection) { + this.setState({ error: '404' }); + } + } - renderForm : function () { - return ( -
    -

    Brew Lookup

    -
    - - - + + }, - + renderNavItems: function () { + return ( + + + + Archive: Search for brews + + + + + + + + + + ); + }, - - + renderForm: function () { + return ( +
    +

    Brew Lookup

    +
    + - {/* In the future, we should be able to filter the results by adding tags. + + + + + + + {/* In the future, we should be able to filter the results by adding tags. <{ - this.loadPage(1, true); - }}> - Search - - -
    -
    - ); - }, + +
    +
    + ); + }, - renderPaginationControls() { - const title = encodeURIComponent(this.state.title); - const size = parseInt(this.state.pageSize); - const {page, totalPages, legacy, v3} = this.state; - const pages = new Array(totalPages).fill().map((_, index) => ( - {index + 1} - )); - - if(totalPages === null) {return;} - - return ( -
    - {page > 1 && ( - - )} -
      {pages}
    - {page < totalPages && ( - - )} -
    - ); - }, + renderPaginationControls() { + const title = encodeURIComponent(this.state.title); + const size = parseInt(this.state.pageSize); + const { page, totalPages, legacy, v3 } = this.state; + const pages = new Array(totalPages).fill().map((_, index) => ( + + {index + 1} + + )); - renderFoundBrews() { - console.table(this.state); - const { title, brewCollection, page, totalPages, error, searching } = this.state; - - if(searching) { - return ( -
    -

    Searching

    -
    - ); - }; + if (totalPages === null) { + return; + } + return ( +
    + {page > 1 && ( + + )} +
      {pages}
    + {page < totalPages && ( + + )} +
    + ); + }, + renderFoundBrews() { + console.log('State when rendering:'); + console.table(this.state); + const { title, brewCollection, page, totalPages, error, searching } = + this.state; - if(title === '') {return (

    Whenever you want, just start typing...

    );} + if (searching) { + return ( +
    +

    Searching

    +
    + ); + } - if (error) { - console.log('render Error: ', error); - let errorMessage; - switch (error.errorCode) { - case '404': - errorMessage = "404 - We didn't find any brew"; - break; - case '503': - errorMessage = ' 503 - Your search is not specific enough. Too many brews meet this criteria for us to display them.'; - break; - case '500': - errorMessage = "500 - We don't know what happened." - default: - errorMessage = 'An unexpected error occurred'; - } - - return ( -
    -

    Error: {errorMessage}

    -
    - ); - }; + if (title === '') { + return ( +
    +

    Whenever you want, just start typing...

    +
    + ); + } - if (!brewCollection || brewCollection.length === 0) { - return ( -
    -

    No brews found

    -
    - ); - }; - - return ( -
    - Brews found: {this.state.totalBrews} - {brewCollection.map((brew, index)=>( - - ))} - {this.renderPaginationControls()} -
    - ); - }, + if (error) { + console.log('render Error: ', error); + let errorMessage; + switch (error.errorCode) { + case '404': + errorMessage = "404 - We didn't find any brew"; + break; + case '503': + errorMessage = + ' 503 - Your search is not specific enough. Too many brews meet this criteria for us to display them.'; + break; + case '500': + errorMessage = "500 - We don't know what happened."; + default: + errorMessage = 'An unexpected error occurred'; + } - render : function () { - return ( -
    - - - {this.renderNavItems()} + return ( +
    +

    Error: {errorMessage}

    +
    + ); + } -
    -
    -

    Welcome to the Archive

    -
    -
    -
    {this.renderForm()}
    -
    -
    -

    Your results, my lordship

    -
    - {this.renderFoundBrews()} -
    -
    -
    -
    - ); - }, + if (!brewCollection || brewCollection.length === 0) { + return ( +
    +

    No brews found

    +
    + ); + } + + return ( +
    + + Brews found: {this.state.totalBrews} + + {brewCollection.map((brew, index) => ( + + ))} + {this.renderPaginationControls()} +
    + ); + }, + + render: function () { + return ( +
    + + + {this.renderNavItems()} + +
    +
    +

    Welcome to the Archive

    +
    +
    +
    + {this.renderForm()} +
    +
    +
    +

    Your results, my lordship

    +
    + {this.renderFoundBrews()} +
    +
    +
    +
    + ); + }, }); module.exports = ArchivePage; diff --git a/server/archive.api.js b/server/archive.api.js index 9fa87eb80..ee1be4b7a 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -8,12 +8,18 @@ const archive = { findBrews: async (req, res, next) => { try { /* + //log db name and collection name, for local purposes const dbName = HomebrewModel.db.name; console.log("Database Name:", dbName); const collectionName = HomebrewModel.collection.name; console.log("Collection Name:", collectionName); */ + + const bright = '\x1b[1m'; // Bright (bold) style + const yellow = '\x1b[93m'; // yellow color + const reset = '\x1b[0m'; // Reset to default style + console.log(`Query as received in ${bright + yellow}archive api${reset}:`); console.table(req.query); const title = req.query.title || ''; @@ -88,11 +94,26 @@ const archive = { return res.json({ brews, page, totalPages, totalBrews }); } catch (error) { console.error(error); - console.log('error status number: ', error.response.status); - if (error.response && error.response.status === 503) { - return res - .status(503) - .json({ errorCode: '503', message: 'Service Unavailable' }); + + if (error.response && error.response.status) { + const status = error.response.status; + + if (status === 500) { + return res.status(500).json({ + errorCode: '500', + message: 'Internal Server Error', + }); + } else if (status === 503) { + return res.status(503).json({ + errorCode: '503', + message: 'Service Unavailable', + }); + } else { + return res.status(status).json({ + errorCode: status.toString(), + message: 'Internal Server Error', + }); + } } else { return res.status(500).json({ errorCode: '500', From 02450982c180fd0f0250523ed741c3f957885c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 8 May 2024 13:32:03 +0200 Subject: [PATCH 100/730] fix brewCollection issue --- client/homebrew/pages/archivePage/archivePage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 9f5068a28..7edb5c807 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -118,7 +118,7 @@ const ArchivePage = createClass({ this.updateStateWithBrews([], 1, 1, 0); } console.log('a', - !this.state.brewCollection || brewCollection.length === 0 + !this.state.brewCollection || this.state.brewCollection.length === 0 ); if (!this.state.brewCollection) { this.setState({ error: '404' }); From 9966e6322d525aee7c813b9b5cdfbe2ea7ae7b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 8 May 2024 15:33:27 +0200 Subject: [PATCH 101/730] pagination controls update search terms --- client/homebrew/pages/archivePage/archivePage.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 7edb5c807..4ac2e4a35 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -117,7 +117,7 @@ const ArchivePage = createClass({ this.setState({ error: `${error.response.status}` }); this.updateStateWithBrews([], 1, 1, 0); } - console.log('a', + console.log("We've come up empty", !this.state.brewCollection || this.state.brewCollection.length === 0 ); if (!this.state.brewCollection) { @@ -252,7 +252,7 @@ const ArchivePage = createClass({ {page > 1 && ( @@ -261,7 +261,7 @@ const ArchivePage = createClass({ {page < totalPages && ( From e30a0c3dce518f4cf8c18068795fe4283b8058e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 8 May 2024 15:41:44 +0200 Subject: [PATCH 102/730] page size log to track issue --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 4ac2e4a35..4f2ea2ca9 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -96,6 +96,7 @@ const ArchivePage = createClass({ } if (title !== '') { + console.log('pagesize when querying: ', this.state.pageSize); try { this.setState({ searching: true, error: null }); From 22f4dade4fa3ed58021fc2da30545cce8fb67f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 8 May 2024 15:51:14 +0200 Subject: [PATCH 103/730] default value to page size --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 4f2ea2ca9..76f89bc5c 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -176,6 +176,7 @@ const ArchivePage = createClass({ min="6" step="2" max="30" + defaultValue={this.state.pageSize} name="pageSize" /> From cca0f3b4dc2297c236367b895ecaddc72e4b89df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 8 May 2024 15:51:31 +0200 Subject: [PATCH 104/730] Revert "pagination controls update search terms" This reverts commit 9966e6322d525aee7c813b9b5cdfbe2ea7ae7b1b. --- client/homebrew/pages/archivePage/archivePage.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 76f89bc5c..eb8e78cc7 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -118,7 +118,7 @@ const ArchivePage = createClass({ this.setState({ error: `${error.response.status}` }); this.updateStateWithBrews([], 1, 1, 0); } - console.log("We've come up empty", + console.log('a', !this.state.brewCollection || this.state.brewCollection.length === 0 ); if (!this.state.brewCollection) { @@ -254,7 +254,7 @@ const ArchivePage = createClass({ {page > 1 && ( @@ -263,7 +263,7 @@ const ArchivePage = createClass({ {page < totalPages && ( From 5eeac603db2e51fd4c59047c249e0c4c9ad9ef8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 9 May 2024 08:24:27 +0200 Subject: [PATCH 105/730] why didn't i think about this sooner --- server/archive.api.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index ee1be4b7a..a38eb269e 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -84,9 +84,7 @@ const archive = { .maxTimeMS(5000) .exec(); - const totalBrews = await HomebrewModel.countDocuments( - titleQuery - ).maxTimeMS(5000); + const totalBrews = brews.length; const totalPages = Math.ceil(totalBrews / pageSize); console.log('Total brews: ', totalBrews); From a89b575b267beccaaaa07cbd53d8962d7f7f2715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 13 May 2024 13:37:53 +0200 Subject: [PATCH 106/730] archive 2.0 --- .../pages/archivePage/archivePage.jsx | 168 ++++++++++-------- server/admin.api.js | 2 - server/archive.api.js | 94 ++++++++-- themes/themes.json | 4 +- 4 files changed, 183 insertions(+), 85 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index eb8e78cc7..71e47f965 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -21,37 +21,37 @@ const ArchivePage = createClass({ getDefaultProps: function () { return {}; }, + getInitialState: function () { return { - //request + //# request title: this.props.query.title || '', - //tags : {}, + //tags: {}, legacy: `${this.props.query.legacy === 'false' ? false : true}`, v3: `${this.props.query.v3 === 'false' ? false : true}`, pageSize: this.props.query.size || 10, page: parseInt(this.props.query.page) || 1, - //response + //# response brewCollection: null, - totalPages: null, totalBrews: null, searching: false, error: null, }; }, + componentDidMount: function () { if (this.state.title !== '') { this.loadPage(this.state.page, false); } + this.state.totalBrews || this.loadTotal(); // Load total if not already loaded }, - updateStateWithBrews: function (brews, page, totalPages, totalBrews) { + updateStateWithBrews: function (brews, page) { this.setState({ brewCollection: brews || null, page: parseInt(page) || 1, - totalPages: totalPages || 1, - totalBrews: totalBrews, searching: false, }); }, @@ -78,6 +78,7 @@ const ArchivePage = createClass({ }, loadPage: async function (page, update) { + console.log('running loadPage'); //load form data directly const title = document.getElementById('title').value || ''; const size = document.getElementById('size').value || 10; @@ -96,46 +97,58 @@ const ArchivePage = createClass({ } if (title !== '') { - console.log('pagesize when querying: ', this.state.pageSize); try { this.setState({ searching: true, error: null }); - await request - .get( - `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` - ) - .then((response) => { - if (response.ok) { - this.updateStateWithBrews( - response.body.brews, - page, - response.body.totalPages, - response.body.totalBrews - ); - } - }); + await request.get( + `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` + ).then((response) => { + if (response.ok) { + this.updateStateWithBrews( + response.body.brews, + page + ); + } + }); } catch (error) { + console.log('error at loadPage: ', error); this.setState({ error: `${error.response.status}` }); - this.updateStateWithBrews([], 1, 1, 0); + this.updateStateWithBrews([], 1); } - console.log('a', - !this.state.brewCollection || this.state.brewCollection.length === 0 - ); if (!this.state.brewCollection) { this.setState({ error: '404' }); } } + }, - + loadTotal: async function () { + console.log('running loadTotal'); + const {title, v3, legacy} = this.state; + + if (title !== '') { + + try { + await request + .get( + `/api/archive/total?title=${title}&v3=${v3}&legacy=${legacy}` + ).then((response) => { + if (response.ok) { + this.setState({totalBrews : response.body.totalBrews}); + } + }); + } catch (error) { + console.log('error at loadTotal: ', error); + this.setState({ error: `${error.response.status}` }); + this.updateStateWithBrews([], 1); + } + } }, renderNavItems: function () { return ( - - Archive: Search for brews - + Archive: Search for brews @@ -161,6 +174,7 @@ const ArchivePage = createClass({ defaultValue={this.state.title} onKeyDown={(e) => { if (e.key === 'Enter') { + this.loadTotal(); this.loadPage(1, true); } }} @@ -211,6 +225,7 @@ const ArchivePage = createClass({ + )} +
      {pages}
    + {page < totalPages && ( + + )} +
    + ); + } else { return;} - return ( -
    - {page > 1 && ( - - )} -
      {pages}
    - {page < totalPages && ( - - )} -
    - ); + }, renderFoundBrews() { console.log('State when rendering:'); - console.table(this.state); + const stateWithoutBrewCollection = { ...this.state }; + delete stateWithoutBrewCollection.brewCollection; + console.table(stateWithoutBrewCollection); + console.table(this.state.brewCollection); + const { title, brewCollection, page, totalPages, error, searching } = this.state; diff --git a/server/admin.api.js b/server/admin.api.js index 626e63d68..5ddba0902 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -100,7 +100,6 @@ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ }); }); - /* Compresses the "text" field of a brew to binary */ router.put('/admin/compress/:id', (req, res)=>{ HomebrewModel.findOne({ _id: req.params.id }) @@ -122,7 +121,6 @@ router.put('/admin/compress/:id', (req, res)=>{ }); }); - router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ try { const totalBrewsCount = await HomebrewModel.countDocuments({}); diff --git a/server/archive.api.js b/server/archive.api.js index a38eb269e..4643e7181 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -3,7 +3,6 @@ const router = require('express').Router(); const asyncHandler = require('express-async-handler'); const archive = { - archiveApi: router, /* Searches for matching title, also attempts to partial match */ findBrews: async (req, res, next) => { try { @@ -17,9 +16,11 @@ const archive = { */ const bright = '\x1b[1m'; // Bright (bold) style - const yellow = '\x1b[93m'; // yellow color + const yellow = '\x1b[93m'; // yellow color const reset = '\x1b[0m'; // Reset to default style - console.log(`Query as received in ${bright + yellow}archive api${reset}:`); + console.log( + `Query as received in ${bright + yellow}archive api${reset}:` + ); console.table(req.query); const title = req.query.title || ''; @@ -84,18 +85,90 @@ const archive = { .maxTimeMS(5000) .exec(); - const totalBrews = brews.length; + return res.json({ brews, page}); - const totalPages = Math.ceil(totalBrews / pageSize); - console.log('Total brews: ', totalBrews); - console.log('Total pages: ', totalPages); - return res.json({ brews, page, totalPages, totalBrews }); } catch (error) { console.error(error); - + if (error.response && error.response.status) { const status = error.response.status; - + + if (status === 500) { + return res.status(500).json({ + errorCode: '500', + message: 'Internal Server Error', + }); + } else if (status === 503) { + return res.status(503).json({ + errorCode: '503', + message: 'Service Unavailable', + }); + } else { + return res.status(status).json({ + errorCode: status.toString(), + message: 'Internal Server Error', + }); + } + } else { + return res.status(500).json({ + errorCode: '500', + message: 'Internal Server Error', + }); + } + } + }, + findTotal: async (req, res) => { + try { + const title = req.query.title || ''; + + const brewsQuery = { + $or: [], + published: true, + }; + if (req.query.legacy === 'true') { + brewsQuery.$or.push({ renderer: 'legacy' }); + } + if (req.query.v3 === 'true') { + brewsQuery.$or.push({ renderer: 'V3' }); + } + // If user wants to use RegEx it needs to format like /text/ + const titleConditionsArray = + title.startsWith('/') && title.endsWith('/') + ? [ + { + 'title': { + $regex: title.slice(1, -1), + $options: 'i', + }, + }, + ] + : buildTitleConditions(title); + + function buildTitleConditions(inputString) { + return [ + { + $text: { + $search: inputString, + $caseSensitive: false, + }, + }, + ]; + } + const titleQuery = { + $and: [brewsQuery, ...titleConditionsArray], + }; + console.table(req.query); + + const totalBrews = await HomebrewModel.countDocuments(titleQuery); + + return res.json({totalBrews}); + + } catch (error) { + console.error(error); + + if (error.response && error.response.status) { + const status = error.response.status; + if (status === 500) { return res.status(500).json({ errorCode: '500', @@ -122,6 +195,7 @@ const archive = { }, }; +router.get('/api/archive/total', asyncHandler(archive.findTotal)); router.get('/api/archive', asyncHandler(archive.findBrews)); module.exports = router; diff --git a/themes/themes.json b/themes/themes.json index 0d28c7394..bc719185d 100644 --- a/themes/themes.json +++ b/themes/themes.json @@ -29,12 +29,12 @@ "baseSnippets": false, "path": "Blank" }, - "Journal": { + "journal": { "name": "Journal", "renderer": "V3", "baseTheme": false, "baseSnippets": "5ePHB", - "path": "Journal" + "path": "journal" } } } \ No newline at end of file From e23166e1d5da8bf95047a4844a9430051479edee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 14 May 2024 09:31:22 +0200 Subject: [PATCH 107/730] when did i change this? --- themes/themes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/themes.json b/themes/themes.json index bc719185d..cb0c5593e 100644 --- a/themes/themes.json +++ b/themes/themes.json @@ -34,7 +34,7 @@ "renderer": "V3", "baseTheme": false, "baseSnippets": "5ePHB", - "path": "journal" + "path": "Journal" } } } \ No newline at end of file From 153812c6e57d599f8c174050231fc104f11dc6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 14 May 2024 09:36:59 +0200 Subject: [PATCH 108/730] simplify console log and remove unused code --- server/archive.api.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index 4643e7181..36aa93429 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -6,21 +6,7 @@ const archive = { /* Searches for matching title, also attempts to partial match */ findBrews: async (req, res, next) => { try { - /* - //log db name and collection name, for local purposes - const dbName = HomebrewModel.db.name; - console.log("Database Name:", dbName); - const collectionName = HomebrewModel.collection.name; - console.log("Collection Name:", collectionName); - - */ - - const bright = '\x1b[1m'; // Bright (bold) style - const yellow = '\x1b[93m'; // yellow color - const reset = '\x1b[0m'; // Reset to default style - console.log( - `Query as received in ${bright + yellow}archive api${reset}:` - ); + console.log(`Query as received in archive api:`); console.table(req.query); const title = req.query.title || ''; From 4b10686336e4b2f2963c8cb1b306f201b689c047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 14 May 2024 09:49:14 +0200 Subject: [PATCH 109/730] simplify logic --- server/archive.api.js | 202 ++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 128 deletions(-) diff --git a/server/archive.api.js b/server/archive.api.js index 36aa93429..e9e118152 100644 --- a/server/archive.api.js +++ b/server/archive.api.js @@ -2,8 +2,72 @@ const HomebrewModel = require('./homebrew.model.js').model; const router = require('express').Router(); const asyncHandler = require('express-async-handler'); +const buildTitleConditionsArray = (title) => { + if (title.startsWith('/') && title.endsWith('/')) { + return [ + { + title: { + $regex: title.slice(1, -1), + $options: 'i', + }, + }, + ]; + } else { + return buildTitleConditions(title); + } +}; + +const buildTitleConditions = (inputString) => { + return [ + { + $text: { + $search: inputString, + $caseSensitive: false, + }, + }, + ]; +}; + +const handleErrorResponse = (res, error, functionName) => { + let status; + let message; + + if (error.response && error.response.status) { + status = error.response.status; + } else { + status = 500; + } + + if (status === 503) { + message = 'Service Unavailable'; + } else { + message = 'Internal Server Error'; + } + + return res.status(status).json({ + errorCode: status.toString(), + message: `Error in function ${functionName}: ${message}`, + }); +}; + +const buildBrewsQuery = (legacy, v3) => { + const brewsQuery = { + $or: [], + published: true, + }; + + if (legacy === 'true') { + brewsQuery.$or.push({ renderer: 'legacy' }); + } + + if (v3 === 'true') { + brewsQuery.$or.push({ renderer: 'V3' }); + } + + return brewsQuery; +}; + const archive = { - /* Searches for matching title, also attempts to partial match */ findBrews: async (req, res, next) => { try { console.log(`Query as received in archive api:`); @@ -12,48 +76,11 @@ const archive = { const title = req.query.title || ''; const page = Math.max(parseInt(req.query.page) || 1, 1); const minPageSize = 6; - const pageSize = Math.max( - parseInt(req.query.size) || 10, - minPageSize - ); + const pageSize = Math.max(parseInt(req.query.size) || 10, minPageSize); const skip = (page - 1) * pageSize; - const brewsQuery = { - $or: [], - published: true, - }; - - if (req.query.legacy === 'true') { - brewsQuery.$or.push({ renderer: 'legacy' }); - } - - if (req.query.v3 === 'true') { - brewsQuery.$or.push({ renderer: 'V3' }); - } - - // If user wants to use RegEx it needs to format like /text/ - const titleConditionsArray = - title.startsWith('/') && title.endsWith('/') - ? [ - { - 'title': { - $regex: title.slice(1, -1), - $options: 'i', - }, - }, - ] - : buildTitleConditions(title); - - function buildTitleConditions(inputString) { - return [ - { - $text: { - $search: inputString, - $caseSensitive: false, - }, - }, - ]; - } + const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3); + const titleConditionsArray = buildTitleConditionsArray(title); const titleQuery = { $and: [brewsQuery, ...titleConditionsArray], @@ -71,112 +98,31 @@ const archive = { .maxTimeMS(5000) .exec(); - return res.json({ brews, page}); + return res.json({ brews, page }); } catch (error) { console.error(error); - - if (error.response && error.response.status) { - const status = error.response.status; - - if (status === 500) { - return res.status(500).json({ - errorCode: '500', - message: 'Internal Server Error', - }); - } else if (status === 503) { - return res.status(503).json({ - errorCode: '503', - message: 'Service Unavailable', - }); - } else { - return res.status(status).json({ - errorCode: status.toString(), - message: 'Internal Server Error', - }); - } - } else { - return res.status(500).json({ - errorCode: '500', - message: 'Internal Server Error', - }); - } + return handleErrorResponse(res, error, 'findBrews'); } }, findTotal: async (req, res) => { try { const title = req.query.title || ''; - const brewsQuery = { - $or: [], - published: true, - }; - if (req.query.legacy === 'true') { - brewsQuery.$or.push({ renderer: 'legacy' }); - } - if (req.query.v3 === 'true') { - brewsQuery.$or.push({ renderer: 'V3' }); - } - // If user wants to use RegEx it needs to format like /text/ - const titleConditionsArray = - title.startsWith('/') && title.endsWith('/') - ? [ - { - 'title': { - $regex: title.slice(1, -1), - $options: 'i', - }, - }, - ] - : buildTitleConditions(title); + const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3); + const titleConditionsArray = buildTitleConditionsArray(title); - function buildTitleConditions(inputString) { - return [ - { - $text: { - $search: inputString, - $caseSensitive: false, - }, - }, - ]; - } const titleQuery = { $and: [brewsQuery, ...titleConditionsArray], }; - console.table(req.query); const totalBrews = await HomebrewModel.countDocuments(titleQuery); - return res.json({totalBrews}); + return res.json({ totalBrews }); } catch (error) { console.error(error); - - if (error.response && error.response.status) { - const status = error.response.status; - - if (status === 500) { - return res.status(500).json({ - errorCode: '500', - message: 'Internal Server Error', - }); - } else if (status === 503) { - return res.status(503).json({ - errorCode: '503', - message: 'Service Unavailable', - }); - } else { - return res.status(status).json({ - errorCode: status.toString(), - message: 'Internal Server Error', - }); - } - } else { - return res.status(500).json({ - errorCode: '500', - message: 'Internal Server Error', - }); - } + return handleErrorResponse(res, error, 'findTotal'); } }, }; From 021ac6840064fe9f0a2db31d5c416c3264808f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 14 May 2024 10:44:16 +0200 Subject: [PATCH 110/730] Update archive page to use pagination with page numbers and ellipses * Change the way pagination is handled on the archive page * Display page links for 10 pages max --- .../pages/archivePage/archivePage.jsx | 112 ++++++++++-------- .../pages/archivePage/archivePage.less | 7 ++ 2 files changed, 70 insertions(+), 49 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 71e47f965..5b444ff58 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -100,16 +100,18 @@ const ArchivePage = createClass({ try { this.setState({ searching: true, error: null }); - await request.get( - `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` - ).then((response) => { - if (response.ok) { - this.updateStateWithBrews( - response.body.brews, - page - ); - } - }); + await request + .get( + `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` + ) + .then((response) => { + if (response.ok) { + this.updateStateWithBrews( + response.body.brews, + page + ); + } + }); } catch (error) { console.log('error at loadPage: ', error); this.setState({ error: `${error.response.status}` }); @@ -123,19 +125,21 @@ const ArchivePage = createClass({ loadTotal: async function () { console.log('running loadTotal'); - const {title, v3, legacy} = this.state; + const { title, v3, legacy } = this.state; if (title !== '') { - try { await request - .get( - `/api/archive/total?title=${title}&v3=${v3}&legacy=${legacy}` - ).then((response) => { - if (response.ok) { - this.setState({totalBrews : response.body.totalBrews}); - } - }); + .get( + `/api/archive/total?title=${title}&v3=${v3}&legacy=${legacy}` + ) + .then((response) => { + if (response.ok) { + this.setState({ + totalBrews: response.body.totalBrews, + }); + } + }); } catch (error) { console.log('error at loadTotal: ', error); this.setState({ error: `${error.response.status}` }); @@ -148,7 +152,9 @@ const ArchivePage = createClass({ return ( - Archive: Search for brews + + Archive: Search for brews + @@ -246,28 +252,36 @@ const ArchivePage = createClass({ if (this.state.totalBrews) { const title = encodeURIComponent(this.state.title); const size = parseInt(this.state.pageSize); - const { page, totalBrews} = this.state; + const { page, totalBrews } = this.state; const totalPages = Math.ceil(totalBrews / size); - - const pages = new Array(totalPages).fill().map((_, index) => ( - - {index + 1} - - )); - - if (totalPages === null) { - return; + + let startPage, endPage; + if (page <= 6) { + startPage = 1; + endPage = Math.min(totalPages, 10); + } else if (page + 4 >= totalPages) { + startPage = Math.max(1, totalPages - 9); + endPage = totalPages; + } else { + startPage = page - 5; + endPage = page + 4; } - + + const pagesAroundCurrent = new Array(endPage - startPage + 1) + .fill() + .map((_, index) => ( + this.loadPage(startPage + index, false)} + > + {startPage + index} + + )); + return (
    {page > 1 && ( @@ -278,7 +292,13 @@ const ArchivePage = createClass({ << )} -
      {pages}
    +
      + {startPage > 1 && 1 ...} + {pagesAroundCurrent} + {endPage < totalPages && ( + ... {totalPages} + )} +
    {page < totalPages && ( )}
      - {startPage > 1 && 1 ...} + {startPage > 1 && this.loadPage(1, false)}>1 ...} {pagesAroundCurrent} {endPage < totalPages && ( - ... {totalPages} + this.loadPage(totalPages, false)}>... {totalPages} )}
    {page < totalPages && ( From 97ef56f9056d2d2e8626957da2b21bfc6f7e8944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 14 May 2024 11:10:48 +0200 Subject: [PATCH 112/730] small changes, tips and style --- client/homebrew/pages/archivePage/archivePage.jsx | 3 ++- .../homebrew/pages/archivePage/archivePage.less | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 5708b774b..dac0e9a33 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -187,7 +187,7 @@ const ArchivePage = createClass({ placeholder="v3 Reference Document" /> - + Tip! you can use RegEx if you format your query as /title/
    + Remember, you can only search brews with this tool if they are published
    ); }, diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 8fcd74610..6f4fc8684 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -4,6 +4,20 @@ body { .content { height: 100%; } + + small { + font-size:10pt; + color:#555; + a { + color:#333; + } + } + + code { + background:lightgrey; + border-radius:5px; + padding-inline:5px + } } .archivePage { @@ -250,6 +264,7 @@ body { 33%, 65% { content:'..'; } + 66%,100% { content:'...'; } From 243038474e3aad1e0f780ab726dcd4cdc46e4294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 17 May 2024 21:23:31 +0200 Subject: [PATCH 113/730] Initial commit --- server/app.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/server/app.js b/server/app.js index e04df77a6..45de67f65 100644 --- a/server/app.js +++ b/server/app.js @@ -195,6 +195,26 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ res.status(200).send(brew.text); }); + +app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res) => { + const { brew } = req; + sanitizeBrew(brew, 'share'); + + const fields = [ 'title', 'pageCount', 'description', 'authors', 'lang', + 'published', 'views', 'shareId', 'createdAt', 'updatedAt', + 'lastViewed', 'thumbnail', 'tags' + ]; + + const metadata = fields.reduce((acc, field) => { + if (brew[field] !== undefined) acc[field] = brew[field]; + return acc; + }, {}); + console.log(metadata); + res.status(200).json(metadata); +}); + + + //User Page app.get('/user/:username', async (req, res, next)=>{ const ownAccount = req.account && (req.account.username == req.params.username); From 8ece54701d67c7d1f6cca1eab046c536e0f6be6e Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 18 May 2024 01:44:42 -0500 Subject: [PATCH 114/730] Add live scrolling to keep the preview in sync with editor position. This catchs CTRL-HOME, CTRL-END, and mouseclicks. It tests for changes on arrow keys and enter. Not sure if it's the best way to do this, but it works quickly on a large, crappy brew. --- client/homebrew/editor/editor.jsx | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 119658f8c..df674c74e 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -22,6 +22,18 @@ const DEFAULT_STYLE_TEXT = dedent` color: black; }`; +let lastPage = 0; +let liveScroll = true; + +const isElementCodeMirror=(element)=>{ + let el = element; + while( el.tagName != 'body' ) { + if( el.classList.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) + return true; + el = el.parentNode; + } + return false; +}; const Editor = createClass({ displayName : 'Editor', @@ -57,6 +69,15 @@ const Editor = createClass({ this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.addEventListener('keydown', this.handleControlKeys); + document.addEventListener('click', (e)=>{ + if(isElementCodeMirror(e.target) && liveScroll ) { + const curPage = this.getCurrentPage(); + if( curPage != lastPage ) { + this.brewJump(); + lastPage = curPage; + } + } + }); const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY); if(editorTheme) { @@ -81,10 +102,36 @@ const Editor = createClass({ }, handleControlKeys : function(e){ + if(liveScroll) { + const movementKeys = [ 13, 33, 34, 37, 38, 39, 40 ]; + if (movementKeys.includes(e.keyCode)) { + const curPage = this.getCurrentPage(); + if( curPage != lastPage ) { + this.brewJump(); + lastPage = curPage; + } + } + } if(!(e.ctrlKey || e.metaKey)) return; const J_KEY = 74; + const END_KEY = 35; + const HOME_KEY = 36; + + // Handle CTRL-HOME and CTRL-END + if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); + + // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == J_KEY)) this.brewJump(); - if (e.shiftKey && (e.keyCode == J_KEY)) this.sourceJump(); + // Source Jump on Shift-CTRL-J + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); + // Toggle Live-scrolling on Shift-CTRL-ALT-J + if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { + console.log('Trying to flip the property?') + console.log(liveScroll); + liveScroll = !liveScroll; + console.log(liveScroll); + } + if( e.keyCode == J_KEY) { e.stopPropagation(); e.preventDefault(); From a711f8eb89e11e628719c7fcd67c9ee33125b429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 18 May 2024 23:07:43 +0200 Subject: [PATCH 115/730] remove regex search --- .../pages/archivePage/archivePage.jsx | 2 +- server/archive.api.js | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index dac0e9a33..f4e79da35 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -187,7 +187,7 @@ const ArchivePage = createClass({ placeholder="v3 Reference Document" /> - Tip! you can use RegEx if you format your query as /title/ + Tip! you can use - to negate words, and "word" to specify an exact string.
    -

    Your results, my lordship

    +

    Your searched returned these results

    {this.renderFoundBrews()}
    diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/archivePage/archivePage.less index 6f4fc8684..31dba3cd6 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/archivePage/archivePage.less @@ -117,7 +117,7 @@ body { background-color: #2C3E50; width: 100%; max-height: 100%; - height: 66.7vh; + height: 66.8vh; padding: 50px; overflow-y:scroll; From b7dc47fe9e9f457f3426f89f26282d0676c072e4 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 18 May 2024 22:17:29 -0500 Subject: [PATCH 118/730] Add a Live Scroll lock/unlock below Brew/Source Jump buttons. The button displays the *next* state of the toggle. IE, if the current state is locked ( Live scrolling is active ) the icon is unlock with a corresponding mouse-over. It may be desirable to invert this. --- client/homebrew/editor/editor.jsx | 10 ++++++---- shared/naturalcrit/splitPane/splitPane.jsx | 16 ++++++++++++++++ shared/naturalcrit/splitPane/splitPane.less | 8 ++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index df674c74e..b08ee9a2b 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -28,7 +28,8 @@ let liveScroll = true; const isElementCodeMirror=(element)=>{ let el = element; while( el.tagName != 'body' ) { - if( el.classList.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) + if ( !el?.classList ) return false + if( el?.classList?.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) return true; el = el.parentNode; } @@ -43,6 +44,7 @@ const Editor = createClass({ text : '', style : '' }, + liveScroll : true, onTextChange : ()=>{}, onStyleChange : ()=>{}, @@ -99,6 +101,9 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) { this.sourceJump(); }; + if(prevProps.liveScroll !== this.props.liveScroll) { + liveScroll = !liveScroll; + }; }, handleControlKeys : function(e){ @@ -126,10 +131,7 @@ const Editor = createClass({ if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); // Toggle Live-scrolling on Shift-CTRL-ALT-J if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { - console.log('Trying to flip the property?') - console.log(liveScroll); liveScroll = !liveScroll; - console.log(liveScroll); } if( e.keyCode == J_KEY) { diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 2101480dc..0718a97b1 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -20,6 +20,7 @@ const SplitPane = createClass({ isDragging : false, moveSource : false, moveBrew : false, + liveScroll : true, showMoveArrows : true }; }, @@ -117,6 +118,20 @@ const SplitPane = createClass({ onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} >
    +
    { + this.setState({ liveScroll: !this.state.liveScroll }); + if(document.getElementById('scrollToggle').classList.contains('fa-unlock')) { + document.getElementById('scrollToggle').className = 'fas fa-lock'; + document.getElementById('scrollToggleDiv').className = 'arrow lock'; + } else { + document.getElementById('scrollToggle').className = 'fas fa-unlock'; + document.getElementById('scrollToggleDiv').className = 'arrow unlock'; + } + }} > + +
    ; } }, @@ -143,6 +158,7 @@ const SplitPane = createClass({ {React.cloneElement(this.props.children[0], { moveBrew : this.state.moveBrew, moveSource : this.state.moveSource, + liveScroll : this.state.liveScroll, setMoveArrows : this.setMoveArrows })} diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index 831b5ce47..2000db72a 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -53,6 +53,14 @@ .tooltipRight('Jump to location in Preview'); top : 60px; } + &.lock{ + .tooltipRight('Lock cursor tracking between windows.'); + top : 90px; + } + &.unlock{ + .tooltipRight('Unlock cursor tracking between windows.'); + top : 90px; + } &:hover{ background-color: #666; } From 86887b536ef18d6432f65dd53f9c50f9fd88d32f Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 19 May 2024 11:16:50 -0500 Subject: [PATCH 119/730] Update Jump keys to match parent PR and shift live scrolling to scroll-lock. Needs non-PC testing. --- client/homebrew/editor/editor.jsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index b08ee9a2b..7879b9941 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -117,24 +117,26 @@ const Editor = createClass({ } } } - if(!(e.ctrlKey || e.metaKey)) return; - const J_KEY = 74; + const M_KEY = 77; const END_KEY = 35; const HOME_KEY = 36; + const SCROLLLOCK_KEY = 145; + + // Toggle Live-scrolling on Scroll Lock + if(e.keyCode == SCROLLLOCK_KEY) { + liveScroll = !liveScroll; + } + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); // Brew Jump on CTRL-J - if((!e.shiftKey) && (e.keyCode == J_KEY)) this.brewJump(); + if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); // Source Jump on Shift-CTRL-J - if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); - // Toggle Live-scrolling on Shift-CTRL-ALT-J - if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { - liveScroll = !liveScroll; - } + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == M_KEY)) this.sourceJump(); - if( e.keyCode == J_KEY) { + if( e.keyCode == M_KEY) { e.stopPropagation(); e.preventDefault(); } From bacdd65025d752531518610691ae80bad48c96c7 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 19 May 2024 11:52:16 -0500 Subject: [PATCH 120/730] Add a CR. --- client/homebrew/editor/editor.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 7879b9941..4d32f36fb 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -126,6 +126,7 @@ const Editor = createClass({ if(e.keyCode == SCROLLLOCK_KEY) { liveScroll = !liveScroll; } + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END From 21244fba58660c03d3e544012ef663703015aef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 19 May 2024 23:45:12 +0200 Subject: [PATCH 121/730] "Removed lodash import, simplified boolean assignments, refactored API request and error handling, and removed unused variables in ArchivePage component." --- .../pages/archivePage/archivePage.jsx | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 57802b4ef..6cf84ef3d 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -2,7 +2,6 @@ require('./archivePage.less'); const React = require('react'); const createClass = require('create-react-class'); -const _ = require('lodash'); const cx = require('classnames'); const Nav = require('naturalcrit/nav/nav.jsx'); @@ -27,8 +26,8 @@ const ArchivePage = createClass({ //# request title: this.props.query.title || '', //tags: {}, - legacy: `${this.props.query.legacy === 'false' ? false : true}`, - v3: `${this.props.query.v3 === 'false' ? false : true}`, + legacy: this.props.query.legacy !== 'false', + v3: this.props.query.v3 !== 'false', pageSize: this.props.query.size || 10, page: parseInt(this.props.query.page) || 1, @@ -100,19 +99,10 @@ const ArchivePage = createClass({ if (title !== '') { try { this.setState({ searching: true, error: null }); - - await request - .get( - `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` - ) - .then((response) => { - if (response.ok) { - this.updateStateWithBrews( - response.body.brews, - page - ); - } - }); + const response = await request.get(`/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}`); + if (response.ok) { + this.updateStateWithBrews(response.body.brews, page); + } } catch (error) { console.log('error at loadPage: ', error); this.setState({ error: `${error.response.status}` }); @@ -252,7 +242,6 @@ const ArchivePage = createClass({ renderPaginationControls() { if (this.state.totalBrews) { - const title = encodeURIComponent(this.state.title); const size = parseInt(this.state.pageSize); const { page, totalBrews } = this.state; @@ -317,7 +306,7 @@ const ArchivePage = createClass({ }, renderFoundBrews() { - const { title, brewCollection, page, totalPages, error, searching } = + const { title, brewCollection, error, searching } = this.state; if (searching) { @@ -344,11 +333,11 @@ const ArchivePage = createClass({ errorMessage = "404 - We didn't find any brew"; break; case '503': - errorMessage = - ' 503 - Service Unavailable, try again later, sorry.'; + errorMessage = "503 - Service Unavailable, try again later, sorry."; break; case '500': errorMessage = "500 - We don't know what happened, go ahead and contact the mods or report as a mistake."; + break; default: errorMessage = 'An unexpected error occurred'; } From 835ca0de3264248405ec87dea5227fd84ef6ab5b Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 20 May 2024 16:21:02 -0500 Subject: [PATCH 122/730] WIP --- client/homebrew/editor/editor.jsx | 7 ++++++- shared/naturalcrit/splitPane/splitPane.jsx | 15 ++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 4d32f36fb..185f37ac6 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -94,6 +94,11 @@ const Editor = createClass({ }, componentDidUpdate : function(prevProps, prevState, snapshot) { + console.log(this.props); + console.log(prevProps); + console.log(this.state); + console.log(prevState); + this.highlightCustomMarkdown(); if(prevProps.moveBrew !== this.props.moveBrew) { this.brewJump(); @@ -126,7 +131,7 @@ const Editor = createClass({ if(e.keyCode == SCROLLLOCK_KEY) { liveScroll = !liveScroll; } - + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 0718a97b1..217fcc80c 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -15,13 +15,14 @@ const SplitPane = createClass({ getInitialState : function() { return { - currentDividerPos : null, - windowWidth : 0, - isDragging : false, - moveSource : false, - moveBrew : false, - liveScroll : true, - showMoveArrows : true + currentDividerPos : null, + windowWidth : 0, + isDragging : false, + moveSource : false, + moveBrew : false, + liveScroll : true, + viewablePageNumber : 0, + showMoveArrows : true }; }, From e69132b40aba81a1edd6f8bd7c9d3279ca67e108 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 20 May 2024 20:31:30 -0500 Subject: [PATCH 123/730] Constant a lookup. --- shared/naturalcrit/splitPane/splitPane.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 217fcc80c..e1b30887e 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -43,7 +43,7 @@ const SplitPane = createClass({ window.addEventListener('resize', this.handleWindowResize); }, - componentWillUnmount : function() { +componentWillUnmount : function() { window.removeEventListener('resize', this.handleWindowResize); }, @@ -123,12 +123,14 @@ const SplitPane = createClass({ style={{ left: this.state.currentDividerPos-4 }} onClick={()=>{ this.setState({ liveScroll: !this.state.liveScroll }); - if(document.getElementById('scrollToggle').classList.contains('fa-unlock')) { - document.getElementById('scrollToggle').className = 'fas fa-lock'; - document.getElementById('scrollToggleDiv').className = 'arrow lock'; + const toggle = document.getElementById('scrollToggle'); + const toggleDiv = document.getElementById('scrollToggleDiv'); + if(toggle.classList.contains('fa-unlock')) { + toggle.className = 'fas fa-lock'; + toggleDiv.className = 'arrow lock'; } else { - document.getElementById('scrollToggle').className = 'fas fa-unlock'; - document.getElementById('scrollToggleDiv').className = 'arrow unlock'; + toggle.className = 'fas fa-unlock'; + toggleDiv.className = 'arrow unlock'; } }} > From bc9ab284d8e4fb031adbad39c734221318ce2249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 08:01:50 +0200 Subject: [PATCH 124/730] Initial UI --- client/homebrew/brewRenderer/brewRenderer.jsx | 2 + .../homebrew/brewRenderer/toolBar/toolBar.jsx | 85 +++++++++++++++++++ .../brewRenderer/toolBar/toolBar.less | 68 +++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 client/homebrew/brewRenderer/toolBar/toolBar.jsx create mode 100644 client/homebrew/brewRenderer/toolBar/toolBar.less diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 38d7454a4..34d239040 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -7,6 +7,7 @@ const _ = require('lodash'); const MarkdownLegacy = require('naturalcrit/markdownLegacy.js'); const Markdown = require('naturalcrit/markdown.js'); const ErrorBar = require('./errorBar/errorBar.jsx'); +const ToolBar = require('./toolBar/toolBar.jsx'); //TODO: move to the brew renderer const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx'); @@ -198,6 +199,7 @@ const BrewRenderer = (props)=>{ contentDidMount={frameDidMount} onClick={()=>{emitClick();}} > +
    diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx new file mode 100644 index 000000000..11eb6ecb9 --- /dev/null +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -0,0 +1,85 @@ +require('./toolBar.less'); +const React = require('react'); +const { useState, useRef, useEffect } = React; +const _ = require('lodash'); + +const ToolBar = () => { + const [state, setState] = useState({ + currentPage: 1, + totalPages: 10, + zoomLevel: 100, + }); + + const setZoomLevel = (direction) => { + let zoomLevel = state.zoomLevel; + if (direction === 'in') { + zoomLevel += 10; + } else { + zoomLevel = zoomLevel - 10; + } + + setState((prevState) => ({ + ...prevState, + zoomLevel, + })); + }; + + const scrollToPage = (direction) => { + let currentPage = state.currentPage; + if (direction === 'next') { + currentPage += 1; + } else { + currentPage = currentPage - 1; + } + setState((prevState) => ({ + ...prevState, + currentPage, + })); + }; + + return ( +
    +
    + +
    + + {state.zoomLevel}% +
    + +
    + +
    + +
    + + {state.currentPage} +
    + +
    +
    + ); +}; + +module.exports = ToolBar; diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.less b/client/homebrew/brewRenderer/toolBar/toolBar.less new file mode 100644 index 000000000..1d3ae5205 --- /dev/null +++ b/client/homebrew/brewRenderer/toolBar/toolBar.less @@ -0,0 +1,68 @@ +.toolBar { + font-family: 'Open Sans', sans-serif; + position: sticky; + top: 0; + left: 0; + width: 100%; + height: 30px; + background-color: #555; + border-top: 1px solid #666; + border-bottom: 1px solid #666; + color: white; + text-align: center; + z-index: 1; + display: flex; + justify-content: center; + align-items: baseline; + column-gap: 15px; + row-gap: 5px; + flex-wrap: wrap; + + span { + background: #eee; + font-family: 'Open Sans', sans-serif; + text-transform: uppercase; + font-weight: normal; + font-size: 16px; + color: #000; + padding: 2px 5px; + border-radius: 7px; + width: 50px; + } + + .tool { + display: flex; + align-items: center; + padding: 0 8px; + color: #ccc; + height: 100%; + + &:hover { + background-color: #444; + } + + button { + background-color: transparent; + font-family: 'Open Sans', sans-serif; + text-transform: uppercase; + font-weight: normal; + font-size: 11px; + color: #ccc; + padding: 0; + width: 70px; + + &:focus-within { + color: white; + font-weight: 800; + height: 100%; + } + + &:disabled { + color: #777; + background-color: transparent !important; + } + } + } + + +} \ No newline at end of file From f9d19c75b29aa5494fa652b01ddce55799161eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 11:57:48 +0200 Subject: [PATCH 125/730] change renderPagination order of operations and fix pagination not loading properly --- .../pages/archivePage/archivePage.jsx | 159 ++++++++++-------- 1 file changed, 91 insertions(+), 68 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 6cf84ef3d..e23af7b26 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -99,7 +99,9 @@ const ArchivePage = createClass({ if (title !== '') { try { this.setState({ searching: true, error: null }); - const response = await request.get(`/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}`); + const response = await request.get( + `/api/archive?title=${title}&page=${page}&size=${size}&v3=${v3}&legacy=${legacy}` + ); if (response.ok) { this.updateStateWithBrews(response.body.brews, page); } @@ -119,6 +121,9 @@ const ArchivePage = createClass({ const { title, v3, legacy } = this.state; if (title !== '') { + this.setState({ + totalBrews: null, + }); try { await request .get( @@ -178,7 +183,10 @@ const ArchivePage = createClass({ placeholder="v3 Reference Document" /> - Tip! you can use - to negate words, and "word" to specify an exact string. + + Tip! you can use - to negate words, and{' '} + "word" to specify an exact string. +
    - Remember, you can only search brews with this tool if they are published + + Remember, you can only search brews with this tool if they + are published +
    ); }, - renderPaginationControls() { - if (this.state.totalBrews) { - const size = parseInt(this.state.pageSize); - const { page, totalBrews } = this.state; - - const totalPages = Math.ceil(totalBrews / size); - - let startPage, endPage; - if (page <= 6) { - startPage = 1; - endPage = Math.min(totalPages, 10); - } else if (page + 4 >= totalPages) { - startPage = Math.max(1, totalPages - 9); - endPage = totalPages; - } else { - startPage = page - 5; - endPage = page + 4; - } - - const pagesAroundCurrent = new Array(endPage - startPage + 1) - .fill() - .map((_, index) => ( - this.loadPage(startPage + index, false)} - > - {startPage + index} - - )); - - return ( -
    - {page > 1 && ( - - )} -
      - {startPage > 1 && this.loadPage(1, false)}>1 ...} - {pagesAroundCurrent} - {endPage < totalPages && ( - this.loadPage(totalPages, false)}>... {totalPages} - )} -
    - {page < totalPages && ( - - )} -
    - ); - } else { + renderPaginationControls: function () { + if (!this.state.totalBrews) { return null; } + + const size = parseInt(this.state.pageSize); + const { page, totalBrews } = this.state; + const totalPages = Math.ceil(totalBrews / size); + + let startPage, endPage; + if (page <= 6) { + startPage = 1; + endPage = Math.min(totalPages, 10); + } else if (page + 4 >= totalPages) { + startPage = Math.max(1, totalPages - 9); + endPage = totalPages; + } else { + startPage = page - 5; + endPage = page + 4; + } + + const pagesAroundCurrent = new Array(endPage - startPage + 1) + .fill() + .map((_, index) => ( + this.loadPage(startPage + index, false)} + > + {startPage + index} + + )); + + return ( +
    + {page > 1 && ( + + )} +
      + {startPage > 1 && ( + this.loadPage(1, false)} + > + 1 ... + + )} + {pagesAroundCurrent} + {endPage < totalPages && ( + this.loadPage(totalPages, false)} + > + ... {totalPages} + + )} +
    + {page < totalPages && ( + + )} +
    + ); }, renderFoundBrews() { - const { title, brewCollection, error, searching } = - this.state; + const { title, brewCollection, error, searching } = this.state; if (searching) { return ( @@ -333,10 +354,12 @@ const ArchivePage = createClass({ errorMessage = "404 - We didn't find any brew"; break; case '503': - errorMessage = "503 - Service Unavailable, try again later, sorry."; + errorMessage = + '503 - Service Unavailable, try again later, sorry.'; break; case '500': - errorMessage = "500 - We don't know what happened, go ahead and contact the mods or report as a mistake."; + errorMessage = + "500 - We don't know what happened, go ahead and contact the mods or report as a mistake."; break; default: errorMessage = 'An unexpected error occurred'; From e9b85e1a9aeaeb94fb3dd2e681aa0027ea315943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 12:06:08 +0200 Subject: [PATCH 126/730] damn totalBrews won't go away --- client/homebrew/pages/archivePage/archivePage.jsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index e23af7b26..17dba86fb 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -91,7 +91,6 @@ const ArchivePage = createClass({ pageSize: size, v3: v3, legacy: legacy, - totalBrews: null, }); this.updateUrl(title, page, size, v3, legacy); } @@ -119,11 +118,11 @@ const ArchivePage = createClass({ loadTotal: async function () { console.log('running loadTotal'); const { title, v3, legacy } = this.state; + this.setState({ + totalBrews: null, + }); if (title !== '') { - this.setState({ - totalBrews: null, - }); try { await request .get( From efda06ebe5cac0dcefd173d0016ac31c4d06ca9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 12:09:41 +0200 Subject: [PATCH 127/730] console log to find the issue --- client/homebrew/pages/archivePage/archivePage.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 17dba86fb..9e428f355 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -118,6 +118,7 @@ const ArchivePage = createClass({ loadTotal: async function () { console.log('running loadTotal'); const { title, v3, legacy } = this.state; + this.setState({ totalBrews: null, }); @@ -141,6 +142,7 @@ const ArchivePage = createClass({ this.updateStateWithBrews([], 1); } } + console.log('total brews in state in loadtotal: ', this.state.totalBrews); }, renderNavItems: function () { From 68c3e1ba84ba4fbc47bec9ba2983014026ca49f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 12:16:07 +0200 Subject: [PATCH 128/730] log at will --- client/homebrew/pages/archivePage/archivePage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index 9e428f355..ee4ea3925 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -248,6 +248,7 @@ const ArchivePage = createClass({ Remember, you can only search brews with this tool if they are published + ); }, From ecfdada810c43cc08ef5bba45ef42034afbddf1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 12:24:47 +0200 Subject: [PATCH 129/730] fix damn error finally --- client/homebrew/pages/archivePage/archivePage.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index ee4ea3925..f271c2f95 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -117,7 +117,9 @@ const ArchivePage = createClass({ loadTotal: async function () { console.log('running loadTotal'); - const { title, v3, legacy } = this.state; + const title = document.getElementById('title').value || ''; + const v3 = document.getElementById('v3').checked; + const legacy = document.getElementById('legacy').checked; this.setState({ totalBrews: null, @@ -142,7 +144,6 @@ const ArchivePage = createClass({ this.updateStateWithBrews([], 1); } } - console.log('total brews in state in loadtotal: ', this.state.totalBrews); }, renderNavItems: function () { @@ -248,7 +249,6 @@ const ArchivePage = createClass({ Remember, you can only search brews with this tool if they are published - ); }, From 8fd165a79b5f1d6cd4b6042e7b7bfc9f6e7c3f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 21 May 2024 23:43:56 +0200 Subject: [PATCH 130/730] form changes --- .../pages/archivePage/archivePage.jsx | 35 +++++++++++++------ .../pages/archivePage/archivePage.less | 2 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index f271c2f95..4f6aab683 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -120,7 +120,7 @@ const ArchivePage = createClass({ const title = document.getElementById('title').value || ''; const v3 = document.getElementById('v3').checked; const legacy = document.getElementById('legacy').checked; - + this.setState({ totalBrews: null, }); @@ -164,6 +164,16 @@ const ArchivePage = createClass({ ); }, + validateInput: function (e) { + const textInput = e.target + const submitButton = document.getElementById('searchButton'); + if (textInput.value.length > 3) { + submitButton.disabled = false; + } else { + submitButton.disabled = true; + } + }, + renderForm: function () { return (
    @@ -176,6 +186,9 @@ const ArchivePage = createClass({ type="text" name="title" defaultValue={this.state.title} + onKeyUp={(e) => { + this.validateInput(e); + }} onKeyDown={(e) => { if (e.key === 'Enter') { this.loadTotal(); @@ -191,15 +204,14 @@ const ArchivePage = createClass({
    - {state.zoomLevel}% +
    + handleInputChange(e.target.value, 'zoom')} + onBlur={(e) => { + const newZoomLevel = parseInt( + e.target.value.replace('%', ''), + 10 + ); + if (newZoomLevel !== state.zoomLevel) { + updateZoom(newZoomLevel); + } + }} + /> + % +
    +
    - {state.currentPage} + handleInputChange(e.target.value, 'page')} + onBlur={(e) => { + parseInt(pageNumberInput) === state.currentPage + 1 || + onPageChange(parseInt(pageNumberInput) - 1); + }} + /> +
    diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.less b/client/homebrew/brewRenderer/toolBar/toolBar.less index 1d3ae5205..db20a51a6 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.less +++ b/client/homebrew/brewRenderer/toolBar/toolBar.less @@ -13,12 +13,12 @@ z-index: 1; display: flex; justify-content: center; - align-items: baseline; + align-items: center; column-gap: 15px; row-gap: 5px; flex-wrap: wrap; - span { + input { background: #eee; font-family: 'Open Sans', sans-serif; text-transform: uppercase; @@ -27,7 +27,7 @@ color: #000; padding: 2px 5px; border-radius: 7px; - width: 50px; + height:1.5em; } .tool { From f23c0bccbc2468dce9f2e08419e1edec7f9fdc58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 19:46:40 +0200 Subject: [PATCH 157/730] "Added onKeyPress event handler to zoom input and page number input to blur the target on Enter key press." --- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index f9879428c..d6b39ffce 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -90,6 +90,11 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { updateZoom(newZoomLevel); } }} + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.target.blur(); + } + }} /> %
    @@ -128,6 +133,11 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { parseInt(pageNumberInput) === state.currentPage + 1 || onPageChange(parseInt(pageNumberInput) - 1); }} + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.target.blur(); + } + }} />
    From 000c3db8cde075d1a211e43c61fe609232d05325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 20:14:41 +0200 Subject: [PATCH 158/730] fixed page error --- client/homebrew/brewRenderer/brewRenderer.jsx | 18 ++++++++++++++++-- .../homebrew/brewRenderer/toolBar/toolBar.jsx | 13 ++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 9cbe824fa..c15e081f1 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -67,6 +67,7 @@ const BrewRenderer = (props)=>{ isMounted : false, visibility : 'hidden', zoom : 100, + currentPageNumber : 1, }); const mainRef = useRef(null); @@ -88,7 +89,8 @@ const BrewRenderer = (props)=>{ iframe.contentWindow.document.querySelector('.brewRenderer'); if (brewRenderer) { const pages = brewRenderer.querySelectorAll('.page'); - if (pageNumber + 1 > pages.length) { + console.log(pageNumber); + if (pageNumber + 1 > pages.length || pageNumber < 0) { console.log(pageNumber, pages.length); console.log('page not found'); } else { @@ -111,6 +113,18 @@ const BrewRenderer = (props)=>{ ...prevState, viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * rawPages.length) })); + + getCurrentPage(e); + }; + + const getCurrentPage = (e) => { + const target = e.target; + const currentPageNumber = Math.ceil(target.scrollTop / target.scrollHeight * rawPages.length); + + setState((prevState) => ({ + ...prevState, + currentPageNumber: currentPageNumber || 1 + })); }; const isInView = (index)=>{ @@ -257,7 +271,7 @@ const BrewRenderer = (props)=>{ contentDidMount={frameDidMount} onClick={()=>{emitClick();}} > - +
    { }); const [pageNumberInput, setPageNumberInput] = useState( - state.currentPage + 1 + state.currentPage ); const [zoomInput, setZoomInput] = useState(state.zoomLevel); @@ -22,12 +22,11 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { // Update currentPage whenever page prop changes useEffect(() => { - console.log(`page number from props ${currentPage}`); setState((prevState) => ({ ...prevState, currentPage: currentPage, })); - setPageNumberInput(currentPage + 1); + setPageNumberInput(currentPage); }, [currentPage]); const setZoomLevel = (direction) => { @@ -113,9 +112,9 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { className="previousPage" onClick={() => { console.log(`page is ${state.currentPage}`); - onPageChange(state.currentPage - 1); + onPageChange(state.currentPage - 2); }} - disabled={state.currentPage === 0} + disabled={state.currentPage <= 1} > @@ -130,7 +129,7 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { value={pageNumberInput} onChange={(e) => handleInputChange(e.target.value, 'page')} onBlur={(e) => { - parseInt(pageNumberInput) === state.currentPage + 1 || + parseInt(pageNumberInput) === state.currentPage || onPageChange(parseInt(pageNumberInput) - 1); }} onKeyPress={(e) => { @@ -145,7 +144,7 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { className="nextPage" onClick={() => { console.log(`page is ${state.currentPage}`); - onPageChange(state.currentPage + 1); + onPageChange(state.currentPage); }} disabled={state.currentPage + 1 === state.totalPages} > From 75c592b437eefc35775d526b1c14362e7856064f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 20:28:34 +0200 Subject: [PATCH 159/730] "Update onPageChange argument in nextPage button onClick handler" --- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index 95aca9163..e41c109c7 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -144,7 +144,7 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { className="nextPage" onClick={() => { console.log(`page is ${state.currentPage}`); - onPageChange(state.currentPage); + onPageChange(state.currentPage+1); }} disabled={state.currentPage + 1 === state.totalPages} > From afa05713824972c1f6edf6a8b92541920edddaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 20:57:09 +0200 Subject: [PATCH 160/730] fix page displacement --- client/homebrew/brewRenderer/brewRenderer.jsx | 8 ++++++-- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index c15e081f1..76494f3eb 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -89,11 +89,12 @@ const BrewRenderer = (props)=>{ iframe.contentWindow.document.querySelector('.brewRenderer'); if (brewRenderer) { const pages = brewRenderer.querySelectorAll('.page'); - console.log(pageNumber); + console.log(`Attempting to scroll to page ${pageNumber} of ${pages.length}`); if (pageNumber + 1 > pages.length || pageNumber < 0) { console.log(pageNumber, pages.length); console.log('page not found'); } else { + console.log(`Scrolling to page: ${pages[pageNumber].id}`); pages[pageNumber].scrollIntoView({ block: 'start' }); } } @@ -119,7 +120,10 @@ const BrewRenderer = (props)=>{ const getCurrentPage = (e) => { const target = e.target; - const currentPageNumber = Math.ceil(target.scrollTop / target.scrollHeight * rawPages.length); + const { scrollTop, clientHeight, scrollHeight } = target; + const totalScrollableHeight = scrollHeight - clientHeight; + + const currentPageNumber = Math.ceil((scrollTop / totalScrollableHeight) * rawPages.length); setState((prevState) => ({ ...prevState, diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index e41c109c7..d6a62316d 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -143,8 +143,8 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { From ed9262801297f6229fa7f29c74a95226dcd4703e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 21:02:03 +0200 Subject: [PATCH 162/730] udpate input zoom --- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index db40c87c7..ba30da4a9 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -18,6 +18,7 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { useEffect(() => { console.log(`Zoom to: ${state.zoomLevel}`); updateZoom(state.zoomLevel); + setZoomInput(state.zoomLevel); }, [state.zoomLevel]); // Update currentPage whenever page prop changes From 0e00460012ef46a7e57a357a8699bacbfca0289a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 21:03:27 +0200 Subject: [PATCH 163/730] change margin bottom to fixed distance --- client/homebrew/brewRenderer/brewRenderer.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 76494f3eb..1632c8f8c 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -245,8 +245,8 @@ const BrewRenderer = (props)=>{ From c60ddb701cac06e75958ec9f35e26611c9c681f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 31 May 2024 21:06:39 +0200 Subject: [PATCH 164/730] this one works best --- client/homebrew/brewRenderer/brewRenderer.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 1632c8f8c..0710442f3 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -246,7 +246,7 @@ const BrewRenderer = (props)=>{ {` .pages { zoom: ${state.zoom}%; - margin-bottom: 2cm; + margin-bottom: 7cm; } `} From de8194d7e0c7cc8f3c5f03c6bc863d58c95cda50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 1 Jun 2024 00:34:45 +0200 Subject: [PATCH 165/730] hide toolbar during printing --- shared/helpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/helpers.js b/shared/helpers.js index 8ca185046..3020890c5 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -23,6 +23,7 @@ const printCurrentBrew = ()=>{ //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0); node.style.display='none'; + node.getElementsByClassName('toolBar').item(0).style.display='none'; node.offsetHeight; // accessing this is enough to trigger a reflow node.style.display=''; } From 1a52acd4a917c0d11c00e6855d8d8ecb34ba41c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 1 Jun 2024 00:37:49 +0200 Subject: [PATCH 166/730] i fixed it wrong --- shared/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/helpers.js b/shared/helpers.js index 3020890c5..2988df71c 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -23,7 +23,7 @@ const printCurrentBrew = ()=>{ //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0); node.style.display='none'; - node.getElementsByClassName('toolBar').item(0).style.display='none'; + window.frames['BrewRenderer'].contentDocument.getElementsByClassName('toolBar').item(0).style.display='none'; node.offsetHeight; // accessing this is enough to trigger a reflow node.style.display=''; } From 95d7ce2876736f2f0ac0748808a83cc341448941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 1 Jun 2024 00:41:44 +0200 Subject: [PATCH 167/730] move toolbar hiding to brewrenderer.less --- client/homebrew/brewRenderer/brewRenderer.less | 3 +++ shared/helpers.js | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index 28ea8005e..ad8da93dd 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -66,6 +66,9 @@ } @media print { + .toolbar { + display: none; + } .brewRenderer { height: 100%; overflow-y: unset; diff --git a/shared/helpers.js b/shared/helpers.js index 2988df71c..b76edd2be 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -22,7 +22,6 @@ const printCurrentBrew = ()=>{ window.frames['BrewRenderer'].contentWindow.print(); //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0); - node.style.display='none'; window.frames['BrewRenderer'].contentDocument.getElementsByClassName('toolBar').item(0).style.display='none'; node.offsetHeight; // accessing this is enough to trigger a reflow node.style.display=''; From 2d051fcdc0380f63625e20f24cd07fbf13eb73b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 1 Jun 2024 00:42:07 +0200 Subject: [PATCH 168/730] misstype --- client/homebrew/brewRenderer/brewRenderer.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index ad8da93dd..bc13aa4af 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -66,7 +66,7 @@ } @media print { - .toolbar { + .toolBar { display: none; } .brewRenderer { From 3fad8227a7b15ca33cee87a1213a3f719c944ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 1 Jun 2024 00:50:16 +0200 Subject: [PATCH 169/730] "Updated brewRenderer.jsx: added id 'zoomStyle' to style tag and changed margin-bottom from 7cm to 5cm." --- client/homebrew/brewRenderer/brewRenderer.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 0710442f3..5f6f7b8fa 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -242,11 +242,11 @@ const BrewRenderer = (props)=>{ const makeZoom = () => { return( - From e3c1e4b6f0d8ffe3117e19427d48205bb6ec81e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 15:50:47 +0200 Subject: [PATCH 170/730] "Updated toolbar.less: changed hover selector to also include focus-within" --- client/homebrew/brewRenderer/toolBar/toolBar.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.less b/client/homebrew/brewRenderer/toolBar/toolBar.less index db20a51a6..8bb5effe5 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.less +++ b/client/homebrew/brewRenderer/toolBar/toolBar.less @@ -37,7 +37,7 @@ color: #ccc; height: 100%; - &:hover { + &:hover,&:focus-within { background-color: #444; } From 202ea1d905401bc1655d115b58ad7a326bcac774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 15:59:09 +0200 Subject: [PATCH 171/730] "Removed margin-bottom from brewRenderer style, added padding-bottom and updated styles in brewRenderer.less" --- client/homebrew/brewRenderer/brewRenderer.jsx | 1 - client/homebrew/brewRenderer/brewRenderer.less | 18 +++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 5f6f7b8fa..fd3dc8346 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -246,7 +246,6 @@ const BrewRenderer = (props)=>{ {` .pages { zoom: ${state.zoom}%; - margin-bottom: 5cm; } `} diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index bc13aa4af..ba6303960 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -1,10 +1,13 @@ @import (multiple, less) 'shared/naturalcrit/styles/reset.less'; .brewRenderer { - will-change : transform; - overflow-y : scroll; + will-change : transform; + overflow-y : scroll; + padding-bottom: 30px; + :where(.pages) { margin : 30px 0px; + & > :where(.page) { width : 215.9mm; height : 279.4mm; @@ -17,27 +20,27 @@ &::-webkit-scrollbar { width: 20px; + &:horizontal{ height: 20px; width:auto; } + &-thumb { background: linear-gradient(90deg, #d3c1af 15px, #00000000 15px); &:horizontal{ background: linear-gradient(0deg, #d3c1af 15px, #00000000 15px); } } + &-corner { visibility: hidden; } } - - - - - } + .pane { position : relative; } + .pageInfo { position : absolute; right : 17px; @@ -53,6 +56,7 @@ &:not(:last-child) { border-right : 1px solid #666666; } } } + .ppr_msg { position : absolute; bottom : 0; From e2a3959feb2df489e2de4d9010a2699b584636fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 16:03:54 +0200 Subject: [PATCH 172/730] "Update brewRenderer.less: changed padding-bottom to padding-block, removed empty lines, and reformatted some styles." --- client/homebrew/brewRenderer/brewRenderer.less | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index ba6303960..83834eddb 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -3,7 +3,7 @@ .brewRenderer { will-change : transform; overflow-y : scroll; - padding-bottom: 30px; + padding-block : 30px; :where(.pages) { margin : 30px 0px; @@ -25,14 +25,14 @@ height: 20px; width:auto; } - + &-thumb { background: linear-gradient(90deg, #d3c1af 15px, #00000000 15px); &:horizontal{ background: linear-gradient(0deg, #d3c1af 15px, #00000000 15px); } } - + &-corner { visibility: hidden; } From 0c9958f4616585a31d5152ab9dd5e306edb4c1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 16:05:57 +0200 Subject: [PATCH 173/730] "Removed '%' symbol handling from zoom input value" --- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index ba30da4a9..e11081eb0 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -45,14 +45,13 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { }; const handleInputChange = (value, type) => { - // Remove the "%" symbol from the input value - const newValue = parseInt(value.replace('%', ''), 10); + const newValue = parseInt(value, 10); // Check the type of input (zoom or page) if (type === 'zoom') { // Check if zoom level is within the allowed range if (newValue >= 10 && newValue <= 300) { - setZoomInput(newValue + '%'); // Add "%" back to the value + setZoomInput(newValue); } } else if (type === 'page') { // Check if page number is within the allowed range @@ -83,7 +82,7 @@ const ToolBar = ({ updateZoom, currentPage, onPageChange, totalPages }) => { onChange={(e) => handleInputChange(e.target.value, 'zoom')} onBlur={(e) => { const newZoomLevel = parseInt( - e.target.value.replace('%', ''), + e.target.value, 10 ); if (newZoomLevel !== state.zoomLevel) { From c2170dd55822502449adf4632580c3562b8ba9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 16:12:46 +0200 Subject: [PATCH 174/730] Remove line hiding toolbar in printCurrentBrew function --- shared/helpers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/helpers.js b/shared/helpers.js index b76edd2be..db1a20dae 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -22,7 +22,6 @@ const printCurrentBrew = ()=>{ window.frames['BrewRenderer'].contentWindow.print(); //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0); - window.frames['BrewRenderer'].contentDocument.getElementsByClassName('toolBar').item(0).style.display='none'; node.offsetHeight; // accessing this is enough to trigger a reflow node.style.display=''; } From a5f453f1e55fef36a6fecbc832db7aa3072697df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 2 Jun 2024 16:13:04 +0200 Subject: [PATCH 175/730] linting toolBar.less --- .../brewRenderer/toolBar/toolBar.less | 116 +++++++++--------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.less b/client/homebrew/brewRenderer/toolBar/toolBar.less index 8bb5effe5..1e2ca1d07 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.less +++ b/client/homebrew/brewRenderer/toolBar/toolBar.less @@ -1,68 +1,64 @@ .toolBar { - font-family: 'Open Sans', sans-serif; - position: sticky; - top: 0; - left: 0; - width: 100%; - height: 30px; - background-color: #555; - border-top: 1px solid #666; - border-bottom: 1px solid #666; - color: white; - text-align: center; - z-index: 1; - display: flex; - justify-content: center; - align-items: center; - column-gap: 15px; - row-gap: 5px; - flex-wrap: wrap; + position : sticky; + top : 0; + left : 0; + z-index : 1; + display : flex; + flex-wrap : wrap; + row-gap : 5px; + column-gap : 15px; + align-items : center; + justify-content : center; + width : 100%; + height : 30px; + font-family : 'Open Sans', sans-serif; + color : white; + text-align : center; + background-color : #555555; + border-top : 1px solid #666666; + border-bottom : 1px solid #666666; - input { - background: #eee; - font-family: 'Open Sans', sans-serif; - text-transform: uppercase; - font-weight: normal; - font-size: 16px; - color: #000; - padding: 2px 5px; - border-radius: 7px; - height:1.5em; - } + input { + height : 1.5em; + padding : 2px 5px; + font-family : 'Open Sans', sans-serif; + font-size : 16px; + font-weight : normal; + color : #000000; + text-transform : uppercase; + background : #EEEEEE; + border-radius : 7px; + } - .tool { - display: flex; - align-items: center; - padding: 0 8px; - color: #ccc; - height: 100%; + .tool { + display : flex; + align-items : center; + height : 100%; + padding : 0 8px; + color : #CCCCCC; - &:hover,&:focus-within { - background-color: #444; - } + &:hover,&:focus-within { background-color : #444444; } - button { - background-color: transparent; - font-family: 'Open Sans', sans-serif; - text-transform: uppercase; - font-weight: normal; - font-size: 11px; - color: #ccc; - padding: 0; - width: 70px; - - &:focus-within { - color: white; - font-weight: 800; - height: 100%; - } - - &:disabled { - color: #777; - background-color: transparent !important; - } - } - } + button { + width : 70px; + padding : 0; + font-family : 'Open Sans', sans-serif; + font-size : 11px; + font-weight : normal; + color : #CCCCCC; + text-transform : uppercase; + background-color : transparent; + &:focus-within { + height : 100%; + font-weight : 800; + color : white; + } + &:disabled { + color : #777777; + background-color : transparent !important; + } + } + } } \ No newline at end of file From a715c9e1e611a38b6058c10293f9fab6cee8ac52 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:26:56 -0500 Subject: [PATCH 176/730] Store livescrolling in local storage Small fixes for loading the correct current state. --- client/homebrew/editor/editor.jsx | 24 +++++++---------- shared/naturalcrit/splitPane/splitPane.jsx | 29 ++++++++++++++++----- shared/naturalcrit/splitPane/splitPane.less | 4 +-- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 185f37ac6..5eaf0345d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -23,7 +23,6 @@ const DEFAULT_STYLE_TEXT = dedent` }`; let lastPage = 0; -let liveScroll = true; const isElementCodeMirror=(element)=>{ let el = element; @@ -44,7 +43,6 @@ const Editor = createClass({ text : '', style : '' }, - liveScroll : true, onTextChange : ()=>{}, onStyleChange : ()=>{}, @@ -67,12 +65,13 @@ const Editor = createClass({ isMeta : function() {return this.state.view == 'meta';}, componentDidMount : function() { + this.updateEditorSize(); this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('click', (e)=>{ - if(isElementCodeMirror(e.target) && liveScroll ) { + if(isElementCodeMirror(e.target) && this.props.liveScroll ) { const curPage = this.getCurrentPage(); if( curPage != lastPage ) { this.brewJump(); @@ -94,10 +93,6 @@ const Editor = createClass({ }, componentDidUpdate : function(prevProps, prevState, snapshot) { - console.log(this.props); - console.log(prevProps); - console.log(this.state); - console.log(prevState); this.highlightCustomMarkdown(); if(prevProps.moveBrew !== this.props.moveBrew) { @@ -106,13 +101,13 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) { this.sourceJump(); }; - if(prevProps.liveScroll !== this.props.liveScroll) { - liveScroll = !liveScroll; + if(prevProps.liveScroll != this.props.liveScroll) { + if (this.props.liveScroll) this.brewJump(); }; }, handleControlKeys : function(e){ - if(liveScroll) { + if(this.props.liveScroll) { const movementKeys = [ 13, 33, 34, 37, 38, 39, 40 ]; if (movementKeys.includes(e.keyCode)) { const curPage = this.getCurrentPage(); @@ -122,14 +117,14 @@ const Editor = createClass({ } } } - const M_KEY = 77; + const X_KEY = 88; const END_KEY = 35; const HOME_KEY = 36; const SCROLLLOCK_KEY = 145; // Toggle Live-scrolling on Scroll Lock if(e.keyCode == SCROLLLOCK_KEY) { - liveScroll = !liveScroll; + this.setState( {liveScroll: !liveScroll} ); } if(!(e.ctrlKey || e.metaKey)) return; @@ -140,9 +135,9 @@ const Editor = createClass({ // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); // Source Jump on Shift-CTRL-J - if ((e.shiftKey) && (!e.altKey) && (e.keyCode == M_KEY)) this.sourceJump(); + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == X_KEY)) this.sourceJump(); - if( e.keyCode == M_KEY) { + if( e.keyCode == X_KEY) { e.stopPropagation(); e.preventDefault(); } @@ -330,6 +325,7 @@ const Editor = createClass({ // console.log(`Scroll to: p${targetPage}`); const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; + if(!window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)) return; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; const interimPos = targetPos >= 0 ? -30 : 30; diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index e1b30887e..71831fb23 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -20,7 +20,6 @@ const SplitPane = createClass({ isDragging : false, moveSource : false, moveBrew : false, - liveScroll : true, viewablePageNumber : 0, showMoveArrows : true }; @@ -41,9 +40,25 @@ const SplitPane = createClass({ }); } window.addEventListener('resize', this.handleWindowResize); + + + // This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts. + const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true'; + this.setState({ + liveScroll : loadLiveScroll + }); + const toggle = document.getElementById('scrollToggle'); + const toggleDiv = document.getElementById('scrollToggleDiv'); + if(loadLiveScroll) { + toggle.className = 'fas fa-lock'; + toggleDiv.className = 'arrow lock'; + } else { + toggle.className = 'fas fa-unlock'; + toggleDiv.className = 'arrow unlock'; + } }, -componentWillUnmount : function() { + componentWillUnmount : function() { window.removeEventListener('resize', this.handleWindowResize); }, @@ -119,21 +134,23 @@ componentWillUnmount : function() { onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} >
    -
    { - this.setState({ liveScroll: !this.state.liveScroll }); + const flipLiveScroll = !this.state.liveScroll; const toggle = document.getElementById('scrollToggle'); const toggleDiv = document.getElementById('scrollToggleDiv'); - if(toggle.classList.contains('fa-unlock')) { + if(flipLiveScroll) { toggle.className = 'fas fa-lock'; toggleDiv.className = 'arrow lock'; } else { toggle.className = 'fas fa-unlock'; toggleDiv.className = 'arrow unlock'; } + window.localStorage.setItem('liveScroll', String(flipLiveScroll)); + this.setState({ liveScroll: flipLiveScroll }); }} > - +
    ; } diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index 2000db72a..f8bc686de 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -54,11 +54,11 @@ top : 60px; } &.lock{ - .tooltipRight('Lock cursor tracking between windows.'); + .tooltipRight('Unlock cursor tracking between windows.'); top : 90px; } &.unlock{ - .tooltipRight('Unlock cursor tracking between windows.'); + .tooltipRight('Lock cursor tracking between windows.'); top : 90px; } &:hover{ From 4818f70aeda2955aaf1a0ab6a067b04786fe2e5e Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:36:44 -0500 Subject: [PATCH 177/730] Add additional visual hinting to liveScroll lock. --- shared/naturalcrit/splitPane/splitPane.less | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index f8bc686de..567c1c6d0 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -56,6 +56,7 @@ &.lock{ .tooltipRight('Unlock cursor tracking between windows.'); top : 90px; + background: #666; } &.unlock{ .tooltipRight('Lock cursor tracking between windows.'); From ea9f9a8c36ed2bbdab2106ba8c81fa4ebf4e88af Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:39:20 -0500 Subject: [PATCH 178/730] Missed a couple of variable repalcements. --- client/homebrew/editor/editor.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index fb842463a..147170023 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -127,13 +127,13 @@ const Editor = createClass({ // Toggle Live-scrolling on Scroll Lock if(e.keyCode == SCROLLLOCK_KEY) { - this.setState( {liveScroll: !liveScroll} ); + this.setState( {liveScroll: !this.props.liveScroll} ); } if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END - if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); + if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); From 510d8f410dbbe78120f72c272af3697391e1bc34 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 22:45:22 -0500 Subject: [PATCH 179/730] Resolve timing issue with liveScroll on linking. Checks to see if prevProps.livescroll has a proper Bool value. If not, do not brewJump() in editor.componantSDidUpdate. --- client/homebrew/editor/editor.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 147170023..06375d21d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -105,7 +105,7 @@ const Editor = createClass({ this.sourceJump(); }; if(prevProps.liveScroll != this.props.liveScroll) { - if (this.props.liveScroll) this.brewJump(); + if ((prevProps.liveScroll != undefined) && (this.props.liveScroll)) this.brewJump(); }; }, @@ -328,7 +328,6 @@ const Editor = createClass({ // console.log(`Scroll to: p${targetPage}`); const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; - if(!window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)) return; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; const interimPos = targetPos >= 0 ? -30 : 30; From c918a79957bc9f34cc1be7e9f2b42184f5fd945a Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 5 Jun 2024 12:44:46 -0500 Subject: [PATCH 180/730] Integrates corrections for Document level unique Header IDs in tandum with marked-gfm-header-id updates. Requries https://github.com/markedjs/marked-gfm-heading-id/issues/542 and an assumed version bump to work. Validated locally. --- package-lock.json | 50 ++++++++++++++++++++++++---------- package.json | 2 +- shared/naturalcrit/markdown.js | 13 +++++---- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index e18ca8ac7..2662f3bea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "marked": "11.2.0", "marked-emoji": "^1.4.0", "marked-extended-tables": "^1.0.8", - "marked-gfm-heading-id": "^3.1.3", + "marked-gfm-heading-id": "file:../marked-gfm-heading-id", "marked-smartypants-lite": "^1.0.2", "markedLegacy": "npm:marked@^0.3.19", "moment": "^2.30.1", @@ -67,6 +67,38 @@ "npm": "^10.2.x" } }, + "../marked-gfm-heading-id": { + "version": "3.1.3", + "license": "MIT", + "dependencies": { + "github-slugger": "^2.0.0" + }, + "devDependencies": { + "@babel/core": "^7.24.6", + "@babel/preset-env": "^7.24.6", + "@rollup/plugin-node-resolve": "^15.2.3", + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/commit-analyzer": "^13.0.0", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^10.0.5", + "@semantic-release/npm": "^12.0.1", + "@semantic-release/release-notes-generator": "^14.0.0", + "babel-jest": "^29.7.0", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.2.0", + "jest-cli": "^29.7.0", + "marked": "^12.0.2", + "rollup": "^4.18.0", + "semantic-release": "^24.0.0", + "tsd": "^0.31.0" + }, + "peerDependencies": { + "marked": ">=4 <13" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -6739,11 +6771,6 @@ "node": ">=0.10.0" } }, - "node_modules/github-slugger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -10168,15 +10195,8 @@ } }, "node_modules/marked-gfm-heading-id": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.1.3.tgz", - "integrity": "sha512-A0cRU4PCueX/5m8VE4mT8uTQ36l3xMYRojz3Eqnk4BmUFZ0T+9Xhn2KvHcANP4qbhfOeuMrWJCTQbASIBR5xeg==", - "dependencies": { - "github-slugger": "^2.0.0" - }, - "peerDependencies": { - "marked": ">=4 <13" - } + "resolved": "../marked-gfm-heading-id", + "link": true }, "node_modules/marked-smartypants-lite": { "version": "1.0.2", diff --git a/package.json b/package.json index c98c42817..36589eae9 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "marked": "11.2.0", "marked-emoji": "^1.4.0", "marked-extended-tables": "^1.0.8", - "marked-gfm-heading-id": "^3.1.3", + "marked-gfm-heading-id": "^3.1.4", "marked-smartypants-lite": "^1.0.2", "markedLegacy": "npm:marked@^0.3.19", "moment": "^2.30.1", diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 95431487d..0ff32b007 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -3,7 +3,7 @@ const _ = require('lodash'); const Marked = require('marked'); const MarkedExtendedTables = require('marked-extended-tables'); const { markedSmartypantsLite: MarkedSmartypantsLite } = require('marked-smartypants-lite'); -const { gfmHeadingId: MarkedGFMHeadingId } = require('marked-gfm-heading-id'); +const { gfmHeadingId: MarkedGFMHeadingId, resetHeadings: MarkedGFMResetHeadingIDs } = require('marked-gfm-heading-id'); const { markedEmoji: MarkedEmojis } = require('marked-emoji'); //Icon fonts included so they can appear in emoji autosuggest dropdown @@ -699,7 +699,7 @@ Marked.use(MarkedVariables()); Marked.use({ extensions: [definitionListsMultiLine, definitionListsSingleLine, superSubScripts, mustacheSpans, mustacheDivs, mustacheInjectInline] }); Marked.use(mustacheInjectBlock); Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false }); -Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite(), MarkedEmojis(MarkedEmojiOptions)); +Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId({ globalSlugs: true }), MarkedSmartypantsLite(), MarkedEmojis(MarkedEmojiOptions)); const nonWordAndColonTest = /[^\w:]/g; const cleanUrl = function (sanitize, base, href) { @@ -814,9 +814,12 @@ let globalPageNumber = 0; module.exports = { marked : Marked, render : (rawBrewText, pageNumber=1)=>{ - globalVarsList[pageNumber] = {}; //Reset global links for current page, to ensure values are parsed in order - varsQueue = []; //Could move into MarkedVariables() - globalPageNumber = pageNumber; + globalVarsList[pageNumber] = {}; //Reset global links for current page, to ensure values are parsed in order + varsQueue = []; //Could move into MarkedVariables() + globalPageNumber = pageNumber; + if(pageNumber==0) { + MarkedGFMResetHeadingIDs(); + } rawBrewText = rawBrewText.replace(/^\\column$/gm, `\n
    \n`) .replace(/^(:+)$/gm, (match)=>`${`
    `.repeat(match.length)}\n`); From 042e217872ed381534ec1bd1b6c66a2a8421e0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 10 Jun 2024 23:23:31 +0200 Subject: [PATCH 181/730] "Refactor ArchivePage component from createClass to functional component with hooks" --- .../pages/archivePage/archivePage.jsx | 438 ++++++++---------- 1 file changed, 201 insertions(+), 237 deletions(-) diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/archivePage/archivePage.jsx index b5ec1f8d6..657837392 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/archivePage/archivePage.jsx @@ -1,7 +1,7 @@ require('./archivePage.less'); const React = require('react'); -const createClass = require('create-react-class'); +const { useState, useEffect, useRef } = React; const cx = require('classnames'); const Nav = require('naturalcrit/nav/nav.jsx'); @@ -11,270 +11,234 @@ const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); -//const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx'); const request = require('../../utils/request-middleware.js'); -const ArchivePage = createClass({ - displayName: 'ArchivePage', - getDefaultProps: function () { - return {}; - }, +const ArchivePage = (props) => { + const [title, setTitle] = useState(props.query.title || ''); + const [legacy, setLegacy] = useState(props.query.legacy !== 'false'); + const [v3, setV3] = useState(props.query.v3 !== 'false'); + const [count, setCount] = useState(props.query.count || 10); + const [page, setPage] = useState(parseInt(props.query.page) || 1); + const [brewCollection, setBrewCollection] = useState(null); + const [totalBrews, setTotalBrews] = useState(null); + const [searching, setSearching] = useState(false); + const [error, setError] = useState(null); - getInitialState: function () { - return { - //# request - title: this.props.query.title || '', - //tags: {}, - legacy: this.props.query.legacy !== 'false', - v3: this.props.query.v3 !== 'false', - count: this.props.query.count || 10, - page: parseInt(this.props.query.page) || 1, + const titleRef = useRef(null); + const countRef = useRef(null); + const v3Ref = useRef(null); + const legacyRef = useRef(null); - //# response - brewCollection: null, - totalBrews: null, - - searching: false, - error: null, - }; - }, - - componentDidMount: function () { - console.log(this.props.query); - console.log(this.state); - - this.validateInput(); - if (this.state.title) { - this.loadPage(this.state.page, false); + useEffect(() => { + validateInput(); + if (title) { + loadPage(page, false); } - this.state.totalBrews || this.loadTotal(); // Load total if not already loaded - }, + !totalBrews && loadTotal(); + }, []); - updateStateWithBrews: function (brews, page) { - this.setState({ - brewCollection: brews || null, - page: parseInt(page) || 1, - searching: false, - }); - }, + const updateStateWithBrews = (brews, page) => { + setBrewCollection(brews || null); + setPage(parseInt(page) || 1); + setSearching(false); + }; - updateUrl: function (title, page, count, v3, legacy) { + const updateUrl = (title, page, count, v3, legacy) => { const url = new URL(window.location.href); const urlParams = new URLSearchParams(); - - Object.entries({ title, page, count, v3, legacy }).forEach(([key, value]) => urlParams.set(key, value)); - + + Object.entries({ title, page, count, v3, legacy }).forEach( + ([key, value]) => urlParams.set(key, value) + ); + url.search = urlParams.toString(); window.history.replaceState(null, null, url); - }, - - loadPage: async function (page, update) { - this.setState({ searching: true, error: null }); - - + }; + + const loadPage = async (page, update) => { + setSearching(true); + setError(null); + const performSearch = async ({ title, count, v3, legacy }) => { - this.updateUrl(title, page, count, v3, legacy); + updateUrl(title, page, count, v3, legacy); if (title !== '') { try { const response = await request.get( `/api/archive?title=${title}&page=${page}&count=${count}&v3=${v3}&legacy=${legacy}` ); if (response.ok) { - this.updateStateWithBrews(response.body.brews, page); - + updateStateWithBrews(response.body.brews, page); } else { throw new Error(`Error: ${response.status}`); } } catch (error) { console.log('error at loadPage: ', error); - this.setState({ error: `${error.response ? error.response.status : error.message}` }); - this.updateStateWithBrews([], 1); + setError( + `${ + error.response + ? error.response.status + : error.message + }` + ); + updateStateWithBrews([], 1); } } else { - this.setState({ error: '404' }); + setError('404'); } }; - - if (update === true) { - const title = document.getElementById('title').value || ''; - const count = document.getElementById('count').value || 10; - const v3 = document.getElementById('v3').checked; - const legacy = document.getElementById('legacy').checked; - - this.setState( - { - title: title, - count: count, - v3: v3, - legacy: legacy, - }, - () => { - // State is updated, now perform the search - performSearch({ title, count, v3, legacy }); - } - ); + + if (update) { + const title = titleRef.current.value || ''; + const count = countRef.current.value || 10; + const v3 = v3Ref.current.checked; + const legacy = legacyRef.current.checked; + + setTitle(title); + setCount(count); + setV3(v3); + setLegacy(legacy); + + performSearch({ title, count, v3, legacy }); } else { - const { title, count, v3, legacy } = this.state; performSearch({ title, count, v3, legacy }); } - }, - - loadTotal: async function () { - const {title, v3, legacy} = this.state; + }; + + const loadTotal = async () => { + setTotalBrews(null); + setError(null); - this.setState({ - totalBrews: null, - error: null - }); - if (title) { try { const response = await request.get( `/api/archive/total?title=${title}&v3=${v3}&legacy=${legacy}` ); - + if (response.ok) { - this.setState({ - totalBrews: response.body.totalBrews, - }); + setTotalBrews(response.body.totalBrews); } else { - throw new Error(`Failed to load total brews: ${response.statusText}`); + throw new Error( + `Failed to load total brews: ${response.statusText}` + ); } } catch (error) { console.log('error at loadTotal: ', error); - this.setState({ error: `${error.response.status}` }); - this.updateStateWithBrews([], 1); + setError(`${error.response.status}`); + updateStateWithBrews([], 1); } } - }, + }; - renderNavItems: function () { - return ( - - - - Archive: Search for brews - - - - - - - - - - ); - }, + const renderNavItems = () => ( + + + + Archive: Search for brews + + + + + + + + + + ); - validateInput: function () { - const textInput = document.getElementById('title'); + const validateInput = () => { + const textInput = titleRef.current; const submitButton = document.getElementById('searchButton'); if (textInput.validity.valid && textInput.value) { submitButton.disabled = false; } else { submitButton.disabled = true; } - }, + }; - renderForm: function () { - return ( -
    -

    Brew Lookup

    -
    -
    + ); - renderPaginationControls: function () { - if (!this.state.totalBrews) { - return null; - } + const renderPaginationControls = () => { + if (!totalBrews) return null; - const count = parseInt(this.state.count); - const { page, totalBrews } = this.state; - const totalPages = Math.ceil(totalBrews / count); + const countInt = parseInt(count); + const totalPages = Math.ceil(totalBrews / countInt); let startPage, endPage; if (page <= 6) { @@ -296,7 +260,7 @@ const ArchivePage = createClass({ className={`pageNumber ${ page === startPage + index ? 'currentPage' : '' }`} - onClick={() => this.loadPage(startPage + index, false)} + onClick={() => loadPage(startPage + index, false)} > {startPage + index} @@ -307,7 +271,7 @@ const ArchivePage = createClass({ {page > 1 && ( @@ -315,8 +279,8 @@ const ArchivePage = createClass({
      {startPage > 1 && ( this.loadPage(1, false)} + className="firstPage" + onClick={() => loadPage(1, false)} > 1 ... @@ -324,8 +288,8 @@ const ArchivePage = createClass({ {pagesAroundCurrent} {endPage < totalPages && ( this.loadPage(totalPages, false)} + className="lastPage" + onClick={() => loadPage(totalPages, false)} > ... {totalPages} @@ -334,18 +298,16 @@ const ArchivePage = createClass({ {page < totalPages && ( )}
    ); - }, - - renderFoundBrews() { - const { title, brewCollection, error, searching } = this.state; + }; + const renderFoundBrews = () => { if (searching) { return (
    @@ -395,43 +357,45 @@ const ArchivePage = createClass({
    ); } - console.log('state when rendering '); - console.table(this.state); + return (
    {`Brews found: `} - {title === '' ? '0' : this.state.totalBrews ? this.state.totalBrews : } + {title === '' ? ( + '0' + ) : totalBrews ? ( + totalBrews + ) : ( + + )} {brewCollection.map((brew, index) => ( ))} - {this.renderPaginationControls()} + {renderPaginationControls()}
    ); - - }, + }; - render: function () { - return ( -
    - - - {this.renderNavItems()} + return ( +
    + + + {renderNavItems()} +
    +
    {renderForm()}
    -
    -
    {this.renderForm()}
    -
    - {this.renderFoundBrews()} -
    +
    + {renderFoundBrews()}
    - ); - }, -}); +
    + ); +}; module.exports = ArchivePage; From 90431efbc92d7adaa57a706ff310a43c302b59c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 11 Jun 2024 00:33:36 +0200 Subject: [PATCH 182/730] "Removed ArchivePage and related files, replaced with VaultPage, updated routes and API endpoints, and made minor changes to theme configuration and error handling." --- client/homebrew/homebrew.jsx | 5 +-- .../basePages/listPage/brewItem/brewItem.jsx | 2 - .../vaultPage.jsx} | 45 +++++++++++-------- .../vaultPage.less} | 2 +- server/admin.api.js | 3 ++ server/app.js | 8 ++-- server/{archive.api.js => vault.api.js} | 13 +++--- themes/themes.json | 2 +- 8 files changed, 43 insertions(+), 37 deletions(-) rename client/homebrew/pages/{archivePage/archivePage.jsx => vaultPage/vaultPage.jsx} (91%) rename client/homebrew/pages/{archivePage/archivePage.less => vaultPage/vaultPage.less} (99%) rename server/{archive.api.js => vault.api.js} (90%) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 49f51aec0..b23f47baa 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -10,7 +10,7 @@ const UserPage = require('./pages/userPage/userPage.jsx'); const SharePage = require('./pages/sharePage/sharePage.jsx'); const NewPage = require('./pages/newPage/newPage.jsx'); const ErrorPage = require('./pages/errorPage/errorPage.jsx'); -const PrintPage = require('./pages/printPage/printPage.jsx'); +const VaultPage = require('./pages/vaultPage/vaultPage.jsx'); const AccountPage = require('./pages/accountPage/accountPage.jsx'); const WithRoute = (props)=>{ @@ -72,9 +72,8 @@ const Homebrew = createClass({ } /> } /> } /> - } /> - } /> } /> + }/> } /> } /> } /> diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx index affc227c0..bf0624f1c 100644 --- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx +++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx @@ -117,8 +117,6 @@ const BrewItem = createClass({ }); } const dateFormatString = 'YYYY-MM-DD HH:mm:ss'; - const authors = brew.authors.length > 0 ? brew.authors : 'No authors'; - return
    {brew.thumbnail && diff --git a/client/homebrew/pages/archivePage/archivePage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx similarity index 91% rename from client/homebrew/pages/archivePage/archivePage.jsx rename to client/homebrew/pages/vaultPage/vaultPage.jsx index 657837392..867812bc5 100644 --- a/client/homebrew/pages/archivePage/archivePage.jsx +++ b/client/homebrew/pages/vaultPage/vaultPage.jsx @@ -1,4 +1,4 @@ -require('./archivePage.less'); +require('./vaultPage.less'); const React = require('react'); const { useState, useEffect, useRef } = React; @@ -14,7 +14,7 @@ const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); const request = require('../../utils/request-middleware.js'); -const ArchivePage = (props) => { +const VaultPage = (props) => { const [title, setTitle] = useState(props.query.title || ''); const [legacy, setLegacy] = useState(props.query.legacy !== 'false'); const [v3, setV3] = useState(props.query.v3 !== 'false'); @@ -29,6 +29,7 @@ const ArchivePage = (props) => { const countRef = useRef(null); const v3Ref = useRef(null); const legacyRef = useRef(null); + const totalBrewsSpanRef = useRef(null); useEffect(() => { validateInput(); @@ -38,6 +39,23 @@ const ArchivePage = (props) => { !totalBrews && loadTotal(); }, []); + useEffect(() => { + console.log(totalBrewsSpanRef); + console.log(totalBrews); + if (totalBrewsSpanRef.current) { + if (title === '') { + totalBrewsSpanRef.current.innerHTML = '0'; + } else { + if (!totalBrews) { + totalBrewsSpanRef.current.innerHTML = + ''; + } else { + totalBrewsSpanRef.current.innerHTML = `${totalBrews}`; + } + } + } + }, [totalBrews, title, () => totalBrewsSpanRef.current]); + const updateStateWithBrews = (brews, page) => { setBrewCollection(brews || null); setPage(parseInt(page) || 1); @@ -65,7 +83,7 @@ const ArchivePage = (props) => { if (title !== '') { try { const response = await request.get( - `/api/archive?title=${title}&page=${page}&count=${count}&v3=${v3}&legacy=${legacy}` + `/api/vault?title=${title}&page=${page}&count=${count}&v3=${v3}&legacy=${legacy}` ); if (response.ok) { updateStateWithBrews(response.body.brews, page); @@ -112,7 +130,7 @@ const ArchivePage = (props) => { if (title) { try { const response = await request.get( - `/api/archive/total?title=${title}&v3=${v3}&legacy=${legacy}` + `/api/vault/total?title=${title}&v3=${v3}&legacy=${legacy}` ); if (response.ok) { @@ -134,7 +152,7 @@ const ArchivePage = (props) => { - Archive: Search for brews + Vault: Search for brews @@ -171,10 +189,7 @@ const ArchivePage = (props) => { pattern=".{3,}" onKeyDown={(e) => { if (e.key === 'Enter') { - if ( - e.target.validity.valid && - e.target.value - ) { + if (e.target.validity.valid && e.target.value) { loadTotal(); loadPage(1, true); } @@ -362,13 +377,7 @@ const ArchivePage = (props) => {
    {`Brews found: `} - {title === '' ? ( - '0' - ) : totalBrews ? ( - totalBrews - ) : ( - - )} + {brewCollection.map((brew, index) => ( { }; return ( -
    +
    {renderNavItems()} @@ -398,4 +407,4 @@ const ArchivePage = (props) => { ); }; -module.exports = ArchivePage; +module.exports = VaultPage; diff --git a/client/homebrew/pages/archivePage/archivePage.less b/client/homebrew/pages/vaultPage/vaultPage.less similarity index 99% rename from client/homebrew/pages/archivePage/archivePage.less rename to client/homebrew/pages/vaultPage/vaultPage.less index 75e9c462e..9f6b8e3df 100644 --- a/client/homebrew/pages/archivePage/archivePage.less +++ b/client/homebrew/pages/vaultPage/vaultPage.less @@ -25,7 +25,7 @@ body { } } -.archivePage { +.vaultPage { overflow-y: hidden; height: 100%; background-color: #2C3E50; diff --git a/server/admin.api.js b/server/admin.api.js index 0b5ecb1fc..66bd58852 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -85,6 +85,7 @@ router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next)=>{ }); }); + /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ const query = uncompressedBrewQuery.clone(); @@ -100,6 +101,7 @@ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ }); }); + /* Compresses the "text" field of a brew to binary */ router.put('/admin/compress/:id', (req, res)=>{ HomebrewModel.findOne({ _id: req.params.id }) @@ -121,6 +123,7 @@ router.put('/admin/compress/:id', (req, res)=>{ }); }); + router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ try { const totalBrewsCount = await HomebrewModel.countDocuments({}); diff --git a/server/app.js b/server/app.js index cc8c7dfef..b0cb0aca5 100644 --- a/server/app.js +++ b/server/app.js @@ -54,7 +54,7 @@ app.use((req, res, next)=>{ app.use(homebrewApi); app.use(require('./admin.api.js')); -app.use(require('./archive.api.js')); +app.use(require('./vault.api.js')); const HomebrewModel = require('./homebrew.model.js').model; const welcomeText = require('fs').readFileSync('client/homebrew/pages/homePage/welcome_msg.md', 'utf8'); @@ -462,8 +462,8 @@ app.use(async (err, req, res, next)=>{ res.status(err.status || err.response?.status || 500).send(err); return; } - if(err.originalUrl?.startsWith('/archive/')) { - // console.log('archive error'); + if(err.originalUrl?.startsWith('/vault/')) { + // console.log('vault error'); res.status(err.status || err.response?.status || 500).send(err); return; } @@ -490,8 +490,6 @@ app.use(async (err, req, res, next)=>{ res.send(page); }); - - app.use((req, res)=>{ if(!res.headersSent) { console.error('Headers have not been sent, responding with a server error.', req.url); diff --git a/server/archive.api.js b/server/vault.api.js similarity index 90% rename from server/archive.api.js rename to server/vault.api.js index 512b071f1..97d91fc54 100644 --- a/server/archive.api.js +++ b/server/vault.api.js @@ -52,10 +52,10 @@ const buildBrewsQuery = (legacy, v3) => { return brewsQuery; }; -const archive = { +const vault = { findBrews: async (req, res, next) => { try { - console.log(`Query as received in archive api for findBrews:`); + console.log(`Query as received in vault api for findBrews:`); console.table(req.query); const title = req.query.title || ''; @@ -91,7 +91,7 @@ const archive = { } }, findTotal: async (req, res) => { - console.log(`Query as received in archive api for totalBrews:`); + console.log(`Query as received in vault api for totalBrews:`); console.table(req.query); try { const title = req.query.title || ''; @@ -102,9 +102,8 @@ const archive = { const titleQuery = { $and: [brewsQuery, ...titleConditionsArray], }; - const totalBrews = await HomebrewModel.countDocuments(titleQuery); - console.log('when returning, totalbrews is ', totalBrews); + console.log('when returning, totalbrews is ', totalBrews, 'for the query ',JSON.stringify(titleQuery)); return res.json({ totalBrews }); } catch (error) { @@ -114,7 +113,7 @@ const archive = { }, }; -router.get('/api/archive/total', asyncHandler(archive.findTotal)); -router.get('/api/archive', asyncHandler(archive.findBrews)); +router.get('/api/vault/total', asyncHandler(vault.findTotal)); +router.get('/api/vault', asyncHandler(vault.findBrews)); module.exports = router; diff --git a/themes/themes.json b/themes/themes.json index cb0c5593e..bc719185d 100644 --- a/themes/themes.json +++ b/themes/themes.json @@ -34,7 +34,7 @@ "renderer": "V3", "baseTheme": false, "baseSnippets": "5ePHB", - "path": "Journal" + "path": "journal" } } } \ No newline at end of file From cba57d1033f5359f455b40071ccc2d62980175b9 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 11 Jun 2024 20:06:20 -0500 Subject: [PATCH 183/730] Fix and future-proof tests to use page 0 where necessary in markdown.render() calls. --- tests/markdown/basic.test.js | 4 +- tests/markdown/definition-lists.test.js | 28 +++--- tests/markdown/emojis.test.js | 14 +-- tests/markdown/mustache-syntax.test.js | 126 ++++++++++++------------ tests/markdown/variables.test.js | 56 +++++------ 5 files changed, 114 insertions(+), 114 deletions(-) diff --git a/tests/markdown/basic.test.js b/tests/markdown/basic.test.js index 80f5520e7..6df19b6e0 100644 --- a/tests/markdown/basic.test.js +++ b/tests/markdown/basic.test.js @@ -4,12 +4,12 @@ const Markdown = require('naturalcrit/markdown.js'); test('Processes the markdown within an HTML block if its just a class wrapper', function() { const source = '
    *Bold text*
    '; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered).toBe('

    Bold text

    \n
    '); }); test('Check markdown is using the custom renderer; specifically that it adds target=_self attribute to internal links in HTML blocks', function() { const source = '
    [Has _self Attribute?](#p1)
    '; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered).toBe(''); }); diff --git a/tests/markdown/definition-lists.test.js b/tests/markdown/definition-lists.test.js index 9f5025d73..d3d9f4b32 100644 --- a/tests/markdown/definition-lists.test.js +++ b/tests/markdown/definition-lists.test.js @@ -5,19 +5,19 @@ const Markdown = require('naturalcrit/markdown.js'); describe('Inline Definition Lists', ()=>{ test('No Term 1 Definition', function() { const source = ':: My First Definition\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    My First Definition
    \n
    '); }); test('Single Definition Term', function() { const source = 'My term :: My First Definition\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    My term
    My First Definition
    \n
    '); }); test('Multiple Definition Terms', function() { const source = 'Term 1::Definition of Term 1\nTerm 2::Definition of Term 2\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    Definition of Term 1
    \n
    Term 2
    Definition of Term 2
    \n
    '); }); }); @@ -25,67 +25,67 @@ describe('Inline Definition Lists', ()=>{ describe('Multiline Definition Lists', ()=>{ test('Single Term, Single Definition', function() { const source = 'Term 1\n::Definition 1\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1
    '); }); test('Single Term, Plural Definitions', function() { const source = 'Term 1\n::Definition 1\n::Definition 2\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1
    \n
    Definition 2
    '); }); test('Multiple Term, Single Definitions', function() { const source = 'Term 1\n::Definition 1\n\nTerm 2\n::Definition 1\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1
    \n
    Term 2
    \n
    Definition 1
    '); }); test('Multiple Term, Plural Definitions', function() { const source = 'Term 1\n::Definition 1\n::Definition 2\n\nTerm 2\n::Definition 1\n::Definition 2\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1
    \n
    Definition 2
    \n
    Term 2
    \n
    Definition 1
    \n
    Definition 2
    '); }); test('Single Term, Single multi-line definition', function() { const source = 'Term 1\n::Definition 1\nand more and\nmore and more\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1 and more and more and more
    '); }); test('Single Term, Plural multi-line definitions', function() { const source = 'Term 1\n::Definition 1\nand more and more\n::Definition 2\nand more\nand more\n::Definition 3\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1 and more and more
    \n
    Definition 2 and more and more
    \n
    Definition 3
    '); }); test('Multiple Term, Single multi-line definition', function() { const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\n'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1 and more and more
    \n
    Term 2
    \n
    Definition 1
    \n
    Definition 2
    '); }); test('Multiple Term, Single multi-line definition, followed by an inline dl', function() { const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\n::Inline Definition (no term)'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1 and more and more
    \n
    Term 2
    \n
    Definition 1
    \n
    Definition 2
    Inline Definition (no term)
    \n
    '); }); test('Multiple Term, Single multi-line definition, followed by paragraph', function() { const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\nParagraph'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    \n
    Definition 1 and more and more
    \n
    Term 2
    \n
    Definition 1
    \n
    Definition 2

    Paragraph

    '); }); test('Block Token cannot be the Term of a multi-line definition', function() { const source = '## Header\n::Definition 1 of a single-line DL\n::Definition 1 of another single-line DL'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('\n
    Definition 1 of a single-line DL
    \n
    Definition 1 of another single-line DL
    \n
    '); }); test('Inline DL has priority over Multiline', function() { const source = 'Term 1 :: Inline definition 1\n:: Inline definition 2 (no DT)'; - const rendered = Markdown.render(source).trim(); + const rendered = Markdown.render(source, 0).trim(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
    Term 1
    Inline definition 1
    \n
    Inline definition 2 (no DT)
    \n
    '); }); }); diff --git a/tests/markdown/emojis.test.js b/tests/markdown/emojis.test.js index a4abbc6a4..a3de0dab1 100644 --- a/tests/markdown/emojis.test.js +++ b/tests/markdown/emojis.test.js @@ -12,37 +12,37 @@ const emoji = 'df_d12_2'; describe(`When emojis/icons are active`, ()=>{ it('when a word is between two colons (:word:), and a matching emoji exists, it is rendered as an emoji', function() { const source = `:${emoji}:`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    `); }); it('when a word is between two colons (:word:), and no matching emoji exists, it is not parsed', function() { const source = `:invalid:`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    :invalid:

    `); }); it('two valid emojis with no whitespace are prioritized over definition lists', function() { const source = `:${emoji}::${emoji}:`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    `); }); it('definition lists that are not also part of an emoji can coexist with normal emojis', function() { const source = `definition :: term ${emoji}::${emoji}:`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    definition
    term df_d12_2:
    `); }); it('A valid emoji is compatible with curly injectors', function() { const source = `:${emoji}:{color:blue,myClass}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    `); }); it('Emojis are not parsed inside of curly span CSS blocks', function() { const source = `{{color:${emoji} text}}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`text`); }); @@ -50,7 +50,7 @@ describe(`When emojis/icons are active`, ()=>{ const source = dedent`{{color:${emoji} text }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); diff --git a/tests/markdown/mustache-syntax.test.js b/tests/markdown/mustache-syntax.test.js index b32876353..cb34fa697 100644 --- a/tests/markdown/mustache-syntax.test.js +++ b/tests/markdown/mustache-syntax.test.js @@ -15,112 +15,112 @@ String.prototype.trimReturns = function(){ describe('Inline: When using the Inline syntax {{ }}', ()=>{ it('Renders a mustache span with text only', function() { const source = '{{ text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text only, but with spaces', function() { const source = '{{ this is a text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text'); }); it('Renders an empty mustache span', function() { const source = '{{}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); it('Renders a mustache span with just a space', function() { const source = '{{ }}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); it('Renders a mustache span with a few spaces only', function() { const source = '{{ }}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); it('Renders a mustache span with text and class', function() { const source = '{{my-class text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and two classes', function() { const source = '{{my-class,my-class2 text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text with spaces and class', function() { const source = '{{my-class this is a text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text'); }); it('Renders a mustache span with text and id', function() { const source = '{{#my-span text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and two ids', function() { const source = '{{#my-span,#my-favorite-span text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and css property', function() { const source = '{{color:red text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and two css properties', function() { const source = '{{color:red,padding:5px text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and css property which contains quotes', function() { const source = '{{font-family:"trebuchet ms" text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text and two css properties which contains quotes', function() { const source = '{{font-family:"trebuchet ms",padding:"5px 10px" text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a mustache span with text with quotes and css property which contains double quotes', function() { const source = '{{font-family:"trebuchet ms" text "with quotes"}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text “with quotes”'); }); it('Renders a mustache span with text with quotes and css property which contains double and simple quotes', function() { const source = `{{--stringVariable:"'string'" text "with quotes"}}`; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`text “with quotes”`); }); it('Renders a mustache span with text, id, class and a couple of css properties', function() { const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span with added attributes', function() { const source = 'Text and {{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e, text}} and more text!'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Text and text and more text!

    \n'); }); }); @@ -132,7 +132,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{ text }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); @@ -140,14 +140,14 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{ }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    `); }); it('Renders a single paragraph with opening and closing brackets', function() { const source = dedent`{{ }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    {{}}

    `); }); @@ -155,7 +155,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{cat }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    `); }); @@ -163,7 +163,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{cat Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -171,7 +171,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{cat,dog Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -179,7 +179,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{color:red Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -187,7 +187,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{--stringVariable:"'string'" Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -195,7 +195,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{--stringVariable:"'string'" Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -203,7 +203,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{cat,color:red Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -211,7 +211,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{color:red,cat,#dog Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -219,7 +219,7 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{#cat,#dog Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -227,13 +227,13 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{color:red,cat,#dog,a="b and c",d="e" Sample text. }}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); it('Renders a div with added attributes', function() { const source = '{{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e\nText and text and more text!\n}}\n'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Text and text and more text!

    \n
    '); }); }); @@ -245,97 +245,97 @@ describe('Injection: When an injection tag follows an element', ()=>{ describe('and that element is an inline-block', ()=>{ it('Renders a span "text" with no injection', function() { const source = '{{ text}}{}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with injected Class name', function() { const source = '{{ text}}{ClassName}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with injected attribute', function() { const source = '{{ text}}{a="b and c"}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with injected style', function() { const source = '{{ text}}{color:red}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with injected style using a string variable', function() { const source = `{{ text}}{--stringVariable:"'string'"}`; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`text`); }); it('Renders a span "text" with two injected styles', function() { const source = '{{ text}}{color:red,background:blue}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with its own ID, overwritten with an injected ID', function() { const source = '{{#oldId text}}{#newId}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with its own attributes, overwritten with an injected attribute, plus a new one', function() { const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new"}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with its own attributes, overwritten with an injected attribute, ignoring "class", "style", and "id"', function() { const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new",class="new",style="new",id="new"}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with its own styles, appended with injected styles', function() { const source = '{{color:blue,height:10px text}}{width:10px,color:red}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders a span "text" with its own classes, appended with injected classes', function() { const source = '{{classA,classB text}}{classA,classC}'; - const rendered = Markdown.render(source); + const rendered = Markdown.render(source, 0); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); it('Renders an emphasis element with injected Class name', function() { const source = '*emphasis*{big}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    emphasis

    '); }); it('Renders a code element with injected style', function() { const source = '`code`{background:gray}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    code

    '); }); it('Renders an image element with injected style', function() { const source = '![alt text](http://i.imgur.com/hMna6G0.png){position:absolute}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    alt text

    '); }); it('Renders an element modified by only the first of two consecutive injections', function() { const source = '{{ text}}{color:red}{background:blue}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text{background:blue}

    '); }); it('Renders an image with added attributes', function() { const source = `![homebrew mug](https://i.imgur.com/hMna6G0.png) {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    homebrew mug

    `); }); }); @@ -343,19 +343,19 @@ describe('Injection: When an injection tag follows an element', ()=>{ describe('and that element is a block', ()=>{ it('renders a div "text" with no injection', function() { const source = '{{\ntext\n}}\n{}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); it('renders a div "text" with injected Class name', function() { const source = '{{\ntext\n}}\n{ClassName}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); it('renders a div "text" with injected style', function() { const source = '{{\ntext\n}}\n{color:red}'; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -364,7 +364,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {color:red,background:blue}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); @@ -373,7 +373,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {--stringVariable:"'string'"}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); @@ -382,7 +382,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {#newId}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -391,7 +391,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {attrA="new",attrC="new"}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -400,7 +400,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {attrA="new",attrC="new",class="new",style="new",id="new"}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -409,7 +409,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {width:10px,color:red}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -418,14 +418,14 @@ describe('Injection: When an injection tag follows an element', ()=>{ text }} {classA,classC}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); it('renders an h2 header "text" with injected class name', function() { const source = dedent`## text {ClassName}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); }); @@ -436,7 +436,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ | 300 | 2 | {ClassName}`; - const rendered = Markdown.render(source).trimReturns(); + const rendered = Markdown.render(source, 0).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    Experience PointsLevel
    01
    3002
    `); }); @@ -447,7 +447,7 @@ describe('Injection: When an injection tag follows an element', ()=>{ // - Dark Chant of the Dentists // - Divine Spell of Crossdressing // {color:red}`; - // const rendered = Markdown.render(source).trimReturns(); + // const rendered = Markdown.render(source, 0).trimReturns(); // expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`...`); // FIXME: expect this to be injected into