changeset 1548:66aa6e140ebb

browser: make `jid_search` more generic: rel 423
author Goffi <goffi@goffi.org>
date Wed, 09 Aug 2023 00:22:16 +0200
parents 383e1fee29f6
children e47c24204449
files libervia/web/pages/_browser/jid_search.py libervia/web/pages/chat/select/_browser/__init__.py
diffstat 2 files changed, 90 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/libervia/web/pages/_browser/jid_search.py	Thu Jul 06 12:12:07 2023 +0200
+++ b/libervia/web/pages/_browser/jid_search.py	Wed Aug 09 00:22:16 2023 +0200
@@ -1,34 +1,101 @@
+import json
+from urllib.parse import quote, urljoin
+
 from bridge import AsyncBridge as Bridge
 from browser import aio, console as log, window
 from cache import cache
-import json
+from template import Template
 
 log.warning = log.warn
 profile = window.profile or ""
 bridge = Bridge()
 
-
 class JidSearch:
 
-    def __init__(self, search_elt, callback, empty_cb=None):
+    def __init__(
+        self,
+        search_elt,
+        container_elt=None,
+        filter_cb=None,
+        empty_cb=None,
+        get_url=None,
+        click_cb=None
+    ):
+        """Initialize the JidSearch instance
+
+        @param search_elt: The HTML <input> element for search
+        @param container_elt: The HTML container to display the search results
+        @param filter_cb: The callback to filter the search results
+        @param empty_cb: The callback when the search box is empty
+        @param get_url: The function to get URL for each entity in the search result
+        @param click_cb: The function to handle the click event on each entity in the
+            search result
+        """
+        self.search_item_tpl = Template("components/search_item.html")
         self.search_elt = search_elt
         self.search_elt.bind("input", self.on_search_input)
         self.last_query = None
         self.current_query = None
-        self.callback = callback
-        self.empty_cb = empty_cb
+        self.container_elt = container_elt
+
+        if click_cb is not None and get_url is None:
+            self.get_url = lambda _: "#"
+        else:
+            self.get_url = get_url if get_url is not None else self.default_get_url
+        self.click_cb = click_cb
+
+        if filter_cb is None:
+            if container_elt is None:
+                raise ValueError("container_elt must be set if filter_cb is not set")
+            filter_cb = self.show_items
+        self.filter_cb = filter_cb
+
+        self.empty_cb = empty_cb or self.on_empty_search
+
         current_search = search_elt.value.strip() or None
         if current_search is not None:
             aio.run(self.perform_search(current_search))
 
+    def default_get_url(self, item):
+        """Default method to get the URL for a given entity
+
+        @param item: The item (entity) for which the URL is required
+        """
+        return urljoin(f"{window.location.href}/", quote(item["entity"]))
+
+    def show_items(self, items):
+        """Display the search items in the specified container
+
+        @param items: The list of search items to be displayed
+        """
+        assert self.container_elt is not None
+        self.container_elt.clear()
+        for item in items:
+            search_item_elt = self.search_item_tpl.get_elt({
+                "url": self.get_url(item),
+                "item": item,
+                "identities": cache.identities
+            })
+            if self.click_cb is not None:
+                search_item_elt.bind('click', lambda evt, item=item: self.click_cb(item))
+            self.container_elt <= search_item_elt
+
     def on_search_input(self, evt):
+        """Handle the 'input' event for the search element
+
+        @param evt: The event object
+        """
         search_text = evt.target.value.strip()
-        if not search_text and self.empty_cb is not None:
+        if not search_text:
             self.empty_cb()
         elif len(search_text) > 2:
             aio.run(self.perform_search(search_text))
 
     async def perform_search(self, query):
+        """Perform the search operation for a given query
+
+        @param query: The search query
+        """
         if self.current_query is None:
             log.debug(f"performing search: {query=}")
             self.current_query = query
@@ -41,4 +108,16 @@
             if current_query != query:
                 await self.perform_search(current_query)
                 return
-            self.callback(jid_items)
+            self.filter_cb(jid_items)
+
+    def on_empty_search(self):
+        """Handle the situation when the search box is empty"""
+        assert self.container_elt is not None
+        items = [
+            {
+                "entity": jid_,
+                "groups": data["groups"]
+            }
+            for jid_, data in cache.roster.items()
+        ]
+        self.show_items(items)
--- a/libervia/web/pages/chat/select/_browser/__init__.py	Thu Jul 06 12:12:07 2023 +0200
+++ b/libervia/web/pages/chat/select/_browser/__init__.py	Wed Aug 09 00:22:16 2023 +0200
@@ -1,51 +1,13 @@
+
 from bridge import AsyncBridge as Bridge
-from browser import aio, bind, console as log, document, window
-from urllib.parse import urljoin, quote
+from browser import console as log, document, window
+from cache import cache
 from jid_search import JidSearch
-from template import Template
-from cache import cache
-from pprint import pp
 
 log.warning = log.warn
-profile = window.profile or ""
-bridge = Bridge()
 
 
-class ChatSelect:
-
-    def __init__(self):
-        self.search_item_tpl = Template("chat/search_item.html")
-        self.chat_items_elt = document["chat_items"]
-
-    def show_items(self, items) -> None:
-        for item in items:
-            search_item_elt = self.search_item_tpl.get_elt({
-                "url": urljoin(f"{window.location.href}/", quote(item["entity"])),
-                "item": item,
-                "identities": cache.identities
-            })
-            self.chat_items_elt <= search_item_elt
-
-    def on_empty_search(self):
-        items = [
-            {
-                "entity": jid_,
-                "groups": data["groups"]
-            }
-            for jid_, data in cache.roster.items()
-        ]
-        self.chat_items_elt.clear()
-        self.show_items(items)
-
-    def on_search_filter(self, search_items):
-        self.chat_items_elt.clear()
-        pp(search_items)
-        self.show_items(search_items)
-
-
-chat_select = ChatSelect()
 jid_search = JidSearch(
     document["search"],
-    chat_select.on_search_filter,
-    chat_select.on_empty_search
+    document["chat_items"],
 )