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', team: 'team', donate: 'donate' }; const SECTION_NAMES = { message: , mission: , reach: , milestones: , initiatives: , financials: , supporters: , team: , 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) { const sectionTop = this.getDimensionsOfSection(element).offsetTop; window.scrollTo({top: sectionTop, behavior: 'smooth'}); // The smooth scrolling doesn't work on Safari // but this code allows scrolling to the correct part of the section // in Safari since the css property 'scrollMarginTop' is also not supported there } } // 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 */}

) }} />

) }} />

) }} />

2003 {/* TODO should this be localized? */}

2004 {/* TODO should this be localized? */}

2007 {/* TODO should this be localized? */}

2008 {/* TODO should this be localized? */}

2009 {/* TODO should this be localized? */}

2009 {/* TODO should this be localized? */}

2010 {/* TODO should this be localized? */}

2013 {/* TODO should this be localized? */}

2013 {/* TODO should this be localized? */}

2014 {/* TODO should this be localized? */}

2016 {/* TODO should this be localized? */}

2017 {/* TODO should this be localized? */}

2019 {/* TODO should this be localized? */}

2019 {/* TODO should this be localized? */}

) }} />

) }} />

) }} />

) }} />

0

) }} />

{/* eslint-disable max-len */}

) }} />
) }} />

) }} />
), CSandLanguageArtsLink: ( ) }} />

), weDoLink: ( ) }} />

) }} />
) }} />

), raspberryLink: ( ) }} />

Abhi

{/* eslint-disable max-len */}

) }} />

angelical
dlore2009
qood
Mechanical_pencil

Black Lives Matter

Black Lives Matter ) }} />

{/* eslint-enable max-len */}

{/* eslint-disable max-len */} {/* eslint-enable max-len */}

{/* eslint-disable max-len */} {/* eslint-enable max-len */}

{/* eslint-disable max-len */} {/* eslint-enable max-len */}

) }} />

{/* eslint-disable max-len */} {/* eslint-enable max-len */}

{/* eslint-disable-next-line max-len */}
{/* eslint-disable-next-line max-len */}

{/* eslint-disable max-len */} Scratch al Sur ), spanishVersionLink: ( ), creativeComputingCurriculumLink: ( Creative Computing Curriculum ) }} /> {/* eslint-enable max-len */}

Scratch Conference Europe ) }} />

{/* eslint-disable-next-line max-len */}
{/* eslint-disable-next-line max-len */}

Scratch Africa Conference ) }} />


$3,898,078 (83%)

$700,000 (15%)

$114,982 (2%)

$4,713,060


$1,135,767 (49%)

$224,104 (10%)

$962,958 (41%)

$2,322,829

David Siegel


Two Sigma
{/* eslint-disable-next-line */}


  • Massachusetts Institute of Technology
  • National Science Foundation
  • Siegel Family Endowment

  • Google
  • LEGO Foundation
  • Little Bluebridge Foundation
  • Smilegate Foundation
  • TAL Education
  • WarnerMedia

  • Mark Dalton
  • Cindy and Evan Goldberg
  • Paul T. Jones
  • BrainPOP
  • Kahn-Rowe Family Fund
  • LEGO Education
  • Morgan Stanley
  • Two Sigma

  • Alex Ginsburg
  • James Tomilson Hill
  • John Overdeck
  • Mitchel Resnick
  • David Shaw
  • David Siegel
  • Tao Ye
  • Christos Zoulas
  • AT&T Aspire
  • Big Hen Group
  • Bloomberg Philanthropies
  • Citibank
  • Credit Suisse
  • EPAM
  • Facebook
  • Goldman Sachs
  • Huron Foundation
  • Intel One-to-One Institute
  • Piantino Family Foundation
  • Playmates Toys
  • Skadden Arps
  • Societe Generale
  • Solomon Wilson Family Foundation
  • Tudor Investments
  • UBS
  • Vista Equity Partners
  • Weill Family Foundation
  • WestRiver Group

  • Erik Anderson
  • Jon Claerbout
  • Jonathan Dinu
  • John Doerr
  • Dan Huttenlocher
  • Justin Nadler
  • Ali-Milan Nekmouche
  • Edward Schmidt
  • Hope Smith
  • Alfred Spector
  • Ben Stein
  • Donald Sussman
  • Glen Whitney
  • AIG
  • Amazon
  • Bank of America
  • Certified Moving & Storage
  • Dalio Foundation, Inc.
  • Dalton Family Foundation
  • Deutsche Bank
  • Ernst & Young
  • Hearst Corporation
  • HedgeServ
  • Humble Bundle
  • Intel Corporation
  • Jenner & Block LLP
  • La Vida Feliz Foundation
  • Silicon Valley Bank
  • Spin Master
  • Union Square Ventures

  • Michael Ball
  • Ken Baron
  • Craig Barrett
  • Adam Beder
  • Mark Bezos
  • Eric Chen
  • Michael Cirillo
  • Eric Dahm
  • Peter Desmond
  • Jeremy Deutsch
  • John Doyle
  • Kenneth Ehlert
  • Tim Ettenheim
  • Alan Eustace
  • Steve Evans
  • Catherine Greenspon
  • Jonathan W. Hitchon
  • Margaret Honey
  • Andrew Janian
  • David Joerg
  • Mark Loughridge
  • Carter Lyons
  • Adam Messinger
  • Robert and Bethany Millard
  • Stephen M. Ross
  • Wray Thorn
  • Jessica Traynor
  • Adobe
  • Anchor Point Foundation
  • Barclays
  • Blackstone Charitable Foundation
  • Blackstone Group
  • Cisco/Meraki
  • Citco
  • Deloitte
  • Eclipse Contracting
  • Funny or Die
  • Hasbro
  • J.P. Morgan
  • Mattel
  • McGraw Hill Education
  • NHK
  • Pearson
  • Pershing Square Foundation
  • SAP
  • Scholastic
  • The Ramsey Family Fund
  • Thelonious Monk Institute of Jazz
  • Via Technologies
  • WilmerHale
  • Zoshinkai Holdings

  • Fastly
  • Amazon Web Services
  • Wilson Sonsini Goodrich & Rosati
  • New Relic
  • Adobe
  • DK
  • No Starch Press
  • Github
  • Travis CI
  • Sauce Labs
  • Pingdom
  • PagerDuty

Mitch Resnick


MIT Media Lab

David Siegel


Two Sigma

Margaret Honey


New York Hall of Science

Christina Miller


Cartoon Network

Avraham Kadar


BrainPOP

Ursula Burns


Xerox

Sheri Vammen

Rich Sauer

); } } AnnualReport.propTypes = { intl: intlShape }; const WrappedAnnualReport = injectIntl(AnnualReport); render( , document.getElementById('app') );