add save button

should be integrated in different way at different position ....
This commit is contained in:
flukx 2024-08-16 15:33:29 +02:00
parent 7937fd52da
commit b055102ebd

View file

@ -9,6 +9,7 @@ import nicegui
from nicegui import ui from nicegui import ui
from part import Part from part import Part
import part_list_io import part_list_io
import datacleanup
def antilen(string: str): def antilen(string: str):
@ -92,7 +93,12 @@ async def list_parts(ui_element: nicegui.ui.element, parts: Iterable[Part]) -> N
ui_element.clear() ui_element.clear()
with ((ui_element)): with ((ui_element)):
for part in parts: for part in parts:
with ui.card(): card = ui.card()
# supplying card and part as default arguments makes it use the current
# value instead of the value at the time of usage
change_card = lambda event, c=card, p=part: show_part_changer(c, p)
with card:
print(f"Create card {id(card)} for {part.name}.")
with ui.row(wrap=False): with ui.row(wrap=False):
with ui.column(): with ui.column():
with ui.row(): with ui.row():
@ -104,6 +110,7 @@ async def list_parts(ui_element: nicegui.ui.element, parts: Iterable[Part]) -> N
else: else:
if name_en != part.name: if name_en != part.name:
ui.label(text=f"({name_en})").style('font-size: 70%') ui.label(text=f"({name_en})").style('font-size: 70%')
ui.button("🖉").on_click(change_card)
other_names = ", ".join(itertools.chain( other_names = ", ".join(itertools.chain(
vars(part).get("name_alt_de", []), vars(part).get("name_alt_de", []),
vars(part).get("name_alt_en", []))) vars(part).get("name_alt_en", [])))
@ -120,9 +127,30 @@ async def list_parts(ui_element: nicegui.ui.element, parts: Iterable[Part]) -> N
"height=100px").props("fit='scale-down'") "height=100px").props("fit='scale-down'")
@ui.page("/") def load_data() -> list[Part]:
def search_page() -> None: """Load data from text files.
"""Create a NiceGUI page with a search input field and search results."""
Could implement that data is only loaded when necessary.
Then an argument force would be useful to reload.
Returns:
list of all things listed in the files
"""
options = get_file_names()
return part_list_io.get_parts(options)
def save_data(parts) -> None:
"""Save parts to files."""
options = get_file_names()
part_list_io.save_parts(parts, options.input_file, options.locations_file)
def search_page(parts: list[Part]) -> None:
"""Create a NiceGUI page with a search input field and search results.
Args:
parts: list of parts to search in
"""
print("(Re)build search page.") print("(Re)build search page.")
# UI container for the search results. # UI container for the search results.
results: Optional[ui.element] = None results: Optional[ui.element] = None
@ -130,8 +158,8 @@ def search_page() -> None:
# Search queries (max. 1) running. Here to be cancellable by different search coroutines. # Search queries (max. 1) running. Here to be cancellable by different search coroutines.
running_queries: list[asyncio.Task] = [] running_queries: list[asyncio.Task] = []
options = get_file_names() # should use the parts as they are when clicked
all_parts = part_list_io.get_parts(options) ui.button("Save").on_click(lambda click_event_arguments, parts=parts: save_data(parts))
async def search(event: nicegui.events.ValueChangeEventArguments) -> None: async def search(event: nicegui.events.ValueChangeEventArguments) -> None:
"""Search for cocktails as you type. """Search for cocktails as you type.
@ -149,7 +177,7 @@ def search_page() -> None:
except asyncio.exceptions.CancelledError: except asyncio.exceptions.CancelledError:
# the next letter was already typed, do not search and rerender for this query # the next letter was already typed, do not search and rerender for this query
return return
query = asyncio.create_task(find_parts(all_parts, event.value)) query = asyncio.create_task(find_parts(parts, event.value))
running_queries.append(query) running_queries.append(query)
try: try:
start = time.monotonic() start = time.monotonic()
@ -180,9 +208,42 @@ def search_page() -> None:
results = ui.column() results = ui.column()
def show_part_changer(ui_element: nicegui.ui.element, part: Part,
save_function: Callable[[], None]) -> None:
"""Clear content of ui element and instead display editing fields.
Args:
ui_element: the ui element (e.g. a card) on which to show the part changing ui
part: the part to change
save_function: what to call when changing is done
"""
def delete_member(member, updated: nicegui.ui.input):
del vars(part)[member]
updated.set_value("")
input_fields = {}
def save_value(event, member):
"""Copy input field value to part member."""
if not event.value:
del(vars(part)[member])
else:
vars(part)[member] = event.value
print(f"Try to let edit {part.name} with {id(ui_element)}.")
ui_element.clear()
with ui_element:
for member in ("name_de", "name_en", "description_de", "description_en"):
with ui.row():
ui.label(member + ":")
input_fields[member] = ui.input(part.get(member, "")).on_value_change(
lambda e, m=member: save_value(e, m))
ui.button("").on_click(lambda m=member, i=input_fields[member]: delete_member(m, i))
ui.button("Save").on_click(save_function)
if __name__ in {"__main__", "__mp_main__"}: if __name__ in {"__main__", "__mp_main__"}:
nicegui.app.add_static_files('/images_landscape', 'images_landscape') nicegui.app.add_static_files('/images_landscape', 'images_landscape')
search_page() search_page(load_data())
ui.run(title="Fahrradteile", ui.run(title="Fahrradteile",
favicon="website_resources/favicon.ico", favicon="website_resources/favicon.ico",
language="de", language="de",