Skip to content

Commit

Permalink
feat(time-slider): add component
Browse files Browse the repository at this point in the history
  • Loading branch information
pwambach committed Oct 22, 2019
1 parent 8489e94 commit a4c8494
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/scripts/components/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import StoriesSelector from '../stories-selector/stories-selector';
import StoriesButton from '../stories-button/stories-button';
import UrlSync from '../url-sync/url-sync';
import LayerLoader from '../layer-loader/layer-loader';
import TimeSlider from '../time-slider/time-slider';

import translations from '../../i18n';
import styles from './app.styl';
Expand All @@ -44,6 +45,7 @@ const TranslatedApp: FunctionComponent = () => {
<Route path="/" exact>
<Globes />
<StoriesButton />
<TimeSlider />

<div className={styles.layoutContainer}>
<Menu />
Expand Down
15 changes: 15 additions & 0 deletions src/scripts/components/time-slider/time-slider.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.timeSlider
position: absolute
bottom: 6em
width: 100%
text-align: center

.input
width: 80%

.label
display: inline-block
width: 80%
color: white
text-align: left
font-size: 2em
74 changes: 74 additions & 0 deletions src/scripts/components/time-slider/time-slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, {FunctionComponent, useState, useMemo, useEffect} from 'react';
import {useSelector} from 'react-redux';

import {selectedLayersSelector} from '../../reducers/layers/selected';
import {detailedLayersSelector} from '../../reducers/layers/details';

import styles from './time-slider.styl';

const TimeSlider: FunctionComponent = () => {
const [time, setTime] = useState(0);
const stepSize = 1000 * 60 * 60 * 24; // one day
const selectedLayers = useSelector(selectedLayersSelector);
const detailedLayers = useSelector(detailedLayersSelector);

// get only active layer ids
const activeLayers = useMemo(
() => Object.values(selectedLayers).filter(Boolean),
[selectedLayers]
);

// get combined and sorted timestamps from all active layers
const allTimestamps = useMemo(
() =>
activeLayers
.map(id => detailedLayers[id])
.filter(Boolean)
.map(({timestamps}) => timestamps)
// @ts-ignore
.flat()
.map((isoString: string) => Number(new Date(isoString)))
.sort((a: number, b: number) => a - b),
[activeLayers, detailedLayers]
);

const min = allTimestamps[0];
const max = allTimestamps[allTimestamps.length - 1];
const timestampsAvailable = allTimestamps.length > 0;

// clamp time according to min/max
useEffect(() => {
if (time < min) {
setTime(min);
}

if (time > max) {
setTime(max);
}
}, [time, min, max]);

// return nothing when no timesteps available
if (!timestampsAvailable) {
return null;
}

return (
<div className={styles.timeSlider}>
<div className={styles.label}>
{new Date(time).toISOString().substr(0, 10)}
</div>

<input
className={styles.input}
type="range"
value={time}
onChange={({target}) => setTime(parseInt(target.value, 10))}
min={min}
max={max}
step={stepSize}
/>
</div>
);
};

export default TimeSlider;
3 changes: 2 additions & 1 deletion src/scripts/config/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const globeState: GlobeState = {

export default {
api: {
layers: 'https://storage.googleapis.com/esa-cfs-storage/layers-{lang}.json',
layers:
'https://storage.googleapis.com/esa-cfs-storage/layers/layers-{lang}.json',
layer:
'https://storage.googleapis.com/esa-cfs-storage/layers/{id}/metadata.json',
stories: 'https://storage.googleapis.com/esa-cfs-storage/stories'
Expand Down

0 comments on commit a4c8494

Please sign in to comment.