Browse Source

Try reworking the render function to always take a View

Getty Ritter 4 years ago
parent
commit
f0e4bf0982
4 changed files with 79 additions and 43 deletions
  1. 33 28
      lc/app.py
  2. 12 11
      lc/model.py
  3. 30 1
      lc/view.py
  4. 4 3
      lc/web.py

+ 33 - 28
lc/app.py

@@ -7,6 +7,7 @@ import lc.config as c
 import lc.error as e
 import lc.model as m
 import lc.request as r
+import lc.view as v
 from lc.web import Endpoint, endpoint, render
 
 app = c.app
@@ -15,16 +16,14 @@ app = c.app
 @endpoint("/")
 class Index(Endpoint):
     def html(self):
-        return render(
-            "main",
+        return render("main", v.Page(
             title="main",
-            content=render(
-                "message",
+            content=render("message", v.Message(
                 title="Lament Configuration",
                 message="Bookmark organizing for real pinheads.",
-            ),
+            )),
             user=self.user,
-        )
+        ))
 
 
 @endpoint("/auth")
@@ -38,7 +37,11 @@ class Auth(Endpoint):
 @endpoint("/login")
 class Login(Endpoint):
     def html(self):
-        return render("main", title="login", content=render("login"), user=self.user)
+        return render("main", v.Page(
+            title="login",
+            content=render("login"),
+            user=self.user,
+        ))
 
 
 @endpoint("/logout")
@@ -64,12 +67,11 @@ class CreateUser(Endpoint):
         if not token:
             raise e.LCRedirect("/")
 
-        return render(
-            "main",
+        return render("main", v.Page(
             title="add user",
             user=self.user,
-            content=render("add_user", token=token),
-        )
+            content=render("add_user"),
+        ))
 
     def api_post(self):
         token = flask.request.args["token"]
@@ -85,12 +87,11 @@ class GetUser(Endpoint):
         u = m.User.by_slug(slug)
         pg = int(flask.request.args.get("page", 1))
         links, pages = u.get_links(as_user=self.user, page=pg)
-        return render(
-            "main",
+        return render("main", v.Page(
             title=f"user {u.name}",
-            content=render("linklist", links=links, pages=pages),
+            content=render("linklist", v.LinkList(links=links, pages=pages)),
             user=self.user,
-        )
+        ))
 
     def api_get(self, slug: str):
         return m.User.by_slug(slug).to_dict()
@@ -100,12 +101,11 @@ class GetUser(Endpoint):
 class UserConfig(Endpoint):
     def html(self, user: str):
         u = self.require_authentication(user)
-        return render(
-            "main",
+        return render("main", v.Page(
             title="configuration",
-            content=render("config", **u.get_config()),
+            content=render("config", u.get_config()),
             user=self.user,
-        )
+        ))
 
 
 @endpoint("/u/<string:user>/invite")
@@ -119,7 +119,11 @@ class CreateInvite(Endpoint):
 @endpoint("/u/<string:user>/l")
 class CreateLink(Endpoint):
     def html(self, user: str):
-        return render("main", title="login", content=render("add_link"), user=self.user)
+        return render("main", v.Page(
+            title="login",
+            content=render("add_link"),
+            user=self.user,
+        ))
 
     def api_post(self, user: str):
         u = self.require_authentication(user)
@@ -142,12 +146,11 @@ class GetLink(Endpoint):
 
     def html(self, user: str, link: str):
         l = m.User.by_slug(user).get_link(int(link))
-        return render(
-            "main",
+        return render("main", v.Page(
             title=f"link {l.name}",
-            content=render("linklist", links=[l]),
+            content=render("linklist", v.LinkList([l])),
             user=self.user,
-        )
+        ))
 
 
 @endpoint("/u/<string:slug>/l/<string:link>/edit")
@@ -167,9 +170,11 @@ class GetTaggedLinks(Endpoint):
         pg = int(flask.request.args.get("page", 0))
         t = u.get_tag(tag)
         links, pages = t.get_links(as_user=self.user, page=pg)
-        return render(
-            "main",
+        return render("main", v.Page(
             title=f"tag {tag}",
-            content=render("linklist", links=links, pages=pages),
+            content=render("linklist", v.LinkList(
+                links=links,
+                pages=pages,
+            )),
             user=self.user,
-        )
+        ))

+ 12 - 11
lc/model.py

@@ -8,6 +8,7 @@ from typing import List, Optional, Tuple
 import lc.config as c
 import lc.error as e
 import lc.request as r
+import lc.view as v
 
 
 class Model(peewee.Model):
@@ -109,22 +110,22 @@ class User(Model):
     def to_dict(self) -> dict:
         return {"id": self.id, "name": self.name}
 
-    def get_config(self) -> dict:
+    def get_config(self) -> v.Config:
         admin_pane = None
         if self.is_admin:
             user_invites = [
-                {
-                    "claimed": ui.claimed_by is not None,
-                    "claimant": ui.claimed_by and ui.claimed_by.name,
-                    "token": ui.token,
-                }
+                v.UserInvite(
+                    claimed=ui.claimed_by is not None,
+                    claimant=ui.claimed_by and ui.claimed_by.name,
+                    token=ui.token,
+                )
                 for ui in UserInvite.select().where(UserInvite.created_by == self)
             ]
-            admin_pane = {"invites": user_invites}
-        return {
-            "username": self.name,
-            "admin_pane": admin_pane,
-        }
+            admin_pane = v.AdminPane(invites=user_invites)
+        return v.Config(
+            username=self.name,
+            admin_pane=admin_pane,
+        )
 
 
 class Link(Model):

+ 30 - 1
lc/view.py

@@ -1,8 +1,27 @@
 from dataclasses import dataclass
-from typing import Optional, List
+from typing import Any, Optional, List
 
 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.per_page) + 1,)
+
 @dataclass
 class UserInvite(View):
     claimed: bool
@@ -18,6 +37,16 @@ class Config(View):
     username: str
     admin_pane: Optional[AdminPane]
 
+@dataclass
+class LinkList(View):
+    links: List[Any]
+    pages: Optional[Pagination] = None
+
+@dataclass
+class Message(View):
+    title: str
+    message: str
+
 @dataclass
 class Page(View):
     title: str

+ 4 - 3
lc/web.py

@@ -1,12 +1,13 @@
 from dataclasses import dataclass
 import flask
 import pystache
-from typing import TypeVar, Type
+from typing import Optional, TypeVar, Type
 
 import lc.config as c
 import lc.error as e
 import lc.model as m
 import lc.request as r
+import lc.view as v
 
 
 T = TypeVar("T", bound=r.Request)
@@ -166,8 +167,8 @@ def endpoint(route: str):
 LOADER = pystache.loader.Loader(extension="mustache", search_dirs=["templates"])
 
 
-def render(name: str, **kwargs) -> str:
+def render(name: str, data: Optional[v.View] = None) -> str:
     """Load and use a Mustache template from the project root"""
     template = LOADER.load_name(name)
     renderer = pystache.Renderer(missing_tags="strict", search_dirs=["templates"])
-    return renderer.render(template, kwargs)
+    return renderer.render(template, data or {})