69 lines
2.6 KiB
Python
69 lines
2.6 KiB
Python
|
|
"""Экспорт отчётов: генерация CSV, история."""
|
||
|
|
import subprocess
|
||
|
|
|
||
|
|
import flet as ft
|
||
|
|
|
||
|
|
from app.core import reports as rep
|
||
|
|
from app.ui.components import snack
|
||
|
|
|
||
|
|
|
||
|
|
class ReportsPage(ft.Column):
|
||
|
|
def __init__(self, page: ft.Page, go):
|
||
|
|
super().__init__(expand=True, scroll=ft.ScrollMode.AUTO, spacing=12)
|
||
|
|
self._page = page
|
||
|
|
|
||
|
|
self.status = ft.Text("", size=13, color=ft.Colors.GREY_500)
|
||
|
|
self.list_col = ft.Column(spacing=4)
|
||
|
|
|
||
|
|
self.controls = [
|
||
|
|
ft.Text("Отчёты", size=28, weight=ft.FontWeight.BOLD),
|
||
|
|
ft.Text("CSV со списком серверов, статусом онлайн, метриками и последними задачами.",
|
||
|
|
size=13, color=ft.Colors.GREY_500),
|
||
|
|
ft.Row([
|
||
|
|
ft.FilledButton("Сгенерировать отчёт", icon=ft.Icons.SUMMARIZE,
|
||
|
|
on_click=self._generate),
|
||
|
|
ft.IconButton(ft.Icons.REFRESH, on_click=lambda e: self._reload()),
|
||
|
|
]),
|
||
|
|
self.status,
|
||
|
|
ft.Divider(),
|
||
|
|
ft.Text("История отчётов", weight=ft.FontWeight.BOLD, size=16),
|
||
|
|
self.list_col,
|
||
|
|
]
|
||
|
|
self._reload()
|
||
|
|
|
||
|
|
def _generate(self, e):
|
||
|
|
self.status.value = "генерация…"
|
||
|
|
self._page.update()
|
||
|
|
|
||
|
|
async def _do():
|
||
|
|
path = await rep.generate()
|
||
|
|
self.status.value = f"сохранён: {path}"
|
||
|
|
self._reload()
|
||
|
|
self._page.run_task(_do)
|
||
|
|
|
||
|
|
def _reload(self):
|
||
|
|
self.list_col.controls = []
|
||
|
|
for p in rep.list_reports():
|
||
|
|
size_kb = p.stat().st_size // 1024
|
||
|
|
self.list_col.controls.append(
|
||
|
|
ft.ListTile(
|
||
|
|
leading=ft.Icon(ft.Icons.DESCRIPTION),
|
||
|
|
title=ft.Text(p.name, size=13),
|
||
|
|
subtitle=ft.Text(f"{size_kb} КБ", size=11),
|
||
|
|
dense=True,
|
||
|
|
trailing=ft.IconButton(
|
||
|
|
ft.Icons.OPEN_IN_NEW, tooltip="Открыть",
|
||
|
|
on_click=lambda e, p=p: self._open(p)),
|
||
|
|
)
|
||
|
|
)
|
||
|
|
if not self.list_col.controls:
|
||
|
|
self.list_col.controls.append(
|
||
|
|
ft.Text("отчётов пока нет", color=ft.Colors.GREY_500))
|
||
|
|
self._page.update()
|
||
|
|
|
||
|
|
def _open(self, path):
|
||
|
|
try:
|
||
|
|
subprocess.Popen(["explorer", "/select,", str(path)])
|
||
|
|
except Exception as ex:
|
||
|
|
snack(self._page, f"не удалось открыть: {ex}", error=True)
|