Replace item dialogs with Popups for better integration

master
Cole Deck 2 days ago
parent 27169ff8a0
commit b1c817432b

@ -82,7 +82,7 @@ def init():
db.create_tables([location, office, item, component, user]) db.create_tables([location, office, item, component, user])
print("Database initialized.") print("Database initialized.")
global search global search
print("Creating cache index...") print("Creating cache index... ", end='', flush=True)
search = ivs() search = ivs()
add = item.select().dicts() add = item.select().dicts()
#print(add) #print(add)
@ -92,9 +92,10 @@ def init():
itm["location"] = item.select().where(item.barcode==itm["barcode"])[0].loc.name itm["location"] = item.select().where(item.barcode==itm["barcode"])[0].loc.name
except: except:
pass pass
print(itm) #print(itm)
#print(type(itm)) #print(type(itm))
search.add_document(itm) search.add_document(itm)
print(len(add))
print("Cache build complete.") print("Cache build complete.")
def search_item(query, filters: dict={}): def search_item(query, filters: dict={}):
@ -128,7 +129,7 @@ def find_item(barcode):
def find_item_location(barcode): def find_item_location(barcode):
try: try:
return item.select().where(item.barcode==barcode).loc return item.select().where(item.barcode==barcode)[0].loc
except: except:
return False return False
@ -311,11 +312,11 @@ def get_location(name, parent=None):
def get_location_id(barcode): def get_location_id(barcode):
try: try:
print("str" + barcode + "str") #print("str" + barcode + "str")
if len(barcode) > 0: if len(barcode) > 0:
query = location.select() query = location.select()
for loc in query: for loc in query:
print(loc.name, loc.locationid) #print(loc.name, loc.locationid)
if loc.locationid == barcode: if loc.locationid == barcode:
return loc return loc
return False return False

@ -74,6 +74,8 @@ class AddPage(rio.Component):
self.popup_show = False self.popup_show = False
else: else:
# OK, add part # OK, add part
if self.location == "":
self.location_code = ""
if create_item(self.partnum, self.serial, self.office, self.code, locationid=self.location_code, description=self.description, manufacturer=self.manu, mac=self.mac, fwver=self.fwver) == False: if create_item(self.partnum, self.serial, self.office, self.code, locationid=self.location_code, description=self.description, manufacturer=self.manu, mac=self.mac, fwver=self.fwver) == False:
self.popup_message = "\n Duplicate barcode! \n\n" self.popup_message = "\n Duplicate barcode! \n\n"
self.popup_show = True self.popup_show = True

