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

feat: Dashboard time range filter and merging of cubes improvements #1644

Merged
merged 14 commits into from
Jul 1, 2024
Merged
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ You can also check the
eggs in the application
- Published charts now have a "more options" button with two actions - "Share"
and "Table view"
- Shared dashboard time range filters are now rendered as one `Date` filter
that can be used to filter all charts in the dashboard. Date range is
combined from all charts in the dashboard and the "lowest" time unit is used
in the time slider (e.g. if one chart has a year resolution and another has
a month resolution, the time slider will show months)
- Fixes
- Fixed using a time range brush in column charts when X dimension is a
`TemporalEntityDimension`
Expand All @@ -49,6 +54,9 @@ You can also check the
several charts e.g. in a dashboard
- Sub-theme filters now work correctly both in the search page and in the
dataset selection modal when adding a new chart based on another cube
- Changing dashboard time range filter presets now correctly updates the
charts
- Merged cubes are now done on a chart basis and are not shared between charts
- Style
- Cleaned up the chart footnotes and moved most of them to the metadata panel
– it means that the footnotes don't look broken anymore for charts based on
Expand All @@ -58,6 +66,8 @@ You can also check the
them
- Updated style of the buttons that open metadata panel
- Data download menu now opens on click, not hover
- Removed unnecessary row gaps in the dashboard layout when e.g. title or
description is missing

# [4.6.1] - 2024-06-05

