validation and misc lint fixes

This commit is contained in:
tomlum 2023-06-28 22:49:28 -04:00
parent 2f7e12bd0c
commit 8868d00e23
4 changed files with 134 additions and 111 deletions

View file

@ -438,5 +438,16 @@
"extensions.otherComputerConnectedText": "Only one computer can be connected to a {deviceName} at a time. If you have another computer connected to your {deviceName}, disconnect the {deviceName} or close Scratch on that computer and try again.", "extensions.otherComputerConnectedText": "Only one computer can be connected to a {deviceName} at a time. If you have another computer connected to your {deviceName}, disconnect the {deviceName} or close Scratch on that computer and try again.",
"bluetooth.enableLocationServicesTitle": "Make sure you have location services enabled on Chromebooks or Android tablets", "bluetooth.enableLocationServicesTitle": "Make sure you have location services enabled on Chromebooks or Android tablets",
"bluetooth.enableLocationServicesText": "Bluetooth can be used to provide location data to the app. In addition to granting the Scratch App permission to access location, location must be enabled in your general device settings. Search for 'Location' in your settings, and make sure it is on. On Chromebooks search for 'Location' in the Google Play Store Android preferences." "bluetooth.enableLocationServicesText": "Bluetooth can be used to provide location data to the app. In addition to granting the Scratch App permission to access location, location must be enabled in your general device settings. Search for 'Location' in your settings, and make sure it is on. On Chromebooks search for 'Location' in the Google Play Store Android preferences.",
"renameAccount.accountBlocked": "Account Blocked",
"renameAccount.toRecover": "To recover a access to your account, change your username.",
"renameAccount.yourScratchAccount": "Your scratch account has been temporarily blocked because your usernamed appears to contain personal information.",
"renameAccount.privacyIssue": "This is a serious privacy issue. When you share information like this, it is visible to everyone on the internet, so please be careful what you share",
"renameAccount.thingsToAvoid": "When creating an username, please remember to avoid using last names, school names, or other private information in your username.",
"renameAccount.changeYourUsername": "Change your Username",
"renameAccount.makeSure": "Make sure the username you chose is aligned with {communityGuidelinesLink}",
"renameAccount.communityGuidelines": "Scratch's Community Guidelines",
"renameAccount.change": "Change",
"renameAccount.pastNotifications": "Here are your past admin notifications"
} }

View file

