diff --git a/src/components/App.tsx b/src/components/App.tsx index 14d3c86..6b7b03d 100755 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -10,16 +10,45 @@ import { Header } from "./header"; import "../assets/scss/App.scss"; +const updateRowSelectionInCodap = (latitude: string, longitude: string, day: number) => { + // TODO: Issue CODAP API request to highlight appropriate case in the case table, using combination of + // Math.floor(day), latitude, and longitude. +} + export const App: React.FC = () => { const [activeTab, setActiveTab] = useState<"location" | "simulation">("location"); const [latitude, setLatitude] = useState(""); const [longitude, setLongitude] = useState(""); - const [dayOfYear, setDayOfYear] = useState("280"); + const [dayOfYear, setDayOfYear] = useState(171); const [locations, setLocations] = useState([]); const [locationSearch, setLocationSearch] = useState(""); const [selectedAttrs, setSelectedAttributes] = useState(kDefaultOnAttributes); const [dataContext, setDataContext] = useState(null); + const handleDayUpdateInTheSimTab = (day: number) => { + console.log("The day of the year has been updated in the simulation tab to: ", day); // TODO: remove it later + // We might to debounce this call, as if the animation is on, or user is dragging the slider, there will be + // lot of events and API calls to CODAP. + updateRowSelectionInCodap(latitude, longitude, Math.floor(day)); + // Note that we do not need to update dayOfYear state variable. It's useful only for the opposite direction + // of the sync process, when user select a row in CODAP and we want to update the day in the simulation tab. + }; + + const handleCaseSelectionInCodap = (_latitude: string, _longitude: string, day: number) => { + // Option 1. Update as much of the plugin state as we can when user selects a case in CODAP. I think this might + // be too much, as it'll clear all the inputs in all the tabs and the user will have to re-enter everything + // if they were in the middle of something. + // setDayOfYear(day); + // setLatitude(_latitude); + // setLongitude(_longitude); + // ...OR... + // Option 2. Update only the day of the year, as that's reasonably unobtrusive and useful. We can first check + // if user actually selected the case from the same location, and only then update the day of the year. + if (latitude === _latitude && longitude === _longitude) { + setDayOfYear(day); + } + } + const { getUniqueLocationsInCodapData } = useCodapData(); // Store a ref to getUniqueLocationsInCodapData so we can call inside useEffect without triggering unnecessary re-runs const getUniqueLocationsRef = useRef(getUniqueLocationsInCodapData); @@ -90,14 +119,14 @@ export const App: React.FC = () => {
diff --git a/src/components/simulation-tab.tsx b/src/components/simulation-tab.tsx index f7ea10c..8297b3d 100644 --- a/src/components/simulation-tab.tsx +++ b/src/components/simulation-tab.tsx @@ -5,30 +5,32 @@ import Seasons from "../grasp-seasons/components/seasons"; import "../assets/scss/simulation-tab.scss"; interface SimulationTabProps { + locations: ILocation[]; latitude: string; longitude: string; - dayOfYear: string; - locations: ILocation[]; setLatitude: (latitude: string) => void; setLongitude: (longitude: string) => void; setLocationSearch: (search: string) => void; - setDayOfYear: (day: string) => void; + dayOfYear: number; + setDayOfYear: (day: number) => void; } export const SimulationTab: React.FC = ({ + locations, latitude, longitude, - locations, - dayOfYear, - setDayOfYear, setLatitude, setLongitude, - setLocationSearch + setLocationSearch, + dayOfYear, + setDayOfYear, }) => { return (
; log?: (action: string, data?: any) => void; + locations: ILocation[]; latitude: string; longitude: string; - locations: ILocation[]; setLatitude: (latitude: string) => void; setLongitude: (longitude: string) => void; setLocationSearch: (name: string) => void; + dayOfYear: number; + setDayOfYear: (day: number) => void; } const Seasons: React.FC = ({ lang = "en_us", initialState = {}, log = (action: string, data?: any) => {}, - latitude, longitude, locations, setLatitude, setLongitude, setLocationSearch }) => { + locations, latitude, longitude, setLatitude, setLongitude, setLocationSearch, dayOfYear, setDayOfYear }) => { const orbitViewRef = useRef(null); // State @@ -81,11 +83,13 @@ const Seasons: React.FC = ({ lang = "en_us", initialState = {}, log = (a const { animationStarted: mainAnimationStarted, toggleState: toggleMainAnimation } = useAnimation({ value: simState.day, setValue: (newDay: number) => { - const stateUpdate: Partial = { day: newDay % 365 }; + const day = newDay % 365; + const stateUpdate: Partial = { day }; if (simState.dailyRotation) { stateUpdate.earthRotation = (newDay % 1) * 2 * Math.PI; } setSimState(prevState => ({ ...prevState, ...stateUpdate })); + setDayOfYear(day); }, speed: simState.dailyRotation ? DAILY_ROTATION_ANIM_SPEED : ANIM_SPEED }); @@ -120,6 +124,10 @@ const Seasons: React.FC = ({ lang = "en_us", initialState = {}, log = (a } }, [longitude]); + useEffect(() => { + setSimState(prevState => ({ ...prevState, day: dayOfYear })); + }, [dayOfYear]); + // Derived state const simLang = simState.lang; const playStopLabel = mainAnimationStarted ? t("~STOP", simLang) : t("~ORBIT_BUTTON", simLang); @@ -160,10 +168,14 @@ const Seasons: React.FC = ({ lang = "en_us", initialState = {}, log = (a setLongitude(formatLatLongNumber(newState.long)); setLocationSearch(""); } + if (newState.day !== undefined) { + setDayOfYear(newState.day); + } }; const handleDaySliderChange = (event: any, ui: any) => { setSimState(prevState => ({ ...prevState, day: ui.value })); + setDayOfYear(ui.value); }; const handleDayIncrement = (increment: number) => () => {