mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-17 00:21:20 -05:00
Merge pull request #745 from rschamp/bugfix/student-registration-url
Grab-bag of student registration fixes
This commit is contained in:
commit
6144c6f8d1
5 changed files with 138 additions and 120 deletions
|
@ -22,6 +22,7 @@
|
|||
}
|
||||
|
||||
.form {
|
||||
position: relative;
|
||||
padding: 3rem 4rem;
|
||||
|
||||
.card-button {
|
||||
|
@ -39,10 +40,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
.help-block {
|
||||
.validation-message {
|
||||
$arrow-border-width: 1rem;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
transform: translate(20rem, -4rem);
|
||||
margin-left: $arrow-border-width;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
|
@ -100,7 +103,7 @@
|
|||
|
||||
@media only screen and (max-width: $desktop - 1) {
|
||||
.card {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
position: relative;
|
||||
transform: none;
|
||||
margin: inherit;
|
||||
|
|
|
@ -100,33 +100,56 @@ module.exports = {
|
|||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
<Slide className="registration-step username-step">
|
||||
<h2><intl.FormattedMessage id="registration.usernameStepTitle" /></h2>
|
||||
<h2>
|
||||
{this.props.title ? (
|
||||
this.props.title
|
||||
) : (
|
||||
<intl.FormattedMessage id="registration.usernameStepTitle" />
|
||||
)}
|
||||
</h2>
|
||||
<p className="description">
|
||||
<intl.FormattedMessage id="registration.usernameStepDescription" />
|
||||
{this.props.description ? (
|
||||
this.props.description
|
||||
) : (
|
||||
<intl.FormattedMessage id="registration.usernameStepDescription" />
|
||||
)}
|
||||
{this.props.tooltip ? (
|
||||
<Tooltip title={'?'}
|
||||
tipContent={this.props.tooltip} />
|
||||
) : (
|
||||
null
|
||||
)}
|
||||
</p>
|
||||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Input label={formatMessage({id: 'registration.createUsername'})}
|
||||
className={this.state.validUsername}
|
||||
type="text"
|
||||
name="user.username"
|
||||
validations={{
|
||||
matchRegexp: /^[\w-]*$/,
|
||||
minLength: 3,
|
||||
maxLength: 20
|
||||
}}
|
||||
validationErrors={{
|
||||
matchRegexp: formatMessage({
|
||||
id: 'registration.validationUsernameRegexp'
|
||||
}),
|
||||
minLength: formatMessage({
|
||||
id: 'registration.validationUsernameMinLength'
|
||||
}),
|
||||
maxLength: formatMessage({
|
||||
id: 'registration.validationUsernameMaxLength'
|
||||
})
|
||||
}}
|
||||
required />
|
||||
<div>
|
||||
<b>{formatMessage({id: 'registration.createUsername'})}</b>
|
||||
{this.props.usernameHelp ? (
|
||||
<p className="help-text">{this.props.usernameHelp}</p>
|
||||
):(
|
||||
null
|
||||
)}
|
||||
<Input className={this.state.validUsername}
|
||||
type="text"
|
||||
name="user.username"
|
||||
validations={{
|
||||
matchRegexp: /^[\w-]*$/,
|
||||
minLength: 3,
|
||||
maxLength: 20
|
||||
}}
|
||||
validationErrors={{
|
||||
matchRegexp: formatMessage({
|
||||
id: 'registration.validationUsernameRegexp'
|
||||
}),
|
||||
minLength: formatMessage({
|
||||
id: 'registration.validationUsernameMinLength'
|
||||
}),
|
||||
maxLength: formatMessage({
|
||||
id: 'registration.validationUsernameMaxLength'
|
||||
})
|
||||
}}
|
||||
required />
|
||||
</div>
|
||||
<Input label={formatMessage({id: 'general.password'})}
|
||||
type={this.state.showPassword ? 'text' : 'password'}
|
||||
name="user.password"
|
||||
|
@ -402,7 +425,9 @@ module.exports = {
|
|||
required />
|
||||
<div className="organization-type">
|
||||
<b><intl.FormattedMessage id="teacherRegistration.orgType" /></b>
|
||||
<p><intl.FormattedMessage id="teacherRegistration.checkAll" /></p>
|
||||
<p className="help-text">
|
||||
<intl.FormattedMessage id="teacherRegistration.checkAll" />
|
||||
</p>
|
||||
<CheckboxGroup name="organization.type"
|
||||
value={[]}
|
||||
options={this.getOrganizationOptions()}
|
||||
|
@ -418,7 +443,9 @@ module.exports = {
|
|||
</div>
|
||||
<div className="url-input">
|
||||
<b><intl.FormattedMessage id="general.website" /></b>
|
||||
<p><intl.FormattedMessage id="teacherRegistration.notRequired" /></p>
|
||||
<p className="help-text">
|
||||
<intl.FormattedMessage id="teacherRegistration.notRequired" />
|
||||
</p>
|
||||
<Input type="url"
|
||||
name="organization.url"
|
||||
required="isFalse"
|
||||
|
@ -718,16 +745,6 @@ module.exports = {
|
|||
ClassInviteStep: React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
classroom: {
|
||||
title: '',
|
||||
thumbnail: '',
|
||||
educator: {
|
||||
username: '',
|
||||
profile: {
|
||||
images: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
'general.getStarted': 'Get Started',
|
||||
'registration.classroomInviteStepDescription': 'has invited you to join the class:'
|
||||
|
@ -741,21 +758,26 @@ module.exports = {
|
|||
render: function () {
|
||||
return (
|
||||
<Slide className="registration-step class-invite-step">
|
||||
<Avatar className="invite-avatar" src={this.props.classroom.educator.profile.images['50x50']} />
|
||||
<h2>{this.props.classroom.educator.username}</h2>
|
||||
<p className="description">
|
||||
{this.props.messages['registration.classroomInviteStepDescription']}
|
||||
</p>
|
||||
<Card>
|
||||
<div className="contents">
|
||||
<h3>{this.props.classroom.title}</h3>
|
||||
<img className="class-image" src={this.props.classroom.images['250x150']} />
|
||||
</div>
|
||||
<NextStepButton onClick={this.onNextStep}
|
||||
waiting={this.props.waiting}
|
||||
text={this.props.messages['general.getStarted']} />
|
||||
</Card>
|
||||
<StepNavigation steps={this.props.totalSteps - 1} active={this.props.activeStep} />
|
||||
{this.props.waiting ? [
|
||||
<Spinner />
|
||||
] : [
|
||||
<Avatar className="invite-avatar"
|
||||
src={this.props.classroom.educator.profile.images['50x50']} />,
|
||||
<h2>{this.props.classroom.educator.username}</h2>,
|
||||
<p className="description">
|
||||
{this.props.messages['registration.classroomInviteStepDescription']}
|
||||
</p>,
|
||||
<Card>
|
||||
<div className="contents">
|
||||
<h3>{this.props.classroom.title}</h3>
|
||||
<img className="class-image" src={this.props.classroom.images['250x150']} />
|
||||
</div>
|
||||
<NextStepButton onClick={this.onNextStep}
|
||||
waiting={this.props.waiting}
|
||||
text={this.props.messages['general.getStarted']} />
|
||||
</Card>,
|
||||
<StepNavigation steps={this.props.totalSteps - 1} active={this.props.activeStep} />
|
||||
]}
|
||||
</Slide>
|
||||
);
|
||||
}
|
||||
|
@ -763,23 +785,14 @@ module.exports = {
|
|||
ClassWelcomeStep: React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
classroom: {
|
||||
title: '',
|
||||
thumbnail: '',
|
||||
educator: {
|
||||
username: '',
|
||||
profile: {
|
||||
images: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
'registration.goToClass': 'Go to Class',
|
||||
'registration.welcomeStepDescription': 'You have successfully set up a Scratch account! ' +
|
||||
'You are now a member of the class:',
|
||||
'registration.welcomeStepPrompt': 'To get started, click on the button below.',
|
||||
'registration.welcomeStepTitle': 'Hurray! Welcome to Scratch!'
|
||||
}
|
||||
},
|
||||
waiting: false
|
||||
};
|
||||
},
|
||||
onNextStep: function () {
|
||||
|
@ -788,18 +801,26 @@ module.exports = {
|
|||
render: function () {
|
||||
return (
|
||||
<Slide className="registration-step class-welcome-step">
|
||||
<h2>{this.props.messages['registration.welcomeStepTitle']}</h2>
|
||||
<p className="description">{this.props.messages['registration.welcomeStepDescription']}</p>
|
||||
<Card>
|
||||
<div className="contents">
|
||||
<h3>{this.props.classroom.title}</h3>
|
||||
<img className="class-image" src={this.props.classroom.images['250x150']} />
|
||||
<p>{this.props.messages['registration.welcomeStepPrompt']}</p>
|
||||
</div>
|
||||
<NextStepButton onClick={this.onNextStep}
|
||||
waiting={this.props.waiting}
|
||||
text={this.props.messages['registration.goToClass']} />
|
||||
</Card>
|
||||
{this.props.waiting ? [
|
||||
<Spinner />
|
||||
] : [
|
||||
<h2>{this.props.messages['registration.welcomeStepTitle']}</h2>,
|
||||
<p className="description">{this.props.messages['registration.welcomeStepDescription']}</p>,
|
||||
<Card>
|
||||
{this.props.classroom ? (
|
||||
<div className="contents">
|
||||
<h3>{this.props.classroom.title}</h3>
|
||||
<img className="class-image" src={this.props.classroom.images['250x150']} />
|
||||
<p>{this.props.messages['registration.welcomeStepPrompt']}</p>
|
||||
</div>
|
||||
) : (
|
||||
null
|
||||
)}
|
||||
<NextStepButton onClick={this.onNextStep}
|
||||
waiting={this.props.waiting}
|
||||
text={this.props.messages['registration.goToClass']} />
|
||||
</Card>
|
||||
]}
|
||||
</Slide>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.help-text {
|
||||
margin: .25rem 0;
|
||||
text-align: left;
|
||||
color: $ui-dark-gray;
|
||||
}
|
||||
|
||||
|
||||
&.class-invite-step,
|
||||
&.class-welcome-step {
|
||||
.card {
|
||||
|
@ -34,24 +41,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.username-step,
|
||||
&.name-step,
|
||||
&.address-step,
|
||||
&.email-step {
|
||||
.help-block {
|
||||
transform: translate(15.75rem, -4rem);
|
||||
}
|
||||
}
|
||||
|
||||
&.demographics-step {
|
||||
.gender-input {
|
||||
margin-top: -5.5rem;
|
||||
}
|
||||
|
||||
.help-block {
|
||||
transform: translate(13rem, -2rem);
|
||||
}
|
||||
|
||||
.radio {
|
||||
margin-right: 2.5rem;
|
||||
line-height: 3rem;
|
||||
|
@ -73,37 +67,28 @@
|
|||
}
|
||||
}
|
||||
|
||||
.help-block {
|
||||
.validation-message {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.organization-step {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
transform: translate(16rem, -4rem);
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
transform: translate(16rem, -16rem);
|
||||
}
|
||||
}
|
||||
|
||||
.organization-type,
|
||||
.url-input {
|
||||
p {
|
||||
margin: .25rem 0;
|
||||
text-align: left;
|
||||
color: $ui-dark-gray;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
&[value="8"] {
|
||||
margin: 1rem 0;
|
||||
|
@ -117,7 +102,7 @@
|
|||
|
||||
&.address-step {
|
||||
.select {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
transform: translate(0, .5rem);
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +123,7 @@
|
|||
|
||||
}
|
||||
|
||||
.help-block {
|
||||
.validation-message {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
|
||||
|
@ -199,19 +184,9 @@
|
|||
text-align: left;
|
||||
}
|
||||
|
||||
&.username-step,
|
||||
&.demographics-step,
|
||||
&.name-step,
|
||||
&.address-step,
|
||||
&.email-step {
|
||||
.help-block {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.phone-step {
|
||||
.checkbox,
|
||||
.help-block {
|
||||
.validation-message {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
@ -238,7 +213,7 @@
|
|||
&.organization-step,
|
||||
&.address-step,
|
||||
&.email-step {
|
||||
.help-block {
|
||||
.validation-message {
|
||||
position: relative;
|
||||
transform: none;
|
||||
margin: inherit;
|
||||
|
|
|
@ -115,12 +115,18 @@
|
|||
"registration.lastStepDescription": "We are currently processing your application. ",
|
||||
"registration.nameStepTooltip": "This information is used for verification and to aggregate usage statistics.",
|
||||
"registration.nextStep": "Next Step",
|
||||
"registration.notOnWebsite": "This information will not appear on the Scratch website.",
|
||||
"registration.personalStepTitle": "Personal Information",
|
||||
"registration.personalStepDescription": "Your individual responses will not be displayed publicly, and will be kept confidential and secure",
|
||||
"registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.",
|
||||
"registration.showPassword": "Show password",
|
||||
"registration.usernameStepDescription": "Fill in the following forms to request an account. The approval process may take up to 24 hours.",
|
||||
"registration.studentUsernameStepDescription": "You can make games, animations, and stories using Scratch. Setting up an account is easy and it's free. Fill in the form below to get started.",
|
||||
"registration.studentUsernameStepHelpText": "Already have a Scratch account?",
|
||||
"registration.studentUsernameStepTitle": "Create a Scratch Account",
|
||||
"registration.studentUsernameStepTooltip": "You'll need to create a new Scratch account to join this class.",
|
||||
"registration.studentUsernameFieldHelpText": "For safety, don't use your real name!",
|
||||
"registration.usernameStepTitle": "Request a Teacher Account",
|
||||
"registration.usernameStepTitleScratcher": "Create a Scratch Account",
|
||||
"registration.validationPasswordLength": "Passwords must be at least six characters",
|
||||
"registration.validationPasswordNotEquals": "Your password may not be \"password\"",
|
||||
"registration.validationPasswordNotUsername": "Your password may not be your username",
|
||||
|
|
|
@ -36,7 +36,8 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
},
|
||||
componentDidMount: function () {
|
||||
api({
|
||||
uri: '/classrooms/' + this.props.classroomId + '/' + this.props.classroomToken
|
||||
uri: '/classrooms/' + this.props.classroomId,
|
||||
params: {token: this.props.classroomToken}
|
||||
}, function (err, body, res) {
|
||||
if (err) {
|
||||
return this.setState({
|
||||
|
@ -86,7 +87,15 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
window.location = '/classes/' + this.props.classroomId + '/';
|
||||
},
|
||||
render: function () {
|
||||
var demographicsDescription = this.props.intl.formatMessage({id: 'registration.notOnWebsite'});
|
||||
var demographicsDescription = this.props.intl.formatMessage({
|
||||
id: 'registration.studentPersonalStepDescription'});
|
||||
var usernameTitle = this.props.intl.formatMessage({id: 'registration.studentUsernameStepTitle'});
|
||||
var usernameHelp = this.props.intl.formatMessage({id: 'registration.studentUsernameFieldHelpText'});
|
||||
var usernameDescription = (
|
||||
this.props.intl.formatMessage({id: 'registration.studentUsernameStepDescription'}) + ' ' +
|
||||
this.props.intl.formatMessage({id: 'registration.studentUsernameStepHelpText'})
|
||||
);
|
||||
var usernameTooltip = this.props.intl.formatMessage({id: 'registration.studentUsernameStepTooltip'});
|
||||
return (
|
||||
<Deck className="student-registration">
|
||||
{this.state.registrationError ?
|
||||
|
@ -96,8 +105,12 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
<Steps.ClassInviteStep classroom={this.state.classroom}
|
||||
messages={this.props.messages}
|
||||
onNextStep={this.advanceStep}
|
||||
waiting={this.state.waiting} />
|
||||
waiting={this.state.waiting || !this.state.classroom} />
|
||||
<Steps.UsernameStep onNextStep={this.advanceStep}
|
||||
title={usernameTitle}
|
||||
description={usernameDescription}
|
||||
tooltip={usernameTooltip}
|
||||
usernameHelp={usernameHelp}
|
||||
waiting={this.state.waiting} />
|
||||
<Steps.DemographicsStep description={demographicsDescription}
|
||||
onNextStep={this.register}
|
||||
|
@ -105,7 +118,7 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
<Steps.ClassWelcomeStep classroom={this.state.classroom}
|
||||
messages={this.props.messages}
|
||||
onNextStep={this.goToClass}
|
||||
waiting={this.state.waiting} />
|
||||
waiting={this.state.waiting || !this.state.classroom} />
|
||||
</Progression>
|
||||
}
|
||||
</Deck>
|
||||
|
|
Loading…
Reference in a new issue