Skip to content

Commit

Permalink
Merge legendUrl and abudanceUrl in to dataUrl. Create a type for Data…
Browse files Browse the repository at this point in the history
…Types, clear out extra vars for Timeline, cleanup Home.
  • Loading branch information
pmandler-umass committed Sep 24, 2024
1 parent 4a0c334 commit 8c2c247
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 124 deletions.
16 changes: 6 additions & 10 deletions src/components/Legend.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
/* eslint-disable no-template-curly-in-string */
import { useEffect, useState } from 'react';
import { changeLegend } from '../hooks/legendUrl';
import { changeLegend, DataTypes} from '../hooks/dataUrl';
import '../styles/Legend.css';

// Interface for the Legend
interface LegendProps {
dataType: string;
dataType: DataTypes;
speciesType: string;
}

/* Creates a custom legend component based on the species scale values. */
function Legend(props: LegendProps) {
const { dataType, speciesType } = props;

const [data, setData] = useState<string>();

// Fetches the JSON of values from the backend
const getJSON = async (url: string) => {
const response = await fetch(url);
if (!response.ok)
if (!response.ok) {
// TODO PAM how should it handle errors?
// check if response worked (no 404 errors etc...)
throw new Error(response.statusText);

}
const d = response.json(); // get JSON from the response
return d; // returns a promise, which resolves to this data value
};
Expand All @@ -32,20 +32,16 @@ function Legend(props: LegendProps) {
getJSON(u)
.then((d) => {
const pushed: any[] = [];
// transforms the JSON into a string and basicslly CSS code that can be inserted into the styles
// transforms the JSON into a string and basically CSS code that can be inserted into the styles
d.map((i: any) => pushed.push(`${i.color} ${i.position}%`));
const x = pushed.join(', ');
setData(x);
})
.catch((error) => {
console.error(error);
});
}, [dataType, speciesType]);

