From e7680ef80bf02ab541f5f6ebc38c7e3bca6f150c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 27 May 2026 22:43:57 +0200 Subject: [PATCH 01/11] proper cleaning function --- .../brewUtils/brewCleanup/brewCleanup.jsx | 41 +++++++++++++++++++ server/admin.api.js | 17 ++++---- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index 721ec1e00..85d77ba85 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -1,8 +1,10 @@ import React, { useState } from 'react'; import request from 'superagent'; +import Moment from 'moment'; const BrewCleanup = ({})=>{ const [count, setCount] = useState(0); + const [brewCollection, setBrewCollection] = useState([]); const [pending, setPending] = useState(false); const [primed, setPrimed] = useState(false); const [error, setError] = useState(null); @@ -14,6 +16,7 @@ const BrewCleanup = ({})=>{ const res = await request.get('/admin/cleanup'); setCount(res.body.count); + setBrewCollection(res.body.brewCollection); setPrimed(true); } catch (err) { setError(err); @@ -36,6 +39,43 @@ const BrewCleanup = ({})=>{ setPrimed(false); } }; + const renderBrewList = ()=>{ + if(!brewCollection) { + console.log(brewCollection) + return null; + } + + return <> +

{`Results - ${brewCollection.length} brews` }

+ + + + + + + + + + + + {brewCollection + .sort((a, b)=>{ // Sort brews from most recently updated + if(a.updatedAt > b.updatedAt) return -1; + return 1; + }) + .map((brew, idx)=>{ + return + + + + + + ; + })} + +
TitleShareLast UpdateCreatedStorage
{brew.title || 'No Title'}{brew.shareId}{Moment(brew.updatedAt).fromNow()}{brew.createdAt ? Moment(brew.createdAt).fromNow() : 'No creation date'}{brew.googleId ? 'Google' : 'Homebrewery'}
+ ; + }; const renderPrimed = ()=>{ if(!primed) return; @@ -49,6 +89,7 @@ const BrewCleanup = ({})=>{ } Found {count} Brews that could be removed. + {renderBrewList()} ; }; diff --git a/server/admin.api.js b/server/admin.api.js index f55eefdf2..60582b75f 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -41,12 +41,13 @@ export default function createAdminApi(vite) { const junkBrewPipeline = [ { $match : { - updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, - lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } - } }, - { $project: { textBinSize: { $binarySize: '$textBin' } } }, - { $match: { textBinSize: { $lt: 140 } } }, - { $limit: 100 } + updatedAt : { $lt: Moment().subtract(365, 'days').toDate() }, + lastViewed : { $lt: Moment().subtract(365, 'days').toDate() } + }}, + { $match: { + authors : [], + }}, + { $limit: 300 } ]; /* Search for brews that aren't compressed (missing the compressed text field) */ @@ -54,10 +55,10 @@ export default function createAdminApi(vite) { 'text' : { '$exists': true } }).lean().limit(10000).select('_id'); - // Search for up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes + // Search for up to 100 brews that have not been viewed or updated in a year router.get('/admin/cleanup', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) - .then((objs)=>res.json({ count: objs.length })) + .then((objs)=>res.json({ count: objs.length, brewCollection : objs })) .catch((error)=>{ console.error(error); res.status(500).json({ error: 'Internal Server Error' }); From 3b71f6fa0ba3966f6b205bb861b6c646ee3a91ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 28 May 2026 10:36:24 +0200 Subject: [PATCH 02/11] change prime to found --- .../brewUtils/brewCleanup/brewCleanup.jsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index 85d77ba85..be1ca0a51 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -6,10 +6,10 @@ const BrewCleanup = ({})=>{ const [count, setCount] = useState(0); const [brewCollection, setBrewCollection] = useState([]); const [pending, setPending] = useState(false); - const [primed, setPrimed] = useState(false); + const [found, setFound] = useState(false); const [error, setError] = useState(null); - const prime = async ()=>{ + const find = async ()=>{ setPending(true); try { @@ -17,7 +17,7 @@ const BrewCleanup = ({})=>{ setCount(res.body.count); setBrewCollection(res.body.brewCollection); - setPrimed(true); + setFound(true); } catch (err) { setError(err); } finally { @@ -36,7 +36,7 @@ const BrewCleanup = ({})=>{ setError(err); } finally { setPending(false); - setPrimed(false); + setFound(false); } }; const renderBrewList = ()=>{ @@ -51,7 +51,6 @@ const BrewCleanup = ({})=>{ Title - Share Last Update Created Storage @@ -66,7 +65,8 @@ const BrewCleanup = ({})=>{ .map((brew, idx)=>{ return {brew.title || 'No Title'} - {brew.shareId} + {//{brew.shareId} + } {Moment(brew.updatedAt).fromNow()} {brew.createdAt ? Moment(brew.createdAt).fromNow() : 'No creation date'} {brew.googleId ? 'Google' : 'Homebrewery'} @@ -76,8 +76,8 @@ const BrewCleanup = ({})=>{ ; }; - const renderPrimed = ()=>{ - if(!primed) return; + const renderFound = ()=>{ + if(!found) return; if(!count) return
No Matching Brews found.
; @@ -97,13 +97,13 @@ const BrewCleanup = ({})=>{

Brew Cleanup

Removes very short brews to tidy up the database

- - {renderPrimed()} + {renderFound()} {error &&
{error.toString()}
} ; From fea86dc261caaa78f5d798f149d3a33c44f74723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 28 May 2026 10:36:35 +0200 Subject: [PATCH 03/11] add secondary pipeline --- server/admin.api.js | 46 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 60582b75f..e16024326 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -39,7 +39,17 @@ export default function createAdminApi(vite) { } }; - const junkBrewPipeline = [ + const junkBrewsPipeline = [ + { $match : { + updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, + lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } + } }, + { $project: { textBinSize: { $binarySize: '$textBin' } } }, + { $match: { textBinSize: { $lt: 140 } } }, + { $limit: 300 } + ]; + + const lostBrewsPipeline = [ { $match : { updatedAt : { $lt: Moment().subtract(365, 'days').toDate() }, lastViewed : { $lt: Moment().subtract(365, 'days').toDate() } @@ -55,9 +65,9 @@ export default function createAdminApi(vite) { 'text' : { '$exists': true } }).lean().limit(10000).select('_id'); - // Search for up to 100 brews that have not been viewed or updated in a year - router.get('/admin/cleanup', mw.adminOnly, (req, res)=>{ - HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) + // Search for up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes + router.get('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ + HomebrewModel.aggregate(junkBrewsPipeline).option({ maxTimeMS: 60000 }) .then((objs)=>res.json({ count: objs.length, brewCollection : objs })) .catch((error)=>{ console.error(error); @@ -65,8 +75,8 @@ export default function createAdminApi(vite) { }); }); - // Delete up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes - router.post('/admin/cleanup', mw.adminOnly, (req, res)=>{ + // Delete up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes + router.post('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ const ids = docs.map((doc)=>doc._id); @@ -79,6 +89,30 @@ export default function createAdminApi(vite) { }); }); + // Search for up to 300 unauthored brews that have not been viewed or updated in a year + router.get('/admin/cleanupLost', mw.adminOnly, (req, res)=>{ + HomebrewModel.aggregate(lostBrewsPipeline).option({ maxTimeMS: 60000 }) + .then((objs)=>res.json({ count: objs.length, brewCollection : objs })) + .catch((error)=>{ + console.error(error); + res.status(500).json({ error: 'Internal Server Error' }); + }); + }); + + // Delete up to 300 unauthored brews that have not been viewed or updated in a year + router.post('/admin/cleanupLost', mw.adminOnly, (req, res)=>{ + HomebrewModel.aggregate(lostBrewPipeline).option({ maxTimeMS: 60000 }) + .then((docs)=>{ + const ids = docs.map((doc)=>doc._id); + return HomebrewModel.deleteMany({ _id: { $in: ids } }); + }).then((result)=>{ + res.json({ count: result.deletedCount }); + }).catch((error)=>{ + console.error(error); + res.status(500).json({ error: 'Internal Server Error' }); + }); + }); + /* Searches for matching edit or share id, also attempts to partial match */ router.get('/admin/lookup/:id', mw.adminOnly, asyncHandler(HomebrewAPI.getBrew('admin', false)), async (req, res, next)=>{ return res.json(req.brew); From 1838a57e53ce15bc3836c91d5ee4f3e74185a5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 29 May 2026 11:32:09 +0200 Subject: [PATCH 04/11] final version --- .../brewUtils/brewCleanup/brewCleanup.jsx | 120 ++++++++++++------ server/admin.api.js | 8 +- 2 files changed, 87 insertions(+), 41 deletions(-) diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index be1ca0a51..cd60e6728 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -3,21 +3,29 @@ import request from 'superagent'; import Moment from 'moment'; const BrewCleanup = ({})=>{ - const [count, setCount] = useState(0); - const [brewCollection, setBrewCollection] = useState([]); + const [junkBrewCollection, setJunkBrewCollection] = useState([]); + const [lostBrewCollection, setLostBrewCollection] = useState([]); const [pending, setPending] = useState(false); - const [found, setFound] = useState(false); const [error, setError] = useState(null); - const find = async ()=>{ + const find = async (type)=>{ setPending(true); - try { - const res = await request.get('/admin/cleanup'); + if(type === 'junk') try { + const res = await request.get('/admin/cleanupJunk'); - setCount(res.body.count); - setBrewCollection(res.body.brewCollection); - setFound(true); + setJunkBrewCollection(res.body.brewCollection); + } catch (err) { + setError(err); + } finally { + setPending(false); + } + + if(type === 'lost') try { + + const res = await request.get('/admin/cleanupLost'); + + setLostBrewCollection(res.body.brewCollection); } catch (err) { setError(err); } finally { @@ -25,28 +33,42 @@ const BrewCleanup = ({})=>{ } }; - const cleanup = async ()=>{ + const cleanup = async (type)=>{ setPending(true); - try { - const res = await request.post('/admin/cleanup'); + if(type === 'junk') try { + console.log('deleting junk') + const res = await request.post('/admin/cleanupJunk'); - setCount(res.body.count); } catch (err) { setError(err); } finally { setPending(false); - setFound(false); + setJunkBrewCollection([]); + } + + if(type === 'lost') try { + const res = await request.post('/admin/cleanupLost'); + + } catch (err) { + setError(err); + } finally { + setPending(false); + setLostBrewCollection([]); } }; - const renderBrewList = ()=>{ - if(!brewCollection) { - console.log(brewCollection) + + const renderBrewList = (type)=>{ + + const brewList = type === 'lost' ? lostBrewCollection : junkBrewCollection; + + if(!brewList || brewList.length === 0) { + console.log(brewList); return null; } - + return <> -

{`Results - ${brewCollection.length} brews` }

+

{`Results - ${brewList.length} brews` }

@@ -57,7 +79,7 @@ const BrewCleanup = ({})=>{ - {brewCollection + {brewList .sort((a, b)=>{ // Sort brews from most recently updated if(a.updatedAt > b.updatedAt) return -1; return 1; @@ -65,8 +87,6 @@ const BrewCleanup = ({})=>{ .map((brew, idx)=>{ return - {// - } @@ -76,36 +96,60 @@ const BrewCleanup = ({})=>{
{brew.title || 'No Title'}{brew.shareId}{Moment(brew.updatedAt).fromNow()} {brew.createdAt ? Moment(brew.createdAt).fromNow() : 'No creation date'} {brew.googleId ? 'Google' : 'Homebrewery'}
; }; - const renderFound = ()=>{ - if(!found) return; + const renderFound = (type)=>{ - if(!count) return
No Matching Brews found.
; + if(type === 'junk' && junkBrewCollection.length === 0 || type === 'lost' && lostBrewCollection.length === 0) return
No Matching Brews found.
; return
- - Found {count} Brews that could be removed. - {renderBrewList()} + Found {type === 'junk' ? junkBrewCollection.length : lostBrewCollection.length} Brews that could be removed. + +
; + }; + const renderJunkBrewCleanup = ()=>{ + return
+

Junk brews

+

Removes very short brews to tidy up the database

+ + + {renderFound('junk')} + + {error &&
{error.toString()}
} +
; + }; + const renderLostBrewCleanup = ()=>{ + return
+

Lost brews

+

Removes very short brews to tidy up the database

+ + + {renderFound('lost')} + + {error &&
{error.toString()}
}
; }; return

Brew Cleanup

-

Removes very short brews to tidy up the database

+ {renderJunkBrewCleanup()} + {renderLostBrewCleanup()} - - {renderFound()} - - {error &&
{error.toString()}
}
; }; diff --git a/server/admin.api.js b/server/admin.api.js index e16024326..4033c30c6 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -44,7 +44,7 @@ export default function createAdminApi(vite) { updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } } }, - { $project: { textBinSize: { $binarySize: '$textBin' } } }, + { $project: { _id: 1, textBinSize: { $binarySize: '$textBin' } } }, { $match: { textBinSize: { $lt: 140 } } }, { $limit: 300 } ]; @@ -77,9 +77,11 @@ export default function createAdminApi(vite) { // Delete up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes router.post('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ - HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) + console.log('deleting'); + HomebrewModel.aggregate(junkBrewsPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ const ids = docs.map((doc)=>doc._id); + console.log(ids); return HomebrewModel.deleteMany({ _id: { $in: ids } }); }).then((result)=>{ res.json({ count: result.deletedCount }); @@ -101,7 +103,7 @@ export default function createAdminApi(vite) { // Delete up to 300 unauthored brews that have not been viewed or updated in a year router.post('/admin/cleanupLost', mw.adminOnly, (req, res)=>{ - HomebrewModel.aggregate(lostBrewPipeline).option({ maxTimeMS: 60000 }) + HomebrewModel.aggregate(lostBrewsPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ const ids = docs.map((doc)=>doc._id); return HomebrewModel.deleteMany({ _id: { $in: ids } }); From 55c4504ed97669a427aea3fbb0e400ddfd009b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 29 May 2026 11:32:31 +0200 Subject: [PATCH 05/11] remove logs --- server/admin.api.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 4033c30c6..c47e72c60 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -77,11 +77,9 @@ export default function createAdminApi(vite) { // Delete up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes router.post('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ - console.log('deleting'); HomebrewModel.aggregate(junkBrewsPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ const ids = docs.map((doc)=>doc._id); - console.log(ids); return HomebrewModel.deleteMany({ _id: { $in: ids } }); }).then((result)=>{ res.json({ count: result.deletedCount }); From ed6bf9f1bb983be303d371bdfdc2dfbe1bf24d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 30 May 2026 00:08:07 +0200 Subject: [PATCH 06/11] last changes --- client/admin/admin.less | 4 ++++ .../brewUtils/brewCleanup/brewCleanup.jsx | 11 ++++++----- server/admin.api.js | 18 ++++++++++-------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/client/admin/admin.less b/client/admin/admin.less index 432f92e8b..e66ead5e3 100644 --- a/client/admin/admin.less +++ b/client/admin/admin.less @@ -111,6 +111,10 @@ body { vertical-align : middle; text-align : center; border-right : 1px solid; + max-width:50ch; + overflow:hidden; + text-overflow: ellipsis; + white-space: nowrap; &:last-child { border-right : none; } } diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index cd60e6728..5f19fb474 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -67,6 +67,7 @@ const BrewCleanup = ({})=>{ return null; } + return <>

{`Results - ${brewList.length} brews` }

@@ -74,21 +75,21 @@ const BrewCleanup = ({})=>{ - + {brewList .sort((a, b)=>{ // Sort brews from most recently updated - if(a.updatedAt > b.updatedAt) return -1; + if(a.lastViewed > b.lastViewed) return -1; return 1; }) .map((brew, idx)=>{ return - + ; })} @@ -101,7 +102,7 @@ const BrewCleanup = ({})=>{ if(type === 'junk' && junkBrewCollection.length === 0 || type === 'lost' && lostBrewCollection.length === 0) return
No Matching Brews found.
; return
- {renderBrewList(type)} + Found {type === 'junk' ? junkBrewCollection.length : lostBrewCollection.length} Brews that could be removed. - + {renderBrewList(type)}
; }; const renderJunkBrewCleanup = ()=>{ diff --git a/server/admin.api.js b/server/admin.api.js index c47e72c60..161570dc2 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -50,14 +50,16 @@ export default function createAdminApi(vite) { ]; const lostBrewsPipeline = [ - { $match : { - updatedAt : { $lt: Moment().subtract(365, 'days').toDate() }, - lastViewed : { $lt: Moment().subtract(365, 'days').toDate() } - }}, - { $match: { - authors : [], - }}, - { $limit: 300 } + { + $match: { + authors: [], + updatedAt: { $lt: Moment().subtract(9, 'years').toDate() }, + lastViewed: { $lt: Moment().subtract(9, 'years').toDate() } + } + }, + { + $limit: 1000 + } ]; /* Search for brews that aren't compressed (missing the compressed text field) */ From b65105598a3e7b8db7d947df4f88f688d61ceda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 2 Jun 2026 14:34:18 +0200 Subject: [PATCH 07/11] going for 6 years for now --- client/admin/brewUtils/brewCleanup/brewCleanup.jsx | 2 +- server/admin.api.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index 5f19fb474..e2acb2a9d 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -89,7 +89,7 @@ const BrewCleanup = ({})=>{ return - + ; })} diff --git a/server/admin.api.js b/server/admin.api.js index 161570dc2..451e2aa83 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -53,12 +53,12 @@ export default function createAdminApi(vite) { { $match: { authors: [], - updatedAt: { $lt: Moment().subtract(9, 'years').toDate() }, - lastViewed: { $lt: Moment().subtract(9, 'years').toDate() } + updatedAt: { $lt: Moment().subtract(6, 'years').toDate() }, + lastViewed: { $lt: Moment().subtract(6, 'years').toDate() } } }, { - $limit: 1000 + $limit: 500 } ]; From e7ec8a2174240e67e36d8f952b313cd8212a0ccb Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 14 Jun 2026 22:34:07 +1200 Subject: [PATCH 08/11] Initial attempt at bug fix --- client/components/splitPane/splitPane.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/components/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx index 7cbfe2066..5eef6bd30 100644 --- a/client/components/splitPane/splitPane.jsx +++ b/client/components/splitPane/splitPane.jsx @@ -18,8 +18,7 @@ const SplitPane = (props)=>{ const [liveScroll, setLiveScroll] = useState(false); useEffect(()=>{ - const savedPos = window.localStorage.getItem(PANE_WIDTH_KEY); - setDividerPos(savedPos ? limitPosition(savedPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)) : window.innerWidth / 2); + handleResize(); setLiveScroll(window.localStorage.getItem(LIVE_SCROLL_KEY) === 'true'); window.addEventListener('resize', handleResize); @@ -29,7 +28,10 @@ const SplitPane = (props)=>{ const limitPosition = (x, min = 1, max = window.innerWidth - 13)=>Math.round(Math.min(max, Math.max(min, x))); //when resizing, the divider should grow smaller if less space is given, then grow back if the space is restored, to the original position - const handleResize = ()=>setDividerPos(limitPosition(window.localStorage.getItem(PANE_WIDTH_KEY), 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13))); + const handleResize = ()=>{ + const savedPos = window.localStorage.getItem(PANE_WIDTH_KEY); + setDividerPos(savedPos ? limitPosition(savedPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)) : window.innerWidth / 2); + }; const handleUp =(e)=>{ e.preventDefault(); From a645b614649e970d641b8f948f5e43c570c1bbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 17 Jun 2026 15:50:21 +0200 Subject: [PATCH 09/11] update comments --- server/admin.api.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/admin.api.js b/server/admin.api.js index 451e2aa83..1d9b5a2bd 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -38,7 +38,8 @@ export default function createAdminApi(vite) { throw { HBErrorCode: '52', code: 401, message: 'Access denied' }; } }; - + + // Search for up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes const junkBrewsPipeline = [ { $match : { updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, @@ -49,12 +50,13 @@ export default function createAdminApi(vite) { { $limit: 300 } ]; + // Search for up to 500 unauthored brews that have not been viewed or updated in two years const lostBrewsPipeline = [ { $match: { authors: [], - updatedAt: { $lt: Moment().subtract(6, 'years').toDate() }, - lastViewed: { $lt: Moment().subtract(6, 'years').toDate() } + updatedAt: { $lt: Moment().subtract(2, 'years').toDate() }, + lastViewed: { $lt: Moment().subtract(2, 'years').toDate() } } }, { @@ -67,7 +69,6 @@ export default function createAdminApi(vite) { 'text' : { '$exists': true } }).lean().limit(10000).select('_id'); - // Search for up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes router.get('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(junkBrewsPipeline).option({ maxTimeMS: 60000 }) .then((objs)=>res.json({ count: objs.length, brewCollection : objs })) @@ -77,7 +78,7 @@ export default function createAdminApi(vite) { }); }); - // Delete up to 300 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes + // Delete result of junkBrewsPipeline router.post('/admin/cleanupJunk', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(junkBrewsPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ @@ -91,7 +92,6 @@ export default function createAdminApi(vite) { }); }); - // Search for up to 300 unauthored brews that have not been viewed or updated in a year router.get('/admin/cleanupLost', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(lostBrewsPipeline).option({ maxTimeMS: 60000 }) .then((objs)=>res.json({ count: objs.length, brewCollection : objs })) @@ -101,7 +101,7 @@ export default function createAdminApi(vite) { }); }); - // Delete up to 300 unauthored brews that have not been viewed or updated in a year + // Delete result of lostBrewsPipeline router.post('/admin/cleanupLost', mw.adminOnly, (req, res)=>{ HomebrewModel.aggregate(lostBrewsPipeline).option({ maxTimeMS: 60000 }) .then((docs)=>{ From 515a59c9decdedff57eeea0eb42bcf0f4ca84e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 17 Jun 2026 15:59:42 +0200 Subject: [PATCH 10/11] updated fields to have proper data --- 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 1d9b5a2bd..d0676f47f 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -45,7 +45,7 @@ export default function createAdminApi(vite) { updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } } }, - { $project: { _id: 1, textBinSize: { $binarySize: '$textBin' } } }, + { $project: { _id: 1, textBinSize: { $binarySize: '$textBin' }, updatedAt: 1, lastViewed: 1} }, { $match: { textBinSize: { $lt: 140 } } }, { $limit: 300 } ]; From edf5a6f9e8e4237829978808ad141459a140db9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 17 Jun 2026 16:22:03 +0200 Subject: [PATCH 11/11] a few touches as gazook requested --- .../brewUtils/brewCleanup/brewCleanup.jsx | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx index e2acb2a9d..7d6c34f55 100644 --- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx +++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx @@ -5,71 +5,89 @@ import Moment from 'moment'; const BrewCleanup = ({})=>{ const [junkBrewCollection, setJunkBrewCollection] = useState([]); const [lostBrewCollection, setLostBrewCollection] = useState([]); - const [pending, setPending] = useState(false); + const [pendingJunk, setPendingJunk] = useState(false); + const [pendingLost, setPendingLost] = useState(false); const [error, setError] = useState(null); const find = async (type)=>{ - setPending(true); + if(type === 'junk') try { + setPendingJunk(true); const res = await request.get('/admin/cleanupJunk'); setJunkBrewCollection(res.body.brewCollection); } catch (err) { setError(err); } finally { - setPending(false); + setPendingJunk(false); } if(type === 'lost') try { - + setPendingLost(true); const res = await request.get('/admin/cleanupLost'); setLostBrewCollection(res.body.brewCollection); } catch (err) { setError(err); } finally { - setPending(false); + setPendingLost(false); } }; const cleanup = async (type)=>{ - setPending(true); if(type === 'junk') try { - console.log('deleting junk') + setPendingJunk(true); + console.log('deleting junk'); const res = await request.post('/admin/cleanupJunk'); } catch (err) { setError(err); } finally { - setPending(false); + setPendingJunk(false); setJunkBrewCollection([]); } if(type === 'lost') try { + setPendingLost(true); const res = await request.post('/admin/cleanupLost'); } catch (err) { setError(err); } finally { - setPending(false); + setPendingLost(false); setLostBrewCollection([]); } }; const renderBrewList = (type)=>{ - const brewList = type === 'lost' ? lostBrewCollection : junkBrewCollection; if(!brewList || brewList.length === 0) { - console.log(brewList); - return null; + return <> +

{`Results - No brews found` }

+
Title Last UpdateCreatedlast viewed Storage
{brew.title || 'No Title'} {Moment(brew.updatedAt).fromNow()}{brew.createdAt ? Moment(brew.createdAt).fromNow() : 'No creation date'}{brew.lastViewed ? Moment(brew.lastViewed).fromNow() : 'No creation date'} {brew.googleId ? 'Google' : 'Homebrewery'}
{brew.title || 'No Title'} {Moment(brew.updatedAt).fromNow()}{brew.lastViewed ? Moment(brew.lastViewed).fromNow() : 'No creation date'}{brew.lastViewed ? Moment(brew.lastViewed).fromNow() : 'No last viewed date'} {brew.googleId ? 'Google' : 'Homebrewery'}
+ + + + + + + + + + + + + +
TitleLast Updatelast viewedStorage
"No brews found"
+ ; } - - + console.log(type); + console.log(brewList); return <> -

{`Results - ${brewList.length} brews` }

+

{`Results - ${brewList.length} brews` }

@@ -91,35 +109,33 @@ const BrewCleanup = ({})=>{ - ; + })}
{Moment(brew.updatedAt).fromNow()} {brew.lastViewed ? Moment(brew.lastViewed).fromNow() : 'No last viewed date'} {brew.googleId ? 'Google' : 'Homebrewery'}
; }; const renderFound = (type)=>{ - - if(type === 'junk' && junkBrewCollection.length === 0 || type === 'lost' && lostBrewCollection.length === 0) return
No Matching Brews found.
; + const deleteButton = !(type === 'junk' && junkBrewCollection.length === 0 || type === 'lost' && lostBrewCollection.length === 0); return
- - - Found {type === 'junk' ? junkBrewCollection.length : lostBrewCollection.length} Brews that could be removed. + } {renderBrewList(type)}
; }; const renderJunkBrewCleanup = ()=>{ return

Junk brews

-

Removes very short brews to tidy up the database

+

Queries unauthored brews that have not been viewed or
updated in 30 days and are shorter than 140 bytes (up to 300)