const bindAll = require('lodash.bindall');
const classNames = require('classnames');
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 React = require('react');
const Button = require('../../components/forms/button.jsx');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Comment = require('../../components/comment/comment.jsx');
const People = require('./people.json');
const PeopleGrid = require('../../components/people-grid/people-grid.jsx');
const WorldMap = require('../../components/world-map/world-map.jsx');
const CountryUsage = require('./country-usage.json');
const Page = require('../../components/page/www/page.jsx');
const render = require('../../lib/render.jsx');
const MediaQuery = require('react-responsive').default;
const frameless = require('../../lib/frameless');
require('./annual-report.scss');
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:
};
const countryNames = Object.keys(CountryUsage);
const countryData = countryNames.map(key => CountryUsage[key].count);
const colorIndex = countryNames.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,
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 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'
});
}
}
setRef (sectionName) {
return ref => (this.sectionRefs[sectionName] = ref);
}
setSubnavRef (ref) {
this.subnavRef = ref;
}
getDimensionsOfSection (sectionRef) {
const {height} = sectionRef.getBoundingClientRect();
const offsetTop = sectionRef.offsetTop;
const offsetBottom = offsetTop + height;
return {
height,
offsetTop,
offsetBottom
};
}
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;
}
}
}
}
handleDropDownClick () {
this.setState({dropdownVisible: !this.state.dropdownVisible});
}
render () {
const subnav = (
{SECTION_NAMES.message}
);
return (
{/* Top Bar */}
{SECTION_NAMES[this.state.currentlyVisible]}
{this.state.dropdownVisible ?
/* Bottom Bar */
{subnav}
:
null
}
{/* Bottom Bar */}
{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? */}
David Siegel
Two Sigma
{/* eslint-disable-next-line */}
- Amazon Web Services
- Fastly
- New Relic
Mitch Resnick
MIT Media Lab
David Siegel
Two Sigma
Margaret Honey
Two Sigma
Christina Miller
Cartoon Network
Avraham Kadar
BrainPOP
Sheri Vammen
Rich Sauer
);
}
}
AnnualReport.propTypes = {
intl: intlShape
};
const WrappedAnnualReport = injectIntl(AnnualReport);
render(
, document.getElementById('app')
);