Skip to content

Commit

Permalink
refact(overview): use hook for calculating chart clickability
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlougheed committed Nov 27, 2024
1 parent 78c4b2f commit b3f9ece
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 37 deletions.
6 changes: 3 additions & 3 deletions src/js/components/Overview/ChartCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import SmallChartCardTitle from '@/components/Util/SmallChartCardTitle';
const CARD_STYLE: CSSProperties = { height: '415px', borderRadius: '11px', ...BOX_SHADOW };
const ROW_EMPTY_STYLE: CSSProperties = { height: `${CHART_HEIGHT}px` };

const ChartCard = memo(({ section, chart, onRemoveChart }: ChartCardProps) => {
const ChartCard = memo(({ section, chart, onRemoveChart, searchable }: ChartCardProps) => {
const t = useTranslationFn();
const containerRef = useRef<HTMLDivElement>(null);
const width = useElementWidth(containerRef, chart.width);
Expand All @@ -21,7 +21,6 @@ const ChartCard = memo(({ section, chart, onRemoveChart }: ChartCardProps) => {
data,
field: { id, description, title, config },
chartConfig,
isSearchable,
} = chart;

const extraOptionsData = [
Expand Down Expand Up @@ -59,7 +58,7 @@ const ChartCard = memo(({ section, chart, onRemoveChart }: ChartCardProps) => {
units={config?.units || ''}
id={id}
key={id}
isClickable={isSearchable}
isClickable={!!searchable}
/>
) : (
<Row style={ROW_EMPTY_STYLE} justify="center" align="middle">
Expand All @@ -77,6 +76,7 @@ export interface ChartCardProps {
section: string;
chart: ChartDataField;
onRemoveChart: (arg: { section: string; id: string }) => void;
searchable?: boolean;
}

export default ChartCard;
13 changes: 11 additions & 2 deletions src/js/components/Overview/OverviewDisplayData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ChartCard from './ChartCard';

import type { ChartDataField } from '@/types/data';

const OverviewDisplayData = ({ section, allCharts }: OverviewDisplayDataProps) => {
const OverviewDisplayData = ({ section, allCharts, searchableFields }: OverviewDisplayDataProps) => {
const dispatch = useAppDispatch();
const isSmallScreen = useSmallScreen();

Expand All @@ -31,7 +31,15 @@ const OverviewDisplayData = ({ section, allCharts }: OverviewDisplayDataProps) =
);

const renderItem = (chart: ChartDataField) => {
return <ChartCard key={chart.id} chart={chart} section={section} onRemoveChart={onRemoveChart} />;
return (
<ChartCard
key={chart.id}
chart={chart}
section={section}
onRemoveChart={onRemoveChart}
searchable={searchableFields.has(chart.id)}
/>
);
};

if (isSmallScreen) {
Expand All @@ -48,6 +56,7 @@ const OverviewDisplayData = ({ section, allCharts }: OverviewDisplayDataProps) =
export interface OverviewDisplayDataProps {
section: string;
allCharts: ChartDataField[];
searchableFields: Set<string>;
}

export default OverviewDisplayData;
12 changes: 10 additions & 2 deletions src/js/components/Overview/OverviewSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import OverviewDisplayData from './OverviewDisplayData';
import { useTranslationFn } from '@/hooks';
import type { ChartDataField } from '@/types/data';

const OverviewSection = ({ title, chartData }: { title: string; chartData: ChartDataField[] }) => {
const OverviewSection = ({
title,
chartData,
searchableFields,
}: {
title: string;
chartData: ChartDataField[];
searchableFields: Set<string>;
}) => {
const t = useTranslationFn();

return (
<Space direction="vertical" size={0} style={{ width: '100%' }}>
<Typography.Title level={3}>{t(title)}</Typography.Title>
<OverviewDisplayData section={title} allCharts={chartData} />
<OverviewDisplayData section={title} allCharts={chartData} searchableFields={searchableFields} />
</Space>
);
};
Expand Down
13 changes: 6 additions & 7 deletions src/js/components/Overview/PublicOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Loader from '@/components/Loader';
import Dataset from '@/components/Provenance/Dataset';

import { useAppSelector } from '@/hooks';
import { useSearchableFields } from '@/features/data/hooks';
import { useSelectedProject, useSelectedScope } from '@/features/metadata/hooks';
import { useTranslation } from 'react-i18next';
import { RequestStatus } from '@/types/requests';
Expand All @@ -28,11 +29,7 @@ const PublicOverview = () => {
const [drawerVisible, setDrawerVisible] = useState(false);
const [aboutContent, setAboutContent] = useState('');

const {
isFetchingData: isFetchingOverviewData,
isContentPopulated,
sections,
} = useAppSelector((state) => state.data);
const { isFetchingData: isFetchingOverviewData, sections } = useAppSelector((state) => state.data);
const { status: aboutStatus, about } = useAppSelector((state) => state.content);

const selectedProject = useSelectedProject();
Expand All @@ -59,7 +56,9 @@ const PublicOverview = () => {
saveToLocalStorage(sections);
}, [sections]);

return !isContentPopulated || isFetchingOverviewData ? (
const searchableFields = useSearchableFields();

return isFetchingOverviewData ? (
<Loader />
) : (
<>
Expand Down Expand Up @@ -94,7 +93,7 @@ const PublicOverview = () => {
<Col flex={1}>
{displayedSections.map(({ sectionTitle, charts }, i) => (
<div key={i} className="overview">
<OverviewSection title={sectionTitle} chartData={charts} />
<OverviewSection title={sectionTitle} chartData={charts} searchableFields={searchableFields} />
</div>
))}
<LastIngestionInfo />
Expand Down
22 changes: 1 addition & 21 deletions src/js/features/data/data.store.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';

import { makeGetDataRequestThunk } from './makeGetDataRequest.thunk';
import type { Sections } from '@/types/data';
import type { Counts } from '@/types/overviewResponse';
import type { QueryState } from '@/features/search/query.store';

export const populateClickable = createAsyncThunk<string[], void, { state: { query: QueryState } }>(
'data/populateClickable',
async (_, { getState }) => {
return getState()
.query.querySections.flatMap((section) => section.fields)
.map((field) => field.id);
}
);

interface DataState {
isFetchingData: boolean;
isContentPopulated: boolean;
defaultLayout: Sections;
sections: Sections;
counts: Counts;
}

const initialState: DataState = {
isFetchingData: true,
isContentPopulated: false,
defaultLayout: [],
sections: [],
counts: {
Expand Down Expand Up @@ -101,14 +89,6 @@ const data = createSlice({
})
.addCase(makeGetDataRequestThunk.rejected, (state) => {
state.isFetchingData = false;
})
.addCase(populateClickable.fulfilled, (state, { payload }) => {
state.sections.forEach((section) => {
section.charts.forEach((chart) => {
chart.isSearchable = payload.includes(chart.id);
});
});
state.isContentPopulated = true;
});
},
});
Expand Down
14 changes: 14 additions & 0 deletions src/js/features/data/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useMemo } from 'react';
import { useSearchQuery } from '@/features/search/hooks';

export const useSearchableFields = () => {
/**
* Hook which calculates a set of searchable fields (which share IDs with charts), which can be used, for example, to
* choose whether to add a click event to a chart for the field.
*/
const { querySections } = useSearchQuery();
return useMemo(
() => new Set(querySections.flatMap((section) => section.fields).map((field) => field.id)),
[querySections]
);
};
1 change: 0 additions & 1 deletion src/js/features/data/makeGetDataRequest.thunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export const makeGetDataRequestThunk = createAsyncThunk<
// Initial display state
isDisplayed: i < MAX_CHARTS,
width: chart.width ?? DEFAULT_CHART_WIDTH, // initial configured width; users can change it from here
isSearchable: false,
};
};

Expand Down
1 change: 0 additions & 1 deletion src/js/types/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export interface ChartDataField {
// display options:
isDisplayed: boolean; // whether the chart is currently displayed (state data)
width: number; // current width (state data); initial data taken from chart config
isSearchable: boolean; // whether the field is searchable
}

export interface ChartData {
Expand Down

0 comments on commit b3f9ece

Please sign in to comment.