Browse Source

Client Notebook Auto Reload (#975) (#976)

Dinh Long Nguyen 1 năm trước cách đây
mục cha
commit
9930266d29

+ 26 - 12
frontend/taipy-gui/src/components/Taipy/Navigate.tsx

@@ -27,32 +27,46 @@ const Navigate = ({ to, params, tab, force }: NavigateProps) => {
     const { dispatch, state } = useContext(TaipyContext);
     const navigate = useNavigate();
     const location = useLocation();
+    const SPECIAL_PARAMS = ["tp_reload_all", "tp_reload_same_route_only", "tprh", "tp_cp_meta"];
 
     useEffect(() => {
         if (to) {
             const tos = to === "/" ? to : "/" + to;
-            const searchParams = new URLSearchParams(params || "");
-            // Handle Resource Handler Id
-            let tprh: string | null = null;
-            let meta: string | null = null;
-            if (searchParams.has("tprh")) {
-                tprh = searchParams.get("tprh");
-                searchParams.delete("tprh");
-                if (searchParams.has("tp_cp_meta")) {
-                    meta = searchParams.get("tp_cp_meta");
-                    searchParams.delete("tp_cp_meta");
+            const filteredParams = params
+                ? Object.keys(params).reduce((acc, key) => {
+                      if (!SPECIAL_PARAMS.includes(key)) {
+                          acc[key] = params[key];
+                      }
+                      return acc;
+                  }, {} as Record<string, string>)
+                : {};
+            const searchParams = new URLSearchParams(filteredParams);
+            // Special case for notebook reload
+            const reloadAll = params?.tp_reload_all === "true";
+            const reloadSameRouteOnly = params?.tp_reload_same_route_only === "true";
+            if (reloadAll) {
+                return navigate(0);
+            }
+            if (reloadSameRouteOnly) {
+                if (location.pathname === tos) {
+                    navigate(0);
                 }
+                return;
             }
+            // Regular navigate cases
             if (Object.keys(state.locations || {}).some((route) => tos === route)) {
                 const searchParamsLocation = new URLSearchParams(location.search);
                 if (force && location.pathname === tos && searchParamsLocation.toString() === searchParams.toString()) {
                     navigate(0);
                 } else {
                     navigate({ pathname: to, search: `?${searchParams.toString()}` });
-                    if (tprh !== null) {
+                    // Handle Resource Handler Id
+                    const tprh = params?.tprh;
+                    if (tprh !== undefined) {
                         // Add a session cookie for the resource handler id
                         document.cookie = `tprh=${tprh};path=/;`;
-                        if (meta !== null) {
+                        const meta = params?.tp_cp_meta;
+                        if (meta !== undefined) {
                             localStorage.setItem("tp_cp_meta", meta);
                         }
                         navigate(0);

+ 5 - 0
taipy/gui/_renderers/__init__.py

@@ -110,6 +110,11 @@ class _Renderer(Page, ABC):
         if not _is_in_notebook():
             raise RuntimeError("'set_content()' must be used in an IPython notebook context")
         self.__process_content(content)
+        if self._notebook_gui is not None and self._notebook_page is not None:
+            if self._notebook_gui._config.root_page is self._notebook_page:
+                self._notebook_gui._navigate("/", {"tp_reload_all": "true"})
+                return
+            self._notebook_gui._navigate(self._notebook_page._route, {"tp_reload_same_route_only": "true"})
 
     def _get_content_detail(self, gui: "Gui") -> str:
         if self._filepath:

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

@@ -140,5 +140,5 @@ class FileWatchdogHandler(FileSystemEventHandler):
         if Path(event.src_path).resolve() == Path(self._file_path).resolve():
             self._renderer.set_content(self._file_path)
             _TaipyLogger._get_logger().info(
-                f"File '{self._file_path}' has been modified. Reload your page to see the changes."
+                f"File '{self._file_path}' has been modified."
             )

+ 4 - 0
taipy/gui/gui.py

@@ -1716,6 +1716,10 @@ class Gui:
         # Update variable directory
         if not page._is_class_module():
             self.__var_dir.add_frame(page._frame)
+        # Special case needed for page to access gui to trigger reload in notebook
+        if _is_in_notebook():
+            page._notebook_gui = self
+            page._notebook_page = new_page
 
     def add_pages(self, pages: t.Optional[t.Union[t.Mapping[str, t.Union[str, Page]], str]] = None) -> None:
         """Add several pages to the Graphical User Interface.

+ 7 - 0
taipy/gui/page.py

@@ -17,6 +17,10 @@ from types import FrameType
 
 from .utils import _filter_locals, _get_module_name_from_frame
 
+if t.TYPE_CHECKING:
+    from ._page import _Page
+    from .gui import Gui
+
 
 class Page:
     """Generic page generator.
@@ -65,6 +69,9 @@ class Page:
                     cls_locals[f] = func.__func__
             self._class_module_name = cls.__name__
             self._class_locals = cls_locals
+        # Special variables only use for page reloading in notebook context
+        self._notebook_gui: t.Optional["Gui"] = None
+        self._notebook_page: t.Optional["_Page"] = None
 
     def create_page(self) -> t.Optional[Page]:
         """Create the page content for page modules.