Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add blocking notification to EditPage #3382

Merged
merged 48 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
963ec28
Initial functionality pass
G-Ambatte Mar 29, 2024
fde1706
Merge branch 'master' into addLockNotification-#3326
G-Ambatte Apr 20, 2024
4bc07ce
Nudge line and button spacing
G-Ambatte Apr 20, 2024
b4b4fbe
Update fixed text and add REMOVAL button (NYI)
G-Ambatte Apr 20, 2024
4c6953a
Differentiate between Edit and Share messages
G-Ambatte Apr 20, 2024
09cf5a9
Fix test
G-Ambatte Apr 20, 2024
9f31a2c
I can spell, honest
G-Ambatte Apr 20, 2024
3a054f1
Merge branch 'master' into addLockNotification-#3326
G-Ambatte May 9, 2024
10a7f34
Update lock message
G-Ambatte May 9, 2024
f6daeb4
Update error message
G-Ambatte May 9, 2024
bf38f95
Pass ID to Lock Notification
G-Ambatte May 9, 2024
632efe8
Add Share ID to lock notification
G-Ambatte May 9, 2024
2424d34
Merge branch 'master' into addLockNotification-#3326
G-Ambatte Jun 1, 2024
a6ce366
Shift NotificationPopup to shared components & update BrewRenderer ref
G-Ambatte Jun 1, 2024
9307092
Lint fix
G-Ambatte Jun 1, 2024
8685c5c
Break Dialog out of NotificationPopup, restore NotificationPopup to o…
G-Ambatte Jun 4, 2024
f3b01bc
Fix for modals
G-Ambatte Jun 4, 2024
1111d82
Tweak dismiss button styling
G-Ambatte Jun 4, 2024
e7735e2
Add closeText prop
G-Ambatte Jun 4, 2024
05ba7b4
Tweak NotificationPopup
G-Ambatte Jun 4, 2024
865c567
Change all Modal references to Dialog
G-Ambatte Jun 4, 2024
5f6d5f5
Change dismiss button to use fa-dismiss
G-Ambatte Jun 4, 2024
24e67e2
Restore Info Circle to notification
G-Ambatte Jun 4, 2024
491b38c
Small cleanup of Dialog component
calculuschild Jun 4, 2024
99ff7fd
linting
calculuschild Jun 4, 2024
7272544
Convert LockNotification.jsx to functional component
calculuschild Jun 4, 2024
ec514cd
Set local storage only if dismissKey prop exists
G-Ambatte Jun 4, 2024
423413e
Merge branch 'master' into addLockNotification-#3326
calculuschild Jun 4, 2024
31b6e0c
Show dialog when dismissKey prop is not specified
G-Ambatte Jun 5, 2024
0efcd5d
Shift LockNotification to use Dialog
G-Ambatte Jun 5, 2024
556ded9
Tweak Dialog to work with showModal and show LockNotifications
G-Ambatte Jun 6, 2024
4f4cef0
Tweak LockNotification styling
G-Ambatte Jun 6, 2024
9e041d2
Fix display property on dialog causing close() to not work
G-Ambatte Jun 6, 2024
fa7b3ea
Shift dismiss button, tweak local storage check
G-Ambatte Jun 6, 2024
38fc647
Change NotificationPopup to inline-block from block
G-Ambatte Jun 6, 2024
ed39852
Move dialog[open] to Dialog component styling
G-Ambatte Jun 6, 2024
866548d
Move renderWarnings to use Dialog
G-Ambatte Jun 6, 2024
359a649
Nudge popups left
G-Ambatte Jun 6, 2024
8c31598
Revert dismiss styling to opacity change on hover
G-Ambatte Jun 6, 2024
7bb92bc
Refactor slightly
calculuschild Jun 6, 2024
54ec1b8
Comment out dialog.less reference
G-Ambatte Jun 6, 2024
476002a
Tweak notificationPopup.less
G-Ambatte Jun 6, 2024
8bbf2e1
Dim background while Modal displayed
G-Ambatte Jun 6, 2024
33c2bee
Remove unused useState
G-Ambatte Jun 7, 2024
08b61a6
Cleanup comments. Fix Indentation.
calculuschild Jun 7, 2024
fdf6acd
Lint notificationPopup.less
calculuschild Jun 7, 2024
6577078
Lint lockNotification.less
calculuschild Jun 7, 2024
66fdf80
Lint renderWarnings.less
calculuschild Jun 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions client/components/dialog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Dialog box, for popups and modal blocking messages
const React = require('react');
const { useRef, useEffect } = React;

function Dialog({ dismissKey, closeText = 'Close', blocking = false, ...rest }) {
const dialogRef = useRef(null);

useEffect(()=>{
if(!dismissKey || !localStorage.getItem(dismissKey)) {
blocking ? dialogRef.current?.showModal() : dialogRef.current?.show();
}
}, []);

const dismiss = ()=>{
dismissKey && localStorage.setItem(dismissKey, true);
dialogRef.current?.close();
};

return (
<dialog ref={dialogRef} onCancel={dismiss} {...rest}>
{rest.children}
<button className='dismiss' onClick={dismiss}>
{closeText}
</button>
</dialog>
);
};

export default Dialog;
11 changes: 6 additions & 5 deletions client/homebrew/brewRenderer/brewRenderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ const BrewRenderer = (props)=>{
</div>
: null}

<ErrorBar errors={props.errors} />
<div className='popups'>
<RenderWarnings />
<NotificationPopup />
</div>

{/*render in iFrame so broken code doesn't crash the site.*/}
<Frame id='BrewRenderer' initialContent={INITIAL_CONTENT}
style={{ width: '100%', height: '100%', visibility: state.visibility }}
Expand All @@ -215,11 +221,6 @@ const BrewRenderer = (props)=>{
tabIndex={-1}
style={{ height: state.height }}>

<ErrorBar errors={props.errors} />
<div className='popups'>
<RenderWarnings />
<NotificationPopup />
</div>
<link href={`/themes/${rendererPath}/Blank/style.css`} type='text/css' rel='stylesheet'/>
{baseThemePath &&
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} type='text/css' rel='stylesheet'/>
Expand Down
105 changes: 35 additions & 70 deletions client/homebrew/brewRenderer/notificationPopup/notificationPopup.jsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,45 @@
require('./notificationPopup.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');

const DISMISS_KEY = 'dismiss_notification12-04-23';

const NotificationPopup = createClass({
displayName : 'NotificationPopup',
getInitialState : function() {
return {
notifications : {}
};
},
componentDidMount : function() {
this.checkNotifications();
window.addEventListener('resize', this.checkNotifications);
},
componentWillUnmount : function() {
window.removeEventListener('resize', this.checkNotifications);
},
notifications : {
psa : function(){
return (
<>
<li key='psa'>
<em>Don't store IMAGES in Google Drive</em><br />
Google Drive is not an image service, and will block images from being used
in brews if they get more views than expected. Google has confirmed they won't fix
this, so we recommend you look for another image hosting service such as imgur, ImgBB or Google Photos.
</li>
import Dialog from '../../../components/dialog.jsx';

<li key='googleDriveFolder'>
<em>Don't delete your Homebrewery folder on Google Drive!</em> <br />
We have had several reports of users losing their brews, not realizing
that they had deleted the files on their Google Drive. If you have a Homebrewery folder
on your Google Drive with *.txt files inside, <em>do not delete it</em>!
We cannot help you recover files that you have deleted from your own
Google Drive.
</li>
const DISMISS_KEY = 'dismiss_notification12-04-23';
const DISMISS_BUTTON = <i className='fas fa-times dismiss' />;

<li key='faq'>
<em>Protect your work! </em> <br />
If you opt not to use your Google Drive, keep in mind that we do not save a history of your projects. Please make frequent backups of your brews!&nbsp;
<a target='_blank' href='https://www.reddit.com/r/homebrewery/comments/adh6lh/faqs_psas_announcements/'>
See the FAQ
</a> to learn how to avoid losing your work!
</li>
</>
);
}
},
checkNotifications : function(){
const hideDismiss = localStorage.getItem(DISMISS_KEY);
if(hideDismiss) return this.setState({ notifications: {} });
const NotificationPopup = ()=>{
return <Dialog className='notificationPopup' dismissKey={DISMISS_KEY} closeText={DISMISS_BUTTON} >
<div className='header'>
<i className='fas fa-info-circle info'></i>
<h3>Notice</h3>
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
</div>
<ul>
<li key='psa'>
<em>Don't store IMAGES in Google Drive</em><br />
Google Drive is not an image service, and will block images from being used
in brews if they get more views than expected. Google has confirmed they won't fix
this, so we recommend you look for another image hosting service such as imgur, ImgBB or Google Photos.
</li>

this.setState({
notifications : _.mapValues(this.notifications, (fn)=>{ return fn(); }) //Convert notification functions into their return text value
});
},
dismiss : function(){
localStorage.setItem(DISMISS_KEY, true);
this.checkNotifications();
},
render : function(){
if(_.isEmpty(this.state.notifications)) return null;
<li key='googleDriveFolder'>
<em>Don't delete your Homebrewery folder on Google Drive!</em> <br />
We have had several reports of users losing their brews, not realizing
that they had deleted the files on their Google Drive. If you have a Homebrewery folder
on your Google Drive with *.txt files inside, <em>do not delete it</em>!
We cannot help you recover files that you have deleted from your own
Google Drive.
</li>

return <div className='notificationPopup'>
<i className='fas fa-times dismiss' onClick={this.dismiss}/>
<i className='fas fa-info-circle info' />
<div className='header'>
<h3>Notice</h3>
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
</div>
<ul>{_.values(this.state.notifications)}</ul>
</div>;
}
});
<li key='faq'>
<em>Protect your work! </em> <br />
If you opt not to use your Google Drive, keep in mind that we do not save a history of your projects. Please make frequent backups of your brews!&nbsp;
<a target='_blank' href='https://www.reddit.com/r/homebrewery/comments/adh6lh/faqs_psas_announcements/'>
See the FAQ
</a> to learn how to avoid losing your work!
</li>
</ul>
</Dialog>;
};

module.exports = NotificationPopup;
Original file line number Diff line number Diff line change
@@ -1,64 +1,60 @@
.popups{
.popups {
position : fixed;
top : @navbarHeight;
right : 15px;
right : 24px;
z-index : 10001;
width : 450px;
}

.notificationPopup{
.notificationPopup {
position : relative;
display : inline-block;
width : 100%;
padding : 15px;
padding-bottom : 10px;
padding-left : 25px;
background-color : @blue;
color : white;
a{
color : #e0e5c1;
background-color : @blue;
border : none;
&[open] { display : inline-block; }
a {
font-weight : 800;
color : #E0E5C1;
}
i.info{
i.info {
position : absolute;
top : 12px;
left : 12px;
opacity : 0.8;
font-size : 2.5em;
opacity : 0.8;
}
i.dismiss{
position : absolute;
top : 10px;
right : 10px;
cursor : pointer;
opacity : 0.6;
&:hover{
opacity : 1;
}
}
.header {
padding-left : 50px;
button.dismiss {
position : absolute;
top : 10px;
right : 10px;
cursor : pointer;
background-color : transparent;
opacity : 0.6;
&:hover { opacity : 1; }
}
small{
opacity : 0.7;
.header { padding-left : 50px; }
small {
font-size : 0.6em;
opacity : 0.7;
}
h3{
h3 {
font-size : 1.1em;
font-weight : 800;
}
ul{
ul {
margin-top : 15px;
font-size : 0.8em;
list-style-position : outside;
list-style-type : disc;
li{
li {
margin-top : 1.4em;
font-size : 0.8em;
line-height : 1.4em;
margin-top : 1.4em;
em{
font-weight : 800;
}
em { font-weight : 800; }
}
}
}
6 changes: 5 additions & 1 deletion client/homebrew/pages/editPage/editPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
const Editor = require('../../editor/editor.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');

const LockNotification = require('./lockNotification/lockNotification.jsx');

const Markdown = require('naturalcrit/markdown.js');

const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
Expand Down Expand Up @@ -52,7 +54,8 @@ const EditPage = createClass({
autoSave : true,
autoSaveWarning : false,
unsavedTime : new Date(),
currentEditorPage : 0
currentEditorPage : 0,
displayLockMessage : this.props.brew.lock || false
};
},

Expand Down Expand Up @@ -393,6 +396,7 @@ const EditPage = createClass({
{this.renderNavbar()}

<div className='content'>
{this.props.brew.lock && <LockNotification shareId={this.props.brew.shareId} message={this.props.brew.lock.editMessage} />}
<SplitPane onDragFinish={this.handleSplitMove}>
<Editor
ref={this.editor}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require('./lockNotification.less');
const React = require('react');
import Dialog from '../../../../components/dialog.jsx';

function LockNotification(props) {
props = {
shareId : 0,
disableLock : ()=>{},
message : '',
...props
};

const removeLock = ()=>{
alert(`Not yet implemented - ID ${props.shareId}`);
};

return <Dialog className='lockNotification' blocking closeText='CONTINUE TO EDITOR' >
<h1>BREW LOCKED</h1>
<p>This brew been locked by the Administrators. It will not be accessible by any method other than the Editor until the lock is removed.</p>
<hr />
<h3>LOCK REASON</h3>
<p>{props.message || 'Unable to retrieve Lock Message'}</p>
<hr />
<p>Once you have resolved this issue, click REQUEST LOCK REMOVAL to notify the Administrators for review.</p>
<p>Click CONTINUE TO EDITOR to temporarily hide this notification; it will reappear the next time the page is reloaded.</p>
<button onClick={removeLock}>REQUEST LOCK REMOVAL</button>
</Dialog>;
};

module.exports = LockNotification;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.lockNotification {
z-index : 1;
width : 80%;
padding : 10px;
margin : 5% 10%;
line-height : 1.5em;
color : black;
text-align : center;
background-color : #CCCCCC;

&::backdrop { background-color : #000000AA; }

button {
margin : 10px;
color : white;
background-color : #333333;

&:hover { background-color : #777777; }
}

h1, h3 {
font-family : 'Open Sans', sans-serif;
font-weight : 800;
}
h1 { font-size : 24px; }
h3 { font-size : 18px; }
}
2 changes: 1 addition & 1 deletion client/homebrew/pages/errorPage/errors/errorIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ const errorIndex = (props)=>{
'100' : dedent`
## This brew has been locked.

Please contact the Administrators to unlock this document.
Only an author may request that this lock is removed.

:

Expand Down
2 changes: 1 addition & 1 deletion server/homebrew.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const api = {
stub = stub?.toObject();

if(stub?.lock?.locked && accessType != 'edit') {
throw { HBErrorCode: '100', code: stub.lock.code, message: stub.lock.message, brewId: stub.shareId, brewTitle: stub.title };
throw { HBErrorCode: '100', 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
Expand Down
2 changes: 1 addition & 1 deletion server/homebrew.api.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ describe('Tests for api', ()=>{
});

it('access is denied to a locked brew', async()=>{
const lockBrew = { title: 'test brew', shareId: '1', lock: { locked: true, code: 404, message: 'brew locked' } };
const lockBrew = { title: 'test brew', shareId: '1', lock: { locked: true, code: 404, shareMessage: 'brew locked' } };
model.get = jest.fn(()=>toBrewPromise(lockBrew));
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));

Expand Down
Loading