feat(dashboards): show owners and improve grid actions UI
This commit is contained in:
@@ -61,6 +61,7 @@ class LastTask(BaseModel):
|
|||||||
None,
|
None,
|
||||||
pattern="^PENDING|RUNNING|SUCCESS|FAILED|ERROR|AWAITING_INPUT|WAITING_INPUT|AWAITING_MAPPING$",
|
pattern="^PENDING|RUNNING|SUCCESS|FAILED|ERROR|AWAITING_INPUT|WAITING_INPUT|AWAITING_MAPPING$",
|
||||||
)
|
)
|
||||||
|
validation_status: Optional[str] = Field(None, pattern="^PASS|FAIL|WARN|UNKNOWN$")
|
||||||
# [/DEF:LastTask:DataClass]
|
# [/DEF:LastTask:DataClass]
|
||||||
|
|
||||||
# [DEF:DashboardItem:DataClass]
|
# [DEF:DashboardItem:DataClass]
|
||||||
@@ -70,6 +71,9 @@ class DashboardItem(BaseModel):
|
|||||||
slug: Optional[str] = None
|
slug: Optional[str] = None
|
||||||
url: Optional[str] = None
|
url: Optional[str] = None
|
||||||
last_modified: Optional[str] = None
|
last_modified: Optional[str] = None
|
||||||
|
created_by: Optional[str] = None
|
||||||
|
modified_by: Optional[str] = None
|
||||||
|
owners: Optional[List[str]] = None
|
||||||
git_status: Optional[GitStatus] = None
|
git_status: Optional[GitStatus] = None
|
||||||
last_task: Optional[LastTask] = None
|
last_task: Optional[LastTask] = None
|
||||||
# [/DEF:DashboardItem:DataClass]
|
# [/DEF:DashboardItem:DataClass]
|
||||||
|
|||||||
@@ -106,7 +106,17 @@ class SupersetClient:
|
|||||||
def get_dashboards_summary(self) -> List[Dict]:
|
def get_dashboards_summary(self) -> List[Dict]:
|
||||||
with belief_scope("SupersetClient.get_dashboards_summary"):
|
with belief_scope("SupersetClient.get_dashboards_summary"):
|
||||||
query = {
|
query = {
|
||||||
"columns": ["id", "dashboard_title", "changed_on_utc", "published"]
|
"columns": [
|
||||||
|
"id",
|
||||||
|
"dashboard_title",
|
||||||
|
"changed_on_utc",
|
||||||
|
"published",
|
||||||
|
"created_by",
|
||||||
|
"created_by_name",
|
||||||
|
"changed_by",
|
||||||
|
"changed_by_name",
|
||||||
|
"owners",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
_, dashboards = self.get_dashboards(query=query)
|
_, dashboards = self.get_dashboards(query=query)
|
||||||
|
|
||||||
@@ -117,11 +127,83 @@ class SupersetClient:
|
|||||||
"id": dash.get("id"),
|
"id": dash.get("id"),
|
||||||
"title": dash.get("dashboard_title"),
|
"title": dash.get("dashboard_title"),
|
||||||
"last_modified": dash.get("changed_on_utc"),
|
"last_modified": dash.get("changed_on_utc"),
|
||||||
"status": "published" if dash.get("published") else "draft"
|
"status": "published" if dash.get("published") else "draft",
|
||||||
|
"created_by": self._extract_user_display(
|
||||||
|
dash.get("created_by_name"),
|
||||||
|
dash.get("created_by"),
|
||||||
|
),
|
||||||
|
"modified_by": self._extract_user_display(
|
||||||
|
dash.get("changed_by_name"),
|
||||||
|
dash.get("changed_by"),
|
||||||
|
),
|
||||||
|
"owners": self._extract_owner_labels(dash.get("owners")),
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
# [/DEF:get_dashboards_summary:Function]
|
# [/DEF:get_dashboards_summary:Function]
|
||||||
|
|
||||||
|
# [DEF:_extract_owner_labels:Function]
|
||||||
|
# @PURPOSE: Normalize dashboard owners payload to stable display labels.
|
||||||
|
# @PRE: owners payload can be None, list of dicts or list of strings.
|
||||||
|
# @POST: Returns deduplicated non-empty owner labels preserving order.
|
||||||
|
# @RETURN: List[str]
|
||||||
|
def _extract_owner_labels(self, owners_payload: Optional[List[Union[Dict, str]]]) -> List[str]:
|
||||||
|
if not isinstance(owners_payload, list):
|
||||||
|
return []
|
||||||
|
|
||||||
|
normalized: List[str] = []
|
||||||
|
for owner in owners_payload:
|
||||||
|
label: Optional[str] = None
|
||||||
|
if isinstance(owner, dict):
|
||||||
|
label = self._extract_user_display(None, owner)
|
||||||
|
else:
|
||||||
|
label = self._sanitize_user_text(owner)
|
||||||
|
if label and label not in normalized:
|
||||||
|
normalized.append(label)
|
||||||
|
return normalized
|
||||||
|
# [/DEF:_extract_owner_labels:Function]
|
||||||
|
|
||||||
|
# [DEF:_extract_user_display:Function]
|
||||||
|
# @PURPOSE: Normalize user payload to a stable display name.
|
||||||
|
# @PRE: user payload can be string, dict or None.
|
||||||
|
# @POST: Returns compact non-empty display value or None.
|
||||||
|
# @RETURN: Optional[str]
|
||||||
|
def _extract_user_display(self, preferred_value: Optional[str], user_payload: Optional[Dict]) -> Optional[str]:
|
||||||
|
preferred = self._sanitize_user_text(preferred_value)
|
||||||
|
if preferred:
|
||||||
|
return preferred
|
||||||
|
|
||||||
|
if isinstance(user_payload, dict):
|
||||||
|
full_name = self._sanitize_user_text(user_payload.get("full_name"))
|
||||||
|
if full_name:
|
||||||
|
return full_name
|
||||||
|
first_name = self._sanitize_user_text(user_payload.get("first_name")) or ""
|
||||||
|
last_name = self._sanitize_user_text(user_payload.get("last_name")) or ""
|
||||||
|
combined = " ".join(part for part in [first_name, last_name] if part).strip()
|
||||||
|
if combined:
|
||||||
|
return combined
|
||||||
|
username = self._sanitize_user_text(user_payload.get("username"))
|
||||||
|
if username:
|
||||||
|
return username
|
||||||
|
email = self._sanitize_user_text(user_payload.get("email"))
|
||||||
|
if email:
|
||||||
|
return email
|
||||||
|
return None
|
||||||
|
# [/DEF:_extract_user_display:Function]
|
||||||
|
|
||||||
|
# [DEF:_sanitize_user_text:Function]
|
||||||
|
# @PURPOSE: Convert scalar value to non-empty user-facing text.
|
||||||
|
# @PRE: value can be any scalar type.
|
||||||
|
# @POST: Returns trimmed string or None.
|
||||||
|
# @RETURN: Optional[str]
|
||||||
|
def _sanitize_user_text(self, value: Optional[Union[str, int]]) -> Optional[str]:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
normalized = str(value).strip()
|
||||||
|
if not normalized:
|
||||||
|
return None
|
||||||
|
return normalized
|
||||||
|
# [/DEF:_sanitize_user_text:Function]
|
||||||
|
|
||||||
# [DEF:get_dashboard:Function]
|
# [DEF:get_dashboard:Function]
|
||||||
# @PURPOSE: Fetches a single dashboard by ID.
|
# @PURPOSE: Fetches a single dashboard by ID.
|
||||||
# @PRE: Client is authenticated and dashboard_id exists.
|
# @PRE: Client is authenticated and dashboard_id exists.
|
||||||
|
|||||||
@@ -305,6 +305,10 @@
|
|||||||
"running": "Running...",
|
"running": "Running...",
|
||||||
"git_status": "Git Status",
|
"git_status": "Git Status",
|
||||||
"last_task": "Last Task",
|
"last_task": "Last Task",
|
||||||
|
"llm_status": "LLM Validation Status",
|
||||||
|
"changed_on": "Changed On",
|
||||||
|
"owners": "Owners",
|
||||||
|
"column_filter": "Column filter",
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"action_migrate": "Migrate",
|
"action_migrate": "Migrate",
|
||||||
"action_backup": "Backup",
|
"action_backup": "Backup",
|
||||||
|
|||||||
@@ -304,6 +304,10 @@
|
|||||||
"running": "Запуск...",
|
"running": "Запуск...",
|
||||||
"git_status": "Статус Git",
|
"git_status": "Статус Git",
|
||||||
"last_task": "Последняя задача",
|
"last_task": "Последняя задача",
|
||||||
|
"llm_status": "Статус LLM пров.",
|
||||||
|
"changed_on": "Дата изменения",
|
||||||
|
"owners": "Владельцы",
|
||||||
|
"column_filter": "Фильтр по колонке",
|
||||||
"actions": "Действия",
|
"actions": "Действия",
|
||||||
"action_migrate": "Мигрировать",
|
"action_migrate": "Мигрировать",
|
||||||
"action_backup": "Создать бэкап",
|
"action_backup": "Создать бэкап",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user