Skip to content

Commit

Permalink
Merge pull request #1292 from visualize-admin/feat/add-layout-step
Browse files Browse the repository at this point in the history
feat: Add layout step
  • Loading branch information
bprusinowski authored Dec 8, 2023
2 parents 610a170 + 1a03e24 commit 644b9da
Show file tree
Hide file tree
Showing 49 changed files with 1,838 additions and 851 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ You can also check the [release page](https://github.com/visualize-admin/visuali
## Unreleased

- Features
- Added layout step to the chart creation flow (tab layout, vertical or tall dashboard)
- Localized cube landing pages are now supported (dcat:landingPage) 🌎
- Temporal dimension filters can now be pinned to dynamically use the most recent value (so that published charts automatically switch to it when the cube is updated) 📅
- Temporal dimensions can now be used as segmentation fields (excluding area and line charts)
Expand Down
14 changes: 7 additions & 7 deletions app/browser/select-dataset-step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ import {
smoothPresenceProps,
} from "@/components/presence";
import {
PanelBodyWrapper,
PanelLayout,
PanelLeftWrapper,
PanelMiddleWrapper,
} from "@/configurator/components/layout";
import { truthy } from "@/domain/types";
import {
Expand Down Expand Up @@ -277,8 +276,8 @@ const SelectDatasetStepContent = () => {
</MotionBox>
)}
</AnimatePresence>
<PanelLayout className={classes.panelLayout} key="panel">
<PanelLeftWrapper className={classes.panelLeft}>
<PanelLayout type="LM" className={classes.panelLayout} key="panel">
<PanelBodyWrapper type="L" className={classes.panelLeft}>
<AnimatePresence mode="wait">
{dataset ? (
<MotionBox
Expand Down Expand Up @@ -310,8 +309,9 @@ const SelectDatasetStepContent = () => {
</MotionBox>
)}
</AnimatePresence>
</PanelLeftWrapper>
<PanelMiddleWrapper
</PanelBodyWrapper>
<PanelBodyWrapper
type="M"
className={classes.panelMiddle}
sx={{ maxWidth: 1040 }}
>
Expand Down Expand Up @@ -383,7 +383,7 @@ const SelectDatasetStepContent = () => {
</MotionBox>
)}
</AnimatePresence>
</PanelMiddleWrapper>
</PanelBodyWrapper>
</PanelLayout>
<Box
sx={{
Expand Down
2 changes: 1 addition & 1 deletion app/components/chart-filters-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const ChartFiltersList = (props: ChartFiltersListProps) => {
<Typography
component="div"
variant="body2"
sx={{ color: "grey.800" }}
sx={{ mb: 4, color: "grey.800" }}
data-testid="chart-filters-list"
>
{allFilters.map(({ dimension, value }, i) => (
Expand Down
77 changes: 58 additions & 19 deletions app/components/chart-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { Theme } from "@mui/material";
import { Box, Theme } from "@mui/material";
import { makeStyles } from "@mui/styles";
import capitalize from "lodash/capitalize";
import React from "react";

import { ChartSelectionTabs } from "@/components/chart-selection-tabs";
import Flex from "@/components/flex";
import { Layout } from "@/config-types";

export const ChartPanel = (props: React.PropsWithChildren<{}>) => {
const { children } = props;

return (
<>
<ChartSelectionTabs />
<ChartPanelInner>{children}</ChartPanelInner>
</>
);
};
const useStyles = makeStyles((theme: Theme) => ({
panelLayoutVertical: {
display: "flex",
flexDirection: "column",
gap: theme.spacing(4),
},
panelLayoutTall: {
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gap: theme.spacing(4),

const useChartPanelInnerStyles = makeStyles<Theme>((theme) => ({
root: {
"& > :nth-child(3n - 2)": {
gridColumn: "1 / span 2",
},
"& > :nth-child(3n - 1, 3n)": {
gridColumn: "1 / span 1",
},
},
chartWrapper: {
display: "flex",
flexDirection: "column",
backgroundColor: theme.palette.grey[100],
border: "1px solid",
Expand All @@ -27,13 +35,44 @@ const useChartPanelInnerStyles = makeStyles<Theme>((theme) => ({
},
}));

const ChartPanelInner = (props: React.PropsWithChildren<{}>) => {
const { children } = props;
const classes = useChartPanelInnerStyles();
type ChartPanelLayoutProps = React.PropsWithChildren<{
type: Extract<Layout, { type: "dashboard" }>["layout"];
}>;

export const ChartPanelLayout = (props: ChartPanelLayoutProps) => {
const { children, type } = props;
const classes = useStyles();

return (
<Flex className={classes.root} sx={{ minHeight: [150, 300, 500] }}>
<div
className={
classes[
`panelLayout${
capitalize(type) as Capitalize<ChartPanelLayoutProps["type"]>
}`
]
}
>
{children}
</Flex>
</div>
);
};

type ChartPanelProps = React.PropsWithChildren<{
editing?: boolean;
layout?: Layout;
}>;

export const ChartWrapper = (props: ChartPanelProps) => {
const { children, editing, layout } = props;
const classes = useStyles();

return (
<>
{(editing || layout?.type === "tab") && <ChartSelectionTabs />}
<Box className={classes.chartWrapper} sx={{ minHeight: [150, 300, 500] }}>
{children}
</Box>
</>
);
};
147 changes: 73 additions & 74 deletions app/components/chart-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Trans } from "@lingui/macro";
import { Box, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { Box } from "@mui/material";
import Head from "next/head";
import { useMemo } from "react";

import { DataSetTable } from "@/browse/datatable";
import { ChartErrorBoundary } from "@/components/chart-error-boundary";
import { ChartFootnotes } from "@/components/chart-footnotes";
import { ChartPanelLayout, ChartWrapper } from "@/components/chart-panel";
import {
ChartTablePreviewProvider,
useChartTablePreview,
Expand All @@ -19,8 +19,11 @@ import { MetadataPanel } from "@/components/metadata-panel";
import {
DataSource,
getChartConfig,
hasChartConfigs,
isConfiguring,
useConfiguratorState,
} from "@/configurator";
import { Description, Title } from "@/configurator/components/annotators";
import {
useDataCubesComponentsQuery,
useDataCubesMetadataQuery,
Expand All @@ -34,36 +37,41 @@ type ChartPreviewProps = {
};

export const ChartPreview = (props: ChartPreviewProps) => {
const [state] = useConfiguratorState(hasChartConfigs);
const editing = isConfiguring(state);

return (
<ChartTablePreviewProvider>
<ChartPreviewInner {...props} />
{state.layout.type === "dashboard" && !editing ? (
<ChartPanelLayout type={state.layout.layout}>
{state.chartConfigs.map((chartConfig) => (
<ChartWrapper
key={chartConfig.key}
editing={editing}
layout={state.layout}
>
<ChartPreviewInner {...props} chartKey={chartConfig.key} />
</ChartWrapper>
))}
</ChartPanelLayout>
) : (
<ChartWrapper editing={editing} layout={state.layout}>
<ChartPreviewInner {...props} />
</ChartWrapper>
)}
</ChartTablePreviewProvider>
);
};

const useStyles = makeStyles<Theme>({
title: {
marginBottom: 2,
cursor: "pointer",
"&:hover": {
textDecoration: "underline",
},
},
description: {
marginBottom: 2,
cursor: "pointer",
"&:hover": {
textDecoration: "underline",
},
},
});
type ChartPreviewInnerProps = ChartPreviewProps & {
chartKey?: string;
};

export const ChartPreviewInner = (props: ChartPreviewProps) => {
const { dataSource } = props;
export const ChartPreviewInner = (props: ChartPreviewInnerProps) => {
const { dataSource, chartKey } = props;
const [state, dispatch] = useConfiguratorState();
const chartConfig = getChartConfig(state);
const chartConfig = getChartConfig(state, chartKey);
const locale = useLocale();
const classes = useStyles();
const commonQueryVariables = {
sourceType: dataSource.type,
sourceUrl: dataSource.url,
Expand Down Expand Up @@ -115,7 +123,7 @@ export const ChartPreviewInner = (props: ChartPreviewProps) => {
justifyContent: "space-between",
flexGrow: 1,
color: "grey.800",
p: 5,
p: 6,
width: "100%",
}}
>
Expand All @@ -134,40 +142,36 @@ export const ChartPreviewInner = (props: ChartPreviewProps) => {
</HintYellow>
</Box>
)}
{(state.state === "CONFIGURING_CHART" ||
state.state === "PUBLISHING") && (
{hasChartConfigs(state) && (
<>
<>
<Flex
sx={{
justifyContent: "space-between",
justifyContent:
state.state === "CONFIGURING_CHART" ||
chartConfig.meta.title[locale]
? "space-between"
: "flex-end",
alignItems: "flex-start",
gap: 2,
}}
>
<Typography
variant="h2"
sx={{
color:
chartConfig.meta.title[locale] === ""
? "grey.500"
: "text",
}}
className={classes.title}
onClick={() =>
dispatch({
type: "ACTIVE_FIELD_CHANGED",
value: "title",
})
}
>
{chartConfig.meta.title[locale] === "" ? (
<Trans id="annotation.add.title">[ Title ]</Trans>
) : (
chartConfig.meta.title[locale]
)}
</Typography>

{(state.state === "CONFIGURING_CHART" ||
chartConfig.meta.title[locale]) && (
<Title
text={chartConfig.meta.title[locale]}
lighterColor
onClick={
state.state === "CONFIGURING_CHART"
? () =>
dispatch({
type: "CHART_ACTIVE_FIELD_CHANGED",
value: "title",
})
: undefined
}
/>
)}
<MetadataPanel
// FIXME: adapt to design
datasetIri={chartConfig.cubes[0].iri}
Expand All @@ -178,37 +182,32 @@ export const ChartPreviewInner = (props: ChartPreviewProps) => {
</Flex>
<Head>
<title key="title">
{chartConfig.meta.title[locale] === ""
{!chartConfig.meta.title[locale]
? // FIXME: adapt to design
metadata?.dataCubesMetadata.map((d) => d.title).join(", ")
: chartConfig.meta.title[locale]}{" "}
- visualize.admin.ch
</title>
</Head>
<Typography
variant="body1"
className={classes.description}
sx={{
color:
chartConfig.meta.description[locale] === ""
? "grey.500"
: "text",
}}
onClick={() =>
dispatch({
type: "ACTIVE_FIELD_CHANGED",
value: "description",
})
}
>
{chartConfig.meta.description[locale] === "" ? (
<Trans id="annotation.add.description">[ Description ]</Trans>
) : (
chartConfig.meta.description[locale]
)}
</Typography>
{(state.state === "CONFIGURING_CHART" ||
chartConfig.meta.description[locale]) && (
<Description
text={chartConfig.meta.description[locale]}
lighterColor
onClick={
state.state === "CONFIGURING_CHART"
? () => {
dispatch({
type: "CHART_ACTIVE_FIELD_CHANGED",
value: "description",
});
}
: undefined
}
/>
)}
</>
<Box ref={containerRef} height={containerHeight.current!}>
<Box ref={containerRef} height={containerHeight.current!} mt={4}>
{isTablePreview ? (
<DataSetTable
sx={{
Expand Down
Loading

1 comment on commit 644b9da

@vercel
Copy link

@vercel vercel bot commented on 644b9da Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization-tool – ./

visualization-tool-alpha.vercel.app
visualization-tool-ixt1.vercel.app
visualization-tool-git-main-ixt1.vercel.app

Please sign in to comment.