Переглянути джерело

Bring progress up to Taipy standards (#1430)

* Bring progress up to Taipy standards

* hook dependency

* fix test

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 11 місяців тому
батько
коміт
4ad52a5401

+ 5 - 0
frontend/taipy-gui/src/components/Taipy/Progress.spec.tsx

@@ -24,6 +24,11 @@ describe("Progress component", () => {
         const elt = getByRole("progressbar");
         expect(elt).toHaveClass("MuiCircularProgress-root");
     });
+    it("uses the class", async () => {
+        const { getByRole } = render(<Progress className="taipy-progress" />);
+        const elt = getByRole("progressbar");
+        expect(elt).toHaveClass("taipy-progress");
+    });
     it("renders circular progress with value (determinate)", () => {
         const { getByRole, getByText } = render(<Progress showValue value={50} />);
         const elt = getByRole("progressbar");

+ 38 - 22
frontend/taipy-gui/src/components/Taipy/Progress.tsx

@@ -18,9 +18,10 @@ import CircularProgress from "@mui/material/CircularProgress";
 import LinearProgress from "@mui/material/LinearProgress";
 import Typography from "@mui/material/Typography";
 
-import { useDynamicProperty } from "../../utils/hooks";
+import { useClassNames, useDynamicProperty } from "../../utils/hooks";
+import { TaipyBaseProps } from "./utils";
 
-interface ProgressBarProps {
+interface ProgressBarProps extends TaipyBaseProps {
     linear?: boolean; //by default - false
     showValue?: boolean; //by default - false
     value?: number; //progress value
@@ -29,10 +30,26 @@ interface ProgressBarProps {
     defaultRender?: boolean;
 }
 
+const linearSx = { display: "flex", alignItems: "center" };
+const linearPrgSx = { width: "100%", mr: 1 };
+const linearTxtSx = { minWidth: 35 };
+const circularSx = { position: "relative", display: "inline-flex" };
+const circularPrgSx = {
+    top: 0,
+    left: 0,
+    bottom: 0,
+    right: 0,
+    position: "absolute",
+    display: "flex",
+    alignItems: "center",
+    justifyContent: "center",
+};
+
 const Progress = (props: ProgressBarProps) => {
-    const { linear, showValue } = props;
+    const { linear = false, showValue = false } = props;
 
-    const value = useDynamicProperty(props.value, props.defaultValue, undefined);
+    const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
+    const value = useDynamicProperty(props.value, props.defaultValue, undefined, "number");
     const render = useDynamicProperty(props.render, props.defaultRender, true);
 
     if (!render) {
@@ -41,29 +58,18 @@ const Progress = (props: ProgressBarProps) => {
 
     return showValue && value !== undefined ? (
         linear ? (
-            <Box sx={{ display: "flex", alignItems: "center" }}>
-                <Box sx={{ width: "100%", mr: 1 }}>
+            <Box sx={linearSx} className={className} id={props.id}>
+                <Box sx={linearPrgSx}>
                     <LinearProgress variant="determinate" value={value} />
                 </Box>
-                <Box sx={{ minWidth: 35 }}>
+                <Box sx={linearTxtSx}>
                     <Typography variant="body2" color="text.secondary">{`${Math.round(value)}%`}</Typography>
                 </Box>
             </Box>
         ) : (
-            <Box sx={{ position: "relative", display: "inline-flex" }}>
+            <Box sx={circularSx} className={className} id={props.id}>
                 <CircularProgress variant="determinate" value={value} />
-                <Box
-                    sx={{
-                        top: 0,
-                        left: 0,
-                        bottom: 0,
-                        right: 0,
-                        position: "absolute",
-                        display: "flex",
-                        alignItems: "center",
-                        justifyContent: "center",
-                    }}
-                >
+                <Box sx={circularPrgSx}>
                     <Typography variant="caption" component="div" color="text.secondary">
                         {`${Math.round(value)}%`}
                     </Typography>
@@ -71,9 +77,19 @@ const Progress = (props: ProgressBarProps) => {
             </Box>
         )
     ) : linear ? (
-        <LinearProgress variant={value === undefined ? "indeterminate" : "determinate"} value={value} />
+        <LinearProgress
+            id={props.id}
+            variant={value === undefined ? "indeterminate" : "determinate"}
+            value={value}
+            className={className}
+        />
     ) : (
-        <CircularProgress variant={value === undefined ? "indeterminate" : "determinate"} value={value} />
+        <CircularProgress
+            id={props.id}
+            variant={value === undefined ? "indeterminate" : "determinate"}
+            value={value}
+            className={className}
+        />
     );
 };
 

+ 4 - 4
frontend/taipy-gui/src/utils/hooks.ts

@@ -29,16 +29,16 @@ import { TIMEZONE_CLIENT } from "../utils";
  * @param defaultStatic - The default static value.
  * @returns The latest updated value.
  */
-export const useDynamicProperty = <T>(value: T, defaultValue: T, defaultStatic: T): T => {
+export const useDynamicProperty = <T>(value: T, defaultValue: T, defaultStatic: T, check_type?: string): T => {
     return useMemo(() => {
-        if (value !== undefined) {
+        if (value !== undefined && (!check_type || typeof value === check_type)) {
             return value;
         }
-        if (defaultValue !== undefined) {
+        if (defaultValue !== undefined && (!check_type || typeof value === check_type)) {
             return defaultValue;
         }
         return defaultStatic;
-    }, [value, defaultValue, defaultStatic]);
+    }, [value, defaultValue, defaultStatic, check_type]);
 };
 
 /**

+ 1 - 1
taipy/gui/_renderers/factory.py

@@ -607,7 +607,7 @@ class _Factory:
             element_name="Progress",
             attributes=attrs,
         )
-        .set_value_and_default(var_type=PropertyType.dynamic_number)
+        .set_value_and_default(var_type=PropertyType.dynamic_number, native_type=True)
         .set_attributes(
             [
                 ("linear", PropertyType.boolean, False),

+ 2 - 1
taipy/gui_core/_context.py

@@ -210,11 +210,12 @@ class _GuiCoreContext(CoreEventConsumerBase):
             _warn(f"Submission ({submission_id}) is not available", e)
 
         finally:
+            entity_id = submission.entity_id if submission else None
             self.gui._broadcast(
                 _GuiCoreContext._CORE_CHANGED_NAME,
                 {
                     "jobs": True,
-                    "scenario": (submission.entity_id if submission else None) or False,
+                    "scenario": entity_id or False,
                     "submission": new_status.value if new_status else None,
                 },
             )

+ 4 - 4
tests/gui/control/test_progress.py

@@ -20,7 +20,7 @@ def test_circular_progress_indeterminate_md(gui: Gui, helpers):
 
 def test_circular_progress_determinate_md(gui: Gui, helpers):
     md_string = "<|progress|value=50|show_value|>"
-    expected_list = ["<Progress", 'value="50"']
+    expected_list = ["<Progress", 'value={50.0}']
     helpers.test_control_md(gui, md_string, expected_list)
 
 
@@ -32,7 +32,7 @@ def test_linear_progress_indeterminate_md(gui: Gui, helpers):
 
 def test_linear_progress_determinate_md(gui: Gui, helpers):
     md_string = "<|progress|value=50|show_value|linear|>"
-    expected_list = ["<Progress", 'value="50"', "linear={true}"]
+    expected_list = ["<Progress", 'value={50.0}', "linear={true}"]
     helpers.test_control_md(gui, md_string, expected_list)
 
 
@@ -44,7 +44,7 @@ def test_circular_progress_indeterminate_html(gui: Gui, helpers):
 
 def test_circular_progress_determinate_html(gui: Gui, helpers):
     html_string = '<taipy:progress show_value value="50"/>'
-    expected_list = ["<Progress", 'value="50"']
+    expected_list = ["<Progress", 'value={50.0}']
     helpers.test_control_html(gui, html_string, expected_list)
 
 
@@ -56,5 +56,5 @@ def test_linear_progress_indeterminate_html(gui: Gui, helpers):
 
 def test_linear_progress_determinate_html(gui: Gui, helpers):
     html_string = '<taipy:progress linear show_value value="50"/>'
-    expected_list = ["<Progress", "linear={true}", 'value="50"']
+    expected_list = ["<Progress", "linear={true}", 'value={50.0}']
     helpers.test_control_html(gui, html_string, expected_list)