@ -17,8 +17,7 @@ const banGoodListPaths = [
'/accounts/bad-username', '/accounts/bad-username',
'/community_guidelines', '/community_guidelines',
'/privacy_policy', '/privacy_policy',
'/terms_of_use', '/terms_of_use'
'/accounts/update_username'
]; ];
module.exports.Status = keyMirror({ module.exports.Status = keyMirror({

View file

@ -1,4 +1,3 @@
/* eslint-disable */
const injectIntl = require('react-intl').injectIntl; const injectIntl = require('react-intl').injectIntl;
// const intlShape = require('react-intl').intlShape; // const intlShape = require('react-intl').intlShape;
// const FormattedMessage = require('react-intl').FormattedMessage; // const FormattedMessage = require('react-intl').FormattedMessage;
@ -20,12 +19,19 @@ import bannedIcon from './blocked-account.svg';
require('../../components/extension-landing/extension-landing.scss'); require('../../components/extension-landing/extension-landing.scss');
require('./bad-username-splash.scss'); require('./bad-username-splash.scss');
const validateNewUsernameForm = values => {
const errors = {};
if (values.canValidate && (values.newUsername !== values.newUsernameConfirm && values.newUsernameConfirm !== '')){
errors.newUsernameConfirm = "usernames don't match";
}
return errors;
};
const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => { const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
const [unauthorizedError, setUnauthorizedError] = React.useState(false) const [unauthorizedError, setUnauthorizedError] = React.useState(false);
const [badUsernameError, setBadUsernameError] = React.useState(false) const [badUsernameError, setBadUsernameError] = React.useState(false);
const [apiError, setAPIError] = React.useState(false) const [apiError, setAPIError] = React.useState(false);
React.useEffect(() => { React.useEffect(() => {
if (user && user.username && user.token){ if (user && user.username && user.token){
@ -34,12 +40,11 @@ const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
}, [user]); }, [user]);
const handleUpdateUsernameUnbanSubmit = (formData, formikBag) => { const handleUpdateUsernameUnbanSubmit = (formData, formikBag) => {
setUnauthorizedError(false) setUnauthorizedError(false);
setBadUsernameError(false) setBadUsernameError(false);
setAPIError(false) setAPIError(false);
formikBag.setSubmitting(false); // formik makes us do this ourselves formikBag.setSubmitting(false); // formik makes us do this ourselves
console.log("attempting submit!")
api({ api({
host: '', host: '',
uri: '/accounts/update_username/', uri: '/accounts/update_username/',
@ -51,19 +56,17 @@ const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
password: formData.password password: formData.password
} }
}, (err, body, res) => { }, (err, body, res) => {
if(res.body.error === "Unauthorized"){ if (res.body.error === 'Unauthorized'){
setUnauthorizedError("error message for unauthorized access") setUnauthorizedError('error message for unauthorized access');
} } else if (res.body.error === 'Invalid username'){
else if(res.body.error === "Invalid username"){ setBadUsernameError('error message for invalid username');
setBadUsernameError("error message for invalid username") } else if (res.body.error){
} setAPIError('error message for API error');
else if(res.body.error){ } else {
setAPIError("error message for API error")
} else{
window.location = '/'; window.location = '/';
} }
}); });
} };
if (hasSession && (!user || !user.banned)){ if (hasSession && (!user || !user.banned)){
window.location = '/'; window.location = '/';
@ -82,12 +85,12 @@ const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
className="banned-icon" className="banned-icon"
src={bannedIcon} src={bannedIcon}
/> />
<h1 className="inline"><FormattedMessage id="renameAccount.accountBlocked"/></h1> <h1 className="inline"><FormattedMessage id="renameAccount.accountBlocked" /></h1>
</span> </span>
<h3><FormattedMessage id="renameAccount.toRecover"/></h3> <h3><FormattedMessage id="renameAccount.toRecover" /></h3>
<p><FormattedMessage id="renameAccount.yourScratchAccount"/></p> <p><FormattedMessage id="renameAccount.yourScratchAccount" /></p>
<p><FormattedMessage id="renameAccount.privacyIssue"/></p> <p><FormattedMessage id="renameAccount.privacyIssue" /></p>
<p><FormattedMessage id="renameAccount.thingsToAvoid"/></p> <p><FormattedMessage id="renameAccount.thingsToAvoid" /></p>
</div> </div>
<div className="col"> <div className="col">
<Formik <Formik
@ -95,101 +98,108 @@ const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
newUsername: '', newUsername: '',
newUsernameConfirm: '', newUsernameConfirm: '',
username: user.username, username: user.username,
password: '' password: '',
canValidate: false
}} }}
validateOnBlur={true} validate={validateNewUsernameForm}
validateOnBlur
validateOnChange={false} validateOnChange={false}
/* eslint-disable react/jsx-no-bind */
onSubmit={handleUpdateUsernameUnbanSubmit} onSubmit={handleUpdateUsernameUnbanSubmit}
> >
{({ {({
errors, errors,
handleSubmit, handleSubmit,
isSubmitting, isSubmitting,
setFieldError, setFieldError,
setFieldTouched, setFieldTouched,
setFieldValue, setFieldValue,
// touched, validateForm
validateField, }) => (
values <JoinFlowStep
}) => { description={<FormattedMessage id="renameAccount.makeSure" />}
return ( innerClassName="change-username-inner"
<JoinFlowStep outerClassName="change-username-outer"
description={<FormattedMessage id="renameAccount.makeSure"/>} title={<FormattedMessage
innerClassName="change-username-inner" id="renameAccount.changeYourUsername"
outerClassName="change-username-outer" values={{communityGuidelinesLink: (<a href="/community_guidelines"><FormattedMessage id="renameAccount.communityGuidelines" /></a>)}}
title={<FormattedMessage id="renameAccount.changeYourUsername" values={{communityGuidelinesLink: <a href="/community_guidelines"><FormattedMessage id="renameAccount.communityGuidelines"/></a>}}/>} />}
waiting={isSubmitting} waiting={isSubmitting}
onSubmit={handleSubmit} onSubmit={handleSubmit}
nextButton={<FormattedMessage id="renameAccount.change"/>} nextButton={<FormattedMessage id="renameAccount.change" />}
> >
<div> <div>
<FormikInput <FormikInput
autoCapitalize="off" autoCapitalize="off"
autoComplete="off" autoComplete="off"
autoCorrect="off" autoCorrect="off"
error={errors.newUsername} error={errors.newUsername}
id="newUsername" id="newUsername"
name="newUsername" name="newUsername"
placeholder={'Type your new username'} placeholder={'Type your new username'}
spellCheck={false} spellCheck={false}
// toolTip={this.state.focused === 'username' && !touched.username && // toolTip={this.state.focused === 'username' && !touched.username &&
// this.props.intl.formatMessage({id: 'registration.usernameAdviceShort'})} // this.props.intl.formatMessage({id: 'registration.usernameAdviceShort'})}
/* eslint-disable react/jsx-no-bind */ validationClassName="validation-left validation-full-width-input"
validate={validateUsername} /* eslint-disable react/jsx-no-bind */
validationClassName="validation-left validation-full-width-input" validateOnChange={false}
/* eslint-disable react/jsx-no-bind */ onChange={e => {
onBlur={() => validateField('newUsername')} setFieldValue('newUsername', e.target.value.substring(0, 30));
onChange={e => { setFieldValue('canValidate', false);
setFieldValue('newUsername', e.target.value.substring(0, 30)); setFieldTouched('newUsername');
setFieldTouched('newUsername'); setFieldError('newUsername', null);
setFieldError('newUsername', null); }}
}} />
/> <FormikInput
<FormikInput autoCapitalize="off"
autoCapitalize="off" autoComplete="off"
autoComplete="off" autoCorrect="off"
autoCorrect="off" className={'join-flow-input'}
className={'join-flow-input'} error={errors.newUsernameConfirm || badUsernameError}
error={errors.newUsernameConfirm || badUsernameError} id="newUsernameConfirm"
id="newUsernameConfirm" validateOnChange={false}
name="newUsernameConfirm" name="newUsernameConfirm"
placeholder={'Type your new username again'} placeholder={'Type your new username again'}
spellCheck={false} spellCheck={false}
validationClassName="validation-left validation-full-width-input" validationClassName="validation-left validation-full-width-input"
onChange={e => { onChange={e => {
setFieldValue('newUsernameConfirm', e.target.value.substring(0, 30)); setFieldValue('newUsernameConfirm', e.target.value.substring(0, 30));
setFieldTouched('newUsernameConfirm'); setFieldTouched('newUsernameConfirm');
setFieldError('newUsernameConfirm', null); setFieldError('newUsernameConfirm', null);
}} setFieldValue('canValidate', false);
/> }}
<FormikInput onBlur={() => {
autoCapitalize="off" setFieldValue('canValidate', true).then(validateForm());
autoComplete="off" }}
autoCorrect="off" />
className={'join-flow-input'} <FormikInput
id="password" autoCapitalize="off"
name="password" autoComplete="off"
placeholder={'Enter your password'} autoCorrect="off"
spellCheck={false} className={'join-flow-input'}
error={unauthorizedError || apiError} id="password"
validationClassName="validation-left validation-full-width-input" name="password"
onChange={e => { placeholder={'Enter your password'}
setFieldValue('password', e.target.value); spellCheck={false}
setFieldTouched('password'); error={unauthorizedError || apiError}
setFieldError('password', null); validationClassName="validation-left validation-full-width-input"
}} onChange={e => {
/> setFieldValue('password', e.target.value);
</div> setFieldTouched('password');
</JoinFlowStep>); setFieldError('password', null);
}} }}
/>
</div>
</JoinFlowStep>)}
</Formik> </Formik>
</div> </div>
</div> </div>
</div> </div>
<div id="admin-message-list"> <div id="admin-message-list">
<div id="admin-message-list-title"> <div id="admin-message-list-title">
<b><FormattedMessage id="renameAccount.pastNotifications"/></b> <b><FormattedMessage id="renameAccount.pastNotifications" /></b>
</div> </div>
{console.log(adminMessages)}
{adminMessages.map(message => ( {adminMessages.map(message => (
<div <div
className="admin-message" className="admin-message"
@ -198,7 +208,7 @@ const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
<div className="admin-message-date"> <div className="admin-message-date">
{new Date(message.datetime_created).toDateString()} {new Date(message.datetime_created).toDateString()}
</div> </div>
{/* // eslint-disable-next-line react/no-danger */} {/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{__html: message.message}} /> <div dangerouslySetInnerHTML={{__html: message.message}} />
</div> </div>
))} ))}

View file

@ -0,0 +1,3 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.66463 34.3035C3.16405 34.7261 3.91148 34.6638 4.33407 34.1643L30.3944 3.36576C30.817 2.86634 30.7547 2.11891 30.2553 1.69632C29.7559 1.27374 29.0084 1.33602 28.5859 1.83544L25.5707 5.39883H7.19999C4.21765 5.39883 1.79999 7.81649 1.79999 10.7988V25.1988C1.79999 27.2974 2.99711 29.1164 4.74571 30.0102L2.52551 32.634C2.10293 33.1335 2.16521 33.8809 2.66463 34.3035ZM6.59065 27.8298L18.6752 13.548H4.49999V25.1988C4.49999 26.4804 5.39295 27.5535 6.59065 27.8298ZM28.8 30.5988H10.4308L12.7154 27.8988H28.8C30.2912 27.8988 31.5 26.69 31.5 25.1988V13.548H24.8584L31.2553 5.98803C33.0033 6.88198 34.2 8.70066 34.2 10.7988V25.1988C34.2 28.1812 31.7823 30.5988 28.8 30.5988Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 838 B