mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 07:38:07 -05:00
Merge pull request #881 from LLK/release/2.2.12
[Master] Release 2.2.12
This commit is contained in:
commit
6f8a6eca42
50 changed files with 1129 additions and 516 deletions
|
@ -36,6 +36,11 @@ env:
|
|||
- GA_TRACKER_VAR=GA_TRACKER_$TRAVIS_BRANCH
|
||||
- GA_TRACKER=${!GA_TRACKER_VAR}
|
||||
- GA_TRACKER=${GA_TRACKER:-$GA_TRACKER_STAGING}
|
||||
- SCRATCH_ENV_master=production
|
||||
- SCRATCH_ENV_STAGING=staging
|
||||
- SCRATCH_ENV_VAR=SCRATCH_ENV_$TRAVIS_BRANCH
|
||||
- SCRATCH_ENV=${!SCRATCH_ENV_VAR}
|
||||
- SCRATCH_ENV=${SCRATCH_ENV:-$SCRATCH_ENV_STAGING}
|
||||
- S3_BUCKET_NAME_master=scratch-www-production
|
||||
- S3_BUCKET_NAME_STAGING=scratch-www-staging
|
||||
- S3_BUCKET_NAME_VAR=S3_BUCKET_NAME_$TRAVIS_BRANCH
|
||||
|
|
3
Makefile
3
Makefile
|
@ -31,8 +31,9 @@ webpack:
|
|||
$(WEBPACK) --bail
|
||||
|
||||
sync-s3:
|
||||
$(S3CMD) sync -P --delete-removed --exclude '.DS_Store' --exclude '*.svg' ./build/ s3://$(S3_BUCKET_NAME)/
|
||||
$(S3CMD) sync -P --delete-removed --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$(S3_BUCKET_NAME)/
|
||||
$(S3CMD) sync -P --delete-removed --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$(S3_BUCKET_NAME)/
|
||||
$(S3CMD) sync -P --delete-removed --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$(S3_BUCKET_NAME)/
|
||||
|
||||
sync-fastly:
|
||||
$(NODE) ./bin/configure-fastly.js
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"ab": {
|
||||
"locale": "ab",
|
||||
"parentLocale": "az"
|
||||
},
|
||||
"an": {
|
||||
"locale": "an",
|
||||
"parentLocale": "ca"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
{
|
||||
"en": "English",
|
||||
"ab": "Аҧсшәа",
|
||||
"ar": "العربية",
|
||||
"an": "Aragonés",
|
||||
"ast": "Asturianu",
|
||||
"id": "Bahasa Indonesia",
|
||||
"ms": "Bahasa Melayu",
|
||||
"bg": "Български",
|
||||
"ca": "Català",
|
||||
"cs": "Česky",
|
||||
"cy": "Cymraeg",
|
||||
|
@ -12,62 +14,63 @@
|
|||
"de": "Deutsch",
|
||||
"yum": "Edible Scratch",
|
||||
"et": "Eesti",
|
||||
"el": "Ελληνικά",
|
||||
"en": "English",
|
||||
"eo": "Esperanto",
|
||||
"es": "Español",
|
||||
"eu": "Euskara",
|
||||
"fa": "فارسی",
|
||||
"fr": "Français",
|
||||
"fur": "Furlan",
|
||||
"ga": "Gaeilge",
|
||||
"gd": "Gàidhlig",
|
||||
"gl": "Galego",
|
||||
"ko": "한국어",
|
||||
"hy": "Հայերեն",
|
||||
"he": "עִבְרִית",
|
||||
"hi": "हिन्दी",
|
||||
"hr": "Hrvatski",
|
||||
"is": "Íslenska",
|
||||
"it": "Italiano",
|
||||
"kn": "ಭಾಷೆ-ಹೆಸರು",
|
||||
"rw": "Kinyarwanda",
|
||||
"km": "សំលៀកបំពាក",
|
||||
"ht": "Kreyòl",
|
||||
"ku": "Kurdî",
|
||||
"la": "Latina",
|
||||
"lv": "Latviešu",
|
||||
"lt": "Lietuvių",
|
||||
"mk": "Македонски",
|
||||
"hu": "Magyar",
|
||||
"ml": "മലയാളം",
|
||||
"mt": "Malti",
|
||||
"mr": "मराठी",
|
||||
"cat": "Meow",
|
||||
"mn": "Монгол хэл",
|
||||
"my": "မြန်မာဘာသာ",
|
||||
"nl": "Nederlands",
|
||||
"ja": "日本語",
|
||||
"ja-hr": "にほんご",
|
||||
"nb": "Norsk Bokmål",
|
||||
"nn": "Norsk Nynorsk",
|
||||
"uz": "Oʻzbekcha",
|
||||
"th": "ไทย",
|
||||
"pl": "Polski",
|
||||
"pt": "Português",
|
||||
"pt-br": "Português Brasileiro",
|
||||
"ro": "Română",
|
||||
"ru": "Русский",
|
||||
"sc": "Sardu",
|
||||
"sq": "Shqiptar",
|
||||
"sk": "Slovenčina",
|
||||
"sl": "Slovenščina",
|
||||
"fi": "suomi",
|
||||
"sr": "Српски",
|
||||
"fi": "Suomi",
|
||||
"sv": "Svenska",
|
||||
"te": "తెలుగు",
|
||||
"nai": "Tepehuan",
|
||||
"vi": "Tiếng Việt",
|
||||
"tr": "Türkçe",
|
||||
"ab": "Аҧсшәа",
|
||||
"ar": "العربية",
|
||||
"bg": "Български",
|
||||
"el": "Ελληνικά",
|
||||
"fa": "فارسی",
|
||||
"he": "עִבְרִית",
|
||||
"hi": "हिन्दी",
|
||||
"hy": "Հայերեն",
|
||||
"ja": "日本語",
|
||||
"ja-hr": "にほんご",
|
||||
"km": "សំលៀកបំពាក",
|
||||
"kn": "ಭಾಷೆ-ಹೆಸರು",
|
||||
"ko": "한국어",
|
||||
"mk": "Македонски",
|
||||
"ml": "മലയാളം",
|
||||
"mn": "Монгол хэл",
|
||||
"mr": "मराठी",
|
||||
"my": "မြန်မာဘာသာ",
|
||||
"ru": "Русский",
|
||||
"sr": "Српски",
|
||||
"th": "ไทย",
|
||||
"uk": "Українська",
|
||||
"zh-cn": "简体中文",
|
||||
"zh-tw": "正體中文"
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
"react-modal": "1.3.0",
|
||||
"react-onclickoutside": "4.1.1",
|
||||
"react-redux": "4.4.5",
|
||||
"react-responsive": "1.1.4",
|
||||
"react-slick": "0.12.2",
|
||||
"react-telephone-input": "3.4.5",
|
||||
"redux": "3.5.2",
|
||||
|
|
|
@ -11,6 +11,7 @@ $background-color: hsla(0, 0, 99, 1); //#FDFDFD
|
|||
/* UI Secondary Colors */
|
||||
$ui-aqua: hsla(170, 70, 50, 1); //#26D9BB
|
||||
$ui-purple: hsla(265, 55, 55, 1); //#824DCB
|
||||
$ui-yellow: hsla(45, 100, 50, 1); //#FFBF00
|
||||
$ui-white: #fff;
|
||||
|
||||
$ui-border: hsla(0, 0, 85, 1); //#D9D9D9
|
||||
|
|
|
@ -5,6 +5,8 @@ var Slider = require('react-slick');
|
|||
|
||||
var Thumbnail = require('../thumbnail/thumbnail.jsx');
|
||||
|
||||
var frameless = require('../../lib/frameless.js');
|
||||
|
||||
require('slick-carousel/slick/slick.scss');
|
||||
require('slick-carousel/slick/slick-theme.scss');
|
||||
require('./carousel.scss');
|
||||
|
@ -27,12 +29,29 @@ var Carousel = React.createClass({
|
|||
render: function () {
|
||||
var settings = this.props.settings || {};
|
||||
defaults(settings, {
|
||||
centerMode: false,
|
||||
dots: false,
|
||||
infinite: false,
|
||||
lazyLoad: true,
|
||||
slidesToShow: 5,
|
||||
slidesToScroll: 5,
|
||||
variableWidth: true
|
||||
variableWidth: true,
|
||||
responsive: [
|
||||
{breakpoint: frameless.mobile, settings: {
|
||||
arrows: true,
|
||||
slidesToScroll: 1,
|
||||
slidesToShow: 1,
|
||||
centerMode: true
|
||||
}},
|
||||
{breakpoint: frameless.tablet, settings: {
|
||||
slidesToScroll: 2,
|
||||
slidesToShow: 2
|
||||
}},
|
||||
{breakpoint: frameless.desktop, settings: {
|
||||
slidesToScroll: 4,
|
||||
slidesToShow: 4
|
||||
}}
|
||||
]
|
||||
});
|
||||
var arrows = this.props.items.length > settings.slidesToShow;
|
||||
var classes = classNames(
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
.intel {
|
||||
img {
|
||||
max-height: 50px
|
||||
max-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
var React = require('react');
|
||||
var FormattedMessage = require('react-intl').FormattedMessage;
|
||||
var ReactIntl = require('react-intl');
|
||||
var FormattedMessage = ReactIntl.FormattedMessage;
|
||||
var injectIntl = ReactIntl.injectIntl;
|
||||
|
||||
var FooterBox = require('../container/footer.jsx');
|
||||
var LanguageChooser = require('../../languagechooser/languagechooser.jsx');
|
||||
|
||||
var MediaQuery = require('react-responsive');
|
||||
var frameless = require('../../../lib/frameless');
|
||||
|
||||
require('./footer.scss');
|
||||
|
||||
var Footer = React.createClass({
|
||||
|
@ -11,159 +16,197 @@ var Footer = React.createClass({
|
|||
render: function () {
|
||||
return (
|
||||
<FooterBox>
|
||||
<div className="lists">
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.about' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/about/">
|
||||
<FormattedMessage id='general.aboutScratch' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/parents/">
|
||||
<FormattedMessage id='general.forParents' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/educators/">
|
||||
<FormattedMessage id='general.forEducators' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/developers">
|
||||
<FormattedMessage id='general.forDevelopers' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/info/credits/">
|
||||
<FormattedMessage id='general.credits' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/jobs/">
|
||||
<FormattedMessage id='general.jobs' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://wiki.scratch.mit.edu/wiki/Scratch_Press">
|
||||
<FormattedMessage id='general.press' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<MediaQuery maxWidth={frameless.tablet - 1}>
|
||||
<div className="lists">
|
||||
<dl>
|
||||
<dd>
|
||||
<a href="/about/">
|
||||
<FormattedMessage id='general.aboutScratch' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/jobs/">
|
||||
<FormattedMessage id='general.jobs' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/contact-us/">
|
||||
<FormattedMessage id='general.contactUs' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dd>
|
||||
<a href="/terms_of_use/">
|
||||
<FormattedMessage id='general.termsOfUse' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/privacy_policy/">
|
||||
<FormattedMessage id='general.privacyPolicy' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/community_guidelines/">
|
||||
<FormattedMessage id='general.guidelines' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</MediaQuery>
|
||||
<MediaQuery minWidth={frameless.tablet}>
|
||||
<div className="lists">
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.about' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/about/">
|
||||
<FormattedMessage id='general.aboutScratch' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/parents/">
|
||||
<FormattedMessage id='general.forParents' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/educators/">
|
||||
<FormattedMessage id='general.forEducators' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/developers">
|
||||
<FormattedMessage id='general.forDevelopers' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/info/credits/">
|
||||
<FormattedMessage id='general.credits' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/jobs/">
|
||||
<FormattedMessage id='general.jobs' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://wiki.scratch.mit.edu/wiki/Scratch_Press">
|
||||
<FormattedMessage id='general.press' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.community' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/community_guidelines/">
|
||||
<FormattedMessage id='general.guidelines' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/discuss/">
|
||||
<FormattedMessage id='footer.discuss' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="https://wiki.scratch.mit.edu/">
|
||||
<FormattedMessage id='general.wiki' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/statistics/">
|
||||
<FormattedMessage id='general.statistics' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.community' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/community_guidelines/">
|
||||
<FormattedMessage id='general.guidelines' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/discuss/">
|
||||
<FormattedMessage id='footer.discuss' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="https://wiki.scratch.mit.edu/">
|
||||
<FormattedMessage id='general.wiki' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/statistics/">
|
||||
<FormattedMessage id='general.statistics' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.support' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/help/">
|
||||
<FormattedMessage id='footer.help' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/info/faq/">
|
||||
<FormattedMessage id='general.faq' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/scratch2download/">
|
||||
<FormattedMessage id='general.offlineEditor' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/contact-us/">
|
||||
<FormattedMessage id='general.contactUs' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="https://secure.donationpay.org/scratchfoundation/">
|
||||
<FormattedMessage id='general.donate'/>
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.support' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/help/">
|
||||
<FormattedMessage id='footer.help' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/info/faq/">
|
||||
<FormattedMessage id='general.faq' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/scratch2download/">
|
||||
<FormattedMessage id='general.offlineEditor' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/contact-us/">
|
||||
<FormattedMessage id='general.contactUs' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="https://secure.donationpay.org/scratchfoundation/">
|
||||
<FormattedMessage id='general.donate'/>
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.legal'/>
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/terms_of_use/">
|
||||
<FormattedMessage id='general.termsOfUse' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/privacy_policy/">
|
||||
<FormattedMessage id='general.privacyPolicy' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/DMCA/">
|
||||
<FormattedMessage id='general.dmca' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='general.legal'/>
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="/terms_of_use/">
|
||||
<FormattedMessage id='general.termsOfUse' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/privacy_policy/">
|
||||
<FormattedMessage id='general.privacyPolicy' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/DMCA/">
|
||||
<FormattedMessage id='general.dmca' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='footer.scratchFamily' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="http://scratched.gse.harvard.edu/">
|
||||
<FormattedMessage id='general.scratchEd' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://www.scratchjr.org/">
|
||||
<FormattedMessage id='general.scratchJr' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://day.scratch.mit.edu/">
|
||||
<FormattedMessage id='general.scratchday' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/conference/">
|
||||
<FormattedMessage id='general.scratchConference' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://www.scratchfoundation.org/">
|
||||
<FormattedMessage id='general.scratchFoundation' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<LanguageChooser />
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='footer.scratchFamily' />
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="http://scratched.gse.harvard.edu/">
|
||||
<FormattedMessage id='general.scratchEd' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://www.scratchjr.org/">
|
||||
<FormattedMessage id='general.scratchJr' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://day.scratch.mit.edu/">
|
||||
<FormattedMessage id='general.scratchday' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/conference/">
|
||||
<FormattedMessage id='general.scratchConference' />
|
||||
</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="http://www.scratchfoundation.org/">
|
||||
<FormattedMessage id='general.scratchFoundation' />
|
||||
</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</MediaQuery>
|
||||
<LanguageChooser locale={this.props.intl.locale} />
|
||||
|
||||
<div className="copyright">
|
||||
<p>
|
||||
|
@ -175,4 +218,4 @@ var Footer = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
module.exports = Footer;
|
||||
module.exports = injectIntl(Footer);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import "../../../colors";
|
||||
@import "../../../frameless";
|
||||
|
||||
#footer {
|
||||
.lists {
|
||||
|
@ -6,11 +7,10 @@
|
|||
text-align: center;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
justify-content: space-around;
|
||||
|
||||
dl {
|
||||
display: inline-block;
|
||||
width: 130pt;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
font-size: .8rem;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
display: block;
|
||||
float: left;
|
||||
margin-right: 1rem;
|
||||
border: 1px solid $active-gray;
|
||||
border: 1px solid $active-dark-gray;
|
||||
border-radius: 3px;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
|
@ -22,7 +22,7 @@
|
|||
&:focus {
|
||||
transition: all .5s ease;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 .25rem $active-gray;
|
||||
box-shadow: 0 0 0 .25rem $active-dark-gray;
|
||||
}
|
||||
|
||||
&:checked {
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
var FormsyMixin = require('formsy-react').Mixin;
|
||||
var ReactPhoneInput = require('react-telephone-input/lib/withStyles');
|
||||
var allCountries = require('react-telephone-input/lib/country_data').allCountries;
|
||||
var defaultValidationHOC = require('./validations.jsx').defaultValidationHOC;
|
||||
var validationHOCFactory = require('./validations.jsx').validationHOCFactory;
|
||||
var Row = require('formsy-react-components').Row;
|
||||
var classNames = require('classnames');
|
||||
var ComponentMixin = require('formsy-react-components').ComponentMixin;
|
||||
var FormsyMixin = require('formsy-react').Mixin;
|
||||
var React = require('react');
|
||||
var ReactPhoneInput = require('react-telephone-input/lib/withStyles');
|
||||
var Row = require('formsy-react-components').Row;
|
||||
|
||||
var defaultValidationHOC = require('./validations.jsx').defaultValidationHOC;
|
||||
var inputHOC = require('./input-hoc.jsx');
|
||||
var intl = require('../../lib/intl.jsx');
|
||||
var validationHOCFactory = require('./validations.jsx').validationHOCFactory;
|
||||
|
||||
var allIso2 = allCountries.map(function (country) {return country.iso2;});
|
||||
|
||||
|
@ -62,7 +64,7 @@ var PhoneInput = React.createClass({
|
|||
});
|
||||
|
||||
var phoneValidationHOC = validationHOCFactory({
|
||||
isPhone: 'Please enter a valid phone number'
|
||||
isPhone: <intl.FormattedMessage id="teacherRegistration.validationPhoneNumber" />
|
||||
});
|
||||
|
||||
module.exports = inputHOC(defaultValidationHOC(phoneValidationHOC(PhoneInput)));
|
||||
|
|
|
@ -23,6 +23,7 @@ module.exports.validations = {
|
|||
return phoneNumberUtil.isValidNumber(parsed);
|
||||
}
|
||||
};
|
||||
module.exports.validations.notEqualsUsername = module.exports.validations.notEquals;
|
||||
|
||||
module.exports.validationHOCFactory = function (defaultValidationErrors) {
|
||||
return function (Component) {
|
||||
|
|
|
@ -15,7 +15,8 @@ var Grid = React.createClass({
|
|||
showLoves: false,
|
||||
showFavorites: false,
|
||||
showRemixes: false,
|
||||
showViews: false
|
||||
showViews: false,
|
||||
showAvatar: false
|
||||
};
|
||||
},
|
||||
render: function () {
|
||||
|
@ -36,10 +37,13 @@ var Grid = React.createClass({
|
|||
showFavorites={this.props.showFavorites}
|
||||
showRemixes={this.props.showRemixes}
|
||||
showViews={this.props.showViews}
|
||||
showAvatar={this.props.showAvatar}
|
||||
type={'project'}
|
||||
href={href}
|
||||
title={item.title}
|
||||
src={item.image}
|
||||
avatar={'https://cdn2.scratch.mit.edu/get_image/user/'
|
||||
+ item.author.id + '_32x32.png'}
|
||||
creator={item.author.username}
|
||||
loves={item.stats.loves}
|
||||
favorites={item.stats.favorites}
|
||||
|
|
|
@ -1,40 +1,89 @@
|
|||
@import "../../frameless";
|
||||
@import "../../colors";
|
||||
|
||||
.grid {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
|
||||
$project-width: 200px;
|
||||
$project-height: 150px;
|
||||
|
||||
$gallery-width: 200px;
|
||||
$gallery-height: 118px;
|
||||
$thumbnail-width: 220px;
|
||||
$thumbnail-inner-width: 204px;
|
||||
|
||||
$project-height: 208px;
|
||||
$gallery-height: 164px;
|
||||
|
||||
.flex-row {
|
||||
margin: 0 auto;
|
||||
padding: 12px;
|
||||
width: (96px + (4 * $project-width)) / $em;
|
||||
padding: 12px 0;
|
||||
width: $cols12;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
padding: 12px;
|
||||
margin: 7px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 3px $box-shadow-gray;
|
||||
background-color: $ui-white;
|
||||
padding-bottom: 4px;
|
||||
width: $thumbnail-width;
|
||||
|
||||
.thumbnail-image {
|
||||
margin: 8px auto;
|
||||
width: $thumbnail-inner-width;
|
||||
}
|
||||
|
||||
.thumbnail-info {
|
||||
margin: 0 auto;
|
||||
width: $thumbnail-inner-width;
|
||||
|
||||
.creator-image {
|
||||
float: left;
|
||||
|
||||
img {
|
||||
margin-right: 8px;
|
||||
border-radius: 4px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail-title {
|
||||
float: left;
|
||||
max-width: 164px;
|
||||
|
||||
.thumbnail-creator a {
|
||||
color: $type-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.project {
|
||||
width: $project-width;
|
||||
height: $project-height;
|
||||
|
||||
img {
|
||||
width: $project-width;
|
||||
height: $project-height;
|
||||
.thumbnail-image {
|
||||
height: 152px;
|
||||
|
||||
img {
|
||||
margin: 0 auto;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
width: $thumbnail-inner-width;
|
||||
height: 152px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.gallery {
|
||||
width: $gallery-width;
|
||||
height: $gallery-height;
|
||||
|
||||
img {
|
||||
width: $gallery-width;
|
||||
height: $gallery-height;
|
||||
.thumbnail-image {
|
||||
height: 120px;
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
width: $thumbnail-inner-width;
|
||||
height: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,15 +93,24 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $tablet - 1) {
|
||||
flex-direction: column;
|
||||
//4 columns
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
.flex-row {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $desktop - 1) {
|
||||
//6 columns
|
||||
@media only screen and (min-width: $mobile) and (max-width: $tablet - 1) {
|
||||
.flex-row {
|
||||
padding: 12px 0;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
width: $cols6;
|
||||
}
|
||||
}
|
||||
|
||||
// 8 columns
|
||||
@media only screen and (min-width: $tablet) and (max-width: $desktop - 1) {
|
||||
.flex-row {
|
||||
width: $cols9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ var LanguageChooser = React.createClass({
|
|||
getDefaultProps: function () {
|
||||
return {
|
||||
languages: languages,
|
||||
locale: window._locale
|
||||
locale: 'en'
|
||||
};
|
||||
},
|
||||
onSetLanguage: function (name, value) {
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
padding-top: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.spinner {
|
||||
margin: 0 .8rem;
|
||||
width: 1rem;
|
||||
|
|
|
@ -251,7 +251,9 @@ var Navigation = React.createClass({
|
|||
<a className={dropdownClasses}
|
||||
href="#" onClick={this.handleAccountNavClick}>
|
||||
<Avatar src={this.props.session.session.user.thumbnailUrl} alt="" />
|
||||
{this.props.session.session.user.username}
|
||||
<span className='profile-name'>
|
||||
{this.props.session.session.user.username}
|
||||
</span>
|
||||
</a>
|
||||
<Dropdown
|
||||
as="ul"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import "../../../colors";
|
||||
@import "../../../frameless";
|
||||
|
||||
#navigation {
|
||||
&.staging {
|
||||
|
@ -231,3 +232,97 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//4 columns
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
#navigation .inner {
|
||||
width: $cols4;
|
||||
|
||||
> ul > li {
|
||||
&.login-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.account-nav {
|
||||
margin-left: 0;
|
||||
|
||||
> a {
|
||||
.avatar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.create,
|
||||
.discuss,
|
||||
.explore,
|
||||
.search,
|
||||
.help,
|
||||
.mystuff,
|
||||
.profile-name {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//6 columns
|
||||
@media only screen and (min-width: $mobile) and (max-width: $tablet - 1) {
|
||||
#navigation .inner {
|
||||
width: $cols6;
|
||||
|
||||
> ul > li {
|
||||
&.login-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.account-nav {
|
||||
margin-left: 0;
|
||||
|
||||
> a {
|
||||
.avatar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discuss,
|
||||
.explore,
|
||||
.search,
|
||||
.mystuff,
|
||||
.profile-name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//8 columns
|
||||
@media only screen and (min-width: $tablet) and (max-width: $desktop - 1) {
|
||||
#navigation .inner {
|
||||
width: $cols8;
|
||||
|
||||
> ul > li {
|
||||
&.login-item,
|
||||
&.account-nav {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.explore,
|
||||
.search,
|
||||
.mystuff {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,38 +89,55 @@ module.exports = {
|
|||
onChangeShowPassword: function (field, value) {
|
||||
this.setState({showPassword: value});
|
||||
},
|
||||
onValidSubmit: function (formData, reset, invalidate) {
|
||||
this.setState({waiting: true});
|
||||
validateUsername: function (username, callback) {
|
||||
callback = callback || function () {};
|
||||
api({
|
||||
host: '',
|
||||
uri: '/accounts/check_username/' + formData.user.username + '/'
|
||||
}, function (err, res) {
|
||||
uri: '/accounts/check_username/' + username + '/'
|
||||
}, function (err, body, res) {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
this.setState({waiting: false});
|
||||
if (err) return invalidate({all: err});
|
||||
res = res[0];
|
||||
switch (res.msg) {
|
||||
if (err || res.statusCode !== 200) {
|
||||
err = err || formatMessage({id: 'general.error'});
|
||||
this.refs.form.refs.formsy.updateInputsWithError({all: err});
|
||||
return callback(false);
|
||||
}
|
||||
body = body[0];
|
||||
|
||||
switch (body.msg) {
|
||||
case 'valid username':
|
||||
this.setState({
|
||||
validUsername: 'pass'
|
||||
});
|
||||
return this.props.onNextStep(formData);
|
||||
return callback(true);
|
||||
case 'username exists':
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameExists'})
|
||||
});
|
||||
return callback(false);
|
||||
case 'bad username':
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameVulgar'})
|
||||
});
|
||||
return callback(false);
|
||||
case 'invalid username':
|
||||
default:
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameInvalid'})
|
||||
});
|
||||
return callback(false);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
onUsernameBlur: function (event) {
|
||||
this.validateUsername(event.currentTarget.value);
|
||||
},
|
||||
onValidSubmit: function (formData) {
|
||||
this.setState({waiting: true});
|
||||
this.validateUsername(formData.user.username, function (isValid) {
|
||||
this.setState({waiting: false});
|
||||
if (isValid) return this.props.onNextStep(formData);
|
||||
}.bind(this));
|
||||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
|
@ -146,7 +163,7 @@ module.exports = {
|
|||
)}
|
||||
</p>
|
||||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Form onValidSubmit={this.onValidSubmit} ref="form">
|
||||
<div>
|
||||
<div className="username-label">
|
||||
<b>{formatMessage({id: 'registration.createUsername'})}</b>
|
||||
|
@ -159,6 +176,7 @@ module.exports = {
|
|||
<Input className={this.state.validUsername}
|
||||
type="text"
|
||||
name="user.username"
|
||||
onBlur={this.onUsernameBlur}
|
||||
validations={{
|
||||
matchRegexp: /^[\w-]*$/,
|
||||
minLength: 3,
|
||||
|
@ -215,6 +233,7 @@ module.exports = {
|
|||
ChoosePasswordStep: intl.injectIntl(React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
username: null,
|
||||
showPassword: false,
|
||||
waiting: false
|
||||
};
|
||||
|
@ -246,7 +265,7 @@ module.exports = {
|
|||
validations={{
|
||||
minLength: 6,
|
||||
notEquals: 'password',
|
||||
notEqualsField: 'user.username'
|
||||
notEqualsUsername: this.props.username
|
||||
}}
|
||||
validationErrors={{
|
||||
minLength: formatMessage({
|
||||
|
@ -255,7 +274,7 @@ module.exports = {
|
|||
notEquals: formatMessage({
|
||||
id: 'registration.validationPasswordNotEquals'
|
||||
}),
|
||||
notEqualsField: formatMessage({
|
||||
notEqualsUsername: formatMessage({
|
||||
id: 'registration.validationPasswordNotUsername'
|
||||
})
|
||||
}}
|
||||
|
@ -504,14 +523,6 @@ module.exports = {
|
|||
onChooseOrganization: function (name, values) {
|
||||
this.setState({otherDisabled: values.indexOf(this.organizationL10nStems.indexOf('orgChoiceOther')) === -1});
|
||||
},
|
||||
onValidSubmit: function (formData, reset, invalidate) {
|
||||
if (formData.organization.type.length < 1) {
|
||||
return invalidate({
|
||||
'organization.type': this.props.intl.formatMessage({id: 'teacherRegistration.validationRequired'})
|
||||
});
|
||||
}
|
||||
return this.props.onNextStep(formData);
|
||||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
|
@ -525,7 +536,7 @@ module.exports = {
|
|||
tipContent={formatMessage({id: 'registration.nameStepTooltip'})} />
|
||||
</p>
|
||||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Form onValidSubmit={this.props.onNextStep}>
|
||||
<Input label={formatMessage({id: 'teacherRegistration.organization'})}
|
||||
type="text"
|
||||
name="organization.name"
|
||||
|
@ -559,11 +570,19 @@ module.exports = {
|
|||
value={[]}
|
||||
options={this.getOrganizationOptions()}
|
||||
onChange={this.onChooseOrganization}
|
||||
validations={{
|
||||
minLength: 1
|
||||
}}
|
||||
validationErrors={{
|
||||
minLength: formatMessage({
|
||||
id: 'teacherRegistration.validationRequired'
|
||||
})
|
||||
}}
|
||||
required />
|
||||
</div>
|
||||
<div className="other-input">
|
||||
<Input type="text"
|
||||
name="organization.other"
|
||||
<Input name="organization.other"
|
||||
type="text"
|
||||
validations={{
|
||||
maxLength: 50
|
||||
}}
|
||||
|
@ -573,7 +592,8 @@ module.exports = {
|
|||
})
|
||||
}}
|
||||
disabled={this.state.otherDisabled}
|
||||
required="isFalse"
|
||||
required={!this.state.otherDisabled}
|
||||
help={null}
|
||||
placeholder={formatMessage({id: 'general.other'})} />
|
||||
</div>
|
||||
<div className="url-input">
|
||||
|
@ -595,7 +615,7 @@ module.exports = {
|
|||
placeholder={'http://'} />
|
||||
</div>
|
||||
<NextStepButton waiting={this.props.waiting}
|
||||
text={<intl.FormattedMessage id="registration.nextStep" />} />
|
||||
text={<intl.FormattedMessage id="registration.nextStep" />} />
|
||||
</Form>
|
||||
</Card>
|
||||
<StepNavigation steps={this.props.totalSteps - 1} active={this.props.activeStep} />
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
|
||||
.row {
|
||||
margin-left: .5rem;
|
||||
|
||||
.validation-message {
|
||||
transform: translate(14rem, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,14 +106,12 @@
|
|||
}
|
||||
|
||||
&.usescratch-step {
|
||||
.form {
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.has-error {
|
||||
.textarea {
|
||||
border: 1px solid $ui-orange;
|
||||
}
|
||||
&.has-error {
|
||||
.textarea {
|
||||
border: 1px solid $ui-orange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,28 +191,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
.validation-message {
|
||||
position: relative;
|
||||
transform: none;
|
||||
margin: inherit;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ var Tabs = React.createClass({
|
|||
this.props.className
|
||||
);
|
||||
return (
|
||||
<SubNavigation className={classes}>
|
||||
{this.props.children}
|
||||
</SubNavigation>
|
||||
<div className='tab-background'>
|
||||
<SubNavigation className={classes}>
|
||||
{this.props.children}
|
||||
</SubNavigation>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,38 +1,53 @@
|
|||
@import "../../colors";
|
||||
@import "../../frameless";
|
||||
|
||||
.tab-background {
|
||||
box-shadow: 0 0 1px $box-shadow-gray;
|
||||
background-color: $ui-white;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
background-color: $ui-gray;
|
||||
padding: 0 0 0 20px;
|
||||
width: calc(100% - 20px);
|
||||
justify-content: flex-start;
|
||||
background-color: $ui-white;
|
||||
padding: 0;
|
||||
width: $cols12;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tabs li {
|
||||
opacity: .75;
|
||||
margin-bottom: -4px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-color: $ui-white;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
width: $cols2;
|
||||
text-align: center;
|
||||
color: $header-gray;
|
||||
|
||||
|
||||
&.active {
|
||||
border-bottom: 3px solid $ui-aqua;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 3px solid $ui-aqua;
|
||||
color: $header-gray;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
padding: .75em 1.5em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-bottom: 3px solid $active-dark-gray;
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 4px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
border-color: $active-gray;
|
||||
background-color: $ui-white;
|
||||
color: $header-gray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tabs li.active {
|
||||
opacity: 1;
|
||||
border-bottom: 4px solid $ui-white;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
border-bottom: 4px solid $ui-white;
|
||||
background-color: $ui-white;
|
||||
color: $header-gray;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
var React = require('react');
|
||||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
|
||||
require('./thumbnail.scss');
|
||||
|
||||
|
@ -13,11 +13,13 @@ var Thumbnail = React.createClass({
|
|||
href: '#',
|
||||
title: 'Project',
|
||||
src: '',
|
||||
avatar: '',
|
||||
type: 'project',
|
||||
showLoves: false,
|
||||
showFavorites: false,
|
||||
showRemixes: false,
|
||||
showViews: false,
|
||||
showAvatar: false,
|
||||
linkTitle: true,
|
||||
alt: ''
|
||||
};
|
||||
|
@ -29,13 +31,8 @@ var Thumbnail = React.createClass({
|
|||
this.props.className
|
||||
);
|
||||
var extra = [];
|
||||
if (this.props.creator) {
|
||||
extra.push(
|
||||
<div key="creator" className="thumbnail-creator">
|
||||
by <a href={'/users/' + this.props.creator + '/'}>{this.props.creator}</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
var info = [];
|
||||
|
||||
if (this.props.loves && this.props.showLoves) {
|
||||
extra.push(
|
||||
<div
|
||||
|
@ -76,7 +73,7 @@ var Thumbnail = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
var imgElement,titleElement;
|
||||
var imgElement,titleElement,avatarElement;
|
||||
if (this.props.linkTitle) {
|
||||
imgElement = <a className="thumbnail-image" href={this.props.href}>
|
||||
<img src={this.props.src} alt={this.props.alt} />
|
||||
|
@ -87,11 +84,30 @@ var Thumbnail = React.createClass({
|
|||
titleElement = this.props.title;
|
||||
}
|
||||
|
||||
info.push(titleElement);
|
||||
|
||||
if (this.props.creator) {
|
||||
info.push(
|
||||
<div key="creator" className="thumbnail-creator">
|
||||
<a href={'/users/' + this.props.creator + '/'}>{this.props.creator}</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.avatar && this.props.showAvatar) {
|
||||
avatarElement =
|
||||
<a className="creator-image" href={'/users/' + this.props.creator + '/'}>
|
||||
<img src={this.props.avatar} alt={this.props.creator} />
|
||||
</a>;
|
||||
}
|
||||
return (
|
||||
<div className={classes} >
|
||||
{imgElement}
|
||||
<div className="thumbnail-title">
|
||||
{titleElement}
|
||||
<div className="thumbnail-info">
|
||||
{avatarElement}
|
||||
<div className="thumbnail-title">
|
||||
{info}
|
||||
</div>
|
||||
</div>
|
||||
{extra}
|
||||
</div>
|
||||
|
|
|
@ -90,9 +90,11 @@
|
|||
$project-height: 108px;
|
||||
width: $project-width;
|
||||
|
||||
img {
|
||||
width: $project-width;
|
||||
height: $project-height;
|
||||
.thumbnail-image {
|
||||
img {
|
||||
width: $project-width;
|
||||
height: $project-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"general.discuss": "Discuss",
|
||||
"general.dmca": "DMCA",
|
||||
"general.emailAddress": "Email Address",
|
||||
"general.error": "Oops! Something went wrong",
|
||||
"general.explore": "Explore",
|
||||
"general.faq": "FAQ",
|
||||
"general.female": "Female",
|
||||
|
@ -56,6 +57,7 @@
|
|||
"general.privacyPolicy": "Privacy Policy",
|
||||
"general.projects": "Projects",
|
||||
"general.profile": "Profile",
|
||||
"general.resourcesTitle": "Educator Resources",
|
||||
"general.scratchConference": "Scratch Conference",
|
||||
"general.scratchday": "Scratch Day",
|
||||
"general.scratchEd": "ScratchEd",
|
||||
|
@ -153,5 +155,7 @@
|
|||
"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.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!"
|
||||
"registration.welcomeStepTitle": "Hurray! Welcome to Scratch!",
|
||||
|
||||
"thumbnail.by": "by"
|
||||
}
|
||||
|
|
9
src/lib/frameless.js
Normal file
9
src/lib/frameless.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* This file contains breakpoints from _frameless.scss, to be used in MediaQuery elements.
|
||||
* All units are in px, as per _frameless.scss and the MediaQuery default arguments.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
desktop: 942,
|
||||
tablet: 640,
|
||||
mobile: 480
|
||||
};
|
|
@ -164,7 +164,7 @@ dl {
|
|||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
dd {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -47,32 +47,28 @@
|
|||
"pattern": "^/conference/plan/?$",
|
||||
"routeAlias": "/conference(?!/201[4-5])",
|
||||
"view": "conference/plan/plan",
|
||||
"title": "Plan Your Visit",
|
||||
"viewportWidth": "device-width"
|
||||
"title": "Plan Your Visit"
|
||||
},
|
||||
{
|
||||
"name": "conference-expectations",
|
||||
"pattern": "^/conference/expect/?$",
|
||||
"routeAlias": "/conference(?!/201[4-5])",
|
||||
"view": "conference/expect/expect",
|
||||
"title": "What to Expect",
|
||||
"viewportWidth": "device-width"
|
||||
"title": "What to Expect"
|
||||
},
|
||||
{
|
||||
"name": "conference-schedule",
|
||||
"pattern": "^/conference/schedule/?$",
|
||||
"routeAlias": "/conference(?!/201[4-5])",
|
||||
"view": "conference/schedule/schedule",
|
||||
"title": "Conference Schedule",
|
||||
"viewportWidth": "device-width"
|
||||
"title": "Conference Schedule"
|
||||
},
|
||||
{
|
||||
"name": "conference-details",
|
||||
"pattern": "^/conference/:id/details/?$",
|
||||
"routeAlias": "/conference(?!/201[4-5])",
|
||||
"view": "conference/details/details",
|
||||
"title": "Event Details",
|
||||
"viewportWidth": "device-width"
|
||||
"title": "Event Details"
|
||||
},
|
||||
{
|
||||
"name": "developers",
|
||||
|
@ -104,11 +100,10 @@
|
|||
},
|
||||
{
|
||||
"name": "teacherregistration",
|
||||
"pattern": "^/educators/register$",
|
||||
"pattern": "^/educators/register/?$",
|
||||
"routeAlias": "/educators(?:/(faq|register|waiting))?/?$",
|
||||
"view": "teacherregistration/teacherregistration",
|
||||
"title": "Teacher Registration",
|
||||
"viewportWidth": "device-width"
|
||||
"title": "Teacher Registration"
|
||||
},
|
||||
{
|
||||
"name": "teacherwaitingroom",
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = {
|
|||
'and animations.',
|
||||
|
||||
// override if mobile-friendly
|
||||
viewportWidth: 942,
|
||||
viewportWidth: 'device-width',
|
||||
|
||||
// Open graph
|
||||
og_image: 'https://scratch.mit.edu/images/scratch-og.png',
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<meta charset="UTF-8" />
|
||||
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta http-equiv="x-frame-options" content="deny">
|
||||
<meta name="viewport" content="width={{viewportWidth}}, initial-scale=1">
|
||||
|
||||
<title>Scratch - {{title}}</title>
|
||||
|
|
|
@ -7,8 +7,11 @@ var render = require('../../lib/render.jsx');
|
|||
var api = require('../../lib/api');
|
||||
|
||||
var Page = require('../../components/page/www/page.jsx');
|
||||
var Box = require('../../components/box/box.jsx');
|
||||
var Tabs = require('../../components/tabs/tabs.jsx');
|
||||
var TitleBanner = require('../../components/title-banner/title-banner.jsx');
|
||||
var Button = require('../../components/forms/button.jsx');
|
||||
var Form = require('../../components/forms/form.jsx');
|
||||
var Select = require('../../components/forms/select.jsx');
|
||||
var SubNavigation = require('../../components/subnavigation/subnavigation.jsx');
|
||||
var Grid = require('../../components/grid/grid.jsx');
|
||||
|
||||
|
@ -27,16 +30,19 @@ var Explore = injectIntl(React.createClass({
|
|||
stories: 'stories'
|
||||
};
|
||||
var typeOptions = ['projects','studios'];
|
||||
var modeOptions = ['trending', 'popular', 'recent', ''];
|
||||
|
||||
var pathname = window.location.pathname.toLowerCase();
|
||||
if (pathname[pathname.length - 1] === '/') {
|
||||
pathname = pathname.substring(0, pathname.length - 1);
|
||||
}
|
||||
var slash = pathname.lastIndexOf('/');
|
||||
var currentCategory = pathname.substring(slash + 1,pathname.length);
|
||||
var typeStart = pathname.indexOf('explore/');
|
||||
var type = pathname.substring(typeStart + 8,slash);
|
||||
if (Object.keys(categoryOptions).indexOf(currentCategory) === -1 || typeOptions.indexOf(type) === -1) {
|
||||
var options = pathname.split('/');
|
||||
var type = options[2];
|
||||
var currentCategory = options[3];
|
||||
var currentMode = options.length > 4 ? options[4] : '';
|
||||
if (Object.keys(categoryOptions).indexOf(currentCategory) === -1 ||
|
||||
typeOptions.indexOf(type) === -1 ||
|
||||
modeOptions.indexOf(currentMode) === -1){
|
||||
window.location = window.location.origin + '/explore/projects/all/';
|
||||
}
|
||||
|
||||
|
@ -44,7 +50,9 @@ var Explore = injectIntl(React.createClass({
|
|||
category: currentCategory,
|
||||
acceptableTabs: categoryOptions,
|
||||
acceptableTypes: typeOptions,
|
||||
acceptableModes: modeOptions,
|
||||
itemType: type,
|
||||
mode: currentMode,
|
||||
loadNumber: 16
|
||||
};
|
||||
},
|
||||
|
@ -59,12 +67,13 @@ var Explore = injectIntl(React.createClass({
|
|||
},
|
||||
getExploreMore: function () {
|
||||
var qText = '&q=' + this.props.acceptableTabs[this.props.category] || '*';
|
||||
|
||||
|
||||
api({
|
||||
uri: '/search/' + this.props.itemType +
|
||||
'?limit=' + this.props.loadNumber +
|
||||
'&offset=' + this.state.offset +
|
||||
'&language=' + this.props.intl.locale +
|
||||
'&mode=' + (this.props.mode ? this.props.mode : 'trending') +
|
||||
qText
|
||||
}, function (err, body) {
|
||||
if (!err) {
|
||||
|
@ -84,14 +93,20 @@ var Explore = injectIntl(React.createClass({
|
|||
break;
|
||||
}
|
||||
}
|
||||
window.location = window.location.origin + '/explore/' + newType + '/' + this.props.tab;
|
||||
window.location = window.location.origin + '/explore/' + newType + '/' + this.props.tab + '/' + this.props.mode;
|
||||
},
|
||||
changeSortMode: function (name, value) {
|
||||
if (this.props.acceptableModes.indexOf(value) !== -1) {
|
||||
window.location = window.location.origin + '/explore/' +
|
||||
this.props.itemType + '/' + this.props.category + '/' + value;
|
||||
}
|
||||
},
|
||||
getBubble: function (type) {
|
||||
var classes = classNames({
|
||||
active: (this.props.category === type)
|
||||
});
|
||||
return (
|
||||
<a href={'/explore/' + this.props.itemType + '/' + type + '/'}>
|
||||
<a href={'/explore/' + this.props.itemType + '/' + type + '/' + this.props.mode}>
|
||||
<li className={classes}>
|
||||
<FormattedMessage id={'general.' + type} />
|
||||
</li>
|
||||
|
@ -103,18 +118,33 @@ var Explore = injectIntl(React.createClass({
|
|||
active: (this.props.itemType === type)
|
||||
});
|
||||
return (
|
||||
<a href={'/explore/' + type + '/' + this.props.category + '/'}>
|
||||
<a href={'/explore/' + type + '/' + this.props.category + '/' + this.props.mode}>
|
||||
<li className={classes}>
|
||||
{this.props.itemType === type ? [
|
||||
<img src={'/svgs/tabs/' + type + '-active.svg'} className={'tab-icon ' + type} />
|
||||
] : [
|
||||
<img src={'/svgs/tabs/' + type + '-inactive.svg'} className={'tab-icon ' + type} />
|
||||
]}
|
||||
<FormattedMessage id={'general.' + type} />
|
||||
</li>
|
||||
</a>
|
||||
);
|
||||
},
|
||||
render: function () {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='outer'>
|
||||
<Box title={'Explore'}>
|
||||
<TitleBanner className="masthead">
|
||||
<div className="inner">
|
||||
<h1>Explore</h1>
|
||||
</div>
|
||||
</TitleBanner>
|
||||
<Tabs>
|
||||
{this.getTab('projects')}
|
||||
{this.getTab('studios')}
|
||||
</Tabs>
|
||||
<div className="sort-controls">
|
||||
<SubNavigation className='categories'>
|
||||
{this.getBubble('all')}
|
||||
{this.getBubble('animations')}
|
||||
|
@ -123,25 +153,29 @@ var Explore = injectIntl(React.createClass({
|
|||
{this.getBubble('music')}
|
||||
{this.getBubble('stories')}
|
||||
</SubNavigation>
|
||||
<Tabs>
|
||||
{this.getTab('projects')}
|
||||
{this.getTab('studios')}
|
||||
</Tabs>
|
||||
<div id='projectBox' key='projectBox'>
|
||||
<Grid items={this.state.loaded}
|
||||
itemType={this.props.itemType}
|
||||
showLoves={false}
|
||||
showFavorites={false}
|
||||
showViews={false} />
|
||||
<SubNavigation className='load'>
|
||||
<button onClick={this.getExploreMore}>
|
||||
<li>
|
||||
<FormattedMessage id='general.loadMore' />
|
||||
</li>
|
||||
</button>
|
||||
</SubNavigation>
|
||||
</div>
|
||||
</Box>
|
||||
<Form className='sort-mode'>
|
||||
<Select name="sort"
|
||||
options={[
|
||||
{value: 'trending', label: 'Trending'},
|
||||
{value: 'popular', label: 'Popular'},
|
||||
{value: 'recent', label: 'Recent'}
|
||||
]}
|
||||
value={this.props.mode}
|
||||
onChange={this.changeSortMode}/>
|
||||
</Form>
|
||||
</div>
|
||||
<div id='projectBox' key='projectBox'>
|
||||
<Grid items={this.state.loaded}
|
||||
itemType={this.props.itemType}
|
||||
cards={true}
|
||||
showLoves={false}
|
||||
showFavorites={false}
|
||||
showViews={false}
|
||||
showAvatar={true}/>
|
||||
<Button onClick={this.getExploreMore} className="white">
|
||||
<FormattedMessage id='general.loadMore' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -4,62 +4,163 @@
|
|||
$base-bg: $ui-white;
|
||||
|
||||
#view {
|
||||
.box {
|
||||
display: block;
|
||||
margin-right: auto;
|
||||
margin-bottom: 20px;
|
||||
margin-left: auto;
|
||||
background-color: $ui-gray;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
.outer {
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
margin-bottom: 0;
|
||||
background-color: $ui-yellow;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.categories {
|
||||
display: inline-block;
|
||||
background-color: $ui-gray;
|
||||
padding-left: 10px;
|
||||
width: calc(100% - 10px);
|
||||
justify-content: left;
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: $ui-white;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
li {
|
||||
opacity: .75;
|
||||
background-color: $ui-white;
|
||||
color: $header-gray;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
border-color: $active-dark-gray;
|
||||
p {
|
||||
margin: 0;
|
||||
width: $cols6;
|
||||
text-align: left;
|
||||
color: $ui-white;
|
||||
|
||||
a {
|
||||
border-bottom: 1px solid $ui-white;
|
||||
color: $ui-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li.active {
|
||||
opacity: 1;
|
||||
border-color: $active-dark-gray;
|
||||
.left-pusher {
|
||||
margin-right: auto;
|
||||
width: 8.75rem;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
width: 58.75rem;
|
||||
}
|
||||
|
||||
/* HACK: sort controls are terrible. There's some sort of magic formula for height of formsy components that I can't control. */
|
||||
|
||||
.sort-controls {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
border-bottom: 1px solid $ui-border;
|
||||
padding: 8px 0;
|
||||
width: 58.75rem;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.sort-mode {
|
||||
margin-top: -4px;
|
||||
width: 13.75rem;
|
||||
|
||||
.select {
|
||||
|
||||
select {
|
||||
margin-bottom: 0;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
height: 32px;
|
||||
color: $header-gray;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.help-block {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.categories {
|
||||
justify-content: flex-start;
|
||||
|
||||
li {
|
||||
border: 0;
|
||||
background-color: $active-gray;
|
||||
color: $ui-white;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
background-color: $ui-aqua;
|
||||
color: $ui-white;
|
||||
|
||||
}
|
||||
|
||||
&:active {
|
||||
padding: .75em 1.5em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
border-color: $active-dark-gray;
|
||||
background-color: $active-dark-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#projectBox {
|
||||
border-top: 2px solid;
|
||||
border-color: $active-gray;
|
||||
background-color: $ui-white;
|
||||
padding-bottom: 30px;
|
||||
background-color: $ui-gray;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 32px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.load button {
|
||||
outline: None;
|
||||
border: None;
|
||||
background-color: $ui-white;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
color: $header-gray;
|
||||
.button {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//4 columns
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
.outer {
|
||||
.tabs {
|
||||
width: $cols4;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//6 columns
|
||||
@media only screen and (min-width: $mobile) and (max-width: $tablet - 1) {
|
||||
.outer {
|
||||
.tabs {
|
||||
width: $cols6;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8 columns
|
||||
@media only screen and (min-width: $tablet) and (max-width: $desktop - 1) {
|
||||
.outer {
|
||||
.tabs {
|
||||
width: $cols8;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols8;
|
||||
}
|
||||
|
||||
#projectBox {
|
||||
.grid {
|
||||
.flex-row {
|
||||
width: $cols9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
"faq.makeGameTitle":"How do I make a game or animation with Scratch?",
|
||||
"faq.makeGameBody":"Check out the <a href= \"/help \">help page</a> to see lots of ways to get started with Scratch. Or just <a href= \"/projects/editor/?tip_bar=getStarted \">dive in</a> to the project editor.",
|
||||
"faq.requirementsTitle":"What are the system requirements for Scratch?",
|
||||
"faq.requirementsBody":"To run Scratch 2, you need a relatively recent web browser (<a href= \"http://google.com/chrome/ \">Chrome</a> 35 or later, <a href= \"http://www.mozilla.org/en-US/firefox/new/ \">Firefox</a> 31 or later, or Internet Explorer 9 or later) with <a href= \" \">Adobe Flash Player</a> version 10.2 or later installed. Scratch 2 is designed to support screen sizes 1024 x 768 or larger. If your computer doesn’t meet these requirements, you can try downloading and installing <a href = \"/scratch_1.4 \">Scratch 1.4</a>, which you can still use to share projects to the Scratch 2 website.",
|
||||
"faq.requirementsBody":"To run Scratch 2, you need to be using (1) a Mac, Linux, or Windows computer; (2) a version of <a href= \" \">Adobe Flash Player</a> released on or after June 15, 2016; (3) a relatively recent web browser: one of the latest two versions of <a href=\"http://google.com/chrome/\">Chrome</a>, <a href=\"http://www.mozilla.org/en-US/firefox/new/\">Firefox</a>, <a href=\"https://support.apple.com/downloads/safari\">Safari</a> (Mac or Windows only), <a href=\"https://www.microsoft.com/EN-US/windows/microsoft-edge\">Edge</a> (Windows only), or <a href=\"https://www.microsoft.com/en-us/download/internet-explorer.aspx\">Internet Explorer 10+</a> (Windows only). If your computer doesn’t meet these requirements, you can try downloading and installing <a href=\"/scratch_1.4\">Scratch 1.4</a>, which you can still use to share projects to the Scratch 2 website.",
|
||||
"faq.offlineTitle":"Do you have a downloadable version so I can create and view projects offline?",
|
||||
"faq.offlineBody":"The <a href= \"/scratch2download/ \">Scratch 2 offline editor (beta version)</a> is now available. You can also still use <a href = \"/scratch_1.4 \">Scratch 1.4</a>. Note: You can have both Scratch 1.4 and 2 on your computer.",
|
||||
"faq.offlineBody":"The Scratch 2 offline editor allows you to create Scratch projects without an internet connection. You can download Scratch 2 from the <a href= \"/scratch2download/ \">website</a>. You can also still use <a href = \"/scratch_1.4 \">Scratch 1.4</a>. Note: You can have both Scratch 1.4 and 2 on your computer.",
|
||||
"faq.uploadOldTitle":"Can I still upload projects created with older versions of Scratch to the website?",
|
||||
"faq.uploadOldBody":"Yes - you can share or upload projects made with earlier versions of Scratch, and they will be visible and playable. (However, you can’t download projects made with or edited in later versions of Scratch and open them in earlier versions. For example, you can’t open a Scratch 2 project in <a href =\"/scratch_1.4\">Scratch 1.4</a>, because <a href =\"/scratch_1.4\">Scratch 1.4</a> doesn’t know how to read the .sb2 project file format.)",
|
||||
"faq.recordVideoTitle":"Can I record a video of my Scratch project?",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
.top {
|
||||
img {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ var render = require('../../lib/render.jsx');
|
|||
var api = require('../../lib/api');
|
||||
|
||||
var Page = require('../../components/page/www/page.jsx');
|
||||
var Box = require('../../components/box/box.jsx');
|
||||
var SubNavigation = require('../../components/subnavigation/subnavigation.jsx');
|
||||
var TitleBanner = require('../../components/title-banner/title-banner.jsx');
|
||||
var Form = require('../../components/forms/form.jsx');
|
||||
var Input = require('../../components/forms/input.jsx');
|
||||
var Button = require('../../components/forms/button.jsx');
|
||||
var Tabs = require('../../components/tabs/tabs.jsx');
|
||||
var Grid = require('../../components/grid/grid.jsx');
|
||||
|
||||
|
@ -62,6 +64,7 @@ var Search = injectIntl(React.createClass({
|
|||
'?limit=' + this.props.loadNumber +
|
||||
'&offset=' + this.state.offset +
|
||||
'&language=' + this.props.intl.locale +
|
||||
'&mode=popular' +
|
||||
termText
|
||||
}, function (err, body) {
|
||||
var loadedSoFar = this.state.loaded;
|
||||
|
@ -71,16 +74,21 @@ var Search = injectIntl(React.createClass({
|
|||
this.setState({offset: currentOffset});
|
||||
}.bind(this));
|
||||
},
|
||||
onSearchSubmit: function (formData) {
|
||||
window.location.href = '/search/projects?q=' + formData.q;
|
||||
},
|
||||
getTab: function (type) {
|
||||
var term = this.props.searchTerm.split(' ').join('+');
|
||||
var allTab = <a href={'/search/' + type + '?q=' + term + '/'}>
|
||||
<li>
|
||||
<img src={'/svgs/tabs/' + type + '-inactive.svg'} className={'tab-icon ' + type} />
|
||||
<FormattedMessage id={'general.' + type} />
|
||||
</li>
|
||||
</a>;
|
||||
if (this.props.tab == type) {
|
||||
allTab = <a href={'/search/' + type + '?q=' + term + '/'}>
|
||||
<li className='active'>
|
||||
<img src={'/svgs/tabs/' + type + '-active.svg'} className={'tab-icon ' + type} />
|
||||
<FormattedMessage id={'general.' + type} />
|
||||
</li>
|
||||
</a>;
|
||||
|
@ -89,32 +97,41 @@ var Search = injectIntl(React.createClass({
|
|||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='outer'>
|
||||
<Box title={formatMessage({id: 'general.results'}) + ':'}
|
||||
subtitle={this.props.searchTerm}
|
||||
moreProps={{className: 'subnavigation'}}>
|
||||
<TitleBanner className="masthead">
|
||||
<div className="inner">
|
||||
<h1>Search</h1>
|
||||
<div className="search">
|
||||
<Form onSubmit={this.onSearchSubmit}>
|
||||
<Button type="submit" className="btn-search" />
|
||||
<Input type="text"
|
||||
aria-label={formatMessage({id: 'general.search'})}
|
||||
placeholder={formatMessage({id: 'general.search'})}
|
||||
defaultValue={decodeURI(this.props.searchTerm)}
|
||||
name="q" />
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</TitleBanner>
|
||||
<Tabs>
|
||||
{this.getTab('projects')}
|
||||
{this.getTab('studios')}
|
||||
</Tabs>
|
||||
<div id='projectBox' key='projectBox'>
|
||||
<Grid items={this.state.loaded}
|
||||
itemType={this.props.tab}
|
||||
showLoves={false}
|
||||
showFavorites={false}
|
||||
showViews={false} />
|
||||
<SubNavigation className='load'>
|
||||
<button onClick={this.getSearchMore}>
|
||||
<li>
|
||||
<FormattedMessage id='general.loadMore' />
|
||||
</li>
|
||||
</button>
|
||||
</SubNavigation>
|
||||
<Grid items={this.state.loaded}
|
||||
itemType={this.props.tab}
|
||||
cards={true}
|
||||
showAvatar={true}
|
||||
showLoves={false}
|
||||
showFavorites={false}
|
||||
showViews={false} />
|
||||
<Button onClick={this.getSearchMore} className="white">
|
||||
<FormattedMessage id='general.loadMore' />
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,33 +4,181 @@
|
|||
$base-bg: $ui-white;
|
||||
|
||||
#view {
|
||||
.box {
|
||||
display: block;
|
||||
margin-right: auto;
|
||||
margin-bottom: 20px;
|
||||
margin-left: auto;
|
||||
background-color: $ui-gray;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
.outer {
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
margin-bottom: 0;
|
||||
background-color: darken($ui-blue, 10%);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#projectBox {
|
||||
border-top: 2px solid;
|
||||
border-color: $active-gray;
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: $ui-white;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
width: $cols6;
|
||||
text-align: left;
|
||||
color: $ui-white;
|
||||
|
||||
a {
|
||||
border-bottom: 1px solid $ui-white;
|
||||
color: $ui-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 0 auto;
|
||||
border-right: 0;
|
||||
width: $cols6;
|
||||
color: $type-white;
|
||||
|
||||
.form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.row {
|
||||
.help-block {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.input,
|
||||
.button {
|
||||
display: inline-block;
|
||||
margin-top: 5px;
|
||||
outline: none;
|
||||
border: 0;
|
||||
background-color: $active-gray;
|
||||
height: 14px;
|
||||
|
||||
&[type=text] {
|
||||
transition: .15s ease background-color;
|
||||
padding: 0;
|
||||
padding-right: 10px;
|
||||
padding-left: 40px;
|
||||
width: calc(100% - 50px);
|
||||
height: 40px;
|
||||
color: $type-white;
|
||||
font-size: .85em;
|
||||
|
||||
&::placeholder {
|
||||
$placeholder-transparent: rgba(255, 255, 255, .75);
|
||||
color: $placeholder-transparent;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
transition: .15s ease background-color;
|
||||
background-color: $active-dark-gray;
|
||||
}
|
||||
|
||||
.ie9 & {
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-search {
|
||||
position: absolute;
|
||||
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
background-image: url("/images/nav-search-glass.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 14px 14px;
|
||||
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select {
|
||||
select {
|
||||
margin-bottom: 0;
|
||||
color: $header-gray;
|
||||
}
|
||||
|
||||
.help-block {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-background {
|
||||
box-shadow: 0 0 1px $box-shadow-gray;
|
||||
background-color: $ui-white;
|
||||
padding-bottom: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.load button {
|
||||
outline: None;
|
||||
border: None;
|
||||
background-color: $ui-white;
|
||||
padding: 0;
|
||||
#projectBox {
|
||||
margin-top: 16px;
|
||||
background-color: $ui-gray;
|
||||
padding-bottom: 32px;
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
color: $header-gray;
|
||||
.button {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//4 columns
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
.outer {
|
||||
.search {
|
||||
width: $cols4;
|
||||
|
||||
.btn-search {
|
||||
left: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
width: $cols4;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//6 columns
|
||||
@media only screen and (min-width: $mobile) and (max-width: $tablet - 1) {
|
||||
.outer {
|
||||
.tabs {
|
||||
width: $cols6;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8 columns
|
||||
@media only screen and (min-width: $tablet) and (max-width: $desktop - 1) {
|
||||
.outer {
|
||||
.tabs {
|
||||
width: $cols8;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
width: $cols8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
"teacherbanner.greeting": "Hi",
|
||||
"teacherbanner.subgreeting": "Teacher Account",
|
||||
"teacherbanner.classesButton": "My Classes",
|
||||
"teacherbanner.resourcesButton": "Educator Resources",
|
||||
"teacherbanner.faqButton": "Teacher Account FAQ",
|
||||
|
||||
"welcome.welcomeToScratch": "Welcome to Scratch!",
|
||||
|
|
|
@ -21,6 +21,9 @@ var Page = require('../../components/page/www/page.jsx');
|
|||
var TeacherBanner = require('../../components/teacher-banner/teacher-banner.jsx');
|
||||
var Welcome = require('../../components/welcome/welcome.jsx');
|
||||
|
||||
var MediaQuery = require('react-responsive');
|
||||
var frameless = require('../../lib/frameless');
|
||||
|
||||
require('./splash.scss');
|
||||
|
||||
var Splash = injectIntl(React.createClass({
|
||||
|
@ -186,16 +189,12 @@ var Splash = injectIntl(React.createClass({
|
|||
|
||||
var rows = [
|
||||
<Box
|
||||
title={formatMessage({
|
||||
id: 'splash.featuredProjects',
|
||||
defaultMessage: 'Featured Projects'})}
|
||||
title={formatMessage({id: 'splash.featuredProjects'})}
|
||||
key="community_featured_projects">
|
||||
<Carousel items={this.state.featuredGlobal.community_featured_projects} />
|
||||
</Box>,
|
||||
<Box
|
||||
title={formatMessage({
|
||||
id: 'splash.featuredStudios',
|
||||
defaultMessage: 'Featured Studios'})}
|
||||
title={formatMessage({id: 'splash.featuredStudios'})}
|
||||
key="community_featured_studios">
|
||||
<Carousel items={this.state.featuredGlobal.community_featured_studios}
|
||||
settings={{slidesToShow: 4, slidesToScroll: 4, lazyLoad: false}} />
|
||||
|
@ -213,8 +212,8 @@ var Splash = injectIntl(React.createClass({
|
|||
this.state.featuredGlobal.curator_top_projects[0].curator_name}
|
||||
moreTitle={formatMessage({id: 'general.learnMore', defaultMessage: 'Learn More'})}
|
||||
moreHref="/studios/386359/">
|
||||
<Carousel
|
||||
items={this.state.featuredGlobal.curator_top_projects} />
|
||||
|
||||
<Carousel items={this.state.featuredGlobal.curator_top_projects} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -226,14 +225,12 @@ var Splash = injectIntl(React.createClass({
|
|||
<Box
|
||||
key="scratch_design_studio"
|
||||
title={
|
||||
formatMessage({
|
||||
id: 'splash.scratchDesignStudioTitle',
|
||||
defaultMessage: 'Scratch Design Studio' })
|
||||
formatMessage({id: 'splash.scratchDesignStudioTitle'})
|
||||
+ ' - ' + this.state.featuredGlobal.scratch_design_studio[0].gallery_title}
|
||||
moreTitle={formatMessage({id: 'splash.visitTheStudio', defaultMessage: 'Visit the studio'})}
|
||||
moreHref={'/studios/' + this.state.featuredGlobal.scratch_design_studio[0].gallery_id + '/'}>
|
||||
<Carousel
|
||||
items={this.state.featuredGlobal.scratch_design_studio} />
|
||||
|
||||
<Carousel items={this.state.featuredGlobal.scratch_design_studio} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -243,14 +240,9 @@ var Splash = injectIntl(React.createClass({
|
|||
this.state.featuredGlobal.community_newest_projects.length > 0) {
|
||||
|
||||
rows.push(
|
||||
<Box
|
||||
title={
|
||||
formatMessage({
|
||||
id: 'splash.recentlySharedProjects',
|
||||
defaultMessage: 'Recently Shared Projects' })}
|
||||
key="community_newest_projects">
|
||||
<Carousel
|
||||
items={this.state.featuredGlobal.community_newest_projects} />
|
||||
<Box title={formatMessage({id: 'splash.recentlySharedProjects'})}
|
||||
key="community_newest_projects">
|
||||
<Carousel items={this.state.featuredGlobal.community_newest_projects} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -259,12 +251,9 @@ var Splash = injectIntl(React.createClass({
|
|||
this.state.featuredCustom.custom_projects_by_following.length > 0) {
|
||||
|
||||
rows.push(
|
||||
<Box title={
|
||||
formatMessage({
|
||||
id: 'splash.projectsByScratchersFollowing',
|
||||
defaultMessage: 'Projects by Scratchers I\'m Following'})}
|
||||
<Box title={formatMessage({id: 'splash.projectsByScratchersFollowing'})}
|
||||
key="custom_projects_by_following">
|
||||
|
||||
|
||||
<Carousel items={this.state.featuredCustom.custom_projects_by_following} />
|
||||
</Box>
|
||||
);
|
||||
|
@ -273,12 +262,9 @@ var Splash = injectIntl(React.createClass({
|
|||
this.state.featuredCustom.custom_projects_loved_by_following.length > 0) {
|
||||
|
||||
rows.push(
|
||||
<Box title={
|
||||
formatMessage({
|
||||
id: 'splash.projectsLovedByScratchersFollowing',
|
||||
defaultMessage: 'Projects Loved by Scratchers I\'m Following'})}
|
||||
<Box title={formatMessage({id: 'splash.projectsLovedByScratchersFollowing'})}
|
||||
key="custom_projects_loved_by_following">
|
||||
|
||||
|
||||
<Carousel items={this.state.featuredCustom.custom_projects_loved_by_following} />
|
||||
</Box>
|
||||
);
|
||||
|
@ -288,31 +274,22 @@ var Splash = injectIntl(React.createClass({
|
|||
this.state.featuredCustom.custom_projects_in_studios_following.length > 0) {
|
||||
|
||||
rows.push(
|
||||
<Box title={
|
||||
formatMessage({
|
||||
id:'splash.projectsInStudiosFollowing',
|
||||
defaultMessage: 'Projects in Studios I\'m Following'})}
|
||||
<Box title={formatMessage({id:'splash.projectsInStudiosFollowing'})}
|
||||
key="custom_projects_in_studios_following">
|
||||
|
||||
|
||||
<Carousel items={this.state.featuredCustom.custom_projects_in_studios_following} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
rows.push(
|
||||
<Box title={
|
||||
formatMessage({
|
||||
id: 'splash.communityRemixing',
|
||||
defaultMessage: 'What the Community is Remixing' })}
|
||||
<Box title={formatMessage({id: 'splash.communityRemixing'})}
|
||||
key="community_most_remixed_projects">
|
||||
|
||||
<Carousel items={shuffle(this.state.featuredGlobal.community_most_remixed_projects)}
|
||||
showRemixes={true} />
|
||||
</Box>,
|
||||
<Box title={
|
||||
formatMessage({
|
||||
id: 'splash.communityLoving',
|
||||
defaultMessage: 'What the Community is Loving' })}
|
||||
<Box title={formatMessage({id: 'splash.communityLoving'})}
|
||||
key="community_most_loved_projects">
|
||||
|
||||
<Carousel items={shuffle(this.state.featuredGlobal.community_most_loved_projects)}
|
||||
|
@ -347,7 +324,7 @@ var Splash = injectIntl(React.createClass({
|
|||
'teacherbanner.greeting': formatMessage({id: 'teacherbanner.greeting'}),
|
||||
'teacherbanner.subgreeting': formatMessage({id: 'teacherbanner.subgreeting'}),
|
||||
'teacherbanner.classesButton': formatMessage({id: 'teacherbanner.classesButton'}),
|
||||
'teacherbanner.resourcesButton': formatMessage({id: 'teacherbanner.resourcesButton'}),
|
||||
'teacherbanner.resourcesButton': formatMessage({id: 'general.resourcesTitle'}),
|
||||
'teacherbanner.faqButton': formatMessage({id: 'teacherbanner.faqButton'})
|
||||
};
|
||||
if (this.state.projectCount === this.getInitialState().projectCount) {
|
||||
|
@ -393,7 +370,9 @@ var Splash = injectIntl(React.createClass({
|
|||
<News items={this.state.news} messages={messages} />
|
||||
</div>
|
||||
] : [
|
||||
<Intro projectCount={this.state.projectCount} messages={messages} key="intro"/>
|
||||
<MediaQuery minWidth={frameless.desktop}>
|
||||
<Intro projectCount={this.state.projectCount} messages={messages} key="intro"/>
|
||||
</MediaQuery>
|
||||
]) : []
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import "../../frameless";
|
||||
|
||||
.splash {
|
||||
.splash-header {
|
||||
display: flex;
|
||||
|
@ -24,7 +26,7 @@
|
|||
|
||||
.news {
|
||||
width: 40%;
|
||||
|
||||
|
||||
img {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
@ -38,4 +40,42 @@
|
|||
.box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//4 columns
|
||||
@media only screen and (max-width: $mobile - 1) {
|
||||
.splash {
|
||||
.splash-header {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
.box {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//6 columns
|
||||
@media only screen and (min-width: $mobile) and (max-width: $tablet - 1) {
|
||||
.splash {
|
||||
.splash-header {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
.box {
|
||||
width: $cols6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//6 columns
|
||||
@media only screen and (min-width: $tablet) and (max-width: $desktop - 1) {
|
||||
.splash {
|
||||
.splash-header {
|
||||
margin: 0 auto;
|
||||
width: $cols8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,8 @@ var StudentCompleteRegistration = intl.injectIntl(React.createClass({
|
|||
{this.props.must_reset_password ?
|
||||
<Steps.ChoosePasswordStep onNextStep={this.advanceStep}
|
||||
showPassword={true}
|
||||
waiting={this.state.waiting} />
|
||||
waiting={this.state.waiting}
|
||||
username={this.props.studentUsername} />
|
||||
:
|
||||
[]
|
||||
}
|
||||
|
|
|
@ -20,18 +20,22 @@ var TeacherFaq = injectIntl(React.createClass({
|
|||
<dl>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherWhatTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherWhatBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherQuestionsTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherQuestionsBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherGoogleTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherGoogleBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherEdTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherEdBody' /></dd>
|
||||
<iframe width="565" height="318" src="https://www.youtube.com/embed/7Hl9GxA1zwQ"
|
||||
frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherSignUpTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherSignUpBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherWaitTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherWaitBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherPersonalTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherPersonalBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherGoogleTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherGoogleBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherEdTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherEdBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherMultipleTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherMultipleBody' /></dd>
|
||||
<dt><FormattedMessage id='teacherfaq.teacherQuestionsTitle' /></dt>
|
||||
<dd><FormattedHTMLMessage id='teacherfaq.teacherQuestionsBody' /></dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section id="student-accounts">
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
{
|
||||
"teacherfaq.title": "Scratch Teacher Account FAQ",
|
||||
"teacherfaq.teacherWhatTitle": "What are teacher accounts?",
|
||||
"teacherfaq.teacherWhatBody": "A Scratch Teacher Account provides teachers and other educators with additional features to manage student participation on Scratch, including the ability to create student accounts, organize student projects into studios, and monitor student comments. Learn more about Teacher Accounts in <a href=\"https://www.youtube.com/watch?v=7Hl9GxA1zwQ\">this video</a>.",
|
||||
"teacherfaq.teacherQuestionsTitle": "What if I have any questions or comments on Teacher Accounts?",
|
||||
"teacherfaq.teacherQuestionsBody": "If you have any questions or feedback on Teacher Accounts, you can message us at <a href=\"mailto:teacher-accounts@scratch.mit.edu\">teacher-accounts@scratch.mit.edu</a>.",
|
||||
"teacherfaq.teacherGoogleTitle": "Are teacher accounts integrated with Google Classroom or any other classroom managment service?",
|
||||
"teacherfaq.teacherGoogleBody": "Scratch Teacher accounts are not integrated with any classroom management services.",
|
||||
"teacherfaq.teacherEdTitle": "Are ScratchEd & Scratch Teacher accounts the same thing?",
|
||||
"teacherfaq.teacherEdBody": "<a href=\"http://scratched.gse.harvard.edu/\">ScratchEd</a> accounts are not linked to Scratch Teacher accounts.",
|
||||
"teacherfaq.teacherWhatBody": "A Scratch Teacher Account provides teachers and other educators with additional features to manage student participation on Scratch, including the ability to create student accounts, organize student projects into studios, and monitor student comments. Learn more about Teacher Accounts in the video below:",
|
||||
"teacherfaq.teacherSignUpTitle": "How do I request a teacher account?",
|
||||
"teacherfaq.teacherSignUpBody": "To request a Teacher Account, go to the teacher account <a href=\"/educators/register\">request form</a>.",
|
||||
"teacherfaq.teacherWaitTitle": "Why do I have to wait 24 hours for my account?",
|
||||
"teacherfaq.teacherWaitBody": "The Scratch Team uses this time to manually review account creation submissions to verify the account creator is an educator.",
|
||||
"teacherfaq.teacherPersonalTitle": "Why do you need to know my personal information during registration?",
|
||||
"teacherfaq.teacherPersonalBody": "We use this information to verify the account creator is an educator. We will not share this information with anyone else, and it will not be shared publicly on the site.",
|
||||
"teacherfaq.teacherGoogleTitle": "Are teacher accounts integrated with Google Classroom or any other classroom managment service?",
|
||||
"teacherfaq.teacherGoogleBody": "Scratch Teacher accounts are not integrated with any classroom management services.",
|
||||
"teacherfaq.teacherEdTitle": "Are Scratch Teacher accounts linked to ScratchEd accounts?",
|
||||
"teacherfaq.teacherEdBody": "No, Scratch Teacher accounts are not linked to <a href=\"http://scratched.gse.harvard.edu/\">ScratchEd</a> accounts.",
|
||||
"teacherfaq.teacherMultipleTitle": "Can a class have multiple teachers?",
|
||||
"teacherfaq.teacherMultipleBody": "A class can only have one teacher account associated with it.",
|
||||
"teacherfaq.teacherQuestionsTitle": "What if I have any questions or comments on Teacher Accounts?",
|
||||
"teacherfaq.teacherQuestionsBody": "If you have any questions or feedback on Teacher Accounts, you can message us at <a href=\"mailto:teacher-accounts@scratch.mit.edu\">teacher-accounts@scratch.mit.edu</a>.",
|
||||
|
||||
"teacherfaq.studentAccountsTitle": "Student Accounts",
|
||||
"teacherfaq.studentVerifyTitle": "Do I have to verify each of my students' emails?",
|
||||
|
@ -21,7 +23,7 @@
|
|||
"teacherfaq.studentEndTitle": "What happens when I \"end\" my class?",
|
||||
"teacherfaq.studentEndBody": "When you end a class, your class profile page will be hidden and your students will no longer be able to log in (but their projects and the class studios will still be visible on the site). You may re-open the class at any time. ",
|
||||
"teacherfaq.studentForgetTitle": "What happens if a student forgets their password?",
|
||||
"teacherfaq.studentForgetBody": "You can manually reset a student password from within your Scratch Teacher Account. First, navigate to <a href=\"/educators/classes\">My Classes</a>. From there, find the correct Class and click on the Students link. You can then reset the password at the student level using the Settings menu. ",
|
||||
"teacherfaq.studentForgetBody": "You can manually reset a student password from within your Scratch Teacher Account. First, navigate to My Classes (either from the purple banner on the homepage or in the dropdown menu next to your user icon). From there, find the correct Class and click on the Students link. You can then reset the password at the student level using the Settings menu. ",
|
||||
"teacherfaq.studentUnsharedTitle": "Can I see unshared student projects?",
|
||||
"teacherfaq.studentUnsharedBody": "Teacher accounts can only access shared student projects.",
|
||||
"teacherfaq.studentDeleteTitle": "Can I delete student accounts?",
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
"teacherlanding.generalUsageSettings": "<b>Settings:</b> schools, museums, libraries, community centers",
|
||||
"teacherlanding.generalUsageGradeLevels": "<b>Grade Levels:</b> elementary, middle, and high school (and some colleges too!)",
|
||||
"teacherlanding.generalUsageSubjectAreas": "<b>Subject Areas:</b> language arts, science, social studies, math, computer science, foreign languages, and the arts",
|
||||
"teacherlanding.resourcesTitle": "Educator Resources",
|
||||
"teacherlanding.scratchEdTitle": "A Community for Educators",
|
||||
"teacherlanding.scratchEdDescription": "<a href=\"http://scratched.gse.harvard.edu/\">ScratchEd</a> is an online community where Scratch educators <a href=\"http://scratched.gse.harvard.edu/stories\">share stories</a>, exchange resources, ask questions, and find people. ScratchEd is developed and supported by the Harvard Graduate School of Education.",
|
||||
"teacherlanding.meetupTitle": "In-Person Gatherings",
|
||||
|
|
|
@ -64,7 +64,7 @@ var Landing = injectIntl(React.createClass({
|
|||
</section>
|
||||
<section id="resources">
|
||||
<span className="nav-spacer"></span>
|
||||
<h2><FormattedMessage id="teacherlanding.resourcesTitle" /></h2>
|
||||
<h2><FormattedMessage id="general.resourcesTitle" /></h2>
|
||||
<FlexRow className="educator-community">
|
||||
<div>
|
||||
<h3><FormattedMessage id="teacherlanding.scratchEdTitle" /></h3>
|
||||
|
@ -82,19 +82,25 @@ var Landing = injectIntl(React.createClass({
|
|||
<h3 id="guides-header"><FormattedMessage id="teacherlanding.guidesTitle" /></h3>
|
||||
<FlexRow className="guides-and-tutorials">
|
||||
<div>
|
||||
<img src="/svgs/teachers/resources.svg" alt="resources icon" />
|
||||
<a href="/help">
|
||||
<img src="/svgs/teachers/resources.svg" alt="resources icon" />
|
||||
</a>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="teacherlanding.helpPage" />
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<img src="/svgs/teachers/tips-window.svg" alt="tips window icon" />
|
||||
<a href="/projects/editor/?tip_bar=home">
|
||||
<img src="/svgs/teachers/tips-window.svg" alt="tips window icon" />
|
||||
</a>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="teacherlanding.tipsWindow" />
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<img src="/svgs/teachers/creative-computing.svg" alt="creative computing icon" />
|
||||
<a href="http://scratched.gse.harvard.edu/guide/">
|
||||
<img src="/svgs/teachers/creative-computing.svg" alt="creative computing icon" />
|
||||
</a>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="teacherlanding.creativeComputing" />
|
||||
</p>
|
||||
|
|
|
@ -85,7 +85,7 @@ var Terms = React.createClass({
|
|||
(for example, in the event of a loss, theft, or unauthorized disclosure
|
||||
of your password), promptly change your password. If you cannot access
|
||||
your account to change your password, notify us at{' '}
|
||||
<a href="mailto:help@scratch.mit.edu"></a>.
|
||||
<a href="mailto:help@scratch.mit.edu">help@scratch.mit.edu</a>.
|
||||
</p>
|
||||
</section>
|
||||
<section id="rules-of-usage">
|
||||
|
|
1
static/svgs/tabs/projects-active.svg
Normal file
1
static/svgs/tabs/projects-active.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><path d="M13.39,3.29V9.4a0.41,0.41,0,0,1-.14.31,4.18,4.18,0,0,1-5.51,0,3.42,3.42,0,0,0-2.23-.84,3.35,3.35,0,0,0-2.07.72v4.05a0.42,0.42,0,1,1-.84,0V3.29A0.41,0.41,0,0,1,2.87,2.9,4.17,4.17,0,0,1,8.27,3a3.39,3.39,0,0,0,4.45,0,0.39,0.39,0,0,1,.43-0.06A0.4,0.4,0,0,1,13.39,3.29Z" fill="#26d9bb" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
After Width: | Height: | Size: 474 B |
1
static/svgs/tabs/projects-inactive.svg
Normal file
1
static/svgs/tabs/projects-inactive.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><path d="M13.39,3.29V9.4a0.41,0.41,0,0,1-.14.31,4.18,4.18,0,0,1-5.51,0,3.42,3.42,0,0,0-2.23-.84,3.35,3.35,0,0,0-2.07.72v4.05a0.42,0.42,0,1,1-.84,0V3.29A0.41,0.41,0,0,1,2.87,2.9,4.17,4.17,0,0,1,8.27,3a3.39,3.39,0,0,0,4.45,0,0.39,0.39,0,0,1,.43-0.06A0.4,0.4,0,0,1,13.39,3.29Z" fill="none" stroke="#6b6b6b" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
After Width: | Height: | Size: 471 B |
1
static/svgs/tabs/studios-active.svg
Normal file
1
static/svgs/tabs/studios-active.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><polyline points="6.88 12.46 6.88 12.46 13.58 12.46 13.58 8 13.58 8" fill="none" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/><polyline points="4.65 10.23 4.65 10.23 11.35 10.23 11.35 5.77 11.35 5.77" fill="none" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/><rect x="2.42" y="3.54" width="6.69" height="4.46" transform="translate(11.54 11.54) rotate(-180)" fill="#26d9bb" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
After Width: | Height: | Size: 596 B |
1
static/svgs/tabs/studios-inactive.svg
Normal file
1
static/svgs/tabs/studios-inactive.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><polyline points="4.65 10.23 4.65 10.23 11.35 10.23 11.35 5.77 11.35 5.77" fill="none" stroke="#6b6b6b" stroke-linecap="round" stroke-linejoin="round"/><rect x="2.42" y="3.54" width="6.69" height="4.46" transform="translate(11.54 11.54) rotate(-180)" fill="none" stroke="#6b6b6b" stroke-linecap="round" stroke-linejoin="round"/><polyline points="6.88 12.46 6.88 12.46 13.58 12.46 13.58 8 13.58 8" fill="none" stroke="#6b6b6b" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
After Width: | Height: | Size: 593 B |
Loading…
Reference in a new issue