mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-26 00:58:14 -05:00
Introduce new tx-push-www script to automate string push to transifex
This commit is contained in:
parent
7bfaa27eb0
commit
2d3158a8f7
12 changed files with 88 additions and 890 deletions
|
@ -139,3 +139,9 @@ stages:
|
|||
- test
|
||||
- name: smoke
|
||||
if: type != pull_request
|
||||
- provider: script
|
||||
on:
|
||||
branch: develop
|
||||
condition: $TRAVIS_EVENT_TYPE == cron
|
||||
skip_cleanup: true
|
||||
script: npm run i18n:push
|
||||
|
|
186
.tx/config
186
.tx/config
|
@ -1,186 +0,0 @@
|
|||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = zh_CN:zh-cn, zh_TW:zh-tw, pt_BR:pt-br, es_419:es-419, aa_DJ:aa-dj
|
||||
|
||||
[scratch-website.explore-l10njson]
|
||||
file_filter = localizations/explore/<lang>.json
|
||||
source_file = src/views/explore/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.general-l10njson]
|
||||
file_filter = localizations/general/<lang>.json
|
||||
source_file = src/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.wedo2-l10njson]
|
||||
file_filter = localizations/wedo2/<lang>.json
|
||||
source_file = src/views/wedo2/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.teacherregistration-l10njson]
|
||||
file_filter = localizations/teacherregistration/<lang>.json
|
||||
source_file = src/views/teacherregistration/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.dmca-l10njson]
|
||||
file_filter = localizations/dmca/<lang>.json
|
||||
source_file = src/views/dmca/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.jobs-l10njson]
|
||||
file_filter = localizations/jobs/<lang>.json
|
||||
source_file = src/views/jobs/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.faq-l10njson]
|
||||
file_filter = localizations/faq/<lang>.json
|
||||
source_file = src/views/faq/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.about-l10njson]
|
||||
file_filter = localizations/about/<lang>.json
|
||||
source_file = src/views/about/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.teacher-faq-l10njson]
|
||||
file_filter = localizations/teacher-faq/<lang>.json
|
||||
source_file = src/views/teachers/faq/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.developers-l10njson]
|
||||
file_filter = localizations/developers/<lang>.json
|
||||
source_file = src/views/developers/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.guidelines-l10njson]
|
||||
file_filter = localizations/guidelines/<lang>.json
|
||||
source_file = src/views/guidelines/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.educator-landing-l10njson]
|
||||
file_filter = localizations/educator-landing/<lang>.json
|
||||
source_file = src/views/teachers/landing/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.splash-l10njson]
|
||||
file_filter = localizations/splash/<lang>.json
|
||||
source_file = src/views/splash/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.conference-index-2019-l10njson]
|
||||
file_filter = localizations/conference-index-2019/<lang>.json
|
||||
source_file = src/views/conference/2019/index/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.conference-index-2017-l10njson]
|
||||
file_filter = localizations/conference-index-2017/<lang>.json
|
||||
source_file = src/views/conference/2017/index/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.credits-l10njson]
|
||||
file_filter = localizations/credits/<lang>.json
|
||||
source_file = src/views/credits/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.download-l10njson]
|
||||
file_filter = localizations/download/<lang>.json
|
||||
source_file = src/views/download/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.download-scratch2-l10njson]
|
||||
file_filter = localizations/download/scratch2/<lang>.json
|
||||
source_file = src/views/download/scratch2/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.camp-l10njson]
|
||||
file_filter = localizations/camp/<lang>.json
|
||||
source_file = src/views/camp/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.messages-l10njson]
|
||||
file_filter = localizations/messages/<lang>.json
|
||||
source_file = src/views/messages/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.research-l10njson]
|
||||
file_filter = localizations/research/<lang>.json
|
||||
source_file = src/views/research/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.preview-l10njson]
|
||||
file_filter = localizations/preview/<lang>.json
|
||||
source_file = src/views/preview/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.ev3-l10njson]
|
||||
source_file = src/views/ev3/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.microbit-l10njson]
|
||||
source_file = src/views/microbit/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.boost-l10njson]
|
||||
source_file = src/views/boost/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.gdxfor-l10njson]
|
||||
source_file = src/views/gdxfor/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.search-l10njson]
|
||||
file_filter = localizations/search/<lang>.json
|
||||
source_file = src/views/search/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.wedo2-legacy-l10njson]
|
||||
source_file = src/views/wedo2-legacy/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.parents-l10njson]
|
||||
source_file = src/views/parents/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.scratch_14-l10njson]
|
||||
source_file = src/views/scratch_1.4/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.ideas-l10njson]
|
||||
source_file = src/views/ideas/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[scratch-website.starter-projects-l10njson]
|
||||
source_file = src/views/starter-projects/l10n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
81
bin/tx-push-www
Executable file
81
bin/tx-push-www
Executable file
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Push www strings to Transifex, using scratch-l10n's tx-push-src.js script
|
||||
|
||||
1. for every file like src/views/.../l10n.json, call tx-push-src.js
|
||||
2. also call tx-push-src.js on the general file, src/l10n.json
|
||||
|
||||
The format of tx-push-src.js's arguments is:
|
||||
$ tx-push-src.js tx-project tx-resource english-json-file
|
||||
So, for example, src/views/parents/l10n.json will use:
|
||||
$ tx-push-src.js scratch-website parents-l10njson src/views/parents/l10n.json
|
||||
|
||||
*/
|
||||
|
||||
const glob = require('glob');
|
||||
const execSync = require('child_process').execSync;
|
||||
|
||||
// determine if this is a dry run, or if we're really pushing to transifex
|
||||
let execute = false;
|
||||
const args = process.argv.slice(2);
|
||||
if (args[0] === '--execute') {
|
||||
process.stdout.write('pushing to transifex...\n');
|
||||
execute = true;
|
||||
} else {
|
||||
process.stdout.write('Dry run: pass "execute" as a parameter to add --execute switch to commands\n');
|
||||
}
|
||||
|
||||
// exceptions to the usual relationship between file path and corresponding
|
||||
// transifex resource name
|
||||
const overrides = {
|
||||
'src/views/teachers/faq/l10n.json': 'teacher-faq-l10njson',
|
||||
'src/views/teachers/landing/l10n.json': 'educator-landing-l10njson',
|
||||
'src/views/conference/2020/index/l10n.json': 'conference-index-2020-l10njson',
|
||||
'src/views/conference/2019/index/l10n.json': 'conference-index-2019-l10njson',
|
||||
'src/views/conference/2017/index/l10n.json': 'conference-index-2017-l10njson'
|
||||
};
|
||||
|
||||
// convert an l10n file path to the usual format of the corresponding
|
||||
// transifex resource name. E.g., for file path src/views/parents/l10n.json ,
|
||||
// return parents-l10njson.
|
||||
const txResourceNameFromPath = l10nFilePath => {
|
||||
const pathRegexp = /(src\/views\/)?(.*)/g;
|
||||
const match = pathRegexp.exec(l10nFilePath);
|
||||
let resourceName = match[2];
|
||||
resourceName = resourceName.replace(/\//g, '-');
|
||||
resourceName = resourceName.replace(/\./g, '');
|
||||
return resourceName;
|
||||
};
|
||||
|
||||
// start with the general l10n file, which is an exception to the format
|
||||
let resources = [{
|
||||
filename: 'src/l10n.json',
|
||||
resourceName: 'general-l10njson'
|
||||
}];
|
||||
|
||||
glob('src/views/**/l10n.json', {}, function (er, files) {
|
||||
files.forEach(filename => {
|
||||
// figure out likely resource name from file path
|
||||
let resourceName = txResourceNameFromPath(filename);
|
||||
if (filename in overrides) { // see if it needs overriding
|
||||
resourceName = overrides[filename];
|
||||
}
|
||||
resources.push({
|
||||
filename: filename,
|
||||
resourceName: resourceName
|
||||
});
|
||||
});
|
||||
|
||||
let cmd;
|
||||
resources.forEach(resource => {
|
||||
cmd = `$(npm bin)/tx-push-src scratch-website ${resource.resourceName} ${resource.filename}`;
|
||||
if (execute) {
|
||||
// push all the source files to transifex - force update
|
||||
process.stdout.write(`running command: ${cmd}\n`);
|
||||
execSync(cmd, {stdio: 'inherit'});
|
||||
} else {
|
||||
process.stdout.write(`command we would run: ${cmd}\n`);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -26,6 +26,7 @@
|
|||
"deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/",
|
||||
"deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/",
|
||||
"deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/",
|
||||
"i18n:push": "tx-push-www --execute",
|
||||
"translate:urls": "node ./bin/get-localized-urls localized-urls.json",
|
||||
"translate:files": "node ./bin/build-locales node_modules/scratch-l10n/www intl",
|
||||
"translate": "npm run translate:urls && npm run translate:files"
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"preview-faq.title": "Scratch 3.0 FAQ"
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
const cheerio = require('cheerio');
|
||||
const injectIntl = require('react-intl').injectIntl;
|
||||
const intlShape = require('react-intl').intlShape;
|
||||
const React = require('react');
|
||||
const xhr = require('xhr');
|
||||
|
||||
const InformationPage = require('../../components/informationpage/informationpage.jsx');
|
||||
|
||||
const Page = require('../../components/page/www/page.jsx');
|
||||
const render = require('../../lib/render.jsx');
|
||||
|
||||
require('./preview-faq.scss');
|
||||
|
||||
class PreviewFaq extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
faqDoc: {__html: ''}
|
||||
};
|
||||
}
|
||||
componentDidMount () {
|
||||
xhr({
|
||||
method: 'GET',
|
||||
uri: 'https://docs.google.com/document/d/e/2PACX-1vQZFrpOagYqEwcrBBCplIomiyguPAodIJVnCq9Sr11WDI_aa2b-JtDWak-Aiu-cwWobTXftRMF6wBbd/pub?embedded=true'
|
||||
}, (error, response, body) => {
|
||||
const $ = cheerio.load(body);
|
||||
this.setState({faqDoc: {__html: $('html').html()}});
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<InformationPage title={this.props.intl.formatMessage({id: 'preview-faq.title'})}>
|
||||
<div className="inner">
|
||||
<div
|
||||
className="preview-faq"
|
||||
dangerouslySetInnerHTML={this.state.faqDoc} // eslint-disable-line react/no-danger
|
||||
/>
|
||||
</div>
|
||||
</InformationPage>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PreviewFaq.propTypes = {
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
const WrappedPreviewFAQ = injectIntl(PreviewFaq);
|
||||
|
||||
render(<Page><WrappedPreviewFAQ /></Page>, document.getElementById('app'));
|
|
@ -1,18 +0,0 @@
|
|||
#view {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.preview-faq {
|
||||
margin-bottom: 5rem;
|
||||
}
|
||||
|
||||
.title-banner-h1 {
|
||||
line-height: 1.7em !important;
|
||||
font-family: "Helvetica Neue", "Helvetica", Arial, sans-serif !important;
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
|
||||
.preview-faq li {
|
||||
margin: 0 2rem !important;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"cards.Scratch2CardsLink": "https://resources.scratch.mit.edu/www/cards/en/Scratch2Cards.pdf",
|
||||
"cards.ScratchCardsAllLink": "https://resources.scratch.mit.edu/www/cards/en/ScratchCardsAll.pdf",
|
||||
"cards.catchCardsLink": "https://resources.scratch.mit.edu/www/cards/en/catchCards.pdf",
|
||||
"cards.danceCardsLink": "https://resources.scratch.mit.edu/www/cards/en/danceCards.pdf",
|
||||
"cards.dressupCardsLink": "https://resources.scratch.mit.edu/www/cards/en/dressupCards.pdf",
|
||||
"cards.fashionCardsLink": "https://resources.scratch.mit.edu/www/cards/en/fashionCards.pdf",
|
||||
"cards.flyCardsLink": "https://resources.scratch.mit.edu/www/cards/en/flyCards.pdf",
|
||||
"cards.hide-seekCardsLink": "https://resources.scratch.mit.edu/www/cards/en/hide-seekCards.pdf",
|
||||
"cards.musicCardsLink": "https://resources.scratch.mit.edu/www/cards/en/musicCards.pdf",
|
||||
"cards.nameCardsLink": "https://resources.scratch.mit.edu/www/cards/en/nameCards.pdf",
|
||||
"cards.petCardsLink": "https://resources.scratch.mit.edu/www/cards/en/petCards.pdf",
|
||||
"cards.pongCardsLink": "https://resources.scratch.mit.edu/www/cards/en/pongCards.pdf",
|
||||
"cards.raceCardsLink": "https://resources.scratch.mit.edu/www/cards/en/raceCards.pdf",
|
||||
"cards.storyCardsLink": "https://resources.scratch.mit.edu/www/cards/en/storyCards.pdf",
|
||||
"guides.CatchGuideLink": "https://resources.scratch.mit.edu/www/guides/en/CatchGuide.pdf",
|
||||
"guides.DanceGuideLink": "https://resources.scratch.mit.edu/www/guides/en/DanceGuide.pdf",
|
||||
"guides.FashionGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FashionGuide.pdf",
|
||||
"guides.FlyGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FlyGuide.pdf",
|
||||
"guides.Getting-Started-Guide-Scratch2Link": "https://resources.scratch.mit.edu/www/guides/en/Getting-Started-Guide-Scratch2.pdf",
|
||||
"guides.HideandSeekGuideLink": "https://resources.scratch.mit.edu/www/guides/en/HideandSeekGuide.pdf",
|
||||
"guides.MusicGuideLink": "https://resources.scratch.mit.edu/www/guides/en/MusicGuide.pdf",
|
||||
"guides.NameGuideLink": "https://resources.scratch.mit.edu/www/guides/en/NameGuide.pdf",
|
||||
"guides.PetGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PetGuide.pdf",
|
||||
"guides.PongGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PongGuide.pdf",
|
||||
"guides.RaceGuideLink": "https://resources.scratch.mit.edu/www/guides/en/RaceGuide.pdf",
|
||||
"guides.StoryGuideLink": "https://resources.scratch.mit.edu/www/guides/en/StoryGuide.pdf"
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"tips.title": "Getting Started",
|
||||
"tips.subTitle": "Start making projects in Scratch by trying the <a href=\"/projects/editor/?tip_bar=getStarted\" class=\"mod-underline\">online tutorial</a> or downloading the <a href=\"{GettingStartedPDF}\" class=\"mod-underline\">PDF Guide</a>.",
|
||||
"tips.tryGettingStarted": "Try the Getting Started tutorial",
|
||||
"tips.tttHeader": "Things to Try",
|
||||
"tips.tttBody": "What do you want to make with Scratch? For each activity, you can try the <strong>Tutorial</strong>, download a set of <strong>Activity Cards</strong>, or view the <strong>Educator Guide</strong>.",
|
||||
"tips.cardsHeader": "Get the Entire Collection of Activity Cards",
|
||||
"tips.cardsBody": "With the Scratch Activity Cards, you can learn to create interactive games, stories, music, animations, and more!",
|
||||
"tips.cardsPurchase": "Purchase Printed Set",
|
||||
"tips.starterProjectsHeader": "Starter Projects",
|
||||
"tips.starterProjectsBody": "You can play with Starter Projects to get ideas for making your own projects.",
|
||||
"tips.starterProjectsPlay": "Play with Starter Projects",
|
||||
"tips.offlineEditorHeader": "Offline Editor",
|
||||
"tips.offlineEditorBody": "To create projects without an Internet connection, you can <a href=\"/download\">download the offline editor</a>.",
|
||||
"tips.questionsHeader": "Questions",
|
||||
"tips.questionsBody": "Have more questions? See the <a href=\"/info/faq\">Frequently Asked Questions</a> or visit the <a href=\"/discuss/7/\">Help with Scripts Forum</a>.",
|
||||
"ttt.tutorial": "Tutorial",
|
||||
"tile.guides": "See Cards and Guides",
|
||||
"tile.tryIt": "Try It",
|
||||
"ttt.placeholder": "Placeholder text",
|
||||
"ttt.tutorialSubtitle": "Find out how to make this project using a step-by-step tutorial in Scratch.",
|
||||
"ttt.activityTitle": "Activity Cards",
|
||||
"ttt.activitySubtitle": "Explore new coding ideas using this set of illustrated cards you can print out.",
|
||||
"ttt.educatorTitle": "Educator Guide",
|
||||
"ttt.educatorSubtitle": "Use this educator guide to plan and lead a one-hour Scratch workshop.",
|
||||
"ttt.open": "Open",
|
||||
"ttt.MakeItFlyTitle": "Make It Fly",
|
||||
"ttt.MakeItFlyDescription": "Animate the Scratch Cat, The Powerpuff Girls, or even a taco!",
|
||||
"ttt.AnimateYourNameTitle": "Animate a Name",
|
||||
"ttt.AnimateYourNameDescription": "Animate the letters of your username, initials, or favorite word.",
|
||||
"ttt.RaceTitle": "Race to the Finish",
|
||||
"ttt.RaceDescription": "Make a game where two characters race each other.",
|
||||
"ttt.MakeMusicTitle": "Make Music",
|
||||
"ttt.MakeMusicDescription": "Choose instruments, add sounds, and press keys to play music.",
|
||||
"ttt.HideAndSeekTitle": "Hide and Seek",
|
||||
"ttt.HideAndSeekDescription": "Make a hide-and-seek game with characters that appear and disappear.",
|
||||
"ttt.StoryTitle": "Create a Story",
|
||||
"ttt.StoryDescription": "Choose characters, add conversation, and bring your story to life.",
|
||||
"ttt.FashionTitle": "Fashion Game",
|
||||
"ttt.FashionDescription": "Make a game where you dress a character with different clothes and styles.",
|
||||
"ttt.PongTitle": "Pong Game",
|
||||
"ttt.PongDescription": "Make a bouncing ball game with sounds, points, and other effects.",
|
||||
"ttt.DanceTitle": "Let's Dance",
|
||||
"ttt.DanceDescription": "Design an animated dance scene with music and dance moves.",
|
||||
"ttt.CatchTitle": "Catch Game",
|
||||
"ttt.CatchDescription": "Make a game where you catch things falling from the sky.",
|
||||
"ttt.VirtualPetTitle": "Virtual Pet",
|
||||
"ttt.VirtualPetDescription": "Create an interactive pet that can eat, drink, and play."
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
const bindAll = require('lodash.bindall');
|
||||
const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage;
|
||||
const FormattedMessage = require('react-intl').FormattedMessage;
|
||||
const injectIntl = require('react-intl').injectIntl;
|
||||
const intlShape = require('react-intl').intlShape;
|
||||
const React = require('react');
|
||||
|
||||
const Button = require('../../components/forms/button.jsx');
|
||||
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
||||
const MasonryGrid = require('../../components/masonrygrid/masonrygrid.jsx');
|
||||
const TitleBanner = require('../../components/title-banner/title-banner.jsx');
|
||||
const TTTModal = require('../../components/modal/ttt/modal.jsx');
|
||||
const TTTTile = require('../../components/ttt-tile/ttt-tile.jsx');
|
||||
|
||||
const Page = require('../../components/page/www/page.jsx');
|
||||
const render = require('../../lib/render.jsx');
|
||||
|
||||
const Tiles = require('./ttt.json');
|
||||
|
||||
require('./tips.scss');
|
||||
|
||||
class Tips extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleShowTTTModal',
|
||||
'handleHideTTTModal',
|
||||
'renderTTTTiles'
|
||||
]);
|
||||
this.state = {
|
||||
currentTile: Tiles[0],
|
||||
TTTModalOpen: false
|
||||
};
|
||||
}
|
||||
handleShowTTTModal (tile) {
|
||||
// expects translated tile
|
||||
this.setState({
|
||||
currentTile: tile,
|
||||
TTTModalOpen: true
|
||||
});
|
||||
}
|
||||
handleHideTTTModal () {
|
||||
this.setState({
|
||||
TTTModalOpen: false
|
||||
});
|
||||
}
|
||||
renderTTTTiles () {
|
||||
|
||||
return Tiles.map((tile, key) => {
|
||||
const translatedTile = {
|
||||
activityLoc: this.props.intl.formatMessage({id: tile.activityLoc}),
|
||||
bannerUrl: tile.bannerUrl,
|
||||
description: this.props.intl.formatMessage({id: tile.description}),
|
||||
guideLoc: this.props.intl.formatMessage({id: tile.guideLoc}),
|
||||
thumbUrl: tile.thumbUrl,
|
||||
title: this.props.intl.formatMessage({id: tile.title}),
|
||||
tutorialLoc: tile.tutorialLoc
|
||||
};
|
||||
return (
|
||||
<TTTTile
|
||||
key={key}
|
||||
onGuideClick={() => { // eslint-disable-line react/jsx-no-bind
|
||||
this.handleShowTTTModal(translatedTile);
|
||||
}}
|
||||
{...translatedTile}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="tips">
|
||||
<TitleBanner className="masthead mod-blue-bg">
|
||||
<h1 className="title-banner-h1">
|
||||
<FormattedMessage id="tips.title" />
|
||||
</h1>
|
||||
<p className="intro title-banner-p">
|
||||
<FormattedHTMLMessage
|
||||
id="tips.subTitle"
|
||||
values={{
|
||||
GettingStartedPDF: this.props.intl.formatMessage({
|
||||
id: 'guides.Getting-Started-Guide-Scratch2Link'
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p className="title-banner-p">
|
||||
<a href="/projects/editor/?tip_bar=getStarted">
|
||||
<Button className="tips-button getting-started-button">
|
||||
<img src="/images/tips/blocks-icon.svg" />
|
||||
<FormattedMessage id="tips.tryGettingStarted" />
|
||||
</Button>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
</TitleBanner>
|
||||
<div className="inner">
|
||||
<section className="ttt-section">
|
||||
<div className="ttt-head">
|
||||
<h2>
|
||||
<FormattedMessage id="tips.tttHeader" />
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="tips.tttBody" />
|
||||
</p>
|
||||
</div>
|
||||
<MasonryGrid >
|
||||
{this.renderTTTTiles()}
|
||||
</MasonryGrid>
|
||||
<TTTModal
|
||||
isOpen={this.state.TTTModalOpen}
|
||||
onRequestClose={this.handleHideTTTModal}
|
||||
{...this.state.currentTile}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
<div className="tips-resources">
|
||||
<div className="inner">
|
||||
<FlexRow
|
||||
as="section"
|
||||
className="tips-info-section cards-info"
|
||||
>
|
||||
<div className="tips-info-body">
|
||||
<h2>
|
||||
<FormattedMessage id="tips.cardsHeader" />
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="tips.cardsBody" />
|
||||
</p>
|
||||
<p className="tips-cards-buttons">
|
||||
<a
|
||||
href={this.props.intl.formatMessage({
|
||||
id: 'cards.ScratchCardsAllLink'
|
||||
})}
|
||||
>
|
||||
<Button className="tips-button">
|
||||
<FormattedMessage id="general.downloadPDF" />
|
||||
</Button>
|
||||
</a>
|
||||
<a
|
||||
href="https://scratch-foundation.myshopify.com/collections/all-products/products/scratch-coding-cards-creative-coding-activities-for-kids"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<Button className="tips-button purchase-button">
|
||||
<FormattedMessage id="tips.cardsPurchase" />
|
||||
<img src="/images/tips/arrow-icon.svg" />
|
||||
</Button>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div className="tips-info-body tips-illustration">
|
||||
<img src="/images/tips/cards-illustration.svg" />
|
||||
</div>
|
||||
</FlexRow>
|
||||
</div>
|
||||
</div>
|
||||
<div className="inner">
|
||||
<div className="tips-divider" />
|
||||
</div>
|
||||
<div className="tips-resources">
|
||||
<div className="inner">
|
||||
<FlexRow
|
||||
as="section"
|
||||
className="tips-info-section"
|
||||
>
|
||||
<div className="tips-info-body tips-illustration">
|
||||
<img
|
||||
className="mod-flow-left"
|
||||
src="/images/tips/project-illustration.svg"
|
||||
/>
|
||||
</div>
|
||||
<div className="tips-info-body">
|
||||
<h2>
|
||||
<FormattedMessage id="tips.starterProjectsHeader" />
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="tips.starterProjectsBody" />
|
||||
</p>
|
||||
<p>
|
||||
<a href="/starter_projects">
|
||||
<Button className="tips-button">
|
||||
<FormattedMessage id="tips.starterProjectsPlay" />
|
||||
</Button>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</FlexRow>
|
||||
</div>
|
||||
</div>
|
||||
<div className="inner">
|
||||
<FlexRow
|
||||
as="section"
|
||||
className="tips-info-section mod-align-top"
|
||||
>
|
||||
<div className="tips-info-body mod-narrow">
|
||||
<img
|
||||
className="tips-icon"
|
||||
src="/images/tips/download-icon.svg"
|
||||
/>
|
||||
<h3>
|
||||
<FormattedMessage id="tips.offlineEditorHeader" />
|
||||
</h3>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="tips.offlineEditorBody" />
|
||||
</p>
|
||||
</div>
|
||||
<div className="tips-info-body mod-narrow">
|
||||
<img
|
||||
className="tips-icon"
|
||||
src="/images/tips/question-icon.svg"
|
||||
/>
|
||||
<h3>
|
||||
<FormattedMessage id="tips.questionsHeader" />
|
||||
</h3>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="tips.questionsBody" />
|
||||
</p>
|
||||
</div>
|
||||
</FlexRow>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Tips.propTypes = {
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
const WrappedTips = injectIntl(Tips);
|
||||
|
||||
render(
|
||||
<Page><WrappedTips /></Page>, document.getElementById('app'));
|
|
@ -1,221 +0,0 @@
|
|||
@import "../../colors";
|
||||
@import "../../frameless";
|
||||
|
||||
$base-bg: $ui-white;
|
||||
|
||||
#view {
|
||||
background-color: $ui-gray;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tips-resources {
|
||||
background-color: $ui-white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ttt-section {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tips-divider {
|
||||
border-top: 1px solid $ui-gray;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tips-banner-image {
|
||||
max-width: calc(100% - 2rem);
|
||||
}
|
||||
|
||||
.tips-button {
|
||||
margin-right: .75rem;
|
||||
background-color: $ui-blue;
|
||||
color: $ui-white;
|
||||
font-size: 1rem;
|
||||
|
||||
&.getting-started-button {
|
||||
margin-right: 0;
|
||||
background-color: $ui-white;
|
||||
color: $link-blue;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-right: 1rem;
|
||||
height: 1.25rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $ui-white;
|
||||
}
|
||||
}
|
||||
|
||||
.purchase-button {
|
||||
img {
|
||||
margin-right: 0;
|
||||
margin-left: .75rem;
|
||||
width: 1rem;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-section {
|
||||
padding: 2.5rem 0;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tips-info-body {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tips-cards-buttons {
|
||||
a {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
img.tips-icon {
|
||||
height: 1.75rem;
|
||||
}
|
||||
//4 columns
|
||||
@media #{$small} {
|
||||
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
padding-bottom: 1.25rem;
|
||||
|
||||
p {
|
||||
max-width: $cols4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ttt-head {
|
||||
|
||||
p {
|
||||
max-width: $cols4;
|
||||
}
|
||||
}
|
||||
|
||||
//put the image first if in 4-column
|
||||
.tips-info-body {
|
||||
max-width: $cols4;
|
||||
text-align: center;
|
||||
|
||||
&.tips-illustration {
|
||||
order: -1;
|
||||
img {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//6 columns
|
||||
@media #{$medium} {
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
|
||||
p {
|
||||
max-width: $cols6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ttt-head {
|
||||
p {
|
||||
max-width: $cols6;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-body.tips-illustration {
|
||||
order: -1;
|
||||
img {
|
||||
width: $cols4;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-body {
|
||||
max-width: $cols4;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//8 columns
|
||||
@media #{$intermediate} {
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
padding-bottom: 2rem;
|
||||
|
||||
p {
|
||||
max-width: $cols6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ttt-head {
|
||||
p {
|
||||
max-width: $cols6;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-section {
|
||||
&.mod-align-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-body {
|
||||
max-width: $cols4;
|
||||
}
|
||||
|
||||
.tips-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
img.mod-flow-left {
|
||||
transform: translate(-1*$cols2);
|
||||
}
|
||||
}
|
||||
|
||||
// 12 columns
|
||||
@media #{$big} {
|
||||
.title-banner {
|
||||
&.masthead {
|
||||
padding-bottom: 1.25rem;
|
||||
|
||||
p {
|
||||
max-width: $cols8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ttt-head {
|
||||
p {
|
||||
max-width: $cols8;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-section {
|
||||
&.mod-align-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info-body {
|
||||
max-width: $cols6;
|
||||
&.mod-narrow {
|
||||
max-width: $cols5;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
[
|
||||
{
|
||||
"title": "ttt.AnimateYourNameTitle",
|
||||
"description": "ttt.AnimateYourNameDescription",
|
||||
"thumbUrl": "/images/ttt/animate-your-name.jpg",
|
||||
"bannerUrl": "/images/ttt/animate-your-name-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=name",
|
||||
"activityLoc": "cards.nameCardsLink",
|
||||
"guideLoc": "guides.NameGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.MakeItFlyTitle",
|
||||
"description": "ttt.MakeItFlyDescription",
|
||||
"thumbUrl": "/images/ttt/make-it-fly.jpg",
|
||||
"bannerUrl": "/images/ttt/make-it-fly-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=fly",
|
||||
"activityLoc": "cards.flyCardsLink",
|
||||
"guideLoc": "guides.FlyGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.MakeMusicTitle",
|
||||
"description": "ttt.MakeMusicDescription",
|
||||
"thumbUrl": "/images/ttt/make-music.jpg",
|
||||
"bannerUrl": "/images/ttt/make-music-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=music",
|
||||
"activityLoc": "cards.musicCardsLink",
|
||||
"guideLoc": "guides.MusicGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.RaceTitle",
|
||||
"description": "ttt.RaceDescription",
|
||||
"thumbUrl": "/images/ttt/race-to-the-finish.jpg",
|
||||
"bannerUrl": "/images/ttt/race-to-the-finish-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=racegame",
|
||||
"activityLoc": "cards.raceCardsLink",
|
||||
"guideLoc": "guides.RaceGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.HideAndSeekTitle",
|
||||
"description": "ttt.HideAndSeekDescription",
|
||||
"thumbUrl": "/images/ttt/hide-and-seek.jpg",
|
||||
"bannerUrl": "/images/ttt/hide-and-seek-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=hide",
|
||||
"activityLoc": "cards.hide-seekCardsLink",
|
||||
"guideLoc": "guides.HideandSeekGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.FashionTitle",
|
||||
"description": "ttt.FashionDescription",
|
||||
"thumbUrl": "/images/ttt/fashion-game.jpg",
|
||||
"bannerUrl": "/images/ttt/fashion-game-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=fashion",
|
||||
"activityLoc": "cards.fashionCardsLink",
|
||||
"guideLoc": "guides.FashionGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.StoryTitle",
|
||||
"description": "ttt.StoryDescription",
|
||||
"thumbUrl": "/images/ttt/create-a-story.jpg",
|
||||
"bannerUrl": "/images/ttt/create-a-story-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=story",
|
||||
"activityLoc": "cards.storyCardsLink",
|
||||
"guideLoc": "guides.StoryGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.PongTitle",
|
||||
"description": "ttt.PongDescription",
|
||||
"thumbUrl": "/images/ttt/pong-game.jpg",
|
||||
"bannerUrl": "/images/ttt/pong-game-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=pong",
|
||||
"activityLoc": "cards.pongCardsLink",
|
||||
"guideLoc": "guides.PongGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.DanceTitle",
|
||||
"description": "ttt.DanceDescription",
|
||||
"thumbUrl": "/images/ttt/lets-dance.jpg",
|
||||
"bannerUrl": "/images/ttt/lets-dance-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=dance",
|
||||
"activityLoc": "cards.danceCardsLink",
|
||||
"guideLoc": "guides.DanceGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.CatchTitle",
|
||||
"description": "ttt.CatchDescription",
|
||||
"thumbUrl": "/images/ttt/catch-game.jpg",
|
||||
"bannerUrl": "/images/ttt/catch-game-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=catch",
|
||||
"activityLoc": "cards.catchCardsLink",
|
||||
"guideLoc": "guides.CatchGuideLink"
|
||||
},
|
||||
{
|
||||
"title": "ttt.VirtualPetTitle",
|
||||
"description": "ttt.VirtualPetDescription",
|
||||
"thumbUrl": "/images/ttt/virtual-pet.jpg",
|
||||
"bannerUrl": "/images/ttt/virtual-pet-banner.jpg",
|
||||
"tutorialLoc": "/projects/editor/?tip_bar=pet",
|
||||
"activityLoc": "cards.petCardsLink",
|
||||
"guideLoc": "guides.PetGuideLink"
|
||||
}
|
||||
]
|
Loading…
Reference in a new issue