Skip to content

Commit

Permalink
Use separateYears better for indirect emissions
Browse files Browse the repository at this point in the history
  • Loading branch information
terotik committed Nov 20, 2024
1 parent c43d38e commit 01688a8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 19 deletions.
58 changes: 48 additions & 10 deletions components/paths/graphs/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ import { useTranslations } from 'next-intl';
import { Table } from 'reactstrap';
import Styled from 'styled-components';

import type { OutcomeNodeFieldsFragment } from '@/common/__generated__/paths/graphql';
import { formatNumber } from '@/common/paths/preprocess';

// import { useFeatures } from '@/common/instance';
interface DataTableProps {
node: OutcomeNodeFieldsFragment;
subNodes?: Node[];
startYear: number;
endYear: number;
separateYears?: number[];
goalName?: string;
}

const TableWrapper = Styled.div`
margin: 0 auto;
Expand All @@ -19,14 +28,18 @@ const TableWrapper = Styled.div`
font-size: 70%;
`;

const DataTable = (props) => {
const { node, subNodes, startYear, endYear } = props;
const DataTable = (props: DataTableProps) => {
const { node, subNodes, startYear, endYear, separateYears, goalName } = props;
const t = useTranslations();
const totalHistoricalValues = node.metric.historicalValues.filter(
(value) => value.year >= startYear && value.year <= endYear
const totalHistoricalValues = node.metric.historicalValues.filter((value) =>
separateYears
? separateYears.includes(value.year)
: value.year >= startYear && value.year <= endYear
);
const totalForecastValues = node.metric.forecastValues.filter(
(value) => value.year >= startYear && value.year <= endYear
const totalForecastValues = node.metric.forecastValues.filter((value) =>
separateYears
? separateYears.includes(value.year)
: value.year >= startYear && value.year <= endYear
);
//const maximumFractionDigits = useFeatures().maximumFractionDigits ?? undefined;
const maximumFractionDigits = 3;
Expand All @@ -35,17 +48,42 @@ const DataTable = (props) => {
totalHistoricalValues.some((val) => val.value !== null) ||
totalForecastValues.some((val) => val.value !== null);

// Add this function to check if a subNode has any data
const hasData = (subNode) => {
const hasHistoricalData = subNode.metric.historicalValues
.filter((value) =>
separateYears
? separateYears.includes(value.year)
: value.year >= startYear && value.year <= endYear
)
.some((value) => value.value !== null);

const hasForecastData = subNode.metric.forecastValues
.filter((value) =>
separateYears
? separateYears.includes(value.year)
: value.year >= startYear && value.year <= endYear
)
.some((value) => value.value !== null);

return hasHistoricalData || hasForecastData;
};

// Filter subNodes to only include those with data
const validSubNodes = subNodes?.filter(hasData);

return (
<TableWrapper>
<h5>
{node.name} ({startYear} - {endYear})
{node.name}, {goalName}
{separateYears ? '' : ` (${startYear} - ${endYear})`}
</h5>
<Table bordered size="sm" responsive>
<thead>
<tr>
<th>{t('table-year')}</th>
<th>{t('table-measure-type')}</th>
{subNodes?.map((subNode) => (
{validSubNodes?.map((subNode) => (
<th key={subNode.id}>{subNode.name}</th>
))}
{hasTotalValues && <th>{node.metric.name}</th>}
Expand All @@ -57,7 +95,7 @@ const DataTable = (props) => {
<tr key={`h-${metric.year}`}>
<td>{metric.year}</td>
<td>{t('table-historical')}</td>
{subNodes?.map((subNode) => (
{validSubNodes?.map((subNode) => (
<td key={`${subNode.id}-${metric.year}`}>
{subNode.metric.historicalValues.find(
(value) => value.year === metric.year
Expand Down Expand Up @@ -92,7 +130,7 @@ const DataTable = (props) => {
<tr key={`f-${metric.year}`}>
<td>{metric.year}</td>
<td>{t('table-scenario-forecast')}</td>
{subNodes?.map((subNode) => (
{validSubNodes?.map((subNode) => (
<td key={`${subNode.id}-${metric.year}`}>
{subNode.metric.forecastValues.find(
(value) => value.year === metric.year
Expand Down
12 changes: 11 additions & 1 deletion components/paths/graphs/DimensionalNodePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,16 @@ export default function DimensionalNodePlot({

const nrYears = usableEndYear - startYear;

const separateYearsConfig: Partial<LayoutAxis> = separateYears
? {
type: 'category' as const,
data: separateYears,
axisTick: {
alignWithLabel: true,
},
}
: { range: [`${startYear - 1}-12-31`, `${usableEndYear}-02-01`] };

const commonXAxisConfig: Partial<LayoutAxis> = {
domain: [0, 1],
ticklen: 10,
Expand All @@ -572,7 +582,7 @@ export default function DimensionalNodePlot({

const mainXAxisConfig: Partial<LayoutAxis> = {
...commonXAxisConfig,
range: [`${startYear - 1}-12-31`, `${usableEndYear}-02-01`],
...separateYearsConfig,
};

const referenceXAxisConfig: Partial<LayoutAxis> = {
Expand Down
20 changes: 18 additions & 2 deletions components/paths/outcome/OutcomeNodeContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import DimensionalPieGraph from '@/components/paths/graphs/DimensionalPieGraph';
import HighlightValue from '@/components/paths/HighlightValue';
import OutcomeNodeDetails from '@/components/paths/outcome/OutcomeNodeDetails';
import ScenarioBadge from '@/components/paths/ScenarioBadge';
import { activeGoalVar } from '@/context/paths/cache';
import { usePaths } from '@/context/paths/paths';
import { useReactiveVar } from '@apollo/client';

const DisplayTab = styled(NavItem)`
font-size: 0.9rem;
Expand Down Expand Up @@ -130,10 +132,16 @@ const OutcomeNodeContent = ({
activeScenario,
refetching,
}: OutcomeNodeContentProps) => {
//console.log('node', node);
const t = useTranslations();
const [activeTabId, setActiveTabId] = useState('graph');
const paths = usePaths();

const activeGoal = useReactiveVar(activeGoalVar);
const separateYears =
activeGoal?.dimensions[0].groups[0] === 'indirect'
? [1990, 2010, 2015, 2020, 2022, 2023]
: null;

const instance = paths?.instance;
if (!instance) return null;
const showDistribution = subNodes.length > 1;
Expand All @@ -158,6 +166,7 @@ const OutcomeNodeContent = ({
metric={node.metricDim!}
startYear={startYear}
endYear={endYear}
separateYears={separateYears}
color={color}
withControls={false}
baselineForecast={node.metric?.baselineForecastValues ?? undefined}
Expand All @@ -175,7 +184,12 @@ const OutcomeNodeContent = ({
const singleYearGraph = useMemo(
() => (
<div>
<DimensionalPieGraph metric={node.metricDim!} endYear={endYear} />
<DimensionalPieGraph
metric={node.metricDim!}
endYear={
separateYears ? separateYears[separateYears.length - 1] : endYear
}
/>
</div>
),
[node, endYear, color]
Expand Down Expand Up @@ -332,6 +346,8 @@ const OutcomeNodeContent = ({
<ContentWrapper tabIndex={0}>
<DataTable
node={node}
goalName={activeGoal?.label}
separateYears={separateYears}
subNodes={subNodes}
color={color}
startYear={startYear}
Expand Down
27 changes: 21 additions & 6 deletions components/paths/toolbar/MediumSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';

import GoalSelector from 'components/paths/GoalSelector';
import RangeSelector from 'components/paths/RangeSelector';
Expand All @@ -8,7 +8,7 @@ import { useTranslations } from 'next-intl';
import { Col, Container, Popover, PopoverBody, Row } from 'reactstrap';
import styled from 'styled-components';

import { yearRangeVar } from '@/context/paths/cache';
import { activeGoalVar, yearRangeVar } from '@/context/paths/cache';
import { usePaths } from '@/context/paths/paths';
import { useReactiveVar } from '@apollo/client';

Expand Down Expand Up @@ -61,11 +61,19 @@ const StyledButton = styled.button<{ ref: HTMLButtonElement }>`
`;

const YearRangeSelector = (props) => {
const { minYear, maxYear, referenceYear } = props;
const { minYear, maxYear, referenceYear, disabled = false } = props;
const inputReference = useRef<HTMLDivElement>(null);
const triggerReference = useRef<HTMLButtonElement | null>(null);

const [popoverOpen, setPopoverOpen] = useState(false);

useEffect(() => {
if (disabled) {
setPopoverOpen(false);
yearRangeVar([minYear, maxYear]);
}
}, [disabled, maxYear, minYear]);

const toggle = () => {
setPopoverOpen(!popoverOpen);
// Focus on the input when the popover is opened
Expand Down Expand Up @@ -96,20 +104,21 @@ const YearRangeSelector = (props) => {
[yearRangeVar]
);
const t = useTranslations();

const buttonLabel = disabled ? '-' : `${yearRange[0]}${yearRange[1]}`;
if (!yearRange) return <div>Loading...</div>;
return (
<div>
<ButtonLabel>{t('comparing-years')}</ButtonLabel>
<StyledButton
className="btn btn-light"
className={`btn btn-light ${disabled ? 'disabled' : ''}`}
id="rangeSelector"
aria-expanded={popoverOpen}
aria-haspopup="dialog"
aria-controls="rangeSelectorPopover"
ref={setTriggerRef}
disabled={disabled}
>
{`${yearRange[0]}${yearRange[1]}`}
{buttonLabel}
</StyledButton>
<Popover
placement="bottom"
Expand Down Expand Up @@ -160,6 +169,11 @@ const MediumSettings = (props) => {
const nrGoals = instance.goals.length;
const hasMultipleGoals = nrGoals > 1;
const columnSizes = getColumnSizes(hasMultipleGoals);
const activeGoal = useReactiveVar(activeGoalVar);
// TODO: This is a hack. We should get this from the backend.
const goalHasSeparateYears =
activeGoal?.dimensions[0].groups[0] === 'indirect' ? true : false;

return (
<Container fluid="xl">
<PanelContent>
Expand All @@ -172,6 +186,7 @@ const MediumSettings = (props) => {
minYear={instance.minimumHistoricalYear}
maxYear={instance.modelEndYear}
referenceYear={instance.referenceYear}
disabled={goalHasSeparateYears}
/>
</StyledDropdownCol>
{hasMultipleGoals && (
Expand Down

0 comments on commit 01688a8

Please sign in to comment.