Skip to content

Commit

Permalink
In-progress UI for updating settings
Browse files Browse the repository at this point in the history
  • Loading branch information
gizmo385 committed Sep 5, 2024
1 parent 0599365 commit fd6fff6
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 12 deletions.
10 changes: 5 additions & 5 deletions lazy_github/lib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import BaseModel

from lazy_github.lib.constants import CONFIG_FOLDER
from lazy_github.lib.constants import CONFIG_FOLDER, IssueOwnerFilter, IssueStateFilter

_CONFIG_FILE_LOCATION = CONFIG_FOLDER / "config.json"

Expand All @@ -21,15 +21,15 @@ class ApiConfig(BaseModel):
class PullRequestSettings(BaseModel):
"""Changes how PRs are retrieved from the Github API"""

state_filter: ISSUE_STATE_FILTER = "all"
owner_filter: ISSUE_OWNER_FILTER = "all"
state_filter: IssueStateFilter = IssueStateFilter.ALL
owner_filter: IssueOwnerFilter = IssueOwnerFilter.ALL


class IssueSettings(BaseModel):
"""Changes how issues are retrieved from the Github API"""

state_filter: ISSUE_STATE_FILTER = "all"
owner_filter: ISSUE_OWNER_FILTER = "all"
state_filter: IssueStateFilter = IssueStateFilter.ALL
owner_filter: IssueOwnerFilter = IssueOwnerFilter.ALL


class RepositorySettings(BaseModel):
Expand Down
12 changes: 12 additions & 0 deletions lazy_github/lib/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from enum import StrEnum
from pathlib import Path

# Content types
Expand Down Expand Up @@ -25,3 +26,14 @@ def favorite_string(favorite: bool) -> str:
def private_string(private: bool) -> str:
"""Helper function to return the right string to indicate if something is private"""
return IS_PRIVATE if private else IS_PUBLIC


class IssueStateFilter(StrEnum):
ALL = "all"
OPEN = "open"
CLOSED = "closed"


class IssueOwnerFilter(StrEnum):
MINE = "mine"
ALL = "all"
10 changes: 3 additions & 7 deletions lazy_github/lib/github/issues.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
from typing import Literal

from lazy_github.lib.github.client import GithubClient
from lazy_github.models.github import Issue, IssueComment, PartialPullRequest, Repository

IssueStateFilter = Literal["open"] | Literal["closed"] | Literal["all"]
IssueOwnerFilter = Literal["all"] | Literal["mine"]
from lazy_github.lib.constants import IssueStateFilter, IssueOwnerFilter


async def list_issues(
client: GithubClient, repo: Repository, state: IssueStateFilter, owner: IssueOwnerFilter
) -> list[Issue]:
"""Fetch issues (included pull requests) from the repo matching the state/owner filters"""
query_params = {"state": state}
if owner == "mine":
query_params = {"state": str(state).lower()}
if owner == IssueOwnerFilter.MINE:
user = await client.user()
query_params["creator"] = user.login

Expand Down
5 changes: 5 additions & 0 deletions lazy_github/ui/screens/primary.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from lazy_github.lib.github.issues import list_issues
from lazy_github.lib.github.pull_requests import get_full_pull_request
from lazy_github.lib.messages import IssuesAndPullRequestsFetched, IssueSelected, PullRequestSelected, RepoSelected
from lazy_github.ui.screens.settings import SettingsModal
from lazy_github.ui.widgets.actions import ActionsContainer
from lazy_github.ui.widgets.command_log import CommandLogSection
from lazy_github.ui.widgets.common import LazyGithubContainer
Expand Down Expand Up @@ -223,6 +224,7 @@ def commands(self) -> tuple[LazyGithubCommand, ...]:
partial(toggle_ui, "pull_requests"),
"Toggle showing or hiding repo pull requests",
),
LazyGithubCommand("Change Settings", self.screen.action_show_settings_modal, "Adjust LazyGithub settings"),
]
return tuple(_commands)

Expand Down Expand Up @@ -257,5 +259,8 @@ async def action_toggle_ui(self, ui_to_hide: str):
widget = self.query_one(f"#{ui_to_hide}", Widget)
widget.display = not widget.display

async def action_show_settings_modal(self) -> None:
self.app.push_screen(SettingsModal(self.client.config))

def on_repo_selected(self, message: RepoSelected) -> None:
self.query_one("#currently_selected_repo", CurrentlySelectedRepo).current_repo_name = message.repo.full_name
159 changes: 159 additions & 0 deletions lazy_github/ui/screens/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import enum
from typing import Any

from pydantic import BaseModel
from pydantic.fields import FieldInfo
from textual.app import ComposeResult, on
from textual.containers import Container, Horizontal, ScrollableContainer, Vertical
from textual.screen import ModalScreen
from textual.widget import Widget
from textual.widgets import Button, Input, Markdown, Rule, Select, Static, Switch

from lazy_github.lib.config import Config
from lazy_github.ui.widgets.command_log import log_event


def field_name_to_readable_name(name: str) -> str:
return name.replace("_", " ").title()


class FieldName(Static):
pass


class FieldSetting(Container):
DEFAULT_CSS = """
FieldSetting {
layout: grid;
grid-size: 2;
height: 3;
}
FieldName {
width: auto;
align: right middle;
}
Input {
width: 70;
}
"""

def _field_to_widget(self) -> Widget:
id = f"adjust_{self.field_name}_input"
if self.field.annotation is bool:
# If the setting is a boolean, render a on/off switch
return Switch(value=self.value, id=id)
elif isinstance(self.field.annotation, type) and issubclass(self.field.annotation, enum.StrEnum):
# If the setting is an enum, then we'll render a dropdown with all of the available options
result = Select(options=[(t.title(), t) for t in list(self.field.annotation)], value=self.value, id=id)
return result
else:
return Input(value=str(self.value), id=id)

def __init__(self, field_name: str, field: FieldInfo, value: Any) -> None:
super().__init__()
self.field_name = field_name
self.field = field
self.value = value

def compose(self) -> ComposeResult:
yield FieldName(f"{field_name_to_readable_name(self.field_name)}:")
yield self._field_to_widget()


class SettingsSection(Vertical):
DEFAULT_CSS = """
SettingsSection {
border: blank white;
height: auto;
}
"""

def __init__(self, parent_field_name: str, model: BaseModel) -> None:
super().__init__()
self.parent_field_name = parent_field_name
self.model = model
self.fields = model.model_fields

def compose(self) -> ComposeResult:
yield Markdown(f"## {field_name_to_readable_name(self.parent_field_name)}")
for field_name, field_info in self.fields.items():
current_value = getattr(self.model, field_name)
yield FieldSetting(field_name, field_info, current_value)


class SettingsContainer(Container):
DEFAULT_CSS = """
SettingsContainer {
dock: top;
height: 80%;
align: center middle;
}
#settings_buttons {
width: auto;
height: auto;
padding-left: 35;
}
"""

def __init__(self, config: Config) -> None:
super().__init__()
self.config = config

def compose(self) -> ComposeResult:
yield Markdown("# LazyGithub Settings")
with ScrollableContainer(id="settings_adjustment"):
for field, value in self.config:
yield SettingsSection(field, value)

yield Rule()

with Horizontal(id="settings_buttons"):
yield Button("Save", id="save_settings", variant="success")
yield Button("Cancel", id="cancel_settings", variant="error")

def _build_updated_settings(self):
pass

@on(Button.Pressed, "#save_settings")
async def save_settings(self, _: Button.Pressed) -> None:
self.notify("Settings saved")
self.app.pop_screen()

@on(Button.Pressed, "#cancel_settings")
async def cancel_settings(self, _: Button.Pressed) -> None:
self.app.pop_screen()


class SettingsModal(ModalScreen):
DEFAULT_CSS = """
SettingsModal {
height: 80%;
}
SettingsContainer {
width: 100;
height: 50;
border: thick $background 80%;
background: $surface;
}
"""

def __init__(self, config: Config) -> None:
super().__init__()
self.config = config

def compose(self) -> ComposeResult:
yield SettingsContainer(self.config)


if __name__ == "__main__":
from textual.app import App

class SettingsMain(App):
def compose(self) -> ComposeResult:
yield SettingsContainer(Config.load_config())

SettingsMain().run()

0 comments on commit fd6fff6

Please sign in to comment.