Allow shifting by time range

This commit is contained in:
Tanner Collin 2024-07-16 01:30:23 +00:00
parent e549afce96
commit e5dbb0af39

View File

@ -22,6 +22,22 @@ const durations = [
{id: 3, len: 'Year', win: '2h', full: '2 hour', delta: [1, 'years'], format: 'M/D', num: 4380, secs: 7200}, {id: 3, len: 'Year', win: '2h', full: '2 hour', delta: [1, 'years'], format: 'M/D', num: 4380, secs: 7200},
]; ];
const parseSlider = (end, duration, slider) => {
//console.log(slider);
// good luck remembering how this works
const lowOffset = slider[0] * duration.secs - duration.num * duration.secs;
const highOffset = slider[1] * duration.secs - duration.num * duration.secs;
const low = moment.unix(end.unix() + lowOffset);
const high = moment.unix(end.unix() + highOffset);
const lowStr = low.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
const highStr = high.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
//console.log(lowStr, highStr);
return [lowStr, highStr];
};
function useSensor(measurement, name, end, duration) { function useSensor(measurement, name, end, duration) {
const [data, setData] = useState(false); const [data, setData] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -51,9 +67,11 @@ function useSensor(measurement, name, end, duration) {
function Owntracks({end, duration, range}) { function Owntracks({end, duration, slider}) {
const [data, loading] = useSensor('owntracks', 'OwnTracks', end, duration); const [data, loading] = useSensor('owntracks', 'OwnTracks', end, duration);
const range = parseSlider(end, duration, slider);
const coords = data.length ? data.filter(x => !range || (x.time >= range[0] && x.time <= range[1])).map(({ lat, lon }) => [lat, lon]).filter(([lat, lon]) => lat !== null || lon !== null) : []; const coords = data.length ? data.filter(x => !range || (x.time >= range[0] && x.time <= range[1])).map(({ lat, lon }) => [lat, lon]).filter(([lat, lon]) => lat !== null || lon !== null) : [];
const handleSubmit = (e) => { const handleSubmit = (e) => {
@ -90,73 +108,89 @@ function Owntracks({end, duration, range}) {
} }
function Graphs({end, duration, range}) { function Graphs({end, duration, slider}) {
return ( return (
<div className='container'> <div className='container'>
<Owntracks end={end} duration={duration} range={range} /> <Owntracks end={end} duration={duration} slider={slider} />
</div> </div>
); );
} }
function Menu({duration, setDuration, end, setEnd, range, setRange}) { function Menu({duration, setDuration, end, setEnd, slider, setSlider}) {
const [submenu, setSubmenu] = useState(false); const [submenu, setSubmenu] = useState(false);
const [showRange, setShowRange] = useState(false); const [showRange, setShowRange] = useState(false);
const chooseDuration = (x) => { const chooseDuration = (x) => {
setSubmenu(false); setSubmenu(false);
setRange(false); setSlider([0, x.num]);
setDuration(x); setDuration(x);
}; };
const chooseEnd = (x) => { const chooseEnd = (x) => {
setSubmenu(false); setSubmenu(false);
const newEnd = x.add(...duration.delta); const newEnd = x.add(...duration.delta);
setRange(false); setSlider([0, duration.num]);
setEnd(newEnd); setEnd(newEnd);
}; };
const chooseNow = (x) => { const chooseNow = (x) => {
setSubmenu(false); setSubmenu(false);
setRange(false); setSlider([0, duration.num]);
setEnd(moment()); setEnd(moment());
}; };
const rangeStart = (x) => {
setEnd(moment(range[0]).add(...duration.delta));
setSlider([0, duration.num]);
};
const rangeEnd = (x) => {
setEnd(moment(range[1]));
setSlider([0, duration.num]);
};
const next = () => { const next = () => {
setSubmenu(false); setSubmenu(false);
setRange(false); setSlider([0, duration.num]);
setEnd(prevEnd => moment(prevEnd).add(...duration.delta)); setEnd(prevEnd => moment(prevEnd).add(...duration.delta));
} }
const prev = () => { const prev = () => {
setSubmenu(false); setSubmenu(false);
setRange(false); setSlider([0, duration.num]);
setEnd(prevEnd => moment(prevEnd).subtract(...duration.delta)); setEnd(prevEnd => moment(prevEnd).subtract(...duration.delta));
} }
const onSlider = (slider) => { const range = parseSlider(end, duration, slider);
console.log(slider);
// good luck remembering how this works
const lowOffset = slider[0] * duration.secs - duration.num * duration.secs;
const highOffset = slider[1] * duration.secs - duration.num * duration.secs;
const low = moment.unix(end.unix() + lowOffset); const rangeTime = (x) => {
const high = moment.unix(end.unix() + highOffset); if (new Date().getTimezoneOffset()) { // non-librewolf browser
return moment(x).format('lll'); // default to browser's TZ
const lowStr = low.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); } else {
const highStr = high.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); return moment(x).tz('America/Edmonton').format('lll');
}
console.log(lowStr, highStr); };
setRange([lowStr, highStr]);
}
return ( return (
<div className='menu'> <div className='menu'>
{showRange && <div className='range'> {(showRange || !!submenu) && <div className='range'>
{moment(range[0]).format('lll')} - {moment(range[1]).format('lll')} {rangeTime(range[0])} - {rangeTime(range[1])}
</div>} </div>}
{submenu ? <div className='time-slider'>
<RangeSlider
min={0}
max={duration.num}
value={slider}
onInput={setSlider}
onThumbDragStart={() => setShowRange(true)}
onThumbDragEnd={() => setShowRange(false)}
onRangeDragStart={() => setShowRange(true)}
onRangeDragEnd={() => setShowRange(false)}
/>
</div>
{!!submenu &&
<div className='submenu'> <div className='submenu'>
{submenu === 'end' && {submenu === 'end' &&
<> <>
@ -174,6 +208,8 @@ function Menu({duration, setDuration, end, setEnd, range, setRange}) {
</div> </div>
<button onClick={chooseNow}>Jump to Now</button> <button onClick={chooseNow}>Jump to Now</button>
<button onClick={rangeStart}>Shift to Range Start</button>
<button onClick={rangeEnd}>Shift to Range End</button>
</> </>
} }
@ -190,20 +226,6 @@ function Menu({duration, setDuration, end, setEnd, range, setRange}) {
</> </>
} }
</div> </div>
:
<div className='time-slider'>
<RangeSlider
min={0}
max={duration.num}
defaultValue={[0, duration.num]}
onInput={onSlider}
onThumbDragStart={() => setShowRange(true)}
onThumbDragEnd={() => setShowRange(false)}
onRangeDragStart={() => setShowRange(true)}
onRangeDragEnd={() => setShowRange(false)}
/>
</div>
} }
<div className='menu-container'> <div className='menu-container'>
@ -232,7 +254,7 @@ function Menu({duration, setDuration, end, setEnd, range, setRange}) {
function App() { function App() {
const [duration, setDuration] = useState(durations[0]); const [duration, setDuration] = useState(durations[0]);
const [end, setEnd] = useState(moment()); const [end, setEnd] = useState(moment());
const [range, setRange] = useState(false); const [slider, setSlider] = useState([0, duration.num]);
return ( return (
<div> <div>
@ -241,14 +263,14 @@ function App() {
setDuration={setDuration} setDuration={setDuration}
end={end} end={end}
setEnd={setEnd} setEnd={setEnd}
range={range} slider={slider}
setRange={setRange} setSlider={setSlider}
/> />
<Graphs <Graphs
end={end} end={end}
duration={duration} duration={duration}
range={range} slider={slider}
/> />
</div> </div>
); );