return (
<div className="Legend">
<div className="Legend-titles">
{/* TODO: Change high and low text to scale values */}
<div>High</div>
<div
className="Legend-innerGradient"
Expand Down
36 changes: 13 additions & 23 deletions src/components/Timeline.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { Slider } from '@mantine/core';
import { useState, useEffect } from 'react';
// Keeps track of the props and prop type going into the component (look up interfaces in TypeScript)
interface TimelineProps {
week: number;
onChangeWeek: (val: string) => void;
}

/* Creates a custom timeline slider that updates what week number of the year the user is currently on. */
function Timeline(props: TimelineProps) {
// Displays tick marks and labels
const marks = [
{ value: 1, label: 'Jan' },
Expand Down Expand Up @@ -64,32 +56,30 @@ function Timeline(props: TimelineProps) {
{ value: 52 },
];

const { week, onChangeWeek } = props;
const [weekVal, setWeekVal] = useState(week);
// Keeps track of the props and prop type going into the component (look up interfaces in TypeScript)
interface TimelineProps {
week: number;
onChangeWeek: (val: number) => void;
}

/* Creates a custom timeline slider that updates what week number of the year the user is currently on. */
function Timeline(props: TimelineProps) {

// Sets the week value on load and every time the user changes it
useEffect(() => {
setWeekVal(week);
}, [week, weekVal]);

/* On change of the slider, the week number is updated. */
const onChangeNumber = (v: number) => {
setWeekVal(v);
onChangeWeek(v.toString());
};

const { week, onChangeWeek } = props;

return (
<div className="Timeline">
<Slider
defaultValue={weekVal}
value={weekVal}
defaultValue={week}
value={week}
marks={marks}
min={1}
max={52}
labelAlwaysOn
step={1}
thumbSize={20}
onChange={(v) => onChangeNumber(v)}
onChange={(v) => onChangeWeek(v)}
/>
</div>
);
Expand Down
15 changes: 0 additions & 15 deletions src/hooks/abundanceUrl.tsx

This file was deleted.

10 changes: 0 additions & 10 deletions src/hooks/legendUrl.tsx

This file was deleted.

107 changes: 41 additions & 66 deletions src/views/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,78 @@ import { Menu, ActionIcon } from '@mantine/core';
import { MapContainer, TileLayer, ImageOverlay } from 'react-leaflet';
import { useState, useEffect, useCallback } from 'react';
import { IconFileDatabase, IconFeather } from '@tabler/icons-react';
import { changeURL } from '../hooks/abundanceUrl';
import { imageURL, DataTypes } from '../hooks/dataUrl';
import taxa from '../assets/taxa.json';
import Timeline from '../components/Timeline';
import Legend from '../components/Legend';
import '../styles/Home.css';
import 'leaflet/dist/leaflet.css';

/* This is the main page and only page of the application. Here, the map renders as well as all the AvianFluApp feature controls */
const MAX_WEEK = 52; // number of weeks in a year

/* This is the main page and only page of the application.
Here, the map renders as well as all the AvianFluApp feature controls */
function Home(this: any) {

// Sets the default position for the map.
const position = {
lat: 45,
lng: -95,
};

// Calls the useState hook provided by React to create state for and set the default state of the url for the current data displayed.

const [url, setUrl] = useState(
'https://avianinfluenza.s3.us-east-2.amazonaws.com/abundance/mean/abundance_mean_1.png'
);

//Sets state for the data type
const [dataType, setDataType] = useState('abundance');
//Sets state for the species type
const [speciesType, setSpeciesType] = useState('mean');
//Sets state for the week number
const [week, setWeek] = useState('1');

/* onClick function for the Species dropdown. When you click on a species, it updates the species state and url state to reflect the changes. */
const onClickSpecies = (val: string) => {
const u = changeURL(dataType, val, week);
setSpeciesType(val);
setUrl(u);
};

/* onClick function for the data type dropdown. When you select a data type, it updates the data state as well as the url. */
const onClickDataType = (val: string) => {
const u = changeURL(val, speciesType, week);
setDataType(val);
setUrl(u);
};

/* onClick function for the week number. When you change the week by sliding the timeline or using arrow keys, it uodstes the week number and the url. */
const onClickWeek = (val: string) => {
const u = changeURL(dataType, speciesType, val);
setWeek(val);
setUrl(u);
};

// the bounds of the data image provided by the backend
// the bounds of the data image provided by the backend TODO PAM needs better explanation
const imageBounds = [
[9.622994, -170.291626],
[79.98956, -49.783429],
];

/* Allows the user to use the front and back arrow keys to control the week number and which image files are being displayed. */

// Sets state for the data type - so far this is abundance or netmovement
const [dataType, setDataType] = useState(DataTypes.ABUNDANCE);
// Sets state for the species type
const [speciesType, setSpeciesType] = useState('mean');
// Sets state for the week number
let this_week = 1; // TODO change to current week
const [week, setWeek] = useState(this_week);
// default state of the url for the current data displayed.
const [url, setUrl] = useState(imageURL(DataTypes.ABUNDANCE, 'mean', this_week));

// Adds a listener for the event in which a user presses a key on the keyboard.
useEffect(() => {
const u = imageURL(dataType, speciesType, week);
setUrl(u);
}, [speciesType, dataType, week]);

/* Allows the user to use the front and back arrow keys to control the week number
and which image files are being displayed. */
const handleSelection = useCallback(
(event: KeyboardEvent) => {
const { key } = event;
const arrowLeftPressed = key === 'ArrowLeft';
const arrowRightPressed = key === 'ArrowRight';

// increments active index (wraps around when at top)
if (arrowLeftPressed) {
if (event.key === 'ArrowRight') {
// increments active index (wraps around when at top)
event.preventDefault();
let temp = parseInt(week, 10) - 1;
if (temp <= 0) temp = 52;
const u = changeURL(dataType, speciesType, temp.toString());
setWeek(temp.toString());
setUrl(u);

let temp = week + 1;
if (temp > MAX_WEEK) temp = 1;
setWeek(temp);
} else if (event.key === 'ArrowLeft') {
// decrements active index (wraps around when at bottom)
} else if (arrowRightPressed) {
event.preventDefault();
let temp = parseInt(week, 10) + 1;
if (temp >= 53) temp = 1;
const u = changeURL(dataType, speciesType, temp.toString());
setWeek(temp.toString());
setUrl(u);
let temp = week - 1;
if (temp <= 0) temp = MAX_WEEK;
setWeek(temp);
}
},
[dataType, speciesType, week]
},[speciesType, dataType, week]
);

// Adds a listener for the event in which a user presses a key on the keyboard.
// Adds a listener for user keyboard events.
useEffect(() => {
document.addEventListener('keydown', handleSelection);

return () => {
document.removeEventListener('keydown', handleSelection);
};
}, [handleSelection]);

// Maps the species from the taxa file provided to a dropdown with options.
const taxaOptions = taxa.map((t) => (
<Menu.Item key={t.value} onClick={() => onClickSpecies(t.value)}>
<Menu.Item key={t.value} onClick={() => setSpeciesType(t.value)}>
{t.label}
</Menu.Item>
));
Expand All @@ -107,7 +82,7 @@ function Home(this: any) {
return (
<div className="Home">
{/* Calls the custom timeline component with the current week onChange function as parameters */}
<Timeline week={parseInt(week, 10)} onChangeWeek={onClickWeek} />
<Timeline week={week} onChangeWeek={setWeek} />
{/* Calls the custom legend component with the data type and species type as parameters. */}
<Legend dataType={dataType} speciesType={speciesType} />

Expand Down Expand Up @@ -145,15 +120,15 @@ function Home(this: any) {
{/* The options for the data type and the corresponsing onClick function call
TODO: add influx and outflux */}
<Menu.Dropdown>
<Menu.Item onClick={() => onClickDataType('abundance')}>
<Menu.Item onClick={() => setDataType(DataTypes.ABUNDANCE)}>
Abundance
</Menu.Item>
<Menu.Item onClick={() => onClickDataType('netmovement')}>
<Menu.Item onClick={() => setDataType(DataTypes.MOVEMENT)}>
Net Movement
</Menu.Item>
</Menu.Dropdown>
</Menu>
{/*The dropdown for the species type */}
{/* The dropdown for the species type */}
<Menu position="left-start" withArrow>
<Menu.Target>
<ActionIcon
Expand Down

0 comments on commit 8c2c247

Please sign in to comment.