Skip to content

Commit

Permalink
poc only two way selection case table and sim day
Browse files Browse the repository at this point in the history
- very hacky and not performant at the moment
- needs revision
- might need to adopt a "get notification -> ask codap" pattern
- which means removing "get notification -> get data from notification" pattern
  • Loading branch information
bacalj committed Aug 16, 2024
1 parent b5b247b commit 0c23785
Showing 1 changed file with 90 additions and 60 deletions.
150 changes: 90 additions & 60 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useEffect, useState, useRef } from "react";
import React, { useEffect, useState, useRef, useCallback } from "react";

Check warning on line 1 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

'useCallback' is defined but never used

Check warning on line 1 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

'useCallback' is defined but never used

Check warning on line 1 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

'useCallback' is defined but never used

Check warning on line 1 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

'useCallback' is defined but never used
import { clsx } from "clsx";
import { ILocation } from "../types";
import { debounce } from "../grasp-seasons/utils/utils";
import { kInitialDimensions, kVersion, kPluginName, kDefaultOnAttributes, kSimulationTabDimensions, kDataContextName } from "../constants";
import { kInitialDimensions, kVersion, kPluginName, kDefaultOnAttributes, kSimulationTabDimensions, kDataContextName, kChildCollectionName } from "../constants";
import { initializePlugin, codapInterface, selectSelf, addDataContextChangeListener, ClientNotification, getCaseByID } from "@concord-consortium/codap-plugin-api";
import { useCodapData } from "../hooks/useCodapData";
import { LocationTab } from "./location-tab";
Expand All @@ -11,20 +11,40 @@ import { Header } from "./header";

import "../assets/scss/App.scss";

