Coverage for src / lexigram / admin / controllers / command_palette.py: 50%
28 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
1"""Controller for the command palette endpoint."""
3from __future__ import annotations
5from typing import Any
7from starlette.requests import Request
8from starlette.responses import JSONResponse
10from lexigram.admin.services.search_service import SearchService
11from lexigram.di.decorators import inject
12from lexigram.logging import get_logger
14logger = get_logger(__name__)
16_STATIC_COMMANDS: list[dict[str, Any]] = [
17 {"label": "Go to Dashboard", "href": "/admin/", "icon": "home", "shortcut": "G D"},
18 {
19 "label": "Manage Users",
20 "href": "/admin/users",
21 "icon": "users",
22 "shortcut": "G U",
23 },
24 {
25 "label": "Toggle Dark Mode",
26 "action": "darkMode = !darkMode",
27 "icon": "moon",
28 "shortcut": "T D",
29 },
30 {"label": "Settings", "href": "#", "icon": "settings", "shortcut": ","},
31]
33_MIN_QUERY_LENGTH = 2
36@inject
37class CommandPaletteController:
38 """Handles the command palette search endpoint.
40 Returns JSON commands that the frontend merges with static commands.
41 """
43 def __init__(self, search_service: SearchService) -> None:
44 self._search_service = search_service
46 async def search(self, request: Request) -> JSONResponse:
47 """Handle GET /admin/command-palette?q=..."""
48 query = (request.query_params.get("q") or "").strip()
49 commands: list[dict[str, Any]] = []
51 # Filter static commands by query
52 for cmd in _STATIC_COMMANDS:
53 if not query or query.lower() in cmd["label"].lower():
54 commands.append(cmd)
56 # Dynamic search results from backend
57 if len(query) >= _MIN_QUERY_LENGTH:
58 try:
59 results = await self._search_service.search(query)
60 for r in results.results:
61 commands.append(
62 {
63 "label": f"{r.resource_label}: {r.title}",
64 "href": r.url,
65 "icon": "search",
66 "subtitle": r.subtitle,
67 }
68 )
69 except Exception:
70 logger.exception("Command palette search failed for query=%s", query)
72 return JSONResponse(commands)