Skip to content

Commit

Permalink
Handle refetch on mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
terotik committed Oct 13, 2024
1 parent 1fda689 commit 236be2a
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 101 deletions.
13 changes: 7 additions & 6 deletions components/common/SelectDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import React, { useEffect, useState } from 'react';

import PopoverTip from 'components/common/PopoverTip';
import Highlighter from 'react-highlight-words';
import Select, {
components,
DropdownIndicatorProps,
MultiValueProps,
OptionProps,
Theme as SelectTheme,
ValueContainerProps,
OptionProps,
} from 'react-select';
import styled, { DefaultTheme, useTheme } from 'styled-components';
import Highlighter from 'react-highlight-words';
import { FormGroup, Label as BSLabel } from 'reactstrap';
import PopoverTip from 'components/common/PopoverTip';
import styled, { DefaultTheme, useTheme } from 'styled-components';

const Label = styled(BSLabel)`
font-weight: ${(props) => props.theme.formLabelFontWeight};
Expand Down Expand Up @@ -262,7 +263,7 @@ type SelectDropdownProps<Option extends SelectDropdownOption> = Parameters<

function SelectDropdown<
Option extends SelectDropdownOption,
IsMulti extends boolean = false
IsMulti extends boolean
>(props: SelectDropdownProps<Option>) {
const {
size,
Expand All @@ -272,7 +273,7 @@ function SelectDropdown<
onChange,
helpText,
invert,
isMulti,
isMulti = false,
...rest
} = props;
const theme = useTheme();
Expand Down
1 change: 0 additions & 1 deletion components/paths/ActionParameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const Parameters = styled.div`

const ActionParameters = (props: { parameters: ParameterInterface[] }) => {
const { parameters } = props;

if (!parameters) {
return null;
}
Expand Down
26 changes: 16 additions & 10 deletions components/paths/CategoryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { DimensionalMetric } from '@/utils/paths/metric';
import { getHttpHeaders } from '@/utils/paths/paths.utils';
import PathsActionNode from '@/utils/paths/PathsActionNode';
import { useQuery, useReactiveVar } from '@apollo/client';
import { NetworkStatus, useQuery, useReactiveVar } from '@apollo/client';

const ContentLoader = styled(Spinner)`
margin: 0 auto;
Expand All @@ -43,8 +43,9 @@ const Card = styled.div`
${(props) => transparentize(0.9, props.theme.themeColors.dark)};
`;

const CardContentBlock = styled.div`
const CardContentBlock = styled.div<{ $disabled?: boolean }>`
margin: ${({ theme }) => `0 ${theme.spaces.s100} ${theme.spaces.s100}`};
opacity: ${({ $disabled = false }) => ($disabled ? 0.5 : 1)};
`;
const CardHeader = styled.h3`
margin: ${({ theme }) => `0 ${theme.spaces.s100} ${theme.spaces.s100}`};
Expand All @@ -61,17 +62,20 @@ const PathsBasicNodeContent = (props) => {
const { categoryId, node, pathsInstance, onLoaded } = props;
const yearRange = useReactiveVar(yearRangeVar);
const activeGoal = useReactiveVar(activeGoalVar);
const t = useTranslations();
// const t = useTranslations();

const { data, loading, error } = useQuery(GET_NODE_CONTENT, {
const { data, loading, error, networkStatus } = useQuery(GET_NODE_CONTENT, {
fetchPolicy: 'no-cache',
variables: { node: node, goal: activeGoal?.id },
notifyOnNetworkStatusChange: true,
context: {
uri: '/api/graphql-paths',
headers: getHttpHeaders({ instanceIdentifier: pathsInstance }),
},
});

const refetching = networkStatus === NetworkStatus.refetch;

useEffect(() => {
if (data) {
const nodeMetric = new DimensionalMetric(data.node.metricDim!);
Expand All @@ -91,7 +95,7 @@ const PathsBasicNodeContent = (props) => {
}
}, [activeGoal, data, yearRange]);

if (loading) {
if (loading && !refetching) {
return <ContentLoader type="grow" />;
}
if (error) {
Expand Down Expand Up @@ -128,8 +132,7 @@ const PathsBasicNodeContent = (props) => {
const unit = nodeMetric.getUnit();

return (
<CardContentBlock>
<div>{nodeMetric.getName()}</div>
<CardContentBlock $disabled={refetching}>
{yearTotal && (
<>
<h5>{label}</h5>
Expand All @@ -153,15 +156,18 @@ const PathsActionNodeContent = (props) => {
const activeGoal = useReactiveVar(activeGoalVar);
const t = useTranslations();

const { data, loading, error } = useQuery(GET_PATHS_ACTION, {
const { data, loading, error, networkStatus } = useQuery(GET_PATHS_ACTION, {
fetchPolicy: 'no-cache',
variables: { action: node, goal: activeGoal?.id },
notifyOnNetworkStatusChange: true,
context: {
uri: '/api/graphql-paths',
headers: getHttpHeaders({ instanceIdentifier: pathsInstance }),
},
});

const refetching = networkStatus === NetworkStatus.refetch;

useEffect(() => {
if (data) {
const pathsAction = new PathsActionNode(data.action);
Expand All @@ -170,7 +176,7 @@ const PathsActionNodeContent = (props) => {
}
}, [activeGoal, data, yearRange]);

if (loading) {
if (loading && !refetching) {
return <ContentLoader type="grow" />;
}
if (error) {
Expand All @@ -180,7 +186,7 @@ const PathsActionNodeContent = (props) => {
const pathsAction = new PathsActionNode(data.action);
const impact = pathsAction.getYearlyImpact(yearRange[1]) || 0;
return (
<CardContentBlock>
<CardContentBlock $disabled={refetching}>
{t('impact')} {yearRange[1]}
<h4>
{yearRange ? beautifyValue(impact) : <span>---</span>}
Expand Down
2 changes: 1 addition & 1 deletion components/paths/ParameterWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ const ParameterWidget = (props: ParameterWidgetProps) => {
const paths = usePaths();
const [SetParameter, { loading: mutationLoading, error: mutationError }] =
useMutation(SET_PARAMETER, {
refetchQueries: ['GetPathsActionList', 'GetScenarios'],
refetchQueries: 'active',
context: {
uri: '/api/graphql-paths',
headers: getHttpHeaders({ instanceIdentifier: paths?.instance.id }),
Expand Down
4 changes: 3 additions & 1 deletion components/paths/ScenarioSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { GET_SCENARIOS } from '@/queries/paths/get-paths-scenarios';
import { getHttpHeaders } from '@/utils/paths/paths.utils';
import { gql, useMutation, useQuery } from '@apollo/client';

const pathsQueries = 'active';

const ACTIVATE_SCENARIO = gql`
mutation ActivateScenario($scenarioId: ID!) {
activateScenario(id: $scenarioId) {
Expand Down Expand Up @@ -78,7 +80,7 @@ const ScenarioSelector = () => {
uri: '/api/graphql-paths',
headers: getHttpHeaders({ instanceIdentifier: paths?.instance.id }),
},
refetchQueries: ['GetPathsActionList', 'GetScenarios'],
refetchQueries: pathsQueries,
});

if (loading) {
Expand Down
3 changes: 1 addition & 2 deletions components/paths/contentblocks/CategoryTypeListBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const CategoryList = (props) => {
}
return updatedCategories;
});
console.log('categoriesPathsData', categoriesPathsData);
//console.log('categoriesPathsData', categoriesPathsData);
//setLoadedCards(prev => ({ ...prev, [id]: impact }));
};