@ -35,6 +35,19 @@ class BrowsePage(rio.Component):
emanufield: str = "" emanufield: str = ""
eoffice: str = "" eoffice: str = ""
edescription: str = "" edescription: str = ""
info_show = False
edit_show = False
iname: str =""
imanu: str =""
iserial: str =""
imac: str =""
ifw: str =""
iloc: str =""
icheckouts: str =""
icheckout_times: str =""
ibarcode: str =""
idesc: str =""
@rio.event.on_populate @rio.event.on_populate
async def _search(self, query=searchtext): async def _search(self, query=searchtext):
@ -56,103 +69,74 @@ class BrowsePage(rio.Component):
async def _search_trigger(self, event: rio.TextInputChangeEvent): async def _search_trigger(self, event: rio.TextInputChangeEvent):
await self._search(event.text) await self._search(event.text)
async def _create_dialog_info(self, code: str) -> str | None: async def copy_info(self, text: str):
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_message = "\n Copied! \n\n"
self.popup_color = 'success' self.popup_color = 'success'
await self.session.set_clipboard(text)
self.popup_show = True self.popup_show = True
await asyncio.sleep(1.5) await asyncio.sleep(1.5)
self.popup_show = False self.popup_show = False
async def _open_info_popup(self, code: str, skip_display=False) -> str | None:
def build_dialog_info() -> rio.Component:
# Build the dialog
itm: dict = find_item(code) itm: dict = find_item(code)
try: try:
loc = itm["location"] self.iloc = itm["location"]
except: except:
loc = "" self.iloc = ""
if itm["checkout"]: if itm["checkout"]:
checkout = itm["checkout_user"] + " - " + loc checkout = itm["checkout_user"] + " - " + self.iloc
else: else:
checkout = loc checkout = self.iloc
self.iname=str(itm["fullname"])
details: rio.ListView = rio.ListView(grow_y=True, min_width=40) self.imanu=str(itm["manufacturer"])
# for key, val in itm.items(): self.iserial=str(itm["serial"])
# details.add(rio.SimpleListItem(text=key,secondary_text=val)) self.imac=str(itm["mac"])
#functools.partial(copy_info, text=item["barcode"]) self.ifw=str(itm["fwver"])
name=str(itm["fullname"]) self.iloc=str(checkout)
manu=str(itm["manufacturer"]) self.icheckouts=str(itm["checkout"])
serial=str(itm["serial"]) self.icheckout_times=str(itm["checkout_start"]) + " to " + str(itm["checkout_end"])
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"]) #office=str(itm["office"])
barcode=str(itm["barcode"]) self.ibarcode=str(itm["barcode"])
desc=str(itm["description"]) self.idesc=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( if not skip_display:
rio.Column( self.edit_show = False
details, self.info_show = True
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 async def _close_info_popup(self):
result = await dialog.wait_for_close() self.edit_show = False
self.info_show = False
await self.force_refresh()
async def _close_edit_popup(self):
await self._open_info_popup(self.ibarcode)
await self.force_refresh()
async def _save_edit_popup(self):
self.edit_show = False
self.info_show = True
await self.force_refresh()
await self._add_part_button()
await asyncio.sleep(1)
await self._open_info_popup(self.ibarcode, skip_display=True)
await self._search()
await asyncio.sleep(1)
self.popup_show = False
await self._open_info_popup(self.ibarcode, skip_display=True)
await self._search()
# Return the selected value
return result async def _delete_edit_popup(self):
self.edit_show = False
self.info_show = False
# TODO: delete here
await self.force_refresh()
async def _create_dialog_edit(self, code: str) -> str | None: async def _open_edit_popup(self, code: str) -> str | None:
itm: dict = find_item(code) itm: dict = find_item(code)
from mac_vendor_lookup import AsyncMacLookup
try: try:
self.elocation: str = itm["location"] self.elocation: str = itm["location"]
self.elocation_code: str = find_item_location(code).locationid self.elocation_code: str = find_item_location(code).locationid
@ -173,30 +157,10 @@ class BrowsePage(rio.Component):
self.emanufield: str = itm["manufacturer"] self.emanufield: str = itm["manufacturer"]
self.eoffice: str = itm["office"] self.eoffice: str = itm["office"]
self.edescription: str = itm["description"] self.edescription: str = itm["description"]
self.info_show = False
self.edit_show = True
async def check_mac(mac): async def add_part(self):
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 == "": if self.ecode == "":
# FAIL # FAIL
self.popup_message = "\n Missing barcode! \n\n" self.popup_message = "\n Missing barcode! \n\n"
@ -205,6 +169,8 @@ class BrowsePage(rio.Component):
else: else:
# OK, add part # OK, add part
if self.elocation == "":
self.elocation_code = ""
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: 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_message = "\n Unable to update! \n\n"
self.popup_show = True self.popup_show = True
@ -214,111 +180,187 @@ class BrowsePage(rio.Component):
self.popup_show = True self.popup_show = True
self.popup_color = 'success' self.popup_color = 'success'
#self.ename: str = "" #self.ename: str = ""
self.epartnum: str = "" self.epartnum = ""
self.emac: str = "" self.emac = ""
self.eserial: str = "" self.eserial = ""
self.efwver: str = "" self.efwver = ""
self.ecode: str = "" self.ecode = ""
self.emacvendor: str = "" self.emacvendor = ""
self.emanu: str = "" self.emanu = ""
self.emanufield: str = "" self.emanufield = ""
self.edescription: str = "" self.edescription = ""
self.elocation: str = "" self.elocation = ""
self.elocation_code: str = "" self.elocation_code = ""
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): async def _add_part_button(self):
await check_mac(event.text) await self.add_part()
async def _update_location(event: rio.TextInputChangeEvent): def click_item_page(self, code):
print("Checking " + event.text) self.session[comps.Settings].selected_item = code
self.elocation = event.text self.session.attach(self.session[comps.Settings])
if get_location_id(event.text) != False: self.session.navigate_to("/item")
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): async def click_item_dialog(self, code):
self.epartnum = event.text self.session[comps.Settings].selected_item = code
await self._open_info_popup(code)
async def _update_eserial(event: rio.TextInputChangeEvent): async def _update_elocation(self, event: rio.TextInputChangeEvent):
self.eserial = event.text print("Checking " + self.elocation)
if get_location_id(self.elocation) != False:
self.elocation_code = self.elocation
print("Found location " + get_location_id(self.elocation).name)
self.elocation = get_location_id(self.elocation).name
async def _update_emanufield(event: rio.TextInputChangeEvent): def build(self) -> rio.Component:
self.emanufield = event.text searchview: rio.ListView = rio.ListView(grow_y=True)
self.emanu = event.text 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"])))
async def _update_efwver(event: rio.TextInputChangeEvent): details = rio.ListView(grow_y=True, min_width=40)
self.efwver = event.text
details.add(rio.SimpleListItem(text=self.iname, on_press=functools.partial(self.copy_info, text=self.iname)))
details.add(rio.SimpleListItem(text=self.imanu, on_press=functools.partial(self.copy_info, text=self.imanu)))
details.add(rio.SimpleListItem(text="Serial",secondary_text=self.iserial, on_press=functools.partial(self.copy_info, text=self.iserial)))
details.add(rio.SimpleListItem(text="MAC",secondary_text=self.imac, on_press=functools.partial(self.copy_info, text=self.imac)))
details.add(rio.SimpleListItem(text="FW Version",secondary_text=self.ifw, on_press=functools.partial(self.copy_info, text=self.ifw)))
details.add(rio.SimpleListItem(text="Location",secondary_text=self.iloc, on_press=functools.partial(self.copy_info, text=self.iloc)))
details.add(rio.SimpleListItem(text="Checked out?",secondary_text=self.icheckouts, on_press=functools.partial(self.copy_info, text=self.icheckouts)))
details.add(rio.SimpleListItem(text="Checkout start/end",secondary_text=self.icheckout_times, on_press=functools.partial(self.copy_info, text=self.icheckout_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=self.ibarcode, on_press=functools.partial(self.copy_info, text=self.ibarcode)))
details.add(rio.SimpleListItem(text="Description",secondary_text=self.idesc, on_press=functools.partial(self.copy_info, text=self.idesc)))
async def _update_edescription(event: rio.TextInputChangeEvent):
self.edescription = event.text
def build_dialog_edit() -> rio.Component: return rio.Column(
# Build the dialog rio.Row(
return rio.Card( 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,
),
),
rio.Popup(
anchor=rio.Text(
text="",
style='heading1',
align_x = 0.5
),
#color=self.popup_color,
is_open=self.info_show,
min_width=40,
position='fullscreen',
color=rio.Color.TRANSPARENT,
content=rio.Card(
rio.Column(
details,
rio.Row(
rio.Button(
content="Close",
on_press=self._close_info_popup
),
rio.Button(
content="Edit",
on_press=functools.partial(self._open_edit_popup, code=self.ibarcode)
),
spacing=2,
margin=2
),
spacing=1,
margin=2,
),
align_x=0.5,
align_y=0.5,
)
),
rio.Popup(
anchor=rio.Text(
text="",
style='heading1',
align_x = 0.5
),
#color=self.popup_color,
is_open=self.edit_show,
min_width=40,
position='fullscreen',
color=rio.Color.TRANSPARENT,
content=rio.Card(
rio.Column( rio.Column(
rio.TextInput( rio.TextInput(
label="Barcode", label="Barcode",
text=self.ecode, text=self.bind().ecode,
is_sensitive=False is_sensitive=False
), ),
rio.TextInput( rio.TextInput(
label="Full part number", label="Full part number",
text=self.epartnum, text=self.bind().epartnum,
on_change=_update_epartnum
), ),
rio.TextInput( rio.TextInput(
label="Serial", label="Serial",
text=self.eserial, text=self.bind().eserial,
on_change=_update_eserial
), ),
rio.TextInput( rio.TextInput(
label="MAC", label="MAC",
text=self.emac, text=self.bind().emac,
on_change=_update_mac,
), ),
rio.TextInput( rio.TextInput(
label="Location (optional)", label="Location",
text=self.elocation, text=self.bind().elocation,
on_change=_update_location, on_change=self._update_elocation,
), ),
rio.TextInput( rio.TextInput(
label="Manufacturer", label="Manufacturer",
text=self.emanufield, text=self.bind().emanu,
on_change=_update_emanufield
), ),
rio.TextInput( rio.TextInput(
label="FW Ver", label="FW Ver",
text=self.efwver, text=self.bind().efwver
on_change=_update_efwver
), ),
rio.MultiLineTextInput( rio.MultiLineTextInput(
label="Description (optional)", label="Description",
text=self.edescription, text=self.bind().edescription
on_change=_update_edescription
), ),
rio.Row( rio.Row(
rio.Button( rio.Button(
content="Cancel", content="Cancel",
on_press=_close_dialog_edit, on_press=self._close_edit_popup,
color='warning' color='warning'
), ),
rio.Button( rio.Button(
content="Delete", content="Delete",
on_press=_delete_dialog_edit, on_press=self._delete_edit_popup,
color='danger' color='danger'
), ),
rio.Button( rio.Button(
content="Save", content="Save",
on_press=_save_dialog_edit on_press=self._save_edit_popup
), ),
spacing=2, spacing=2,
margin=2 margin=2
@ -329,80 +371,6 @@ class BrowsePage(rio.Component):
align_x=0.5, align_x=0.5,
align_y=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, spacing=2,
min_width=60, min_width=60,

@ -89,7 +89,7 @@ class InventorySearch:
:param filters: A meilisearch compatible filter statement. :param filters: A meilisearch compatible filter statement.
:returns: The search results dict. Actual results are in a list under "hits", but there are other nice values that are useful in the root element.""" :returns: The search results dict. Actual results are in a list under "hits", but there are other nice values that are useful in the root element."""
if filters: if filters:
q = self.idxref.search(query, {"filter": filters}) q = self.idxref.search(query, {"filter": filters, "limit": 1000})
else: else:
q = self.idxref.search(query) q = self.idxref.search(query)
return q return q

Loading…
Cancel
Save