0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-02 04:12:47 +00:00

create error navitem and use it in all necessary use cases

This commit is contained in:
Charlie Humphreys
2023-01-21 00:25:35 -06:00
parent 7755affa1e
commit 79db97efdf
12 changed files with 133 additions and 113 deletions

View File

@@ -0,0 +1,84 @@
require('./error-navitem.less');
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const createClass = require('create-react-class');
const ErrorNavItem = createClass({
getDefaultProps : function() {
return {
error : '',
parent : null
};
},
render : function() {
const clearError = ()=>{
const state = {
error : null
};
if(this.props.parent.state.isSaving) {
state.isSaving = false;
}
this.props.parent.setState(state);
};
const error = this.props.error;
const status = error.status;
const message = error.body?.message;
let errMsg = '';
try {
errMsg += `${error.toString()}\n\n`;
errMsg += `\`\`\`\n${error.stack}\n`;
errMsg += `${JSON.stringify(error.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(status === 409) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Conflict: please refresh to get latest changes'}
</div>
</Nav.item>;
} else if(status === 412) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Your client is out of date. Please save your changes elsewhere and refresh.'}
</div>
</Nav.item>;
}
if(error.req.url.match(/^\/api.*Google.*$/m)){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
Looks like your Google credentials have
expired! Visit our log in page to sign out
and sign back in with Google,
then try saving again!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${window.location.href}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer' href={`https://github.com/naturalcrit/homebrewery/issues/new?template=save_issue.yml&error-code=${encodeURIComponent(errMsg)}`}>
here
</a>.
</div>
</Nav.item>;
}
});
module.exports = ErrorNavItem;

View File

@@ -1,11 +1,16 @@
.navItem { .navItem {
&.error {
position : relative;
background-color : @red;
}
.errorContainer{ .errorContainer{
animation-name: glideDown; animation-name: glideDown;
animation-duration: 0.4s; animation-duration: 0.4s;
position : absolute; position : absolute;
top : 100%; top : 100%;
left : 50%; left : 50%;
z-index : 500; z-index : 1000;
width : 140px; width : 140px;
padding : 3px; padding : 3px;
color : white; color : white;

View File

@@ -4,7 +4,7 @@ const createClass = require('create-react-class');
const _ = require('lodash'); const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
const moment = require('moment'); const moment = require('moment');
const request = require('superagent'); const request = require('../../../../utils/request-middleware.js');
const googleDriveIcon = require('../../../../googleDrive.png'); const googleDriveIcon = require('../../../../googleDrive.png');
const dedent = require('dedent-tabs').default; const dedent = require('dedent-tabs').default;
@@ -18,7 +18,8 @@ const BrewItem = createClass({
description : '', description : '',
authors : [], authors : [],
stubbed : true stubbed : true
} },
reportError : null
}; };
}, },
@@ -33,8 +34,12 @@ const BrewItem = createClass({
request.delete(`/api/${this.props.brew.googleId ?? ''}${this.props.brew.editId}`) request.delete(`/api/${this.props.brew.googleId ?? ''}${this.props.brew.editId}`)
.send() .send()
.end(function(err, res){ .end((err, res)=>{
location.reload(); if(err && this.props.reportError) {
this.props.reportError(err.response);
} else {
location.reload();
}
}); });
}, },

View File

@@ -23,7 +23,8 @@ const ListPage = createClass({
brews : [] brews : []
} }
], ],
navItems : <></> navItems : <></>,
reportError : null
}; };
}, },
getInitialState : function() { getInitialState : function() {
@@ -81,7 +82,7 @@ const ListPage = createClass({
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>; if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>;
return _.map(brews, (brew, idx)=>{ return _.map(brews, (brew, idx)=>{
return <BrewItem brew={brew} key={idx}/>; return <BrewItem brew={brew} key={idx} reportError={this.props.reportError}/>;
}); });
}, },

View File

@@ -12,6 +12,7 @@ const Navbar = require('../../navbar/navbar.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 PrintLink = require('../../navbar/print.navitem.jsx'); const PrintLink = require('../../navbar/print.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const Account = require('../../navbar/account.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
@@ -261,10 +262,6 @@ const EditPage = createClass({
}, },
renderSaveButton : function(){ renderSaveButton : function(){
if(this.state.error){
return require('../../utils/render-error-nav-item.jsx')(this, this.state.error);
}
if(this.state.autoSaveWarning && this.hasChanges()){ if(this.state.autoSaveWarning && this.hasChanges()){
this.setAutosaveWarning(); this.setAutosaveWarning();
const elapsedTime = Math.round((new Date() - this.state.unsavedTime) / 1000 / 60); const elapsedTime = Math.round((new Date() - this.state.unsavedTime) / 1000 / 60);
@@ -352,10 +349,13 @@ const EditPage = createClass({
<Nav.section> <Nav.section>
{this.renderGoogleDriveIcon()} {this.renderGoogleDriveIcon()}
<Nav.dropdown className='save-menu'> {this.state.error ?
{this.renderSaveButton()} <ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
{this.renderAutoSaveButton()} <Nav.dropdown className='save-menu'>
</Nav.dropdown> {this.renderSaveButton()}
{this.renderAutoSaveButton()}
</Nav.dropdown>
}
<NewBrew /> <NewBrew />
<HelpNavItem/> <HelpNavItem/>
<Nav.dropdown> <Nav.dropdown>

View File

@@ -13,10 +13,6 @@
cursor : initial; cursor : initial;
color : #666; color : #666;
} }
&.error{
position : relative;
background-color : @red;
}
} }
.googleDriveStorage { .googleDriveStorage {
position : relative; position : relative;

View File

@@ -12,6 +12,7 @@ const NewBrewItem = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx'); const HelpNavItem = require('../../navbar/help.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 SplitPane = require('naturalcrit/splitPane/splitPane.jsx'); const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
@@ -55,16 +56,13 @@ const HomePage = createClass({
brew : { ...prevState.brew, text: text } brew : { ...prevState.brew, text: text }
})); }));
}, },
renderSaveError : function(){
if(this.state.error) {
return require('../../utils/render-error-nav-item.jsx')(this, this.state.error);
}
return null;
},
renderNavbar : function(){ renderNavbar : function(){
return <Navbar ver={this.props.ver}> return <Navbar ver={this.props.ver}>
<Nav.section> <Nav.section>
{this.renderSaveError()} {this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
null
}
<NewBrewItem /> <NewBrewItem />
<HelpNavItem /> <HelpNavItem />
<RecentNavItem /> <RecentNavItem />

View File

@@ -46,9 +46,5 @@
&:hover{ &:hover{
background-color: @green; background-color: @green;
} }
&.error{
position : relative;
background-color : @red;
}
} }
} }

