Merge branch 'develop' of https://github.com/LLK/scratch-www into readme-refactor

This commit is contained in:
Ben Wheeler 2019-11-25 16:14:18 -05:00
commit 534658ec7a
14 changed files with 162 additions and 268 deletions

25
package-lock.json generated
View file

@ -12032,6 +12032,24 @@
"prepend-http": "^1.0.0",
"query-string": "^4.1.0",
"sort-keys": "^1.0.0"
},
"dependencies": {
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"dev": true,
"requires": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"dev": true
}
}
},
"npm-run-path": {
@ -13907,11 +13925,12 @@
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
},
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
"dev": true,
"requires": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}

View file

@ -112,6 +112,7 @@
"po2icu": "0.0.2",
"postcss-loader": "2.0.10",
"prop-types": "15.6.0",
"query-string": "^5.1.1",
"react": "16.2.0",
"react-dom": "16.2.0",
"react-intl": "2.8.0",

View file

@ -22,7 +22,7 @@ const Footer = props => (
</a>
</dd>
<dd>
<a href="/jobs">
<a href="https://www.scratchfoundation.org/opportunities">
<FormattedMessage id="general.jobs" />
</a>
</dd>
@ -83,7 +83,7 @@ const Footer = props => (
</a>
</dd>
<dd>
<a href="/jobs">
<a href="https://www.scratchfoundation.org/opportunities">
<FormattedMessage id="general.jobs" />
</a>
</dd>

View file

@ -148,18 +148,9 @@
"title": "Ideas"
},
{
"name": "jobs",
"pattern": "^/jobs/?$",
"routeAlias": "/jobs(/moderator)?/?$",
"view": "jobs/jobs",
"title": "Jobs"
},
{
"name": "jobs-moderator",
"pattern": "^/jobs/moderator/?$",
"routeAlias": "/jobs(/moderator)?/?$",
"view": "jobs/moderator/moderator",
"title": "Community Moderator"
"name": "jobs-redirect",
"pattern": "^/jobs/?(\\?.*)?$",
"redirect": "https://www.scratchfoundation.org/opportunities/"
},
{
"name": "join",
@ -524,7 +515,7 @@
},
{
"name": "imagine-if-tutorial-redirect",
"pattern": "^/imagine/?$",
"pattern": "^/imagine/?(\\?.*)?$",
"redirect": "/projects/editor/?tutorial=imagine"
},
{
@ -569,12 +560,12 @@
},
{
"name": "talking-tales-tutorial-redirect",
"pattern": "^/talking-tales/?$",
"pattern": "^/talking-tales/?(\\?.*)?$",
"redirect": "/projects/editor?tutorial=talking"
},
{
"name": "code-a-cartoon-tutorial-redirect",
"pattern": "^/code-a-cartoon/?$",
"pattern": "^/code-a-cartoon/?(\\?.*)?$",
"redirect": "/projects/331474033/editor/?tutorial=code-cartoon"
},
{

View file

@ -32,12 +32,20 @@ const Credits = () => (
key={`person-${index}`}
>
<div>
<a href={`https://scratch.mit.edu/users/${person.userName}/`}>
{person.userName ? (
<a href={`https://scratch.mit.edu/users/${person.userName}/`}>
<Avatar
alt=""
src={`https://cdn.scratch.mit.edu/get_image/user/${person.userId || 'default'}_80x80.png`}
/>
</a>
) : (
/* if userName is not given, there's no chance userId is given */
<Avatar
alt=""
src={`https://cdn.scratch.mit.edu/get_image/user/${person.userId || 'default'}_80x80.png`}
src={`https://cdn.scratch.mit.edu/get_image/user/default_80x80.png`}
/>
</a>
)}
</div>
<span className="avatar-text">
{person.name}
@ -145,7 +153,8 @@ const Credits = () => (
Christina Huang, Tony Hwang, Abdulrahman Idlbi, Randy Jou, Lily Kim,
Tauntaun Kim, Saskia Leggett, Tim Mickel, Amon Millner, Ricarose Roque,
Andrea Saxman, Jay Silver, Tammy Stern, Lis Sylvan, Hanako Tjia, Claudia
Urrea, Oren Zuckerman.
Urrea, Oren Zuckerman, Tina Quach, My Nguyen, Lisa O&apos;Brien, Joel Gritter,
Linda Fernsel, Ellen Daoust, Julia Zimmerman.
</p>
<p>
<FormattedMessage id="credits.partnersBody" />

View file

@ -39,11 +39,6 @@
"userId": 27383273,
"name": "Karishma Chadha"
},
{
"userName": "SunnyDay4aBlueJay",
"userId": 24164779,
"name": "Ellen Daoust"
},
{
"userName": "shruti",
"userId": 3714374,
@ -54,11 +49,6 @@
"userId": 900283,
"name": "Champika Fernando"
},
{
"userName": "LiFaytheGoblin",
"userId": 1048810,
"name": "Linda Fernsel"
},
{
"userName": "dietbacon",
"userId": 24137617,
@ -84,11 +74,6 @@
"userId": 49156,
"name": "Mark Goff"
},
{
"userName": "GulpTea",
"userId": 26249744,
"name": "Joel Gritter"
},
{
"userName": "codubee",
"userId": 10866958,
@ -104,11 +89,6 @@
"userId": 22183577,
"name": "Sean Hickey"
},
{
"userName": "theladynico",
"userId": 35550237,
"name": "Nicole Hughes"
},
{
"userName": "sgcc_",
"userId": 21986973,
@ -134,16 +114,6 @@
"userId": 24838781,
"name": "Marian Muthui"
},
{
"userName": "me_win",
"userId": 7664502,
"name": "My Nguyen"
},
{
"userName": "lob12",
"userId": 2860339,
"name": "Lisa O'Brien"
},
{
"userName": "",
"userId": "",
@ -164,11 +134,6 @@
"userId": 2286560,
"name": "Carmelo Presicce"
},
{
"userName": "quacht",
"userId": 25500116,
"name": "Tina Quach"
},
{
"userName": "mres",
"userId": 167,
@ -235,8 +200,33 @@
"name": "Kathy Wu"
},
{
"userName": "stymphalianbirb",
"userId": 2796185,
"name": "Julia Zimmerman"
"userName": "amylaser",
"userId": 17462181,
"name": "Amy Lee"
},
{
"userName": "algorithmar",
"userId": 43013126,
"name": "Maren Vernon"
},
{
"userName": "bluecrazie",
"userId": 50257624,
"name": "JT Galla"
},
{
"userName": "Za-Chary",
"userId": 974363,
"name": "Zachary Deiman"
},
{
"userName": "Mos20",
"userId": 52545208,
"name": "Joan Fusco"
},
{
"userName": "pixelmoth",
"userId": 2408962,
"name": "Jacy Edelman"
}
]

View file

@ -228,7 +228,7 @@ const Developers = () => (
id="developers.joinBody"
values={{
jobsPageLink: (
<a href="/jobs">
<a href="https://www.scratchfoundation.org/opportunities">
<FormattedMessage id="developers.joinBodyJobsLinkText" />
</a>
),

View file

@ -1,45 +0,0 @@
const React = require('react');
const render = require('../../lib/render.jsx');
const FormattedMessage = require('react-intl').FormattedMessage;
const Page = require('../../components/page/www/page.jsx');
require('./jobs.scss');
const Jobs = () => (
<div className="jobs">
<div className="top">
<div className="inner">
<img src="/images/jobs.png" />
<h2><FormattedMessage id="jobs.titleQuestion" /></h2>
</div>
</div>
<div className="middle">
<div className="inner">
<h3><FormattedMessage id="jobs.joinScratchTeam" /></h3>
<p><FormattedMessage id="jobs.info" /></p>
<p><FormattedMessage id="jobs.workEnvironment" /></p>
</div>
</div>
<div className="bottom">
<div className="inner">
<h3><FormattedMessage id="jobs.openings" /></h3>
{/* <FormattedMessage id="jobs.nojobs" /> */}
<ul>
<li>
<a href="https://scratch.mit.edu/jobs/moderator">
Community Moderator
</a>
<span>
Remote
</span>
</li>
</ul>
</div>
</div>
</div>
);
render(<Page><Jobs /></Page>, document.getElementById('app'));

View file

@ -1,42 +0,0 @@
@import "../../colors";
.jobs {
.top {
img {
margin-bottom: 10px;
width: 100%;
}
}
.middle {
margin: 20px 0;
background-color: $ui-gray;
padding: 40px 0;
width: 100%;
}
.bottom {
width: 100%;
line-height: 200%;
.thin-heading {
padding: 20px 0;
}
p {
margin: auto;
width: 70%;
}
ul {
padding-left: 0;
list-style: none;
li {
span {
margin-left: 10px;
}
}
}
}
}

View file

@ -1,8 +0,0 @@
{
"jobs.info": "With Scratch, young people from all backgrounds are learning to program their own interactive stories, games, and animations. Children and teens from around the world have created and shared more than 10 million projects in the rapidly-growing Scratch online community.",
"jobs.joinScratchTeam": "Join the Scratch Team!",
"jobs.openings": "Current Job Openings",
"jobs.titleQuestion": "Want to work on an innovative project that is transforming the ways young people create, share, and learn?",
"jobs.workEnvironment":"Were seeking curious and motivated people to join our Scratch Team at the MIT Media Lab. We're a diverse group of educators, designers, and engineers, who work together in a playful, creative environment full of LEGO bricks, craft materials, and maker tools. We strongly value diversity, collaboration, and respect in the workplace.",
"jobs.nojobs":"We don't have any open positions at this time. Please check back soon for opportunities!"
}

View file

@ -1,108 +0,0 @@
const React = require('react');
const Page = require('../../../components/page/www/page.jsx');
const render = require('../../../lib/render.jsx');
const InformationPage = require('../../../components/informationpage/informationpage.jsx');
const Moderator = () => (
<InformationPage title={'Community Moderator'}>
<div className="inner info-inner">
<p>
Interested in online communities, internet culture, and
working with kids? We&#39;re seeking community moderators
to work with the <a href="/">Scratch</a> Team. Scratch
Moderators help keep Scratch a safe, trusted, and friendly
environment.
</p>
<p>
Scratch is a free service where young people learn to
program by creating interactive stories, games, and
animations which they can share to an online community.
Scratch has grown to more than 30 million registered
members (ages 8 and up) who create and share thousands
of projects each day. Moderators will gain valuable
experience working online with youth in a creative,
interest-driven setting.
</p>
<h3>Responsibilities:</h3>
<ul>
<li>
Promote the values and core ideas of the Scratch
project (such as inclusiveness, creative collaboration,
and constructive feedback)
</li>
<li>
Review reported users, projects, studios, and comments
for appropriateness on the Scratch website
</li>
<li>
Work with young people to help them understand what they
did that breaks our <a href="/community_guidelines">Community Guidelines</a>
</li>
<li>
Determine when a person is or isnt likely to be able to
participate constructively in the Scratch online community
</li>
</ul>
<br />
<h3>Qualifications:</h3>
<ul>
<li>
Active participation in online communities, forums,
or social media
</li>
<li>
Excellent writing and communication skills
</li>
<li>
Comfortable learning to use new software and websites
</li>
<li>
Strong online research skills
</li>
<li>
Good judgement and ability to consider issues from
multiple perspectives
</li>
<li>
Able to work well independently, manage your time
well, and stay focused while working remotely
</li>
<li>
Able to work well as part of a team and participate
in group discussions
</li>
<li>
Not required, but would be nice: ability to read and
write in multiple languages (especially if one of those
languages is Japanese, Korean, or Russian!)
</li>
</ul>
<br />
<p>
This position is part-time (10-15 hours per week),
flexible hours (this work can be done 24/7 and we
set a schedule which fits in with your life),
under contract with starting pay of $12 per hour.
All candidates must be at least 18 years old and
have authorization to work in the United States.
</p>
<p><b>(MIT Media Lab, Cambridge, MA or Remote)</b></p>
<p>
Send a copy of your resume, links to one or more of your online
presences, and cover letter to{' '}
<a href="mailto:jobs+moderator@scratch.mit.edu">jobs+moderator@scratch.mit.edu</a>.
</p>
<p>
<i>
Really want the gig? <a href="/create">Create</a> an
awesome Scratch project to introduce yourself, share
it on the Scratch website, and send us a link.
</i>
</p>
</div>
</InformationPage>
);
render(<Page><Moderator /></Page>, document.getElementById('app'));

View file

@ -111,6 +111,7 @@ const PreviewPresentation = ({
onSocialClosed,
onToggleComments,
onToggleStudio,
onUpdateProjectData,
onUpdateProjectId,
onUpdateProjectThumbnail,
originalInfo,
@ -345,6 +346,7 @@ const PreviewPresentation = ({
onProjectLoaded={onProjectLoaded}
onRemixing={onRemixing}
onSetProjectThumbnailer={onSetProjectThumbnailer}
onUpdateProjectData={onUpdateProjectData}
onUpdateProjectId={onUpdateProjectId}
onUpdateProjectThumbnail={onUpdateProjectThumbnail}
/>
@ -725,6 +727,7 @@ PreviewPresentation.propTypes = {
onSocialClosed: PropTypes.func,
onToggleComments: PropTypes.func,
onToggleStudio: PropTypes.func,
onUpdateProjectData: PropTypes.func,
onUpdateProjectId: PropTypes.func,
onUpdateProjectThumbnail: PropTypes.func,
originalInfo: projectShape,

View file

@ -8,7 +8,9 @@ const PropTypes = require('prop-types');
const connect = require('react-redux').connect;
const injectIntl = require('react-intl').injectIntl;
const parser = require('scratch-parser');
const queryString = require('query-string');
const api = require('../../lib/api');
const Page = require('../../components/page/www/page.jsx');
const storage = require('../../lib/storage.js').default;
const log = require('../../lib/log');
@ -36,6 +38,7 @@ const IntlGUI = injectIntl(GUI.default);
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
const initSentry = require('../../lib/sentry.js');
const xhr = require('xhr');
initSentry();
class Preview extends React.Component {
@ -73,6 +76,7 @@ class Preview extends React.Component {
'handleSeeInside',
'handleSetProjectThumbnailer',
'handleShare',
'handleUpdateProjectData',
'handleUpdateProjectId',
'handleUpdateProjectTitle',
'handleToggleComments',
@ -219,6 +223,84 @@ class Preview extends React.Component {
this.props.getRemixes(this.state.projectId);
}
}
// This is copy of what is in save-project-to-server in GUI that adds
// an extra get of the project info from api. We do this to wait for replication
// lag to pass. This is intended to be a temporary fix until we use the data
// from the create request to fill the projectInfo state.
handleUpdateProjectData (projectId, vmState, params) {
const opts = {
body: vmState,
// If we set json:true then the body is double-stringified, so don't
headers: {
'Content-Type': 'application/json'
},
withCredentials: true
};
const creatingProject = projectId === null || typeof projectId === 'undefined';
const queryParams = {};
if (params.hasOwnProperty('originalId')) queryParams.original_id = params.originalId;
if (params.hasOwnProperty('isCopy')) queryParams.is_copy = params.isCopy;
if (params.hasOwnProperty('isRemix')) queryParams.is_remix = params.isRemix;
if (params.hasOwnProperty('title')) queryParams.title = params.title;
let qs = queryString.stringify(queryParams);
if (qs) qs = `?${qs}`;
if (creatingProject) {
Object.assign(opts, {
method: 'post',
url: `${this.props.projectHost}/${qs}`
});
} else {
Object.assign(opts, {
method: 'put',
url: `${this.props.projectHost}/${projectId}${qs}`
});
}
return new Promise((resolve, reject) => {
xhr(opts, (err, response) => {
if (err) return reject(err);
if (response.statusCode !== 200) return reject(response.statusCode);
let body;
try {
// Since we didn't set json: true, we have to parse manually
body = JSON.parse(response.body);
} catch (e) {
return reject(e);
}
body.id = projectId;
if (creatingProject) {
body.id = body['content-name'];
}
resolve(body);
});
}).then(body => {
const fetchProjectInfo = (count, resolve) => {
api({
uri: `/projects/${body.id}`,
authentication: this.props.user.token
}, (err, projectInfo, response) => {
if (err) {
log.error(`Could not fetch project after creating: ${err}`);
return resolve(body);
}
if (typeof body === 'undefined' || response.statusCode === 404) {
// Retry after 500ms, 1.5s, 3.5s, 7.5s and then stop.
if (count > 4) {
return resolve(body);
}
return setTimeout(
fetchProjectInfo.bind(this, count + 1, resolve),
500 * Math.pow(2, count));
}
return resolve(body);
});
};
if (creatingProject) {
return new Promise((resolve, reject) => fetchProjectInfo(1, resolve, reject));
}
return body;
});
}
setScreenFromOrientation () {
/*
* If the user is on a mobile device, switching to
@ -702,6 +784,7 @@ class Preview extends React.Component {
onSocialClosed={this.handleSocialClose}
onToggleComments={this.handleToggleComments}
onToggleStudio={this.handleToggleStudio}
onUpdateProjectData={this.handleUpdateProjectData}
onUpdateProjectId={this.handleUpdateProjectId}
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
/>
@ -739,6 +822,7 @@ class Preview extends React.Component {
onSetLanguage={this.handleSetLanguage}
onShare={this.handleShare}
onToggleLoginOpen={this.props.handleToggleLoginOpen}
onUpdateProjectData={this.handleUpdateProjectData}
onUpdateProjectId={this.handleUpdateProjectId}
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
onUpdateProjectTitle={this.handleUpdateProjectTitle}

View file

@ -101,9 +101,9 @@ tap.test('clickCreditsLink', options, t => {
// JOBS
tap.test('clickJobsLink', options, t => {
const linkText = 'Jobs';
const expectedHref = '/jobs';
const expectedUrl = 'https://www.scratchfoundation.org/opportunities/';
clickFooterLinks(linkText).then(url => {
t.equal(url.substr(-expectedHref.length), expectedHref);
t.equal(url, expectedUrl);
t.end();
});
});