very first dummy version of a search with all the project Kladeradatsch
This commit is contained in:
parent
479b973d43
commit
6bd6bbb14c
12 changed files with 148 additions and 2 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.idea
|
||||
testasync.py
|
||||
out
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
|||
[submodule "src/flinventory"]
|
||||
path = src/flinventory
|
||||
[submodule "flinventory_gui/flinventory"]
|
||||
path = flinventory_gui/flinventory
|
||||
url = https://flugit.hilsky.de/flukx/flinventory.git
|
||||
branch = bikeparts
|
||||
|
|
4
.mypyrc
Normal file
4
.mypyrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
[mypy]
|
||||
packages=flinventoryGUI
|
||||
[mypy-flinventoryGUI.flinventory.*]
|
||||
ignore_errors=True
|
21
.pylintrc
Normal file
21
.pylintrc
Normal file
|
@ -0,0 +1,21 @@
|
|||
[tool.pylint.main]
|
||||
# Add files or directories matching the regular expressions patterns to the
|
||||
# ignore-list. The regex matches against paths and can be in Posix or Windows
|
||||
# format. Because '\\' represents the directory delimiter on Windows systems, it
|
||||
# can't be used as an escape character.
|
||||
# Unfortunately this does not what I expect. I get errors from the submodule.
|
||||
ignore-paths = 'flinventoryGUI/flinventory/.*'
|
||||
|
||||
# List of module names for which member attributes should not be checked and will
|
||||
# not be imported (useful for modules/projects where namespaces are manipulated
|
||||
# during runtime and thus existing member attributes cannot be deduced by static
|
||||
# analysis). It supports qualified module names, as well as Unix pattern
|
||||
# matching.
|
||||
ignored-modules=flinventoryGUI.flinventory.part
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode = true
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=logging-format-interpolation,logging-not-lazy,logging-fstring-interpolation
|
12
README.md
12
README.md
|
@ -3,3 +3,15 @@
|
|||
A GUI for the flinventory project/ data format.
|
||||
|
||||
Currently only intended for bike part lists.
|
||||
|
||||
It's run with `python flinventory_gui/search.py`.
|
||||
|
||||
## Packages and importing
|
||||
|
||||
I still don't understand the import and package mechanism of python.
|
||||
I tried a lot of different combinations of . and import and import from
|
||||
but could not get search.py working at the same time as keeping the
|
||||
scripts like datacleanup.py in flinventory working.
|
||||
My terrible workaround now is to symlink the necessary python files
|
||||
in flinventory_gui from the subdirectory (and submodule) inventory.
|
||||
Please fix this if you have understood python import mechanism.
|
16
environment.yml
Normal file
16
environment.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
# this file specifies what the suitable conda environment for this
|
||||
# project looks like
|
||||
name: bikeparts-gui
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
# from submodule flinventory:
|
||||
- pypandoc
|
||||
- python-slugify
|
||||
- imagesize
|
||||
- treelib
|
||||
- pylint
|
||||
- mypy
|
||||
# imagemagick for datacleanup rotate
|
||||
- nicegui
|
||||
|
7
flinventory_gui/__main_.py
Normal file
7
flinventory_gui/__main_.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
"""This is run if the module is run as python -m flinventory_gui.
|
||||
|
||||
The GUI is served in a web browser.
|
||||
"""
|
||||
from . import search
|
||||
|
||||
search.search_page()
|
1
flinventory_gui/location.py
Symbolic link
1
flinventory_gui/location.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
flinventory/location.py
|
1
flinventory_gui/part.py
Symbolic link
1
flinventory_gui/part.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
flinventory/part.py
|
80
flinventory_gui/search.py
Normal file
80
flinventory_gui/search.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
"""Search in a parts list."""
|
||||
|
||||
import asyncio
|
||||
from typing import Optional, Iterable, NamedTuple
|
||||
import nicegui
|
||||
from nicegui import ui
|
||||
from part import Part
|
||||
|
||||
class ImageDirectories(NamedTuple):
|
||||
images_landscape: str
|
||||
images_portrait: str
|
||||
DEFAULT_IMAGE_DIRECTORIES = ImageDirectories(images_landscape = "", images_portrait = "")
|
||||
|
||||
async def find_parts(search_string: str) -> list[Part]:
|
||||
"""Gives parts that the user might have searched for.
|
||||
|
||||
Args:
|
||||
search_string: Input of user
|
||||
Returns:
|
||||
list of parts that somehow include the search string
|
||||
"""
|
||||
return [Part({"name_de": "Dummy thing"}, DEFAULT_IMAGE_DIRECTORIES, {})]
|
||||
|
||||
|
||||
def list_parts(ui_element: nicegui.ui.element, parts: Iterable[Part]) -> None:
|
||||
"""Replaces content of ui_element with information about the parts.
|
||||
|
||||
Args:
|
||||
ui_element: Some UI element that can be changed.
|
||||
parts: list of parts to be displayed.
|
||||
"""
|
||||
ui_element.clear()
|
||||
with ui_element:
|
||||
# enter the context of the the ui element
|
||||
# inside this context all ui things are placed in this element
|
||||
if not parts:
|
||||
ui.label("Nothing found.")
|
||||
else:
|
||||
for part in parts:
|
||||
ui.label(part.name)
|
||||
|
||||
|
||||
def search_page() -> None:
|
||||
"""Add a search page to the UI."""
|
||||
results: Optional[ui.element] = None
|
||||
"""UI container for the search results."""
|
||||
running_queries: list[asyncio.Task] = []
|
||||
"""Search queries (max. 1) running. Here to be cancellable by different search coroutines."""
|
||||
|
||||
async def search(event: nicegui.events.ValueChangeEventArguments) -> None:
|
||||
"""Search for cocktails as you type.
|
||||
|
||||
Args:
|
||||
event: the input field change event. The new value event.value is used.
|
||||
"""
|
||||
if running_queries:
|
||||
for query in running_queries:
|
||||
query.cancel()
|
||||
query = asyncio.create_task(find_parts(event.value))
|
||||
running_queries.append(query)
|
||||
try:
|
||||
response = await query
|
||||
except asyncio.exceptions.CancelledError:
|
||||
pass
|
||||
else:
|
||||
if results:
|
||||
list_parts(results, response)
|
||||
else:
|
||||
ui.notify("Internal error: results element is None.")
|
||||
|
||||
|
||||
search_field = ui.input(on_change=search) \
|
||||
.props('autofocus outlined rounded item-aligned input-class="ml-3"') \
|
||||
.classes('w-96 self-center mt-24 transition-all')
|
||||
results = ui.column()
|
||||
|
||||
|
||||
if __name__ in {"__main__", "__mp_main__"}:
|
||||
search_page()
|
||||
ui.run()
|
1
flinventory_gui/sign.py
Symbolic link
1
flinventory_gui/sign.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
flinventory/sign.py
|
Loading…
Reference in a new issue