Activity editing

This commit is contained in:
3wc 2023-10-31 23:55:19 +00:00
parent 0c58555b43
commit e8ff5f1411
3 changed files with 100 additions and 26 deletions

View File

@ -8,7 +8,6 @@ from textual.events import DescendantBlur
from textual.widgets import Header, Footer, DataTable, Input, Button, Label, Checkbox from textual.widgets import Header, Footer, DataTable, Input, Button, Label, Checkbox
from textual.containers import Horizontal, Vertical from textual.containers import Horizontal, Vertical
from textual.coordinate import Coordinate from textual.coordinate import Coordinate
from textual.reactive import reactive
from textual.screen import Screen, ModalScreen from textual.screen import Screen, ModalScreen
from textual_autocomplete import AutoComplete, Dropdown, DropdownItem from textual_autocomplete import AutoComplete, Dropdown, DropdownItem
@ -75,21 +74,65 @@ class ListScreen(Screen):
self._refresh() self._refresh()
class ActivityEditScreen(ModalScreen): class ActivityEditScreen(ModalScreen):
BINDINGS = [("escape", "cancel", "Cancel")] BINDINGS = [
("escape", "cancel", "Cancel"),
("ctrl+s", "save", "Save"),
]
category_id = None
category_name = ''
def _get_categories(self, input_state):
categories = [DropdownItem(c.name, str(c.id)) for c in HamsterCategory.select()]
return ActivityMappingScreen._filter_dropdowns(categories, input_state.value)
def __init__(self, category, activity):
if category is not None:
self.category_id = category.id
self.category_name = category.name
self.activity_name = activity.name
super().__init__()
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Grid( yield Vertical(
Label("Are you sure you want to quit?", id="question"), Horizontal(Label("Category:"),
Button("Quit", variant="error", id="quit"), AutoComplete(
Button("Cancel", variant="primary", id="cancel"), Input(placeholder="Type to search...", id="category",
id="dialog", value=self.category_name),
Dropdown(items=self._get_categories),
),
),
Horizontal(Label("Activity:"), Input(value=self.activity_name,
id='activity')),
) )
@on(Input.Submitted, "#category")
def category_submitted(self, event):
if event.control.parent.dropdown.selected_item is not None:
self.category_id = str(
event.control.parent.dropdown.selected_item.left_meta
)
self.query_one("#activity").focus()
@on(DescendantBlur, "#category")
def category_blur(self, event):
if event.control.parent.dropdown.selected_item is not None:
self.category_id = str(
event.control.parent.dropdown.selected_item.left_meta
)
def action_cancel(self): def action_cancel(self):
self.dismiss(None) self.dismiss(None)
def action_save(self):
self.dismiss(
{
"category": self.category_id,
"activity": self.query_one('#activity').value,
}
)
class ActivityMappingScreen(ModalScreen): class ActivityMappingScreen(ModalScreen):
BINDINGS = [ BINDINGS = [
@ -376,10 +419,27 @@ class ActivityListScreen(ListScreen):
del self.move_from_activity del self.move_from_activity
def action_edit(self): def action_edit(self):
def handle_edit(properties): row_idx: int = self.table.cursor_row
print(properties) row_cells = self.table.get_row_at(row_idx)
self.app.push_screen(ActivityEditScreen(), handle_edit) try:
category = HamsterCategory.get(id=row_cells[0])
except HamsterCategory.DoesNotExist:
category = None
activity = HamsterActivity.get(id=row_cells[2])
def handle_edit(properties):
if properties is None:
return
activity.name = properties['activity']
activity.category_id = properties['category']
activity.save()
self._refresh()
self.app.push_screen(ActivityEditScreen(
category=category,
activity=activity
), handle_edit)
def action_mapping(self): def action_mapping(self):
selected_activity = ( selected_activity = (

View File

@ -1,50 +1,64 @@
DataTable { DataTable {
height: 90%; height: 90%;
} }
DataTable .datatable--cursor { DataTable .datatable--cursor {
background: grey; background: grey;
} }
DataTable:focus .datatable--cursor { DataTable:focus .datatable--cursor {
background: orange; background: orange;
} }
#filter { #filter {
display: none; display: none;
} }
#filter Input { #filter Input {
width: 50%; width: 50%;
} }
ActivityEditScreen, ActivityMappingScreen { ActivityEditScreen, ActivityMappingScreen {
align: center middle; align: center middle;
} }
ActivityEditScreen > Vertical,
ActivityMappingScreen > Vertical { ActivityMappingScreen > Vertical {
padding: 0 1; padding: 0 1;
width: auto; width: 80;
height: 30; height: 30;
border: thick $background 80%; border: thick $background 80%;
background: $surface; background: $surface;
} }
ActivityMappingScreen Horizontal { ActivityEditScreen > Vertical {
align: left middle; height: 10;
width: auto;
} }
ActivityMappingScreen Horizontal {
align: left middle;
width: auto;
}
ActivityEditScreen Horizontal {
width: 80;
}
ActivityEditScreen Label,
ActivityMappingScreen Label { ActivityMappingScreen Label {
padding: 0 1; padding: 0 1;
width: auto; width: auto;
border: blank; border: blank;
} }
ActivityMappingScreen AutoComplete { ActivityMappingScreen AutoComplete {
width: 80; width: 80;
} }
#description, #tags { #description, #tags {
width: 30; width: 30;
}
ActivityEditScreen Input {
width: 60;
} }

View File

@ -17,7 +17,7 @@ class KimaiAPI(object):
auth_headers = {"X-AUTH-USER": KIMAI_USERNAME, "X-AUTH-TOKEN": KIMAI_API_KEY} auth_headers = {"X-AUTH-USER": KIMAI_USERNAME, "X-AUTH-TOKEN": KIMAI_API_KEY}
def __init__(self): def __init__(self):
requests_cache.install_cache("kimai", backend="sqlite", expire_after=1800) # requests_cache.install_cache("kimai", backend="sqlite", expire_after=1800)
self.customers_json = requests.get( self.customers_json = requests.get(
f"{self.KIMAI_API_URL}/customers?visible=3", headers=self.auth_headers f"{self.KIMAI_API_URL}/customers?visible=3", headers=self.auth_headers
).json() ).json()