123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- 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'<span class="tag">{link}</span>'
- def _href(self, tag: str, init: List[str]) -> str:
- link = "/".join(init + [tag])
- return f'<a href="/u/{self.user}/t/{link}">{tag}</a>'
- 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
|