diff libervia/web/pages/forums/view/page_meta.py @ 1642:c03297bb8d19

server, browser (forums): Redesign of the forum feature: Forum has been fully redesigned, it now uses pubsub relationships and pubsub extended discovery to handle the hierarchy. Categories lead to topics (which are the name of the items of a blog-like nodes). Topics have comment nodes which are used to show the topic messages. Subscription state is retrieve when a thread is shown, and can be changed easily with as ingle button click. Quill editor is used, and is extended with Quill-Mention to easily send a mention to an XMPP entity. Attachments and tags are handled with buttons added to Quill editor. Search in a thread is using Pubsub MAM, is the same way as for blogs. rel 463
author Goffi <goffi@goffi.org>
date Sat, 06 Sep 2025 16:30:46 +0200
parents 301fe2f1a34a
children
line wrap: on
line diff
--- a/libervia/web/pages/forums/view/page_meta.py	Sat Sep 06 12:12:42 2025 +0200
+++ b/libervia/web/pages/forums/view/page_meta.py	Sat Sep 06 16:30:46 2025 +0200
@@ -10,22 +10,104 @@
 
 name = "forum_view"
 label = D_("View")
-access = C.PAGES_ACCESS_PUBLIC
-template = "forum/view.html"
+access = C.PAGES_ACCESS_PROFILE
+template = "forum/view_messages.html"
 
 
 def parse_url(self, request):
-    self.get_path_args(request, ["service", "node"], 2, service="jid")
+    self.get_path_args(request, ["service", "node", "item"], 3, service="jid")
+
+
+def add_breadcrumb(self, request, breadcrumbs):
+    return None
 
 
 async def prepare_render(self, request):
+    profile = self.get_profile(request) or C.SERVICE_PROFILE
     data = self.get_r_data(request)
-    data["show_comments"] = False
-    blog_page = self.get_page_by_name("blog_view")
-    request.args[b"before"] = [b""]
-    request.args[b"reverse"] = [b"1"]
-    await blog_page.prepare_render(self, request)
-    request.template_data["login_url"] = self.get_page_redirect_url(request)
+    parent_service, parent_node, parent_item_id = (
+        data["service"],
+        data["node"],
+        data["item"],
+    )
+    parent_item_data = data_format.deserialise(
+        await self.host.bridge_call(
+            "mb_get",
+            parent_service.userhost(),
+            parent_node,
+            C.NO_LIMIT,
+            [parent_item_id],
+            data_format.serialise({}),
+            profile,
+        )
+    )
+    parent_item = parent_item_data["items"][0]
+    try:
+        service_s = parent_item["comments"][0]["service"]
+        node = parent_item["comments"][0]["node"]
+    except (KeyError, IndexError) as e:
+        log.warning(f"No comment node found {e}:\n{parent_item=}")
+        self.page_error(request, C.HTTP_SERVICE_UNAVAILABLE)
+        return
+
+    page_max = data.get("page_max", 20)
+    extra = self.get_pubsub_extra(request, page_max=page_max)
+    self.handle_search(request, extra)
+    if not self.use_cache(request):
+        extra[C.KEY_USE_CACHE] = False
+    blog_data = data_format.deserialise(
+        await self.host.bridge_call(
+            "mb_get",
+            service_s,
+            node,
+            C.NO_LIMIT,
+            [],
+            data_format.serialise(extra),
+            profile,
+        )
+    )
+    for parent_item in blog_data["items"]:
+        try:
+            comments_service = parent_item["comments"][0]["service"]
+            comments_node = parent_item["comments"][0]["node"]
+        except (KeyError, IndexError):
+            log.warning(f"Can't get comments node for item: {parent_item}")
+            continue
+        else:
+            parent_item["http_url"] = self.get_page_by_name("forum_view").get_url(
+                comments_service, comments_node
+            )
+    self.set_pagination(request, blog_data)
+    await self.fill_missing_identities(
+        request, [i["author_jid"] for i in blog_data["items"]]
+    )
+
+    # We check if we are subscribed to the service.
+    try:
+        subscriptions = data_format.deserialise(
+            await self.host.bridge_call(
+                "ps_subscriptions_get",
+                service_s,
+                node,
+                profile,
+            )
+        )
+    except Exception as e:
+        log.warning("Can't retrieve subscriptions, assuming that we are not subscribed.")
+        subscribed = False
+    else:
+        subscribed = any(s.get("state") == "subscribed" for s in subscriptions)
+
+    request.template_data.update(
+        {
+            "topic_title": parent_item["title"],
+            "service": service_s,
+            "node": node,
+            "blog_items": blog_data,
+            "subscribed": subscribed,
+        }
+    )
+    self.expose_to_scripts(request, node=node, service=service_s, subscribed=subscribed)
 
 
 async def on_data_post(self, request):
@@ -41,7 +123,8 @@
         mb_data = {"service": service, "node": node, "content_rich": body}
         try:
             await self.host.bridge_call(
-                "mb_send", data_format.serialise(mb_data), profile)
+                "mb_send", data_format.serialise(mb_data), profile
+            )
         except Exception as e:
             if "forbidden" in str(e):
                 self.page_error(request, 401)