diff --git a/.eslintrc b/.eslintrc
index 853e777b4..aad7e8fb7 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,4 +1,5 @@
{
+ "parser": "babel-eslint",
"rules": {
"curly": [2, "multi-line"],
"eol-last": [2],
@@ -14,16 +15,12 @@
},
"env": {
"browser": true,
+ "es6": true,
"node": true
},
"globals": {
"formatMessage": true
},
- "ecmaFeatures": {
- "arrowFunctions": true,
- "blockBindings": true,
- "jsx": true
- },
"plugins": [
"react",
"json"
diff --git a/package.json b/package.json
index 433dc50f1..a72efc85b 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"async": "1.5.2",
"autoprefixer": "6.3.6",
"babel-core": "6.10.4",
+ "babel-eslint": "5.0.4",
"babel-loader": "6.2.4",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.11.1",
diff --git a/src/components/card/card.scss b/src/components/card/card.scss
index e9527167d..f2bbf9a60 100644
--- a/src/components/card/card.scss
+++ b/src/components/card/card.scss
@@ -5,4 +5,111 @@
border-radius: 8px / $em;
box-shadow: 0 0 0 .125rem $active-gray;
background-color: $ui-white;
+
+ .card-button {
+ display: block;
+ border-radius: .5rem;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ box-shadow: none;
+ background-color: $ui-aqua;
+ width: 23.75rem;
+ height: 4rem;
+
+ &:hover {
+ box-shadow: none;
+ }
+ }
+
+ .form {
+ padding: 3rem 4rem;
+
+ .card-button {
+ margin: 0 0 -3rem -4rem;
+ }
+
+ .form-group {
+ margin-bottom: 1.2rem;
+
+ &.has-error {
+ .input {
+ border: 1px solid $ui-orange;
+ }
+ }
+ }
+ }
+
+ .help-block {
+ $arrow-border-width: 1rem;
+ display: block;
+ position: absolute;
+ margin-left: $arrow-border-width;
+ border: 1px solid $active-gray;
+ border-radius: 5px;
+ background-color: $ui-orange;
+ padding: 1rem;
+ max-width: 18.75rem;
+ min-height: 1rem;
+ max-height: 3rem;
+ overflow: visible;
+ color: $type-white;
+
+ &:before {
+ display: block;
+ position: absolute;
+ top: 1rem;
+ left: -$arrow-border-width / 2;
+
+ transform: rotate(45deg);
+
+ border-bottom: 1px solid $active-gray;
+ border-left: 1px solid $active-gray;
+ border-radius: 5px;
+
+ background-color: $ui-orange;
+ width: $arrow-border-width;
+ height: $arrow-border-width;
+
+ content: "";
+ }
+ }
+
+}
+
+@media only screen and (max-width: $mobile - 1) {
+ .card {
+ width: 22.5rem;
+
+ .form {
+ text-align: left;
+
+ .button {
+ width: 22.5rem;
+ }
+ }
+ }
+}
+
+@media only screen and (max-width: $tablet - 1) {
+ .card {
+ .input {
+ width: 90%;
+ }
+ }
+}
+
+@media only screen and (max-width: $desktop - 1) {
+ .card {
+ .help-block {
+ position: relative;
+ transform: none;
+ margin: inherit;
+ width: 100%;
+ height: inherit;
+
+ &:before {
+ display: none;
+ }
+ }
+ }
}
diff --git a/src/components/deck/deck.jsx b/src/components/deck/deck.jsx
index 35b8334cc..5d929c68a 100644
--- a/src/components/deck/deck.jsx
+++ b/src/components/deck/deck.jsx
@@ -10,7 +10,7 @@ var Deck = React.createClass({
-
+
{this.props.children}
diff --git a/src/components/deck/deck.scss b/src/components/deck/deck.scss
index c8ff26caf..30991a092 100644
--- a/src/components/deck/deck.scss
+++ b/src/components/deck/deck.scss
@@ -6,146 +6,22 @@
.deck {
min-height: 100vh;
- img {
+ .logo {
margin-left: 2px;
padding: 12px 0;
width: 76px;
}
- .step-navigation {
- margin-top: 2rem;
- text-align: center;
- }
-
.slide {
max-width: 28.75rem;
-
- h2,
- .description {
- text-align: center;
- color: $type-white;
- }
-
- .description {
- margin-top: 0;
- margin-bottom: 2rem;
- }
}
.card {
- margin: 0 auto;
- width: 23.75rem;
- }
-
- .form {
- padding: 3rem 4rem;
-
- .form-group {
- margin-bottom: 1.2rem;
-
- &.has-error {
- .input {
- border: 1px solid $ui-orange;
- }
- }
- }
-
- .button {
- margin: 0 0 -3rem -4rem;
- border-radius: .5rem;
- box-shadow: none;
- width: 23.75rem;
- height: 4rem;
-
- &.card-button {
- display: block;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- background-color: $ui-aqua;
- }
-
- &:hover {
- box-shadow: none;
- }
- }
+ width: 23.75rem;
}
.input {
width: $cols5;
}
- .help-block {
- $arrow-border-width: 1rem;
- display: block;
- position: absolute;
- margin-left: $arrow-border-width;
- border: 1px solid $active-gray;
- border-radius: 5px;
- background-color: $ui-orange;
- padding: 1rem;
- max-width: 18.75rem;
- min-height: 1rem;
- max-height: 3rem;
- overflow: visible;
- color: $type-white;
-
- &:before {
- display: block;
- position: absolute;
- top: 1rem;
- left: -$arrow-border-width / 2;
-
- transform: rotate(45deg);
-
- border-bottom: 1px solid $active-gray;
- border-left: 1px solid $active-gray;
- border-radius: 5px;
-
- background-color: $ui-orange;
- width: $arrow-border-width;
- height: $arrow-border-width;
-
- content: "";
- }
- }
-}
-
-@media only screen and (max-width: $mobile - 1) {
- .deck {
- .card {
- width: 22.5rem;
- }
-
- .form {
- text-align: left;
-
- .button {
- width: 22.5rem;
- }
- }
- }
-}
-
-@media only screen and (max-width: $tablet - 1) {
- .deck {
- .input {
- width: 90%;
- }
- }
-}
-
-@media only screen and (max-width: $desktop - 1) {
- .deck {
- .help-block {
- position: relative;
- transform: none;
- margin: inherit;
- width: 100%;
- height: inherit;
-
- &:before {
- display: none;
- }
- }
- }
}
diff --git a/src/components/forms/input.scss b/src/components/forms/input.scss
index 265b7750d..d33a02705 100644
--- a/src/components/forms/input.scss
+++ b/src/components/forms/input.scss
@@ -35,4 +35,9 @@ $pass-bg: lighten($ui-aqua, 35%);
border: 1px solid $active-dark-gray;
background-color: $pass-bg;
}
+
+ /* IE10/11-specific style resets */
+ &::-ms-reveal, &::-ms-clear {
+ display: none;
+ }
}
diff --git a/src/components/registration/steps.jsx b/src/components/registration/steps.jsx
index 7db166575..634a82858 100644
--- a/src/components/registration/steps.jsx
+++ b/src/components/registration/steps.jsx
@@ -6,6 +6,7 @@ var intl = require('../../lib/intl.jsx');
var log = require('../../lib/log');
var smartyStreets = require('../../lib/smarty-streets');
+var Avatar = require('../../components/avatar/avatar.jsx');
var Button = require('../../components/forms/button.jsx');
var Card = require('../../components/card/card.jsx');
var CharCount = require('../../components/forms/charcount.jsx');
@@ -23,6 +24,8 @@ var StepNavigation = require('../../components/stepnavigation/stepnavigation.jsx
var TextArea = require('../../components/forms/textarea.jsx');
var Tooltip = require('../../components/tooltip/tooltip.jsx');
+require('./steps.scss');
+
var DEFAULT_COUNTRY = 'us';
var NextStepButton = React.createClass({
@@ -34,7 +37,7 @@ var NextStepButton = React.createClass({
},
render: function () {
return (
-
} />
+ text={} />
@@ -487,14 +495,14 @@ module.exports = {
return 0;
}.bind(this));
return (
-
+
+ tipContent={formatMessage({id: 'registration.nameStepTooltip'})} />
@@ -558,14 +566,14 @@ module.exports = {
var textAreaClass = (this.state.characterCount > this.props.maxCharacters) ? 'fail' : '';
return (
-
+
+ tipContent={formatMessage({id: 'registration.nameStepTooltip'})} />
@@ -625,14 +633,14 @@ module.exports = {
render: function () {
var formatMessage = this.props.intl.formatMessage;
return (
-
+
+ tipContent={formatMessage({id: 'registration.nameStepTooltip'})} />
@@ -669,7 +677,7 @@ module.exports = {
},
render: function () {
return (
-
+
@@ -707,10 +715,99 @@ 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:'
+ },
+ waiting: false
+ };
+ },
+ onNextStep: function () {
+ this.props.onNextStep();
+ },
+ render: function () {
+ return (
+
+
+ {this.props.classroom.educator.username}
+
+ {this.props.messages['registration.classroomInviteStepDescription']}
+
+
+
+
{this.props.classroom.title}
+
![]({this.props.classroom.images['250x150']})
+
+
+
+
+
+ );
+ }
+ }),
+ 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!'
+ }
+ };
+ },
+ onNextStep: function () {
+ this.props.onNextStep();
+ },
+ render: function () {
+ return (
+
+ {this.props.messages['registration.welcomeStepTitle']}
+ {this.props.messages['registration.welcomeStepDescription']}
+
+
+
{this.props.classroom.title}
+
![]({this.props.classroom.images['250x150']})
+
{this.props.messages['registration.welcomeStepPrompt']}
+
+
+
+
+ );
+ }
+ }),
RegistrationError: intl.injectIntl(React.createClass({
render: function () {
return (
-
+
Something went wrong
There was an error while processing your registration
diff --git a/src/components/registration/steps.scss b/src/components/registration/steps.scss
new file mode 100644
index 000000000..c9258a098
--- /dev/null
+++ b/src/components/registration/steps.scss
@@ -0,0 +1,254 @@
+@import "../../colors";
+@import "../../frameless";
+
+.registration-step {
+ .demographics-checkbox-is-robot {
+ display: none;
+ }
+
+ .invite-avatar {
+ display: block;
+ margin: 0 auto 1rem auto;
+ border: 2px solid $ui-white;
+ border-radius: 8px;
+ }
+
+ .gender-input,
+ .other-input {
+ float: right;
+ width: 90%;
+
+ .row {
+ margin-left: .5rem;
+ }
+ }
+
+ &.class-invite-step,
+ &.class-welcome-step {
+ .card {
+ text-align: center;
+
+ .contents {
+ padding: 2rem 0;
+ }
+ }
+ }
+
+ &.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;
+
+ input {
+ margin-right: 1rem;
+ }
+ }
+ }
+
+ &.phone-step {
+ .form-group {
+ margin-bottom: 2rem;
+ }
+
+ input {
+ &[type=checkbox] {
+ margin-bottom: 1.25rem;
+ }
+ }
+
+ .help-block {
+ margin-top: .5rem;
+ }
+
+ .checkbox-row {
+ .help-block {
+ margin-top: 0;
+ }
+ }
+ }
+
+ &.organization-step {
+ .help-block {
+ transform: translate(16rem, -4rem);
+ }
+
+ .checkbox-group {
+ .help-block {
+ 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;
+ }
+ }
+
+ .other-input {
+ margin-top: -5.75rem;
+ }
+ }
+
+ &.address-step {
+ .select {
+ .help-block {
+ transform: translate(0, .5rem);
+ }
+ }
+ }
+
+ &.usescratch-step {
+ .form {
+ .form-group {
+ margin-bottom: 0;
+
+ &.has-error {
+ .textarea {
+ border: 1px solid $ui-orange;
+ }
+ }
+ }
+
+
+ }
+
+ .help-block {
+ margin-top: .75rem;
+ }
+
+ p {
+ &.char-count {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ text-align: right;
+ }
+ }
+ }
+
+ &.last-step,
+ &.error-step {
+ &.slide {
+ max-width: 38.75rem;
+ }
+
+ .card {
+ margin: 1rem auto;
+ padding: 1.5rem;
+ width: initial;
+
+ h4,
+ p {
+ text-align: left;
+ }
+
+ p {
+ margin: 0;
+ }
+ }
+ }
+}
+
+@media only screen and (max-width: $mobile - 1) {
+ .registration-step {
+ &.demographics-step {
+ .radio {
+ width: 100%;
+ text-align: left;
+ }
+ }
+
+ &.last-step,
+ &.error-step {
+ .card {
+ margin: 0 auto;
+ width: 18.75rem;
+ }
+ }
+ }
+}
+
+@media only screen and (max-width: $desktop - 1) {
+ .registration-step {
+ .form {
+ text-align: left;
+ }
+
+ &.username-step,
+ &.demographics-step,
+ &.name-step,
+ &.address-step,
+ &.email-step {
+ .help-block {
+ transform: none;
+ }
+ }
+
+ &.phone-step {
+ .checkbox,
+ .help-block {
+ text-align: left;
+ }
+
+ .checkbox {
+ margin-bottom: 1rem;
+ }
+ }
+
+ &.organization-step {
+ .checkbox-group {
+ text-align: left;
+ }
+ }
+ }
+}
+
+/* IE10 and IE11 fallback */
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+ .registration-step {
+ &.username-step,
+ &.demographics-step,
+ &.name-step,
+ &.phone-step,
+ &.organization-step,
+ &.address-step,
+ &.email-step {
+ .help-block {
+ position: relative;
+ transform: none;
+ margin: inherit;
+ width: 100%;
+ height: inherit;
+
+ &:before {
+ display: none;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/slide/slide.scss b/src/components/slide/slide.scss
index 0d201a535..1fbf439ba 100644
--- a/src/components/slide/slide.scss
+++ b/src/components/slide/slide.scss
@@ -1,7 +1,28 @@
@import "../../frameless";
+@import "../../colors";
.slide {
padding: 10px;
+
+ > h2,
+ > .description {
+ text-align: center;
+ color: $type-white;
+ }
+
+ > .description {
+ margin-top: 0;
+ margin-bottom: 2rem;
+ }
+
+ .card {
+ margin: 0 auto;
+ }
+
+ .step-navigation {
+ margin-top: 2rem;
+ text-align: center;
+ }
}
@media only screen and (max-width: $tablet - 1) {
diff --git a/src/l10n.json b/src/l10n.json
index dda968f53..ef224cb86 100644
--- a/src/l10n.json
+++ b/src/l10n.json
@@ -12,7 +12,6 @@
"general.copyright": "Scratch is a project of the Lifelong Kindergarten Group at the MIT Media Lab",
"general.country": "Country",
"general.create": "Create",
- "general.createUsername": "Create a Username",
"general.credits": "Credits",
"general.discuss": "Discuss",
"general.dmca": "DMCA",
@@ -77,9 +76,6 @@
"general.username": "Username",
"general.validationEmail": "Please enter a valid email address",
"general.validationEmailMatch": "The emails do not match",
- "general.validationUsernameExists": "Sorry, that username already exists",
- "general.validationUsernameVulgar": "Hmm, that looks inappropriate",
- "general.validationUsernameInvalid": "Invalid username",
"general.viewAll": "View All",
"general.website": "Website",
"general.whatsHappening": "What's Happening?",
@@ -109,13 +105,34 @@
"parents.FaqResourcesQ": "What resources are available for learning Scratch?",
"parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab.",
- "registration.lastStepTitle": "Thank you for requesting a Scratch Teacher Account",
- "registration.lastStepDescription": "We are currently processing your application. ",
+ "registration.checkOutResources": "Get Started with Resources",
+ "registration.checkOutResourcesDescription": "Explore materials for educators and facilitators written by the Scratch Team, including tips, tutorials, and guides.",
"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.lastStepTitle": "Thank you for requesting a Scratch Teacher Account",
+ "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.showPassword": "Show password",
+ "registration.usernameStepDescription": "Fill in the following forms to request an account. The approval process may take up to 24 hours.",
+ "registration.usernameStepTitle": "Request a Teacher 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",
+ "registration.validationUsernameRegexp": "Your username may only contain letters, numbers, \"-\", and \"_\"",
+ "registration.validationUsernameMinLength": "Usernames must be at least 3 characters",
+ "registration.validationUsernameMaxLength": "Usernames must be at most 20 characters",
+ "registration.validationUsernameExists": "Sorry, that username already exists",
+ "registration.validationUsernameVulgar": "Hmm, that looks inappropriate",
+ "registration.validationUsernameInvalid": "Invalid username",
"registration.waitForApproval": "Wait for Approval",
"registration.waitForApprovalDescription": "You can log into your Scratch Account now, but the features specific to Teachers are not yet available. Your information is being reviewed. Please be patient, the approval process can take up to 24 hours. You will receive an email indicating your account has been upgraded once your account has been approved.",
- "registration.checkOutResources": "Get Started with Resources",
- "registration.checkOutResourcesDescription": "Explore materials for educators and facilitators written by the Scratch Team, including tips, tutorials, and guides."
-
+ "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!"
}
diff --git a/src/routes.json b/src/routes.json
index 2f076a608..5a7072d87 100644
--- a/src/routes.json
+++ b/src/routes.json
@@ -12,109 +12,16 @@
"title": "About"
},
{
- "name": "developers",
- "pattern": "^/developers/?$",
- "view": "developers/developers",
- "title": "Developers"
+ "name": "guidelines",
+ "pattern": "^/community_guidelines/?$",
+ "view": "guidelines/guidelines",
+ "title": "Scratch Community Guidelines"
},
{
- "name": "hoc",
- "pattern": "^/hoc/?$",
- "view": "hoc/hoc",
- "title": "Hour of Code"
- },
- {
- "name": "explore",
- "pattern": "^/explore/:projects/:all/?$",
- "routeAlias": "^/explore(?!/ajax)",
- "view": "explore/explore",
- "title": "Explore"
- },
- {
- "name": "explore-redirect",
- "pattern": "^/explore/?$",
- "routeAlias": "^/explore(?!/ajax)",
- "redirect": "/explore/projects/all"
- },
- {
- "name": "explore-projects-redirect",
- "pattern": "^/explore/projects/?$",
- "routeAlias": "^/explore(?!/ajax)",
- "redirect": "/explore/projects/all"
- },
- {
- "name": "explore-studios-redirect",
- "pattern": "^/explore/studios/?$",
- "routeAlias": "^/explore(?!/ajax)",
- "redirect": "/explore/studios/all"
- },
- {
- "name": "search",
- "pattern": "^/search/:projects?$/?$",
- "routeAlias": "^/search",
- "view": "search/search",
- "title": "Search"
- },
- {
- "name": "credits",
- "pattern": "^/info/credits/?$",
- "view": "credits/credits",
- "title": "Credits"
- },
- {
- "name": "faq",
- "pattern": "^/info/faq/?$",
- "view": "faq/faq",
- "title": "FAQ"
- },
- {
- "name": "educator-landing",
- "pattern": "^/educators/?$",
- "view": "teachers/landing/landing",
- "title": "Educators"
- },
- {
- "name": "teacher-faq",
- "pattern": "^/educators/faq/?$",
- "view": "teachers/faq/faq",
- "title": "Teacher Accounts FAQ"
- },
- {
- "name": "cards",
- "pattern": "^/info/cards/?$",
- "view": "cards/cards",
- "title": "Cards"
- },
- {
- "name": "communityblocks-interviews",
- "pattern": "^/info/communityblocks-interviews/?$",
- "view": "communityblocks-interviews/communityblocks-interviews",
- "title": "Community Blocks Beta Tester Interviews"
- },
- {
- "name": "jobs",
- "pattern": "^/jobs/?$",
- "view": "jobs/jobs",
- "title": "Jobs"
- },
- {
- "name": "teacherregistration",
- "pattern": "^/educators/register$",
- "view": "teacherregistration/teacherregistration",
- "title": "Teacher Registration",
- "viewportWidth": "device-width"
- },
- {
- "name": "teacherwaitingroom",
- "pattern": "^/educators/waiting",
- "view": "teacherwaitingroom/teacherwaitingroom",
- "title": "Thank you for requesting a Scratch Teacher Account"
- },
- {
- "name": "wedo2",
- "pattern": "^/wedo/?$",
- "view": "wedo2/wedo2",
- "title": "LEGO WeDo 2.0"
+ "name": "student-registration",
+ "pattern": "^/classes/:id/register/:token",
+ "view": "studentregistration/studentregistration",
+ "title": "Class Registration"
},
{
"name": "conference-index",
@@ -157,9 +64,10 @@
"viewportWidth": "device-width"
},
{
- "name": "donate",
- "pattern": "^/info/donate/?",
- "redirect": "https://secure.donationpay.org/scratchfoundation/"
+ "name": "developers",
+ "pattern": "^/developers/?$",
+ "view": "developers/developers",
+ "title": "Developers"
},
{
"name": "dmca",
@@ -168,10 +76,72 @@
"title": "DMCA"
},
{
- "name": "guidelines",
- "pattern": "^/community_guidelines/?$",
- "view": "guidelines/guidelines",
- "title": "Scratch Community Guidelines"
+ "name": "educator-landing",
+ "pattern": "^/educators/?$",
+ "view": "teachers/landing/landing",
+ "title": "Educators"
+ },
+ {
+ "name": "teacher-faq",
+ "pattern": "^/educators/faq/?$",
+ "view": "teachers/faq/faq",
+ "title": "Teacher Accounts FAQ"
+ },
+ {
+ "name": "teacherregistration",
+ "pattern": "^/educators/register$",
+ "view": "teacherregistration/teacherregistration",
+ "title": "Teacher Registration",
+ "viewportWidth": "device-width"
+ },
+ {
+ "name": "teacherwaitingroom",
+ "pattern": "^/educators/waiting",
+ "view": "teacherwaitingroom/teacherwaitingroom",
+ "title": "Thank you for requesting a Scratch Teacher Account"
+ },
+ {
+ "name": "explore",
+ "pattern": "^/explore/:projects/:all/?$",
+ "routeAlias": "^/explore(?!/ajax)",
+ "view": "explore/explore",
+ "title": "Explore"
+ },
+ {
+ "name": "hoc",
+ "pattern": "^/hoc/?$",
+ "view": "hoc/hoc",
+ "title": "Hour of Code"
+ },
+ {
+ "name": "cards",
+ "pattern": "^/info/cards/?$",
+ "view": "cards/cards",
+ "title": "Cards"
+ },
+ {
+ "name": "communityblocks-interviews",
+ "pattern": "^/info/communityblocks-interviews/?$",
+ "view": "communityblocks-interviews/communityblocks-interviews",
+ "title": "Community Blocks Beta Tester Interviews"
+ },
+ {
+ "name": "credits",
+ "pattern": "^/info/credits/?$",
+ "view": "credits/credits",
+ "title": "Credits"
+ },
+ {
+ "name": "faq",
+ "pattern": "^/info/faq/?$",
+ "view": "faq/faq",
+ "title": "FAQ"
+ },
+ {
+ "name": "jobs",
+ "pattern": "^/jobs/?$",
+ "view": "jobs/jobs",
+ "title": "Jobs"
},
{
"name": "privacypolicy",
@@ -179,10 +149,46 @@
"view": "privacypolicy/privacypolicy",
"title": "Privacy Policy"
},
+ {
+ "name": "search",
+ "pattern": "^/search/:projects?$/?$",
+ "routeAlias": "^/search",
+ "view": "search/search",
+ "title": "Search"
+ },
{
"name": "terms",
"pattern": "^/terms_of_use/?$",
"view": "terms/terms",
"title": "Scratch Terms of Use"
+ },
+ {
+ "name": "wedo2",
+ "pattern": "^/wedo/?$",
+ "view": "wedo2/wedo2",
+ "title": "LEGO WeDo 2.0"
+ },
+ {
+ "name": "donate",
+ "pattern": "^/info/donate/?",
+ "redirect": "https://secure.donationpay.org/scratchfoundation/"
+ },
+ {
+ "name": "explore-redirect",
+ "pattern": "^/explore/?$",
+ "routeAlias": "^/explore(?!/ajax)",
+ "redirect": "/explore/projects/all"
+ },
+ {
+ "name": "explore-projects-redirect",
+ "pattern": "^/explore/projects/?$",
+ "routeAlias": "^/explore(?!/ajax)",
+ "redirect": "/explore/projects/all"
+ },
+ {
+ "name": "explore-studios-redirect",
+ "pattern": "^/explore/studios/?$",
+ "routeAlias": "^/explore(?!/ajax)",
+ "redirect": "/explore/studios/all"
}
]
diff --git a/src/views/studentregistration/l10n.json b/src/views/studentregistration/l10n.json
new file mode 100644
index 000000000..ede12528d
--- /dev/null
+++ b/src/views/studentregistration/l10n.json
@@ -0,0 +1,3 @@
+{
+ "studentRegistration.classroomApiGeneralError": "Sorry, we could not find the registration information for this class"
+}
diff --git a/src/views/studentregistration/studentregistration.jsx b/src/views/studentregistration/studentregistration.jsx
new file mode 100644
index 000000000..c7710e0ba
--- /dev/null
+++ b/src/views/studentregistration/studentregistration.jsx
@@ -0,0 +1,124 @@
+var defaults = require('lodash.defaultsdeep');
+var React = require('react');
+var render = require('../../lib/render.jsx');
+
+var api = require('../../lib/api');
+var intl = require('../../lib/intl.jsx');
+
+var Deck = require('../../components/deck/deck.jsx');
+var Progression = require('../../components/progression/progression.jsx');
+var Steps = require('../../components/registration/steps.jsx');
+
+require('./studentregistration.scss');
+
+var StudentRegistration = intl.injectIntl(React.createClass({
+ type: 'StudentRegistration',
+ getDefaultProps: function () {
+ return {
+ classroomId: null,
+ classroomToken: null
+ };
+ },
+ getInitialState: function () {
+ return {
+ formData: {},
+ registrationError: null,
+ step: 0,
+ waiting: false
+ };
+ },
+ advanceStep: function (formData) {
+ formData = formData || {};
+ this.setState({
+ step: this.state.step + 1,
+ formData: defaults({}, formData, this.state.formData)
+ });
+ },
+ componentDidMount: function () {
+ api({
+ uri: '/classrooms/' + this.props.classroomId + '/' + this.props.classroomToken
+ }, function (err, body, res) {
+ if (err) {
+ return this.setState({
+ registrationError: this.props.intl.formatMessage({
+ id: 'studentRegistration.classroomApiGeneralError'
+ })
+ });
+ }
+ if (res.statusCode === 404) {
+ // TODO: Use react-router for this
+ return window.location = '/404';
+ }
+ this.setState({classroom: body});
+ }.bind(this));
+ },
+ register: function (formData) {
+ this.setState({waiting: true});
+ formData = defaults({}, formData || {}, this.state.formData);
+ api({
+ host: '',
+ uri: '/classes/register_new_student/',
+ method: 'post',
+ useCsrf: true,
+ formData: {
+ username: formData.user.username,
+ password: formData.user.password,
+ birth_month: formData.user.birth.month,
+ birth_year: formData.user.birth.year,
+ gender: (
+ formData.user.gender === 'other' ?
+ formData.user.genderOther :
+ formData.user.gender
+ ),
+ country: formData.user.country,
+ is_robot: formData.user.isRobot,
+ classroom_id: this.props.classroomId,
+ classroom_token: this.props.classroomToken
+ }
+ }, function (err, res) {
+ this.setState({waiting: false});
+ if (err) return this.setState({registrationError: err});
+ if (res[0].success) return this.advanceStep(formData);
+ this.setState({registrationError: res[0].msg});
+ }.bind(this));
+ },
+ goToClass: function () {
+ window.location = '/classes/' + this.props.classroomId + '/';
+ },
+ render: function () {
+ var demographicsDescription = this.props.intl.formatMessage({id: 'registration.notOnWebsite'});
+ return (
+
+ {this.state.registrationError ?
+
+ :
+
+
+
+
+
+
+ }
+
+ );
+ }
+}));
+
+var [classroomId, _, classroomToken] = document.location.pathname.split('/')
+ .filter(function (p) {
+ if (p) return p;
+ })
+ .slice(-3);
+
+var props = {classroomId, classroomToken};
+
+render(, document.getElementById('app'));
diff --git a/src/views/studentregistration/studentregistration.scss b/src/views/studentregistration/studentregistration.scss
new file mode 100644
index 000000000..206177e45
--- /dev/null
+++ b/src/views/studentregistration/studentregistration.scss
@@ -0,0 +1,13 @@
+@import "../../colors";
+@import "../../frameless";
+
+@include responsive-layout (".student-registration", ".slide");
+
+html,
+body {
+ background-color: darken($ui-purple, 8%);
+}
+
+.teacher-registration {
+ background-color: $ui-purple;
+}
diff --git a/src/views/teacherregistration/l10n.json b/src/views/teacherregistration/l10n.json
index b99e49e57..8a3ef05b6 100644
--- a/src/views/teacherregistration/l10n.json
+++ b/src/views/teacherregistration/l10n.json
@@ -1,19 +1,6 @@
{
- "teacherRegistration.usernameStepDescription": "Fill in the following forms to request an account. The approval process may take up to 24 hours.",
- "teacherRegistration.usernameStepTitle": "Request a Teacher Account",
- "teacherRegistration.validationUsernameRegexp": "Your username may only contain letters, numbers, \"-\", and \"_\"",
- "teacherRegistration.validationUsernameMinLength": "Usernames must be at least 3 characters",
- "teacherRegistration.validationUsernameMaxLength": "Usernames must be at most 20 characters",
- "teacherRegistration.validationPasswordLength": "Passwords must be at least six characters",
- "teacherRegistration.validationPasswordNotEquals": "Your password may not be \"password\"",
- "teacherRegistration.validationPasswordNotUsername": "Your password may not be your username",
- "teacherRegistration.showPassword": "Show password",
- "teacherRegistration.nextStep": "Next Step",
- "teacherRegistration.personalStepTitle": "Personal Information",
- "teacherRegistration.personalStepDescription": "Your individual responses will not be displayed publicly, and will be kept confidential and secure",
"teacherRegistration.nameStepTitle": "First & Last Name",
"teacherRegistration.nameStepDescription": "Your name will not be displayed publicly, and will be kept confidential and secure.",
- "teacherRegistration.nameStepTooltip": "This information is used for verification and to aggregate usage statistics.",
"teacherRegistration.firstName": "First Name",
"teacherRegistration.lastName": "Last Name",
"teacherRegistration.phoneStepTitle": "Phone Number",
diff --git a/src/views/teacherregistration/teacherregistration.jsx b/src/views/teacherregistration/teacherregistration.jsx
index 4c012bc9b..cb0df97e1 100644
--- a/src/views/teacherregistration/teacherregistration.jsx
+++ b/src/views/teacherregistration/teacherregistration.jsx
@@ -79,28 +79,28 @@ var TeacherRegistration = React.createClass({
:
-
+
-
-
+
+
-
-
-
+
+
+
}
diff --git a/src/views/teacherregistration/teacherregistration.scss b/src/views/teacherregistration/teacherregistration.scss
index 336eddecb..98390100a 100644
--- a/src/views/teacherregistration/teacherregistration.scss
+++ b/src/views/teacherregistration/teacherregistration.scss
@@ -10,209 +10,4 @@ body {
.teacher-registration {
background-color: $ui-purple;
-
- .demographics-checkbox-is-robot {
- display: none;
- }
-
- .gender-input,
- .other-input {
- float: right;
- width: 90%;
-
- .row {
- margin-left: .5rem;
- }
- }
-
- .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;
-
- input {
- margin-right: 1rem;
- }
- }
- }
-
- .phone-step {
- .form-group {
- margin-bottom: 2rem;
- }
-
- input {
- &[type=checkbox] {
- margin-bottom: 1.25rem;
- }
- }
-
- .help-block {
- margin-top: .5rem;
- }
-
- .checkbox-row {
- .help-block {
- margin-top: 0;
- }
- }
- }
-
- .organization-step {
- .help-block {
- transform: translate(16rem, -4rem);
- }
-
- .checkbox-group {
- .help-block {
- 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;
- }
- }
-
- .other-input {
- margin-top: -5.75rem;
- }
- }
-
- .address-step {
- .select {
- .help-block {
- transform: translate(0, .5rem);
- }
- }
- }
-
- .usescratch-step {
- .form {
- .form-group {
- margin-bottom: 0;
-
- &.has-error {
- .textarea {
- border: 1px solid $ui-orange;
- }
- }
- }
-
-
- }
-
- .help-block {
- margin-top: .75rem;
- }
-
- p {
- &.char-count {
- margin-top: 0;
- margin-bottom: 1rem;
- text-align: right;
- }
- }
- }
-
- .last-step,
- .error-step {
- &.slide {
- max-width: 38.75rem;
- }
-
- .card {
- margin: 1rem auto;
- padding: 1.5rem;
- width: initial;
-
- h4,
- p {
- text-align: left;
- }
-
- p {
- margin: 0;
- }
- }
- }
-}
-
-@media only screen and (max-width: $mobile - 1) {
- .teacher-registration {
- .demographics-step {
- .radio {
- width: 100%;
- text-align: left;
- }
- }
-
- .last-step,
- .error-step {
- .card {
- margin: 0 auto;
- width: 18.75rem;
- }
- }
- }
-}
-
-@media only screen and (max-width: $desktop - 1) {
- .teacher-registration {
- .form {
- text-align: left;
- }
-
- .username-step,
- .demographics-step,
- .name-step {
- .help-block {
- transform: none;
- }
- }
-
- .phone-step {
- .checkbox,
- .help-block {
- text-align: left;
- }
-
- .checkbox {
- margin-bottom: 1rem;
- }
- }
-
- .organization-step {
- .checkbox-group {
- text-align: left;
- }
- }
- }
}
diff --git a/src/views/teachers/landing/l10n.json b/src/views/teachers/landing/l10n.json
index 8e8ac23b1..c4fd9ca41 100644
--- a/src/views/teachers/landing/l10n.json
+++ b/src/views/teachers/landing/l10n.json
@@ -1,16 +1,17 @@
{
"teacherlanding.title": "Scratch for Educators",
"teacherlanding.intro": "Your students can use Scratch to code their own interactive stories, animations, and games. In the process, they learn to think creatively, reason systematically, and work collaboratively — essential skills for everyone in today’s society.",
- "teacherlanding.inPracticeAnchor": "In Practice",
+ "teacherlanding.inPracticeAnchor": "Who Uses Scratch?",
"teacherlanding.resourcesAnchor": "Resources",
"teacherlanding.inPracticeTitle": "Who Uses Scratch?",
"teacherlanding.inPracticeIntro": "Educators are using Scratch in a wide variety of: ",
"teacherlanding.generalUsageSettings": "Settings: schools, museums, libraries, community centers",
"teacherlanding.generalUsageGradeLevels": "Grade Levels: elementary, middle, and high school (and some colleges too!)",
"teacherlanding.generalUsageSubjectAreas": "Subject Areas: language arts, science, social studies, math, computer science, foreign languages, and the arts",
- "teacherlanding.ingridTitle": "Instructional Technology Specialist",
- "teacherlanding.dylanTitle": "Educational Technologist",
- "teacherlanding.afterSchoolTitle": "After-School Program",
+ "teacherlanding.elementaryTitle": "Elementary Schools",
+ "teacherlanding.middleTitle": "Middle Schools",
+ "teacherlanding.communityTitle": "Community Programs",
+ "teacherlanding.afterSchoolTitle": "After-School Programs",
"teacherlanding.resourcesTitle": "Educator Resources",
"teacherlanding.scratchEdTitle": "A Community for Educators",
"teacherlanding.scratchEdDescription": "ScratchEd is an online community where Scratch educators share stories, exchange resources, ask questions, and find people. ScratchEd is developed and supported by the Harvard Graduate School of Education.",
diff --git a/src/views/teachers/landing/landing.jsx b/src/views/teachers/landing/landing.jsx
index e61973412..fdb6222d6 100644
--- a/src/views/teachers/landing/landing.jsx
+++ b/src/views/teachers/landing/landing.jsx
@@ -62,34 +62,34 @@ var Landing = injectIntl(React.createClass({
-
-
-
-
-
+
-
Dylan Ryder
-
+
+
The School at Columbia University
+
+
+
+
+
+
+
Cambridge Public Schools
+ alt="Community Programs" />
-
Plug-In Studios
-
+
+
Plug-In Studio
+ alt="After-School Programs" />
-
Ghana Code Club
-
+
+
Ghana Code Club