Expand Down Expand Up @@ -275,7 +275,6 @@ const CategoryTypeListBlock = (props: CategoryTypeListBlockProps) => {
const { id = '', heading, groupByLevel, listByLevel, categoryType } = props;
const plan = usePlan();

console.log('categorytypelistblockprops', props);
const { data, loading, error } = useQuery(
GET_CATEGORIES_FOR_CATEGORY_TYPE_LIST,
{
Expand Down
139 changes: 76 additions & 63 deletions components/paths/contentblocks/PathsOutcomeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { useMemo, useState } from 'react';
import { useState } from 'react';

import { useTranslations } from 'next-intl';
import { Card, CardBody, Col, Container, Row } from 'reactstrap';
Expand All @@ -15,14 +15,14 @@ import { activeScenarioVar, yearRangeVar } from '@/context/paths/cache';
import { usePaths } from '@/context/paths/paths';
import GET_PAGE from '@/queries/paths/get-paths-page';
import { getHttpHeaders } from '@/utils/paths/paths.utils';
import { useQuery, useReactiveVar } from '@apollo/client';
import { NetworkStatus, useQuery, useReactiveVar } from '@apollo/client';

const ErrorBackground = styled.div`
background-color: ${(props) => props.theme.brandDark};
min-height: 800px;
`;

const StyledCard = styled(Card)`
const StyledCard = styled(Card)<{ $disabled?: boolean }>`
margin-top: 5rem;
width: 100%;
transition: all 0.5s ease;
Expand All @@ -40,6 +40,10 @@ const StyledCard = styled(Card)`
margin-bottom: 2rem;
fill: ${(props) => props.theme.brandDark};
}
.card-body {
opacity: ${({ $disabled = false }) => ($disabled ? 0.5 : 1)};
}
`;

const findVisibleNodes = (allNodes, lastNodeId: string, visibleNodes) => {
Expand All @@ -53,15 +57,20 @@ const findVisibleNodes = (allNodes, lastNodeId: string, visibleNodes) => {
return visibleNodes;
};

export default function PathsOutcomeBlock(props) {
const { heading, helpText, outcomeNodeId } = props;
export default function PathsOutcomeBlock() {
//const { heading, helpText, outcomeNodeId } = props;
const t = useTranslations();
const pathsInstance = usePaths();
const yearRange = useReactiveVar(yearRangeVar);
const activeScenario = useReactiveVar(activeScenarioVar);
const path = '';
const { data } = useQuery<GetPageQuery, GetPageQueryVariables>(GET_PAGE, {
const [lastActiveNodeId, setLastActiveNodeId] = useState<string | undefined>(
undefined
);
const queryResp = useQuery<GetPageQuery, GetPageQueryVariables>(GET_PAGE, {
variables: { path, goal: null },
fetchPolicy: 'cache-and-network',
notifyOnNetworkStatusChange: true,
context: {
uri: '/api/graphql-paths',
headers: getHttpHeaders({
Expand All @@ -70,65 +79,69 @@ export default function PathsOutcomeBlock(props) {
},
});

if (!data) {
const { loading, error, previousData, networkStatus } = queryResp;
const refetching = networkStatus === NetworkStatus.refetch;

const data = queryResp.data ?? previousData;

if (loading && !refetching) {
return <ContentLoader />;
}

const { outcomeNode } = data.page;
const { upstreamNodes } = outcomeNode;
const allNodes = useMemo(
() => new Map(upstreamNodes.map((node) => [node.id, node])),
[upstreamNodes]
);
allNodes.set(outcomeNode.id, outcomeNode);
const [lastActiveNodeId, setLastActiveNodeId] = useState<string | undefined>(
outcomeNode.id
);
const activeNodeId = outcomeNode.id;
// TODO: filtering out empty nodes, in some instances there are some -> investigate why
const visibleNodes = findVisibleNodes(allNodes, activeNodeId, []).filter(
(node) => node?.id
);
if (data?.page) {
const outcomeNode = data.page?.outcomeNode ?? null;
const upstreamNodes = outcomeNode?.upstreamNodes ?? [];

const outcomeType = visibleNodes[0].quantity;

return (
<ErrorBackground className="mb-5">
<Container>
<Row>
<Col>
<StyledCard>
<CardBody>
{visibleNodes.map((node, index) => (
<OutcomeCardSet
key={node.id}
// Hacky solution to support different sub node titles depending on level
subNodesTitle={
index === 0
? t('outcome-sub-nodes')
: t('outcome-sub-nodes-secondary')
}
nodeMap={allNodes}
rootNode={node}
startYear={yearRange[0]}
endYear={yearRange[1]}
activeScenario={activeScenario?.name || ''}
parentColor="#666"
activeNodeId={
index < visibleNodes.length - 1
? visibleNodes[index + 1].id
: undefined
}
lastActiveNodeId={lastActiveNodeId}
setLastActiveNodeId={setLastActiveNodeId}
refetching={false}
/>
))}
</CardBody>
</StyledCard>
</Col>
</Row>
</Container>
</ErrorBackground>
);
const allNodes = new Map(upstreamNodes.map((node) => [node.id, node]));

allNodes.set(outcomeNode.id, outcomeNode);
//setLastActiveNodeId(outcomeNode.id);
const activeNodeId = outcomeNode.id;
// TODO: filtering out empty nodes, in some instances there are some -> investigate why
const visibleNodes = findVisibleNodes(allNodes, activeNodeId, []).filter(
(node) => node?.id
);

//const outcomeType = visibleNodes[0].quantity;

return (
<ErrorBackground className="mb-5">
<Container>
<Row>
<Col>
<StyledCard $disabled={refetching}>
<CardBody>
{visibleNodes.map((node, index) => (
<OutcomeCardSet
key={node.id}
// Hacky solution to support different sub node titles depending on level
subNodesTitle={
index === 0
? t('outcome-sub-nodes')
: t('outcome-sub-nodes-secondary')
}
nodeMap={allNodes}
rootNode={node}
startYear={yearRange[0]}
endYear={yearRange[1]}
activeScenario={activeScenario?.name || ''}
parentColor="#666"
activeNodeId={
index < visibleNodes.length - 1
? visibleNodes[index + 1].id
: undefined
}
lastActiveNodeId={lastActiveNodeId}
setLastActiveNodeId={setLastActiveNodeId}
refetching={refetching}
/>
))}
</CardBody>
</StyledCard>
</Col>
</Row>
</Container>
</ErrorBackground>
);
}
}
Loading

0 comments on commit 236be2a

Please sign in to comment.