from dataclasses import dataclass from datetime import datetime from typing import Any, Optional, List import lc.config as c class View: pass @dataclass class Pagination(View): current: int last: int def previous(self) -> Optional[dict]: if self.current > 1: return {"page": self.current - 1} return None def next(self) -> Optional[dict]: if self.current < self.last: return {"page": self.current + 1} return None @classmethod def from_total(cls, current, total) -> "Pagination": return cls( current=current, last=((total - 1) // c.app.per_page) + 1, ) @dataclass class UserInvite(View): claimed: bool claimant: str token: str @dataclass class AddUser(View): token: str @dataclass class AdminPane(View): invites: List[UserInvite] @dataclass class Config(View): username: str admin_pane: Optional[AdminPane] msg: Optional[int] = None def bookmarklet_link(self): return ( "javascript:(function(){window.open(`" + c.app.config.app_path + "/u/" + self.username + "/l?name=${document.title}&url=${document.URL}`);})();" ) def message(self) -> Optional[str]: if self.msg == 1: return "Password changed." elif self.msg == 2: return "Mismatched new passwords; please try again." elif self.msg == 3: return "Incorrect old password; please try again." return None @dataclass class Tag(View): url: str name: str @dataclass class HierTagList: user: str tags: List[Tag] def render(self) -> str: groups: dict = {} for tag in (t.name for t in self.tags): if "/" not in tag: groups[tag] = groups.get(tag, {}) else: chunks = tag.split("/") focus = groups[chunks[0]] = groups.get(chunks[0], {}) for chunk in chunks[1:]: focus[chunk] = focus = focus.get(chunk, {}) return "\n".join(self.render_html(k, v) for k, v in groups.items()) def render_html(self, prefix: str, values: dict) -> str: link = self._render_html(prefix, values, []) return f'{link}' def _href(self, tag: str, init: List[str]) -> str: link = "/".join(init + [tag]) return f'{tag}' def _render_html(self, prefix: str, values: dict, init: List[str]) -> str: if not values: return self._href(prefix, init) if len(values) == 1: k, v = values.popitem() rest = self._render_html(k, v, init + [prefix]) prefix_href = self._href(prefix, init) return f"{prefix_href}/{rest}" else: fragments = [] for k, v in values.items(): fragments.append(self._render_html(k, v, init + [prefix])) items = ", ".join(fragments) prefix_href = self._href(prefix, init) return f"{prefix_href}/{{{items}}}" @dataclass class Link(View): id: int url: str name: str description: str private: bool tags: List[Tag] created: datetime is_mine: bool link_url: str user: str def hier_tags(self) -> str: return HierTagList(user=self.user, tags=self.tags).render() @dataclass class LinkList(View): links: List[Any] tags: List[Tag] user: str pages: Optional[Pagination] = None def hier_tags(self) -> str: return HierTagList(user=self.user, tags=self.tags).render() @dataclass class SingleLink(View): link: Any all_tags: List[Tag] @dataclass class Message(View): title: str message: str @dataclass class AddLinkDefaults(View): user: str all_tags: List[Tag] url: Optional[str] = None name: Optional[str] = None def post_url(self) -> str: return f"/u/{self.user}/l" @dataclass class Page(View): title: str content: str user: Optional[Any] @dataclass class Error(View): code: int message: str