104 lines
2.9 KiB
Python
104 lines
2.9 KiB
Python
"""
|
|
This is where the application is implemented.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from textual import on
|
|
from textual.app import App, ComposeResult
|
|
from textual.containers import HorizontalGroup
|
|
from textual.logging import TextualHandler
|
|
from textual.screen import Screen
|
|
from textual.widget import Widget
|
|
from textual.widgets import Button, DataTable, Footer, Header, Input, Static
|
|
|
|
from .database import create_db_and_tables, engine
|
|
from .models import add_to_database, load_initial_data, make_teilchen_input
|
|
|
|
logging.basicConfig(
|
|
level="NOTSET",
|
|
handlers=[TextualHandler()],
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
TEILCHEN_DATA_HEADER = "pk Name Description Number Tags".split()
|
|
|
|
|
|
class SammlerApp(App):
|
|
async def on_mount(self) -> None:
|
|
create_db_and_tables()
|
|
self.push_screen(AddInventoryScreen())
|
|
|
|
|
|
class SearchBar(Static):
|
|
DEFAULT_CSS = """
|
|
#teilchen-input {
|
|
width: 4fr;
|
|
}
|
|
#button-search, #button-add {
|
|
width: 1fr;
|
|
}
|
|
"""
|
|
|
|
def compose(self) -> ComposeResult:
|
|
with HorizontalGroup(id="search-bar-widget"):
|
|
yield Input(
|
|
placeholder='This is a name. "This is the description" #these #are #tags',
|
|
tooltip=(
|
|
"Enter a name followed by a period, then a description "
|
|
'enclosed in double quotes ("). You should use #hashtags for any meta information. '
|
|
"Hashtags can be placed anywhere."
|
|
),
|
|
id="teilchen-input",
|
|
type="text",
|
|
)
|
|
yield Button("Add", variant="success", classes="search-bar-buttons", id="button-add")
|
|
yield Button(
|
|
"Search",
|
|
variant="default",
|
|
classes="search-bar-buttons",
|
|
id="button-search",
|
|
)
|
|
|
|
@on(Input.Submitted)
|
|
async def parse_input(self, event: Input.Submitted) -> None:
|
|
|
|
if not (tc := await make_teilchen_input(event.value)):
|
|
return
|
|
|
|
event.input.value = ""
|
|
|
|
teilchen = await add_to_database(tc, engine)
|
|
self.screen.query_one(DataTable).add_row(
|
|
teilchen.id, teilchen.name, teilchen.description, teilchen.number, teilchen.tags
|
|
)
|
|
|
|
|
|
class SearchResults(Widget):
|
|
def compose(self) -> ComposeResult:
|
|
yield DataTable(id="table-search-result", cursor_type="row", zebra_stripes=True)
|
|
|
|
async def on_mount(self) -> None:
|
|
table: DataTable = self.query_one(DataTable)
|
|
table.add_columns(*TEILCHEN_DATA_HEADER)
|
|
table.add_rows(await load_initial_data(engine))
|
|
|
|
|
|
class AddInventoryScreen(Screen):
|
|
def compose(self) -> ComposeResult:
|
|
yield Header()
|
|
yield SearchBar()
|
|
yield SearchResults()
|
|
yield Footer()
|
|
|
|
|
|
# so we can import it without running it
|
|
app = SammlerApp()
|
|
|
|
|
|
def main() -> None:
|
|
app.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|