diff --git a/client/homebrew/navbar/vault.navitem.jsx b/client/homebrew/navbar/vault.navitem.jsx
index 8752b8e0f..51c5c341d 100644
--- a/client/homebrew/navbar/vault.navitem.jsx
+++ b/client/homebrew/navbar/vault.navitem.jsx
@@ -2,11 +2,16 @@ const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
-module.exports = function(props){
- return
+ rel="noopener noreferrer"
+ >
Vault
+ );
};
diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx
index 59e831aa4..377260d0f 100644
--- a/client/homebrew/pages/vaultPage/vaultPage.jsx
+++ b/client/homebrew/pages/vaultPage/vaultPage.jsx
@@ -16,458 +16,458 @@ const SplitPane = require('../../../../shared/naturalcrit/splitPane/splitPane.js
const request = require('../../utils/request-middleware.js');
const VaultPage = (props) => {
- const [title, setTitle] = useState(props.query.title || '');
- //state author
- const [author, setAuthor] = useState(props.query.author || '');
- const [legacy, setLegacy] = useState(props.query.legacy !== 'false');
- const [v3, setV3] = useState(props.query.v3 !== 'false');
- const [count, setCount] = useState(props.query.count || 20);
- 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);
+ const [title, setTitle] = useState(props.query.title || '');
+ //state author
+ const [author, setAuthor] = useState(props.query.author || '');
+ const [legacy, setLegacy] = useState(props.query.legacy !== 'false');
+ const [v3, setV3] = useState(props.query.v3 !== 'false');
+ const [count, setCount] = useState(props.query.count || 20);
+ 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);
- const titleRef = useRef(null);
- const authorRef = useRef(null);
- const countRef = useRef(null);
- const v3Ref = useRef(null);
- const legacyRef = useRef(null);
- const searchButtonRef = useRef(null);
+ const titleRef = useRef(null);
+ const authorRef = useRef(null);
+ const countRef = useRef(null);
+ const v3Ref = useRef(null);
+ const legacyRef = useRef(null);
+ const searchButtonRef = useRef(null);
- useEffect(() => {
- disableSubmitIfFormInvalid();
- loadPage(page, false, true);
- }, []);
+ useEffect(() => {
+ disableSubmitIfFormInvalid();
+ loadPage(page, false, true);
+ }, []);
- const updateStateWithBrews = (brews, page) => {
- setBrewCollection(brews || null);
- setPage(parseInt(page) || 1);
- setSearching(false);
- };
+ const updateStateWithBrews = (brews, page) => {
+ setBrewCollection(brews || null);
+ setPage(parseInt(page) || 1);
+ setSearching(false);
+ };
- const updateUrl = (title, author, count, v3, legacy, page) => {
- const url = new URL(window.location.href);
- const urlParams = new URLSearchParams();
+ const updateUrl = (title, author, count, v3, legacy, page) => {
+ const url = new URL(window.location.href);
+ const urlParams = new URLSearchParams();
- Object.entries({
- title,
- author,
- count,
- v3,
- legacy,
- page,
- }).forEach(([key, value]) => urlParams.set(key, value));
+ Object.entries({
+ title,
+ author,
+ count,
+ v3,
+ legacy,
+ page,
+ }).forEach(([key, value]) => urlParams.set(key, value));
- url.search = urlParams.toString();
- window.history.replaceState(null, null, url);
- };
+ url.search = urlParams.toString();
+ window.history.replaceState(null, null, url);
+ };
- const loadPage = async (page, update, total) => {
- //Different searches use the update or total props to make only the necessary queries and functions
+ const loadPage = async (page, update, total) => {
+ //Different searches use the update or total props to make only the necessary queries and functions
- if (!validateForm()) {
- return;
- }
+ if (!validateForm()) {
+ return;
+ }
- setSearching(true);
- setError(null);
+ setSearching(true);
+ setError(null);
- const performSearch = async ({ title, author, count, v3, legacy }) => {
- updateUrl(title, author, count, v3, legacy, page);
- console.log(title, author, count, v3, legacy);
- if ((title || author) && (v3 || legacy)) {
- try {
- const response = await request.get(
- `/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}`
- );
- if (response.ok) {
- updateStateWithBrews(response.body.brews, page);
- } else {
- throw new Error(`Error: ${response.status}`);
- }
- } catch (error) {
- console.log('error at loadPage: ', error);
- setError(
- `${
- error.response
- ? error.response.status
- : error.message
- }`
- );
- updateStateWithBrews([], 1);
- }
- } else {
- setError('404');
- }
- };
+ const performSearch = async ({ title, author, count, v3, legacy }) => {
+ updateUrl(title, author, count, v3, legacy, page);
+ console.log(title, author, count, v3, legacy);
+ if ((title || author) && (v3 || legacy)) {
+ try {
+ const response = await request.get(
+ `/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}`
+ );
+ if (response.ok) {
+ updateStateWithBrews(response.body.brews, page);
+ } else {
+ throw new Error(`Error: ${response.status}`);
+ }
+ } catch (error) {
+ console.log('error at loadPage: ', error);
+ setError(
+ `${
+ error.response
+ ? error.response.status
+ : error.message
+ }`
+ );
+ updateStateWithBrews([], 1);
+ }
+ } else {
+ setError('404');
+ }
+ };
- const loadTotal = async ({ title, v3, legacy }) => {
- setTotalBrews(null);
- setError(null);
- if ((title || author) && (v3 || legacy)) {
- try {
- const response = await request.get(
- `/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}`
- );
+ const loadTotal = async ({ title, v3, legacy }) => {
+ setTotalBrews(null);
+ setError(null);
+ if ((title || author) && (v3 || legacy)) {
+ try {
+ const response = await request.get(
+ `/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}`
+ );
- if (response.ok) {
- setTotalBrews(response.body.totalBrews);
- } else {
- throw new Error(
- `Failed to load total brews: ${response.statusText}`
- );
- }
- } catch (error) {
- console.log('error at loadTotal: ', error);
- setError(`${error.response.status}`);
- updateStateWithBrews([], 1);
- }
- }
- };
+ if (response.ok) {
+ setTotalBrews(response.body.totalBrews);
+ } else {
+ throw new Error(
+ `Failed to load total brews: ${response.statusText}`
+ );
+ }
+ } catch (error) {
+ console.log('error at loadTotal: ', error);
+ setError(`${error.response.status}`);
+ updateStateWithBrews([], 1);
+ }
+ }
+ };
- const title = titleRef.current.value || '';
- const author = authorRef.current.value || '';
- const count = countRef.current.value || 10;
- const v3 = v3Ref.current.checked != false;
- const legacy = legacyRef.current.checked != false;
+ const title = titleRef.current.value || '';
+ const author = authorRef.current.value || '';
+ const count = countRef.current.value || 10;
+ const v3 = v3Ref.current.checked != false;
+ const legacy = legacyRef.current.checked != false;
- console.log(title);
- if (update) {
- setTitle(title);
- setAuthor(author);
- setCount(count);
- setV3(v3);
- setLegacy(legacy);
- }
+ console.log(title);
+ if (update) {
+ setTitle(title);
+ setAuthor(author);
+ setCount(count);
+ setV3(v3);
+ setLegacy(legacy);
+ }
- // Perform search with the latest input values, because state is not fast enough
- performSearch({ title, author, count, v3, legacy });
+ // Perform search with the latest input values, because state is not fast enough
+ performSearch({ title, author, count, v3, legacy });
- if (total) {
- loadTotal({ title, author, v3, legacy });
- }
- };
+ if (total) {
+ loadTotal({ title, author, v3, legacy });
+ }
+ };
- const renderNavItems = () => (
-
-
-
- Vault: Search for brews
-
-
-
-
-
-
-
-
-
- );
+ const renderNavItems = () => (
+
+
+
+ Vault: Search for brews
+
+
+
+
+
+
+
+
+
+ );
- const validateForm = () => {
- //form validity: title or author must be written, and at least one renderer set
- const { current: titleInput } = titleRef;
- const { current: legacyCheckbox } = legacyRef;
- const { current: v3Checkbox } = v3Ref;
- const { current: authorInput } = authorRef;
+ const validateForm = () => {
+ //form validity: title or author must be written, and at least one renderer set
+ const { current: titleInput } = titleRef;
+ const { current: legacyCheckbox } = legacyRef;
+ const { current: v3Checkbox } = v3Ref;
+ const { current: authorInput } = authorRef;
- const isTitleValid = titleInput.validity.valid && titleInput.value;
- //because a pattern attr is set in the input, title must be over 2 chars long
- const isAuthorValid = authorInput.validity.valid && authorInput.value;
- const isCheckboxChecked = legacyCheckbox.checked || v3Checkbox.checked;
+ const isTitleValid = titleInput.validity.valid && titleInput.value;
+ //because a pattern attr is set in the input, title must be over 2 chars long
+ const isAuthorValid = authorInput.validity.valid && authorInput.value;
+ const isCheckboxChecked = legacyCheckbox.checked || v3Checkbox.checked;
- const isFormValid =
- (isTitleValid || isAuthorValid) && isCheckboxChecked;
+ const isFormValid =
+ (isTitleValid || isAuthorValid) && isCheckboxChecked;
- return isFormValid;
- };
+ return isFormValid;
+ };
- const disableSubmitIfFormInvalid = () => {
- const { current: submitButton } = searchButtonRef;
- submitButton.disabled = !validateForm();
- };
+ const disableSubmitIfFormInvalid = () => {
+ const { current: submitButton } = searchButtonRef;
+ submitButton.disabled = !validateForm();
+ };
- const renderForm = () => (
-
-
Brew Lookup
-
-
- Title of the brew
- {
- if (e.key === 'Enter') {
- if (!searchButtonRef.current.disabled) {
- loadPage(1, true, true);
- }
- }
- }}
- placeholder="v3 Reference Document"
- />
-
+ const renderForm = () => (
+
+
Brew Lookup
+
+
+ Title of the brew
+ {
+ if (e.key === 'Enter') {
+ if (!searchButtonRef.current.disabled) {
+ loadPage(1, true, true);
+ }
+ }
+ }}
+ placeholder="v3 Reference Document"
+ />
+
-
- Author of the brew
- {
- if (e.key === 'Enter') {
- if (!searchButtonRef.current.disabled) {
- loadPage(1, true, true);
- }
- }
- }}
- placeholder="Gazook89"
- />
-
+
+ Author of the brew
+ {
+ if (e.key === 'Enter') {
+ if (!searchButtonRef.current.disabled) {
+ loadPage(1, true, true);
+ }
+ }
+ }}
+ placeholder="Gazook89"
+ />
+
-
- Results per page
-
- 10
- 20
- 40
- 60
-
-
+
+ Results per page
+
+ 10
+ 20
+ 40
+ 60
+
+
-
-
- Search for v3 brews
-
+
+
+ Search for v3 brews
+
-
-
- Search for legacy brews
-
+
+
+ Search for legacy brews
+
- {
- loadPage(1, true, true);
- }}
- >
- Search
-
-
-
-
- Tips and tricks
-
-
- You can only search brews with this tool if they are
- published
-
-
- Usernames are case sensitive, make sure you are writing
- it correctly
-
-
- You can use - to negate words, assuming
- there is any word not negated, and "word"
- to specify an exact string.
-
+ {
+ loadPage(1, true, true);
+ }}
+ >
+ Search
+
+
+
+
+ Tips and tricks
+
+
+ You can only search brews with this tool if they are
+ published
+
+
+ Usernames are case sensitive, make sure you are writing
+ it correctly
+
+
+ You can use - to negate words, assuming
+ there is any word not negated, and "word"
+ to specify an exact string.
+
-
- Some words like a, after, through, itself, or here, are
- ignored in searches, make sure your search has relevant
- words. The full list can be found
-
- here
-
-
-
-
-
-
- );
+
+ Some words like a, after, through, itself, or here, are
+ ignored in searches, make sure your search has relevant
+ words. The full list can be found
+
+ here
+
+
+
+
+
+
+ );
- const renderPaginationControls = () => {
- if (!totalBrews) return null;
+ const renderPaginationControls = () => {
+ if (!totalBrews) return null;
- const countInt = parseInt(count);
- const totalPages = Math.ceil(totalBrews / countInt);
+ const countInt = parseInt(count);
+ const totalPages = Math.ceil(totalBrews / countInt);
- 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;
- }
+ 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) => (
- loadPage(startPage + index, false, false)}
- >
- {startPage + index}
-
- ));
+ const pagesAroundCurrent = new Array(endPage - startPage + 1)
+ .fill()
+ .map((_, index) => (
+ loadPage(startPage + index, false, false)}
+ >
+ {startPage + index}
+
+ ));
- return (
-
- );
- };
+ return (
+
+ );
+ };
- const renderFoundBrews = () => {
- if (searching) {
- return (
-
-
Searching
-
- );
- }
+ const renderFoundBrews = () => {
+ 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 - 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';
- }
+ 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 - 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';
+ }
- return (
-
-
Error: {errorMessage}
-
- );
- }
+ return (
+
+
Error: {errorMessage}
+
+ );
+ }
- if (!brewCollection) {
- return (
-
-
No search yet
-
- );
- }
+ if (!brewCollection) {
+ return (
+
+
No search yet
+
+ );
+ }
- if (brewCollection.length === 0) {
- return (
-
-
No brews found
-
- );
- }
+ if (brewCollection.length === 0) {
+ return (
+
+
No brews found
+
+ );
+ }
- return (
-
-
- {`Brews found: `}
- {totalBrews}
-
- {brewCollection.map((brew, index) => (
-
- ))}
- {renderPaginationControls()}
-
- );
- };
+ return (
+
+
+ {`Brews found: `}
+ {totalBrews}
+
+ {brewCollection.map((brew, index) => (
+
+ ))}
+ {renderPaginationControls()}
+
+ );
+ };
- return (
-
-
-
- {renderNavItems()}
-
-
- {renderForm()}
+ return (
+
+
+
+ {renderNavItems()}
+
+
+ {renderForm()}
-
- {renderFoundBrews()}
-
-
-
-
- );
+
+ {renderFoundBrews()}
+
+
+
+
+ );
};
module.exports = VaultPage;
diff --git a/server/vault.api.js b/server/vault.api.js
index 996ccf536..6a5b58140 100644
--- a/server/vault.api.js
+++ b/server/vault.api.js
@@ -5,121 +5,121 @@ const HomebrewModel = require('./homebrew.model.js').model;
const router = express.Router();
const buildTitleConditions = (title) => {
- if (!title) return {};
- return {
- $text: {
- $search: title,
- $caseSensitive: false,
- },
- };
+ if (!title) return {};
+ return {
+ $text: {
+ $search: title,
+ $caseSensitive: false,
+ },
+ };
};
const buildAuthorConditions = (author) => {
- if (!author) return {};
- return { authors: author };
+ if (!author) return {};
+ return { authors: author };
};
//"$and": [ {"published": true}, {"$text": { "$search": "titleString", "$caseSensitive": false } }, { "authors" : "authorString"}]
//is a good example of a query constructed with this function
const handleErrorResponse = (res, error, functionName) => {
- const status = error.response?.status || 500;
- const message =
- status === 503 ? 'Service Unavailable' : 'Internal Server Error';
+ const status = error.response?.status || 500;
+ const message =
+ status === 503 ? 'Service Unavailable' : 'Internal Server Error';
- console.error(`Error in ${functionName}:`, error);
+ console.error(`Error in ${functionName}:`, error);
- return res.status(status).json({
- errorCode: status.toString(),
- message: `Error in function ${functionName}: ${message}`,
- });
+ return res.status(status).json({
+ errorCode: status.toString(),
+ message: `Error in function ${functionName}: ${message}`,
+ });
};
const buildBrewsQuery = (legacy, v3) => {
- const brewsQuery = { published: true };
- if (legacy === 'true' && v3 === 'true') return { published: true };
+ const brewsQuery = { published: true };
+ if (legacy === 'true' && v3 === 'true') return { published: true };
- if (legacy === 'true' && v3 !== 'true') {
- brewsQuery.renderer = 'legacy';
- } else if (v3 === 'true' && legacy !== 'true') {
- brewsQuery.renderer = 'V3';
- }
+ if (legacy === 'true' && v3 !== 'true') {
+ brewsQuery.renderer = 'legacy';
+ } else if (v3 === 'true' && legacy !== 'true') {
+ brewsQuery.renderer = 'V3';
+ }
- return brewsQuery;
+ return brewsQuery;
};
const vault = {
- findBrews: async (req, res) => {
- try {
- const title = req.query.title || '';
- const author = req.query.author || '';
- const page = Math.max(parseInt(req.query.page) || 1, 1);
- const mincount = 10;
- const count = Math.max(parseInt(req.query.count) || 20, mincount);
- const skip = (page - 1) * count;
+ findBrews: async (req, res) => {
+ try {
+ const title = req.query.title || '';
+ const author = req.query.author || '';
+ const page = Math.max(parseInt(req.query.page) || 1, 1);
+ const mincount = 10;
+ const count = Math.max(parseInt(req.query.count) || 20, mincount);
+ const skip = (page - 1) * count;
- const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3);
- const titleConditions = buildTitleConditions(title);
- const authorConditions = buildAuthorConditions(author);
+ const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3);
+ const titleConditions = buildTitleConditions(title);
+ const authorConditions = buildAuthorConditions(author);
- const combinedQuery = {
- $and: [brewsQuery, titleConditions, authorConditions],
- };
+ const combinedQuery = {
+ $and: [brewsQuery, titleConditions, authorConditions],
+ };
- const projection = {
- editId: 0,
- googleId: 0,
- text: 0,
- textBin: 0,
- version: 0,
- thumbnail: 0,
- };
+ const projection = {
+ editId: 0,
+ googleId: 0,
+ text: 0,
+ textBin: 0,
+ version: 0,
+ thumbnail: 0,
+ };
- const brews = await HomebrewModel.find(combinedQuery, projection)
- .skip(skip)
- .limit(count)
- .maxTimeMS(5000)
- .exec();
+ const brews = await HomebrewModel.find(combinedQuery, projection)
+ .skip(skip)
+ .limit(count)
+ .maxTimeMS(5000)
+ .exec();
- console.log(
- 'Query in findBrews: ',
- JSON.stringify(combinedQuery, null, 2)
- );
- return res.json({ brews, page });
- } catch (error) {
- console.error(error);
- return handleErrorResponse(res, error, 'findBrews');
- }
- },
+ console.log(
+ 'Query in findBrews: ',
+ JSON.stringify(combinedQuery, null, 2)
+ );
+ return res.json({ brews, page });
+ } catch (error) {
+ console.error(error);
+ return handleErrorResponse(res, error, 'findBrews');
+ }
+ },
- findTotal: async (req, res) => {
- try {
- const title = req.query.title || '';
- const author = req.query.author || '';
+ findTotal: async (req, res) => {
+ try {
+ const title = req.query.title || '';
+ const author = req.query.author || '';
- const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3);
- const titleConditions = buildTitleConditions(title);
- const authorConditions = buildAuthorConditions(author);
+ const brewsQuery = buildBrewsQuery(req.query.legacy, req.query.v3);
+ const titleConditions = buildTitleConditions(title);
+ const authorConditions = buildAuthorConditions(author);
- const combinedQuery = {
- $and: [brewsQuery, titleConditions, authorConditions],
- };
+ const combinedQuery = {
+ $and: [brewsQuery, titleConditions, authorConditions],
+ };
- const totalBrews = await HomebrewModel.countDocuments(
- combinedQuery
- );
- console.log(
- 'when returning, the total of brews is ',
- totalBrews,
- 'for the query',
- JSON.stringify(combinedQuery)
- );
- return res.json({ totalBrews });
- } catch (error) {
- console.error(error);
- return handleErrorResponse(res, error, 'findTotal');
- }
- },
+ const totalBrews = await HomebrewModel.countDocuments(
+ combinedQuery
+ );
+ console.log(
+ 'when returning, the total of brews is ',
+ totalBrews,
+ 'for the query',
+ JSON.stringify(combinedQuery)
+ );
+ return res.json({ totalBrews });
+ } catch (error) {
+ console.error(error);
+ return handleErrorResponse(res, error, 'findTotal');
+ }
+ },
};
router.get('/api/vault/total', asyncHandler(vault.findTotal));