11from __future__ import annotations
22
3+ from deephaven .plugin .utilities import is_enterprise_environment
4+
35import re
46from dataclasses import dataclass
57from typing import TypedDict , Union
@@ -75,43 +77,27 @@ class NavigationTarget(TypedDict, total=False):
7577
7678# Patterns for detecting embed/app/iframe routes in a URL path.
7779_EMBED_WIDGET_RE = re .compile (r"/embed/widget/" )
78- _APP_WIDGET_RE = re .compile (r"/app/widget /" )
80+ _DASHBOARD_RE = re .compile (r"/dashboard /" )
7981_IFRAME_WIDGET_RE = re .compile (r"/iframe/widget/" )
8082
81- # Patterns for extracting the base URL from a path.
82- _WIDGET_ROUTE_RE = re .compile (r"^(.*?)(?:/embed/widget/|/app/widget/|/iframe/widget/)" )
83-
84-
8583try :
86- from deephaven_enterprise .client .session_manager import (
84+ # Import SessionManager for enterprise widget path resolution.
85+ from deephaven_enterprise .client .session_manager import ( # pyright: ignore[reportMissingImports]
8786 SessionManager ,
8887 )
89-
90- _has_enterprise = True
9188except ImportError :
92- _has_enterprise = False
89+ pass
9390
9491
9592def _get_serial_for_name (name : str ) -> int :
96- if not _has_enterprise :
93+ if not is_enterprise_environment () :
9794 raise RuntimeError (
98- "deephaven_enterprise is required for embed to app path conversion"
95+ "deephaven_enterprise is required for embed to dashboard path conversion"
9996 )
100- sm = SessionManager ()
97+ sm = SessionManager () # pyright: ignore[reportUnboundVariable]
10198 return sm .controller_client .get_serial_for_name (name = name )
10299
103100
104- def _extract_base_url (current_url_path : str ) -> str :
105- """
106- Extract the base URL from a URL path by finding the portion before
107- /embed/widget/, /app/widget/, or /iframe/widget/.
108-
109- Returns an empty string if no known prefix is found.
110- """
111- m = _WIDGET_ROUTE_RE .match (current_url_path )
112- return m .group (1 ) if m else ""
113-
114-
115101def _detect_embed (current_url_path : str ) -> bool :
116102 """
117103 Detect whether the current URL is an embed/iframe route (True) or
@@ -121,26 +107,31 @@ def _detect_embed(current_url_path: str) -> bool:
121107 current_url_path
122108 ):
123109 return True
124- if _APP_WIDGET_RE .search (current_url_path ):
110+ if _DASHBOARD_RE .search (current_url_path ):
125111 return False
126112 return True
127113
128114
129115def resolve_widget_path (
130116 widget_path : WidgetPath | EnterpriseWidgetPath ,
131117 current_url_path : str ,
118+ base_url : str = "/" ,
132119) -> str :
133120 """
134121 Resolve a WidgetPath or EnterpriseWidgetPath to an absolute URL path string.
135122
136123 Args:
137124 widget_path: The widget path descriptor.
138125 current_url_path: The current absolute URL path from the browser.
126+ base_url: The base URL from the frontend (import.meta.env.BASE_URL).
127+ Defaults to "/".
139128
140129 Returns:
141130 The resolved absolute URL path string.
142131 """
143- base_url = _extract_base_url (current_url_path )
132+ # Normalize base_url: ensure no trailing slash for clean concatenation
133+ base = base_url .rstrip ("/" )
134+
144135 embed = widget_path .embed
145136 if embed is None :
146137 embed = _detect_embed (current_url_path )
@@ -152,11 +143,9 @@ def resolve_widget_path(
152143
153144 if isinstance (widget_path , WidgetPath ):
154145 if embed :
155- # Non-enterprise embed route
156- path = f"{ base_url } /iframe/widget/{ widget_path .widget } { local_suffix } "
146+ path = f"{ base } /iframe/widget/{ widget_path .widget } { local_suffix } "
157147 else :
158- # Non-enterprise app route (future work — use iframe for now)
159- path = f"{ base_url } /iframe/widget/{ widget_path .widget } { local_suffix } "
148+ path = f"{ base } { local_suffix } " if local_suffix else (base or "/" )
160149 return path
161150
162151 # EnterpriseWidgetPath
@@ -168,14 +157,14 @@ def resolve_widget_path(
168157 if widget_path .replica_slot is not None
169158 else ""
170159 )
171- path = f"{ base_url } /embed/widget/{ query_part } /{ widget_path .widget } { replica } { local_suffix } "
160+ path = f"{ base } /embed/widget/{ query_part } /{ widget_path .widget } { replica } { local_suffix } "
172161 else :
173- # Enterprise app route: <base>/app/widget/ <serial>- <widget>[/local/...]
162+ # Enterprise app route: <base>/dashboard/ <serial>_ <widget>[/local/...]
174163 query = widget_path .query
175164 if isinstance (query , str ):
176165 serial = _get_serial_for_name (query )
177166 else :
178167 serial = query
179- path = f"{ base_url } /app/widget/ { serial } - { widget_path .widget } { local_suffix } "
168+ path = f"{ base } /dashboard/ { serial } _ { widget_path .widget } { local_suffix } "
180169
181170 return path
0 commit comments