mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 23:57:55 -05:00
Merge pull request #5633 from paulkaplan/remove-debug-errors
Improve errors around following studios
This commit is contained in:
commit
6e43607a1d
11 changed files with 100 additions and 50 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -7613,6 +7613,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react-hooks": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz",
|
||||
"integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
"eslint-config-scratch": "7.0.0",
|
||||
"eslint-plugin-json": "2.0.1",
|
||||
"eslint-plugin-react": "7.14.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"fastly": "1.2.1",
|
||||
"formik": "1.5.4",
|
||||
"formsy-react": "1.1.4",
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = {
|
|||
globals: {
|
||||
process: true
|
||||
},
|
||||
plugins: ['json'],
|
||||
plugins: ['json', 'react-hooks'],
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect'
|
||||
|
@ -17,6 +17,7 @@ module.exports = {
|
|||
'camelcase': [2, {
|
||||
properties: 'never', // This is from the base `scratch` config
|
||||
allow: ['^UNSAFE_'] // Allow until migrated to new lifecycle methods
|
||||
}]
|
||||
}],
|
||||
'react-hooks/rules-of-hooks': 'error'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Debug = ({label, data}) => (<div style={{padding: '2rem', border: '1px solid red', margin: '2rem'}}>
|
||||
<small>{label}</small>
|
||||
<code>
|
||||
<pre style={{fontSize: '0.75rem'}}>
|
||||
{JSON.stringify(data, null, ' ')}
|
||||
</pre>
|
||||
</code>
|
||||
</div>);
|
||||
|
||||
Debug.propTypes = {
|
||||
label: PropTypes.string,
|
||||
data: PropTypes.any // eslint-disable-line react/forbid-prop-types
|
||||
};
|
||||
|
||||
export default Debug;
|
|
@ -18,6 +18,15 @@
|
|||
"studio.updateErrors.thumbnailTooLarge": "Maximum file size is 512 KB and less than 500x500 pixels.",
|
||||
"studio.updateErrors.thumbnailInvalid": "Upload a valid image. The file you uploaded was either not an image or a corrupted image.",
|
||||
|
||||
"studio.followErrors.confirmEmail": "Please confirm your email address first",
|
||||
"studio.followErrors.generic": "Something went wrong following the studio",
|
||||
|
||||
"studio.sectionLoadError.projectsHeadline": "Something went wrong loading projects",
|
||||
"studio.sectionLoadError.curatorsHeadline": "Something went wrong loading curators",
|
||||
"studio.sectionLoadError.managersHeadline": "Something went wrong loading managers",
|
||||
"studio.sectionLoadError.activityHeadline": "Something went wrong loading activity",
|
||||
"studio.sectionLoadError.tryAgain": "Try again",
|
||||
|
||||
"studio.projectsHeader": "Projects",
|
||||
"studio.addProjectsHeader": "Add Projects",
|
||||
"studio.addProject": "Add",
|
||||
|
|
|
@ -6,7 +6,6 @@ import {connect} from 'react-redux';
|
|||
|
||||
import {activity} from './lib/redux-modules';
|
||||
import {loadActivity} from './lib/studio-activity-actions';
|
||||
import Debug from './debug.jsx';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import SocialMessage from '../../components/social-message/social-message.jsx';
|
||||
|
@ -181,10 +180,15 @@ const StudioActivity = ({items, loading, error, moreToLoad, onLoadMore}) => {
|
|||
<h2><FormattedMessage id="studio.activityHeader" /></h2>
|
||||
</div>
|
||||
{loading && <div>Loading...</div>}
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
/>}
|
||||
{error && <div className="studio-section-load-error studio-info-box studio-info-box-error">
|
||||
<h3><FormattedMessage id="studio.sectionLoadError.activityHeadline" /></h3>
|
||||
<button
|
||||
className="button"
|
||||
onClick={onLoadMore}
|
||||
>
|
||||
<FormattedMessage id="studio.sectionLoadError.tryAgain" />
|
||||
</button>
|
||||
</div>}
|
||||
<ul
|
||||
className="studio-messages-list"
|
||||
>
|
||||
|
|
|
@ -5,7 +5,6 @@ import {FormattedMessage} from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import {curators} from './lib/redux-modules';
|
||||
import Debug from './debug.jsx';
|
||||
import {CuratorTile} from './studio-member-tile.jsx';
|
||||
import CuratorInviter from './studio-curator-inviter.jsx';
|
||||
import {loadCurators} from './lib/studio-member-actions';
|
||||
|
@ -28,10 +27,15 @@ const StudioCurators = ({
|
|||
<h2><FormattedMessage id="studio.curatorsHeader" /></h2>
|
||||
</div>
|
||||
{canInviteCurators && <CuratorInviter />}
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
/>}
|
||||
{error && <div className="studio-section-load-error studio-info-box studio-info-box-error">
|
||||
<h3><FormattedMessage id="studio.sectionLoadError.curatorsHeadline" /></h3>
|
||||
<button
|
||||
className="button"
|
||||
onClick={onLoadMore}
|
||||
>
|
||||
<FormattedMessage id="studio.sectionLoadError.tryAgain" />
|
||||
</button>
|
||||
</div>}
|
||||
<div className="studio-members-grid">
|
||||
{items.length === 0 && !loading ? (
|
||||
<div className="studio-empty">
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
/* eslint-disable react/jsx-no-bind */
|
||||
import React from 'react';
|
||||
import React, {useState} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {connect} from 'react-redux';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import onClickOutside from 'react-onclickoutside';
|
||||
|
||||
import {selectIsFollowing} from '../../redux/studio';
|
||||
import {selectCanFollowStudio} from '../../redux/studio-permissions';
|
||||
import {
|
||||
mutateFollowingStudio, selectIsMutatingFollowing, selectFollowingMutationError
|
||||
mutateFollowingStudio, selectIsMutatingFollowing, selectFollowingMutationError, Errors
|
||||
} from '../../redux/studio-mutations';
|
||||
import classNames from 'classnames';
|
||||
import ValidationMessage from '../../components/forms/validation-message.jsx';
|
||||
|
||||
const errorToMessageId = error => {
|
||||
switch (error) {
|
||||
case Errors.PERMISSION: return 'studio.followErrors.confirmEmail';
|
||||
default: return 'studio.followErrors.generic';
|
||||
}
|
||||
};
|
||||
|
||||
const StudioFollow = ({
|
||||
canFollow,
|
||||
|
@ -18,16 +27,24 @@ const StudioFollow = ({
|
|||
followingError,
|
||||
handleFollow
|
||||
}) => {
|
||||
if (!canFollow) return null;
|
||||
const fieldClassName = classNames('button', 'studio-follow-button', {
|
||||
'mod-mutating': isMutating
|
||||
});
|
||||
const [hideValidationMessage, setHideValidationMessage] = useState(false);
|
||||
|
||||
StudioFollow.handleClickOutside = () => {
|
||||
setHideValidationMessage(true);
|
||||
};
|
||||
if (!canFollow) return null;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="studio-info-section">
|
||||
<button
|
||||
className={fieldClassName}
|
||||
disabled={isMutating}
|
||||
onClick={() => handleFollow(!isFollowing)}
|
||||
onClick={() => {
|
||||
setHideValidationMessage(false);
|
||||
handleFollow(!isFollowing);
|
||||
}}
|
||||
>
|
||||
{isMutating ? '...' : (
|
||||
isFollowing ?
|
||||
|
@ -35,8 +52,11 @@ const StudioFollow = ({
|
|||
<FormattedMessage id="studio.followStudio" />
|
||||
)}
|
||||
</button>
|
||||
{followingError && <div>Error mutating following: {followingError}</div>}
|
||||
</React.Fragment >
|
||||
{followingError && !hideValidationMessage && <ValidationMessage
|
||||
mode="error"
|
||||
message={<FormattedMessage id={errorToMessageId(followingError)} />}
|
||||
/>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -48,6 +68,10 @@ StudioFollow.propTypes = {
|
|||
handleFollow: PropTypes.func
|
||||
};
|
||||
|
||||
const clickOutsideConfig = {
|
||||
handleClickOutside: () => StudioFollow.handleClickOutside
|
||||
};
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
canFollow: selectCanFollowStudio(state),
|
||||
|
@ -58,4 +82,4 @@ export default connect(
|
|||
{
|
||||
handleFollow: mutateFollowingStudio
|
||||
}
|
||||
)(StudioFollow);
|
||||
)(onClickOutside(StudioFollow, clickOutsideConfig));
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
selectStudioHasReachedManagerThreshold
|
||||
} from '../../redux/studio.js';
|
||||
import {loadManagers} from './lib/studio-member-actions';
|
||||
import Debug from './debug.jsx';
|
||||
import {ManagerTile} from './studio-member-tile.jsx';
|
||||
import StudioInfoBox from './studio-info-box.jsx';
|
||||
import AlertProvider from '../../components/alert/alert-provider.jsx';
|
||||
|
@ -85,10 +84,15 @@ const StudioManagers = ({
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
/>}
|
||||
{error && <div className="studio-section-load-error studio-info-box studio-info-box-error">
|
||||
<h3><FormattedMessage id="studio.sectionLoadError.managersHeadline" /></h3>
|
||||
<button
|
||||
className="button"
|
||||
onClick={onLoadMore}
|
||||
>
|
||||
<FormattedMessage id="studio.sectionLoadError.tryAgain" />
|
||||
</button>
|
||||
</div>}
|
||||
<div className="studio-members-grid">
|
||||
{items.map(item =>
|
||||
(<ManagerTile
|
||||
|
|
|
@ -7,7 +7,6 @@ import classNames from 'classnames';
|
|||
|
||||
import {projects} from './lib/redux-modules';
|
||||
import {selectCanAddProjects, selectCanEditOpenToAll, selectShowProjectMuteError} from '../../redux/studio-permissions';
|
||||
import Debug from './debug.jsx';
|
||||
import StudioProjectAdder from './studio-project-adder.jsx';
|
||||
import StudioProjectTile from './studio-project-tile.jsx';
|
||||
import {loadProjects} from './lib/studio-project-actions.js';
|
||||
|
@ -24,7 +23,7 @@ const StudioProjects = ({
|
|||
useEffect(() => {
|
||||
if (items.length === 0) onLoadMore();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<AlertProvider>
|
||||
<div className="studio-projects">
|
||||
|
@ -49,12 +48,19 @@ const StudioProjects = ({
|
|||
</CommentingStatus>
|
||||
}
|
||||
{canAddProjects && <StudioProjectAdder />}
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
/>}
|
||||
|
||||
{error && <div className="studio-section-load-error studio-info-box studio-info-box-error">
|
||||
<h3><FormattedMessage id="studio.sectionLoadError.projectsHeadline" /></h3>
|
||||
<button
|
||||
className="button"
|
||||
onClick={onLoadMore}
|
||||
>
|
||||
<FormattedMessage id="studio.sectionLoadError.tryAgain" />
|
||||
</button>
|
||||
</div>}
|
||||
|
||||
<div className="studio-projects-grid">
|
||||
{items.length === 0 && !loading ? (
|
||||
{items.length === 0 && !loading && !error ? (
|
||||
<div className="studio-empty">
|
||||
{canAddProjects ? (
|
||||
<React.Fragment>
|
||||
|
|
|
@ -174,9 +174,18 @@ $radius: 8px;
|
|||
padding-bottom: 14px;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.studio-section-load-error {
|
||||
margin-top: 2rem;
|
||||
padding: 1rem;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.studio-tab-nav {
|
||||
border-bottom: 1px solid $active-dark-gray;
|
||||
padding-bottom: 8px;
|
||||
|
|
Loading…
Reference in a new issue