Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

187887752 date format improvements, attribute refinements #23

Merged
merged 12 commits into from
Aug 15, 2024
39 changes: 22 additions & 17 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,36 @@ export const App: React.FC = () => {
const [activeTab, setActiveTab] = useState<"location" | "simulation">("location");
const [latitude, setLatitude] = useState("");
const [longitude, setLongitude] = useState("");
const [dayOfYear, setDayOfYear] = useState(171);
const [dayOfYear, /*setDayOfYear */] = useState(171);
bacalj marked this conversation as resolved.
Show resolved Hide resolved
const [locations, setLocations] = useState<ILocation[]>([]);
const [locationSearch, setLocationSearch] = useState<string>("");
const [selectedAttrs, setSelectedAttributes] = useState<string[]>(kDefaultOnAttributes);
const [dataContext, setDataContext] = useState<any>(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
// console.log("The day of the year has been updated in the simulation tab to: ", day); // TODO: implement this
// 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);
}
}
// TODO: Handle case selection - sync sim tab with CODAP selection
// 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
Expand All @@ -70,7 +71,11 @@ export const App: React.FC = () => {
const isResource = resource === `dataContextChangeNotice[${kDataContextName}]`;
if (!isResource) return;

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

if ( casesDeleted ) {
const uniqeLocations = await getUniqueLocationsRef.current();
Expand Down
6 changes: 3 additions & 3 deletions src/components/location-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export const LocationTab: React.FC<LocationTabProps> = ({
} = useCodapData();

useEffect(() => {
const updateAttributesVisibility = async () => {
const updateEachAttrVisibility = () => {
for (const attr of kChildCollectionAttributes) {
const isSelected = selectedAttrs.includes(attr.name);
await updateAttributeVisibility(attr.name, !isSelected);
updateAttributeVisibility(attr.name, !isSelected);
}
};

updateAttributesVisibility();
updateEachAttrVisibility();
}, [selectedAttrs, updateAttributeVisibility]);

const handleLatChange = (event: React.ChangeEvent<HTMLInputElement>) => {
Expand Down
84 changes: 60 additions & 24 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const kDefaultMaxRows = 4;
export const kParentCollectionName = "Locations";
export const kChildCollectionName = "Daylight Info";

export const kAdjustSpringForwardOutlier = false;

export const kParentCollectionAttributes = [
{
name: "latitude",
Expand All @@ -31,67 +33,101 @@ export const kParentCollectionAttributes = [
{
name: "longitude",
type: "numeric"

},
{
name: "location",
type: "categorical"

}
// NOTE: If data are to be historical, add year attribute
];

export const kChildCollectionAttributes = [
{
name: "date",
title: "Date",
type: "date",
hasToken: true
hasToken: true,
precision: "day",
description: "Date"
},
{
name: "dayLength",
title: "Day Length",
name: "Day length",
title: "Day length",
bacalj marked this conversation as resolved.
Show resolved Hide resolved
type: "numeric",
hasToken: true
hasToken: true,
unit: "hours",
description: "Day length in hours"
},
{
name: "sunrise",
title: "Sunrise",
name: "rawSunrise",
title: "rawSunrise",
type: "date",
hasToken: true
hasToken: false,
hidden: true,
precision: "seconds",
description: "sunrise as date object"
},
{
name: "sunset",
title: "Sunset",
name: "rawSunset",
title: "rawSunset",
type: "date",
hasToken: true
hasToken: false,
hidden: true,
precision: "seconds",
description: "sunset as date object"
},
{
name: "dayNumber",
title: "Day Number",
name: "Sunrise",
title: "Sunrise",
type: "numeric",
hasToken: false
hasToken: true,
unit: "decimal hours",
formula: "hours(rawSunrise)+minutes(rawSunrise)/60",
description: "time in decimal hours"
},
{
name: "sunlightAngle",
title: "Sunlight Angle",
name: "Sunset",
title: "Sunset",
type: "numeric",
hasToken: true
hasToken: true,
unit: "decimal hours",
formula: "hours(rawSunset)+minutes(rawSunset)/60",
description: "time in decimal hours"
},
{
name: "solarIntensity",
title: "Solar Intensity",
name: "Sunlight angle",
title: "Sunlight angle",
type: "numeric",
hasToken: true
hasToken: true,
unit: "°",
description: "angle in degrees of sunlight at solar noon"
},
{
name: "season",
name: "Solar intensity",
title: "Solar intensity",
type: "numeric",
hasToken: true,
unit: "W/㎡",
description: "intensity of solar energy in watts per square meter at solar noon, disregarding all atmospheric effects"
},
{
name: "Season",
title: "Season",
type: "categorical",
hasToken: true
}
];

export const kDefaultOnAttributes = [
bacalj marked this conversation as resolved.
Show resolved Hide resolved
"date", "sunrise", "sunset", "dayLength"
"date", "Day length"
];

export const kDateWithTimeFormats = {
asZuluISO: "YYYY-MM-DDTHH:mm[Z]", // 1999-01-23T21:45Z
asLocalISOWithTZOffset: "YYYY-MM-DDTHH:mmZ", // 1999-01-23T14:45-07:00
asClockTimeString: "HH:mm", // 14:45
asClockTimeStringAMPM: "h:mm a", // 2:45 PM
}

export const kDateFormats = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we end up using formulas for the date display column we will not need these, these are mostly here for making iteration easier.

asLocalISODate: "YYYY-MM-DD",
}
17 changes: 8 additions & 9 deletions src/hooks/useCodapData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,13 @@ export const useCodapData = () => {
latitude: location.latitude,
longitude: location.longitude,
location: location.name,
dayNumber: solarEvent.dayAsInteger,
date: solarEvent.day,
sunrise: solarEvent.sunrise,
sunset: solarEvent.sunset,
dayLength: solarEvent.dayLength,
season: solarEvent.season,
sunlightAngle: solarEvent.sunlightAngle,
solarIntensity: solarEvent.solarIntensity
rawSunrise: solarEvent.rawSunrise,
rawSunset: solarEvent.rawSunset,
"Day length": solarEvent.dayLength,
"Season": solarEvent.season,
"Sunlight angle": solarEvent.sunlightAngle,
"Solar intensity": solarEvent.solarIntensity
};

return record;
Expand All @@ -84,11 +83,11 @@ export const useCodapData = () => {
}
};

const updateAttributeVisibility = async (attributeName: string, hidden: boolean) => {
const updateAttributeVisibility = (attributeName: string, hidden: boolean) => {
if (!dataContext) return;

try {
await updateAttribute(
updateAttribute(
kDataContextName,
kChildCollectionName,
attributeName,
Expand Down
7 changes: 3 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ export interface DaylightCalcOptions {
}

export interface DaylightInfo {
day: string;
sunrise: string;
sunset: string;
day: string; // read into CODAP as an ISO date
rawSunrise: string; // read into CODAP as an ISO date
rawSunset: string; // read into CODAP as an ISO date
dayLength: number;
dayAsInteger: number;
season: string;
sunlightAngle: number;
solarIntensity: number;
Expand Down
Loading
Loading