from __future__ import annotations from dataclasses import KW_ONLY, field from typing import * # type: ignore import rio from .. import components as comps from .add_page import AddPage from db_classes import * import functools import asyncio class BrowsePage(rio.Component): searchtext: str = "" items: list = [] office: str = "" filters: dict = {} popup_message: str = "" popup_show: bool = False popup_color: str = 'success' elocation: str = "" elocation_code: str = "" epartnum: str = "" emac: str = "" eserial: str = "" efwver: str = "" ecode: str = "" emacvendor: str = "" emanu: str = "" emanufield: str = "" eoffice: str = "" edescription: str = "" @rio.event.on_populate async def _search(self, query=searchtext): self.office = self.session[comps.Settings].office self.filters['office'] = self.office self.items = search_item(query, self.filters) await self.force_refresh() @rio.event.periodic(1) async def set_office_init(self): if self.office != self.session[comps.Settings].office: self.office = self.session[comps.Settings].office #print(self.office) await self._search() async def _search_trigger(self, event: rio.TextInputChangeEvent): await self._search(event.text) async def _create_dialog_info(self, code: str) -> str | None: async def copy_info(text: str): await self.session.set_clipboard(text) # TODO: show "Copied!" popup self.popup_message = "\n Copied! \n\n" self.popup_color = 'success' self.popup_show = True await asyncio.sleep(1.5) self.popup_show = False def build_dialog_info() -> rio.Component: # Build the dialog itm: dict = find_item(code) try: loc = itm["location"] except: loc = "" if itm["checkout"]: checkout = itm["checkout_user"] + " - " + loc else: checkout = loc details: rio.ListView = rio.ListView(grow_y=True, min_width=40) # for key, val in itm.items(): # details.add(rio.SimpleListItem(text=key,secondary_text=val)) #functools.partial(copy_info, text=item["barcode"]) name=str(itm["fullname"]) manu=str(itm["manufacturer"]) serial=str(itm["serial"]) mac=str(itm["mac"]) fw=str(itm["fwver"]) loc=str(checkout) checkouts=str(itm["checkout"]) checkout_times=str(itm["checkout_start"]) + " to " + str(itm["checkout_end"]) #office=str(itm["office"]) barcode=str(itm["barcode"]) desc=str(itm["description"]) details.add(rio.SimpleListItem(text=name, on_press=functools.partial(copy_info, text=name))) details.add(rio.SimpleListItem(text=manu, on_press=functools.partial(copy_info, text=manu))) details.add(rio.SimpleListItem(text="Serial",secondary_text=serial, on_press=functools.partial(copy_info, text=serial))) details.add(rio.SimpleListItem(text="MAC",secondary_text=mac, on_press=functools.partial(copy_info, text=mac))) details.add(rio.SimpleListItem(text="FW Version",secondary_text=fw, on_press=functools.partial(copy_info, text=fw))) details.add(rio.SimpleListItem(text="Location",secondary_text=loc, on_press=functools.partial(copy_info, text=loc))) details.add(rio.SimpleListItem(text="Checked out?",secondary_text=checkouts, on_press=functools.partial(copy_info, text=checkouts))) details.add(rio.SimpleListItem(text="Checkout start/end",secondary_text=checkout_times, on_press=functools.partial(copy_info, text=checkout_times))) #details.add(rio.SimpleListItem(text="Office",secondary_text=office, on_press=functools.partial(copy_info, text=office))) details.add(rio.SimpleListItem(text="Barcode",secondary_text=barcode, on_press=functools.partial(copy_info, text=barcode))) details.add(rio.SimpleListItem(text="Description",secondary_text=desc, on_press=functools.partial(copy_info, text=desc))) return rio.Card( rio.Column( details, rio.Row( rio.Button( content="Close", on_press=_close_dialog_info ), rio.Button( content="Edit", on_press=functools.partial(self._create_dialog_edit, code=code) ), spacing=2, margin=2 ), spacing=1, margin=2, ), align_x=0.5, align_y=0.5, ) async def _close_dialog_info() -> None: # This function will be called whenever the user selects an # Item. It simply closes the dialog with the selected value. await dialog.close() dialog = await self.session.show_custom_dialog( build=build_dialog_info, # Prevent the user from interacting with the rest of the app # while the dialog is open modal=True, # Don't close the dialog if the user clicks outside of it user_closeable=True, ) # Wait for the user to select an option result = await dialog.wait_for_close() # Return the selected value return result async def _create_dialog_edit(self, code: str) -> str | None: itm: dict = find_item(code) from mac_vendor_lookup import AsyncMacLookup try: self.elocation: str = itm["location"] self.elocation_code: str = find_item_location(code).locationid except: self.elocation: str = "" self.elocation_code: str = "" self.epartnum: str = itm["fullname"] self.emac: str = itm["mac"] self.eserial: str = itm["serial"] self.efwver: str = itm["fwver"] self.ecode: str = code self.popup_message: str = "" self.popup_show: bool = False self.popup_color: str = 'warning' self.emacvendor: str = "" self.emanu: str = itm["manufacturer"] self.emanufield: str = itm["manufacturer"] self.eoffice: str = itm["office"] self.edescription: str = itm["description"] async def check_mac(mac): print("Checking", mac) self.emac = mac try: macvendor = await AsyncMacLookup().lookup(mac) if self.emanufield == "" or self.emanufield == self.emacvendor: # blank or set by MAC already self.emanu = macvendor self.emanufield = macvendor else: self.emanu = self.emanufield self.emacvendor = macvendor #print(macvendor) except: pass # not valid MAC? async def check_all(): await check_mac(self.emac) # check part number # lookup in PL_Export_rel async def add_part(): await check_all() if self.ecode == "": # FAIL self.popup_message = "\n Missing barcode! \n\n" self.popup_show = True self.popup_color = 'danger' else: # OK, add part if update_item(self.epartnum, self.eserial, self.office, self.ecode, locationid=self.elocation_code, description=self.edescription, manufacturer=self.emanu, mac=self.emac, fwver=self.efwver) == False: self.popup_message = "\n Unable to update! \n\n" self.popup_show = True self.popup_color = 'warning' else: self.popup_message = "\n Part updated! \n\n" self.popup_show = True self.popup_color = 'success' #self.ename: str = "" self.epartnum: str = "" self.emac: str = "" self.eserial: str = "" self.efwver: str = "" self.ecode: str = "" self.emacvendor: str = "" self.emanu: str = "" self.emanufield: str = "" self.edescription: str = "" self.elocation: str = "" self.elocation_code: str = "" async def _add_part_enter(event: rio.TextInputConfirmEvent): await add_part() async def _add_part_button(): await add_part() async def _update_mac(event: rio.TextInputChangeEvent): await check_mac(event.text) async def _update_location(event: rio.TextInputChangeEvent): print("Checking " + event.text) self.elocation = event.text if get_location_id(event.text) != False: self.elocation_code = event.text print("Found location " + get_location_id(event.text).name) self.elocation = get_location_id(event.text).name async def _update_epartnum(event: rio.TextInputChangeEvent): self.epartnum = event.text async def _update_eserial(event: rio.TextInputChangeEvent): self.eserial = event.text async def _update_emanufield(event: rio.TextInputChangeEvent): self.emanufield = event.text self.emanu = event.text async def _update_efwver(event: rio.TextInputChangeEvent): self.efwver = event.text async def _update_edescription(event: rio.TextInputChangeEvent): self.edescription = event.text def build_dialog_edit() -> rio.Component: # Build the dialog return rio.Card( rio.Column( rio.TextInput( label="Barcode", text=self.ecode, is_sensitive=False ), rio.TextInput( label="Full part number", text=self.epartnum, on_change=_update_epartnum ), rio.TextInput( label="Serial", text=self.eserial, on_change=_update_eserial ), rio.TextInput( label="MAC", text=self.emac, on_change=_update_mac, ), rio.TextInput( label="Location (optional)", text=self.elocation, on_change=_update_location, ), rio.TextInput( label="Manufacturer", text=self.emanufield, on_change=_update_emanufield ), rio.TextInput( label="FW Ver", text=self.efwver, on_change=_update_efwver ), rio.MultiLineTextInput( label="Description (optional)", text=self.edescription, on_change=_update_edescription ), rio.Row( rio.Button( content="Cancel", on_press=_close_dialog_edit, color='warning' ), rio.Button( content="Delete", on_press=_delete_dialog_edit, color='danger' ), rio.Button( content="Save", on_press=_save_dialog_edit ), spacing=2, margin=2 ), spacing=1, margin=2 ), align_x=0.5, align_y=0.5 ) async def _close_dialog_edit() -> None: await dialog.close() async def _save_dialog_edit() -> None: await dialog.close() await _add_part_button() await asyncio.sleep(2) self.popup_show = False async def _delete_dialog_edit() -> None: await dialog.close() dialog = await self.session.show_custom_dialog( build=build_dialog_edit, # Prevent the user from interacting with the rest of the app # while the dialog is open modal=True, # Don't close the dialog if the user clicks outside of it user_closeable=False, ) # Wait for the user to select an option result = await dialog.wait_for_close() # Return the selected value return result def click_item_page(self, code): self.session[comps.Settings].selected_item = code self.session.attach(self.session[comps.Settings]) self.session.navigate_to("/item") async def click_item_dialog(self, code): self.session[comps.Settings].selected_item = code #self.session.attach(self.session[comps.Settings]) #self.session.navigate_to("/item") ret = await self._create_dialog_info(code) def build(self) -> rio.Component: searchview: rio.ListView = rio.ListView(grow_y=True) for item in self.items: try: loc = item["location"] except: loc = "" if item["checkout"]: checkout = item["checkout_user"] + " - " + loc else: checkout = loc searchview.add(rio.SimpleListItem(text=item["fullname"],secondary_text=(item["manufacturer"] + " - Serial: " + item["serial"] + "\n" + checkout), on_press=functools.partial( self.click_item_dialog, code=item["barcode"]))) return rio.Column( rio.Row( rio.TextInput( text=self.bind().searchtext, on_change=self._search_trigger, label="Search" ) ), searchview, rio.Popup( anchor=rio.Text( text="", style='heading1', align_x = 0.5 ), color=self.popup_color, is_open=self.popup_show, content=rio.Text( text=self.popup_message, ), ), spacing=2, min_width=60, align_x=0.5, align_y=0, )