Skip to content
Snippets Groups Projects
Unverified Commit 2822362f authored by github-automation-metabase's avatar github-automation-metabase Committed by GitHub
Browse files

:robot: backported "Move section logic to hook" (#49468)


Co-authored-by: default avatarOisin Coveney <oisin@metabase.com>
parent 3352028c
Branches
Tags
No related merge requests found
import { css } from "@emotion/react";
import styled from "@emotion/styled";
import Radio from "metabase/core/components/Radio";
interface SectionContainerProps {
isDashboard: boolean;
}
export const SectionContainer = styled.div<SectionContainerProps>`
${({ isDashboard }) =>
isDashboard &&
css`
margin-top: 1rem;
`}
export const SectionContainer = styled.div`
width: 100%;
${Radio.RadioGroupVariants.join(", ")} {
......
import { useCallback, useMemo, useState } from "react";
import { t } from "ttag";
import _ from "underscore";
import Radio from "metabase/core/components/Radio";
......@@ -23,11 +22,9 @@ import {
ChartSettingsMenu,
SectionContainer,
} from "./BaseChartSettings.styled";
import { useChartSettingsSections } from "./hooks";
import type { BaseChartSettingsProps } from "./types";
// section names are localized
const DEFAULT_TAB_PRIORITY = [t`Data`];
export const BaseChartSettings = ({
initial,
series,
......@@ -38,9 +35,17 @@ export const BaseChartSettings = ({
chartSettings,
transformedSeries,
}: BaseChartSettingsProps) => {
const [currentSection, setCurrentSection] = useState<string | null>(
initial?.section ?? null,
);
const {
chartSettingCurrentSection,
currentSectionHasColumnSettings,
sectionNames,
setCurrentSection,
showSectionPicker,
visibleWidgets,
} = useChartSettingsSections({
initial,
widgets,
});
const [currentWidget, setCurrentWidget] = useState<Widget | null>(
initial?.widget ?? null,
);
......@@ -138,10 +143,13 @@ export const BaseChartSettings = ({
return null;
}, [currentWidget, widgets]);
const handleShowSection = useCallback((section: string) => {
setCurrentSection(section);
setCurrentWidget(null);
}, []);
const handleShowSection = useCallback(
(section: string) => {
setCurrentSection(section);
setCurrentWidget(null);
},
[setCurrentSection],
);
// allows a widget to temporarily replace itself with a different widget
const handleShowWidget = useCallback(
......@@ -167,56 +175,6 @@ export const BaseChartSettings = ({
[chartSettings, onChange],
);
const sections: Record<string, Widget[]> = useMemo(() => {
const sectionObj: Record<string, Widget[]> = {};
for (const widget of widgets) {
if (widget.widget && !widget.hidden) {
sectionObj[widget.section] = sectionObj[widget.section] || [];
sectionObj[widget.section].push(widget);
}
}
// Move settings from the "undefined" section in the first tab
if (sectionObj["undefined"] && Object.values(sectionObj).length > 1) {
const extra = sectionObj["undefined"];
delete sectionObj["undefined"];
Object.values(sectionObj)[0].unshift(...extra);
}
return sectionObj;
}, [widgets]);
const sectionNames = Object.keys(sections);
// This sorts the section radio buttons.
const sectionSortOrder = [
"data",
"display",
"axes",
// include all section names so any forgotten sections are sorted to the end
...sectionNames.map(x => x.toLowerCase()),
];
sectionNames.sort((a, b) => {
const [aIdx, bIdx] = [a, b].map(x =>
sectionSortOrder.indexOf(x.toLowerCase()),
);
return aIdx - bIdx;
});
const chartSettingCurrentSection = useMemo(
() =>
currentSection && sections[currentSection]
? currentSection
: _.find(DEFAULT_TAB_PRIORITY, name => name in sections) ||
sectionNames[0],
[currentSection, sectionNames, sections],
);
const visibleWidgets = sections[chartSettingCurrentSection] || [];
const currentSectionHasColumnSettings = (
sections[chartSettingCurrentSection] || []
).some((widget: Widget) => widget.id === "column_settings");
const extraWidgetProps = {
// NOTE: special props to support adding additional fields
question,
......@@ -227,22 +185,11 @@ export const BaseChartSettings = ({
onChangeSeriesColor: handleChangeSeriesColor,
};
const showSectionPicker =
// don't show section tabs for a single section
sectionNames.length > 1 &&
// hide the section picker if the only widget is column_settings
!(
visibleWidgets.length === 1 &&
visibleWidgets[0].id === "column_settings" &&
// and this section doesn't have that as a direct child
!currentSectionHasColumnSettings
);
return (
<>
<ChartSettingsMenu data-testid="chartsettings-sidebar">
{showSectionPicker && (
<SectionContainer isDashboard={false}>
<SectionContainer>
<Radio
value={chartSettingCurrentSection ?? undefined}
onChange={handleShowSection}
......
import { useMemo, useState } from "react";
import { t } from "ttag";
import _ from "underscore";
import type { Widget } from "../types";
import type { BaseChartSettingsProps } from "./types";
// section names are localized
const DEFAULT_TAB_PRIORITY = [t`Data`];
export const useChartSettingsSections = ({
initial,
widgets,
}: Pick<BaseChartSettingsProps, "initial" | "widgets">) => {
const [currentSection, setCurrentSection] = useState<string | null>(
initial?.section ?? null,
);
const sections: Record<string, Widget[]> = useMemo(() => {
const sectionObj: Record<string, Widget[]> = {};
for (const widget of widgets) {
if (widget.widget && !widget.hidden) {
sectionObj[widget.section] = sectionObj[widget.section] || [];
sectionObj[widget.section].push(widget);
}
}
// Move settings from the "undefined" section in the first tab
if (sectionObj["undefined"] && Object.values(sectionObj).length > 1) {
const extra = sectionObj["undefined"];
delete sectionObj["undefined"];
Object.values(sectionObj)[0].unshift(...extra);
}
return sectionObj;
}, [widgets]);
const sectionNames = Object.keys(sections);
// This sorts the section radio buttons.
const sectionSortOrder = [
"data",
"display",
"axes",
// include all section names so any forgotten sections are sorted to the end
...sectionNames.map(x => x.toLowerCase()),
];
sectionNames.sort((a, b) => {
const [aIdx, bIdx] = [a, b].map(x =>
sectionSortOrder.indexOf(x.toLowerCase()),
);
return aIdx - bIdx;
});
const chartSettingCurrentSection = useMemo(
() =>
currentSection && sections[currentSection]
? currentSection
: _.find(DEFAULT_TAB_PRIORITY, name => name in sections) ||
sectionNames[0],
[currentSection, sectionNames, sections],
);
const visibleWidgets = sections[chartSettingCurrentSection] || [];
const currentSectionHasColumnSettings = visibleWidgets.some(
(widget: Widget) => widget.id === "column_settings",
);
const showSectionPicker =
// don't show section tabs for a single section
sectionNames.length > 1 &&
// hide the section picker if the only widget is column_settings
!(
visibleWidgets.length === 1 &&
visibleWidgets[0].id === "column_settings" &&
// and this section doesn't have that as a direct child
!currentSectionHasColumnSettings
);
return {
sectionNames,
setCurrentSection,
currentSectionHasColumnSettings,
chartSettingCurrentSection,
showSectionPicker,
visibleWidgets,
};
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment