Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#398-expand-exposed-type-parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
jrobinAV authored Dec 13, 2024
2 parents 53ea8bf + abe324c commit aa9a18a
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 38 deletions.
3 changes: 3 additions & 0 deletions .github/actions/gui-test/e2e/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: end-to-end test
runs:
using: "composite"
steps:
- name: Check Python and iPython versions
shell: bash
run: pipenv run python --version && pipenv run ipython --version
- name: install kernel
shell: bash
run: pipenv run ipython kernel install --name "python3" --user
Expand Down
2 changes: 1 addition & 1 deletion frontend/taipy-gui/src/components/Taipy/Chat.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ describe("Chat Component", () => {
});
jest.restoreAllMocks();
});
it("Not upload image over a file size limit", async () => {
it("does not upload image over a file size limit", async () => {
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByText, getByAltText } = render(
Expand Down
13 changes: 10 additions & 3 deletions frontend/taipy-gui/src/components/Taipy/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import React, {
ReactNode,
lazy,
ChangeEvent,
UIEvent,
} from "react";
import { SxProps, Theme, darken, lighten } from "@mui/material/styles";
import Avatar from "@mui/material/Avatar";
Expand Down Expand Up @@ -250,6 +251,7 @@ const Chat = (props: ChatProps) => {
const [imagePreview, setImagePreview] = useState<string | null>(null);
const [objectURLs, setObjectURLs] = useState<string[]>([]);
const fileInputRef = useRef<HTMLInputElement>(null);
const userScrolled = useRef(false);

const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
const active = useDynamicProperty(props.active, props.defaultActive, true);
Expand Down Expand Up @@ -424,7 +426,7 @@ const Chat = (props: ChatProps) => {
);

const showBottom = useCallback(() => {
anchorDivRef.current?.scrollIntoView();
anchorDivRef.current?.scrollIntoView && anchorDivRef.current?.scrollIntoView();
setShowMessage(false);
}, []);

Expand All @@ -450,8 +452,9 @@ const Chat = (props: ChatProps) => {
}
}
page.current.key = getChatKey(0, pageSize);
!userScrolled.current && showBottom();
}
}, [refresh, pageSize, props.messages]);
}, [refresh, pageSize, props.messages, showBottom]);

useEffect(() => {
if (showMessage && !isAnchorDivVisible) {
Expand Down Expand Up @@ -490,10 +493,14 @@ const Chat = (props: ChatProps) => {
[loadMoreItems]
);

const handleOnScroll = useCallback((evt: UIEvent) => {
userScrolled.current = (evt.target as HTMLDivElement).scrollHeight - (evt.target as HTMLDivElement).offsetHeight - (evt.target as HTMLDivElement).scrollTop > 1;
}, []);

return (
<Tooltip title={hover || ""}>
<Paper className={`${className} ${getComponentClassName(props.children)}`} sx={boxSx} id={id}>
<Grid container rowSpacing={2} sx={gridSx} ref={scrollDivRef}>
<Grid container rowSpacing={2} sx={gridSx} ref={scrollDivRef} onScroll={handleOnScroll}>
{rows.length && !rows[0] ? (
<Grid className={getSuffixedClassNames(className, "-load")} size={12} sx={noAnchorSx}>
<Box sx={loadMoreSx}>
Expand Down
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
4 changes: 1 addition & 3 deletions taipy/gui_core/_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,11 +639,10 @@ def submit_entity(self, state: State, id: str, payload: t.Dict[str, str]):
client_id=self.gui._get_client_id(),
module_context=self.gui._get_locals_context(),
)
client_status = _ClientStatus(self.gui._get_client_id(), submission_entity.submission_status)
client_status = _ClientStatus(self.gui._get_client_id(), None)
with self.submissions_lock:
self.client_submission[submission_entity.id] = client_status
if Config.core.mode == "development":
client_status.submission_status = SubmissionStatus.SUBMITTED
self.submission_status_callback(submission_entity.id)
_GuiCoreContext.__assign_var(state, error_var, "")
except Exception as e:
Expand Down Expand Up @@ -715,7 +714,6 @@ def _get_sort_params(params: t.Optional[t.List[t.Any]] = None, parent: t.Optiona
args.append(None)
return args


def get_sorted_datanode_list(
self,
entities: t.Union[
Expand Down
Loading

0 comments on commit aa9a18a

Please sign in to comment.