const bindAll = require('lodash.bindall');
const classNames = require('classnames');
const React = require('react');
const MediaQuery = require('react-responsive').default;
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 render = require('../../lib/render.jsx');
const frameless = require('../../lib/frameless');
const Avatar = require('../../components/avatar/avatar.jsx');
const Page = require('../../components/page/www/page.jsx');
const Grid = require('../../components/grid/grid.jsx');
const Button = require('../../components/forms/button.jsx');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Comment = require('../../components/comment/comment.jsx');
const WorldMap = require('../../components/world-map/world-map.jsx');
const CountryUsage = require('./country-usage.json');
const PeopleGrid = require('../../components/people-grid/people-grid.jsx');
const People = require('./people.json');
const BLMProjects = require('./blm-projects.json');
const VideoPreview = require('../../components/video-preview/video-preview.jsx');
require('./annual-report.scss');
// Some constants used for the page subnav and section refs
const SECTIONS = {
message: 'message',
mission: 'mission',
reach: 'reach',
milestones: 'milestones',
initiatives: 'initiatives',
financials: 'financials',
supporters: 'supporters',
leadership: 'leadership',
donate: 'donate'
};
const SECTION_NAMES = {
message: ,
mission: ,
reach: ,
milestones: ,
initiatives: ,
financials: ,
supporters: ,
leadership: ,
donate:
};
// Constants used for world map data processing/formatting for use with Plotly
const countryKeys = Object.keys(CountryUsage);
const countryNames = countryKeys.map(key => CountryUsage[key].display);
const countryData = countryKeys.map(key => CountryUsage[key].count);
const colorIndex = countryKeys.map(key => CountryUsage[key]['log count']);
class AnnualReport extends React.Component {
constructor (props) {
super(props);
// Storage for each of the section refs when we need to refer
// to them in the scroll handling code
// These will be stored with a short lowercase key representing
// the specific section (e.g. 'mission')
this.sectionRefs = {};
this.subnavRef = null;
this.state = {
currentlyVisible: SECTIONS.message, // The currently visible section
dropdownVisible: false
};
bindAll(this, [
'scrollTo',
'setRef',
'setSubnavRef',
'handleSubnavItemClick',
'getDimensionsOfSection',
'handleScroll',
'handleDropDownClick'
]);
}
componentDidMount () {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnMount () {
window.removeEventListener('scroll', this.handleScroll);
}
// A generic handler for a subnav item that takes the name of the
// section to scroll to (all lowercase)
handleSubnavItemClick (sectionName) {
// Return a button click handler that will close the dropdown if open
// and scrolls to the correct section
return () => {
this.setState({dropdownVisible: false});
this.scrollTo(this.sectionRefs[sectionName]);
};
}
scrollTo (element) {
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
// Generically create a ref for the given section, stored in
// this.sectionRefs
setRef (sectionName) {
return ref => (this.sectionRefs[sectionName] = ref);
}
setSubnavRef (ref) {
this.subnavRef = ref;
}
// Calculate the dimensions of a given section for use in figuring out
// which section is currently visible
getDimensionsOfSection (sectionRef) {
const {height} = sectionRef.getBoundingClientRect();
const offsetTop = sectionRef.offsetTop;
const offsetBottom = offsetTop + height;
return {
height,
offsetTop,
offsetBottom
};
}
// While scrolling, update the subnav to reflect the currently visible section
handleScroll () {
const subnavHeight = this.getDimensionsOfSection(this.subnavRef).height;
// The additional 50 is to account for the main site nav height
const currentScrollPosition = window.scrollY + subnavHeight + 50;
// Find which section is currently visible based on our scroll position
for (const key in this.sectionRefs) {
if (!this.sectionRefs.hasOwnProperty(key)) continue;
const currentRef = this.sectionRefs[key];
const {offsetBottom, offsetTop} = this.getDimensionsOfSection(currentRef);
if (currentScrollPosition > offsetTop && currentScrollPosition < offsetBottom) {
if (this.state.currentlyVisible !== key) {
this.setState({currentlyVisible: key});
return;
}
}
}
}
// Click handler for responsive subnav dropdown
handleDropDownClick () {
this.setState({dropdownVisible: !this.state.dropdownVisible});
}
render () {
// Element containing buttons to scroll to each of the sections in the
// annual report. The layout of this component will be different on
// different screen sizes (see below)
const subnav =
(
{SECTION_NAMES.message}
);
return (
{/* Top Bar */}
{SECTION_NAMES[this.state.currentlyVisible]}
{this.state.dropdownVisible ?
/* Bottom Bar */
{subnav}
:
null
}
{/* For large screens, show whole subnav, with no dropdown */}
{subnav}
{/* Show the wave icon inside this div in smaller screens */}
)
}}
/>
)
}}
/>
Our Mission
Our mission is to provide all children, from all backgrounds, with opportunities to imagine, create, and collaborate with new technologies — so they can shape the world of tomorrow.
We are committed to prioritizing equity across all aspects of our work, with a particular focus on initiatives and approaches that support children, families, and educators furthest from educational justice.
We’ve developed Scratch as a free, safe, playful learning environment that engages all children in thinking creatively, reasoning systematically, and working collaboratively — essential skills for everyone in today's society. We work with educators and families to support children in exploring, sharing, and learning.
In developing new technologies, activities, and learning materials, we are guided by what we call the Four P’s of Creative Learning:
Projects
Engage children in designing, creating, and expressing themselves creatively
Peers
Support children in collaborating, sharing, remixing, and mentoring
Passion
Enable children to build on their interests and work on personally meaningful projects
Play
Encourage children to tinker, experiment, and iterate