Просмотр исходного кода

Implement an article "browser" that navigates among sites and dates

jherve 1 год назад
Родитель
Сommit
d3eadaf4b7

+ 37 - 0
src/de_quoi_parle_le_monde/storage.py

@@ -358,6 +358,43 @@ class Storage:
                 for a in main_articles
             ]
 
+    async def list_neighbouring_main_articles(
+        self,
+        site_id: int,
+        featured_article_snapshot_id: int | None = None,
+        max_interval_s: int = 3600 * 12,
+    ):
+        async with self.conn as conn:
+            main_articles = await conn.execute_fetchall(
+                """
+                SELECT mav.*, unixepoch(mav.timestamp_virtual) - unixepoch((
+                    SELECT timestamp_virtual
+                    FROM main_articles_view mav
+                    WHERE site_id = ? AND featured_article_snapshot_id = ?
+                )) AS time_diff
+                FROM main_articles_view mav
+                WHERE
+                    (site_id = ? AND abs(time_diff) < ?)
+                    OR time_diff = 0
+                ORDER BY abs(time_diff) ASC
+                """,
+                [site_id, featured_article_snapshot_id, site_id, max_interval_s],
+            )
+
+            return [
+                {
+                    "site_id": a[0],
+                    "snapshot_id": a[1],
+                    "featured_article_snapshot_id": a[2],
+                    "original_url": a[3],
+                    "timestamp_virtual": a[4],
+                    "title": a[5],
+                    "url": a[6],
+                    "time_diff": a[7],
+                }
+                for a in main_articles
+            ]
+
     async def select_from(self, table):
         async with self.conn as conn:
             return await conn.execute_fetchall(

+ 54 - 0
src/de_quoi_parle_le_monde/web.py

@@ -24,6 +24,60 @@ async def index(request: Request, storage: Storage = Depends(get_db)):
     )
 
 
+@app.get("/sites/{id}/main_article/{snapshot_id}", response_class=HTMLResponse)
+async def site_main_article_snapshot(
+    request: Request,
+    id: int,
+    snapshot_id: int,
+    storage: Storage = Depends(get_db),
+):
+    def get_article_sibling(after_before_articles, cond_fun):
+        return min(
+            [a for a in after_before_articles if cond_fun(a)],
+            key=lambda a: abs(a["time_diff"]),
+        )
+
+    main_articles = await storage.list_neighbouring_main_articles(id, snapshot_id)
+    [focused_article] = [
+        a
+        for a in main_articles
+        if a["site_id"] == id and a["featured_article_snapshot_id"] == snapshot_id
+    ]
+    simultaneous_articles = [
+        a for a in main_articles if a["site_id"] != id and a["time_diff"] == 0
+    ]
+    same_site_articles = [
+        a for a in main_articles if a["site_id"] == id and a["time_diff"] != 0
+    ]
+
+    return templates.TemplateResponse(
+        request=request,
+        name="site_main_article_detail.html",
+        context={
+            "site_id": id,
+            "focused": focused_article,
+            "simultaneous_up": [
+                a
+                for a in simultaneous_articles
+                if a["site_id"] > focused_article["site_id"]
+            ],
+            "simultaneous_down": [
+                a
+                for a in simultaneous_articles
+                if a["site_id"] < focused_article["site_id"]
+            ],
+            "after": get_article_sibling(
+                same_site_articles,
+                lambda a: a["time_diff"] > 0,
+            ),
+            "before": get_article_sibling(
+                same_site_articles,
+                lambda a: a["time_diff"] < 0,
+            ),
+        },
+    )
+
+
 @app.get("/sites/{id}/main_article", response_class=HTMLResponse)
 async def site_main_article(
     request: Request,

+ 52 - 0
templates/site_main_article_detail.html

@@ -0,0 +1,52 @@
+<html>
+<head>
+    <title>Hello</title>
+    <link href="{{ url_for('static', path='/style.css') }}" rel="stylesheet">
+</head>
+<body>
+    <a href="{{ url_for('index') }}">Homepage</a>
+    <h1>Site {{ site_id }}</h1>
+
+    {% macro article(a) -%}
+        <a href="{{ url_for('site_main_article_snapshot', id=a['site_id'], snapshot_id=a['featured_article_snapshot_id']) }}">
+            {{ a["title"] }}
+        </a>
+    {%- endmacro %}
+
+    <div id="article_browser">
+        <div class="simultaneous_up">
+            Up
+            <ul>
+                {% for a in simultaneous_up %}
+                    <li>{{ article(a) }}</li>
+                {% endfor %}
+            </ul>
+        </div>
+        <div class="focused">{{ focused["title"] }}</div>
+        {% if after %}
+            <div class="after">
+                After
+                <ul>
+                    <li>{{ article(after) }} @ {{ after["time_diff"] }}</li>
+                </ul>
+            </div>
+        {% endif %}
+        {% if before %}
+            <div class="before">
+                Before
+                <ul>
+                    <li>{{ article(before) }} @ {{ before["time_diff"] }}</li>
+                </ul>
+            </div>
+        {% endif %}
+        <div class="simultaneous_down">
+            Down
+            <ul>
+                {% for a in simultaneous_down %}
+                    <li>{{ article(a) }}</li>
+                {% endfor %}
+            </ul>
+        </div>
+    </div>
+</body>
+</html>