Skip to content

Commit

Permalink
feat: Add a way to add and remove text blocks
Browse files Browse the repository at this point in the history
...not rendered on the canvas yet.
  • Loading branch information
bprusinowski committed Nov 26, 2024
1 parent 11b1207 commit 9465641
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 36 deletions.
14 changes: 9 additions & 5 deletions app/components/chart-panel-layout-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,30 @@ const decodeLayouts = (layouts: Layouts) => {
);
};

export const ChartPanelLayoutCanvas = (props: ChartPanelLayoutTypeProps) => {
const { chartConfigs, renderChart, className } = props;
export const ChartPanelLayoutCanvas = ({
chartConfigs,
renderChart,
className,
}: ChartPanelLayoutTypeProps) => {
const [state, dispatch] = useConfiguratorState(hasChartConfigs);
const layout = state.layout;
const [layouts, setLayouts] = useState<Layouts>(() => {
assert(
state.layout.type === "dashboard" && state.layout.layout === "canvas",
layout.type === "dashboard" && layout.layout === "canvas",
"ChartPanelLayoutGrid should be rendered only for dashboard layout with canvas"
);

return state.layout.layouts;
return layout.layouts;
});

const handleChangeLayouts = (layouts: Layouts) => {
const layout = state.layout;
assert(
layout.type === "dashboard" && layout.layout === "canvas",
"ChartPanelLayoutGrid should be rendered only for dashboard layout with canvas"
);

const parsedLayouts = decodeLayouts(layouts);

if (!parsedLayouts) {
return;
}
Expand Down
26 changes: 15 additions & 11 deletions app/components/react-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ export const ChartGridLayout = ({
} & ComponentProps<typeof ResponsiveReactGridLayout>) => {
const classes = useStyles();
const [state, dispatch] = useConfiguratorState(hasChartConfigs);
const configLayout = state.layout;
const layout = state.layout;
assert(
configLayout.type === "dashboard" && configLayout.layout === "canvas",
layout.type === "dashboard" && layout.layout === "canvas",
"ChartGridLayout can only be used in a canvas layout!"
);
const allowHeightInitialization = isLayouting(state);
Expand Down Expand Up @@ -268,7 +268,10 @@ export const ChartGridLayout = ({
return [
breakpoint,
chartLayouts.map((chartLayout) => {
if (configLayout.layoutsMetadata[chartLayout.i]?.initialized) {
if (
layout.blocks.find((block) => block.key === chartLayout.i)
?.initialized
) {
return chartLayout;
}

Expand Down Expand Up @@ -315,14 +318,15 @@ export const ChartGridLayout = ({
dispatch({
type: "LAYOUT_CHANGED",
value: {
...configLayout,
...layout,
layouts: newLayouts,
layoutsMetadata: Object.fromEntries(
state.chartConfigs.map(({ key }) => {
const layoutMetadata = configLayout.layoutsMetadata[key];
return [key, { ...layoutMetadata, initialized: true }];
})
),
blocks: layout.blocks.map((block) => {
return {
...block,
// TODO: initialize other block types
initialized: block.type === "chart" ? true : block.initialized,
};
}),
},
});
}
Expand All @@ -333,7 +337,7 @@ export const ChartGridLayout = ({
enhancedLayouts,
mountedForSomeTime,
resize,
configLayout,
layout,
state.chartConfigs,
]);

Expand Down
29 changes: 18 additions & 11 deletions app/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1136,23 +1136,31 @@ export const ReactGridLayoutsType = t.record(
);
export type ReactGridLayoutsType = t.TypeOf<typeof ReactGridLayoutsType>;

const ReactGridLayoutMetadata = t.type({
initialized: t.boolean,
const LayoutChartBlock = t.type({
type: t.literal("chart"),
key: t.string,
});
export type ReactGridLayoutMetadata = t.TypeOf<typeof ReactGridLayoutMetadata>;
export type LayoutChartBlock = t.TypeOf<typeof LayoutChartBlock>;

const ReactGridLayoutsMetadataType = t.record(
t.string,
ReactGridLayoutMetadata
);
export type ReactGridLayoutsMetadataType = t.TypeOf<
typeof ReactGridLayoutsMetadataType
>;
const LayoutTextBlock = t.type({
type: t.literal("text"),
key: t.string,
title: t.string,
description: t.string,
});
export type LayoutTextBlock = t.TypeOf<typeof LayoutTextBlock>;

const LayoutBlock = t.intersection([
t.union([LayoutChartBlock, LayoutTextBlock]),
t.type({ initialized: t.boolean }),
]);
export type LayoutBlock = t.TypeOf<typeof LayoutBlock>;

const Layout = t.intersection([
t.type({
activeField: t.union([t.undefined, t.string]),
meta: Meta,
blocks: t.array(LayoutBlock),
}),
t.union([
t.type({
Expand All @@ -1166,7 +1174,6 @@ const Layout = t.intersection([
type: t.literal("dashboard"),
layout: t.literal("canvas"),
layouts: ReactGridLayoutsType,
layoutsMetadata: ReactGridLayoutsMetadataType,
}),
t.type({
type: t.literal("singleURLs"),
Expand Down
1 change: 1 addition & 0 deletions app/configurator/components/add-dataset-dialog.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const photovoltaikChartStateMock: ConfiguratorStateConfiguringChart = {
layout: {
activeField: "y",
type: "tab",
blocks: [{ type: "chart", key: "8-5RW138pTDA", initialized: true }],
meta: {
title: {
de: "",
Expand Down
3 changes: 3 additions & 0 deletions app/configurator/components/configurator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ const LayoutingStep = () => {
value: {
type: "tab",
meta: state.layout.meta,
blocks: state.layout.blocks,
activeField: undefined,
},
});
Expand All @@ -614,6 +615,7 @@ const LayoutingStep = () => {
value: {
type: "dashboard",
meta: state.layout.meta,
blocks: state.layout.blocks,
layout: "tall",
activeField: undefined,
},
Expand All @@ -634,6 +636,7 @@ const LayoutingStep = () => {
(chartConfig) => chartConfig.key
),
meta: state.layout.meta,
blocks: state.layout.blocks,
activeField: undefined,
},
});
Expand Down
71 changes: 66 additions & 5 deletions app/configurator/components/layout-configurator.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { t, Trans } from "@lingui/macro";
import {
Box,
IconButton as MUIIconButton,
Stack,
Switch,
SwitchProps,
Expand Down Expand Up @@ -55,8 +56,10 @@ import {
} from "@/domain/data";
import { useTimeFormatLocale, useTimeFormatUnit } from "@/formatters";
import { useConfigsCubeComponents } from "@/graphql/hooks";
import { Icon } from "@/icons";
import { useLocale } from "@/src";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";
import { createId } from "@/utils/create-id";
import { getTimeFilterOptions } from "@/utils/time-filter-options";

export const LayoutConfigurator = () => {
Expand Down Expand Up @@ -541,16 +544,70 @@ const DashboardTimeRangeFilterOptions = ({
};

const LayoutBlocksConfigurator = () => {
const [state] = useConfiguratorState(isLayouting);
const [state, dispatch] = useConfiguratorState(isLayouting);
const { layout } = state;
const { blocks } = layout;

const handleAddTextBlock = useEventCallback(() => {
dispatch({
type: "LAYOUT_CHANGED",
value: {
...layout,
blocks: [
...layout.blocks,
{
type: "text",
key: createId(),
title: "",
description: "",
initialized: false,
},
],
},
});
});

const handleRemoveBlock = useEventCallback((key: string) => {
dispatch({
type: "LAYOUT_CHANGED",
value: {
...layout,
blocks: layout.blocks.filter((b) => b.key !== key),
},
});
});

return layout.type === "dashboard" && layout.layout === "canvas" ? (
<ControlSection role="tablist" aria-labelledby="controls-blocks" collapse>
<SubsectionTitle titleId="controls-blocks" gutterBottom={false}>
<Trans id="controls.section.block-options">Text elements</Trans>
</SubsectionTitle>
<ControlSectionContent px="small" gap="none">
<AddButton>
<Box sx={{ mb: 4 }}>
{blocks
.filter((b) => b.type === "text")
.map((block) => (
<Box
key={block.key}
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
height: 40,
px: 2,
}}
>
<Typography variant="body2">{block.key}</Typography>
<MUIIconButton
size="small"
onClick={() => handleRemoveBlock(block.key)}
>
<Icon name="trash" size={16} />
</MUIIconButton>
</Box>
))}
</Box>
<AddButton onClick={handleAddTextBlock}>
<Trans id="controls.section.block-options.text-block-add">
Add text
</Trans>
Expand Down Expand Up @@ -586,9 +643,13 @@ const migrateLayout = (
...layout,
layout: newLayoutType,
layouts,
layoutsMetadata: Object.fromEntries(
chartConfigs.map(({ key }) => [key, { initialized: false }])
),
blocks: chartConfigs.map(({ key }) => {
return {
type: "chart",
key,
initialized: false,
};
}),
};
} else {
return {
Expand Down
5 changes: 3 additions & 2 deletions app/configurator/configurator-state/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export async function publishState(
) {
switch (state.layout.type) {
case "singleURLs":
const { publishableChartKeys, meta } = state.layout;
const { publishableChartKeys, meta, blocks } = state.layout;
const reversedChartKeys = publishableChartKeys.slice().reverse();

// Charts are published in order, keep the current tab open with first chart
Expand All @@ -203,7 +203,8 @@ export async function publishState(
// Ensure that the layout is reset to single-chart mode
layout: {
type: "tab",
meta: meta,
meta,
blocks,
activeField: undefined,
},
},
Expand Down
1 change: 1 addition & 0 deletions app/configurator/configurator-state/initial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const getInitialConfiguringConfigBasedOnCube = (props: {
it: "",
},
},
blocks: [{ type: "chart", key: chartConfig.key, initialized: false }],
activeField: undefined,
},
chartConfigs: [chartConfig],
Expand Down
2 changes: 2 additions & 0 deletions app/configurator/configurator-state/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const configStateMock = {
type: "singleURLs",
publishableChartKeys: [],
meta: {} as ConfiguratorStateConfiguringChart["layout"]["meta"],
blocks: [{ type: "chart", key: "abc", initialized: true }],
},
chartConfigs: [
{
Expand Down Expand Up @@ -101,6 +102,7 @@ export const configStateMock = {
it: "",
},
},
blocks: [{ type: "chart", key: "2of7iJAjccuj", initialized: true }],
},
chartConfigs: [
{
Expand Down
8 changes: 8 additions & 0 deletions app/docs/charts.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ColumnsStory = {
description: { en: "", de: "", fr: "", it: "" },
label: { en: "", de: "", fr: "", it: "" },
},
blocks: [{ type: "chart", key: chartConfig.key, initialized: true }],
activeField: undefined,
},
chartConfigs: [chartConfig],
Expand Down Expand Up @@ -129,6 +130,13 @@ const ScatterplotStory = {
description: { en: "", de: "", fr: "", it: "" },
label: { en: "", de: "", fr: "", it: "" },
},
blocks: [
{
type: "chart",
key: scatterplotChartConfig.key,
initialized: true,
},
],
activeField: undefined,
},
chartConfigs: [chartConfig],
Expand Down
1 change: 1 addition & 0 deletions app/docs/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const states: ConfiguratorState[] = [
description: { en: "", de: "", fr: "", it: "" },
label: { en: "", de: "", fr: "", it: "" },
},
blocks: [{ type: "chart", key: "column", initialized: true }],
activeField: undefined,
},
chartConfigs: [
Expand Down
3 changes: 2 additions & 1 deletion app/docs/lines.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ const LineChartStory = () => (
description: { en: "", de: "", fr: "", it: "" },
label: { en: "", de: "", fr: "", it: "" },
},
blocks: [{ type: "chart", key: chartConfig.key, initialized: false }],
activeField: undefined,
},
chartConfigs: [chartConfig],
activeChartKey: "line",
activeChartKey: chartConfig.key,
dashboardFilters: {
timeRange: {
active: false,
Expand Down
2 changes: 1 addition & 1 deletion app/utils/chart-config/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const CONFIGURATOR_STATE_VERSION = "4.0.0";
export const CONFIGURATOR_STATE_VERSION = "4.1.0";

export const CHART_CONFIG_VERSION = "4.0.0";
Loading

0 comments on commit 9465641

Please sign in to comment.