Merge pull request #84 from rschamp/feature/homepage-rows-api

Pull homepage rows from the API
This commit is contained in:
Ray Schamp 2015-10-20 15:00:53 -04:00
commit 3105edc3b6
5 changed files with 187 additions and 29 deletions

14
en.json
View file

@ -17,6 +17,7 @@
"general.jobs": "Jobs",
"general.joinScratch": "Join Scratch",
"general.legal": "Legal",
"general.learnMore": "Learn More",
"general.messages": "Messages",
"general.myStuff": "My Stuff",
"general.offlineEditor": "Offline Editor",
@ -49,5 +50,16 @@
"parents.FaqAgeRangeA": "While Scratch is primarily designed for 8 to 16 year olds, it is also used by people of all ages, including younger children with their parents.",
"parents.FaqAgeRangeQ": "What is the age range for Scratch?",
"parents.FaqResourcesQ": "What resources are available for learning Scratch?",
"parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab."
"parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab.",
"splash.featuredProjects": "Featured Projects",
"splash.featuredStudios": "Featured Studios",
"splash.projectsCuratedBy": "Projects Curated by",
"splash.scratchDesignStudioTitle": "Scratch Design Studio",
"splash.visitTheStudio": "Visit the studio",
"splash.recentlySharedProjects": "Recently Shared Projects",
"splash.projectsByScratchersFollowing": "Projects by Scratchers I'm Following",
"splash.projectsLovedByScratchersFollowing": "Projects Loved by Scratchers I'm Following",
"splash.projectsInStudiosFollowing": "Projects in Studios I'm Following",
"splash.communityRemixing": "What the Community is Remixing",
"splash.communityLoving": "What the Community is Loving"
}

View file

@ -3,7 +3,8 @@
"/csrf_token/",
"/fragment/",
"/get_image/",
"/login_retry",
"/login_retry/",
"/media/",
"/session/",
"/static/"
]

View file

@ -14,6 +14,8 @@ var Carousel = React.createClass({
getDefaultProps: function () {
return {
items: require('./carousel.json'),
showRemixes: false,
showLoves: false,
settings: {
arrows: true,
dots: false,
@ -43,15 +45,17 @@ var Carousel = React.createClass({
return (
<Thumbnail key={item.id}
showLoves={this.props.showLoves}
showRemixes={this.props.showRemixes}
type={item.type}
href={href}
title={item.title}
src={item.thumbnailUrl}
src={item.thumbnail_url}
creator={item.creator}
remixes={item.remixes}
loves={item.loves} />
remixes={item.remixers_count}
loves={item.love_count} />
);
})}
}.bind(this))}
</Slider>
);
}

View file

