From c0c4773e2e393e335857fe3af37d915875e4719b Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 13:25:14 +0200 Subject: [PATCH 01/10] style: Update metadata and filters positions + styles --- app/charts/shared/chart-data-filters.tsx | 19 +++++---- app/components/chart-preview.tsx | 50 ++++++++++++------------ app/components/chart-published.tsx | 35 +++++++++-------- app/components/chart-shared.tsx | 18 +++++++++ app/components/metadata-panel.tsx | 14 +++---- 5 files changed, 81 insertions(+), 55 deletions(-) create mode 100644 app/components/chart-shared.tsx diff --git a/app/charts/shared/chart-data-filters.tsx b/app/charts/shared/chart-data-filters.tsx index 80fe5bc75..dbdce263a 100644 --- a/app/charts/shared/chart-data-filters.tsx +++ b/app/charts/shared/chart-data-filters.tsx @@ -128,10 +128,9 @@ export const ChartDataFilters = (props: ChartDataFiltersProps) => { ) : ( - + { {componentIris.length > 0 && ( )} diff --git a/app/components/chart-preview.tsx b/app/components/chart-preview.tsx index 8f8198c9b..5018c1878 100644 --- a/app/components/chart-preview.tsx +++ b/app/components/chart-preview.tsx @@ -6,12 +6,12 @@ import { useDraggable, useDroppable, } from "@dnd-kit/core"; -import { t, Trans } from "@lingui/macro"; +import { Trans, t } from "@lingui/macro"; import { Box, IconButton, useEventCallback } from "@mui/material"; import Head from "next/head"; import React, { - forwardRef, ReactNode, + forwardRef, useCallback, useMemo, useState, @@ -29,6 +29,7 @@ import { ChartWrapperProps, } from "@/components/chart-panel"; import { chartPanelLayoutGridClasses } from "@/components/chart-panel-layout-grid"; +import { ChartFiltersMetadataWrapper } from "@/components/chart-shared"; import { ChartTablePreviewProvider, useChartTablePreview, @@ -46,10 +47,10 @@ import { BANNER_MARGIN_TOP } from "@/components/presence"; import { ChartConfig, DataSource, + Layout, getChartConfig, hasChartConfigs, isConfiguring, - Layout, useConfiguratorState, } from "@/configurator"; import { Description, Title } from "@/configurator/components/annotators"; @@ -540,17 +541,7 @@ export const ChartPreviewInner = (props: ChartPreviewInnerProps) => { // title and the chart (subgrid layout) )} - - {!disableMetadataPanel && ( - - )} - {actionElementSlot} - + {actionElementSlot} {configuring || chartConfig.meta.description[locale] ? ( { // title and the chart (subgrid layout) )} - {chartConfig.interactiveFiltersConfig?.dataFilters.active ? ( - - ) : ( - // We need to have a span here to keep the space between the - // description and the chart (subgrid layout) - - )} + + ) + } + metadataPanel={ + !disableMetadataPanel && ( + + ) + } + />
{ // title and the chart (subgrid layout) )} - {meta.description[locale] ? ( @@ -356,16 +351,24 @@ const ChartPublishedInner = (props: ChartPublishInnerProps) => { // title and the chart (subgrid layout) )} - {chartConfig.interactiveFiltersConfig?.dataFilters.active ? ( - - ) : ( - // We need to have a span here to keep the space between the - // description and the chart (subgrid layout) - - )} + + ) + } + metadataPanel={ + + } + />
{ + return ( + + {/* As metadata is absolutely positioned, we need to give the container some height so it's correctly aligned. */} + {filters ? filters :
} + {metadataPanel} + + ); +}; diff --git a/app/components/metadata-panel.tsx b/app/components/metadata-panel.tsx index 16047b29a..6de28cc69 100644 --- a/app/components/metadata-panel.tsx +++ b/app/components/metadata-panel.tsx @@ -89,7 +89,11 @@ const useDrawerStyles = makeStyles((theme) => { const useOtherStyles = makeStyles((theme) => { return { toggleButton: { - alignSelf: "flex-start", + position: "absolute", + right: 0, + top: "-0.15rem", + height: "fit-content", + padding: 0, }, header: { display: "flex", @@ -267,7 +271,6 @@ export const MetadataPanel = (props: MetadataPanelProps) => { return ( <> - { const ToggleButton = ({ onClick }: { onClick: () => void }) => { const classes = useOtherStyles(); - return ( )} - {componentIris.length > 0 && ( Date: Mon, 3 Jun 2024 15:44:41 +0200 Subject: [PATCH 04/10] fix: Metadata panel width on small screens --- app/components/metadata-panel.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/metadata-panel.tsx b/app/components/metadata-panel.tsx index 6de28cc69..28eb7d1a1 100644 --- a/app/components/metadata-panel.tsx +++ b/app/components/metadata-panel.tsx @@ -71,15 +71,15 @@ const useDrawerStyles = makeStyles((theme) => { return { root: { position: "static", - "& > .MuiPaper-root": { - top: ({ top }: { top: number }) => top, + top: ({ top }) => top, bottom: 0, - width: DRAWER_WIDTH, + width: "100%", + maxWidth: DRAWER_WIDTH, height: "auto", paddingLeft: theme.spacing(4), paddingRight: theme.spacing(4), - borderRight: `1px ${theme.palette.divider} solid`, + borderRight: `1px solid ${theme.palette.divider}`, boxShadow: "none", }, }, From 944c7f43e23bba54e26026a657fb9135bc3ca0ab Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 16:21:42 +0200 Subject: [PATCH 05/10] refactor: Prepare for separation of chart filters toggle and list --- app/components/chart-preview.tsx | 35 +++++-------------- app/components/chart-published.tsx | 29 +++++----------- app/components/chart-shared.tsx | 56 ++++++++++++++++++++++++------ app/components/metadata-panel.tsx | 4 --- 4 files changed, 64 insertions(+), 60 deletions(-) diff --git a/app/components/chart-preview.tsx b/app/components/chart-preview.tsx index 5018c1878..806b7400f 100644 --- a/app/components/chart-preview.tsx +++ b/app/components/chart-preview.tsx @@ -18,7 +18,6 @@ import React, { } from "react"; import { DataSetTable } from "@/browse/datatable"; -import { ChartDataFilters } from "@/charts/shared/chart-data-filters"; import { LoadingStateProvider } from "@/charts/shared/chart-loading-state"; import { ArrowMenu } from "@/components/arrow-menu"; import { ChartErrorBoundary } from "@/components/chart-error-boundary"; @@ -29,7 +28,7 @@ import { ChartWrapperProps, } from "@/components/chart-panel"; import { chartPanelLayoutGridClasses } from "@/components/chart-panel-layout-grid"; -import { ChartFiltersMetadataWrapper } from "@/components/chart-shared"; +import { ChartControls } from "@/components/chart-shared"; import { ChartTablePreviewProvider, useChartTablePreview, @@ -42,7 +41,6 @@ import Flex from "@/components/flex"; import { Checkbox } from "@/components/form"; import { HintYellow } from "@/components/hint"; import { MenuActionItem } from "@/components/menu-action-item"; -import { MetadataPanel } from "@/components/metadata-panel"; import { BANNER_MARGIN_TOP } from "@/components/presence"; import { ChartConfig, @@ -428,13 +426,11 @@ const SingleURLsPreview = (props: SingleURLsPreviewProps) => { type ChartPreviewInnerProps = ChartPreviewProps & { chartKey?: string | null; actionElementSlot?: ReactNode; - disableMetadataPanel?: boolean; children?: React.ReactNode; }; export const ChartPreviewInner = (props: ChartPreviewInnerProps) => { - const { dataSource, chartKey, actionElementSlot, disableMetadataPanel } = - props; + const { dataSource, chartKey, actionElementSlot } = props; const [state, dispatch] = useConfiguratorState(); const configuring = isConfiguring(state); const chartConfig = getChartConfig(state, chartKey); @@ -563,26 +559,13 @@ export const ChartPreviewInner = (props: ChartPreviewInnerProps) => { // title and the chart (subgrid layout) )} - - ) - } - metadataPanel={ - !disableMetadataPanel && ( - - ) - } +
{ // title and the chart (subgrid layout) )} - - ) - } - metadataPanel={ - - } + +
, + "dataSource" | "chartConfigs" + >; }) => { + const disableFilters = + !chartConfig.interactiveFiltersConfig?.dataFilters.active; return ( - - {/* As metadata is absolutely positioned, we need to give the container some height so it's correctly aligned. */} - {filters ? filters :
} - {metadataPanel} + + + {!disableFilters && ( + + )} + + + + + + + ); }; diff --git a/app/components/metadata-panel.tsx b/app/components/metadata-panel.tsx index 28eb7d1a1..e4ac0aec1 100644 --- a/app/components/metadata-panel.tsx +++ b/app/components/metadata-panel.tsx @@ -89,10 +89,6 @@ const useDrawerStyles = makeStyles((theme) => { const useOtherStyles = makeStyles((theme) => { return { toggleButton: { - position: "absolute", - right: 0, - top: "-0.15rem", - height: "fit-content", padding: 0, }, header: { From a77c01c447740ca04af599e9c5420791bf627299 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 16:23:39 +0200 Subject: [PATCH 06/10] refactor: Separate ChartDataFiltersToggle and ChartDataFiltersList --- app/charts/shared/chart-data-filters.tsx | 104 ++++++++++++++--------- app/components/chart-shared.tsx | 16 ++-- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/app/charts/shared/chart-data-filters.tsx b/app/charts/shared/chart-data-filters.tsx index 491df1eb5..1affd5c08 100644 --- a/app/charts/shared/chart-data-filters.tsx +++ b/app/charts/shared/chart-data-filters.tsx @@ -62,28 +62,27 @@ type PreparedFilter = { mappedFilters: Filters; }; -type ChartDataFiltersProps = { +export const useChartDataFiltersState = ({ + dataSource, + chartConfig, +}: { dataSource: DataSource; chartConfig: ChartConfig; -}; - -export const ChartDataFilters = (props: ChartDataFiltersProps) => { - const { dataSource, chartConfig } = props; - const { loading } = useLoadingState(); - const dataFilters = useChartInteractiveFilters((d) => d.dataFilters); +}) => { const componentIris = chartConfig.interactiveFiltersConfig?.dataFilters .componentIris as string[]; - const queryFilters = useQueryFilters({ - chartConfig, - allowNoneValues: true, - componentIris, - }); const [open, setOpen] = useState(false); useEffect(() => { if (componentIris.length === 0) { setOpen(false); } }, [componentIris.length]); + const { loading } = useLoadingState(); + const queryFilters = useQueryFilters({ + chartConfig, + allowNoneValues: true, + componentIris, + }); const preparedFilters: PreparedFilter[] | undefined = useMemo(() => { return chartConfig.cubes.map((cube) => { const cubeQueryFilters = queryFilters.find( @@ -116,7 +115,22 @@ export const ChartDataFilters = (props: ChartDataFiltersProps) => { chartConfig, preparedFilters, }); + return { + open, + setOpen, + dataSource, + chartConfig, + loading, + error, + preparedFilters, + componentIris, + }; +}; +export const ChartDataFiltersToggle = ( + props: ReturnType +) => { + const { open, setOpen, loading, error, componentIris } = props; return error ? ( @@ -174,36 +188,50 @@ export const ChartDataFilters = (props: ChartDataFiltersProps) => { )} - {componentIris.length > 0 && ( - - {preparedFilters?.map(({ cubeIri, interactiveFilters }) => - Object.keys(interactiveFilters).map((dimensionIri) => ( - - )) - )} - - )} ); }; +export const ChartDataFiltersList = ( + props: ReturnType +) => { + const { + open, + dataSource, + chartConfig, + loading, + preparedFilters, + componentIris, + } = props; + const dataFilters = useChartInteractiveFilters((d) => d.dataFilters); + return componentIris.length > 0 ? ( + + {preparedFilters?.map(({ cubeIri, interactiveFilters }) => + Object.keys(interactiveFilters).map((dimensionIri) => ( + + )) + )} + + ) : null; +}; + type DataFilterProps = { cubeIri: string; dimensionIri: string; diff --git a/app/components/chart-shared.tsx b/app/components/chart-shared.tsx index ba4cfd696..546f5a895 100644 --- a/app/components/chart-shared.tsx +++ b/app/components/chart-shared.tsx @@ -1,7 +1,11 @@ import { Box } from "@mui/material"; import { ComponentProps } from "react"; -import { ChartDataFilters } from "@/charts/shared/chart-data-filters"; +import { + ChartDataFiltersList, + ChartDataFiltersToggle, + useChartDataFiltersState, +} from "@/charts/shared/chart-data-filters"; import { MetadataPanel } from "@/components/metadata-panel"; import { ChartConfig, DataSource } from "@/configurator"; @@ -19,6 +23,10 @@ export const ChartControls = ({ }) => { const disableFilters = !chartConfig.interactiveFiltersConfig?.dataFilters.active; + const chartFiltersState = useChartDataFiltersState({ + dataSource, + chartConfig, + }); return ( - {!disableFilters && ( - - )} + {!disableFilters && } - + {!disableFilters && } ); From 6fbe42c6ff4ea666142a240607aa292db29187f0 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 16:28:21 +0200 Subject: [PATCH 07/10] refactor: Clean up --- app/charts/shared/chart-data-filters.tsx | 78 +++++++++++------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/app/charts/shared/chart-data-filters.tsx b/app/charts/shared/chart-data-filters.tsx index 1affd5c08..5155631a2 100644 --- a/app/charts/shared/chart-data-filters.tsx +++ b/app/charts/shared/chart-data-filters.tsx @@ -40,7 +40,6 @@ import { import { useTimeFormatLocale } from "@/formatters"; import { useDataCubesComponentsQuery } from "@/graphql/hooks"; import { - DataCubeObservationFilter, PossibleFiltersDocument, PossibleFiltersQuery, PossibleFiltersQueryVariables, @@ -52,6 +51,7 @@ import { useChartInteractiveFilters, useInteractiveFiltersGetState, } from "@/stores/interactive-filters"; +import { assert } from "@/utils/assert"; import { hierarchyToOptions } from "@/utils/hierarchy"; import useEvent from "@/utils/use-event"; @@ -69,8 +69,9 @@ export const useChartDataFiltersState = ({ dataSource: DataSource; chartConfig: ChartConfig; }) => { - const componentIris = chartConfig.interactiveFiltersConfig?.dataFilters - .componentIris as string[]; + const componentIris = + chartConfig.interactiveFiltersConfig?.dataFilters.componentIris; + assert(componentIris, "Data filters are not enabled for this chart."); const [open, setOpen] = useState(false); useEffect(() => { if (componentIris.length === 0) { @@ -83,29 +84,25 @@ export const useChartDataFiltersState = ({ allowNoneValues: true, componentIris, }); - const preparedFilters: PreparedFilter[] | undefined = useMemo(() => { + const preparedFilters = useMemo(() => { return chartConfig.cubes.map((cube) => { - const cubeQueryFilters = queryFilters.find( - (d) => d.iri === cube.iri - ) as DataCubeObservationFilter; + const cubeQueryFilters = queryFilters.find((d) => d.iri === cube.iri); + assert(cubeQueryFilters, "Cube query filters not found."); const filtersByMappingStatus = getFiltersByMappingStatus(chartConfig, { cubeIri: cube.iri, }); const { unmappedFilters, mappedFilters } = filtersByMappingStatus; const unmappedKeys = Object.keys(unmappedFilters); - const unmappedFiltersArray = Object.entries( + const unmappedEntries = Object.entries( cubeQueryFilters.filters as Filters ).filter(([k]) => unmappedKeys.includes(k)); - const interactiveFiltersArray = unmappedFiltersArray.filter(([k]) => + const interactiveFiltersList = unmappedEntries.filter(([k]) => componentIris.includes(k) ); - return { cubeIri: cube.iri, - interactiveFilters: Object.fromEntries(interactiveFiltersArray), - unmappedFilters: Object.fromEntries( - unmappedFiltersArray - ) as SingleFilters, + interactiveFilters: Object.fromEntries(interactiveFiltersList), + unmappedFilters: Object.fromEntries(unmappedEntries) as SingleFilters, mappedFilters, }; }); @@ -214,25 +211,35 @@ export const ChartDataFiltersList = ( gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", }} > - {preparedFilters?.map(({ cubeIri, interactiveFilters }) => - Object.keys(interactiveFilters).map((dimensionIri) => ( - - )) - )} + {preparedFilters.map(({ cubeIri, interactiveFilters }) => { + return Object.keys(interactiveFilters).map((dimensionIri) => { + return ( + + ); + }); + })} ) : null; }; -type DataFilterProps = { +const DataFilter = ({ + cubeIri, + dimensionIri, + dataSource, + chartConfig, + dataFilters, + interactiveFilters, + disabled, +}: { cubeIri: string; dimensionIri: string; dataSource: DataSource; @@ -240,18 +247,7 @@ type DataFilterProps = { dataFilters: DataFilters; interactiveFilters: Filters; disabled: boolean; -}; - -const DataFilter = (props: DataFilterProps) => { - const { - cubeIri, - dimensionIri, - dataSource, - chartConfig, - dataFilters, - interactiveFilters, - disabled, - } = props; +}) => { const locale = useLocale(); const filters = useChartConfigFilters(chartConfig); const chartLoadingState = useLoadingState(); From 7d8e288c80cfaf6810d32b5d82e1d04264bc8203 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 16:32:26 +0200 Subject: [PATCH 08/10] fix: Loading indicator animation --- app/configurator/components/field.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/configurator/components/field.tsx b/app/configurator/components/field.tsx index 629a4d8c1..5756abb79 100644 --- a/app/configurator/components/field.tsx +++ b/app/configurator/components/field.tsx @@ -849,7 +849,7 @@ export const ColorPickerField = ({ export const LoadingIndicator = () => { const classes = useStyles(); - return ; + return ; }; export const FieldLabel = ({ From a5e26b423e5b4c6c91bcd160a8b048a873f12d10 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 16:54:23 +0200 Subject: [PATCH 09/10] refactor: Rename --- app/components/chart-shared.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/components/chart-shared.tsx b/app/components/chart-shared.tsx index 546f5a895..473db9d7e 100644 --- a/app/components/chart-shared.tsx +++ b/app/components/chart-shared.tsx @@ -21,8 +21,7 @@ export const ChartControls = ({ "dataSource" | "chartConfigs" >; }) => { - const disableFilters = - !chartConfig.interactiveFiltersConfig?.dataFilters.active; + const showFilters = chartConfig.interactiveFiltersConfig?.dataFilters.active; const chartFiltersState = useChartDataFiltersState({ dataSource, chartConfig, @@ -37,7 +36,7 @@ export const ChartControls = ({ }} > - {!disableFilters && } + {showFilters && } - {!disableFilters && } + {showFilters && } ); From afc487230f285d33b35f3b069ec691f4556d66fb Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Mon, 3 Jun 2024 17:05:50 +0200 Subject: [PATCH 10/10] style: Add margin top --- app/components/chart-shared.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/components/chart-shared.tsx b/app/components/chart-shared.tsx index 473db9d7e..8a825d1d4 100644 --- a/app/components/chart-shared.tsx +++ b/app/components/chart-shared.tsx @@ -33,6 +33,7 @@ export const ChartControls = ({ gridTemplateAreas: ` "filtersToggle metadataToggle" "filtersList filtersList"`, + mt: 4, }} >