refactor: remove admin recommendation summaries
This commit is contained in:
+4
-624
@@ -447,15 +447,9 @@ class FileService:
|
|||||||
page = max(page, 1)
|
page = max(page, 1)
|
||||||
size = min(max(size, 1), 100)
|
size = min(max(size, 1), 100)
|
||||||
keyword = keyword.strip().lower()
|
keyword = keyword.strip().lower()
|
||||||
status = self._normalize_file_view_preset_choice(
|
status = status.strip().lower()
|
||||||
status, self.VIEW_PRESET_STATUS_VALUES
|
file_type = file_type.strip().lower()
|
||||||
)
|
health = health.strip().lower()
|
||||||
file_type = self._normalize_file_view_preset_choice(
|
|
||||||
file_type, self.VIEW_PRESET_TYPE_VALUES
|
|
||||||
)
|
|
||||||
health = self._normalize_file_view_preset_choice(
|
|
||||||
health, self.VIEW_PRESET_HEALTH_VALUES
|
|
||||||
)
|
|
||||||
sort_by = self._normalize_sort_by(sort_by)
|
sort_by = self._normalize_sort_by(sort_by)
|
||||||
reverse = sort_order.strip().lower() != "asc"
|
reverse = sort_order.strip().lower() != "asc"
|
||||||
|
|
||||||
@@ -496,27 +490,8 @@ class FileService:
|
|||||||
key=lambda item: self._get_sort_value(item, sort_by),
|
key=lambda item: self._get_sort_value(item, sort_by),
|
||||||
reverse=reverse,
|
reverse=reverse,
|
||||||
)
|
)
|
||||||
view_summary = self._build_file_view_summary(
|
|
||||||
files=enriched_files,
|
|
||||||
all_file_count=len(all_files),
|
|
||||||
filters={
|
|
||||||
"keyword": keyword,
|
|
||||||
"status": status or "all",
|
|
||||||
"type": file_type or "all",
|
|
||||||
"health": health or "all",
|
|
||||||
"sortBy": sort_by,
|
|
||||||
"sort_by": sort_by,
|
|
||||||
"sortOrder": "desc" if reverse else "asc",
|
|
||||||
"sort_order": "desc" if reverse else "asc",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
offset = (page - 1) * size
|
offset = (page - 1) * size
|
||||||
return (
|
return enriched_files[offset : offset + size], len(enriched_files), summary
|
||||||
enriched_files[offset : offset + size],
|
|
||||||
len(enriched_files),
|
|
||||||
summary,
|
|
||||||
view_summary,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _empty_health_summary(self) -> dict[str, int]:
|
def _empty_health_summary(self) -> dict[str, int]:
|
||||||
return {
|
return {
|
||||||
@@ -553,189 +528,6 @@ class FileService:
|
|||||||
if "never_retrieved" in reasons:
|
if "never_retrieved" in reasons:
|
||||||
summary["neverRetrievedCount"] += 1
|
summary["neverRetrievedCount"] += 1
|
||||||
|
|
||||||
def _build_file_view_summary(
|
|
||||||
self,
|
|
||||||
files: list[dict[str, Any]],
|
|
||||||
all_file_count: int,
|
|
||||||
filters: dict[str, Any],
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
view_counts = {
|
|
||||||
"totalFiles": len(files),
|
|
||||||
"activeCount": 0,
|
|
||||||
"expiredCount": 0,
|
|
||||||
"textCount": 0,
|
|
||||||
"fileCount": 0,
|
|
||||||
"chunkedCount": 0,
|
|
||||||
**self._empty_health_summary(),
|
|
||||||
"storageUsed": sum(item.get("size") or 0 for item in files),
|
|
||||||
"usedCount": sum(item.get("usedCount") or 0 for item in files),
|
|
||||||
}
|
|
||||||
|
|
||||||
for item in files:
|
|
||||||
if item.get("isExpired"):
|
|
||||||
view_counts["expiredCount"] += 1
|
|
||||||
else:
|
|
||||||
view_counts["activeCount"] += 1
|
|
||||||
if item.get("isText"):
|
|
||||||
view_counts["textCount"] += 1
|
|
||||||
else:
|
|
||||||
view_counts["fileCount"] += 1
|
|
||||||
if item.get("isChunked"):
|
|
||||||
view_counts["chunkedCount"] += 1
|
|
||||||
self._accumulate_health_summary(view_counts, item)
|
|
||||||
|
|
||||||
cards = self._build_file_view_summary_cards(view_counts)
|
|
||||||
actions = self._build_file_view_summary_actions(cards)
|
|
||||||
strongest_severity = self._get_strongest_summary_severity(cards)
|
|
||||||
active_filter_count = sum(
|
|
||||||
[
|
|
||||||
1 if str(filters.get("keyword") or "").strip() else 0,
|
|
||||||
1 if str(filters.get("status") or "all").strip() != "all" else 0,
|
|
||||||
1 if str(filters.get("type") or "all").strip() != "all" else 0,
|
|
||||||
1 if str(filters.get("health") or "all").strip() != "all" else 0,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"total": len(files),
|
|
||||||
"filteredTotal": len(files),
|
|
||||||
"filtered_total": len(files),
|
|
||||||
"allTotal": max(int(all_file_count or 0), 0),
|
|
||||||
"all_total": max(int(all_file_count or 0), 0),
|
|
||||||
"activeFilterCount": active_filter_count,
|
|
||||||
"active_filter_count": active_filter_count,
|
|
||||||
"hasFilters": active_filter_count > 0,
|
|
||||||
"has_filters": active_filter_count > 0,
|
|
||||||
"strongestSeverity": strongest_severity,
|
|
||||||
"strongest_severity": strongest_severity,
|
|
||||||
"filters": filters,
|
|
||||||
"summary": view_counts,
|
|
||||||
"healthSummary": view_counts,
|
|
||||||
"health_summary": view_counts,
|
|
||||||
"cards": cards,
|
|
||||||
"items": cards,
|
|
||||||
"actions": actions,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _build_file_view_summary_cards(
|
|
||||||
self, summary: dict[str, Any]
|
|
||||||
) -> list[dict[str, Any]]:
|
|
||||||
candidates = [
|
|
||||||
{
|
|
||||||
"key": "storage_issue",
|
|
||||||
"severity": "danger",
|
|
||||||
"priority": 100,
|
|
||||||
"count": summary["storageIssueCount"],
|
|
||||||
"health": "storage_issue",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "expired",
|
|
||||||
"severity": "danger" if summary["expiredCount"] >= 10 else "warning",
|
|
||||||
"priority": 90,
|
|
||||||
"count": summary["expiredCount"],
|
|
||||||
"health": "expired",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "expiring_soon",
|
|
||||||
"severity": "warning",
|
|
||||||
"priority": 80,
|
|
||||||
"count": summary["expiringSoonCount"],
|
|
||||||
"health": "expiring_soon",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "never_retrieved",
|
|
||||||
"severity": "neutral",
|
|
||||||
"priority": 60,
|
|
||||||
"count": summary["neverRetrievedCount"],
|
|
||||||
"health": "never_retrieved",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "permanent",
|
|
||||||
"severity": "neutral",
|
|
||||||
"priority": 40,
|
|
||||||
"count": summary["permanentCount"],
|
|
||||||
"health": "permanent",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
cards = [
|
|
||||||
self._build_file_view_summary_item(
|
|
||||||
key=item["key"],
|
|
||||||
severity=item["severity"],
|
|
||||||
priority=item["priority"],
|
|
||||||
count=item["count"],
|
|
||||||
health=item["health"],
|
|
||||||
)
|
|
||||||
for item in candidates
|
|
||||||
if item["count"] > 0
|
|
||||||
]
|
|
||||||
|
|
||||||
if not cards:
|
|
||||||
key = "empty" if summary["totalFiles"] == 0 else "healthy"
|
|
||||||
cards.append(
|
|
||||||
self._build_file_view_summary_item(
|
|
||||||
key=key,
|
|
||||||
severity="success" if summary["totalFiles"] > 0 else "neutral",
|
|
||||||
priority=10,
|
|
||||||
count=summary["totalFiles"],
|
|
||||||
health="healthy" if summary["totalFiles"] > 0 else "all",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
cards.sort(key=lambda item: (-item["priority"], item["key"]))
|
|
||||||
return cards[:4]
|
|
||||||
|
|
||||||
def _build_file_view_summary_actions(
|
|
||||||
self, cards: list[dict[str, Any]]
|
|
||||||
) -> list[dict[str, Any]]:
|
|
||||||
action_key_map = {
|
|
||||||
"storage_issue": "inspect_storage",
|
|
||||||
"expired": "cleanup_expired",
|
|
||||||
"expiring_soon": "extend_expiring",
|
|
||||||
"never_retrieved": "review_never_retrieved",
|
|
||||||
"permanent": "review_permanent",
|
|
||||||
"healthy": "monitor",
|
|
||||||
"empty": "clear_filters",
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
**item,
|
|
||||||
"sourceKey": item["key"],
|
|
||||||
"source_key": item["key"],
|
|
||||||
"suggestedAction": action_key_map.get(item["key"], "review"),
|
|
||||||
"suggested_action": action_key_map.get(item["key"], "review"),
|
|
||||||
}
|
|
||||||
for item in cards
|
|
||||||
if item["severity"] != "success"
|
|
||||||
]
|
|
||||||
|
|
||||||
def _build_file_view_summary_item(
|
|
||||||
self,
|
|
||||||
key: str,
|
|
||||||
severity: str,
|
|
||||||
priority: int,
|
|
||||||
count: int,
|
|
||||||
health: str,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
return {
|
|
||||||
"key": key,
|
|
||||||
"severity": severity,
|
|
||||||
"priority": priority,
|
|
||||||
"count": max(int(count or 0), 0),
|
|
||||||
"actionType": "filter",
|
|
||||||
"action_type": "filter",
|
|
||||||
"health": health,
|
|
||||||
"targetHealth": health,
|
|
||||||
"target_health": health,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _get_strongest_summary_severity(self, items: list[dict[str, Any]]) -> str:
|
|
||||||
severity_order = {"danger": 3, "warning": 2, "neutral": 1, "success": 0}
|
|
||||||
return max(
|
|
||||||
(item["severity"] for item in items),
|
|
||||||
key=lambda severity: severity_order.get(severity, 0),
|
|
||||||
default="success",
|
|
||||||
)
|
|
||||||
|
|
||||||
async def build_file_health_summary(
|
async def build_file_health_summary(
|
||||||
self, file_codes: list[FileCodes], now: Optional[datetime] = None
|
self, file_codes: list[FileCodes], now: Optional[datetime] = None
|
||||||
) -> dict[str, int]:
|
) -> dict[str, int]:
|
||||||
@@ -747,418 +539,6 @@ class FileService:
|
|||||||
self._accumulate_health_summary(summary, item)
|
self._accumulate_health_summary(summary, item)
|
||||||
return summary
|
return summary
|
||||||
|
|
||||||
async def get_dashboard_maintenance_queue(self) -> dict[str, Any]:
|
|
||||||
file_codes = await FileCodes.all()
|
|
||||||
now = await get_now()
|
|
||||||
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
||||||
today_size = sum(
|
|
||||||
file_code.size
|
|
||||||
for file_code in file_codes
|
|
||||||
if file_code.created_at and file_code.created_at >= today_start
|
|
||||||
)
|
|
||||||
expired_count = 0
|
|
||||||
for file_code in file_codes:
|
|
||||||
if await file_code.is_expired():
|
|
||||||
expired_count += 1
|
|
||||||
|
|
||||||
health_summary = await self.build_file_health_summary(file_codes, now=now)
|
|
||||||
return self.build_dashboard_maintenance_queue(
|
|
||||||
health_summary=health_summary,
|
|
||||||
total_files=len(file_codes),
|
|
||||||
expired_count=expired_count,
|
|
||||||
today_size=today_size,
|
|
||||||
upload_size_limit=settings.uploadSize,
|
|
||||||
open_upload=settings.openUpload,
|
|
||||||
enable_chunk=settings.enableChunk,
|
|
||||||
max_save_seconds=settings.max_save_seconds,
|
|
||||||
)
|
|
||||||
|
|
||||||
def build_dashboard_operational_insights(
|
|
||||||
self,
|
|
||||||
health_summary: dict[str, int],
|
|
||||||
total_files: int,
|
|
||||||
expired_count: int,
|
|
||||||
today_size: int,
|
|
||||||
upload_size_limit: int,
|
|
||||||
open_upload: int,
|
|
||||||
enable_chunk: int,
|
|
||||||
max_save_seconds: int,
|
|
||||||
) -> list[dict[str, Any]]:
|
|
||||||
def to_int(value: Any) -> int:
|
|
||||||
try:
|
|
||||||
return int(value or 0)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
total_files = to_int(total_files)
|
|
||||||
expired_count = to_int(expired_count)
|
|
||||||
today_size = to_int(today_size)
|
|
||||||
upload_size_limit = to_int(upload_size_limit)
|
|
||||||
open_upload = to_int(open_upload)
|
|
||||||
enable_chunk = to_int(enable_chunk)
|
|
||||||
max_save_seconds = to_int(max_save_seconds)
|
|
||||||
insights = []
|
|
||||||
|
|
||||||
if health_summary.get("storageIssueCount", 0) > 0:
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="storage_issue",
|
|
||||||
severity="danger",
|
|
||||||
priority=100,
|
|
||||||
count=health_summary["storageIssueCount"],
|
|
||||||
action_type="file_queue",
|
|
||||||
health="storage_issue",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if expired_count > 0:
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="expired_cleanup",
|
|
||||||
severity="danger" if expired_count >= 10 else "warning",
|
|
||||||
priority=90,
|
|
||||||
count=expired_count,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="expired",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if health_summary.get("expiringSoonCount", 0) > 0:
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="expiring_soon",
|
|
||||||
severity="warning",
|
|
||||||
priority=80,
|
|
||||||
count=health_summary["expiringSoonCount"],
|
|
||||||
action_type="file_queue",
|
|
||||||
health="expiring_soon",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
never_retrieved_count = health_summary.get("neverRetrievedCount", 0)
|
|
||||||
if total_files > 0 and never_retrieved_count >= max(3, total_files // 5):
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="never_retrieved",
|
|
||||||
severity="neutral",
|
|
||||||
priority=60,
|
|
||||||
count=never_retrieved_count,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="never_retrieved",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if open_upload and max_save_seconds <= 0:
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="guest_upload_retention",
|
|
||||||
severity="warning",
|
|
||||||
priority=50,
|
|
||||||
count=1,
|
|
||||||
action_type="settings",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
upload_size_limit > 0
|
|
||||||
and today_size >= upload_size_limit
|
|
||||||
and not enable_chunk
|
|
||||||
):
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="chunking_disabled",
|
|
||||||
severity="neutral",
|
|
||||||
priority=40,
|
|
||||||
count=1,
|
|
||||||
action_type="settings",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not insights:
|
|
||||||
insights.append(
|
|
||||||
self._build_dashboard_operational_insight(
|
|
||||||
key="healthy",
|
|
||||||
severity="success",
|
|
||||||
priority=10,
|
|
||||||
count=total_files,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="healthy",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
insights.sort(key=lambda item: (-item["priority"], item["key"]))
|
|
||||||
return insights[:4]
|
|
||||||
|
|
||||||
def build_dashboard_maintenance_queue(
|
|
||||||
self,
|
|
||||||
health_summary: dict[str, int],
|
|
||||||
total_files: int,
|
|
||||||
expired_count: int,
|
|
||||||
today_size: int,
|
|
||||||
upload_size_limit: int,
|
|
||||||
open_upload: int,
|
|
||||||
enable_chunk: int,
|
|
||||||
max_save_seconds: int,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
def to_int(value: Any) -> int:
|
|
||||||
try:
|
|
||||||
return int(value or 0)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
total_files = to_int(total_files)
|
|
||||||
expired_count = to_int(expired_count)
|
|
||||||
today_size = to_int(today_size)
|
|
||||||
upload_size_limit = to_int(upload_size_limit)
|
|
||||||
open_upload = to_int(open_upload)
|
|
||||||
enable_chunk = to_int(enable_chunk)
|
|
||||||
max_save_seconds = to_int(max_save_seconds)
|
|
||||||
items = []
|
|
||||||
|
|
||||||
if health_summary.get("storageIssueCount", 0) > 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="storage_issue",
|
|
||||||
severity="danger",
|
|
||||||
category="storage",
|
|
||||||
priority=100,
|
|
||||||
count=health_summary["storageIssueCount"],
|
|
||||||
action_type="file_queue",
|
|
||||||
health="storage_issue",
|
|
||||||
suggested_action="inspect_storage",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if expired_count > 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="expired_cleanup",
|
|
||||||
severity="danger" if expired_count >= 10 else "warning",
|
|
||||||
category="retention",
|
|
||||||
priority=90,
|
|
||||||
count=expired_count,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="expired",
|
|
||||||
suggested_action="cleanup_or_extend",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if health_summary.get("expiringSoonCount", 0) > 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="expiring_soon",
|
|
||||||
severity="warning",
|
|
||||||
category="retention",
|
|
||||||
priority=80,
|
|
||||||
count=health_summary["expiringSoonCount"],
|
|
||||||
action_type="file_queue",
|
|
||||||
health="expiring_soon",
|
|
||||||
suggested_action="extend_expiration",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
never_retrieved_count = health_summary.get("neverRetrievedCount", 0)
|
|
||||||
if never_retrieved_count > 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="never_retrieved",
|
|
||||||
severity="neutral",
|
|
||||||
category="adoption",
|
|
||||||
priority=60,
|
|
||||||
count=never_retrieved_count,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="never_retrieved",
|
|
||||||
suggested_action="review_usage",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
permanent_count = health_summary.get("permanentCount", 0)
|
|
||||||
if permanent_count > 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="permanent_review",
|
|
||||||
severity="neutral",
|
|
||||||
category="retention",
|
|
||||||
priority=45,
|
|
||||||
count=permanent_count,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="permanent",
|
|
||||||
suggested_action="review_retention",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if open_upload and max_save_seconds <= 0:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="guest_upload_retention",
|
|
||||||
severity="warning",
|
|
||||||
category="settings",
|
|
||||||
priority=70,
|
|
||||||
count=1,
|
|
||||||
action_type="settings",
|
|
||||||
suggested_action="set_retention_limit",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
upload_size_limit > 0
|
|
||||||
and today_size >= upload_size_limit
|
|
||||||
and not enable_chunk
|
|
||||||
):
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="chunking_disabled",
|
|
||||||
severity="neutral",
|
|
||||||
category="settings",
|
|
||||||
priority=40,
|
|
||||||
count=1,
|
|
||||||
action_type="settings",
|
|
||||||
suggested_action="enable_chunking",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not items:
|
|
||||||
items.append(
|
|
||||||
self._build_dashboard_maintenance_item(
|
|
||||||
key="healthy",
|
|
||||||
severity="success",
|
|
||||||
category="system",
|
|
||||||
priority=10,
|
|
||||||
count=total_files,
|
|
||||||
action_type="file_queue",
|
|
||||||
health="healthy",
|
|
||||||
suggested_action="monitor",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
items.sort(key=lambda item: (-item["priority"], item["key"]))
|
|
||||||
summary = self._build_dashboard_maintenance_summary(items)
|
|
||||||
return {
|
|
||||||
"items": items,
|
|
||||||
"maintenanceItems": items,
|
|
||||||
"maintenance_items": items,
|
|
||||||
"summary": summary,
|
|
||||||
"maintenanceSummary": summary,
|
|
||||||
"maintenance_summary": summary,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _build_dashboard_maintenance_item(
|
|
||||||
self,
|
|
||||||
key: str,
|
|
||||||
severity: str,
|
|
||||||
category: str,
|
|
||||||
priority: int,
|
|
||||||
count: int,
|
|
||||||
action_type: str,
|
|
||||||
suggested_action: str,
|
|
||||||
health: Optional[str] = None,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
action = {
|
|
||||||
"type": action_type,
|
|
||||||
"actionType": action_type,
|
|
||||||
"action_type": action_type,
|
|
||||||
"suggestedAction": suggested_action,
|
|
||||||
"suggested_action": suggested_action,
|
|
||||||
}
|
|
||||||
if health:
|
|
||||||
action.update(
|
|
||||||
{
|
|
||||||
"health": health,
|
|
||||||
"targetHealth": health,
|
|
||||||
"target_health": health,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"key": key,
|
|
||||||
"severity": severity,
|
|
||||||
"category": category,
|
|
||||||
"priority": priority,
|
|
||||||
"count": max(int(count or 0), 0),
|
|
||||||
"action": action,
|
|
||||||
"actionType": action_type,
|
|
||||||
"action_type": action_type,
|
|
||||||
"suggestedAction": suggested_action,
|
|
||||||
"suggested_action": suggested_action,
|
|
||||||
"targetHealth": health,
|
|
||||||
"target_health": health,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _build_dashboard_maintenance_summary(
|
|
||||||
self, items: list[dict[str, Any]]
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
severity_order = {"danger": 3, "warning": 2, "neutral": 1, "success": 0}
|
|
||||||
strongest_severity = max(
|
|
||||||
(item["severity"] for item in items),
|
|
||||||
key=lambda severity: severity_order.get(severity, 0),
|
|
||||||
default="success",
|
|
||||||
)
|
|
||||||
actionable_items = [item for item in items if item["severity"] != "success"]
|
|
||||||
file_queue_count = sum(
|
|
||||||
item["count"]
|
|
||||||
for item in actionable_items
|
|
||||||
if item.get("actionType") == "file_queue"
|
|
||||||
)
|
|
||||||
settings_count = sum(
|
|
||||||
item["count"]
|
|
||||||
for item in actionable_items
|
|
||||||
if item.get("actionType") == "settings"
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
"total": len(items),
|
|
||||||
"actionableCount": len(actionable_items),
|
|
||||||
"actionable_count": len(actionable_items),
|
|
||||||
"dangerCount": sum(1 for item in items if item["severity"] == "danger"),
|
|
||||||
"danger_count": sum(1 for item in items if item["severity"] == "danger"),
|
|
||||||
"warningCount": sum(1 for item in items if item["severity"] == "warning"),
|
|
||||||
"warning_count": sum(1 for item in items if item["severity"] == "warning"),
|
|
||||||
"successCount": sum(1 for item in items if item["severity"] == "success"),
|
|
||||||
"success_count": sum(1 for item in items if item["severity"] == "success"),
|
|
||||||
"neutralCount": sum(1 for item in items if item["severity"] == "neutral"),
|
|
||||||
"neutral_count": sum(1 for item in items if item["severity"] == "neutral"),
|
|
||||||
"fileQueueCount": file_queue_count,
|
|
||||||
"file_queue_count": file_queue_count,
|
|
||||||
"settingsCount": settings_count,
|
|
||||||
"settings_count": settings_count,
|
|
||||||
"strongestSeverity": strongest_severity,
|
|
||||||
"strongest_severity": strongest_severity,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _build_dashboard_operational_insight(
|
|
||||||
self,
|
|
||||||
key: str,
|
|
||||||
severity: str,
|
|
||||||
priority: int,
|
|
||||||
count: int,
|
|
||||||
action_type: str,
|
|
||||||
health: Optional[str] = None,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
action = {
|
|
||||||
"type": action_type,
|
|
||||||
"actionType": action_type,
|
|
||||||
"action_type": action_type,
|
|
||||||
}
|
|
||||||
if health:
|
|
||||||
action.update(
|
|
||||||
{
|
|
||||||
"health": health,
|
|
||||||
"targetHealth": health,
|
|
||||||
"target_health": health,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"key": key,
|
|
||||||
"severity": severity,
|
|
||||||
"priority": priority,
|
|
||||||
"count": max(int(count or 0), 0),
|
|
||||||
"action": action,
|
|
||||||
"actionType": action_type,
|
|
||||||
"action_type": action_type,
|
|
||||||
"targetHealth": health,
|
|
||||||
"target_health": health,
|
|
||||||
}
|
|
||||||
|
|
||||||
async def _build_admin_file_item(
|
async def _build_admin_file_item(
|
||||||
self, file_code: FileCodes, now: Optional[datetime] = None
|
self, file_code: FileCodes, now: Optional[datetime] = None
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
|
|||||||
+2
-45
@@ -99,32 +99,11 @@ async def dashboard(file_service: FileService = Depends(get_file_service)):
|
|||||||
today_codes = FileCodes.filter(created_at__gte=today_start)
|
today_codes = FileCodes.filter(created_at__gte=today_start)
|
||||||
yesterday_file_codes = await yesterday_codes
|
yesterday_file_codes = await yesterday_codes
|
||||||
today_file_codes = await today_codes
|
today_file_codes = await today_codes
|
||||||
today_size = sum([code.size for code in today_file_codes])
|
|
||||||
expired_count = 0
|
expired_count = 0
|
||||||
for file_code in all_codes:
|
for file_code in all_codes:
|
||||||
if await file_code.is_expired():
|
if await file_code.is_expired():
|
||||||
expired_count += 1
|
expired_count += 1
|
||||||
health_summary = await file_service.build_file_health_summary(all_codes, now=now)
|
health_summary = await file_service.build_file_health_summary(all_codes, now=now)
|
||||||
operational_insights = file_service.build_dashboard_operational_insights(
|
|
||||||
health_summary=health_summary,
|
|
||||||
total_files=len(all_codes),
|
|
||||||
expired_count=expired_count,
|
|
||||||
today_size=today_size,
|
|
||||||
upload_size_limit=settings.uploadSize,
|
|
||||||
open_upload=settings.openUpload,
|
|
||||||
enable_chunk=settings.enableChunk,
|
|
||||||
max_save_seconds=settings.max_save_seconds,
|
|
||||||
)
|
|
||||||
maintenance_queue = file_service.build_dashboard_maintenance_queue(
|
|
||||||
health_summary=health_summary,
|
|
||||||
total_files=len(all_codes),
|
|
||||||
expired_count=expired_count,
|
|
||||||
today_size=today_size,
|
|
||||||
upload_size_limit=settings.uploadSize,
|
|
||||||
open_upload=settings.openUpload,
|
|
||||||
enable_chunk=settings.enableChunk,
|
|
||||||
max_save_seconds=settings.max_save_seconds,
|
|
||||||
)
|
|
||||||
|
|
||||||
text_count = sum(1 for file_code in all_codes if file_code.text is not None)
|
text_count = sum(1 for file_code in all_codes if file_code.text is not None)
|
||||||
chunked_count = sum(1 for file_code in all_codes if file_code.is_chunked)
|
chunked_count = sum(1 for file_code in all_codes if file_code.is_chunked)
|
||||||
@@ -149,7 +128,7 @@ async def dashboard(file_service: FileService = Depends(get_file_service)):
|
|||||||
"yesterdayCount": len(yesterday_file_codes),
|
"yesterdayCount": len(yesterday_file_codes),
|
||||||
"yesterdaySize": str(sum([code.size for code in yesterday_file_codes])),
|
"yesterdaySize": str(sum([code.size for code in yesterday_file_codes])),
|
||||||
"todayCount": len(today_file_codes),
|
"todayCount": len(today_file_codes),
|
||||||
"todaySize": str(today_size),
|
"todaySize": str(sum([code.size for code in today_file_codes])),
|
||||||
"activeCount": len(all_codes) - expired_count,
|
"activeCount": len(all_codes) - expired_count,
|
||||||
"expiredCount": expired_count,
|
"expiredCount": expired_count,
|
||||||
"textCount": text_count,
|
"textCount": text_count,
|
||||||
@@ -163,15 +142,6 @@ async def dashboard(file_service: FileService = Depends(get_file_service)):
|
|||||||
"maxSaveSeconds": settings.max_save_seconds,
|
"maxSaveSeconds": settings.max_save_seconds,
|
||||||
**health_summary,
|
**health_summary,
|
||||||
"healthSummary": health_summary,
|
"healthSummary": health_summary,
|
||||||
"operationalInsights": operational_insights,
|
|
||||||
"operational_insights": operational_insights,
|
|
||||||
"insights": operational_insights,
|
|
||||||
"maintenanceQueue": maintenance_queue,
|
|
||||||
"maintenance_queue": maintenance_queue,
|
|
||||||
"maintenanceItems": maintenance_queue["items"],
|
|
||||||
"maintenance_items": maintenance_queue["items"],
|
|
||||||
"maintenanceSummary": maintenance_queue["summary"],
|
|
||||||
"maintenance_summary": maintenance_queue["summary"],
|
|
||||||
"topSuffixes": [
|
"topSuffixes": [
|
||||||
{"suffix": suffix, "count": count}
|
{"suffix": suffix, "count": count}
|
||||||
for suffix, count in suffix_counter.most_common(8)
|
for suffix, count in suffix_counter.most_common(8)
|
||||||
@@ -186,13 +156,6 @@ async def dashboard(file_service: FileService = Depends(get_file_service)):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@admin_api.get("/dashboard/maintenance-queue")
|
|
||||||
async def dashboard_maintenance_queue(
|
|
||||||
file_service: FileService = Depends(get_file_service),
|
|
||||||
):
|
|
||||||
return APIResponse(detail=await file_service.get_dashboard_maintenance_queue())
|
|
||||||
|
|
||||||
|
|
||||||
@admin_api.get("/activities")
|
@admin_api.get("/activities")
|
||||||
async def admin_activities(
|
async def admin_activities(
|
||||||
limit: int = 20,
|
limit: int = 20,
|
||||||
@@ -374,7 +337,7 @@ async def file_list(
|
|||||||
):
|
):
|
||||||
page = max(page, 1)
|
page = max(page, 1)
|
||||||
size = min(max(size, 1), 100)
|
size = min(max(size, 1), 100)
|
||||||
files, total, summary, view_summary = await file_service.list_files(
|
files, total, summary = await file_service.list_files(
|
||||||
page,
|
page,
|
||||||
size,
|
size,
|
||||||
keyword,
|
keyword,
|
||||||
@@ -391,12 +354,6 @@ async def file_list(
|
|||||||
"data": files,
|
"data": files,
|
||||||
"total": total,
|
"total": total,
|
||||||
"summary": summary,
|
"summary": summary,
|
||||||
"viewSummary": view_summary,
|
|
||||||
"view_summary": view_summary,
|
|
||||||
"currentViewSummary": view_summary,
|
|
||||||
"current_view_summary": view_summary,
|
|
||||||
"actionSummary": view_summary,
|
|
||||||
"action_summary": view_summary,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user