test ferst

This commit is contained in:
jze9
2026-05-13 19:05:07 +05:00
commit 0ac1c8a862
33 changed files with 3702 additions and 0 deletions

189
web/views/news_detail.py Normal file
View File

@@ -0,0 +1,189 @@
import flet as ft
import designer as d
import api_client as api
import theme_manager
class NewsDetailView:
def __init__(self, page: ft.Page, slug: str):
self.page = page
self.slug = slug
self._content_col = ft.Column(
[ft.Container(content=d.loader(), alignment=ft.alignment.center, padding=40)],
expand=True,
)
def build_page_view(self) -> ft.View:
header = ft.Container(
content=ft.Row(
[
ft.IconButton(
ft.icons.ARROW_BACK,
icon_color=ft.colors.WHITE,
tooltip="Назад",
on_click=lambda e: self.page.go("/"),
),
ft.Row([
ft.Icon(ft.icons.NEWSPAPER, color=ft.colors.WHITE, size=24),
ft.Text("Новости", size=18, weight=ft.FontWeight.BOLD, color=ft.colors.WHITE),
], spacing=8),
ft.Container(width=40),
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
),
bgcolor=d.ADMIN_SIDEBAR,
padding=ft.padding.symmetric(horizontal=16, vertical=12),
)
return ft.View(
route=f"/news/{self.slug}",
bgcolor=d.BACKGROUND,
controls=[
ft.Column(
[
header,
ft.Container(
content=self._content_col,
alignment=ft.alignment.top_center,
expand=True,
padding=ft.padding.symmetric(horizontal=24, vertical=20),
),
],
spacing=0,
expand=True,
scroll=ft.ScrollMode.AUTO,
)
],
)
async def load(self):
article = await api.get_article(self.slug)
if not article:
theme_manager.reset_font(self.page)
self._content_col.controls = [
ft.Container(
content=ft.Column(
[
ft.Icon(ft.icons.ARTICLE_OUTLINED, size=64, color=d.DIVIDER),
d.headline("Статья не найдена", size=20),
d.btn_outlined("На главную", on_click=lambda e: self.page.go("/")),
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=16,
),
alignment=ft.alignment.center,
padding=60,
)
]
self.page.update()
return
font = article.get("font_family", "Merriweather")
theme_manager.apply_article_font(self.page, font)
self._render(article)
def _render(self, a: dict):
font = a.get("font_family", "Merriweather")
cat = a.get("category")
tags = a.get("tags", [])
pub_date = a.get("published_at", "")[:10] if a.get("published_at") else ""
meta_chips = ft.Row(wrap=True, spacing=8, run_spacing=8)
if cat:
meta_chips.controls.append(
ft.Container(
content=ft.Text(cat["name"], size=12, color=ft.colors.WHITE),
bgcolor=d.PRIMARY,
border_radius=4,
padding=ft.padding.symmetric(horizontal=10, vertical=4),
)
)
for tag in tags:
meta_chips.controls.append(
ft.Container(
content=ft.Text(f"#{tag['name']}", size=12, color=d.PRIMARY),
bgcolor=ft.colors.with_opacity(0.1, d.PRIMARY),
border_radius=4,
padding=ft.padding.symmetric(horizontal=10, vertical=4),
)
)
controls = [
d.headline(a["title"], size=30, font=d.FONT_DISPLAY),
ft.Row(
[
meta_chips,
ft.Row([
ft.Text(pub_date, size=12, color=d.TEXT_SECONDARY),
ft.Row([
ft.Icon(ft.icons.REMOVE_RED_EYE_OUTLINED, size=14, color=d.TEXT_SECONDARY),
ft.Text(str(a.get("view_count", 0)), size=12, color=d.TEXT_SECONDARY),
], spacing=4),
], spacing=16),
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
wrap=True,
),
]
if a.get("cover_url"):
controls.append(
ft.Container(
content=ft.Image(
src=a["cover_url"],
width=float("inf"),
height=400,
fit=ft.ImageFit.COVER,
border_radius=12,
),
border_radius=12,
clip_behavior=ft.ClipBehavior.HARD_EDGE,
)
)
if a.get("excerpt"):
controls.append(
ft.Container(
content=ft.Text(
a["excerpt"],
size=16,
color=d.TEXT_SECONDARY,
italic=True,
),
border=ft.Border(left=ft.BorderSide(4, d.PRIMARY)),
padding=ft.padding.only(left=16, top=8, bottom=8),
)
)
controls.append(d.divider())
controls.append(
ft.Markdown(
value=a.get("content", ""),
selectable=True,
extension_set=ft.MarkdownExtensionSet.GITHUB_WEB,
on_tap_link=lambda e: self.page.launch_url(e.data),
auto_follow_links=False,
)
)
controls.append(ft.Divider(height=32, color="transparent"))
controls.append(
ft.TextButton(
"← Назад к новостям",
icon=ft.icons.ARROW_BACK,
style=ft.ButtonStyle(color=d.PRIMARY),
on_click=lambda e: self.page.go("/"),
)
)
self._content_col.controls = [
ft.Container(
content=ft.Column(controls, spacing=16),
bgcolor=d.SURFACE,
border_radius=12,
padding=32,
border=ft.border.all(1, d.DIVIDER),
)
]
self.page.update()