mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-27 22:33:07 +00:00
Compare commits
294 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ede3d7cf3 | ||
|
|
e56b2a7ce5 | ||
|
|
ad8e004fa9 | ||
|
|
e05d2e805c | ||
|
|
a083999943 | ||
|
|
247bc719b8 | ||
|
|
cd01014d79 | ||
|
|
7ab1efb0c9 | ||
|
|
eb05ac00a6 | ||
|
|
2bc39a468f | ||
|
|
c735ab7c35 | ||
|
|
d5e367649e | ||
|
|
f10444f14a | ||
|
|
29d4003bd2 | ||
|
|
1225e5cb6a | ||
|
|
aab24c732e | ||
|
|
d7d690a9d1 | ||
|
|
4f39222724 | ||
|
|
a1e585ccaa | ||
|
|
373a627c14 | ||
|
|
a7cb73b02e | ||
|
|
cd3e517b03 | ||
|
|
ef201409d9 | ||
|
|
e3ef93f03a | ||
|
|
1990064be4 | ||
|
|
44099c813c | ||
|
|
56185e2a1c | ||
|
|
590318ff1d | ||
|
|
48a5a70d2e | ||
|
|
1c1901c90a | ||
|
|
ebae351033 | ||
|
|
e54d81ceef | ||
|
|
849da23829 | ||
|
|
1e36e63ed6 | ||
|
|
abb2d57879 | ||
|
|
52779eec35 | ||
|
|
9e694e5e46 | ||
|
|
321b8a0696 | ||
|
|
f2563e436f | ||
|
|
3c6f49aa0a | ||
|
|
9bc5701006 | ||
|
|
a3a5f749ab | ||
|
|
36b026d89e | ||
|
|
dbd4a5c490 | ||
|
|
0d95c48988 | ||
|
|
0d40f4eb16 | ||
|
|
6234943ffd | ||
|
|
702f55bdbd | ||
|
|
859117cdf8 | ||
|
|
7474605b93 | ||
|
|
00a83ec16e | ||
|
|
afa1e7974a | ||
|
|
1517c00132 | ||
|
|
6d24908465 | ||
|
|
fd2d1f1ce2 | ||
|
|
226ad49663 | ||
|
|
e830c51a16 | ||
|
|
b6e904c9c8 | ||
|
|
3fc2e5202e | ||
|
|
f0b447866c | ||
|
|
c528c8639a | ||
|
|
47d8bb20d2 | ||
|
|
bb08aed1a8 | ||
|
|
9a2f18fc0d | ||
|
|
df21f978df | ||
|
|
fb8c4c5c44 | ||
|
|
19102db23a | ||
|
|
8d2a9ed9cb | ||
|
|
a0010c9c84 | ||
|
|
f7c3e81b7b | ||
|
|
c7f695e86a | ||
|
|
e6e220fbec | ||
|
|
8658a6a97a | ||
|
|
cd94857b13 | ||
|
|
3825bcbbfb | ||
|
|
981e7986ce | ||
|
|
89583528c2 | ||
|
|
e588e68313 | ||
|
|
e4c2ffe973 | ||
|
|
c41116e6c8 | ||
|
|
b66ac43b35 | ||
|
|
c30404804d | ||
|
|
6b10e1aacb | ||
|
|
e6185879c8 | ||
|
|
e776e5e054 | ||
|
|
04bbb3d615 | ||
|
|
5d1f589b07 | ||
|
|
ce5f093945 | ||
|
|
371e464eb2 | ||
|
|
804d714473 | ||
|
|
8d00389aa2 | ||
|
|
d64787168b | ||
|
|
49a1a74263 | ||
|
|
2636635397 | ||
|
|
c49c620ce1 | ||
|
|
0b00162590 | ||
|
|
5e19bdaee7 | ||
|
|
bda8be6ec1 | ||
|
|
132a7d1f53 | ||
|
|
2dbb92a37e | ||
|
|
a124bd8657 | ||
|
|
5323e6ca7a | ||
|
|
8423c48fd1 | ||
|
|
e8aceac133 | ||
|
|
5a692a74c5 | ||
|
|
6436e62ec0 | ||
|
|
c9947d7f91 | ||
|
|
3b3127248b | ||
|
|
1d2355e802 | ||
|
|
b85bb7bdd4 | ||
|
|
5e69718f4f | ||
|
|
fc294807fd | ||
|
|
dc7d877e6f | ||
|
|
d8f0618691 | ||
|
|
955b34b637 | ||
|
|
8dea2ca9fb | ||
|
|
696bcd4367 | ||
|
|
c6f87eded0 | ||
|
|
62b96f4e79 | ||
|
|
8faae1e645 | ||
|
|
e4852b7077 | ||
|
|
2dc4ebb39f | ||
|
|
59672b79d8 | ||
|
|
59717fe630 | ||
|
|
3f9c7a1794 | ||
|
|
ca1f2dd1c3 | ||
|
|
a8e6f5cf26 | ||
|
|
f3a774d55c | ||
|
|
834980890a | ||
|
|
969eb354ce | ||
|
|
9288ead130 | ||
|
|
a8a4930225 | ||
|
|
2bc7cda8c9 | ||
|
|
f1ab332ce0 | ||
|
|
d50f23354a | ||
|
|
662a2d776a | ||
|
|
80f07bf0b0 | ||
|
|
6cf2dd8186 | ||
|
|
5de20cb451 | ||
|
|
aa0d0bed48 | ||
|
|
c92f30cfe0 | ||
|
|
2a8e4b2a63 | ||
|
|
51c7549b45 | ||
|
|
ea5170e6a6 | ||
|
|
cef90f5ff9 | ||
|
|
5a9b77190a | ||
|
|
59a5f641af | ||
|
|
0bda666127 | ||
|
|
5b96ef4406 | ||
|
|
af5bbdc677 | ||
|
|
c1dc712542 | ||
|
|
3e2c2de269 | ||
|
|
cc08579583 | ||
|
|
e562ebef48 | ||
|
|
e206b501a6 | ||
|
|
016a9fa1e8 | ||
|
|
01ee184044 | ||
|
|
ddf2006285 | ||
|
|
5232c16eb2 | ||
|
|
bdfd194672 | ||
|
|
cb0cb32860 | ||
|
|
1e080b30fd | ||
|
|
90431efbc9 | ||
|
|
99b0c2b54e | ||
|
|
042e217872 | ||
|
|
609f5a3330 | ||
|
|
058d70ed82 | ||
|
|
cbdf06f39d | ||
|
|
6f6c142aa2 | ||
|
|
72cb8e7db9 | ||
|
|
133295c225 | ||
|
|
54efc18ad4 | ||
|
|
43f77dc525 | ||
|
|
34d37b24f1 | ||
|
|
1e6427ca56 | ||
|
|
b9152867b8 | ||
|
|
879a1f5a57 | ||
|
|
0f9ba1a5ae | ||
|
|
d96d3c501e | ||
|
|
215888baf4 | ||
|
|
d56ea62b5e | ||
|
|
888cf55b3d | ||
|
|
4d7b1864d9 | ||
|
|
319746f6cd | ||
|
|
8fd165a79b | ||
|
|
ecfdada810 | ||
|
|
68c3e1ba84 | ||
|
|
efda06ebe5 | ||
|
|
e9b85e1a9a | ||
|
|
f9d19c75b2 | ||
|
|
21244fba58 | ||
|
|
55dd4efe41 | ||
|
|
6e08fcca80 | ||
|
|
3d0a9ea805 | ||
|
|
a711f8eb89 | ||
|
|
97ef56f905 | ||
|
|
124af97cc8 | ||
|
|
021ac68400 | ||
|
|
4b10686336 | ||
|
|
153812c6e5 | ||
|
|
9aa3ebe872 | ||
|
|
e23166e1d5 | ||
|
|
a89b575b26 | ||
|
|
5eeac603db | ||
|
|
cca0f3b4dc | ||
|
|
22f4dade4f | ||
|
|
e30a0c3dce | ||
|
|
9966e6322d | ||
|
|
02450982c1 | ||
|
|
f9f2e604c0 | ||
|
|
40ac8b1909 | ||
|
|
f1a2037bca | ||
|
|
ded78c6639 | ||
|
|
51fcb59f09 | ||
|
|
e75c556443 | ||
|
|
752b2caaf4 | ||
|
|
3c84143511 | ||
|
|
094ad3bd59 | ||
|
|
01e3cd0296 | ||
|
|
fd6109099a | ||
|
|
8c07b12bb0 | ||
|
|
eb404b8e5b | ||
|
|
0fdb5e83cf | ||
|
|
2a780bc482 | ||
|
|
f61b664687 | ||
|
|
04844a4422 | ||
|
|
3afc9f83d9 | ||
|
|
e08435568c | ||
|
|
1a80a74d4f | ||
|
|
9c53541cbd | ||
|
|
62db393969 | ||
|
|
d7c9ab43bc | ||
|
|
fcb4c722c6 | ||
|
|
7626f63beb | ||
|
|
a6e45c7fd1 | ||
|
|
2658831e83 | ||
|
|
ffdbe46a23 | ||
|
|
6a11cd0e28 | ||
|
|
153ab63393 | ||
|
|
ea1855485c | ||
|
|
3427fa1e94 | ||
|
|
46262c56db | ||
|
|
3482d92ab6 | ||
|
|
74ac8f9ffa | ||
|
|
7e289950fa | ||
|
|
9fc8af6553 | ||
|
|
7ffc02c3e5 | ||
|
|
2f323cde8a | ||
|
|
534131d994 | ||
|
|
d233e2b4a5 | ||
|
|
05a7defcb8 | ||
|
|
eeec24ae78 | ||
|
|
1d778e3249 | ||
|
|
3bb44d8a17 | ||
|
|
71c52b4587 | ||
|
|
fe449abb47 | ||
|
|
46d1f89b77 | ||
|
|
bf1f2054de | ||
|
|
399caaaeff | ||
|
|
27b4176e23 | ||
|
|
a8bc6b4e1d | ||
|
|
3ca8f72762 | ||
|
|
8aec5dbba6 | ||
|
|
cccebd8494 | ||
|
|
5fbbd92ea7 | ||
|
|
81f26e0892 | ||
|
|
9366284e1d | ||
|
|
9aa5eea8c9 | ||
|
|
20f61bff07 | ||
|
|
625819da91 | ||
|
|
2c691d84f2 | ||
|
|
4630d2640b | ||
|
|
043f24d5ca | ||
|
|
87e18c0521 | ||
|
|
7e30f860b2 | ||
|
|
0ac0ffe53d | ||
|
|
ae4e1b55e6 | ||
|
|
756ced088c | ||
|
|
8ce6b22be7 | ||
|
|
6184d64f89 | ||
|
|
c00c2626b4 | ||
|
|
89fddd0210 | ||
|
|
0c167d803c | ||
|
|
c50042c1e7 | ||
|
|
0dc1b46466 | ||
|
|
4ed9fc7d0e | ||
|
|
162929bdca | ||
|
|
54a2f6940c | ||
|
|
0dff59d793 | ||
|
|
7951c4a03a | ||
|
|
66fd56fccb | ||
|
|
da699e999f | ||
|
|
c6a5f50c76 | ||
|
|
74c7395ab9 |
57
changelog.md
57
changelog.md
@@ -84,9 +84,54 @@ pre {
|
|||||||
## changelog
|
## changelog
|
||||||
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
||||||
|
|
||||||
### Tuesday 8/27/2024 - v3.14.2
|
### Wednesday 9/04/2024 - v3.15.0
|
||||||
{{taskList
|
|
||||||
|
|
||||||
|
{{taskList
|
||||||
|
##### 5e-Cleric, abquintic, calculuschild, Gazook89, G-Ambatte, Ericsheid, Kaiburr
|
||||||
|
|
||||||
|
* [x] New {{openSans **VAULT** {{fas,fa-dungeon}}}} page 🎉🎉🎉
|
||||||
|
:
|
||||||
|
All **PUBLISHED** brews ({{openSans :fas_circle_info: **Properties**}} menu) will be searchable, by title or author, and filtered by renderer. More features and adjustments will be coming.
|
||||||
|
:
|
||||||
|
Note: If any of your own brews are not showing up in search (particularly if stored on Google Drive), please edit and re-save to ensure our database has the data needed from document to be searchable.
|
||||||
|
|
||||||
|
Fixes issue [#697](https://github.com/naturalcrit/homebrewery/issues/697)
|
||||||
|
|
||||||
|
##### Gazook89
|
||||||
|
|
||||||
|
* [x] Auto-focus on text editor when switching editor tabs
|
||||||
|
}}
|
||||||
|
|
||||||
|
### Wednesday 8/28/2024 - v3.14.3
|
||||||
|
|
||||||
|
{{taskList
|
||||||
|
##### calculuschild, G-Ambatte
|
||||||
|
|
||||||
|
* [x] New {{openSans **IMAGES → {{fac,image-wrap-left}} IMAGE WRAP LEFT/RIGHT**}} snippets
|
||||||
|
|
||||||
|
Fixes issue [#380](https://github.com/naturalcrit/homebrewery/issues/380)
|
||||||
|
|
||||||
|
* [x] Fix v3.14.2 bug with `꞉꞉꞉꞉` failing after tables
|
||||||
|
|
||||||
|
##### 5e-Cleric
|
||||||
|
|
||||||
|
* [x] Fix Account page crash when not logged in
|
||||||
|
|
||||||
|
Fixes issue [#3605](https://github.com/naturalcrit/homebrewery/issues/3605)
|
||||||
|
|
||||||
|
##### abquintic
|
||||||
|
|
||||||
|
* [x] Fix jump hotkeys conflicting with `CTRL + SHIFT`. Preview and Source movement shortcuts now use `CTRL + SHIFT + META + LEFT\RIGHTARROW`
|
||||||
|
|
||||||
|
##### G-Ambatte
|
||||||
|
|
||||||
|
* [x] Fix display issue with image wrap icons
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
### Tuesday 8/27/2024 - v3.14.2
|
||||||
|
|
||||||
|
{{taskList
|
||||||
##### calculuschild
|
##### calculuschild
|
||||||
|
|
||||||
* [x] Reroute invalid urls to homepage
|
* [x] Reroute invalid urls to homepage
|
||||||
@@ -119,7 +164,7 @@ Fixes issues [#3572](https://github.com/naturalcrit/homebrewery/issues/3572)
|
|||||||
|
|
||||||
Fixes issues [#1430](https://github.com/naturalcrit/homebrewery/issues/1430)
|
Fixes issues [#1430](https://github.com/naturalcrit/homebrewery/issues/1430)
|
||||||
|
|
||||||
* [x] Fix colon `:::` being parsed in codeblocks
|
* [x] Fix colon `꞉꞉꞉꞉` being parsed in codeblocks
|
||||||
|
|
||||||
* [x] Prevent crashes when loading undefined renderer or theme bundle
|
* [x] Prevent crashes when loading undefined renderer or theme bundle
|
||||||
|
|
||||||
@@ -133,12 +178,11 @@ Fixes issues [#1430](https://github.com/naturalcrit/homebrewery/issues/1430)
|
|||||||
##### 5e-Cleric, Gazook89
|
##### 5e-Cleric, Gazook89
|
||||||
|
|
||||||
* [x] Viewer tools for zoom/page navigation
|
* [x] Viewer tools for zoom/page navigation
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
### Tuesday 8/13/2024 - v3.14.1
|
### Tuesday 8/13/2024 - v3.14.1
|
||||||
{{taskList
|
|
||||||
|
|
||||||
|
{{taskList
|
||||||
##### abquintic
|
##### abquintic
|
||||||
|
|
||||||
* [x] Allow Table of Contents to flow across columns
|
* [x] Allow Table of Contents to flow across columns
|
||||||
@@ -181,16 +225,13 @@ Fixes issues [#3613](https://github.com/naturalcrit/homebrewery/issues/3613)
|
|||||||
|
|
||||||
Fixes issues [#3622](https://github.com/naturalcrit/homebrewery/issues/3622)
|
Fixes issues [#3622](https://github.com/naturalcrit/homebrewery/issues/3622)
|
||||||
|
|
||||||
|
|
||||||
##### calculuschild
|
##### calculuschild
|
||||||
|
|
||||||
* [x] Fix `/migrate` page using an editor context instead of share context
|
* [x] Fix `/migrate` page using an editor context instead of share context
|
||||||
|
|
||||||
|
|
||||||
##### 5e-Cleric
|
##### 5e-Cleric
|
||||||
|
|
||||||
* [x] Fix Monster Stat Blocks losing color in Safari
|
* [x] Fix Monster Stat Blocks losing color in Safari
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
\page
|
\page
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const _ = require('lodash');
|
|||||||
|
|
||||||
import Dialog from '../../../components/dialog.jsx';
|
import Dialog from '../../../components/dialog.jsx';
|
||||||
|
|
||||||
const DISMISS_KEY = 'dismiss_notification12-04-23';
|
const DISMISS_KEY = 'dismiss_notification04-09-24';
|
||||||
const DISMISS_BUTTON = <i className='fas fa-times dismiss' />;
|
const DISMISS_BUTTON = <i className='fas fa-times dismiss' />;
|
||||||
|
|
||||||
const NotificationPopup = ()=>{
|
const NotificationPopup = ()=>{
|
||||||
@@ -15,11 +15,12 @@ const NotificationPopup = ()=>{
|
|||||||
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
|
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li key='psa'>
|
<li key='Vault'>
|
||||||
<em>Don't store IMAGES in Google Drive</em><br />
|
<em>Search brews with our new page!</em><br />
|
||||||
Google Drive is not an image service, and will block images from being used
|
We have been working very hard in making this possible, now you can share your work and look at it in the new <a href="/vault">Vault</a> page!
|
||||||
in brews if they get more views than expected. Google has confirmed they won't fix
|
All PUBLISHED brews will be available to anyone searching there, by title or author, and filtering by renderer.
|
||||||
this, so we recommend you look for another image hosting service such as imgur, ImgBB or Google Photos.
|
|
||||||
|
More features will be coming.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li key='googleDriveFolder'>
|
<li key='googleDriveFolder'>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const Editor = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleControlKeys : function(e){
|
handleControlKeys : function(e){
|
||||||
if(!(e.ctrlKey || e.metaKey)) return;
|
if(!(e.ctrlKey && e.metaKey)) return;
|
||||||
const LEFTARROW_KEY = 37;
|
const LEFTARROW_KEY = 37;
|
||||||
const RIGHTARROW_KEY = 39;
|
const RIGHTARROW_KEY = 39;
|
||||||
if (e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump();
|
if (e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump();
|
||||||
@@ -113,7 +113,10 @@ const Editor = createClass({
|
|||||||
this.props.setMoveArrows(newView === 'text');
|
this.props.setMoveArrows(newView === 'text');
|
||||||
this.setState({
|
this.setState({
|
||||||
view : newView
|
view : newView
|
||||||
}, this.updateEditorSize); //TODO: not sure if updateeditorsize needed
|
}, ()=>{
|
||||||
|
this.codeEditor.current?.codeMirror.focus();
|
||||||
|
this.updateEditorSize();
|
||||||
|
}); //TODO: not sure if updateeditorsize needed
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrentPage : function(){
|
getCurrentPage : function(){
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const UserPage = require('./pages/userPage/userPage.jsx');
|
|||||||
const SharePage = require('./pages/sharePage/sharePage.jsx');
|
const SharePage = require('./pages/sharePage/sharePage.jsx');
|
||||||
const NewPage = require('./pages/newPage/newPage.jsx');
|
const NewPage = require('./pages/newPage/newPage.jsx');
|
||||||
const ErrorPage = require('./pages/errorPage/errorPage.jsx');
|
const ErrorPage = require('./pages/errorPage/errorPage.jsx');
|
||||||
|
const VaultPage = require('./pages/vaultPage/vaultPage.jsx');
|
||||||
const AccountPage = require('./pages/accountPage/accountPage.jsx');
|
const AccountPage = require('./pages/accountPage/accountPage.jsx');
|
||||||
|
|
||||||
const WithRoute = (props)=>{
|
const WithRoute = (props)=>{
|
||||||
@@ -71,6 +72,7 @@ const Homebrew = createClass({
|
|||||||
<Route path='/new/:id' element={<WithRoute el={NewPage} brew={this.props.brew} userThemes={this.props.userThemes}/>} />
|
<Route path='/new/:id' element={<WithRoute el={NewPage} brew={this.props.brew} userThemes={this.props.userThemes}/>} />
|
||||||
<Route path='/new' element={<WithRoute el={NewPage} userThemes={this.props.userThemes}/> } />
|
<Route path='/new' element={<WithRoute el={NewPage} userThemes={this.props.userThemes}/> } />
|
||||||
<Route path='/user/:username' element={<WithRoute el={UserPage} brews={this.props.brews} />} />
|
<Route path='/user/:username' element={<WithRoute el={UserPage} brews={this.props.brews} />} />
|
||||||
|
<Route path='/vault' element={<WithRoute el={VaultPage}/>}/>
|
||||||
<Route path='/changelog' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
<Route path='/changelog' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||||
<Route path='/faq' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
<Route path='/faq' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||||
<Route path='/migrate' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
<Route path='/migrate' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||||
|
|||||||
17
client/homebrew/navbar/vault.navitem.jsx
Normal file
17
client/homebrew/navbar/vault.navitem.jsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||||
|
|
||||||
|
module.exports = function (props) {
|
||||||
|
return (
|
||||||
|
<Nav.item
|
||||||
|
color='purple'
|
||||||
|
icon='fas fa-dungeon'
|
||||||
|
href='/vault'
|
||||||
|
newTab={false}
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
>
|
||||||
|
Vault
|
||||||
|
</Nav.item>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -19,7 +19,8 @@ const BrewItem = createClass({
|
|||||||
stubbed : true
|
stubbed : true
|
||||||
},
|
},
|
||||||
updateListFilter : ()=>{},
|
updateListFilter : ()=>{},
|
||||||
reportError : ()=>{}
|
reportError : ()=>{},
|
||||||
|
renderStorage : true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -95,6 +96,7 @@ const BrewItem = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderStorageIcon : function(){
|
renderStorageIcon : function(){
|
||||||
|
if(!this.props.renderStorage) return;
|
||||||
if(this.props.brew.googleId) {
|
if(this.props.brew.googleId) {
|
||||||
return <span title={this.props.brew.webViewLink ? 'Your Google Drive Storage': 'Another User\'s Google Drive Storage'}>
|
return <span title={this.props.brew.webViewLink ? 'Your Google Drive Storage': 'Another User\'s Google Drive Storage'}>
|
||||||
<a href={this.props.brew.webViewLink} target='_blank'>
|
<a href={this.props.brew.webViewLink} target='_blank'>
|
||||||
@@ -142,10 +144,14 @@ const BrewItem = createClass({
|
|||||||
}
|
}
|
||||||
<span title={`Authors:\n${brew.authors?.join('\n')}`}>
|
<span title={`Authors:\n${brew.authors?.join('\n')}`}>
|
||||||
<i className='fas fa-user'/> {brew.authors?.map((author, index)=>(
|
<i className='fas fa-user'/> {brew.authors?.map((author, index)=>(
|
||||||
<>
|
<React.Fragment key={index}>
|
||||||
<a key={index} href={`/user/${author}`}>{author}</a>
|
{author === 'hidden'
|
||||||
|
? <span title="Username contained an email address; hidden to protect user's privacy">{author}</span>
|
||||||
|
: <a href={`/user/${author}`}>{author}</a>
|
||||||
|
}
|
||||||
{index < brew.authors.length - 1 && ', '}
|
{index < brew.authors.length - 1 && ', '}
|
||||||
</>))}
|
</React.Fragment>
|
||||||
|
))}
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
|
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ const dedent = require('dedent-tabs').default;
|
|||||||
|
|
||||||
const loginUrl = 'https://www.naturalcrit.com/login';
|
const loginUrl = 'https://www.naturalcrit.com/login';
|
||||||
|
|
||||||
|
//001-050 : Brew errors
|
||||||
|
//050-100 : Other pages errors
|
||||||
|
|
||||||
const errorIndex = (props)=>{
|
const errorIndex = (props)=>{
|
||||||
return {
|
return {
|
||||||
// Default catch all
|
// Default catch all
|
||||||
@@ -149,8 +152,16 @@ const errorIndex = (props)=>{
|
|||||||
|
|
||||||
**Brew ID:** ${props.brew.brewId}`,
|
**Brew ID:** ${props.brew.brewId}`,
|
||||||
|
|
||||||
|
//account page when account is not defined
|
||||||
|
'50' : dedent`
|
||||||
|
## You are not signed in
|
||||||
|
|
||||||
|
You are trying to access the account page, but are not signed in to an account.
|
||||||
|
|
||||||
|
Please login or signup at our [login page](https://www.naturalcrit.com/login?redirect=https://homebrewery.naturalcrit.com/account).`,
|
||||||
|
|
||||||
// Brew locked by Administrators error
|
// Brew locked by Administrators error
|
||||||
'100' : dedent`
|
'51' : dedent`
|
||||||
## This brew has been locked.
|
## This brew has been locked.
|
||||||
|
|
||||||
Only an author may request that this lock is removed.
|
Only an author may request that this lock is removed.
|
||||||
@@ -160,6 +171,11 @@ const errorIndex = (props)=>{
|
|||||||
**Brew ID:** ${props.brew.brewId}
|
**Brew ID:** ${props.brew.brewId}
|
||||||
|
|
||||||
**Brew Title:** ${props.brew.brewTitle}`,
|
**Brew Title:** ${props.brew.brewTitle}`,
|
||||||
|
|
||||||
|
'90' : dedent` An unexpected error occurred while looking for these brews.
|
||||||
|
Try again in a few minutes.`,
|
||||||
|
|
||||||
|
'91' : dedent` An unexpected error occurred while trying to get the total of brews.`,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ const Nav = require('naturalcrit/nav/nav.jsx');
|
|||||||
const Navbar = require('../../navbar/navbar.jsx');
|
const Navbar = require('../../navbar/navbar.jsx');
|
||||||
const NewBrewItem = require('../../navbar/newbrew.navitem.jsx');
|
const NewBrewItem = require('../../navbar/newbrew.navitem.jsx');
|
||||||
const HelpNavItem = require('../../navbar/help.navitem.jsx');
|
const HelpNavItem = require('../../navbar/help.navitem.jsx');
|
||||||
|
const VaultNavItem = require('../../navbar/vault.navitem.jsx');
|
||||||
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
|
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
|
||||||
const AccountNavItem = require('../../navbar/account.navitem.jsx');
|
const AccountNavItem = require('../../navbar/account.navitem.jsx');
|
||||||
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
|
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
|
||||||
const { fetchThemeBundle } = require('../../../../shared/helpers.js');
|
const { fetchThemeBundle } = require('../../../../shared/helpers.js');
|
||||||
|
|
||||||
|
|
||||||
const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
|
const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
|
||||||
const Editor = require('../../editor/editor.jsx');
|
const Editor = require('../../editor/editor.jsx');
|
||||||
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
|
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
|
||||||
@@ -76,6 +76,7 @@ const HomePage = createClass({
|
|||||||
}
|
}
|
||||||
<NewBrewItem />
|
<NewBrewItem />
|
||||||
<HelpNavItem />
|
<HelpNavItem />
|
||||||
|
<VaultNavItem />
|
||||||
<RecentNavItem />
|
<RecentNavItem />
|
||||||
<AccountNavItem />
|
<AccountNavItem />
|
||||||
</Nav.section>
|
</Nav.section>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const Account = require('../../navbar/account.navitem.jsx');
|
|||||||
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
|
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
|
||||||
const HelpNavItem = require('../../navbar/help.navitem.jsx');
|
const HelpNavItem = require('../../navbar/help.navitem.jsx');
|
||||||
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
|
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
|
||||||
|
const VaultNavitem = require('../../navbar/vault.navitem.jsx');
|
||||||
|
|
||||||
const UserPage = createClass({
|
const UserPage = createClass({
|
||||||
displayName : 'UserPage',
|
displayName : 'UserPage',
|
||||||
@@ -66,6 +67,7 @@ const UserPage = createClass({
|
|||||||
}
|
}
|
||||||
<NewBrew />
|
<NewBrew />
|
||||||
<HelpNavItem />
|
<HelpNavItem />
|
||||||
|
<VaultNavitem/>
|
||||||
<RecentNavItem />
|
<RecentNavItem />
|
||||||
<Account />
|
<Account />
|
||||||
</Nav.section>
|
</Nav.section>
|
||||||
|
|||||||
396
client/homebrew/pages/vaultPage/vaultPage.jsx
Normal file
396
client/homebrew/pages/vaultPage/vaultPage.jsx
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
require('./vaultPage.less');
|
||||||
|
|
||||||
|
const React = require('react');
|
||||||
|
const { useState, useEffect, useRef } = React;
|
||||||
|
|
||||||
|
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 SplitPane = require('../../../../shared/naturalcrit/splitPane/splitPane.jsx');
|
||||||
|
const ErrorIndex = require('../errorPage/errors/errorIndex.js');
|
||||||
|
|
||||||
|
const request = require('../../utils/request-middleware.js');
|
||||||
|
|
||||||
|
const VaultPage = (props)=>{
|
||||||
|
const [pageState, setPageState] = useState(parseInt(props.query.page) || 1);
|
||||||
|
|
||||||
|
//Response state
|
||||||
|
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 submitButtonRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
disableSubmitIfFormInvalid();
|
||||||
|
loadPage(pageState, true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const updateStateWithBrews = (brews, page)=>{
|
||||||
|
setBrewCollection(brews || null);
|
||||||
|
setPageState(parseInt(page) || 1);
|
||||||
|
setSearching(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, page)=>{
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
const urlParams = new URLSearchParams(url.search);
|
||||||
|
|
||||||
|
urlParams.set('title', titleValue);
|
||||||
|
urlParams.set('author', authorValue);
|
||||||
|
urlParams.set('count', countValue);
|
||||||
|
urlParams.set('v3', v3Value);
|
||||||
|
urlParams.set('legacy', legacyValue);
|
||||||
|
urlParams.set('page', page);
|
||||||
|
|
||||||
|
url.search = urlParams.toString();
|
||||||
|
window.history.replaceState(null, '', url.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
const performSearch = async (title, author, count, v3, legacy, page)=>{
|
||||||
|
updateUrl(title, author, count, v3, legacy, page);
|
||||||
|
|
||||||
|
const response = await request.get(
|
||||||
|
`/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}`
|
||||||
|
).catch((error)=>{
|
||||||
|
console.log('error at loadPage: ', error);
|
||||||
|
setError(error);
|
||||||
|
updateStateWithBrews([], 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(response.ok)
|
||||||
|
updateStateWithBrews(response.body.brews, page);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadTotal = async (title, author, v3, legacy)=>{
|
||||||
|
setTotalBrews(null);
|
||||||
|
|
||||||
|
const response = await request.get(
|
||||||
|
`/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}`
|
||||||
|
).catch((error)=>{
|
||||||
|
console.log('error at loadTotal: ', error);
|
||||||
|
setError(error);
|
||||||
|
updateStateWithBrews([], 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(response.ok)
|
||||||
|
setTotalBrews(response.body.totalBrews);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadPage = async (page, updateTotal)=>{
|
||||||
|
if(!validateForm())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setSearching(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
performSearch(title, author, count, v3, legacy, page);
|
||||||
|
|
||||||
|
if(updateTotal)
|
||||||
|
loadTotal(title, author, v3, legacy);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderNavItems = ()=>(
|
||||||
|
<Navbar>
|
||||||
|
<Nav.section>
|
||||||
|
<Nav.item className='brewTitle'>
|
||||||
|
Vault: Search for brews
|
||||||
|
</Nav.item>
|
||||||
|
</Nav.section>
|
||||||
|
<Nav.section>
|
||||||
|
<NewBrew />
|
||||||
|
<HelpNavItem />
|
||||||
|
<RecentNavItem />
|
||||||
|
<Account />
|
||||||
|
</Nav.section>
|
||||||
|
</Navbar>
|
||||||
|
);
|
||||||
|
|
||||||
|
const validateForm = ()=>{
|
||||||
|
//form validity: title or author must be written, and at least one renderer set
|
||||||
|
const isTitleValid = titleRef.current.validity.valid && titleRef.current.value;
|
||||||
|
const isAuthorValid = authorRef.current.validity.valid && authorRef.current.value;
|
||||||
|
const isCheckboxChecked = legacyRef.current.checked || v3Ref.current.checked;
|
||||||
|
|
||||||
|
const isFormValid = (isTitleValid || isAuthorValid) && isCheckboxChecked;
|
||||||
|
|
||||||
|
return isFormValid;
|
||||||
|
};
|
||||||
|
|
||||||
|
const disableSubmitIfFormInvalid = ()=>{
|
||||||
|
submitButtonRef.current.disabled = !validateForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderForm = ()=>(
|
||||||
|
<div className='brewLookup'>
|
||||||
|
<h2 className='formTitle'>Brew Lookup</h2>
|
||||||
|
<div className='formContents'>
|
||||||
|
<label>
|
||||||
|
Title of the brew
|
||||||
|
<input
|
||||||
|
ref={titleRef}
|
||||||
|
type='text'
|
||||||
|
name='title'
|
||||||
|
defaultValue={props.query.title || ''}
|
||||||
|
onKeyUp={disableSubmitIfFormInvalid}
|
||||||
|
pattern='.{3,}'
|
||||||
|
title='At least 3 characters'
|
||||||
|
onKeyDown={(e)=>{
|
||||||
|
if(e.key === 'Enter' && !submitButtonRef.current.disabled)
|
||||||
|
loadPage(1, true);
|
||||||
|
}}
|
||||||
|
placeholder='v3 Reference Document'
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Author of the brew
|
||||||
|
<input
|
||||||
|
ref={authorRef}
|
||||||
|
type='text'
|
||||||
|
name='author'
|
||||||
|
pattern='.{1,}'
|
||||||
|
defaultValue={props.query.author || ''}
|
||||||
|
onKeyUp={disableSubmitIfFormInvalid}
|
||||||
|
onKeyDown={(e)=>{
|
||||||
|
if(e.key === 'Enter' && !submitButtonRef.current.disabled)
|
||||||
|
loadPage(1, true);
|
||||||
|
}}
|
||||||
|
placeholder='Username'
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Results per page
|
||||||
|
<select ref={countRef} name='count' defaultValue={props.query.count || 20}>
|
||||||
|
<option value='10'>10</option>
|
||||||
|
<option value='20'>20</option>
|
||||||
|
<option value='40'>40</option>
|
||||||
|
<option value='60'>60</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
className='renderer'
|
||||||
|
ref={v3Ref}
|
||||||
|
type='checkbox'
|
||||||
|
defaultChecked={props.query.v3 !== 'false'}
|
||||||
|
onChange={disableSubmitIfFormInvalid}
|
||||||
|
/>
|
||||||
|
Search for v3 brews
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
className='renderer'
|
||||||
|
ref={legacyRef}
|
||||||
|
type='checkbox'
|
||||||
|
defaultChecked={props.query.legacy !== 'false'}
|
||||||
|
onChange={disableSubmitIfFormInvalid}
|
||||||
|
/>
|
||||||
|
Search for legacy brews
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button
|
||||||
|
id='searchButton'
|
||||||
|
ref={submitButtonRef}
|
||||||
|
onClick={()=>{
|
||||||
|
loadPage(1, true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
<i
|
||||||
|
className={searching ? 'fas fa-spin fa-spinner': 'fas fa-search'}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<legend>
|
||||||
|
<h3>Tips and tricks</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Only <b>published</b> brews are searchable via this tool
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Usernames are case-sensitive
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Use <code>"word"</code> to match an exact string,
|
||||||
|
and <code>-</code> to exclude words (at least one word must not be negated)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Some common words like "a", "after", "through", "itself", "here", etc.,
|
||||||
|
are ignored in searches. The full list can be found
|
||||||
|
<a href='https://github.com/mongodb/mongo/blob/0e3b3ca8480ddddf5d0105d11a94bd4698335312/src/mongo/db/fts/stop_words_english.txt'>
|
||||||
|
here
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<small>New features will be coming, such as filters and search by tags.</small>
|
||||||
|
</legend>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderPaginationControls = ()=>{
|
||||||
|
if(!totalBrews) return null;
|
||||||
|
|
||||||
|
const countInt = parseInt(props.query.count || 20);
|
||||||
|
const totalPages = Math.ceil(totalBrews / countInt);
|
||||||
|
|
||||||
|
let startPage, endPage;
|
||||||
|
if(pageState <= 6) {
|
||||||
|
startPage = 1;
|
||||||
|
endPage = Math.min(totalPages, 10);
|
||||||
|
} else if(pageState + 4 >= totalPages) {
|
||||||
|
startPage = Math.max(1, totalPages - 9);
|
||||||
|
endPage = totalPages;
|
||||||
|
} else {
|
||||||
|
startPage = pageState - 5;
|
||||||
|
endPage = pageState + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagesAroundCurrent = new Array(endPage - startPage + 1)
|
||||||
|
.fill()
|
||||||
|
.map((_, index)=>(
|
||||||
|
<a
|
||||||
|
key={startPage + index}
|
||||||
|
className={`pageNumber ${
|
||||||
|
pageState === startPage + index ? 'currentPage' : ''
|
||||||
|
}`}
|
||||||
|
onClick={()=>loadPage(startPage + index, false)}
|
||||||
|
>
|
||||||
|
{startPage + index}
|
||||||
|
</a>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='paginationControls'>
|
||||||
|
<button
|
||||||
|
className='previousPage'
|
||||||
|
onClick={()=>loadPage(pageState - 1, false)}
|
||||||
|
disabled={pageState === startPage}
|
||||||
|
>
|
||||||
|
<i className='fa-solid fa-chevron-left'></i>
|
||||||
|
</button>
|
||||||
|
<ol className='pages'>
|
||||||
|
{startPage > 1 && (
|
||||||
|
<a
|
||||||
|
className='pageNumber firstPage'
|
||||||
|
onClick={()=>loadPage(1, false)}
|
||||||
|
>
|
||||||
|
1 ...
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
{pagesAroundCurrent}
|
||||||
|
{endPage < totalPages && (
|
||||||
|
<a
|
||||||
|
className='pageNumber lastPage'
|
||||||
|
onClick={()=>loadPage(totalPages, false)}
|
||||||
|
>
|
||||||
|
... {totalPages}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</ol>
|
||||||
|
<button
|
||||||
|
className='nextPage'
|
||||||
|
onClick={()=>loadPage(pageState + 1, false)}
|
||||||
|
disabled={pageState === totalPages}
|
||||||
|
>
|
||||||
|
<i className='fa-solid fa-chevron-right'></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderFoundBrews = ()=>{
|
||||||
|
if(searching) {
|
||||||
|
return (
|
||||||
|
<div className='foundBrews searching'>
|
||||||
|
<h3 className='searchAnim'>Searching</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
const errorText = ErrorIndex()[error.HBErrorCode.toString()] || '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='foundBrews noBrews'>
|
||||||
|
<h3>Error: {errorText}</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!brewCollection) {
|
||||||
|
return (
|
||||||
|
<div className='foundBrews noBrews'>
|
||||||
|
<h3>No search yet</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(brewCollection.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className='foundBrews noBrews'>
|
||||||
|
<h3>No brews found</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='foundBrews'>
|
||||||
|
<span className='totalBrews'>
|
||||||
|
{`Brews found: `}
|
||||||
|
<span>{totalBrews}</span>
|
||||||
|
</span>
|
||||||
|
{brewCollection.map((brew, index)=>{
|
||||||
|
return (
|
||||||
|
<BrewItem
|
||||||
|
brew={{ ...brew }}
|
||||||
|
key={index}
|
||||||
|
reportError={props.reportError}
|
||||||
|
renderStorage={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{renderPaginationControls()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='vaultPage'>
|
||||||
|
<link href='/themes/V3/Blank/style.css' rel='stylesheet' />
|
||||||
|
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet' />
|
||||||
|
{renderNavItems()}
|
||||||
|
<div className='content'>
|
||||||
|
<SplitPane showDividerButtons={false}>
|
||||||
|
<div className='form dataGroup'>{renderForm()}</div>
|
||||||
|
|
||||||
|
<div className='resultsContainer dataGroup'>
|
||||||
|
{renderFoundBrews()}
|
||||||
|
</div>
|
||||||
|
</SplitPane>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = VaultPage;
|
||||||
371
client/homebrew/pages/vaultPage/vaultPage.less
Normal file
371
client/homebrew/pages/vaultPage/vaultPage.less
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
body {
|
||||||
|
height : 100vh;
|
||||||
|
|
||||||
|
.content { height : 100%; }
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size : 10pt;
|
||||||
|
color : #555555;
|
||||||
|
|
||||||
|
a { color : #333333; }
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding-inline : 5px;
|
||||||
|
background : lightgrey;
|
||||||
|
border-radius : 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*:not(input) { user-select : none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.vaultPage {
|
||||||
|
height : 100%;
|
||||||
|
overflow-y : hidden;
|
||||||
|
background-color : #2C3E50;
|
||||||
|
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background : #2C3E50;
|
||||||
|
|
||||||
|
.dataGroup {
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
background : white;
|
||||||
|
|
||||||
|
&.form .brewLookup {
|
||||||
|
position : relative;
|
||||||
|
padding : 50px clamp(20px, 4vw, 50px);
|
||||||
|
|
||||||
|
h1, h2, h3, h4 {
|
||||||
|
font-family : 'CodeBold';
|
||||||
|
letter-spacing : 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
legend {
|
||||||
|
h3 {
|
||||||
|
margin-block : 30px 20px;
|
||||||
|
font-size : 20px;
|
||||||
|
text-align : center;
|
||||||
|
border-bottom : 2px solid;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
padding-inline : 30px 10px;
|
||||||
|
li {
|
||||||
|
margin-block : 5px;
|
||||||
|
line-height : calc(1em + 5px);
|
||||||
|
list-style : disc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position : absolute;
|
||||||
|
top : 0;
|
||||||
|
right : 0;
|
||||||
|
left : 0;
|
||||||
|
display : block;
|
||||||
|
padding : 10px;
|
||||||
|
font-weight : 900;
|
||||||
|
color : white;
|
||||||
|
white-space : pre-wrap;
|
||||||
|
content : 'Error:\A At least one renderer should be enabled to make a search';
|
||||||
|
background : rgb(255, 60, 60);
|
||||||
|
opacity : 0;
|
||||||
|
transition : opacity 0.5s;
|
||||||
|
}
|
||||||
|
&:not(:has(input[type='checkbox']:checked))::after { opacity : 1; }
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin : 20px 0;
|
||||||
|
font-size : 30px;
|
||||||
|
color : black;
|
||||||
|
text-align : center;
|
||||||
|
border-bottom : 2px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContents {
|
||||||
|
position : relative;
|
||||||
|
display : flex;
|
||||||
|
flex-direction : column;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display : flex;
|
||||||
|
align-items : center;
|
||||||
|
margin : 10px 0;
|
||||||
|
}
|
||||||
|
select { margin : 0 10px; }
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin : 0 10px;
|
||||||
|
|
||||||
|
&:invalid { background : rgb(255, 188, 181); }
|
||||||
|
|
||||||
|
&[type='checkbox'] {
|
||||||
|
position : relative;
|
||||||
|
display : inline-block;
|
||||||
|
width : 50px;
|
||||||
|
height : 30px;
|
||||||
|
font-family : 'WalterTurncoat';
|
||||||
|
font-size : 20px;
|
||||||
|
font-weight : 800;
|
||||||
|
color : white;
|
||||||
|
letter-spacing : 2px;
|
||||||
|
appearance : none;
|
||||||
|
background : red;
|
||||||
|
isolation : isolate;
|
||||||
|
border-radius : 5px;
|
||||||
|
|
||||||
|
&::before,&::after {
|
||||||
|
position : absolute;
|
||||||
|
inset : 0;
|
||||||
|
z-index : 5;
|
||||||
|
padding-top : 2px;
|
||||||
|
text-align : center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display : block;
|
||||||
|
content : 'No';
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display : none;
|
||||||
|
content : 'Yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
background : green;
|
||||||
|
|
||||||
|
&::before { display : none; }
|
||||||
|
&::after { display : block; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#searchButton {
|
||||||
|
position : absolute;
|
||||||
|
right : 20px;
|
||||||
|
bottom : 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-left : 10px;
|
||||||
|
animation-duration : 1000s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.resultsContainer {
|
||||||
|
display : flex;
|
||||||
|
flex-direction : column;
|
||||||
|
height : 100%;
|
||||||
|
overflow-y : auto;
|
||||||
|
font-family : 'BookInsanityRemake';
|
||||||
|
font-size : 0.34cm;
|
||||||
|
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-family : 'Open Sans';
|
||||||
|
font-weight : 900;
|
||||||
|
color : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foundBrews {
|
||||||
|
position : relative;
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
max-height : 100%;
|
||||||
|
padding : 50px 50px 70px 50px;
|
||||||
|
overflow-y : scroll;
|
||||||
|
background-color : #2C3E50;
|
||||||
|
|
||||||
|
h3 { font-size : 25px; }
|
||||||
|
|
||||||
|
&.noBrews {
|
||||||
|
display : grid;
|
||||||
|
place-items : center;
|
||||||
|
color : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.searching {
|
||||||
|
display : grid;
|
||||||
|
place-items : center;
|
||||||
|
color : white;
|
||||||
|
|
||||||
|
h3 { position : relative; }
|
||||||
|
|
||||||
|
h3.searchAnim::after {
|
||||||
|
position : absolute;
|
||||||
|
top : 50%;
|
||||||
|
right : 0;
|
||||||
|
width : max-content;
|
||||||
|
height : 1em;
|
||||||
|
content : '';
|
||||||
|
translate : calc(100% + 5px) -50%;
|
||||||
|
animation : trailingDots 2s ease infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.totalBrews {
|
||||||
|
position : fixed;
|
||||||
|
right : 0;
|
||||||
|
bottom : 0;
|
||||||
|
z-index : 1000;
|
||||||
|
padding : 8px 10px;
|
||||||
|
font-family : 'Open Sans';
|
||||||
|
font-size : 11px;
|
||||||
|
font-weight : 800;
|
||||||
|
color : white;
|
||||||
|
background-color : #333333;
|
||||||
|
|
||||||
|
.searchAnim {
|
||||||
|
position : relative;
|
||||||
|
display : inline-block;
|
||||||
|
width : 3ch;
|
||||||
|
height : 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchAnim::after {
|
||||||
|
position : absolute;
|
||||||
|
top : 50%;
|
||||||
|
right : 0;
|
||||||
|
width : max-content;
|
||||||
|
height : 1em;
|
||||||
|
content : '';
|
||||||
|
translate : -50% -50%;
|
||||||
|
animation : trailingDots 2s ease infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brewItem {
|
||||||
|
width : 47%;
|
||||||
|
margin-right : 40px;
|
||||||
|
color : black;
|
||||||
|
isolation:isolate;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
position:absolute;
|
||||||
|
inset:0;
|
||||||
|
display:block;
|
||||||
|
content:'';
|
||||||
|
background-image : url('/assets/parchmentBackground.jpg');
|
||||||
|
z-index:-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(even of .brewItem) { margin-right : 0; }
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family : 'MrEavesRemake';
|
||||||
|
font-size : 0.75cm;
|
||||||
|
font-weight : 800;
|
||||||
|
line-height : 0.988em;
|
||||||
|
color : var(--HB_Color_HeaderText);
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
font-family : 'ScalySansRemake';
|
||||||
|
font-size : 1.2em;
|
||||||
|
position:relative;
|
||||||
|
z-index:2;
|
||||||
|
|
||||||
|
>span {
|
||||||
|
margin-right : 12px;
|
||||||
|
line-height : 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.links {
|
||||||
|
z-index:2;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 0px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationControls {
|
||||||
|
position : absolute;
|
||||||
|
left : 50%;
|
||||||
|
display : grid;
|
||||||
|
grid-template-areas : 'previousPage currentPage nextPage';
|
||||||
|
grid-template-columns : 50px 1fr 50px;
|
||||||
|
place-items : center;
|
||||||
|
width : auto;
|
||||||
|
translate : -50%;
|
||||||
|
|
||||||
|
.pages {
|
||||||
|
display : flex;
|
||||||
|
grid-area : currentPage;
|
||||||
|
justify-content : space-evenly;
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
padding : 5px 8px;
|
||||||
|
text-align : center;
|
||||||
|
|
||||||
|
.pageNumber {
|
||||||
|
margin-inline : 1vw;
|
||||||
|
font-family : 'Open Sans';
|
||||||
|
font-weight : 900;
|
||||||
|
color : white;
|
||||||
|
text-underline-position : under;
|
||||||
|
text-wrap : nowrap;
|
||||||
|
cursor : pointer;
|
||||||
|
|
||||||
|
&.currentPage {
|
||||||
|
color : gold;
|
||||||
|
text-decoration : underline;
|
||||||
|
pointer-events : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.firstPage { margin-right : -5px; }
|
||||||
|
|
||||||
|
&.lastPage { margin-left : -5px; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width : max-content;
|
||||||
|
|
||||||
|
&.previousPage { grid-area : previousPage; }
|
||||||
|
|
||||||
|
&.nextPage { grid-area : nextPage; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes trailingDots {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
32% { content : ' .'; }
|
||||||
|
|
||||||
|
33%,
|
||||||
|
65% { content : ' ..'; }
|
||||||
|
|
||||||
|
66%,
|
||||||
|
100% { content : ' ...'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// media query for when the page is smaller than 1079 px in width
|
||||||
|
@media screen and (max-width : 1079px) {
|
||||||
|
.vaultPage .content {
|
||||||
|
|
||||||
|
.dataGroup.form .brewLookup { padding : 1px 20px 20px 10px; }
|
||||||
|
|
||||||
|
.dataGroup.resultsContainer .foundBrews .brewItem {
|
||||||
|
width : 100%;
|
||||||
|
margin-inline : auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,6 +52,12 @@
|
|||||||
.book-part-cover {
|
.book-part-cover {
|
||||||
mask-image: url('../icons/book-part-cover.svg');
|
mask-image: url('../icons/book-part-cover.svg');
|
||||||
}
|
}
|
||||||
|
.image-wrap-left {
|
||||||
|
mask-image: url('../icons/image-wrap-left.svg');
|
||||||
|
}
|
||||||
|
.image-wrap-right {
|
||||||
|
mask-image: url('../icons/image-wrap-right.svg');
|
||||||
|
}
|
||||||
.davek {
|
.davek {
|
||||||
mask-image: url('../icons/Davek.svg');
|
mask-image: url('../icons/Davek.svg');
|
||||||
}
|
}
|
||||||
|
|||||||
58
client/icons/image-wrap-left.svg
Normal file
58
client/icons/image-wrap-left.svg
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 512.00006 512"
|
||||||
|
xml:space="preserve"
|
||||||
|
id="svg10"
|
||||||
|
sodipodi:docname="noun-wrap-image-left-212078.svg"
|
||||||
|
width="512.00006"
|
||||||
|
height="512"
|
||||||
|
inkscape:export-filename="image-wrap-right.svg"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs10" /><sodipodi:namedview
|
||||||
|
id="namedview10"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#111111"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 185.80018,144 H 32"
|
||||||
|
id="path11"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none"
|
||||||
|
inkscape:export-filename="image-wrap-right.svg"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 185.80018,368 H 32"
|
||||||
|
id="path11-8"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 480.00007,32 H 32"
|
||||||
|
id="path11-8-2-67"
|
||||||
|
clip-path="none"
|
||||||
|
sodipodi:nodetypes="cc" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 480.00008,480 H 32"
|
||||||
|
id="path11-8-2-67-2"
|
||||||
|
clip-path="none"
|
||||||
|
sodipodi:nodetypes="cc" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 160.0001,255.98832 32,256.01162"
|
||||||
|
id="path11-0"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none" /><path
|
||||||
|
id="path23"
|
||||||
|
style="opacity:0.922046;fill:#000000;fill-opacity:1;stroke-width:64;stroke-linecap:round;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||||
|
d="m 416.00008,96 a 160,160 0 0 1 96,32.50977 v 254.98046 a 160,160 0 0 1 -96,32.50977 160,160 0 0 1 -160,-160 160,160 0 0 1 160,-160 z" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
58
client/icons/image-wrap-right.svg
Normal file
58
client/icons/image-wrap-right.svg
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 512.00006 512"
|
||||||
|
xml:space="preserve"
|
||||||
|
id="svg10"
|
||||||
|
sodipodi:docname="noun-wrap-image-left-212078.svg"
|
||||||
|
width="512.00006"
|
||||||
|
height="512"
|
||||||
|
inkscape:export-filename="image-wrap-right.svg"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs10" /><sodipodi:namedview
|
||||||
|
id="namedview10"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#111111"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 326.1999,144 H 480.00008"
|
||||||
|
id="path11"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none"
|
||||||
|
inkscape:export-filename="image-wrap-right.svg"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 326.1999,368 H 480.00008"
|
||||||
|
id="path11-8"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 32.00001,32 H 480.00008"
|
||||||
|
id="path11-8-2-67"
|
||||||
|
clip-path="none"
|
||||||
|
sodipodi:nodetypes="cc" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 32,480 H 480.00008"
|
||||||
|
id="path11-8-2-67-2"
|
||||||
|
clip-path="none"
|
||||||
|
sodipodi:nodetypes="cc" /><path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 351.99998,255.98832 128.0001,0.0233"
|
||||||
|
id="path11-0"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
clip-path="none" /><path
|
||||||
|
id="path23"
|
||||||
|
style="opacity:0.922046;fill:#000000;fill-opacity:1;stroke-width:64;stroke-linecap:round;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||||
|
d="M 96,96 A 160,160 0 0 0 0,128.50977 V 383.49023 A 160,160 0 0 0 96,416 160,160 0 0 0 256,256 160,160 0 0 0 96,96 Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
176
package-lock.json
generated
176
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "homebrewery",
|
"name": "homebrewery",
|
||||||
"version": "3.14.2",
|
"version": "3.15.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "homebrewery",
|
"name": "homebrewery",
|
||||||
"version": "3.14.2",
|
"version": "3.15.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"@babel/plugin-transform-runtime": "^7.25.4",
|
"@babel/plugin-transform-runtime": "^7.25.4",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.25.4",
|
||||||
"@babel/preset-react": "^7.24.7",
|
"@babel/preset-react": "^7.24.7",
|
||||||
"@googleapis/drive": "^8.13.0",
|
"@googleapis/drive": "^8.14.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
@@ -33,12 +33,12 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "11.2.0",
|
"marked": "11.2.0",
|
||||||
"marked-emoji": "^1.4.2",
|
"marked-emoji": "^1.4.2",
|
||||||
"marked-extended-tables": "^1.0.8",
|
"marked-extended-tables": "^1.0.10",
|
||||||
"marked-gfm-heading-id": "^3.2.0",
|
"marked-gfm-heading-id": "^3.2.0",
|
||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.5.4",
|
"mongoose": "^8.6.0",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@@ -52,13 +52,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-jest": "^28.8.0",
|
"eslint-plugin-jest": "^28.8.2",
|
||||||
"eslint-plugin-react": "^7.35.0",
|
"eslint-plugin-react": "^7.35.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
"postcss-less": "^6.0.0",
|
"postcss-less": "^6.0.0",
|
||||||
"stylelint": "^16.8.2",
|
"stylelint": "^16.9.0",
|
||||||
"stylelint-config-recess-order": "^5.1.0",
|
"stylelint-config-recess-order": "^5.1.0",
|
||||||
"stylelint-config-recommended": "^14.0.1",
|
"stylelint-config-recommended": "^14.0.1",
|
||||||
"supertest": "^7.0.0"
|
"supertest": "^7.0.0"
|
||||||
@@ -2091,9 +2091,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@googleapis/drive": {
|
"node_modules/@googleapis/drive": {
|
||||||
"version": "8.13.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.14.0.tgz",
|
||||||
"integrity": "sha512-xpXzZeYtNNFLy1m2D5A8/QR2bngpjLPEvO5KZUW4Dlwi/SBHYNTjVm37IQagtQg6QUJlFb4lVLewenUdZZB1rA==",
|
"integrity": "sha512-AOokfpP6pCdcJXWA8khaCEgbGpWYavWTdAAhL4idbbf2VCQcJ2f7vPalAYNu6a4Sfj0Ly4Ehnd1xw9J9TixB1A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"googleapis-common": "^7.0.0"
|
"googleapis-common": "^7.0.0"
|
||||||
},
|
},
|
||||||
@@ -2970,7 +2970,6 @@
|
|||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz",
|
||||||
"integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==",
|
"integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sparse-bitfield": "^3.0.3"
|
"sparse-bitfield": "^3.0.3"
|
||||||
}
|
}
|
||||||
@@ -3172,14 +3171,12 @@
|
|||||||
"node_modules/@types/webidl-conversions": {
|
"node_modules/@types/webidl-conversions": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||||
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
|
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/whatwg-url": {
|
"node_modules/@types/whatwg-url": {
|
||||||
"version": "11.0.5",
|
"version": "11.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
|
||||||
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
|
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/webidl-conversions": "*"
|
"@types/webidl-conversions": "*"
|
||||||
}
|
}
|
||||||
@@ -4434,7 +4431,6 @@
|
|||||||
"version": "6.8.0",
|
"version": "6.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz",
|
||||||
"integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==",
|
"integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.20.1"
|
"node": ">=16.20.1"
|
||||||
}
|
}
|
||||||
@@ -5882,9 +5878,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-jest": {
|
"node_modules/eslint-plugin-jest": {
|
||||||
"version": "28.8.0",
|
"version": "28.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz",
|
||||||
"integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==",
|
"integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
@@ -5907,11 +5903,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-react": {
|
"node_modules/eslint-plugin-react": {
|
||||||
"version": "7.35.0",
|
"version": "7.35.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.1.tgz",
|
||||||
"integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
|
"integrity": "sha512-B5ok2JgbaaWn/zXbKCGgKDNL2tsID3Pd/c/yvjcpsd9HQDwyYc/TQv3AZMmOvrJgCs3AnYNUHRCQEMMQAYJ7Yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"array-includes": "^3.1.8",
|
"array-includes": "^3.1.8",
|
||||||
"array.prototype.findlast": "^1.2.5",
|
"array.prototype.findlast": "^1.2.5",
|
||||||
@@ -10430,12 +10425,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-extended-tables": {
|
"node_modules/marked-extended-tables": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.0.10.tgz",
|
||||||
"integrity": "sha512-GcVQP7EnfQ98o09ooqM4t4M0qfpKdKuk7/z4qZfgkLyXTXsIyFS1eeBmfC36o1NbR6aSq8ynL/LeTz3w4RS27Q==",
|
"integrity": "sha512-zvRS0GPTkxq8UWawSDecd1Rxd2KD8crrmq2QALGDdrgkcgRNQzHlbnlujBGuXxdgDJg7f6UTv+JpcfejBpKdSg==",
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"marked": ">=3 <12"
|
"marked": ">=3 <15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-gfm-heading-id": {
|
"node_modules/marked-gfm-heading-id": {
|
||||||
@@ -10513,8 +10507,7 @@
|
|||||||
"node_modules/memory-pager": {
|
"node_modules/memory-pager": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
||||||
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
|
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/meow": {
|
"node_modules/meow": {
|
||||||
"version": "13.2.0",
|
"version": "13.2.0",
|
||||||
@@ -10562,11 +10555,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/micromatch": {
|
"node_modules/micromatch": {
|
||||||
"version": "4.0.7",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"braces": "^3.0.3",
|
"braces": "^3.0.3",
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
@@ -10765,7 +10757,6 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
|
||||||
"integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
|
"integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/whatwg-url": "^11.0.2",
|
"@types/whatwg-url": "^11.0.2",
|
||||||
"whatwg-url": "^13.0.0"
|
"whatwg-url": "^13.0.0"
|
||||||
@@ -10775,7 +10766,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
||||||
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"punycode": "^2.3.0"
|
"punycode": "^2.3.0"
|
||||||
},
|
},
|
||||||
@@ -10787,7 +10777,6 @@
|
|||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -10796,7 +10785,6 @@
|
|||||||
"version": "13.0.0",
|
"version": "13.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
|
||||||
"integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
|
"integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tr46": "^4.1.1",
|
"tr46": "^4.1.1",
|
||||||
"webidl-conversions": "^7.0.0"
|
"webidl-conversions": "^7.0.0"
|
||||||
@@ -10806,13 +10794,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose": {
|
"node_modules/mongoose": {
|
||||||
"version": "8.5.4",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.0.tgz",
|
||||||
"integrity": "sha512-nG3eehhWf9l1q80WuHvp5DV+4xDNFpDWLE5ZgcFD5tslUV2USJ56ogun8gaZ62MKAocJnoStjAdno08b8U57hg==",
|
"integrity": "sha512-p6VSbYKvD4ZIabqo8C0kS5eKX1Xpji+opTAIJ9wyuPJ8Y/FblgXSMnFRXnB40bYZLKPQT089K5KU8+bqIXtFdw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bson": "^6.7.0",
|
"bson": "^6.7.0",
|
||||||
"kareem": "2.6.3",
|
"kareem": "2.6.3",
|
||||||
"mongodb": "6.7.0",
|
"mongodb": "6.8.0",
|
||||||
"mpath": "0.9.0",
|
"mpath": "0.9.0",
|
||||||
"mquery": "5.0.0",
|
"mquery": "5.0.0",
|
||||||
"ms": "2.1.3",
|
"ms": "2.1.3",
|
||||||
@@ -10830,7 +10818,6 @@
|
|||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10844,7 +10831,6 @@
|
|||||||
"version": "5.1.3",
|
"version": "5.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz",
|
||||||
"integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==",
|
"integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10861,7 +10847,6 @@
|
|||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz",
|
||||||
"integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==",
|
"integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10876,7 +10861,6 @@
|
|||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10888,10 +10872,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose/node_modules/mongodb": {
|
"node_modules/mongoose/node_modules/mongodb": {
|
||||||
"version": "6.7.0",
|
"version": "6.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz",
|
||||||
"integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==",
|
"integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mongodb-js/saslprep": "^1.1.5",
|
"@mongodb-js/saslprep": "^1.1.5",
|
||||||
"bson": "^6.7.0",
|
"bson": "^6.7.0",
|
||||||
@@ -13231,7 +13214,6 @@
|
|||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||||
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"memory-pager": "^1.0.2"
|
"memory-pager": "^1.0.2"
|
||||||
}
|
}
|
||||||
@@ -13573,9 +13555,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/stylelint": {
|
"node_modules/stylelint": {
|
||||||
"version": "16.8.2",
|
"version": "16.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.9.0.tgz",
|
||||||
"integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==",
|
"integrity": "sha512-31Nm3WjxGOBGpQqF43o3wO9L5AC36TPIe6030Lnm13H3vDMTcS21DrLh69bMX+DBilKqMMVLian4iG6ybBoNRQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -13588,9 +13570,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-parser-algorithms": "^3.0.0",
|
"@csstools/css-parser-algorithms": "^3.0.1",
|
||||||
"@csstools/css-tokenizer": "^3.0.0",
|
"@csstools/css-tokenizer": "^3.0.1",
|
||||||
"@csstools/media-query-list-parser": "^3.0.0",
|
"@csstools/media-query-list-parser": "^3.0.1",
|
||||||
"@csstools/selector-specificity": "^4.0.0",
|
"@csstools/selector-specificity": "^4.0.0",
|
||||||
"@dual-bundle/import-meta-resolve": "^4.1.0",
|
"@dual-bundle/import-meta-resolve": "^4.1.0",
|
||||||
"balanced-match": "^2.0.0",
|
"balanced-match": "^2.0.0",
|
||||||
@@ -13612,7 +13594,7 @@
|
|||||||
"known-css-properties": "^0.34.0",
|
"known-css-properties": "^0.34.0",
|
||||||
"mathml-tag-names": "^2.1.3",
|
"mathml-tag-names": "^2.1.3",
|
||||||
"meow": "^13.2.0",
|
"meow": "^13.2.0",
|
||||||
"micromatch": "^4.0.7",
|
"micromatch": "^4.0.8",
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picocolors": "^1.0.1",
|
"picocolors": "^1.0.1",
|
||||||
"postcss": "^8.4.41",
|
"postcss": "^8.4.41",
|
||||||
@@ -13623,7 +13605,7 @@
|
|||||||
"resolve-from": "^5.0.0",
|
"resolve-from": "^5.0.0",
|
||||||
"string-width": "^4.2.3",
|
"string-width": "^4.2.3",
|
||||||
"strip-ansi": "^7.1.0",
|
"strip-ansi": "^7.1.0",
|
||||||
"supports-hyperlinks": "^3.0.0",
|
"supports-hyperlinks": "^3.1.0",
|
||||||
"svg-tags": "^1.0.0",
|
"svg-tags": "^1.0.0",
|
||||||
"table": "^6.8.2",
|
"table": "^6.8.2",
|
||||||
"write-file-atomic": "^5.0.1"
|
"write-file-atomic": "^5.0.1"
|
||||||
@@ -13684,70 +13666,6 @@
|
|||||||
"stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1"
|
"stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stylelint/node_modules/@csstools/css-parser-algorithms": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@csstools/css-tokenizer": "^3.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/stylelint/node_modules/@csstools/css-tokenizer": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/stylelint/node_modules/@csstools/media-query-list-parser": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@csstools/css-parser-algorithms": "^3.0.1",
|
|
||||||
"@csstools/css-tokenizer": "^3.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/stylelint/node_modules/ansi-regex": {
|
"node_modules/stylelint/node_modules/ansi-regex": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||||
@@ -13947,17 +13865,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/supports-hyperlinks": {
|
"node_modules/supports-hyperlinks": {
|
||||||
"version": "3.0.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz",
|
||||||
"integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
|
"integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-flag": "^4.0.0",
|
"has-flag": "^4.0.0",
|
||||||
"supports-color": "^7.0.0"
|
"supports-color": "^7.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.18"
|
"node": ">=14.18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/supports-hyperlinks/node_modules/has-flag": {
|
"node_modules/supports-hyperlinks/node_modules/has-flag": {
|
||||||
@@ -13965,7 +13885,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -13975,7 +13894,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-flag": "^4.0.0"
|
"has-flag": "^4.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
14
package.json
14
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "homebrewery",
|
"name": "homebrewery",
|
||||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||||
"version": "3.14.2",
|
"version": "3.15.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"npm": "^10.2.x",
|
"npm": "^10.2.x",
|
||||||
"node": "^20.8.x"
|
"node": "^20.8.x"
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
"@babel/plugin-transform-runtime": "^7.25.4",
|
"@babel/plugin-transform-runtime": "^7.25.4",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.25.4",
|
||||||
"@babel/preset-react": "^7.24.7",
|
"@babel/preset-react": "^7.24.7",
|
||||||
"@googleapis/drive": "^8.13.0",
|
"@googleapis/drive": "^8.14.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
@@ -108,12 +108,12 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "11.2.0",
|
"marked": "11.2.0",
|
||||||
"marked-emoji": "^1.4.2",
|
"marked-emoji": "^1.4.2",
|
||||||
"marked-extended-tables": "^1.0.8",
|
"marked-extended-tables": "^1.0.10",
|
||||||
"marked-gfm-heading-id": "^3.2.0",
|
"marked-gfm-heading-id": "^3.2.0",
|
||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.5.4",
|
"mongoose": "^8.6.0",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@@ -127,13 +127,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-jest": "^28.8.0",
|
"eslint-plugin-jest": "^28.8.2",
|
||||||
"eslint-plugin-react": "^7.35.0",
|
"eslint-plugin-react": "^7.35.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
"postcss-less": "^6.0.0",
|
"postcss-less": "^6.0.0",
|
||||||
"stylelint": "^16.8.2",
|
"stylelint": "^16.9.0",
|
||||||
"stylelint-config-recess-order": "^5.1.0",
|
"stylelint-config-recess-order": "^5.1.0",
|
||||||
"stylelint-config-recommended": "^14.0.1",
|
"stylelint-config-recommended": "^14.0.1",
|
||||||
"supertest": "^7.0.0"
|
"supertest": "^7.0.0"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ app.use((req, res, next)=>{
|
|||||||
|
|
||||||
app.use(homebrewApi);
|
app.use(homebrewApi);
|
||||||
app.use(require('./admin.api.js'));
|
app.use(require('./admin.api.js'));
|
||||||
|
app.use(require('./vault.api.js'));
|
||||||
|
|
||||||
const HomebrewModel = require('./homebrew.model.js').model;
|
const HomebrewModel = require('./homebrew.model.js').model;
|
||||||
const welcomeText = require('fs').readFileSync('client/homebrew/pages/homePage/welcome_msg.md', 'utf8');
|
const welcomeText = require('fs').readFileSync('client/homebrew/pages/homePage/welcome_msg.md', 'utf8');
|
||||||
@@ -361,6 +362,15 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
|||||||
const data = {};
|
const data = {};
|
||||||
data.title = 'Account Information Page';
|
data.title = 'Account Information Page';
|
||||||
|
|
||||||
|
if(!req.account) {
|
||||||
|
res.set('WWW-Authenticate', 'Bearer realm="Authorization Required"');
|
||||||
|
const error = new Error('No valid account');
|
||||||
|
error.status = 401;
|
||||||
|
error.HBErrorCode = '50';
|
||||||
|
error.page = data.title;
|
||||||
|
return next(error);
|
||||||
|
};
|
||||||
|
|
||||||
let auth;
|
let auth;
|
||||||
let googleCount = [];
|
let googleCount = [];
|
||||||
if(req.account) {
|
if(req.account) {
|
||||||
@@ -424,6 +434,11 @@ if(isLocalEnvironment){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Vault Page
|
||||||
|
app.get('/vault', asyncHandler(async(req, res, next)=>{
|
||||||
|
return next();
|
||||||
|
}));
|
||||||
|
|
||||||
//Send rendered page
|
//Send rendered page
|
||||||
app.use(asyncHandler(async (req, res, next)=>{
|
app.use(asyncHandler(async (req, res, next)=>{
|
||||||
if (!req.route) return res.redirect('/'); // Catch-all for invalid routes
|
if (!req.route) return res.redirect('/'); // Catch-all for invalid routes
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ const api = {
|
|||||||
stub = stub?.toObject();
|
stub = stub?.toObject();
|
||||||
|
|
||||||
if(stub?.lock?.locked && accessType != 'edit') {
|
if(stub?.lock?.locked && accessType != 'edit') {
|
||||||
throw { HBErrorCode: '100', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title };
|
throw { HBErrorCode: '51', code: stub.lock.code, message: stub.lock.shareMessage, brewId: stub.shareId, brewTitle: stub.title };
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a google id, try to find the google brew
|
// If there is a google id, try to find the google brew
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ describe('Tests for api', ()=>{
|
|||||||
const req = { brew: {} };
|
const req = { brew: {} };
|
||||||
const next = jest.fn();
|
const next = jest.fn();
|
||||||
|
|
||||||
await expect(fn(req, null, next)).rejects.toEqual({ 'HBErrorCode': '100', 'brewId': '1', 'brewTitle': 'test brew', 'code': 404, 'message': 'brew locked' });
|
await expect(fn(req, null, next)).rejects.toEqual({ 'HBErrorCode': '51', 'brewId': '1', 'brewTitle': 'test brew', 'code': 404, 'message': 'brew locked' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
102
server/vault.api.js
Normal file
102
server/vault.api.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const asyncHandler = require('express-async-handler');
|
||||||
|
const HomebrewModel = require('./homebrew.model.js').model;
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const titleConditions = (title)=>{
|
||||||
|
if(!title) return {};
|
||||||
|
return {
|
||||||
|
$text : {
|
||||||
|
$search : title,
|
||||||
|
$caseSensitive : false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const authorConditions = (author)=>{
|
||||||
|
if(!author) return {};
|
||||||
|
return { authors: author };
|
||||||
|
};
|
||||||
|
|
||||||
|
const rendererConditions = (legacy, v3)=>{
|
||||||
|
if(legacy === 'true' && v3 !== 'true')
|
||||||
|
return { renderer: 'legacy' };
|
||||||
|
|
||||||
|
if(v3 === 'true' && legacy !== 'true')
|
||||||
|
return { renderer: 'V3' };
|
||||||
|
|
||||||
|
return {}; // If all renderers selected, renderer field not needed in query for speed
|
||||||
|
};
|
||||||
|
|
||||||
|
const findBrews = async (req, res)=>{
|
||||||
|
const title = req.query.title || '';
|
||||||
|
const author = req.query.author || '';
|
||||||
|
const page = Math.max(parseInt(req.query.page) || 1, 1);
|
||||||
|
const count = Math.max(parseInt(req.query.count) || 20, 10);
|
||||||
|
const skip = (page - 1) * count;
|
||||||
|
|
||||||
|
const combinedQuery = {
|
||||||
|
$and : [
|
||||||
|
{ published: true },
|
||||||
|
rendererConditions(req.query.legacy, req.query.v3),
|
||||||
|
titleConditions(title),
|
||||||
|
authorConditions(author)
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const projection = {
|
||||||
|
editId : 0,
|
||||||
|
googleId : 0,
|
||||||
|
text : 0,
|
||||||
|
textBin : 0,
|
||||||
|
version : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
await HomebrewModel.find(combinedQuery, projection)
|
||||||
|
.skip(skip)
|
||||||
|
.limit(count)
|
||||||
|
.maxTimeMS(5000)
|
||||||
|
.exec()
|
||||||
|
.then((brews)=>{
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
|
const processedBrews = brews.map((brew)=>{
|
||||||
|
brew.authors = brew.authors.map((author)=>emailRegex.test(author) ? 'hidden' : author
|
||||||
|
);
|
||||||
|
return brew;
|
||||||
|
});
|
||||||
|
res.json({ brews: processedBrews, page });
|
||||||
|
})
|
||||||
|
.catch((error)=>{
|
||||||
|
throw { ...error, message: 'Error finding brews in Vault search', HBErrorCode: 90 };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const findTotal = async (req, res)=>{
|
||||||
|
const title = req.query.title || '';
|
||||||
|
const author = req.query.author || '';
|
||||||
|
|
||||||
|
const combinedQuery = {
|
||||||
|
$and : [
|
||||||
|
{ published: true },
|
||||||
|
rendererConditions(req.query.legacy, req.query.v3),
|
||||||
|
titleConditions(title),
|
||||||
|
authorConditions(author)
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
await HomebrewModel.countDocuments(combinedQuery)
|
||||||
|
.then((totalBrews)=>{
|
||||||
|
console.log(`when returning, the total of brews is ${totalBrews} for the query ${JSON.stringify(combinedQuery)}`);
|
||||||
|
res.json({ totalBrews });
|
||||||
|
})
|
||||||
|
.catch((error)=>{
|
||||||
|
throw { ...error, message: 'Error finding brews in Vault search findTotal function', HBErrorCode: 91 };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
router.get('/api/vault/total', asyncHandler(findTotal));
|
||||||
|
router.get('/api/vault', asyncHandler(findBrews));
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -102,6 +102,20 @@ renderer.link = function (href, title, text) {
|
|||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Expose `src` attribute as `--HB_src` to make the URL accessible via CSS
|
||||||
|
renderer.image = function (href, title, text) {
|
||||||
|
href = cleanUrl(href);
|
||||||
|
if (href === null)
|
||||||
|
return text;
|
||||||
|
|
||||||
|
let out = `<img src="${href}" alt="${text}" style="--HB_src:url(${href});"`;
|
||||||
|
if (title)
|
||||||
|
out += ` title="${title}"`;
|
||||||
|
|
||||||
|
out += '>';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable default reflink behavior, as it steps on our variables extension
|
// Disable default reflink behavior, as it steps on our variables extension
|
||||||
tokenizer.def = function () {
|
tokenizer.def = function () {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -727,12 +741,18 @@ const MarkedEmojiOptions = {
|
|||||||
renderer : (token)=>`<i class="${token.emoji}"></i>`
|
renderer : (token)=>`<i class="${token.emoji}"></i>`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tableTerminators = [
|
||||||
|
`:+\\n`, // hardBreak
|
||||||
|
` *{[^\n]+}`, // blockInjector
|
||||||
|
` *{{[^{\n]*\n.*?\n}}` // mustacheDiv
|
||||||
|
]
|
||||||
|
|
||||||
Marked.use(MarkedVariables());
|
Marked.use(MarkedVariables());
|
||||||
Marked.use({ extensions : [definitionListsMultiLine, definitionListsSingleLine, forcedParagraphBreaks, superSubScripts,
|
Marked.use({ extensions : [definitionListsMultiLine, definitionListsSingleLine, forcedParagraphBreaks, superSubScripts,
|
||||||
mustacheSpans, mustacheDivs, mustacheInjectInline] });
|
mustacheSpans, mustacheDivs, mustacheInjectInline] });
|
||||||
Marked.use(mustacheInjectBlock);
|
Marked.use(mustacheInjectBlock);
|
||||||
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
|
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
|
||||||
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId({ globalSlugs: true }), MarkedSmartypantsLite(), MarkedEmojis(MarkedEmojiOptions));
|
Marked.use(MarkedExtendedTables(tableTerminators), MarkedGFMHeadingId({ globalSlugs: true }), MarkedSmartypantsLite(), MarkedEmojis(MarkedEmojiOptions));
|
||||||
|
|
||||||
function cleanUrl(href) {
|
function cleanUrl(href) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ const SplitPane = createClass({
|
|||||||
getDefaultProps : function() {
|
getDefaultProps : function() {
|
||||||
return {
|
return {
|
||||||
storageKey : 'naturalcrit-pane-split',
|
storageKey : 'naturalcrit-pane-split',
|
||||||
onDragFinish : function(){} //fires when dragging
|
onDragFinish : function(){}, //fires when dragging
|
||||||
|
showDividerButtons : true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -18,8 +19,7 @@ const SplitPane = createClass({
|
|||||||
windowWidth : 0,
|
windowWidth : 0,
|
||||||
isDragging : false,
|
isDragging : false,
|
||||||
moveSource : false,
|
moveSource : false,
|
||||||
moveBrew : false,
|
moveBrew : false
|
||||||
showMoveArrows : true
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -142,9 +142,11 @@ const SplitPane = createClass({
|
|||||||
width={this.state.currentDividerPos}
|
width={this.state.currentDividerPos}
|
||||||
>
|
>
|
||||||
{React.cloneElement(this.props.children[0], {
|
{React.cloneElement(this.props.children[0], {
|
||||||
|
...(this.props.showDividerButtons && {
|
||||||
moveBrew: this.state.moveBrew,
|
moveBrew: this.state.moveBrew,
|
||||||
moveSource: this.state.moveSource,
|
moveSource: this.state.moveSource,
|
||||||
setMoveArrows : this.setMoveArrows
|
setMoveArrows: this.setMoveArrows,
|
||||||
|
}),
|
||||||
})}
|
})}
|
||||||
</Pane>
|
</Pane>
|
||||||
{this.renderDivider()}
|
{this.renderDivider()}
|
||||||
|
|||||||
@@ -322,9 +322,9 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders an image element with injected style', function() {
|
it('Renders an image element with injected style', function() {
|
||||||
const source = '{position:absolute}';
|
const source = '{position:absolute}';
|
||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img style="position:absolute;" src="http://i.imgur.com/hMna6G0.png" alt="alt text"></p>');
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img style="--HB_src:url(https://i.imgur.com/hMna6G0.png); position:absolute;" src="https://i.imgur.com/hMna6G0.png" alt="alt text"></p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders an element modified by only the first of two consecutive injections', function() {
|
it('Renders an element modified by only the first of two consecutive injections', function() {
|
||||||
@@ -343,19 +343,19 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
|||||||
it('Renders an image with added attributes', function() {
|
it('Renders an image with added attributes', function() {
|
||||||
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
|
const source = ` {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).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e"></p>`);
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="--HB_src:url(https://i.imgur.com/hMna6G0.png); position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e"></p>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders an image with "=" in the url, and added attributes', function() {
|
it('Renders an image with "=" in the url, and added attributes', function() {
|
||||||
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
|
const source = ` {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).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png?auth=12345&height=1024" alt="homebrew mug" a="b and c" d="e"></p>`);
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="--HB_src:url(https://i.imgur.com/hMna6G0.png?auth=12345&height=1024); position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png?auth=12345&height=1024" alt="homebrew mug" a="b and c" d="e"></p>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders an image and added attributes with "=" in the value, ', function() {
|
it('Renders an image and added attributes with "=" in the value, ', function() {
|
||||||
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e,otherUrl="url?auth=12345"}`;
|
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e,otherUrl="url?auth=12345"}`;
|
||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e" otherUrl="url?auth=12345"></p>`);
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="--HB_src:url(https://i.imgur.com/hMna6G0.png); position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e" otherUrl="url?auth=12345"></p>`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -315,21 +315,21 @@ describe('Normal Links and Images', ()=>{
|
|||||||
const source = ``;
|
const source = ``;
|
||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
||||||
<p><img src="url" alt="alt text"></p>`.trimReturns());
|
<p><img src="url" alt="alt text" style="--HB_src:url(url);"></p>`.trimReturns());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders normal images with a title', function() {
|
it('Renders normal images with a title', function() {
|
||||||
const source = 'An image !';
|
const source = 'An image !';
|
||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
||||||
<p>An image <img src="url" alt="alt text" title="and title">!</p>`.trimReturns());
|
<p>An image <img src="url" alt="alt text" style="--HB_src:url(url);" title="and title">!</p>`.trimReturns());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Applies curly injectors to images', function() {
|
it('Applies curly injectors to images', function() {
|
||||||
const source = `{width:100px}`;
|
const source = `{width:100px}`;
|
||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
||||||
<p><img style="width:100px;" src="url" alt="alt text"></p>`.trimReturns());
|
<p><img style="--HB_src:url(url); width:100px;" src="url" alt="alt text"></p>`.trimReturns());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders normal links', function() {
|
it('Renders normal links', function() {
|
||||||
|
|||||||
@@ -153,6 +153,18 @@ module.exports = [
|
|||||||
gen : dedent`
|
gen : dedent`
|
||||||
 {width:325px,mix-blend-mode:multiply}`
|
 {width:325px,mix-blend-mode:multiply}`
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name : 'Image Wrap Left',
|
||||||
|
icon : 'fac image-wrap-left',
|
||||||
|
gen : dedent`
|
||||||
|
 {width:280px,margin-right:-3cm,wrapLeft}`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'Image Wrap Right',
|
||||||
|
icon : 'fac image-wrap-right',
|
||||||
|
gen : dedent`
|
||||||
|
 {width:280px,margin-left:-3cm,wrapRight}`
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name : 'Background Image',
|
name : 'Background Image',
|
||||||
icon : 'fas fa-tree',
|
icon : 'fas fa-tree',
|
||||||
|
|||||||
@@ -156,6 +156,19 @@ body { counter-reset : page-numbers; }
|
|||||||
break-inside : avoid;
|
break-inside : avoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrap Text */
|
||||||
|
.wrapLeft {
|
||||||
|
shape-outside : var(--HB_src);
|
||||||
|
float : right;
|
||||||
|
shape-margin : 0.2cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapRight {
|
||||||
|
shape-outside : var(--HB_src);
|
||||||
|
float : left;
|
||||||
|
shape-margin : 0.2cm;
|
||||||
|
}
|
||||||
|
|
||||||
/* Watermark */
|
/* Watermark */
|
||||||
.watermark {
|
.watermark {
|
||||||
position : absolute;
|
position : absolute;
|
||||||
|
|||||||
Reference in New Issue
Block a user