feat: add slug-only dashboard profile filter and unify backend imports
This commit is contained in:
3
backend/src/core/__init__.py
Normal file
3
backend/src/core/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# [DEF:src.core:Package]
|
||||
# @PURPOSE: Backend core services and infrastructure package root.
|
||||
# [/DEF:src.core:Package]
|
||||
3
backend/src/core/auth/__init__.py
Normal file
3
backend/src/core/auth/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# [DEF:src.core.auth:Package]
|
||||
# @PURPOSE: Authentication and authorization package root.
|
||||
# [/DEF:src.core.auth:Package]
|
||||
@@ -141,6 +141,11 @@ def _ensure_user_dashboard_preferences_columns(bind_engine):
|
||||
"ALTER TABLE user_dashboard_preferences "
|
||||
"ADD COLUMN dashboards_table_density VARCHAR NOT NULL DEFAULT 'comfortable'"
|
||||
)
|
||||
if "show_only_slug_dashboards" not in existing_columns:
|
||||
alter_statements.append(
|
||||
"ALTER TABLE user_dashboard_preferences "
|
||||
"ADD COLUMN show_only_slug_dashboards BOOLEAN NOT NULL DEFAULT TRUE"
|
||||
)
|
||||
|
||||
if not alter_statements:
|
||||
return
|
||||
|
||||
@@ -76,17 +76,8 @@ class PluginLoader:
|
||||
"""
|
||||
Loads a single Python module and extracts PluginBase subclasses.
|
||||
"""
|
||||
# Try to determine the correct package prefix based on how the app is running
|
||||
# For standalone execution, we need to handle the import differently
|
||||
if __name__ == "__main__" or "test" in __name__:
|
||||
# When running as standalone or in tests, use relative import
|
||||
package_name = f"plugins.{module_name}"
|
||||
elif "backend.src" in __name__:
|
||||
package_prefix = "backend.src.plugins"
|
||||
package_name = f"{package_prefix}.{module_name}"
|
||||
else:
|
||||
package_prefix = "src.plugins"
|
||||
package_name = f"{package_prefix}.{module_name}"
|
||||
# All runtime code is imported through the canonical `src` package root.
|
||||
package_name = f"src.plugins.{module_name}"
|
||||
|
||||
# print(f"DEBUG: Loading plugin {module_name} as {package_name}")
|
||||
spec = importlib.util.spec_from_file_location(package_name, file_path)
|
||||
@@ -198,4 +189,4 @@ class PluginLoader:
|
||||
return plugin_id in self._plugins
|
||||
# [/DEF:has_plugin:Function]
|
||||
|
||||
# [/DEF:PluginLoader:Class]
|
||||
# [/DEF:PluginLoader:Class]
|
||||
|
||||
@@ -150,11 +150,19 @@ class SupersetClient:
|
||||
# @PRE: Client is authenticated.
|
||||
# @POST: Returns a list of dashboard metadata summaries.
|
||||
# @RETURN: List[Dict]
|
||||
def get_dashboards_summary(self) -> List[Dict]:
|
||||
def get_dashboards_summary(self, require_slug: bool = False) -> List[Dict]:
|
||||
with belief_scope("SupersetClient.get_dashboards_summary"):
|
||||
# Rely on list endpoint default projection to stay compatible
|
||||
# across Superset versions and preserve owners in one request.
|
||||
query: Dict[str, Any] = {}
|
||||
if require_slug:
|
||||
query["filters"] = [
|
||||
{
|
||||
"col": "slug",
|
||||
"opr": "neq",
|
||||
"value": "",
|
||||
}
|
||||
]
|
||||
_, dashboards = self.get_dashboards(query=query)
|
||||
|
||||
# Map fields to DashboardMetadata schema
|
||||
@@ -232,23 +240,35 @@ class SupersetClient:
|
||||
page: int,
|
||||
page_size: int,
|
||||
search: Optional[str] = None,
|
||||
require_slug: bool = False,
|
||||
) -> Tuple[int, List[Dict]]:
|
||||
with belief_scope("SupersetClient.get_dashboards_summary_page"):
|
||||
query: Dict[str, Any] = {
|
||||
"page": max(page - 1, 0),
|
||||
"page_size": page_size,
|
||||
}
|
||||
filters: List[Dict[str, Any]] = []
|
||||
if require_slug:
|
||||
filters.append(
|
||||
{
|
||||
"col": "slug",
|
||||
"opr": "neq",
|
||||
"value": "",
|
||||
}
|
||||
)
|
||||
normalized_search = (search or "").strip()
|
||||
if normalized_search:
|
||||
# Superset list API supports filter objects with `opr` operator.
|
||||
# `ct` -> contains (ILIKE on most Superset backends).
|
||||
query["filters"] = [
|
||||
filters.append(
|
||||
{
|
||||
"col": "dashboard_title",
|
||||
"opr": "ct",
|
||||
"value": normalized_search,
|
||||
}
|
||||
]
|
||||
)
|
||||
if filters:
|
||||
query["filters"] = filters
|
||||
|
||||
total_count, dashboards = self.get_dashboards_page(query=query)
|
||||
|
||||
|
||||
3
backend/src/core/utils/__init__.py
Normal file
3
backend/src/core/utils/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# [DEF:src.core.utils:Package]
|
||||
# @PURPOSE: Shared utility package root.
|
||||
# [/DEF:src.core.utils:Package]
|
||||
Reference in New Issue
Block a user