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:
84
client/homebrew/navbar/error-navitem.jsx
Normal file
84
client/homebrew/navbar/error-navitem.jsx
Normal 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;
|
||||||
@@ -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;
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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}/>;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -13,10 +13,6 @@
|
|||||||
cursor : initial;
|
cursor : initial;
|
||||||
color : #666;
|
color : #666;
|
||||||
}
|
}
|
||||||
&.error{
|
|
||||||
position : relative;
|
|
||||||
background-color : @red;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.googleDriveStorage {
|
.googleDriveStorage {
|
||||||
position : relative;
|
position : relative;
|
||||||
|
|||||||
@@ -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 />
|
||||||
|
|||||||
@@ -46,9 +46,5 @@
|
|||||||
&:hover{
|
&:hover{
|
||||||
background-color: @green;
|
background-color: @green;
|
||||||
}
|
}
|
||||||
&.error{
|
|
||||||
position : relative;
|
|
||||||
background-color : @red;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 />
|
||||||
|
|||||||
@@ -4,9 +4,5 @@
|
|||||||
&:hover{
|
&:hover{
|
||||||
background-color: @green;
|
background-color: @green;
|
||||||
}
|
}
|
||||||
&.error{
|
|
||||||
position : relative;
|
|
||||||
background-color : @red;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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>;
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user