diff --git a/README.md b/README.md index 9119d000..fc598548 100644 --- a/README.md +++ b/README.md @@ -72,4 +72,4 @@ The app can then be run by any web server. **When building the site for deployment provide the base url trough the `BASEURL` environment variable. Omit the leading slash. (E.g. https://example.com)** # License -This project is licensed under **The MIT License (MIT)**, see the [LICENSE](LICENSE.md) file for more details. +This project is licensed under **Apache 2**, see the [LICENSE](LICENSE) file for more details. diff --git a/app/assets/graphics/content/co2_april_1_20.png b/app/assets/graphics/content/co2_april_1_20.png new file mode 100644 index 00000000..c38deab1 Binary files /dev/null and b/app/assets/graphics/content/co2_april_1_20.png differ diff --git a/app/assets/graphics/content/la-port.png b/app/assets/graphics/content/la-port.png index a87bbcce..b2a747d5 100644 Binary files a/app/assets/graphics/content/la-port.png and b/app/assets/graphics/content/la-port.png differ diff --git a/app/assets/graphics/content/no2_south_america.png b/app/assets/graphics/content/no2_south_america.png index 1e239b62..8ad7d10e 100644 Binary files a/app/assets/graphics/content/no2_south_america.png and b/app/assets/graphics/content/no2_south_america.png differ diff --git a/app/assets/graphics/content/water-quality-chlorophyll-a-sf.png b/app/assets/graphics/content/water-quality-chlorophyll-a-sf.png index 47c46743..1409d3a2 100644 Binary files a/app/assets/graphics/content/water-quality-chlorophyll-a-sf.png and b/app/assets/graphics/content/water-quality-chlorophyll-a-sf.png differ diff --git a/app/assets/icons/collecticons/speech-balloon.svg b/app/assets/icons/collecticons/speech-balloon.svg new file mode 100755 index 00000000..aa8475be --- /dev/null +++ b/app/assets/icons/collecticons/speech-balloon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/assets/scripts/components/common/share.js b/app/assets/scripts/components/common/copy-field.js similarity index 55% rename from app/assets/scripts/components/common/share.js rename to app/assets/scripts/components/common/copy-field.js index d688b65c..23520c1e 100644 --- a/app/assets/scripts/components/common/share.js +++ b/app/assets/scripts/components/common/copy-field.js @@ -1,25 +1,11 @@ import React from 'react'; import { PropTypes as T } from 'prop-types'; import styled from 'styled-components'; -import { withRouter } from 'react-router-dom'; import Clipboard from 'clipboard'; import Button from '../../styles/button/button'; -import Dropdown, { - DropTitle, - DropMenu, - DropInset, - DropMenuItem -} from './dropdown'; import Form from '../../styles/form/form'; import FormInput from '../../styles/form/input'; -import collecticon from '../../styles/collecticons'; - -const ShareIconMenu = styled(DropMenuItem)` - :before { - ${({ useIcon }) => collecticon(useIcon)} - } -`; const FormInputGroup = styled.div` display: grid; @@ -36,60 +22,9 @@ const FormInputGroup = styled.div` } `; -class ShareOptions extends React.Component { - render () { - const url = window.location.toString(); - return ( - - Share - - } - > - Share - -
  • - - Facebook - -
  • -
  • - - Twitter - -
  • -
    - - - -
    - ); - } -} - -export default withRouter(ShareOptions); - // This needs to be a separate class because of the mount and unmount methods. // The dropdown unmounts when closed and the refs would be lost otherwise. -class CopyField extends React.Component { +export class CopyField extends React.Component { constructor (props) { super(props); this.state = { @@ -140,7 +75,7 @@ class CopyField extends React.Component { this.triggerEl = el; }} > - Copy to clipboard + Copy to clipboard diff --git a/app/assets/scripts/components/common/layers/layer-detection-ship.js b/app/assets/scripts/components/common/layers/layer-detection-ship.js index 03c60db5..66e92903 100644 --- a/app/assets/scripts/components/common/layers/layer-detection-ship.js +++ b/app/assets/scripts/components/common/layers/layer-detection-ship.js @@ -16,7 +16,7 @@ export default { raster: { type: 'raster', tiles: [ - `${config.api}/{z}/{x}/{y}@1x?url=s3://covid-eo-data/planet/{spotlightId}_{date}.tif&resampling_method=nearest&bidx=1,2,3` + `${config.api}/{z}/{x}/{y}@1x?url=s3://covid-eo-data/planet/{spotlightId}-{date}.tif&resampling_method=nearest&bidx=1,2,3` ] } }, diff --git a/app/assets/scripts/components/common/layers/layer-no2.js b/app/assets/scripts/components/common/layers/layer-no2.js index 5c04eb68..ee410874 100644 --- a/app/assets/scripts/components/common/layers/layer-no2.js +++ b/app/assets/scripts/components/common/layers/layer-no2.js @@ -9,15 +9,18 @@ export default { name: 'Nitrogen dioxide', type: 'raster-timeseries', domain: [ - '2019-03-01', - '2020-03-01' + '2018-03-01', + '2020-04-01' ], source: { type: 'raster', tiles: [ - `${config.api}/{z}/{x}/{y}@1x?url=s3://covid-eo-data/OMNO2d_HRM/OMI_trno2_0.10x0.10_{date}_Col3_V4.nc.tif&resampling_method=bilinear&bidx=1&rescale=0%2C1e16&color_map=custom_no2&color_formula=gamma r {gamma}` + `${config.api}/{z}/{x}/{y}@1x?url=s3://covid-eo-data/OMNO2d_HRM/OMI_trno2_0.10x0.10_{date}_Col3_V4.nc.tif&resampling_method=bilinear&bidx=1&rescale=0%2C1.5e16&color_map=custom_no2&color_formula=gamma r {gamma}` ] }, + paint: { + 'raster-opacity': 0.75 + }, exclusiveWith: ['co2', 'co2-diff', 'gibs-population', 'car-count', 'nightlights-viirs', 'nightlights-hd', 'detection-ship', 'detection-multi', 'water-chlorophyll', 'water-spm'], enabled: true, compare: { diff --git a/app/assets/scripts/components/common/layers/types.js b/app/assets/scripts/components/common/layers/types.js index ec0934a9..74d4fae6 100644 --- a/app/assets/scripts/components/common/layers/types.js +++ b/app/assets/scripts/components/common/layers/types.js @@ -74,7 +74,7 @@ export const layerTypes = { 'raster-timeseries': { update: (ctx, layerInfo, prevProps) => { const { mbMap, mbMapComparing, mbMapComparingLoaded, props } = ctx; - const { id, source, compare } = layerInfo; + const { id, source, compare, paint } = layerInfo; const prevLayerInfo = prevProps.layers.find(l => l.id === layerInfo.id); const { date, comparing } = props; @@ -119,7 +119,8 @@ export const layerTypes = { { id: id, type: 'raster', - source: id + source: id, + paint: paint || {} }, 'admin-0-boundary-bg' ); @@ -135,7 +136,7 @@ export const layerTypes = { }, show: (ctx, layerInfo) => { const { mbMap, props } = ctx; - const { id, source } = layerInfo; + const { id, source, paint } = layerInfo; const { date } = props; if (!date) return; @@ -147,7 +148,8 @@ export const layerTypes = { { id: id, type: 'raster', - source: id + source: id, + paint: paint || {} }, 'admin-0-boundary-bg' ); @@ -190,6 +192,17 @@ export const layerTypes = { const rastId = `${id}-raster`; const { vector, raster } = source; + // Do not update if: + if ( + // There's no date defined. + prevProps.date && date && + // Dates are the same + date.getTime() === prevProps.date.getTime() + ) return; + + // The source we're updating is not present. + if (!mbMap.getSource(id)) return; + const formatDate = format(utcDate(date), dateFormats[layerInfo.timeUnit]); const vectorData = vector.data.replace('{date}', formatDate); const rasterTiles = raster.tiles.map(tile => tile.replace('{date}', formatDate)); diff --git a/app/assets/scripts/components/common/page-footer.js b/app/assets/scripts/components/common/page-footer.js index efe0d27d..889da899 100644 --- a/app/assets/scripts/components/common/page-footer.js +++ b/app/assets/scripts/components/common/page-footer.js @@ -125,7 +125,7 @@ const PageFooter = props => {
    NASA official
    - {this.state.panelOpen && } - - - - Menu + {this.state.panelOpen && } + + {isMediumDown && ( + + )} + + + + + Menu + {isMediumDown && ( + + )} + + + +
  • - - - -
  • - -
  • -
  • - -
  • -
  • - -
  • - - + +
  • + -
  • -
  • - -
  • - {spotlightAreas && - spotlightAreas.map((ss) => ( -
  • + + + Explore + +
  • - ))} - - - Indicators - -
  • - -
  • - {indicatorsList - .filter((d) => !!d.LongForm) - .map((d) => ( -
  • - -
  • - ))} -
    - -
    -
    - - ) : ( - - -
  • - -
  • -
  • - - Explore - - } - > - Explore - -
  • - - Global - -
  • - {spotlightAreas && - spotlightAreas.map((ss) => ( -
  • - - {ss.label} - -
  • - ))} - - -
  • - - About - -
  • -
    - - -
  • - - Indicators - - } - > - Indicators - - {indicatorsList - .filter((d) => !!d.LongForm) - .map((d) => ( -
  • - - {d.name} - -
  • - ))} - - -
  • - - About - -
  • -
    - - -
  • - -
  • -
  • - -
  • -
  • - -
  • -
    -
    - )} + {spotlightAreas && + spotlightAreas.map((ss) => ( +
  • + +
  • + ))} + + + +
  • + + + Indicators + + {indicatorsList + .filter((d) => !!d.LongForm) + .map((d) => ( +
  • + +
  • + ))} + + + +
  • + +
  • +
  • + +
  • + + + + Share + +
  • + +
  • +
  • + +
  • +
    + + + +
    +
    + + + + ); diff --git a/app/assets/scripts/components/common/summary-expandable.js b/app/assets/scripts/components/common/summary-expandable.js new file mode 100644 index 00000000..f0197f88 --- /dev/null +++ b/app/assets/scripts/components/common/summary-expandable.js @@ -0,0 +1,69 @@ +import React, { Component } from 'react'; +import { PropTypes as T } from 'prop-types'; +import styled, { css } from 'styled-components'; + +import Button from '../../styles/button/button'; +import { glsp } from '../../styles/utils/theme-values'; + +const SummarySelf = styled.section` + padding: ${glsp()}; +`; + +const SummaryContent = styled.div` + position: relative; + overflow: hidden; + margin-bottom: ${glsp(0.5)}; + transition: max-height 320ms ease-in-out, opacity 320ms ease-in-out; + max-height: ${({ isExpanded }) => (isExpanded ? '400vh' : '6rem')}; + + > *:not(:last-child) { + margin-bottom: ${glsp()}; + } + + ${({ isExpanded }) => !isExpanded && css` + ::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + height: 1rem; + width: 100%; + background: linear-gradient(to top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); + } + `} +`; + +class SummaryExpandable extends Component { + constructor (props) { + super(props); + + this.state = { + isExpanded: false + }; + } + + render () { + const { children, className } = this.props; + const { isExpanded } = this.state; + + return ( + + {children} + + + ); + } +} + +SummaryExpandable.propTypes = { + className: T.string, + children: T.node +}; + +export default SummaryExpandable; diff --git a/app/assets/scripts/components/development/index.js b/app/assets/scripts/components/development/index.js index 1df8d631..572e68db 100644 --- a/app/assets/scripts/components/development/index.js +++ b/app/assets/scripts/components/development/index.js @@ -12,12 +12,40 @@ import { } from '../../styles/inpage'; import Constrainer from '../../styles/constrainer'; import Prose from '../../styles/type/prose'; +import Button from '../../styles/button/button'; import { glsp } from '../../styles/utils/theme-values'; +import media from '../../styles/utils/media-queries'; + +const ContributeCta = styled.div` + display: grid; + grid-gap: ${glsp()}; + grid-template-columns: repeat(12, 1fr); + + > * { + grid-column: auto / span 12; + } + + ${media.mediumUp` + > * { + grid-column: auto / span 4; + } + `} + + ${media.largeUp` + > * { + grid-column: auto / span 3; + } + `} +`; const PageConstrainer = styled(Constrainer)` - ${Prose} { + ${Prose}${Prose} { max-width: 50rem; + + ${media.largeUp` + margin-bottom: ${glsp(3)}; + `} } > *:not(:last-child) { @@ -46,10 +74,28 @@ export default class Development extends React.Component {

    We welcome your feedback to help improve the Dashboard.

    -

    - Link to Github. -

    + + + + diff --git a/app/assets/scripts/components/global/sec-panel.js b/app/assets/scripts/components/global/sec-panel.js index 22072dfa..dce9e5fb 100644 --- a/app/assets/scripts/components/global/sec-panel.js +++ b/app/assets/scripts/components/global/sec-panel.js @@ -13,7 +13,14 @@ import ShadowScrollbar from '../common/shadow-scrollbar'; import { glsp } from '../../styles/utils/theme-values'; import { utcDate } from '../../utils/utils'; -import { isLargeViewport } from '../../styles/utils/media-queries'; +import media, { isLargeViewport } from '../../styles/utils/media-queries'; +import SummaryExpandable from '../common/summary-expandable'; + +const PanelSelf = styled(Panel)` + ${media.largeUp` + width: 30rem; + `} +`; const BodyScroll = styled(ShadowScrollbar)` flex: 1; @@ -68,7 +75,7 @@ class ExpMapSecPanel extends React.Component { render () { return ( - + +

    As communities around the world have changed their behavior in response to the spread of novel coronavirus, NASA satellites have observed associated changes in the environment.

    +

    Use the dashboard to interact with real NASA data and investigate how social distancing measures and regional shelter-in-place guidelines have affected Earth’s air, land, and water.

    +

    Explore global changes in nitrogen dioxide (NO2), a common air pollutant, and carbon dioxide (CO2), a potent greenhouse gas, on the worldwide map, or see how localized changes in water quality, nightlights, and other economic indicators for specific spotlight areas may have been influenced by changes in our behavior due to COVID-19.

    +

    This experimental dashboard will continue to evolve as more data become available.

    +
    {this.renderContent()} diff --git a/app/assets/scripts/components/home/index.js b/app/assets/scripts/components/home/index.js index d77211dc..cb732736 100644 --- a/app/assets/scripts/components/home/index.js +++ b/app/assets/scripts/components/home/index.js @@ -206,7 +206,7 @@ const IntroStories = styled.section` padding: ${glsp(0.75, 1, 1.25, 1)}; ${media.smallUp` - min-height: 12rem; + min-height: 7.5rem; `} ${media.mediumUp` @@ -216,7 +216,7 @@ const IntroStories = styled.section` &::before { ${collecticon('chart-bars')} - font-size: 8rem; + font-size: 6rem; line-height: 1; opacity: 0.16; position: absolute; diff --git a/app/assets/scripts/components/indicators/indicator-co2.js b/app/assets/scripts/components/indicators/indicator-co2.js index 9cb5e189..5e3f74a4 100644 --- a/app/assets/scripts/components/indicators/indicator-co2.js +++ b/app/assets/scripts/components/indicators/indicator-co2.js @@ -4,14 +4,16 @@ import styled from 'styled-components'; import Prose from '../../styles/type/prose'; import Gridder from '../../styles/gridder'; import InpageHGroup from '../../styles/inpage-hgroup'; +import MediaImage from '../../styles/media-image'; import { Fold, FoldDetails } from '../../styles/fold'; -import { - IntroLead -} from '../../styles/datasets'; +import { IntroLead } from '../../styles/datasets'; import media from '../../styles/utils/media-queries'; import { glsp } from '../../styles/utils/theme-values'; import Heading from '../../styles/type/heading'; +import config from '../../config'; + +const { baseUrl } = config; const LeadFold = styled(Fold)` padding-bottom: 0; @@ -30,15 +32,14 @@ const IntroFold = styled(Fold)` ${FoldDetails} { grid-column: content-start / content-end; - - ${media.mediumUp` - grid-column: content-start / content-8; - `} - - ${media.largeUp` - grid-column: content-start / content-10; - `} } + + ${media.largeUp` + ${Prose} { + column-count: 2; + column-gap: ${glsp(2)}; + } + `} `; const ResearchFold = styled(Fold)` @@ -78,6 +79,26 @@ const InterpretDataFold = styled(Fold)` align-items: center; } + ${MediaImage} { + grid-column: full-start / full-end; + + ${media.mediumUp` + grid-column: content-start / content-end; + `} + + ${media.largeUp` + grid-column: full-start / content-7; + grid-row: 1; + `} + + figcaption { + padding: 0 ${glsp()}; + max-width: 30rem; + text-align: center; + margin: 0 auto; + } + } + ${FoldDetails} { grid-column: content-start / content-end; @@ -86,7 +107,7 @@ const InterpretDataFold = styled(Fold)` `} ${media.largeUp` - grid-column: content-start / content-10; + grid-column: content-8 / content-end; `} } `; @@ -138,7 +159,7 @@ const FactsFold = styled(Fold)` ${Prose} { grid-column: content-start / content-end; - + ${media.mediumUp` grid-column: content-start / content-8; `} @@ -162,8 +183,10 @@ class CO2LongForm extends React.Component { - Reductions in carbon dioxide (CO2) emissions due to COVID-19 shutdowns are expected to reduce the rate at which CO2 accumulates in the atmosphere, but not its total atmospheric concentration. - + Reductions in carbon dioxide (CO2) emissions due to + COVID-19 shutdowns are expected to reduce the rate at which CO + 2 accumulates in the atmosphere, but not its total + atmospheric concentration. @@ -172,22 +195,54 @@ class CO2LongForm extends React.Component { -

    - Reductions in carbon dioxide (CO2) emissions due to COVID-19 shutdowns are expected to reduce the rate at which CO2 accumulates in the atmosphere, but not its total atmospheric concentration. + Reductions in carbon dioxide (CO2) emissions due to + COVID-19 shutdowns are expected to reduce the rate at which CO + 2 accumulates in the atmosphere, but not its total + atmospheric concentration.

    - - Carbon dioxide (CO2) is a greenhouse gas primarily emitted from the combustion of fossil fuels such as petroleum, coal, and natural gas. Scientists widely agree that the build-up of excess carbon dioxide and other greenhouse gases within Earth’s atmosphere has contributed to the rapid change in global climate. + Carbon dioxide (CO2) is a greenhouse gas primarily + emitted from the combustion of fossil fuels such as petroleum, + coal, and natural gas.{' '} + + Scientists widely agree{' '} + + that the build-up of excess carbon dioxide and other + greenhouse gases within Earth’s atmosphere has contributed to + the rapid change in global climate.

    - - During lockdowns and in response to other social distancing measures throughout the COVID-19 pandemic, there have been significant but temporary reductions in CO2 emissions. These reductions are accompanied by comparable reductions in short-lived air pollutants, such as nitrogen dioxide (NO2). While fossil fuel combustion emits far more CO2 than NO2, scientists anticipate much smaller changes in the atmospheric concentration of CO2 due to its larger atmospheric abundance, relatively long lifespan, and role of trees and other plants in its seasonal absorption. + During lockdowns and in response to other social distancing + measures throughout the COVID-19 pandemic, there have been + significant but temporary reductions in CO2{' '} + emissions. These reductions are accompanied by comparable + reductions in short-lived air pollutants, such as{' '} + + nitrogen dioxide (NO2) + + . While fossil fuel combustion emits far more CO2{' '} + than NO2, scientists anticipate much smaller + changes in the atmospheric concentration of CO2 due + to its larger atmospheric abundance, relatively long lifespan, + and role of trees and other plants in its seasonal absorption.

    - Because of this, regional-scale changes in CO2 concentrations are expected to be no larger than 1 part per million (ppm), out of the 415 ppm CO2 background – a change of only 0.25%. The longer-term implications of this temporary reduction will take time and rigorous scientific study to fully understand. + Because of this, regional-scale changes in CO2{' '} + concentrations are expected to be no larger than 1 part per + million (ppm), out of the 415 ppm CO2 background – + a change of only 0.25%. The longer-term implications of this + temporary reduction will take time and rigorous scientific + study to fully understand.

    -
    @@ -201,15 +256,44 @@ class CO2LongForm extends React.Component { />

    - To track the changes in atmospheric CO2 during COVID-19 shutdowns, researchers are using observations from the NASA Orbiting Carbon Observatory 2 (OCO-2) and Japan’s Greenhouse gases Observing SATellite (GOSAT). + To track the changes in atmospheric CO2 during + COVID-19 shutdowns, researchers are using observations from the{' '} + + NASA Orbiting Carbon Observatory 2 (OCO-2) + {' '} + and{' '} + + Japan’s Greenhouse gases Observing SATellite (GOSAT) + + .

    - OCO-2 and GOSAT provide estimates of average column atmospheric CO2 concentrations from Earth’s surface to space. OCO-2, which launched in 2014, provides changes in atmospheric CO2 on regional scales across the globe. GOSAT, which launched in 2009, provides targeted atmospheric CO2 observations that can be used to track changes over large urban areas. + OCO-2 and GOSAT provide estimates of average column atmospheric + CO2 concentrations from Earth’s surface to space. + OCO-2, which launched in 2014, provides changes in atmospheric + CO2 on regional scales across the globe. GOSAT, which + launched in 2009, provides targeted atmospheric CO2{' '} + observations that can be used to track changes over large urban + areas.

    - Ongoing research by the OCO-2 Science Team at NASA’s Jet Propulsion Laboratory (JPL), Colorado State University, and the Global Modeling and Assimilation Office (GMAO) at NASA’s Goddard Space Flight Center seeks to better understand the atmospheric CO2 effects of the COVID-19 shutdowns. The Japan Aerospace Exploration Agency (JAXA) GOSAT Project Team and the GOSAT Earth Observation Research Center (EORC) generated the GOSAT products. + Ongoing research by the OCO-2 Science Team at NASA’s Jet + Propulsion Laboratory (JPL), Colorado State University, and the + Global Modeling and Assimilation Office (GMAO) at NASA’s Goddard + Space Flight Center seeks to better understand the atmospheric + CO2 effects of the COVID-19 shutdowns. The Japan + Aerospace Exploration Agency (JAXA) GOSAT Project Team and the + GOSAT Earth Observation Research Center (EORC) generated the + GOSAT products.

    -
    @@ -223,33 +307,50 @@ class CO2LongForm extends React.Component { />

    - Unlike satellite-derived NO2 measurements, which are captured continuously on a daily basis, the coverage of CO2 measurements from OCO-2 and GOSAT is not as dense. Because of this, measurements from OCO-2 and GOSAT collected over weeks to months must be combined to yield high-resolution global maps of CO2. In addition, in order to account for long-range transport of CO2 by the wind, the data must further be assimilated into atmospheric transport models like those used to predict the weather. - + Unlike satellite-derived NO2 measurements, which + are captured continuously on a daily basis, the coverage of CO + 2 measurements from OCO-2 and GOSAT is not as + dense. Because of this, measurements from OCO-2 and GOSAT + collected over weeks to months must be combined to yield + high-resolution global maps of CO2. In addition, in + order to account for long-range transport of CO2 by + the wind, the data must further be assimilated into + atmospheric transport models like those used to predict the + weather.

    -

    - The NASA dashboard uses NASA’s Global Earth Observing System Constituent Data Assimilation System (GEOS CoDAS) developed by GMAO to ingest the OCO-2 data and produce gap-filled maps. - + The NASA dashboard uses NASA’s Global Earth Observing System + Constituent Data Assimilation System (GEOS CoDAS) developed by + GMAO to ingest the OCO-2 data and produce gap-filled maps.

    -

    - To more clearly discriminate between the COVID-19 related changes and much larger seasonal variations, observations from 2020 are compared with a carefully constructed baseline CO2 climatology derived from a reference simulation that was corrected for persistent biases between the model and OCO-2 observations collected in 2015-2019. - + To more clearly discriminate between the COVID-19 related + changes and much larger seasonal variations, observations from + 2020 are compared with a carefully constructed baseline CO + 2 climatology derived from a reference simulation + that was corrected for persistent biases between the model and + OCO-2 observations collected in 2015-2019.

    + + CO2 difference on April 1, 2020. + - +

    - Carbon dioxide data courtesy of the OCO-2 Science Team at NASA’s Jet Propulsion Laboratory, Colorado State University, and the Global Modeling and Assimilation Office at NASA’s Goddard Space Flight Center using OCO-2 and GOSAT data. + Carbon dioxide data courtesy of the OCO-2 Science Team at NASA’s + Jet Propulsion Laboratory, Colorado State University, and the + Global Modeling and Assimilation Office at NASA’s Goddard Space + Flight Center using OCO-2 and GOSAT data.

    @@ -262,12 +363,37 @@ class CO2LongForm extends React.Component { dashColor={metadata.color} /> - NASA Features + + NASA Features + diff --git a/app/assets/scripts/components/indicators/indicator-shipping.js b/app/assets/scripts/components/indicators/indicator-shipping.js index 4a5f9f20..32053892 100644 --- a/app/assets/scripts/components/indicators/indicator-shipping.js +++ b/app/assets/scripts/components/indicators/indicator-shipping.js @@ -35,11 +35,11 @@ const IntroFold = styled(Fold)` grid-column: full-start / full-end; ${media.mediumUp` - grid-column: content-start / content-end; + grid-column: content-2 / content-7; `} ${media.largeUp` - grid-column: full-start / content-8; + grid-column: content-8 / full-end; grid-row: 1; `} @@ -60,7 +60,7 @@ const IntroFold = styled(Fold)` `} ${media.largeUp` - grid-column: content-8 / content-end; + grid-column: content-start / content-8; `} } `; @@ -103,7 +103,7 @@ const InterpretingDataFold = styled(Fold)` } ${MediaImage} { - grid-column: content-start / content-end; + grid-column: full-start / full-end; ${media.mediumUp` grid-column: content-2 / content-7; diff --git a/app/assets/scripts/components/indicators/indicator-water-quality.js b/app/assets/scripts/components/indicators/indicator-water-quality.js index 52db30bf..93a86684 100644 --- a/app/assets/scripts/components/indicators/indicator-water-quality.js +++ b/app/assets/scripts/components/indicators/indicator-water-quality.js @@ -4,28 +4,68 @@ import styled from 'styled-components'; import Prose from '../../styles/type/prose'; import Gridder from '../../styles/gridder'; import InpageHGroup from '../../styles/inpage-hgroup'; -import { Fold } from '../../styles/fold'; +import { Fold, FoldDetails } from '../../styles/fold'; import MediaImage from '../../styles/media-image'; import media from '../../styles/utils/media-queries'; import Heading from '../../styles/type/heading'; import config from '../../config'; import { indicatorGroupColors } from '../../styles/theme/theme'; +import { glsp } from '../../styles/utils/theme-values'; +import { IntroLead } from '../../styles/datasets'; const { baseUrl } = config; +const LeadFold = styled(Fold)` + padding-bottom: 0; + + ${media.largeUp` + padding-bottom: ${glsp(3)}; + `} +`; + const IntroFold = styled(Fold)` padding-bottom: 0; - ${Prose} { + ${Gridder} { + align-items: center; + } + + ${MediaImage} { + grid-column: full-start / full-end; + + ${media.mediumUp` + grid-column: content-start / content-end; + `} + + ${media.largeUp` + grid-column: full-start / content-8; + grid-row: 1; + `} + + figcaption { + margin: 0 auto; + padding: 0 ${glsp()}; + max-width: 40rem; + text-align: center; + + ${media.mediumUp` + /* Image has a white border which must be taken into account. */ + margin-top: -${glsp()}; + `} + } + } + + ${FoldDetails} { grid-column: content-start / content-end; + text-align: left; ${media.mediumUp` grid-column: content-start / content-8; `} ${media.largeUp` - grid-column: content-start / content-10; + grid-column: content-8 / content-end; `} } `; @@ -91,7 +131,6 @@ const InterpretingDataFold = styled(Fold)` `; const AdditionalResourcesFold = styled(Fold)` - ${Gridder} { align-items: center; } @@ -129,48 +168,51 @@ class WQLongForm extends React.Component { render () { return ( + + + + Human activity greatly influences water quality. Runoff from + agriculture and cities can overload coastal waters with excess + nutrients, ships in ports and other waterways can mix up sediment + and increase turbidity, and even air pollution can end up in our + water. + + + + - -

    - Images of the Earth at night give us an extraordinary view of - human activity over time. The nighttime environment illuminates - Earth features like city infrastructure, lightning flashes, - fishing boats navigating open water, gas flares, aurora, and - natural hazards like lava flowing from an active volcano. Paired - with the moonlight, researchers can also spot snow and ice, as - well as other reflective surfaces that allow nighttime land and - ocean analysis. -

    -

    - During the COVID-19 pandemic, researchers are using night light - observations to track variations in energy use, migration, and - transportation in response to social distancing and lockdown - measures. -

    -

    - Scientists are examining whether the amount of algae - (chlorophyll-a) and sediment (turbidity) in water bodies was - affected by the shutdowns in response to the COVID-19 pandemic. - However, teasing out those signals from normal variations due to - weather and economic changes is challenging. -

    - -
    - Chlorophyll-a is an indicator of algae growth. During - coronavirus-related shutdowns, changes in our activity may - affect the amount of nutrients flowing in water bodies. This - image shows the changes in chlorophyll-a for the San Francisco - Bay Area on April 3, 2020. Redder colors indicate higher - levels of chlorophyll-a and worse water quality. Bluer colors - indicate lower levels of chlorophyll-a and improved water - quality. Image Credit: NASA. -
    -
    -
    + + +

    + As lockdown restrictions were put into place around the world + in response to the novel coronavirus, the immediate reduction + in vehicle and ship traffic led to noticeable improvements in + our air quality. Now, researchers are looking to see if those + same benefits will be reflected in our water. +

    +

    + Scientists are examining whether the amount of algae + (chlorophyll-a) and sediment (turbidity) in water bodies was + affected by the shutdowns in response to the COVID-19 + pandemic. However, teasing out those signals from normal + variations due to weather and economic changes is challenging. +

    +
    +
    + + Chlorophyll-a is an indicator of algae growth. During + coronavirus-related shutdowns, changes in our activity may + affect the amount of nutrients flowing in water bodies. This + image shows the changes in chlorophyll-a for the San Francisco + Bay Area on April 3, 2020. Redder colors indicate higher levels + of chlorophyll-a and worse water quality. Bluer colors indicate + lower levels of chlorophyll-a and improved water quality. Image + Credit: NASA. +
    diff --git a/app/assets/scripts/components/spotlight/single/index.js b/app/assets/scripts/components/spotlight/single/index.js index 3ff97f9e..de7fac4f 100644 --- a/app/assets/scripts/components/spotlight/single/index.js +++ b/app/assets/scripts/components/spotlight/single/index.js @@ -45,6 +45,7 @@ import { } from '../../../utils/map-explore-utils'; import QsState from '../../../utils/qs-state'; import media, { isLargeViewport } from '../../../styles/utils/media-queries'; +import summaries from './summaries'; const ExploreCanvas = styled.div` display: grid; @@ -184,7 +185,7 @@ class SpotlightAreasSingle extends React.Component { } render () { - const { spotlight, spotlightList, indicatorGroups } = this.props; + const { spotlight, spotlightList, indicatorGroups, summary } = this.props; if (spotlight.hasError() || indicatorGroups.hasError()) return ; @@ -274,6 +275,7 @@ class SpotlightAreasSingle extends React.Component { this.resizeMap(); this.onPanelChange('panelSec', revealed); }} + summary={summary} indicators={indicators} indicatorGroups={indicatorGroupsData} selectedDate={ @@ -296,6 +298,7 @@ SpotlightAreasSingle.propTypes = { spotlight: T.object, spotlightList: T.object, indicatorGroups: T.object, + summary: T.node, match: T.object, location: T.object, history: T.object @@ -305,6 +308,7 @@ function mapStateToProps (state, props) { const { spotlightId } = props.match.params; return { + summary: summaries[spotlightId], mapLayers: getSpotlightLayers(spotlightId), spotlightList: wrapApiResult(state.spotlight.list), spotlight: wrapApiResult( diff --git a/app/assets/scripts/components/spotlight/single/sec-panel.js b/app/assets/scripts/components/spotlight/single/sec-panel.js index d58e97da..cd5c9cc2 100644 --- a/app/assets/scripts/components/spotlight/single/sec-panel.js +++ b/app/assets/scripts/components/spotlight/single/sec-panel.js @@ -13,6 +13,7 @@ import { import { Accordion, AccordionFold } from '../../common/accordion'; import Heading from '../../../styles/type/heading'; import Prose from '../../../styles/type/prose'; +import SummaryExpandable from '../../common/summary-expandable'; import { glsp } from '../../../styles/utils/theme-values'; import { utcDate } from '../../../utils/utils'; @@ -71,7 +72,7 @@ const Attribution = styled.p` `; export default function SecPanel (props) { - const { onPanelChange, indicators, indicatorGroups, selectedDate } = props; + const { onPanelChange, indicators, indicatorGroups, selectedDate, summary } = props; // Ensure that we only deal with groups that have data. const groups = (indicatorGroups || []).filter(g => ( @@ -91,6 +92,10 @@ export default function SecPanel (props) { } bodyContent={ + {summary && ( + {summary} + )} + {({ checkExpanded, setExpanded }) => ( !!groups.length && groups.map((group, idx) => ( @@ -174,6 +179,7 @@ export default function SecPanel (props) { SecPanel.propTypes = { onPanelChange: T.func, + summary: T.node, indicators: T.array, indicatorGroups: T.array, selectedDate: T.object diff --git a/app/assets/scripts/components/spotlight/single/summaries.js b/app/assets/scripts/components/spotlight/single/summaries.js new file mode 100644 index 00000000..71d01f3e --- /dev/null +++ b/app/assets/scripts/components/spotlight/single/summaries.js @@ -0,0 +1,107 @@ +import React from 'react'; + +const summaries = { + be: ( + <> +

    + Chinese authorities suspended travel and closed businesses in late + January 2020 in response to the novel coronavirus. Satellite + observations since then have revealed changes in activity for Beijing’s + 21 million residents, including changes in fossil fuel emissions and + other economic activity. +

    +

    + Lockdowns and social distancing measures implemented in response to the + coronavirus pandemic led to significant but temporary reductions in + nitrogen dioxide (NO2) and carbon dioxide (CO2) emissions from fossil + fuel combustion and other human activities. +

    + + ), + gh: ( + <> +

    + Located on the North Sea on the coast of Belgium, the Port of Ghent is a + highly trafficked seaport. By focusing on changes in this typically + bustling area, researchers are able to compare changes in nightlights, + an indicator of economic activity before and after novel coronavirus + lockdowns began. +

    + + ), + du: ( + <> +

    + The Port of Dunkirk is the third-largest maritime port in northern + France. Located on the busy North Sea, the port is well known for the + comings and goings of heavy cargo barges. In early March, following + French government guidance, the port began to limit activity in response + to the novel coronavirus. +

    + + ), + la: ( + <> +

    + California was the first state in the U.S. to set mandatory stay-at-home + restrictions in an attempt to slow the spread of the novel coronavirus. + These orders went into effect for the whole state on March 19, 2020, + including for the city of Los Angeles and its approximately 4 million + residents. During the lockdown, LA saw cleaner air and quieter streets. +

    + + ), + ny: ( + <> +

    + As COVID-19 cases soared in New York City, more than 8 million residents + sheltered-in-place or fled the city. It remained in lockdown with strict + social distancing measures in place for more than two months, from March + through June 2020. +

    +

    + Satellite data reveal how changes in fossil fuel emissions and other + economic activity during coronavirus-related lockdowns affected New York + City’s air, land, and water. These data help visualize how + neighborhoods, commercial centers, and more changed due to social + distancing measures. +

    + + ), + sf: ( + <> +

    + California was one of the first states to implement COVID-19 + restrictions. A shelter-in-place mandate went into effect for six + counties in the San Francisco metropolitan area on March 17, 2020. While + the mandate was in effect, non-essential businesses were closed, and + approximately 6.7 million residents in the area were asked to stay home. +

    +

    + Satellite data reveal clearing of the air and improvements in water + quality during the lockdown. +

    + + ), + tk: ( + <> +

    + Japan declared a state of emergency in its two largest cities, Tokyo and + Osaka, and five of their surrounding prefectures in response to the + coronavirus pandemic on April 7, 2020. While the declaration allowed + these municipalities to request that residents remain at home, it was + not mandatory. +

    +

    + In Tokyo and around the world, researchers are using satellite data to + study how stay-at-home orders are affecting the environment around us. + Nightlights data track variations in energy use, migration, and + transportation, and nitrogen dioxide data track changes in + transportation and energy use in response to social distancing and + lockdown measures.{' '} +

    + + ) +}; + +export default summaries; diff --git a/package.json b/package.json index a84bdd73..93c1f757 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "covid-dashboard", - "version": "0.8.0", + "version": "0.9.0", "description": "Frontend application for the Covid Dashboard", "repository": { "type": "git",