154 lines
4.7 KiB
Python
154 lines
4.7 KiB
Python
from textual.screen import Screen
|
|
from textual.widgets import Input, Select, LoadingIndicator, Static
|
|
from textual.containers import HorizontalGroup, ScrollableContainer
|
|
from textual.app import ComposeResult
|
|
from textual import work
|
|
|
|
from widgets import Navbar
|
|
from screens.repo_view_screen import RepoViewScreen
|
|
|
|
from human_readable import time_delta
|
|
from datetime import datetime, timedelta
|
|
|
|
import requests
|
|
|
|
|
|
class SearchResult(HorizontalGroup):
|
|
DEFAULT_CSS = """
|
|
SearchResult {
|
|
padding: 0 1;
|
|
margin: 0 1;
|
|
margin-top: 1;
|
|
border: tall $surface;
|
|
|
|
Static {
|
|
width: auto;
|
|
link-style: bold;
|
|
link-color: $primary;
|
|
}
|
|
}
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
repo_data: dict
|
|
):
|
|
super().__init__()
|
|
self.repo_data = repo_data
|
|
self.author = repo_data["owner"]
|
|
self.repo_name = repo_data["name"]
|
|
self.description = repo_data["description"]
|
|
self.is_fork = repo_data["fork"]
|
|
self.updated_at = datetime.fromisoformat(repo_data["updated_at"]).replace(tzinfo=None)
|
|
|
|
|
|
|
|
def compose(self) -> ComposeResult:
|
|
updated_string = time_delta(datetime.now() - self.updated_at)
|
|
yield Static(f"[@click='view_user({self.author["id"]})']{self.author["login"]}[/] / [@click='screen.view_repo(\"{self.author["login"]}\",\"{self.repo_name}\")']{self.repo_name}[/]{' [d]\[[cyan]fork[/]]' if self.is_fork else ''}\n{self.description}\n[d]Updated {updated_string} ago")
|
|
|
|
class SearchScreen(Screen):
|
|
DEFAULT_CSS = """
|
|
#search-box {
|
|
padding: 1;
|
|
padding-bottom: 0;
|
|
border-bottom: hkey $surface;
|
|
|
|
#query {
|
|
width: 1fr;
|
|
}
|
|
|
|
Select {
|
|
width: 25;
|
|
}
|
|
}
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.selects_changed = [] # just used to prevent some issues
|
|
|
|
def action_view_repo(self, author: str, repo_name: str):
|
|
self.app.switch_screen(RepoViewScreen(author, repo_name))
|
|
|
|
@work(exclusive=True)
|
|
async def action_search_query(self):
|
|
query_input = self.query_one("#query")
|
|
loading = self.query_one(LoadingIndicator)
|
|
results = self.query_one(ScrollableContainer)
|
|
|
|
loading.display = True
|
|
|
|
# get params we need to send
|
|
sort = self.query_one("#sort-select").value
|
|
order = self.query_one("#order-select").value
|
|
users_or_repos = self.query_one("#search-select").value
|
|
|
|
# send off a request
|
|
response = requests.get(
|
|
url=self.app.GITEA_HOST + "api/v1/repos/search",
|
|
params={
|
|
"q": query_input.value,
|
|
"limit": 20,
|
|
"sort": sort,
|
|
"order": order
|
|
}
|
|
)
|
|
|
|
loading.display = False
|
|
|
|
# error handling
|
|
if not response.ok:
|
|
self.notify(response.text, title="Error while getting search results:", severity="error")
|
|
return
|
|
|
|
# display results
|
|
results.remove_children(SearchResult)
|
|
to_mount = []
|
|
for result in response.json()["data"]:
|
|
to_mount.append(SearchResult(result))
|
|
results.mount_all(to_mount)
|
|
|
|
# self explanitory
|
|
query_input.clear()
|
|
query_input.focus()
|
|
|
|
def on_input_submitted(self, event: Input.Submitted):
|
|
if event.input.id == "query":
|
|
self.action_search_query()
|
|
|
|
def on_select_changed(self, event: Select.Changed):
|
|
if not event.select.id in self.selects_changed:
|
|
self.selects_changed.append(event.select.id)
|
|
return
|
|
|
|
self.action_search_query()
|
|
|
|
def on_mount(self):
|
|
self.action_search_query()
|
|
#self.query_one(LoadingIndicator).display = False
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield Navbar()
|
|
|
|
with HorizontalGroup(id="search-box"):
|
|
yield Input(placeholder="Search repos...", id="query")
|
|
yield Select([
|
|
("Alphabetical", "alpha"),
|
|
("Creation date", "created"),
|
|
("Last updated", "updated"),
|
|
("Size", "size"),
|
|
("ID", "id")
|
|
], id="sort-select", allow_blank=False, value="updated")
|
|
yield Select([
|
|
("Ascending", "asc"),
|
|
("Descending", "desc")
|
|
], id="order-select", allow_blank=False, value="desc")
|
|
yield Select.from_values([
|
|
"Repositories",
|
|
"Users",
|
|
], id="search-select", allow_blank=False, value="Repositories")
|
|
|
|
with ScrollableContainer(id="results"):
|
|
yield LoadingIndicator() |