diff --git a/taipy/gui/extension/library.py b/taipy/gui/extension/library.py
index 27c16021c3..4b0dc9bd88 100644
--- a/taipy/gui/extension/library.py
+++ b/taipy/gui/extension/library.py
@@ -16,7 +16,7 @@
from abc import ABC, abstractmethod
from inspect import isclass
from pathlib import Path
-from urllib.parse import urlencode
+from urllib.parse import urlencode, urlparse
from .._renderers.builder import _Builder
from .._warnings import _warn
@@ -115,7 +115,7 @@ def __init__(
default_property (str): The name of the default property for this element.
properties (Dict[str, ElementProperty]): The dictionary containing the properties of this element, where the keys are the property names and the values are instances of ElementProperty.
inner_properties (Optional[List[ElementProperty]]): The optional list of inner properties for this element.
- Default values are set/binded automatically.
+ Default values are set/bound automatically.
react_component (Optional[str]): The name of the component to be created on the front-end.
If not specified, it is set to a camel case version of the element's name
("one_name" is transformed to "OneName").
@@ -324,9 +324,27 @@ def get_js_module_name(self) -> str:
"""
return _to_camel_case(self.get_name(), True)
+ def __get_class_folder(self):
+ if not hasattr(self, "_class_folder"):
+ module_obj = sys.modules.get(self.__class__.__module__)
+ base = (Path(".") if module_obj is None else Path(module_obj.__file__).parent).resolve() # type: ignore
+ self._class_folder = base if base.exists() else Path(".").resolve()
+ return self._class_folder
+
+ def _do_get_relative_paths(self, paths: t.List[str]) -> t.List[str]:
+ ret = set()
+ for path in paths or []:
+ if bool(urlparse(path).netloc):
+ ret.add(path)
+ elif file_paths := self.__get_class_folder().glob(path):
+ ret.update([file_path.relative_to(self.__get_class_folder()).as_posix() for file_path in file_paths])
+ elif path:
+ ret.add(path)
+ return list(ret)
+
def get_scripts(self) -> t.List[str]:
"""
- Return the list of the mandatory script file pathnames.
+ Return the list of the mandatory script file path names.
If a script file pathname is an absolute URL it will be used as is.
If it's not it will be passed to `(ElementLibrary.)get_resource()^` to retrieve a local
@@ -363,9 +381,7 @@ def get_resource(self, name: str) -> Path:
Arguments:
name (str): The name of the resource for which a local Path should be returned.
""" # noqa: E501
- module_obj = sys.modules.get(self.__class__.__module__)
- base = (Path(".") if module_obj is None else Path(module_obj.__file__).parent).resolve() # type: ignore
- base = base if base.exists() else Path(".").resolve()
+ base = self.__get_class_folder()
file = (base / name).resolve()
if str(file).startswith(str(base)) and file.exists():
return file
diff --git a/taipy/gui/gui.py b/taipy/gui/gui.py
index 7e344bc772..c9488ddebd 100644
--- a/taipy/gui/gui.py
+++ b/taipy/gui/gui.py
@@ -1332,12 +1332,8 @@ def __send_ws_download(self, content: str, name: str, on_action: str) -> None:
)
def __send_ws_alert(
- self, type: str,
- message: str,
- system_notification: bool,
- duration: int,
- notification_id: t.Optional[str] = None
- ) -> None:
+ self, type: str, message: str, system_notification: bool, duration: int, notification_id: t.Optional[str] = None
+ ) -> None:
payload = {
"type": _WsType.ALERT.value,
"atype": type,
@@ -2278,10 +2274,9 @@ def _close_notification(
message="", # No need for a message when closing
system_notification=False, # System notification not needed for closing
duration=0, # No duration since it's an immediate close
- notification_id=notification_id
+ notification_id=notification_id,
)
-
def _hold_actions(
self,
callback: t.Optional[t.Union[str, t.Callable]] = None,
@@ -2661,13 +2656,13 @@ def __register_blueprint(self):
s if bool(urlparse(s).netloc) else f"{Gui._EXTENSION_ROOT}/{name}/{s}{lib.get_query(s)}"
for name, libs in Gui.__extensions.items()
for lib in libs
- for s in (lib.get_scripts() or [])
+ for s in (lib._do_get_relative_paths(lib.get_scripts()))
]
styles = [
s if bool(urlparse(s).netloc) else f"{Gui._EXTENSION_ROOT}/{name}/{s}{lib.get_query(s)}"
for name, libs in Gui.__extensions.items()
for lib in libs
- for s in (lib.get_styles() or [])
+ for s in (lib._do_get_relative_paths(lib.get_styles()))
]
if self._get_config("stylekit", True):
styles.append("stylekit/stylekit.css")
diff --git a/taipy/gui_core/_GuiCoreLib.py b/taipy/gui_core/_GuiCoreLib.py
index e9f5c2a435..1bf6fd9dbf 100644
--- a/taipy/gui_core/_GuiCoreLib.py
+++ b/taipy/gui_core/_GuiCoreLib.py
@@ -65,7 +65,7 @@ class _GuiCore(ElementLibrary):
__DATANODE_SELECTOR_SORT_VAR = "__tpgc_dn_sort"
__DATANODE_SELECTOR_ERROR_VAR = "__tpgc_dn_error"
- __elts = {
+ __elements = {
"scenario_selector": Element(
"value",
{
@@ -314,10 +314,10 @@ def get_name(self) -> str:
return _GuiCore.__LIB_NAME
def get_elements(self) -> t.Dict[str, Element]:
- return _GuiCore.__elts
+ return _GuiCore.__elements
def get_scripts(self) -> t.List[str]:
- return ["lib/taipy-gui-core.js"]
+ return ["lib/*.js"]
def on_init(self, gui: Gui) -> t.Optional[t.Tuple[str, t.Any]]:
self.ctx = _GuiCoreContext(gui)