@ -13,7 +13,9 @@ var Thumbnail = React.createClass({
href: '/projects/1000/',
title: 'Example Project',
src: 'http://www.lorempixel.com/144/108/',
type: 'project'
type: 'project',
showLoves: false,
showRemixes: false
};
},
render: function () {
@ -26,7 +28,7 @@ var Thumbnail = React.createClass({
if (this.props.creator) {
extra.push(<div key="creator" className="thumbnail-creator">by {this.props.creator}</div>);
}
if (this.props.loves) {
if (this.props.loves && this.props.showLoves) {
extra.push(
<div key="loves" className="thumbnail-loves"
title={this.props.loves + ' loves'}>
@ -34,7 +36,7 @@ var Thumbnail = React.createClass({
</div>
);
}
if (this.props.remixes) {
if (this.props.remixes && this.props.showRemixes) {
extra.push(
<div key="remixes" className="thumbnail-remixes"
title={this.props.remixes + ' remixes'}>

View file

@ -1,3 +1,4 @@
var injectIntl = require('react-intl').injectIntl;
var React = require('react');
var render = require('../../lib/render.jsx');
@ -14,7 +15,7 @@ var News = require('../../components/news/news.jsx');
require('./splash.scss');
var Splash = React.createClass({
var Splash = injectIntl(React.createClass({
type: 'Splash',
mixins: [
Api,
@ -25,21 +26,42 @@ var Splash = React.createClass({
projectCount: 10569070,
activity: [],
news: [],
featured: require('./featured.json')
featuredCustom: {},
featuredGlobal: {}
};
},
getGlobalHomepageRows: function () {
this.api({
uri: '/proxy/featured'
}, function (err, body) {
if (!err) this.setState({featuredGlobal: body});
}.bind(this));
},
getCustomHomepageRows: function () {
this.api({
uri: '/proxy/users/' + this.state.session.user.id + '/featured'
}, function (err, body) {
if (!err) this.setState({featuredCustom: body});
}.bind(this));
},
componentDidUpdate: function (prevProps, prevState) {
if (this.state.session.user != prevState.session.user && this.state.session.user) {
this.getNews();
this.getActivity();
if (this.state.session.user != prevState.session.user) {
if (this.state.session.user) {
this.getActivity();
this.getCustomHomepageRows();
this.getNews();
} else {
this.setState({featuredCustom: []});
}
}
},
componentDidMount: function () {
this.getGlobalHomepageRows();
if (this.state.session.user) {
this.getNews();
this.getActivity();
this.getCustomHomepageRows();
this.getNews();
}
// @todo API request for Featured
},
getNews: function () {
this.api({
@ -55,7 +77,133 @@ var Splash = React.createClass({
if (!err) this.setState({'activity': body});
}.bind(this));
},
renderHomepageRows: function () {
var formatMessage = this.props.intl.formatMessage;
var rows = [
<Box
title={formatMessage({
id: 'splash.featuredProjects',
defaultMessage: 'Featured Projects'})}
key="community_featured_projects">
<Carousel items={this.state.featuredGlobal.community_featured_projects} />
</Box>,
<Box
title={formatMessage({
id: 'splash.featuredStudios',
defaultMessage: 'Featured Studios'})}
key="community_featured_studios">
<Carousel items={this.state.featuredGlobal.community_featured_studios} />
</Box>
];
if (
this.state.featuredGlobal.curator_top_projects &&
this.state.featuredGlobal.curator_top_projects.length > 4) {
rows.push(
<Box
key="curator_top_projects"
title={
'Projects Curated by ' +
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} />
</Box>
);
}
if (
this.state.featuredGlobal.scratch_design_studio &&
this.state.featuredGlobal.scratch_design_studio.length > 4) {
rows.push(
<Box
key="scratch_design_studio"
title={
formatMessage({
id: 'splash.scratchDesignStudioTitle',
defaultMessage: 'Scratch Design Studio' })
+ ' - ' + 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} />
</Box>
);
}
if (this.state.session.user) {
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>
);
}
if (this.state.featuredCustom.custom_projects_by_following) {
rows.push(
<Box
title={
formatMessage({
id: 'splash.projectsByScratchersFollowing',
defaultMessage: 'Projects by Scratchers I\'m Following'})}
key="custom_projects_by_following">
<Carousel items={this.state.featuredCustom.custom_projects_by_following} />
</Box>
);
}
if (this.state.featuredCustom.custom_projects_loved_by_following) {
rows.push(
<Box
title={
formatMessage({
id: 'splash.projectsLovedByScratchersFollowing',
defaultMessage: 'Projects Loved by Scratchers I\'m Following'})}
key="custom_projects_loved_by_following">
<Carousel items={this.state.featuredCustom.custom_projects_loved_by_following} />
</Box>
);
}
if (this.state.featuredCustom.custom_projects_in_studios_following) {
rows.push(
<Box
title={
formatMessage({
id:'splash.projectsInStudiosFollowing',
defaultMessage: 'Projects in Studios I\'m Following'})}
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' })}
key="community_most_remixed_projects">
<Carousel items={this.state.featuredGlobal.community_most_remixed_projects} showRemixes={true} />
</Box>,
<Box
title={
formatMessage({
id: 'splash.communityLoving',
defaultMessage: 'What the Community is Loving' })}
key="community_most_loved_projects">
<Carousel items={this.state.featuredGlobal.community_most_loved_projects} showLoves={true} />
</Box>
);
return rows;
},
render: function () {
var featured = this.renderHomepageRows();
return (
<div className="inner">
{this.state.session.user ? [
@ -66,18 +214,9 @@ var Splash = React.createClass({
] : [
<Intro projectCount={this.state.projectCount} key="intro"/>
]}
{this.state.featured.map(function (set) {
return (
<Box
key={set.title}
className="featured"
title={set.title}
moreTitle={set.moreTitle}
moreHref={set.moreHref}>
<Carousel items={set.items} />
</Box>
);
})}
{featured}
<AdminPanel>
<dt>Tools</dt>
<dd>
@ -116,6 +255,6 @@ var Splash = React.createClass({
</div>
);
}
});
}));
render(<Splash />, document.getElementById('view'));