Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/nowcasting-app/components/LegendTooltop.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type TipPosition = "left" | "right" | "middle" | "top";
type TipPosition = "left" | "right" | "middle" | "top" | "top-right";

type LegendTooltipProps = {
children: React.ReactNode;
Expand All @@ -13,6 +13,8 @@ const getPositionClass = (position: TipPosition) => {
if (position === "middle") return "bottom-1 left-1/2 transform -translate-x-1/2 translate-y-full";
if (position === "top")
return "-top-[calc(100%+0.75rem)] left-1/2 transform -translate-x-1/2 -translate-y-full";
if (position === "top-right")
return "-top-[calc(100%+0.75rem)] left-0 transform -translate-y-full";

return "top-0 left-0"; // Default case for top-left
};
Expand All @@ -24,13 +26,13 @@ const LegendTooltip: React.FC<LegendTooltipProps> = ({
className
}) => {
return (
<div className={`relative z-[100] overflow-visible cursor-default group ${className || ""}`}>
<div className={`relative overflow-visible cursor-default group ${className || ""}`}>
{children}
{tip && (
<div
className={`absolute ${getPositionClass(
position
)} hidden w-max max-w-64 mt-6 group-hover:flex flex-wrap`}
)} hidden z-[100] w-max max-w-64 mt-6 group-hover:flex flex-wrap`}
>
<span
className={`flex top-0 text-center mb-0 mt-2 text-xs px-3 py-1 leading-snug bg-mapbox-black bg-opacity-95 rounded-lg text-white drop-shadow-lg`}
Expand Down
115 changes: 79 additions & 36 deletions apps/nowcasting-app/components/charts/ChartLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ export const ChartLegend: FC<ChartLegendProps> = ({ className }) => {
}
}

const seasonalMeanTooltipContent = (
<div className="flex flex-col text-left justify-center items-start gap-2 text-xs text-ocf-gray-300 py-1">
<p>
The seasonal mean is calculated by taking the average of the PV generation for each day of
the year over the past 8 years.
</p>
<p>
This provides a baseline for understanding typical PV generation patterns and can be useful
for comparing against actual generation data.
</p>
</div>
);

Copy link
Contributor

Choose a reason for hiding this comment

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

This looks great, could you add one for the Seasonal quanitles tool

The seasonal quantiles are calculated by taking the quantiles of the PV generation for each day of
        the year over the past 8 years.

        This provides a baseline with uncertainties for understanding typical PV generation patterns and can be useful
        for comparing against actual generation data.

const ocfForecastTooltipContent = (
<LegendTooltipContent inputs={["ECMWF", "MET_OFFICE", "SAT"]} />
);
Expand All @@ -57,61 +70,63 @@ export const ChartLegend: FC<ChartLegendProps> = ({ className }) => {

return (
<div className="@container flex flex-initial">
<div className="flex flex-1 flex-col justify-between align-items:baseline px-3 text-xs tracking-wider text-ocf-gray-300 py-2 gap-3 bg-mapbox-black-500 overflow-y-visible @sm:flex-row @xl:gap-6">
<div className="flex flex-1 flex-col justify-between align-items:baseline px-3 text-xs tracking-wider text-ocf-gray-300 py-2 gap-0 bg-mapbox-black-500 overflow-y-visible @sm:flex-row @xl:gap-6">
<div
className={`flex flex-initial pr-2 justify-between flex-col overflow-x-auto @md:pr-0 @md:flex-col @md:gap-0 @lg:flex-row @lg:gap-5`}
className={`flex flex-initial justify-between flex-col overflow-x-auto @md:pr-0 @md:flex-col @md:gap-0 @lg:flex-row @lg:gap-5 @2xl:pr-2`}
style={{ overflow: "visible" }}
>
<div className={legendItemContainerClasses}>
<LegendItem
iconClasses={"text-ocf-black"}
dashStyle={"dashed"}
label={"PV live initial estimate"}
dataKey={`GENERATION`}
/>
<LegendItem
iconClasses={"text-ocf-black"}
label={"PV live updated"}
dataKey={`GENERATION_UPDATED`}
/>
<div
className={`${legendItemContainerClasses} hidden @2xl:flex dash:hidden @4xl:dash:flex`}
>
<LegendTooltip
tip={ocfForecastTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap @2xl:hidden dash:flex flex-col @4xl:dash:hidden"
className="relative w-full whitespace-pre-wrap"
>
<LegendItem
iconClasses={"text-ocf-yellow"}
dashStyle={"both"}
label={"OCF Latest"}
symbolStyle={"both"}
label={"Current"}
dataKey={`FORECAST`}
/>
</LegendTooltip>
{showNHourView && (
<LegendTooltip
tip={ocfNHrForecastTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap @2xl:hidden dash:flex flex-col @4xl:dash:hidden"
className="relative w-full whitespace-pre-wrap"
>
<LegendItem
iconClasses={"text-ocf-orange"}
dashStyle={"both"}
label={`OCF ${nHourForecast}hr`}
symbolStyle={"both"}
label={`${nHourForecast} hour`}
dataKey={`N_HOUR_FORECAST`}
/>
</LegendTooltip>
)}

<LegendTooltip
tip={seasonalMeanTooltipContent}
position={"top-right"}
className="relative w-full whitespace-pre-wrap"
>
<LegendItem
iconClasses={"text-[#ffdfd1]"}
label={"Seasonal Mean"}
dataKey={`SEASONAL_MEAN`}
/>
</LegendTooltip>
</div>
<div
className={`${legendItemContainerClasses} hidden @2xl:flex dash:hidden @4xl:dash:flex`}
>

<div className={legendItemContainerClasses}>
<LegendTooltip
tip={ocfForecastTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap"
className="relative w-full whitespace-pre-wrap @2xl:hidden dash:flex flex-col @4xl:dash:hidden"
>
<LegendItem
iconClasses={"text-ocf-yellow"}
dashStyle={"both"}
symbolStyle={"both"}
label={"OCF Latest"}
dataKey={`FORECAST`}
/>
Expand All @@ -120,27 +135,25 @@ export const ChartLegend: FC<ChartLegendProps> = ({ className }) => {
<LegendTooltip
tip={ocfNHrForecastTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap"
className="relative w-full whitespace-pre-wrap @2xl:hidden dash:flex flex-col @4xl:dash:hidden"
>
<LegendItem
iconClasses={"text-ocf-orange"}
dashStyle={"both"}
symbolStyle={"both"}
label={`OCF ${nHourForecast}hr`}
dataKey={`N_HOUR_FORECAST`}
/>
</LegendTooltip>
)}
</div>
<div className={legendItemContainerClasses}>
<LegendTooltip
tip={ocfEcmwfForecastTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap"
>
<LegendItem
iconClasses={"text-ocf-teal-500"}
dashStyle={"both"}
label={`OCF ECMWF-only`}
symbolStyle={"both"}
label={`ECMWF-only`}
dataKey={`INTRADAY_ECMWF_ONLY`}
/>
</LegendTooltip>
Expand All @@ -151,8 +164,8 @@ export const ChartLegend: FC<ChartLegendProps> = ({ className }) => {
>
<LegendItem
iconClasses={"text-metOffice"}
dashStyle={"both"}
label={`OCF Met Office-only`}
symbolStyle={"both"}
label={`Met Office-only`}
dataKey={`MET_OFFICE_ONLY`}
/>
</LegendTooltip>
Expand All @@ -163,15 +176,45 @@ export const ChartLegend: FC<ChartLegendProps> = ({ className }) => {
>
<LegendItem
iconClasses={"text-ocf-yellow-200"}
dashStyle={"both"}
label={`OCF Satellite-only`}
symbolStyle={"both"}
label={`Satellite-only`}
dataKey={`SAT_ONLY`}
/>
</LegendTooltip>
</div>
</div>
<div className={legendItemContainerClasses}>
<LegendItem
iconClasses={"text-ocf-black"}
symbolStyle={"dashed"}
label={"PV live initial"}
dataKey={`GENERATION`}
/>
<LegendItem
iconClasses={"text-ocf-black"}
label={"PV live updated"}
dataKey={`GENERATION_UPDATED`}
/>
<LegendTooltip
tip={seasonalMeanTooltipContent}
position={"top"}
className="relative w-full whitespace-pre-wrap @2xl:hidden"
>
<LegendItem
iconClasses={"text-[#ffdfd1]"}
label={"Seasonal Mean"}
dataKey={`SEASONAL_MEAN`}
/>
</LegendTooltip>
<LegendItem
iconClasses={"text-[#ffdfd1]"}
symbolStyle={"area"}
label={"Seasonal quantiles"}
dataKey={`SEASONAL_BOUNDS`}
/>
</div>
{showNHourView && (
<div className="flex flex-1 w-full justify-end items-end gap-3 pr-3 pb-1 @md:flex-col @lg:gap-4 @2xl:flex-row @3xl:gap-12">
<div className="flex flex-1 w-full justify-end items-end gap-3 pr-3 pb-1 pt-1 @md:flex-col @lg:gap-4 @2xl:flex-row @3xl:gap-12">
<div className="flex">
<>
<div className="h-8 w-10 mr-2 custom-select bg-mapbox-black-600 rounded-md">
Expand Down
12 changes: 8 additions & 4 deletions apps/nowcasting-app/components/charts/LegendItem.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { FC, useEffect, useMemo, useState } from "react";
import useGlobalState from "../helpers/globalState";
import { LegendLineGraphIcon } from "../icons/icons";
import { LegendAreaGraphIcon, LegendLineGraphIcon } from "../icons/icons";
import Toggle from "../Toggle";

const LegendItem: FC<{
iconClasses: string;
label: string;
dashStyle?: "both" | "dashed" | "solid";
symbolStyle?: "both" | "dashed" | "solid" | "area";
dataKey: string;
}> = ({ iconClasses, label, dashStyle, dataKey }) => {
}> = ({ iconClasses, label, symbolStyle, dataKey }) => {
const [visibleLines, setVisibleLines] = useGlobalState("visibleLines");
const [mounted, setMounted] = useState(false);

Expand All @@ -31,7 +31,11 @@ const LegendItem: FC<{

return (
<div className="flex items-center flex-initial">
<LegendLineGraphIcon className={iconClasses} dashStyle={dashStyle} />
{symbolStyle === "area" ? (
<LegendAreaGraphIcon className={iconClasses} />
) : (
<LegendLineGraphIcon className={iconClasses} dashStyle={symbolStyle} />
)}
<button
className="inline-flex flex-1 text-left pl-1 max-w-full w-auto leading-tight text-2xs @lg:pr-1 @xl:pr-0 @xl:text-2xs dash:text-base dash:tracking-wider dash:pb-1"
onClick={toggleLineVisibility}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const GspPvRemixChart: FC<{
pvRealDayInData: pvRealDataIn,
pvRealDayAfterData: pvRealDataAfter,
timeTrigger: selectedTime,
delta: deltaView
delta: deltaView,
gsp: true
});
const now30min = formatISODateString(get30MinNow());
const dataMissing =
Expand Down
Loading