test ferst
This commit is contained in:
189
web/views/news_detail.py
Normal file
189
web/views/news_detail.py
Normal 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()
|
||||
Reference in New Issue
Block a user