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

Fix css syntax for Metric component #2318

Merged
merged 2 commits into from
Dec 12, 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
146 changes: 136 additions & 10 deletions frontend/taipy-gui/src/components/Taipy/Metric.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ describe("Metric Component", () => {
});

it("applies style correctly when deltaColor is set", async () => {
const { container } = render(<Metric delta={10} deltaColor="#FF4136" />);
const { container } = render(<Metric delta={10} deltaColor="#FF4136" />);
await waitFor(() => {
const elt = container.querySelector(".delta");
expect(elt).toHaveStyle({
Expand All @@ -249,7 +249,7 @@ describe("Metric Component", () => {
});

it("applies style correctly when deltaColor is set invert", async () => {
const { container } = render(<Metric delta={10} deltaColor="invert" />);
const { container } = render(<Metric delta={10} deltaColor="invert" />);
await waitFor(() => {
const elt = container.querySelector(".delta");
expect(elt).toHaveStyle({
Expand All @@ -259,15 +259,15 @@ describe("Metric Component", () => {
});

it("processes type and threshold props correctly when type is linear", async () => {
const { container } = render(<Metric type="linear" threshold={50} />);
const { container } = render(<Metric type="linear" threshold={50} />);
await waitFor(() => {
const elt = container.querySelector(".bullet");
expect(elt).toBeInTheDocument();
});
});

it("processes type and threshold props correctly when type is not linear", async () => {
const { container } = render(<Metric type="angular" threshold={50} />);
const { container } = render(<Metric type="angular" threshold={50} />);
await waitFor(() => {
const elt = container.querySelector(".angular");
expect(elt).toBeInTheDocument();
Expand All @@ -286,6 +286,132 @@ describe("Metric Component", () => {
});
});

it("applies style correctly when height is set to 100px", async () => {
const { container } = render(<Metric height="100px" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100%",
height: "100px",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when height is set to 30em", async () => {
const { container } = render(<Metric height="30em" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100%",
height: "30em",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when height is set to 30%", async () => {
const { container } = render(<Metric height="30%" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100%",
height: "30%",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when height is set to 30vh", async () => {
const { container } = render(<Metric height="30vh" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100%",
height: "30vh",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when height is set to 30vw", async () => {
const { container } = render(<Metric height="30vw" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100%",
height: "30vw",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when width is set to 100px", async () => {
const { container } = render(<Metric width="100px" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "100px",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when width is set to 30em", async () => {
const { container } = render(<Metric width="30em" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "30em",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when width is set to 30%", async () => {
const { container } = render(<Metric width="30%" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "30%",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when width is set to 30vh", async () => {
const { container } = render(<Metric width="30vh" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "30vh",
position: "relative",
display: "inline-block",
});
});
});

it("applies style correctly when width is set to 30vw", async () => {
const { container } = render(<Metric width="30vw" />);
await waitFor(() => {
const elt = container.querySelector(".js-plotly-plot");
expect(elt).toHaveStyle({
width: "30vw",
position: "relative",
display: "inline-block",
});
});
});


it("processes type prop correctly when type is none (string)", async () => {
const { container } = render(<Metric type="none" />);
await waitFor(() => {
Expand All @@ -295,7 +421,7 @@ describe("Metric Component", () => {
expect(angularAxis).not.toBeInTheDocument();
});
});

it("processes type prop correctly when type is None", async () => {
const { container } = render(<Metric type="None" />);
await waitFor(() => {
Expand All @@ -315,8 +441,8 @@ describe("Metric Component", () => {

const { container } = render(
<ThemeProvider theme={darkTheme}>
<Metric template_Dark_={JSON.stringify(darkTemplate)} />
</ThemeProvider>
<Metric template_Dark_={JSON.stringify(darkTemplate)} />
</ThemeProvider>,
);
await waitFor(() => {
const elt = container.querySelector(".main-svg");
Expand All @@ -335,8 +461,8 @@ describe("Metric Component", () => {

const { container } = render(
<ThemeProvider theme={lightTheme}>
<Metric template_Light_={JSON.stringify(lightTemplate)} />
</ThemeProvider>
<Metric template_Light_={JSON.stringify(lightTemplate)} />
</ThemeProvider>,
);
await waitFor(() => {
const elt = container.querySelector(".main-svg");
Expand All @@ -348,7 +474,7 @@ describe("Metric Component", () => {

it.skip("logs an error when template_Dark_ prop is not a valid JSON string", () => {
const consoleSpy = jest.spyOn(console, "info");
render(<Metric template_Dark_="not a valid JSON string"/>);
render(<Metric template_Dark_="not a valid JSON string" />);
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error while parsing Metric.template"));
consoleSpy.mockRestore();
}); // TODO: Not working at the moment, need to fix
Expand Down
53 changes: 35 additions & 18 deletions frontend/taipy-gui/src/components/Taipy/Metric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const emptyLayout = {} as Partial<Layout>;
const defaultStyle = { position: "relative", display: "inline-block", width: "100%" } as CSSProperties;
const skeletonStyle = { ...defaultStyle, minHeight: "7em" };
const plotConfig = { displaylogo: false };
const boxStyle = { height: "100vh" };

const Metric = (props: MetricProps) => {
const { showValue = true } = props;
Expand Down Expand Up @@ -92,17 +93,17 @@ const Metric = (props: MetricProps) => {
delta !== undefined && mode.push("delta");
const deltaIncreasing = props.deltaColor
? {
color: props.deltaColor == "invert" ? "#FF4136" : props.deltaColor,
}
color: props.deltaColor == "invert" ? "#FF4136" : props.deltaColor,
}
: undefined;
const deltaDecreasing =
props.deltaColor == "invert"
? {
color: "#3D9970",
}
color: "#3D9970",
}
: props.negativeDeltaColor
? { color: props.negativeDeltaColor }
: undefined;
? { color: props.negativeDeltaColor }
: undefined;
return [
{
domain: { x: [0, 1], y: [0, 1] },
Expand Down Expand Up @@ -158,8 +159,6 @@ const Metric = (props: MetricProps) => {
const layout = useMemo(() => {
const layout = {
...baseLayout,
height: baseLayout.height !== undefined ? baseLayout.height : props.height,
width: baseLayout.width !== undefined ? baseLayout.width : props.width,
};
let template = undefined;
try {
Expand All @@ -185,24 +184,42 @@ const Metric = (props: MetricProps) => {
return layout as Partial<Layout>;
}, [
props.title,
props.height,
props.width,
props.template,
props.template_Dark_,
props.template_Light_,
theme.palette.mode,
baseLayout,
]);

const style = useMemo(() => {
const normalizeSize = (val: string | number | undefined): string | undefined => {
if (typeof val === "number" || (typeof val === "string" && /^\d+$/.test(val))) {
return `${val}px`;
}
return val;
};

const width = props.width ? normalizeSize(props.width) : "100%";
const height = props.height ? normalizeSize(props.height) : undefined;

return { ...defaultStyle, width, height };
}, [props.width, props.height]);

return (
<Tooltip title={hover || ""}>
<Box className={`${className} ${getComponentClassName(props.children)}`}>
<Suspense fallback={<Skeleton key="skeleton" sx={skeletonStyle} />}>
<Plot data={data} layout={layout} style={defaultStyle} config={plotConfig} useResizeHandler />
</Suspense>
{props.children}
</Box>
</Tooltip>
<Tooltip title={hover || ""}>
<Box className={`${className} ${getComponentClassName(props.children)}`} style={boxStyle}>
<Suspense fallback={<Skeleton key="skeleton" sx={skeletonStyle} />}>
<Plot
data={data}
layout={layout}
style={style}
config={plotConfig}
useResizeHandler
/>
</Suspense>
{props.children}
</Box>
</Tooltip>
);
};

Expand Down
Loading