View File

@@ -10,6 +10,7 @@ const Markdown = require('naturalcrit/markdown.js');
const Nav = require('naturalcrit/nav/nav.jsx'); const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx'); const Navbar = require('../../navbar/navbar.jsx');
const AccountNavItem = require('../../navbar/account.navitem.jsx'); const AccountNavItem = require('../../navbar/account.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const HelpNavItem = require('../../navbar/help.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx');
@@ -156,10 +157,6 @@ const NewPage = createClass({
}, },
renderSaveButton : function(){ renderSaveButton : function(){
if(this.state.error){
return require('../../utils/render-error-nav-item.jsx')(this, this.state.error);
}
if(this.state.isSaving){ if(this.state.isSaving){
return <Nav.item icon='fas fa-spinner fa-spin' className='save'> return <Nav.item icon='fas fa-spinner fa-spin' className='save'>
save... save...
@@ -189,7 +186,10 @@ const NewPage = createClass({
</Nav.section> </Nav.section>
<Nav.section> <Nav.section>
{this.renderSaveButton()} {this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
this.renderSaveButton()
}
{this.renderLocalPrintButton()} {this.renderLocalPrintButton()}
<HelpNavItem /> <HelpNavItem />
<RecentNavItem /> <RecentNavItem />

View File

@@ -4,9 +4,5 @@
&:hover{ &:hover{
background-color: @green; background-color: @green;
} }
&.error{
position : relative;
background-color : @red;
}
} }
} }

View File

@@ -12,6 +12,7 @@ const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx'); 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 UserPage = createClass({ const UserPage = createClass({
displayName : 'UserPage', displayName : 'UserPage',
@@ -19,7 +20,8 @@ const UserPage = createClass({
return { return {
username : '', username : '',
brews : [], brews : [],
query : '' query : '',
error : null
}; };
}, },
getInitialState : function() { getInitialState : function() {
@@ -50,10 +52,19 @@ const UserPage = createClass({
brewCollection : brewCollection brewCollection : brewCollection
}; };
}, },
errorReported : function(error) {
this.setState({
error
});
},
navItems : function() { navItems : function() {
return <Navbar> return <Navbar>
<Nav.section> <Nav.section>
{this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
null
}
<NewBrew /> <NewBrew />
<HelpNavItem /> <HelpNavItem />
<RecentNavItem /> <RecentNavItem />
@@ -63,7 +74,7 @@ const UserPage = createClass({
}, },
render : function(){ render : function(){
return <ListPage brewCollection={this.state.brewCollection} navItems={this.navItems()} query={this.props.query}></ListPage>; return <ListPage brewCollection={this.state.brewCollection} navItems={this.navItems()} query={this.props.query} reportError={this.errorReported}></ListPage>;
} }
}); });

View File

@@ -1,72 +0,0 @@
require('./render-error-nav-item.less');
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
module.exports = function(component, error){
const clearError = ()=>{
const state = {
error : null
};
if(component.state.isSaving) {
state.isSaving = false;
}
component.setState(state);
};
const status = error.status;
const message = error.body?.message;
let errMsg = '';
try {
errMsg += `${error.toString()}\n\n`;
errMsg += `\`\`\`\n${error.stack}\n`;
errMsg += `${JSON.stringify(error.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(status === 409) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Conflict: please refresh to get latest changes'}
</div>
</Nav.item>;
} else if(status === 412) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Your client is out of date. Please save your changes elsewhere and refresh.'}
</div>
</Nav.item>;
}
if(error.req.url.match(/^\/api.*Google.*$/m)){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
Looks like your Google credentials have
expired! Visit our log in page to sign out
and sign back in with Google,
then try saving again!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${window.location.href}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer' href={`https://github.com/naturalcrit/homebrewery/issues/new?template=save_issue.yml&error-code=${encodeURIComponent(errMsg)}`}>
here
</a>.
</div>
</Nav.item>;
};