mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 07:38:07 -05:00
Merge pull request #782 from LLK/release/2.2.11
[Develop] Release 2.2.11
This commit is contained in:
commit
02ff0217c9
22 changed files with 234 additions and 144 deletions
|
@ -21,31 +21,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
position: relative;
|
||||
padding: 3rem 4rem;
|
||||
|
||||
.card-button {
|
||||
margin: 0 0 -3rem -4rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.2rem;
|
||||
|
||||
&.has-error {
|
||||
.input {
|
||||
border: 1px solid $ui-orange;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
$arrow-border-width: 1rem;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate(20rem, -4rem);
|
||||
transform: translate(16rem, 0);
|
||||
margin-left: $arrow-border-width;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
|
@ -77,6 +59,27 @@
|
|||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 3rem 4rem;
|
||||
|
||||
.card-button {
|
||||
margin: 0 0 -3rem -4rem;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-bottom: 1.2rem;
|
||||
|
||||
&.has-error {
|
||||
.input {
|
||||
border: 1px solid $ui-orange;
|
||||
}
|
||||
}
|
||||
|
||||
.col-sm-9 {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
}
|
||||
|
||||
.input {
|
||||
width: $cols5;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,7 @@ var Checkbox = React.createClass({
|
|||
this.props.className
|
||||
);
|
||||
return (
|
||||
<div className={classes}>
|
||||
<FRCCheckbox {... this.props} />
|
||||
</div>
|
||||
<FRCCheckbox rowClassName={classes} {... this.props} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,14 +29,14 @@ var Input = React.createClass({
|
|||
},
|
||||
render: function () {
|
||||
var classes = classNames(
|
||||
'input',
|
||||
this.state.status,
|
||||
this.props.className
|
||||
this.props.className,
|
||||
{'no-label': (typeof this.props.label === 'undefined')}
|
||||
);
|
||||
return (this.props.type === 'submit' || this.props.noformsy ?
|
||||
<input {... this.props} className={classes} /> :
|
||||
return (
|
||||
<FRCInput {... this.props}
|
||||
className={classes}
|
||||
className="input"
|
||||
rowClassName={classes}
|
||||
onValid={this.onValid}
|
||||
onInvalid={this.onInvalid} />
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ $pass-bg: lighten($ui-aqua, 35%);
|
|||
|
||||
.input {
|
||||
transition: all .5s ease;
|
||||
margin: .75rem 0;
|
||||
margin-bottom: .75rem;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
background-color: $base-bg;
|
||||
|
|
|
@ -42,7 +42,7 @@ var PhoneInput = React.createClass({
|
|||
return (
|
||||
<Row {... this.getRowProperties()}
|
||||
htmlFor={this.getId()}
|
||||
className={classNames('phone-input', this.props.className)}
|
||||
rowClassName={classNames('phone-input', this.props.className)}
|
||||
>
|
||||
<div className="input-group">
|
||||
<ReactPhoneInput className="form-control"
|
||||
|
@ -53,9 +53,9 @@ var PhoneInput = React.createClass({
|
|||
label={null}
|
||||
disabled={this.isFormDisabled() || this.props.disabled}
|
||||
/>
|
||||
{this.renderHelp()}
|
||||
{this.renderErrorMessage()}
|
||||
</div>
|
||||
{this.renderHelp()}
|
||||
{this.renderErrorMessage()}
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@import "../../colors";
|
||||
|
||||
.input-group {
|
||||
margin: .75rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.react-tel-input {
|
||||
margin-bottom: .75rem;
|
||||
width: 100%;
|
||||
|
||||
input {
|
||||
|
|
|
@ -4,8 +4,19 @@
|
|||
* the formsy-react-components
|
||||
*/
|
||||
|
||||
.form-group {
|
||||
.row {
|
||||
.required-symbol {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
|
||||
&.no-label {
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
select {
|
||||
transition: all .5s ease;
|
||||
margin: .75rem 0;
|
||||
margin-bottom: .75rem;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
background: $ui-light-gray url("../../../static/svgs/forms/carot.svg") no-repeat right center;
|
||||
|
|
|
@ -11,11 +11,13 @@ var TextArea = React.createClass({
|
|||
type: 'TextArea',
|
||||
render: function () {
|
||||
var classes = classNames(
|
||||
'textarea',
|
||||
'textarea-row',
|
||||
this.props.className
|
||||
);
|
||||
return (
|
||||
<FRCTextarea {... this.props} className={classes} />
|
||||
<FRCTextarea {... this.props}
|
||||
className="textarea"
|
||||
rowClassName={classes} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.textarea {
|
||||
transition: all 1s ease;
|
||||
margin: .75rem 0;
|
||||
margin-bottom: .75rem;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
background-color: $ui-light-gray;
|
||||
|
|
|
@ -11,6 +11,7 @@ var api = require('../../../lib/api');
|
|||
var Avatar = require('../../avatar/avatar.jsx');
|
||||
var Button = require('../../forms/button.jsx');
|
||||
var Dropdown = require('../../dropdown/dropdown.jsx');
|
||||
var Form = require('../../forms/form.jsx');
|
||||
var Input = require('../../forms/input.jsx');
|
||||
var log = require('../../../lib/log.js');
|
||||
var Login = require('../../login/login.jsx');
|
||||
|
@ -170,6 +171,9 @@ var Navigation = React.createClass({
|
|||
this.props.dispatch(sessionActions.refreshSession());
|
||||
this.closeRegistration();
|
||||
},
|
||||
onSearchSubmit: function (formData) {
|
||||
window.location.href = '/search/projects?q=' + formData.q;
|
||||
},
|
||||
render: function () {
|
||||
var classes = classNames({
|
||||
'logged-in': this.props.session.session.user
|
||||
|
@ -216,14 +220,13 @@ var Navigation = React.createClass({
|
|||
</li>
|
||||
|
||||
<li className="search">
|
||||
<form action="/search/projects" method="get">
|
||||
<Form onSubmit={this.onSearchSubmit}>
|
||||
<Button type="submit" className="btn-search" />
|
||||
<Input type="text"
|
||||
aria-label={formatMessage({id: 'general.search'})}
|
||||
placeholder={formatMessage({id: 'general.search'})}
|
||||
name="q"
|
||||
noformsy />
|
||||
</form>
|
||||
name="q" />
|
||||
</Form>
|
||||
</li>
|
||||
{this.props.session.status === sessionActions.Status.FETCHED ? (
|
||||
this.props.session.session.user ? [
|
||||
|
|
|
@ -47,12 +47,18 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
form {
|
||||
.form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
.row {
|
||||
.help-block {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.input,
|
||||
.button {
|
||||
display: inline-block;
|
||||
margin-top: 5px;
|
||||
outline: none;
|
||||
|
|
|
@ -27,6 +27,23 @@ var Tooltip = require('../../components/tooltip/tooltip.jsx');
|
|||
require('./steps.scss');
|
||||
|
||||
var DEFAULT_COUNTRY = 'us';
|
||||
var getCountryOptions = function (defaultCountry) {
|
||||
var options = countryData.countryOptions.concat({
|
||||
label: <intl.FormattedMessage id="registration.selectCountry" />,
|
||||
disabled: true,
|
||||
selected: true
|
||||
});
|
||||
if (typeof defaultCountry !== 'undefined') {
|
||||
return options.sort(function (a, b) {
|
||||
if (a.disabled) return -1;
|
||||
if (b.disabled) return 1;
|
||||
if (a.value === defaultCountry) return -1;
|
||||
if (b.value === defaultCountry) return 1;
|
||||
return 0;
|
||||
}.bind(this));
|
||||
}
|
||||
return options;
|
||||
};
|
||||
|
||||
var NextStepButton = React.createClass({
|
||||
getDefaultProps: function () {
|
||||
|
@ -124,12 +141,14 @@ module.exports = {
|
|||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<div>
|
||||
<b>{formatMessage({id: 'registration.createUsername'})}</b>
|
||||
{this.props.usernameHelp ? (
|
||||
<p className="help-text">{this.props.usernameHelp}</p>
|
||||
):(
|
||||
null
|
||||
)}
|
||||
<div className="username-label">
|
||||
<b>{formatMessage({id: 'registration.createUsername'})}</b>
|
||||
{this.props.usernameHelp ? (
|
||||
<p className="help-text">{this.props.usernameHelp}</p>
|
||||
):(
|
||||
null
|
||||
)}
|
||||
</div>
|
||||
<Input className={this.state.validUsername}
|
||||
type="text"
|
||||
name="user.username"
|
||||
|
@ -251,7 +270,6 @@ module.exports = {
|
|||
DemographicsStep: intl.injectIntl(React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
defaultCountry: DEFAULT_COUNTRY,
|
||||
waiting: false,
|
||||
description: null
|
||||
};
|
||||
|
@ -265,7 +283,7 @@ module.exports = {
|
|||
'August', 'September', 'October', 'November', 'December'
|
||||
].map(function (label, id) {
|
||||
return {
|
||||
value: id+1,
|
||||
value: id + 1,
|
||||
label: this.props.intl.formatMessage({id: 'general.month' + label})};
|
||||
}.bind(this));
|
||||
},
|
||||
|
@ -321,8 +339,7 @@ module.exports = {
|
|||
</div>
|
||||
<Select label={formatMessage({id: 'general.country'})}
|
||||
name="user.country"
|
||||
options={countryData.countryOptions}
|
||||
value={this.props.defaultCountry}
|
||||
options={getCountryOptions(DEFAULT_COUNTRY)}
|
||||
required />
|
||||
<Checkbox className="demographics-checkbox-is-robot"
|
||||
label="I'm a robot!"
|
||||
|
@ -573,17 +590,6 @@ module.exports = {
|
|||
var formatMessage = this.props.intl.formatMessage;
|
||||
var stateOptions = countryData.subdivisionOptions[this.state.countryChoice];
|
||||
stateOptions = [{}].concat(stateOptions);
|
||||
var countryOptions = countryData.countryOptions.concat({
|
||||
label: formatMessage({id: 'teacherRegistration.selectCountry'}),
|
||||
disabled: true,
|
||||
selected: true
|
||||
}).sort(function (a, b) {
|
||||
if (a.disabled) return -1;
|
||||
if (b.disabled) return 1;
|
||||
if (a.value === this.props.defaultCountry) return -1;
|
||||
if (b.value === this.props.defaultCountry) return 1;
|
||||
return 0;
|
||||
}.bind(this));
|
||||
return (
|
||||
<Slide className="registration-step address-step">
|
||||
<h2>
|
||||
|
@ -598,7 +604,8 @@ module.exports = {
|
|||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Select label={formatMessage({id: 'general.country'})}
|
||||
name="address.country"
|
||||
options={countryOptions}
|
||||
options={getCountryOptions()}
|
||||
value={this.props.defaultCountry}
|
||||
onChange={this.onChangeCountry}
|
||||
required />
|
||||
<Input label={formatMessage({id: 'teacherRegistration.addressLine1'})}
|
||||
|
@ -762,7 +769,8 @@ module.exports = {
|
|||
getDefaultProps: function () {
|
||||
return {
|
||||
email: null,
|
||||
invited: false
|
||||
invited: false,
|
||||
confirmed: false
|
||||
};
|
||||
},
|
||||
render: function () {
|
||||
|
@ -805,7 +813,7 @@ module.exports = {
|
|||
);
|
||||
}
|
||||
})),
|
||||
ClassInviteStep: intl.injectIntl(React.createClass({
|
||||
ClassInviteNewStudentStep: intl.injectIntl(React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
waiting: false
|
||||
|
@ -825,7 +833,7 @@ module.exports = {
|
|||
src={this.props.classroom.educator.profile.images['50x50']} />,
|
||||
<h2>{this.props.classroom.educator.username}</h2>,
|
||||
<p className="description">
|
||||
{formatMessage({id: 'registration.classroomInviteStepDescription'})}
|
||||
{formatMessage({id: 'registration.classroomInviteNewStudentStepDescription'})}
|
||||
</p>,
|
||||
<Card>
|
||||
<div className="contents">
|
||||
|
@ -842,6 +850,47 @@ module.exports = {
|
|||
);
|
||||
}
|
||||
})),
|
||||
ClassInviteExistingStudentStep: intl.injectIntl(React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
classroom: null,
|
||||
onHandleLogOut: function () {},
|
||||
studentUsername: null,
|
||||
waiting: false
|
||||
};
|
||||
},
|
||||
onNextStep: function () {
|
||||
this.props.onNextStep();
|
||||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
<Slide className="registration-step class-invite-step">
|
||||
{this.props.waiting ? [
|
||||
<Spinner />
|
||||
] : [
|
||||
<h2>{this.props.studentUsername}</h2>,
|
||||
<p className="description">
|
||||
{formatMessage({id: 'registration.classroomInviteExistingStudentStepDescription'})}
|
||||
</p>,
|
||||
<Card>
|
||||
<div className="contents">
|
||||
<h3>{this.props.classroom.title}</h3>
|
||||
<img className="class-image" src={this.props.classroom.images['250x150']} />
|
||||
<p>{formatMessage({id: 'registration.invitedBy'})}</p>
|
||||
<p><strong>{this.props.classroom.educator.username}</strong></p>
|
||||
</div>
|
||||
<NextStepButton onClick={this.onNextStep}
|
||||
waiting={this.props.waiting}
|
||||
text={formatMessage({id: 'general.getStarted'})} />
|
||||
</Card>,
|
||||
<p><a onClick={this.props.onHandleLogOut}>{formatMessage({id: 'registration.notYou'})}</a></p>,
|
||||
<StepNavigation steps={this.props.totalSteps - 1} active={this.props.activeStep} />
|
||||
]}
|
||||
</Slide>
|
||||
);
|
||||
}
|
||||
})),
|
||||
ClassWelcomeStep: intl.injectIntl(React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
|
|
|
@ -29,6 +29,15 @@
|
|||
color: $ui-dark-gray;
|
||||
}
|
||||
|
||||
&.class-invite-step {
|
||||
text-align: center;
|
||||
|
||||
> p a {
|
||||
text-decoration: underline;
|
||||
color: $ui-white;
|
||||
font-weight: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&.class-invite-step,
|
||||
&.class-welcome-step {
|
||||
|
@ -41,6 +50,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.username-step {
|
||||
.username-label {
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.demographics-step {
|
||||
.gender-input {
|
||||
margin-top: -5.5rem;
|
||||
|
@ -66,26 +81,12 @@
|
|||
margin-bottom: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
.validation-message {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.organization-step {
|
||||
.validation-message {
|
||||
transform: translate(16rem, -4rem);
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
.validation-message {
|
||||
transform: translate(16rem, -16rem);
|
||||
transform: translate(16rem, 8rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,14 +101,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.address-step {
|
||||
.select {
|
||||
.validation-message {
|
||||
transform: translate(0, .5rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.usescratch-step {
|
||||
.form {
|
||||
.form-group {
|
||||
|
@ -119,12 +112,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
|
||||
p {
|
||||
|
|
|
@ -111,19 +111,24 @@
|
|||
"registration.choosePasswordStepDescription": "Type in a new password for your account. You will use this password the next time you log into Scratch.",
|
||||
"registration.choosePasswordStepTitle": "Create a password",
|
||||
"registration.choosePasswordStepTooltip": "Don't use your name or anything that's easy for someone else to guess.",
|
||||
"registration.classroomInviteStepDescription": "has invited you to join the class:",
|
||||
"registration.classroomApiGeneralError": "Sorry, we could not find the registration information for this class",
|
||||
"registration.classroomInviteExistingStudentStepDescription": "you have been invited to join the class:",
|
||||
"registration.classroomInviteNewStudentStepDescription": "has invited you to join the class:",
|
||||
"registration.confirmYourEmail": "Confirm Your Email",
|
||||
"registration.confirmYourEmailDescription": "If you haven't already, please click the link in the confirmation email sent to:",
|
||||
"registration.createUsername": "Create a Username",
|
||||
"registration.goToClass": "Go to Class",
|
||||
"registration.invitedBy": "invited by",
|
||||
"registration.lastStepTitle": "Thank you for requesting a Scratch Teacher Account",
|
||||
"registration.lastStepDescription": "We are currently processing your application. ",
|
||||
"registration.mustBeNewStudent": "You must be a new student to complete your registration",
|
||||
"registration.nameStepTooltip": "This information is used for verification and to aggregate usage statistics.",
|
||||
"registration.newPassword": "New Password",
|
||||
"registration.nextStep": "Next Step",
|
||||
"registration.notYou": "Not you? Log in as another user",
|
||||
"registration.personalStepTitle": "Personal Information",
|
||||
"registration.personalStepDescription": "Your individual responses will not be displayed publicly, and will be kept confidential and secure",
|
||||
"registration.selectCountry": "select country",
|
||||
"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.",
|
||||
|
|
|
@ -79,6 +79,12 @@ module.exports.refreshSession = function () {
|
|||
body.flags.must_complete_registration &&
|
||||
window.location.pathname !== '/classes/complete_registration') {
|
||||
return window.location = '/classes/complete_registration';
|
||||
} else if (
|
||||
body.flags &&
|
||||
body.flags.must_reset_password &&
|
||||
!body.flags.must_complete_registration &&
|
||||
window.location.pathname !== '/classes/student_password_reset/') {
|
||||
return window.location = '/classes/student_password_reset/';
|
||||
} else {
|
||||
dispatch(tokenActions.getToken());
|
||||
dispatch(module.exports.setSession(body));
|
||||
|
|
|
@ -6,6 +6,7 @@ var render = require('../../lib/render.jsx');
|
|||
var sessionStatus = require('../../redux/session').Status;
|
||||
var api = require('../../lib/api');
|
||||
var intl = require('../../lib/intl.jsx');
|
||||
var log = require('../../lib/log.js');
|
||||
|
||||
var Deck = require('../../components/deck/deck.jsx');
|
||||
var Progression = require('../../components/progression/progression.jsx');
|
||||
|
@ -33,17 +34,16 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
});
|
||||
},
|
||||
componentDidUpdate: function (prevProps) {
|
||||
if (prevProps.session.session !== this.props.session.session &&
|
||||
this.props.session.session.permissions &&
|
||||
this.props.session.session.permissions.student) {
|
||||
var classroomId = this.props.session.session.user.classroomId;
|
||||
if (prevProps.studentUsername !== this.props.studentUsername && this.props.newStudent) {
|
||||
this.setState({waiting: true});
|
||||
api({
|
||||
uri: '/classrooms/' + classroomId
|
||||
uri: '/classrooms/' + this.props.classroomId
|
||||
}, function (err, body, res) {
|
||||
if (err || res.statusCode === 404) {
|
||||
this.setState({waiting: false});
|
||||
if (err || res.statusCode !== 200) {
|
||||
return this.setState({
|
||||
registrationErrors: {
|
||||
__all__: this.props.intl.formatMessage({id: 'studentRegistration.classroomApiGeneralError'})
|
||||
__all__: this.props.intl.formatMessage({id: 'registration.classroomApiGeneralError'})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -51,6 +51,18 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
}.bind(this));
|
||||
}
|
||||
},
|
||||
handleLogOut: function (e) {
|
||||
e.preventDefault();
|
||||
api({
|
||||
host: '',
|
||||
method: 'post',
|
||||
uri: '/accounts/logout/',
|
||||
useCsrf: true
|
||||
}, function (err) {
|
||||
if (err) return log.error(err);
|
||||
window.location = '/';
|
||||
}.bind(this));
|
||||
},
|
||||
register: function (formData) {
|
||||
this.setState({waiting: true});
|
||||
formData = defaults({}, formData || {}, this.state.formData);
|
||||
|
@ -65,7 +77,7 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
country: formData.user.country,
|
||||
is_robot: formData.user.isRobot
|
||||
};
|
||||
if (this.props.session.session.flags.must_reset_password) {
|
||||
if (this.props.must_reset_password) {
|
||||
submittedData.password = formData.user.password;
|
||||
}
|
||||
api({
|
||||
|
@ -88,36 +100,36 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
var demographicsDescription = this.props.intl.formatMessage({
|
||||
id: 'registration.studentPersonalStepDescription'});
|
||||
var registrationErrors = this.state.registrationErrors;
|
||||
var sessionFetched = this.props.session.status === sessionStatus.FETCHED;
|
||||
if (sessionFetched &&
|
||||
!(this.props.session.session.permissions.student &&
|
||||
this.props.session.session.flags.must_complete_registration)) {
|
||||
if (!this.props.newStudent) {
|
||||
registrationErrors = {
|
||||
__all__: this.props.intl.formatMessage({id: 'registration.mustBeNewStudent'})
|
||||
};
|
||||
}
|
||||
return (
|
||||
<Deck className="student-registration">
|
||||
{sessionFetched && this.state.classroom ?
|
||||
(registrationErrors ?
|
||||
<Steps.RegistrationError>
|
||||
<ul>
|
||||
{Object.keys(registrationErrors).map(function (field) {
|
||||
var label = field + ': ';
|
||||
if (field === '__all__') {
|
||||
label = '';
|
||||
}
|
||||
return (<li>{label}{registrationErrors[field]}</li>);
|
||||
})}
|
||||
</ul>
|
||||
</Steps.RegistrationError>
|
||||
:
|
||||
{registrationErrors ? (
|
||||
<Steps.RegistrationError>
|
||||
<ul>
|
||||
{Object.keys(registrationErrors).map(function (field) {
|
||||
var label = field + ': ';
|
||||
if (field === '__all__') {
|
||||
label = '';
|
||||
}
|
||||
return (<li>{label}{registrationErrors[field]}</li>);
|
||||
})}
|
||||
</ul>
|
||||
</Steps.RegistrationError>
|
||||
) : (
|
||||
this.state.waiting || !this.state.classroom ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<Progression {... this.state}>
|
||||
<Steps.ClassInviteStep classroom={this.state.classroom}
|
||||
messages={this.props.messages}
|
||||
onNextStep={this.advanceStep}
|
||||
<Steps.ClassInviteExistingStudentStep classroom={this.state.classroom}
|
||||
onHandleLogOut={this.handleLogOut}
|
||||
onNextStep={this.advanceStep}
|
||||
studentUsername={this.props.studentUsername}
|
||||
waiting={this.state.waiting} />
|
||||
{this.props.session.session.flags.must_reset_password ?
|
||||
{this.props.must_reset_password ?
|
||||
<Steps.ChoosePasswordStep onNextStep={this.advanceStep}
|
||||
showPassword={true}
|
||||
waiting={this.state.waiting} />
|
||||
|
@ -132,9 +144,7 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
waiting={this.state.waiting} />
|
||||
</Progression>
|
||||
)
|
||||
:
|
||||
<Spinner />
|
||||
}
|
||||
)}
|
||||
</Deck>
|
||||
);
|
||||
}
|
||||
|
@ -142,7 +152,14 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
|
||||
var mapStateToProps = function (state) {
|
||||
return {
|
||||
session: state.session
|
||||
classroomId: state.session.session.user && state.session.session.user.classroomId,
|
||||
must_reset_password: state.session.session.flags && state.session.session.flags.must_reset_password,
|
||||
newStudent: (
|
||||
state.session.session.permissions &&
|
||||
state.session.session.permissions.student &&
|
||||
state.session.session.flags.must_complete_registration),
|
||||
sessionFetched: state.session.status === sessionStatus.FETCHED,
|
||||
studentUsername: state.session.session.user && state.session.session.user.username
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"studentRegistration.classroomApiGeneralError": "Sorry, we could not find the registration information for this class"
|
||||
}
|
|
@ -35,14 +35,16 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
});
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.setState({waiting: true});
|
||||
api({
|
||||
uri: '/classrooms/' + this.props.classroomId,
|
||||
params: {token: this.props.classroomToken}
|
||||
}, function (err, body, res) {
|
||||
this.setState({waiting: false});
|
||||
if (err) {
|
||||
return this.setState({
|
||||
registrationError: this.props.intl.formatMessage({
|
||||
id: 'studentRegistration.classroomApiGeneralError'
|
||||
id: 'registration.classroomApiGeneralError'
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -104,9 +106,9 @@ var StudentRegistration = intl.injectIntl(React.createClass({
|
|||
</Steps.RegistrationError>
|
||||
:
|
||||
<Progression {... this.state}>
|
||||
<Steps.ClassInviteStep classroom={this.state.classroom}
|
||||
onNextStep={this.advanceStep}
|
||||
waiting={this.state.waiting || !this.state.classroom} />
|
||||
<Steps.ClassInviteNewStudentStep classroom={this.state.classroom}
|
||||
onNextStep={this.advanceStep}
|
||||
waiting={this.state.waiting || !this.state.classroom} />
|
||||
<Steps.UsernameStep onNextStep={this.advanceStep}
|
||||
title={usernameTitle}
|
||||
description={usernameDescription}
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
"teacherRegistration.orgChoiceMiddleSchool": "Middle School",
|
||||
"teacherRegistration.orgChoiceHighSchool": "High School",
|
||||
"teacherRegistration.orgChoiceUniversity": "College/University",
|
||||
"teacherRegistration.orgChoiceAfterschool": "Afterscool Program",
|
||||
"teacherRegistration.orgChoiceAfterschool": "Afterschool Program",
|
||||
"teacherRegistration.orgChoiceMuseum": "Museum",
|
||||
"teacherRegistration.orgChoiceLibrary": "Library",
|
||||
"teacherRegistration.orgChoiceCamp": "Camp",
|
||||
"teacherRegistration.orgChoiceOther": " ",
|
||||
"teacherRegistration.notRequired": "Not Required",
|
||||
"teacherRegistration.selectCountry": "select country",
|
||||
"teacherRegistration.addressValidationError": "This doesn't look like a real address",
|
||||
"teacherRegistration.addressLine1": "Address Line 1",
|
||||
"teacherRegistration.addressLine2": "Address Line 2 (Optional)",
|
||||
|
|
|
@ -10,6 +10,11 @@ require('./teacherwaitingroom.scss');
|
|||
|
||||
var TeacherWaitingRoom = React.createClass({
|
||||
displayName: 'TeacherWaitingRoom',
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
if (nextProps.session.permissions.educator && nextProps.session.permissions.social) {
|
||||
window.location.href = '/educators/classes/';
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
var permissions = this.props.session.permissions || {};
|
||||
var user = this.props.session.user || {};
|
||||
|
|
Loading…
Reference in a new issue