Expand Down
6 changes: 2 additions & 4 deletions app/charts/column/chart-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,11 @@ const ChartColumns = memo((props: ChartProps<ColumnConfig>) => {
const { chartConfig, dimensions } = props;
const { fields, interactiveFiltersConfig } = chartConfig;
const filters = useChartConfigFilters(chartConfig);
const { sharedFilters } = useDashboardInteractiveFilters();

const dashboardFilters = useDashboardInteractiveFilters();
const showTimeBrush = shouldShowBrush(
interactiveFiltersConfig,
sharedFilters
dashboardFilters.timeRange
);

return (
<>
{fields.segment?.componentIri && fields.segment.type === "stacked" ? (
Expand Down
10 changes: 5 additions & 5 deletions app/charts/combo/chart-combo-line-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ const ChartComboLineColumn = memo(
(props: ChartProps<ComboLineColumnConfig>) => {
const { chartConfig } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

const dashboardFilters = useDashboardInteractiveFilters();
return (
<ComboLineColumnChart {...props}>
<ChartContainer type="comboLineColumn">
Expand All @@ -37,9 +36,10 @@ const ChartComboLineColumn = memo(
<AxisWidthBand />
<ComboLineColumn />
<InteractionColumns />
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
{shouldShowBrush(
interactiveFiltersConfig,
dashboardFilters.timeRange
) && <BrushTime />}
</ChartSvg>
<HoverDotMultiple />
<Ruler rotate />
Expand Down
10 changes: 5 additions & 5 deletions app/charts/combo/chart-combo-line-dual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ export const ChartComboLineDualVisualization = (
const ChartComboLineDual = memo((props: ChartProps<ComboLineDualConfig>) => {
const { chartConfig } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

const dashboardFilters = useDashboardInteractiveFilters();
return (
<ComboLineDualChart {...props}>
<ChartContainer type="comboLineDual">
Expand All @@ -36,9 +35,10 @@ const ChartComboLineDual = memo((props: ChartProps<ComboLineDualConfig>) => {
<AxisTimeDomain />
<ComboLineDual />
<InteractionHorizontal />
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
{shouldShowBrush(
interactiveFiltersConfig,
dashboardFilters.timeRange
) && <BrushTime />}
</ChartSvg>
<HoverDotMultiple />
<Ruler />
Expand Down
9 changes: 5 additions & 4 deletions app/charts/combo/chart-combo-line-single.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,18 @@ const ChartComboLineSingle = memo(
(props: ChartProps<ComboLineSingleConfig>) => {
const { chartConfig } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();
const dashboardFilters = useDashboardInteractiveFilters();
return (
<ComboLineSingleChart {...props}>
<ChartContainer type="comboLineSingle">
<ChartSvg>
<AxisHeightLinear /> <AxisTime /> <AxisTimeDomain />
<ComboLineSingle />
<InteractionHorizontal />
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
{shouldShowBrush(
interactiveFiltersConfig,
dashboardFilters.timeRange
) && <BrushTime />}
</ChartSvg>
<HoverDotMultiple />
<Ruler />
Expand Down
10 changes: 5 additions & 5 deletions app/charts/line/chart-lines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export const ChartLinesVisualization = (
const ChartLines = memo((props: ChartProps<LineConfig>) => {
const { chartConfig } = props;
const { fields, interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

const dashboardFilters = useDashboardInteractiveFilters();
return (
<LineChart {...props}>
<ChartContainer type="line">
Expand All @@ -40,9 +39,10 @@ const ChartLines = memo((props: ChartProps<LineConfig>) => {
<Lines />
<ErrorWhiskers />
<InteractionHorizontal />
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
{shouldShowBrush(
interactiveFiltersConfig,
dashboardFilters.timeRange
) && <BrushTime />}
</ChartSvg>

<Ruler />
Expand Down
12 changes: 3 additions & 9 deletions app/charts/shared/brush/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import {
ComboLineColumnConfig,
ComboLineDualConfig,
ComboLineSingleConfig,
DashboardTimeRangeFilter,
LineConfig,
} from "@/configurator";
import { Observation } from "@/domain/data";
import { useFormatFullDateAuto } from "@/formatters";
import {
SharedFilter,
useChartInteractiveFilters,
useInteractiveFiltersGetState,
} from "@/stores/interactive-filters";
Expand All @@ -44,16 +44,10 @@ export const shouldShowBrush = (
| ColumnConfig
)["interactiveFiltersConfig"]
| undefined,
sharedFilters: SharedFilter[] | undefined
dashboardTimeRange: DashboardTimeRangeFilter | undefined
) => {
const chartTimeRange = interactiveFiltersConfig?.timeRange;
const chartTimeRangeIri = chartTimeRange?.componentIri;
const sharedFilter = sharedFilters?.find(
(x) => x.type === "timeRange" && x.componentIri === chartTimeRangeIri
);
return (
(chartTimeRange?.active && !sharedFilter) || sharedFilter?.active == false
);
return chartTimeRange?.active && !dashboardTimeRange?.active;
};

export const BrushTime = () => {
Expand Down
20 changes: 2 additions & 18 deletions app/charts/shared/chart-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import {
isTemporalEntityDimension,
} from "@/domain/data";
import { Has } from "@/domain/types";
import { getOriginalIris, isJoinById } from "@/graphql/join";
import { ScaleType, TimeUnit } from "@/graphql/resolver-types";
import {
useChartInteractiveFilters,
Expand Down Expand Up @@ -511,24 +510,11 @@ export const useChartData = (
const interactiveToTime = timeRange.to?.getTime();
const dashboardFilters = useDashboardInteractiveFilters();
const interactiveTimeRangeFilters = useMemo(() => {
const isDashboardFilterActive = !!dashboardFilters.sharedFilters.find(
(f) => {
const timeRangeFilterIri = interactiveTimeRange?.componentIri;
if (f.type !== "timeRange" || !timeRangeFilterIri) {
return false;
}
return isJoinById(timeRangeFilterIri)
? getOriginalIris(timeRangeFilterIri, chartConfig).includes(
f.componentIri
)
: f.componentIri === timeRangeFilterIri;
}
);
const interactiveTimeRangeFilter: ValuePredicate | null =
getXAsDate &&
interactiveFromTime &&
interactiveToTime &&
(interactiveTimeRange?.active || isDashboardFilterActive)
(interactiveTimeRange?.active || dashboardFilters.timeRange?.active)
? (d: Observation) => {
const time = getXAsDate(d).getTime();
return time >= interactiveFromTime && time <= interactiveToTime;
Expand All @@ -537,13 +523,11 @@ export const useChartData = (

return interactiveTimeRangeFilter ? [interactiveTimeRangeFilter] : [];
}, [
dashboardFilters.sharedFilters,
dashboardFilters.timeRange,
getXAsDate,
interactiveFromTime,
interactiveToTime,
interactiveTimeRange?.active,
interactiveTimeRange?.componentIri,
chartConfig,
]);

// interactive time slider
Expand Down
17 changes: 10 additions & 7 deletions app/components/chart-filters-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ export const ChartFiltersList = ({
sourceType: dataSource.type,
sourceUrl: dataSource.url,
locale,
cubeFilters: cubeQueryFilters.map((filter) => ({
iri: filter.iri,
componentIris: filter.componentIris,
filters: filter.filters,
joinBy: filter.joinBy,
loadValues: true,
})),
cubeFilters: chartConfig.cubes.map((cube) => {
const f = cubeQueryFilters.find((f) => f.iri === cube.iri);
return {
iri: f?.iri ?? cube.iri,
componentIris: f?.componentIris,
filters: f?.filters,
joinBy: f?.joinBy,
loadValues: true,
};
}),
},
});
const allFilters = useMemo(() => {
Expand Down
2 changes: 1 addition & 1 deletion app/components/chart-footnotes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const ChartFootnotes = ({
const formatLocale = useTimeFormatLocale();

return (
<Box sx={{ "& > :not(:last-child)": { mb: 3 } }}>
<Box sx={{ mt: 1, "& > :not(:last-child)": { mb: 3 } }}>
{data?.dataCubesMetadata.map((metadata) => (
<div key={metadata.iri}>
<ChartFootnotesLegend
Expand Down
3 changes: 2 additions & 1 deletion app/components/chart-panel-layout-tall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const ChartPanelLayoutTallRow = (props: ChartPanelLayoutTallRowProps) => {
xs: "1fr",
md: "calc(50% - 8px) calc(50% - 8px)",
},
gap: "16px",
gridAutoRows: "min-content",
columnGap: 4,
}}
>
{row.chartConfigs.map(row.renderChart)}
Expand Down
17 changes: 7 additions & 10 deletions app/components/chart-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ const ChartPreviewInner = (props: ChartPreviewInnerProps) => {
>
<Flex
sx={{
height: "fit-content",
justifyContent:
configuring || chartConfig.meta.title[locale]
? "space-between"
Expand All @@ -484,12 +485,10 @@ const ChartPreviewInner = (props: ChartPreviewInnerProps) => {
: undefined
}
/>
) : // We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
state.layout.type === "dashboard" ? (
<span>&nbsp;</span>
) : (
<span />
// We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
<span style={{ height: 1 }} />
)}
<Box
sx={{
Expand Down Expand Up @@ -519,12 +518,10 @@ const ChartPreviewInner = (props: ChartPreviewInnerProps) => {
: undefined
}
/>
) : // We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
state.layout.type === "dashboard" ? (
<span>&nbsp;</span>
) : (
<span />
// We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
<span style={{ height: 1 }} />
)}
<ChartControls
dataSource={dataSource}
Expand Down
17 changes: 7 additions & 10 deletions app/components/chart-published.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ const ChartPublishedInnerImpl = (props: ChartPublishInnerProps) => {
<InteractiveFiltersChartProvider chartConfigKey={chartConfig.key}>
<Flex
sx={{
height: "fit-content",
justifyContent: meta.title[locale]
? "space-between"
: "flex-end",
Expand All @@ -335,12 +336,10 @@ const ChartPublishedInnerImpl = (props: ChartPublishInnerProps) => {
text={meta.title[locale]}
smaller={state.layout.type === "dashboard"}
/>
) : // We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
state.layout.type === "dashboard" ? (
<span>&nbsp;</span>
) : (
<span />
// We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
<span style={{ height: 1 }} />
)}
<ChartMoreButton
configKey={configKey}
Expand All @@ -352,12 +351,10 @@ const ChartPublishedInnerImpl = (props: ChartPublishInnerProps) => {
text={meta.description[locale]}
smaller={state.layout.type === "dashboard"}
/>
) : // We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
state.layout.type === "dashboard" ? (
<span>&nbsp;</span>
) : (
<span />
// We need to have a span here to keep the space between the
// title and the chart (subgrid layout)
<span style={{ height: 1 }} />
)}
<ChartControls
dataSource={dataSource}
Expand Down
Loading
Loading