const debouncedUpdateRowSelectionInCodap = debounce((latitude: string, longitude: string, day: number) => {
console.log("\n| SIM day is: ", day, " so issue API request to update selected row in CODAP ",
"\n latitude: ", latitude,
"\n longitude: ", longitude,
"\n day: ", day,
"\n Math.floor(day) ", Math.floor(day));

// Here, you would add the actual API call to update the row selection in CODAP
// For example:
// codapInterface.sendRequest({
// action: "update",
// resource: `dataContext[${kDataContextName}].selectionList`,
// values: [{ latitude, longitude, dayOfYear: Math.floor(day) }]
// });
const debouncedUpdateRowSelectionInCodap = debounce((
latitude: string,
longitude: string,
day: number
) => {
//console.log(`\n| Selecting case in ${kDataContextName} where latitude: ${latitude}, longitude: ${longitude}, day: ${day}`);
// TODO: It seems roundabout to look up the case id and then go back to ask for it
// But I was unable to find an example of how to select a case by its attribute values
// Next thing for this might be to see if the case ids might be mapped somewhere to the dayOfYear
// It could be a more direct way to select the case rather than two api requests
codapInterface.sendRequest({
action: "get",
resource: `dataContext[${kDataContextName}].collection[${kChildCollectionName}].caseSearch[dayOfYear==${Math.floor(day)}]`
}).then((result: any) => {
console.log("| case search result: ", result);

Check warning on line 29 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Unexpected console statement

Check warning on line 29 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

Unexpected console statement
if (result.success && result.values.length > 0) {
const caseID = result.values[0].id;
return codapInterface.sendRequest({
action: "create",
resource: `dataContext[${kDataContextName}].selectionList`,
values: [caseID]
});
} else {
console.log("No matching case found");

Check warning on line 38 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Unexpected console statement

Check warning on line 38 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

Unexpected console statement
return null;
}
}).then((selectionResult: any) => {
if (selectionResult) {
console.log("Selection result:", selectionResult);

Check warning on line 43 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Unexpected console statement

Check warning on line 43 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

Unexpected console statement
}
}).catch((error: any) => {
console.error("Error in selection process:", error);
});
}, 250);

export const App: React.FC = () => {
Expand All @@ -37,35 +57,35 @@ export const App: React.FC = () => {
const [selectedAttrs, setSelectedAttributes] = useState<string[]>(kDefaultOnAttributes);
const [dataContext, setDataContext] = useState<any>(null);

// Store a ref to getUniqueLocationsInCodapData so we can call inside useEffect without triggering unnecessary re-runs
const { getUniqueLocationsInCodapData } = useCodapData();
const getUniqueLocationsRef = useRef(getUniqueLocationsInCodapData);

const handleDayUpdateInTheSimTab = (day: number) => {
debouncedUpdateRowSelectionInCodap(latitude, longitude, day);
// NOTE: not need update dayOfYear state variable. It's useful only for the opposite direction
// it's useful when user select a row in CODAP and we want to update the day in the sim
};

const handleCaseSelectionInCodap = (_latitude: string, _longitude: string, day: number) => {
console.log("| calling handleCaseSelectionInCodap with selected values: ", _latitude, _longitude, day);
console.log("| matching lat long?: \n current location: ", latitude, longitude, "\n selected location: ", _latitude, _longitude);
console.log("| matching day?: \n current dayOfYear in sim: ", dayOfYear, "\n selected day in codap: ", day);
const correctLocation = latitude === _latitude && longitude === _longitude;
const isNewDay = dayOfYear !== day;
if (correctLocation && isNewDay) {
console.log("| we should update the dayOfYear in the sim tab to day, ", day);
//setDayOfYear(day);
const handleCaseSelectionInCodap = (
selectedLatitude: string,
selectedLongitude: string,
selectedDay: number,
currentLatitude: string,
currentLongitude: string,
currentDayOfYear: number
) => {
// TODO: this is a little hacky - we cooerce the numbers to strings to compare them
const rowInLocation = `${currentLatitude},${currentLongitude}` === `${selectedLatitude},${selectedLongitude}`;
const newDayChoice = `${currentDayOfYear}` !== `${selectedDay}`;
if (rowInLocation && newDayChoice) {
setDayOfYear(selectedDay);
// TODO: this works, but CODAP is also resetting the case table so we scroll away from selected row
// Perhaps because it is re-rendering the table with the new case selected?
}
// if user actually selected the case from the same location, then update the day of the year.
// if (latitude === _latitude && longitude === _longitude) {
// setDayOfYear(day);
// }
}


// Store a ref to getUniqueLocationsInCodapData so we can call inside useEffect without triggering unnecessary re-runs
const { getUniqueLocationsInCodapData } = useCodapData();
const getUniqueLocationsRef = useRef(getUniqueLocationsInCodapData);
};

useEffect(() => {
const initialize = async () => {
console.log("| !! Initializing plugin");

Check warning on line 88 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Unexpected console statement

Check warning on line 88 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

Unexpected console statement
try {
await initializePlugin({
pluginName: kPluginName,
Expand All @@ -75,35 +95,45 @@ export const App: React.FC = () => {
} catch (e) {
console.error("Failed to initialize plugin, error:", e);
}

// TODO: make this more general, and then decipher what to do with the data
const handleDataContextChange = async (listenerRes: ClientNotification) => {
const { resource, values } = listenerRes;
const isResource = resource === `dataContextChangeNotice[${kDataContextName}]`;
if (!isResource || !values.result.success) return;

// Checking if cases were deleted. If they were, we need to update the locations list.
const casesDeleted = values.operation === "selectCases" && values.result.cases.length === 0
const caseSelected = values.operation === "selectCases" && values.result.cases.length === 1;

if ( casesDeleted ) {
const uniqeLocations = await getUniqueLocationsRef.current();
if (uniqeLocations) setLocations(uniqeLocations);
} else if (caseSelected) {
const parentCaseId = values.result.cases[0].parent;
const selectedDay = values.result.cases[0].values.dayOfYear;
const parentCase = await getCaseByID(kDataContextName, parentCaseId);
const selectedLatitude = parentCase.values.case.values.latitude;
const selectedLongitude = parentCase.values.case.values.longitude;
handleCaseSelectionInCodap(selectedLatitude, selectedLongitude, selectedDay);
}
};
addDataContextChangeListener(kDataContextName, handleDataContextChange);
};

initialize();
}, []);

useEffect(() => {
const handleDataContextChange = async (listenerRes: ClientNotification) => {
console.log("| dataContextChangeNotice: ", listenerRes);

Check warning on line 105 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Unexpected console statement

Check warning on line 105 in src/components/App.tsx

View workflow job for this annotation

GitHub Actions / S3 Deploy

Unexpected console statement
const { resource, values } = listenerRes;
const isResource = resource === `dataContextChangeNotice[${kDataContextName}]`;
if (!isResource || !values.result.success) return;

const casesDeleted = values.operation === "selectCases" && values.result.cases.length === 0
const caseSelected = values.operation === "selectCases" && values.result.cases.length === 1;

if (casesDeleted) {
const uniqeLocations = await getUniqueLocationsRef.current();
if (uniqeLocations) setLocations(uniqeLocations);
}
else if (caseSelected) {
const parentCaseId = values.result.cases[0].parent;
const selectedDay = values.result.cases[0].values.dayOfYear;
const parentCase = await getCaseByID(kDataContextName, parentCaseId);
const selectedLatitude = parentCase.values.case.values.latitude;
const selectedLongitude = parentCase.values.case.values.longitude;
handleCaseSelectionInCodap(
selectedLatitude,
selectedLongitude,
selectedDay,
latitude,
longitude,
dayOfYear
);
}
};
addDataContextChangeListener(kDataContextName, handleDataContextChange);
// TODO: this is kind of working but not sure about how to clean up the listener?
}, [latitude, longitude, dayOfYear]);

const handleTabClick = (tab: "location" | "simulation") => {
setActiveTab(tab);
// Update dimensions of the plugin window when switching tabs.
Expand Down

0 comments on commit 0c23785

Please sign in to comment.