Mercurial > libervia-web
comparison libervia/web/pages/_browser/jid_search.py @ 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 | 7f3f5ae7d65a |
children | e47c24204449 |
comparison
equal
deleted
inserted
replaced
1547:383e1fee29f6 | 1548:66aa6e140ebb |
---|---|
1 import json | |
2 from urllib.parse import quote, urljoin | |
3 | |
1 from bridge import AsyncBridge as Bridge | 4 from bridge import AsyncBridge as Bridge |
2 from browser import aio, console as log, window | 5 from browser import aio, console as log, window |
3 from cache import cache | 6 from cache import cache |
4 import json | 7 from template import Template |
5 | 8 |
6 log.warning = log.warn | 9 log.warning = log.warn |
7 profile = window.profile or "" | 10 profile = window.profile or "" |
8 bridge = Bridge() | 11 bridge = Bridge() |
9 | 12 |
10 | |
11 class JidSearch: | 13 class JidSearch: |
12 | 14 |
13 def __init__(self, search_elt, callback, empty_cb=None): | 15 def __init__( |
16 self, | |
17 search_elt, | |
18 container_elt=None, | |
19 filter_cb=None, | |
20 empty_cb=None, | |
21 get_url=None, | |
22 click_cb=None | |
23 ): | |
24 """Initialize the JidSearch instance | |
25 | |
26 @param search_elt: The HTML <input> element for search | |
27 @param container_elt: The HTML container to display the search results | |
28 @param filter_cb: The callback to filter the search results | |
29 @param empty_cb: The callback when the search box is empty | |
30 @param get_url: The function to get URL for each entity in the search result | |
31 @param click_cb: The function to handle the click event on each entity in the | |
32 search result | |
33 """ | |
34 self.search_item_tpl = Template("components/search_item.html") | |
14 self.search_elt = search_elt | 35 self.search_elt = search_elt |
15 self.search_elt.bind("input", self.on_search_input) | 36 self.search_elt.bind("input", self.on_search_input) |
16 self.last_query = None | 37 self.last_query = None |
17 self.current_query = None | 38 self.current_query = None |
18 self.callback = callback | 39 self.container_elt = container_elt |
19 self.empty_cb = empty_cb | 40 |
41 if click_cb is not None and get_url is None: | |
42 self.get_url = lambda _: "#" | |
43 else: | |
44 self.get_url = get_url if get_url is not None else self.default_get_url | |
45 self.click_cb = click_cb | |
46 | |
47 if filter_cb is None: | |
48 if container_elt is None: | |
49 raise ValueError("container_elt must be set if filter_cb is not set") | |
50 filter_cb = self.show_items | |
51 self.filter_cb = filter_cb | |
52 | |
53 self.empty_cb = empty_cb or self.on_empty_search | |
54 | |
20 current_search = search_elt.value.strip() or None | 55 current_search = search_elt.value.strip() or None |
21 if current_search is not None: | 56 if current_search is not None: |
22 aio.run(self.perform_search(current_search)) | 57 aio.run(self.perform_search(current_search)) |
23 | 58 |
59 def default_get_url(self, item): | |
60 """Default method to get the URL for a given entity | |
61 | |
62 @param item: The item (entity) for which the URL is required | |
63 """ | |
64 return urljoin(f"{window.location.href}/", quote(item["entity"])) | |
65 | |
66 def show_items(self, items): | |
67 """Display the search items in the specified container | |
68 | |
69 @param items: The list of search items to be displayed | |
70 """ | |
71 assert self.container_elt is not None | |
72 self.container_elt.clear() | |
73 for item in items: | |
74 search_item_elt = self.search_item_tpl.get_elt({ | |
75 "url": self.get_url(item), | |
76 "item": item, | |
77 "identities": cache.identities | |
78 }) | |
79 if self.click_cb is not None: | |
80 search_item_elt.bind('click', lambda evt, item=item: self.click_cb(item)) | |
81 self.container_elt <= search_item_elt | |
82 | |
24 def on_search_input(self, evt): | 83 def on_search_input(self, evt): |
84 """Handle the 'input' event for the search element | |
85 | |
86 @param evt: The event object | |
87 """ | |
25 search_text = evt.target.value.strip() | 88 search_text = evt.target.value.strip() |
26 if not search_text and self.empty_cb is not None: | 89 if not search_text: |
27 self.empty_cb() | 90 self.empty_cb() |
28 elif len(search_text) > 2: | 91 elif len(search_text) > 2: |
29 aio.run(self.perform_search(search_text)) | 92 aio.run(self.perform_search(search_text)) |
30 | 93 |
31 async def perform_search(self, query): | 94 async def perform_search(self, query): |
95 """Perform the search operation for a given query | |
96 | |
97 @param query: The search query | |
98 """ | |
32 if self.current_query is None: | 99 if self.current_query is None: |
33 log.debug(f"performing search: {query=}") | 100 log.debug(f"performing search: {query=}") |
34 self.current_query = query | 101 self.current_query = query |
35 jid_items = json.loads(await bridge.jid_search(query, "")) | 102 jid_items = json.loads(await bridge.jid_search(query, "")) |
36 await cache.fill_identities(i["entity"] for i in jid_items) | 103 await cache.fill_identities(i["entity"] for i in jid_items) |
39 self.current_query = None | 106 self.current_query = None |
40 current_query = self.search_elt.value.strip() | 107 current_query = self.search_elt.value.strip() |
41 if current_query != query: | 108 if current_query != query: |
42 await self.perform_search(current_query) | 109 await self.perform_search(current_query) |
43 return | 110 return |
44 self.callback(jid_items) | 111 self.filter_cb(jid_items) |
112 | |
113 def on_empty_search(self): | |
114 """Handle the situation when the search box is empty""" | |
115 assert self.container_elt is not None | |
116 items = [ | |
117 { | |
118 "entity": jid_, | |
119 "groups": data["groups"] | |
120 } | |
121 for jid_, data in cache.roster.items() | |
122 ] | |
123 self.show_items(items) |