Commit 78649b69 authored by Ray Schamp's avatar Ray Schamp

Merge pull request #353 from morantsur/feature/microworlds

Moving Microworlds pages to scratch-www & adding arts
parents ea04658b 99772ca4
var React = require('react');
require('./microworld.scss');
var Box = require('../../components/box/box.jsx');
var Carousel = require('../../components/carousel/carousel.jsx');
var Modal = require('../../components/modal/modal.jsx');
var NestedCarousel = require('../../components/nestedcarousel/nestedcarousel.jsx');
var Microworld = React.createClass({
type: 'Microworld',
propTypes: {
microworldData: React.PropTypes.node.isRequired
},
markVideoOpen: function (key) {
{/* When a video is clicked, mark it as an open video, so the video Modal will open.
Key is the number of the video, so distinguish between different videos on the page */}
var videoOpenArr = this.state.videoOpen;
videoOpenArr[key] = true;
this.setState({videoOpen: videoOpenArr});
},
markVideoClosed: function (key) {
{/* When a video's x is clicked, mark it as closed, so the video Modal will disappear.
Key is the number of the video, so distinguish between different videos on the page */}
var videoOpenArr = this.state.videoOpen;
videoOpenArr[key] = false;
this.setState({videoOpen: videoOpenArr});
},
getInitialState: function () {
return {
videoOpen: {}
};
},
renderVideos: function () {
var videos = this.props.microworldData.videos;
if (!videos || videos.length <= 0) {
return null;
}
return (
<div className="videos-section section">
<h1>Get Inspired...</h1>
<div className="videos-container">
<div className="videos">
{videos.map(this.renderVideo)}
</div>
</div>
</div>
);
},
renderVideo: function (video, key) {
var frameProps = {
width: 570,
height: 357,
padding: 15
};
return (
<div>
<div className="video">
<div className="play-button" onClick={this.markVideoOpen.bind(this, key)}>
</div>
<img src={video.image} />
</div>
<Modal
className="video-modal"
isOpen={this.state.videoOpen[key]}
onRequestClose={this.markVideoClosed.bind(this, key)}
style={{content:frameProps}}>
<iframe src={video.link} width="560" height="315" frameBorder="0"
webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</Modal>
</div>
);
},
renderEditorWindow: function () {
var projectId = this.props.microworldData.microworld_project_id;
if (!projectId) {
return null;
}
return (
<div className="editor section">
<h1>Start Creating!</h1>
<a href={'//scratch.mit.edu/projects/'+ projectId +'/#editor'}>
<img className="scratch-link" src="/images/scratch-og.png"></img>
</a>
<iframe src={'//scratch.mit.edu/projects/embed-editor/' + projectId + '/?isMicroworld=true'}
frameBorder="0"> </iframe>
{this.renderTips()}
</div>
);
},
renderTips: function () {
var tips = this.props.microworldData.tips;
if (!tips || tips.length <= 0) {
return null;
}
return (
<div className="box nestedcarousel">
<div className="box-header">
</div>
<div className="box-content">
<NestedCarousel items={tips} settings={{slidesToShow:1,slidesToScroll:1}}/>
</div>
</div>
);
},
renderStarterProject: function () {
var starterProjects = this.props.microworldData.starter_projects;
if (!starterProjects || starterProjects.length <= 0){
return null;
}
return (
<div className="project-ideas">
<h1>Check out ideas for more projects</h1>
<Box
title="More Starter Projects"
key="starter_projects">
<Carousel items={starterProjects} />
</Box>
</div>
);
},
renderProjectIdeasBox: function () {
var communityProjects = this.props.microworldData.community_projects;
if (!communityProjects || communityProjects.size <= 0) {
return null;
}
var featured = communityProjects.featured_projects;
var all = communityProjects.newest_projects;
var rows = [];
if (featured && featured.length > 0){
rows.push(
<Box
title="Featured Community Projects"
key="community_featured_projects">
<Carousel items={featured} />
</Box>
);
}
if (all && all.length > 0) {
rows.push(
<Box
title="All Community Projects"
key="community_all_projects">
<Carousel items={all} />
</Box>
);
}
if (rows.length <= 0) {
return null;
}
return (
<div className="project-ideas">
<h1>Get inspiration from other projects</h1>
{rows}
</div>
);
},
renderForum: function () {
if (!this.props.microworldData.show_forum) {
return null;
}
return (
<div className="forum">
<h1>Chat with others!</h1>
<img src="/images/forum-image.png"/>
</div>
);
},
renderDesignStudio: function () {
var designChallenge = this.props.microworldData.design_challenge;
if (!designChallenge) {
return null;
}
if (designChallenge.studio_id) {
var studioHref = 'https://scratch.mit.edu//studios/' + designChallenge.studio_id + '/';
}
if (designChallenge.project_id) {
return (
<div className="side-by-side section">
<h1>Join our Design Challenge!</h1>
<div className="design-studio">
<iframe src={'https://scratch.mit.edu/projects/' + designChallenge.project_id +
'/#fullscreen'} frameBorder="0"> </iframe>
</div>
<div className="design-studio-projects">
<Box title="Examples"
key="scratch_design_studio"
moreTitle={studioHref ? 'Visit the studio' : null}
moreHref={studioHref ? studioHref : null}>
{/* The two carousels are used to show two rows of projects, one above the
other. This should be probably be changed, to allow better scrolling. */}
<Carousel settings={{slidesToShow:2,slidesToScroll:2}}
items={this.props.microworldData.design_challenge.studio1} />
<Carousel settings={{slidesToShow:2,slidesToScroll:2}}
items={this.props.microworldData.design_challenge.studio2} />
</Box>
</div>
</div>
);
} else {
return (
<div className="section">
<h1>Join our Design Challenge!</h1>
<Box
title="design Challenge Projects"
key="scratch_design_studio"
moreTitle={studioHref ? 'Visit the studio' : null}
moreHref={studioHref ? studioHref : null}>
<Carousel items={this.props.microworldData.design_challenge.studio1.concat(
this.props.microworldData.design_challenge.studio2)} />
</Box>
</div>
);
}
},
render: function () {
return (
<div className="inner">
<div className="top-banner section">
<h1>{this.props.microworldData.title}</h1>
<p>{this.props.microworldData.description.join(' ')}</p>
</div>
{this.renderVideos()}
<div className="content">
{this.renderEditorWindow()}
{this.renderStarterProject()}
{this.renderDesignStudio()}
{this.renderProjectIdeasBox()}
{this.renderForum()}
</div>
</div>
);
}
});
module.exports = Microworld;
@import "../../colors";
@import "../../frameless";
$base-bg: $ui-white;
#view {
background-color: $base-bg;
padding: 0;
// To be integrated into the Global Typography standards
h3,
p {
font-weight: 300;
}
p {
line-height: 2em;
}
h1 {
margin: 0 auto;
padding: 5px 10%;
text-align: center;
color: $type-gray;
}
.top-banner,
.videos-section,
.section {
padding: 30px 0;
width: 100%;
h1,
p {
margin: 0 auto;
padding: 5px 10%;
text-align: center;
color: $type-gray;
}
}
.videos-container {
display: flex;
margin: 0 auto;
justify-content: center;
flex-wrap: wrap;
align-items: center;
.videos {
display: inline-flex;
justify-content: center;
flex-wrap: wrap;
}
.video {
position: relative;
margin: 10px;
border-radius: 7px;
background-color: $active-gray;
padding: 2px;
max-width: 290px;
}
img {
margin: 10px 10px 5px;
border-radius: 5px;
width: calc(100% - 20px);
height: 179px;
}
.play-button {
display: block;
top: calc(50% - 25px);
left: calc(50% - 35px);
opacity: .8;
border: 5px solid $ui-border;
border-radius: 20px;
background-color: $type-gray;
width: 70px;
height: 50px;
&,
&:after {
position: absolute;
margin: 0;
cursor: pointer;
padding: 0;
}
&:after {
$play-arrow: rgba(255, 255, 255, 0);
top: 37px;
left: 28px;
margin-top: -30px;
border: solid transparent;
border-width: 18px;
border-color: $play-arrow;
border-left-color: $ui-white;
width: 0;
height: 0;
content: " ";
pointer-events: none;
}
}
}
.content {
img {
display: block;
margin-right: auto;
margin-left: auto;
}
.box,
iframe {
display: block;
margin-right: auto;
margin-left: auto;
border: 0;
padding-top: 25px;
padding-bottom: 15px;
}
iframe {
height: 600px;
}
.editor {
position: relative;
iframe {
width: 100%;
}
.scratch-link {
position: absolute;
right: 3%;
width: 10%;
}
}
.side-by-side {
margin-right: auto;
margin-left: auto;
height: 520px;
.design-studio-projects,
.design-studio {
display: inline-block;
width: 45%;
height: 500px;
}
.design-studio-projects {
float: right;
}
.design-studio {
float: left;
iframe {
margin-top: 60px;
width: 200%;
-webkit-transform: scale(.5);
-webkit-transform-origin: top left;
-moz-transform: scale(.5);
}
}
}
}
.box-content {
.nestedcarousel {
text-align: center;
.thumbnail {
display: inline-block;
margin: 0 50px;
}
}
}
}
[
{
"title":"Start Dancing",
"thumbnails":[
{
"type":"tip",
"title":"First, select a sprite",
"thumbnailUrl":"/images/microworlds/hiphop/dancer-sprite.png"
},
{
"type":"tip",
"title":"Then, try this script",
"thumbnailUrl":"/images/microworlds/hiphop/switch-wait.gif"
},
{
"type":"tip",
"title":"Start it!",
"thumbnailUrl":"/images/microworlds/hiphop/green-flag.gif"
}
]
},
{
"title":"Repeat the Dance",
"thumbnails":[
{
"type":"tip",
"title":"Add another \"wait\"",
"thumbnailUrl":"/images/microworlds/hiphop/add-wait.gif"
},
{
"type":"tip",
"title":"Drag this block over",
"thumbnailUrl":"/images/microworlds/hiphop/add-repeat.gif"
},
{
"type":"tip",
"title":"Start it",
"thumbnailUrl":"/images/microworlds/hiphop/green-flag.gif"
}
]
}
]
\ No newline at end of file
var classNames = require('classnames');
var defaults = require('lodash.defaults');
var React = require('react');
var Slider = require('react-slick');
var Thumbnail = require('../thumbnail/thumbnail.jsx');
require('slick-carousel/slick/slick.scss');
require('slick-carousel/slick/slick-theme.scss');
require('./nestedcarousel.scss');
{/*
NestedCarousel is used to show a carousel, where each slide is composed of a few
thumbnails (for example, to show step-by-syep tips, where each stage has a few steps).
It creates the thumbnails without links.
Each slide has a title, and then a list of thumbnails, that will be shown together.
*/}
var NestedCarousel = React.createClass({
type: 'NestedCarousel',
propTypes: {
items: React.PropTypes.array
},
getDefaultProps: function () {
return {
items: require('./nestedcarousel.json')
};
},
render: function () {
var settings = this.props.settings || {};
defaults(settings, {
dots: true,
infinite: false,
lazyLoad: true,
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: false
});
var arrows = this.props.items.length > settings.slidesToShow;
var classes = classNames(
'nestedcarousel',
'carousel',
this.props.className
);
var stages = [];
for (var i=0; i < this.props.items.length; i++) {
var items = this.props.items[i].thumbnails;
var thumbnails = [];
for (var j=0; j < items.length; j++) {
var item = items[j];
thumbnails.push(
<Thumbnail key={'inner_' + i + '_' + j}
title={item.title}
src={item.thumbnailUrl}
linkTitle = {false} />);
}
stages.push(
<div key={'outer_' + i}>
<h3>{this.props.items[i].title}</h3>
{thumbnails}
</div>);
}
return (
<Slider className={classes} arrows={arrows} {... settings}>
{stages}
</Slider>
);
}
});
module.exports = NestedCarousel;
@import "../../colors";
@import "../carousel/carousel.scss";
.nestedcarousel {
/* Overrides carousel's settings for extra padding */
.slick-slide {
padding: 0;
/* Add some padding under the title for each slide */
h3 {
padding-bottom: 10px;
}
/* Align to top. Important when one of the slides have
more than one line of text */
.thumbnail.project {
vertical-align: top;
}
}
}
...@@ -16,6 +16,7 @@ var Thumbnail = React.createClass({ ...@@ -16,6 +16,7 @@ var Thumbnail = React.createClass({
type: 'project', type: 'project',
showLoves: false, showLoves: false,
showRemixes: false, showRemixes: false,
linkTitle: true,
alt: '' alt: ''
}; };
}, },
...@@ -55,13 +56,23 @@ var Thumbnail = React.createClass({ ...@@ -55,13 +56,23 @@ var Thumbnail = React.createClass({
</div> </div>
); );
} }
var imgElement,titleElement;
if (this.props.linkTitle) {
imgElement = <a className="thumbnail-image" href={this.props.href}>
<img src={this.props.src} alt={this.props.alt} />
</a>;
titleElement = <a href={this.props.href}>{this.props.title}</a>;
} else {
imgElement = <img src={this.props.src} />;
titleElement = this.props.title;
}
return ( return (
<div className={classes} > <div className={classes} >
<a className="thumbnail-image" href={this.props.href}> {imgElement}
<img src={this.props.src} alt={this.props.alt} />
</a>
<div className="thumbnail-title"> <div className="thumbnail-title">
<a href={this.props.href}>{this.props.title}</a> {titleElement}
</div> </div>
{extra} {extra}
</div> </div>
......
This diff is collapsed.
var render = require('../../lib/render.jsx');
var Microworld = require('../../components/microworld/microworld.jsx');
var microworldData = require('./microworld_art.json');
render(<Microworld microworldData={microworldData} />, document.getElementById('view'));
This diff is collapsed.
var render = require('../../lib/render.jsx');
var Microworld = require('../../components/microworld/microworld.jsx');
var microworldData = require('./microworld_fashion.json');
render(<Microworld microworldData={microworldData} />, document.getElementById('view'));
This diff is collapsed.
var render = require('../../lib/render.jsx');
var Microworld = require('../../components/microworld/microworld.jsx');
var microworldData = require('./microworld_hiphop.json');
render(<Microworld microworldData={microworldData} />, document.getElementById('view'));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment