From 6d2cbaacc04e068c77e7c70f3f10e1f8945a26fc Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 5 Feb 2025 21:35:21 +1300 Subject: [PATCH 1/6] Add Admin API for getByUser --- server/admin.api.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/server/admin.api.js b/server/admin.api.js index 1a39f020b..a7d1d9811 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -93,7 +93,7 @@ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ /* Cleans `` from the "text" field of a brew */ router.put('/admin/clean/script/:id', asyncHandler(HomebrewAPI.getBrew('admin', false)), async (req, res)=>{ - console.log(`[ADMIN] Cleaning script tags from ShareID ${req.params.id}`); + console.log(`[ADMIN: ${req.account?.username || 'Not Logged In'}] Cleaning script tags from ShareID ${req.params.id}`); function cleanText(text){return text.replaceAll(/(<\/?s)cript/gi, '');}; @@ -114,6 +114,18 @@ router.put('/admin/clean/script/:id', asyncHandler(HomebrewAPI.getBrew('admin', return await HomebrewAPI.updateBrew(req, res); }); +/* Get list of a user's documents */ +router.get('/admin/user/list/:user', mw.adminOnly, async (req, res)=>{ + const username = req.params.user; + const fields = { _id: 0, text: 0, textBin: 0 }; // Remove unnecessary fields from document lists + + console.log(`[ADMIN: ${req.account?.username || 'Not Logged In'}] Get brew list for ${username}`); + + const brews = await HomebrewModel.getByUser(username, true, fields); + + return res.json(brews); +}); + /* Compresses the "text" field of a brew to binary */ router.put('/admin/compress/:id', (req, res)=>{ HomebrewModel.findOne({ _id: req.params.id }) From 03798e945dc4e69845e6da1b456c52afba8e7dbc Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 5 Feb 2025 21:35:33 +1300 Subject: [PATCH 2/6] Add UI --- client/admin/admin.jsx | 4 +- .../authorUtils/authorLookup/authorLookup.jsx | 90 +++++++++++++++++++ .../authorLookup/authorLookup.less | 48 ++++++++++ client/admin/authorUtils/authorUtils.jsx | 13 +++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 client/admin/authorUtils/authorLookup/authorLookup.jsx create mode 100644 client/admin/authorUtils/authorLookup/authorLookup.less create mode 100644 client/admin/authorUtils/authorUtils.jsx diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index f2f2667a4..c24f7f176 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -4,8 +4,9 @@ const createClass = require('create-react-class'); const BrewUtils = require('./brewUtils/brewUtils.jsx'); const NotificationUtils = require('./notificationUtils/notificationUtils.jsx'); +import AuthorUtils from './authorUtils/authorUtils.jsx'; -const tabGroups = ['brew', 'notifications']; +const tabGroups = ['brew', 'notifications', 'authors']; const Admin = createClass({ getDefaultProps : function() { @@ -39,6 +40,7 @@ const Admin = createClass({ {this.state.currentTab==='brew' && } {this.state.currentTab==='notifications' && } + {this.state.currentTab==='authors' && } ; } diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx new file mode 100644 index 000000000..50226d93d --- /dev/null +++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx @@ -0,0 +1,90 @@ +import './authorLookup.less'; + +import React from 'react'; +import request from 'superagent'; + +const authorLookup = ()=>{ + const [author, setAuthor] = React.useState(''); + const [searching, setSearching] = React.useState(false); + const [results, setResults] = React.useState([]); + + const lookup = async ()=>{ + if(!author) return; + + setSearching(true); + setResults([]); + + await request.get(`/admin/user/list/${author}`) + .then((brews)=>{ + setResults(brews.body); + setSearching(false); + }); + }; + + const renderResults = ()=>{ + if(results.length == 0) return <> +

Results

+

None found.

+ ; + + return <> +

{`Results - ${results.length}`}

+ + + + + + + + + + + + {results + .sort((a, b)=>{ // Sort brews from most recently updated + if(a.updatedAt > b.updatedAt) return -1; + if(a.updatedAt < b.updatedAt) return 1; + return 0; + }) + .map((brew, idx)=>{ + return + + + + + + ; + })} + +
TitleShareEditLast UpdateStorage
{brew.title}{brew.shareId}{brew.editId}{brew.updatedAt}{brew.googleId ? 'Google' : 'Homebrewery'}
+ ; + }; + + const handleKeyPress = (evt)=>{ + if(evt.key === 'Enter') return lookup(); + }; + + const handleChange = (evt)=>{ + setAuthor(evt.target.value); + }; + + return ( +
+
+

Author Lookup

+ +
+
+ {renderResults()} +
+
+ ); +}; + +module.exports = authorLookup; diff --git a/client/admin/authorUtils/authorLookup/authorLookup.less b/client/admin/authorUtils/authorLookup/authorLookup.less new file mode 100644 index 000000000..7f6903aa5 --- /dev/null +++ b/client/admin/authorUtils/authorLookup/authorLookup.less @@ -0,0 +1,48 @@ +.authorLookup { + position : relative; + display : flex; + flex-direction : column; + + .field { + display : flex; + gap : 5px; + align-items : center; + justify-items : stretch; + width : 100%; + margin-bottom : 20px; + + + input { + height : 33px; + padding : 0px 10px; + margin-bottom : unset; + font-family : monospace; + } + + button { + width: 50px; + + i { margin-right : 10px; } + } + } + + table.resultsTable { + * { + border: 1px solid black; + vertical-align: middle; + padding: 5px; + } + + th { + font-weight: bold; + } + + th, td { + text-align: center; + + &:first-of-type { + text-align: left; + } + } + } +} \ No newline at end of file diff --git a/client/admin/authorUtils/authorUtils.jsx b/client/admin/authorUtils/authorUtils.jsx new file mode 100644 index 000000000..a96eea528 --- /dev/null +++ b/client/admin/authorUtils/authorUtils.jsx @@ -0,0 +1,13 @@ +import React from 'react'; + +import AuthorLookup from './authorLookup/authorLookup.jsx'; + +const authorUtils = ()=>{ + return ( +
+ +
+ ); +}; + +module.exports = authorUtils; \ No newline at end of file From e89920bd1e0a3949f56b9218dde87eb9fdc703b2 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Feb 2025 07:41:53 +1300 Subject: [PATCH 3/6] Remove unneeded `.then()` Co-authored-by: Trevor Buckner --- client/admin/authorUtils/authorLookup/authorLookup.jsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx index 50226d93d..b5b7735e7 100644 --- a/client/admin/authorUtils/authorLookup/authorLookup.jsx +++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx @@ -14,12 +14,9 @@ const authorLookup = ()=>{ setSearching(true); setResults([]); - await request.get(`/admin/user/list/${author}`) - .then((brews)=>{ - setResults(brews.body); - setSearching(false); - }); - }; + const brews = await request.get(`/admin/user/list/${author}`); + setResults(brews.body); + setSearching(false); const renderResults = ()=>{ if(results.length == 0) return <> From bbc601cf47d8d7bd1e52944709a9fb229dc099e5 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Feb 2025 07:42:35 +1300 Subject: [PATCH 4/6] Simplify sort algorithm Co-authored-by: Trevor Buckner --- client/admin/authorUtils/authorLookup/authorLookup.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx index b5b7735e7..8cbe31176 100644 --- a/client/admin/authorUtils/authorLookup/authorLookup.jsx +++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx @@ -40,8 +40,7 @@ const authorLookup = ()=>{ {results .sort((a, b)=>{ // Sort brews from most recently updated if(a.updatedAt > b.updatedAt) return -1; - if(a.updatedAt < b.updatedAt) return 1; - return 0; + return 1; }) .map((brew, idx)=>{ return From d48d5260a4f5b044befa03e830921a37efc89710 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Feb 2025 07:54:15 +1300 Subject: [PATCH 5/6] Fix missing } --- client/admin/authorUtils/authorLookup/authorLookup.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx index 8cbe31176..d4d117147 100644 --- a/client/admin/authorUtils/authorLookup/authorLookup.jsx +++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx @@ -17,6 +17,7 @@ const authorLookup = ()=>{ const brews = await request.get(`/admin/user/list/${author}`); setResults(brews.body); setSearching(false); + }; const renderResults = ()=>{ if(results.length == 0) return <> From 64b7527ad0fcd3fa2b5bc18d1bd577246f505b68 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 12 Feb 2025 08:01:07 +1300 Subject: [PATCH 6/6] Convert space indentation to tabs --- .../authorUtils/authorLookup/authorLookup.jsx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx index d4d117147..a239f901f 100644 --- a/client/admin/authorUtils/authorLookup/authorLookup.jsx +++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx @@ -39,19 +39,19 @@ const authorLookup = ()=>{ {results - .sort((a, b)=>{ // Sort brews from most recently updated - if(a.updatedAt > b.updatedAt) return -1; - return 1; - }) - .map((brew, idx)=>{ - return - {brew.title} - {brew.shareId} - {brew.editId} - {brew.updatedAt} - {brew.googleId ? 'Google' : 'Homebrewery'} - ; - })} + .sort((a, b)=>{ // Sort brews from most recently updated + if(a.updatedAt > b.updatedAt) return -1; + return 1; + }) + .map((brew, idx)=>{ + return + {brew.title} + {brew.shareId} + {brew.editId} + {brew.updatedAt} + {brew.googleId ? 'Google' : 'Homebrewery'} + ; + })} ; @@ -70,7 +70,7 @@ const authorLookup = ()=>{

Author Lookup