Commit 6144c6f8 authored by Ray Schamp's avatar Ray Schamp Committed by GitHub

Merge pull request #745 from rschamp/bugfix/student-registration-url

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