tui: more work

This commit is contained in:
2025-09-21 00:33:35 -04:00
parent dd546dcce2
commit 2612fc984c

298
tui.py
View File

@ -8,9 +8,11 @@ import bcrypt
import secrets import secrets
import string import string
from sqlalchemy.engine import Row from sqlalchemy.engine import Row
import inflection
from core.data import Data from core.data import Data
from core.config import CoreConfig from core.config import CoreConfig
from core.const import AllnetCountryCode
try: try:
from asciimatics.widgets import Frame, Layout, Text, Button, RadioButtons, CheckBox, Divider, Label from asciimatics.widgets import Frame, Layout, Text, Button, RadioButtons, CheckBox, Divider, Label
@ -139,7 +141,7 @@ class MainView(Frame):
layout.add_widget(Button("User Management", self._user_mgmt)) layout.add_widget(Button("User Management", self._user_mgmt))
layout.add_widget(Button("Card Management", self._card_mgmt)) layout.add_widget(Button("Card Management", self._card_mgmt))
layout.add_widget(Button("Arcade Management", self._arcade_mgmt)) layout.add_widget(Button("Arcade Management", self._arcade_mgmt))
layout.add_widget(Button("Machine Management", self._mech_mgmt)) layout.add_widget(Button("Machine Management", self._machine_mgmt))
layout.add_widget(Button("Quit", self._quit)) layout.add_widget(Button("Quit", self._quit))
self.fix() self.fix()
@ -156,9 +158,9 @@ class MainView(Frame):
self.save() self.save()
raise NextScene("Arcade Management") raise NextScene("Arcade Management")
def _mech_mgmt(self): def _machine_mgmt(self):
self.save() self.save()
raise NextScene("Mech Management") raise NextScene("Machine Management")
@staticmethod @staticmethod
def _quit(): def _quit():
@ -193,7 +195,7 @@ class ManageUserView(Frame):
usr_cards = [] usr_cards = []
if state.selected_user.id != 0: if state.selected_user.id != 0:
cards = loop.run_until_complete(data.card.get_user_cards(state.selected_user.id)) cards = loop.run_until_complete(data.card.get_user_cards(state.selected_user.id))
for card in cards: for card in cards or []:
usr_cards.append(card._asdict()) usr_cards.append(card._asdict())
if len(usr_cards) > 0: if len(usr_cards) > 0:
@ -693,6 +695,65 @@ class ManageArcadeView(Frame):
self.save() self.save()
raise NextScene("Main") raise NextScene("Main")
class CreateArcadeView(Frame):
def __init__(self, screen: Screen):
super(CreateArcadeView, self).__init__(
screen,
screen.height * 2 // 3,
screen.width * 2 // 3,
hover_focus=True,
can_scroll=False,
title="Create Arcade"
)
layout = Layout([100], fill_frame=True)
self.add_layout(layout)
layout.add_widget(Text("Name:", "name"))
layout.add_widget(Text("Nickname:", "nickname"))
layout.add_widget(Text("Timezone:", "timezone"))
layout.add_widget(Text("VPN IP:", "ip"))
layout.add_widget(CheckBox("", "Add Machine:", "is_add_machine", ))
layout.add_widget(RadioButtons([
(inflection.titleize(x.name), x.value) for x in AllnetCountryCode
], "Country:", "country"))
layout3 = Layout([100])
self.add_layout(layout3)
layout3.add_widget(Text("", f"status", readonly=True, disabled=True))
layout2 = Layout([1, 1, 1, 1])
self.add_layout(layout2)
layout2.add_widget(Button("OK", self._ok), 0)
layout2.add_widget(Button("Cancel", self._cancel), 3)
self.fix()
def _ok(self):
self.save()
state.clear_last_err()
self.find_widget('status').value = state.last_err
loop.run_until_complete(self._create_arcade_async(self.data.get("name"), self.data.get("nickname"), self.data.get("country"), self.data.get('timezone'), self.data.get('ip')))
raise NextScene("Create Machine" if self.data.get("is_add_machine") else "Arcade Management")
async def _create_arcade_async(self, name: str, nickname: Optional[str], country: str, timezone: Optional[str], ip: Optional[str]):
arcade_id = await data.arcade.create_arcade(name, nickname if nickname != "" else None, country)
if timezone:
data.arcade.set_arcade_timezone(arcade_id, timezone)
if ip:
data.arcade.set_arcade_vpn_ip(arcade_id, ip)
if arcade_id:
state.set_arcade(arcade_id, country, name)
def _cancel(self):
state.clear_last_err()
self.find_widget('status').value = state.last_err
raise NextScene("Arcade Management")
class LookupArcadeView(Frame): class LookupArcadeView(Frame):
def __init__(self, screen): def __init__(self, screen):
super(LookupArcadeView, self).__init__( super(LookupArcadeView, self).__init__(
@ -800,6 +861,231 @@ class LookupArcadeView(Frame):
self.find_widget('status').value = state.last_err self.find_widget('status').value = state.last_err
raise NextScene("Arcade Management") raise NextScene("Arcade Management")
class ManageMachineView(Frame):
def __init__(self, screen: Screen):
super(ManageMachineView, self).__init__(
screen,
screen.height * 2 // 3,
screen.width * 2 // 3,
hover_focus=True,
can_scroll=False,
title="Machine Management",
on_load=self._redraw
)
layout = Layout([3])
self.add_layout(layout)
layout.add_widget(Button("Create Machine", self._create))
layout.add_widget(Button("Lookup Machine", self._lookup))
def _redraw(self):
self._layouts = [self._layouts[0]]
layout = Layout([3])
self.add_layout(layout)
layout.add_widget(Button("Reassign Machine", self._reassign, disabled=state.selected_machine.id == 0 or state.selected_machine.id is None))
layout.add_widget(Button("Edit Machine", self._edit, disabled=state.selected_machine.id == 0 or state.selected_machine.id is None))
layout.add_widget(Button("Delete Machine", self._del, disabled=state.selected_machine.id == 0 or state.selected_machine.id is None))
layout.add_widget((Divider()))
layout2 = Layout([1, 1, 1])
self.add_layout(layout2)
a = Text("", f"status", readonly=True, disabled=True)
a.value = f"Selected Machine: {state.selected_arcade}"
layout2.add_widget(a)
layout2.add_widget(Button("Back", self._back), 2)
self.fix()
def _create(self):
self.save()
raise NextScene("Create Machine")
def _lookup(self):
self.save()
raise NextScene("Lookup Machine")
def _reassign(self):
self.save()
raise NextScene("Reassign Machine")
def _edit(self):
self.save()
raise NextScene("Edit Machine")
def _del(self):
self.save()
raise NextScene("Delete Machine")
def _back(self):
self.save()
raise NextScene("Main")
class CreateMachineView(Frame):
def __init__(self, screen: Screen):
super(CreateMachineView, self).__init__(
screen,
screen.height - 10,
screen.width * 2 // 3,
hover_focus=True,
can_scroll=False,
title="Create Machine"
)
layout = Layout([100], fill_frame=True)
self.add_layout(layout)
layout.add_widget(Text("Arcade:", "arcade_id"))
layout.add_widget(Text("Serial:", "serial"))
layout.add_widget(Text("Game:", "game_id"))
layout.add_widget(CheckBox("", "Real Cabinet:", "is_cab", ))
layout.add_widget(RadioButtons([("Not Set", None)] + [
(inflection.titleize(x.name), x.value) for x in AllnetCountryCode
], "Country Override:", "country"))
layout3 = Layout([100])
self.add_layout(layout3)
layout3.add_widget(Text("", f"status", readonly=True, disabled=True))
layout2 = Layout([1, 1, 1, 1])
self.add_layout(layout2)
layout2.add_widget(Button("OK", self._ok), 0)
layout2.add_widget(Button("Cancel", self._cancel), 3)
self.fix()
def _redraw(self):
self.find_widget("arcade_id").value = state.selected_arcade.id
def _ok(self):
self.save()
state.clear_last_err()
self.find_widget('status').value = state.last_err
loop.run_until_complete(self._create_arcade_async(self.data.get("name"), self.data.get("nickname"), self.data.get("country"), self.data.get('timezone'), self.data.get('ip')))
raise NextScene("Arcade Management")
async def _create_arcade_async(self, arcade_id: int, serial: str, game: Optional[str], is_cab: bool, country: Optional[str]):
machine_id = await data.arcade.create_machine(arcade_id, serial, None, game, is_cab)
if country:
data.arcade.set_machine_country(machine_id, country)
if machine_id:
state.set_machine(machine_id, serial)
def _cancel(self):
state.clear_last_err()
self.find_widget('status').value = state.last_err
raise NextScene("Machine Management")
class LookupMachineView(Frame):
def __init__(self, screen):
super(LookupMachineView, self).__init__(
screen,
screen.height * 2 // 3,
screen.width * 2 // 3,
hover_focus=True,
can_scroll=False,
title="Lookup Machine"
)
layout = Layout([1, 1], fill_frame=True)
self.add_layout(layout)
layout.add_widget(RadioButtons([
("Name", "1"),
("Serial", "2"),
("Arcade ID", "3"),
("Machine ID", "4"),
], "Search By:", "search_type"))
layout.add_widget(Text("Search:", "search_str"), 1)
layout3 = Layout([100])
self.add_layout(layout3)
layout3.add_widget(Text("", f"status", readonly=True, disabled=True))
layout2 = Layout([1, 1, 1, 1])
self.add_layout(layout2)
layout2.add_widget(Button("Search", self._lookup), 0)
layout2.add_widget(Button("Cancel", self._cancel), 3)
self.fix()
def _lookup(self):
self.save()
if not self.data.get("search_str"):
state.set_last_err("Search cannot be blank")
self.find_widget('status').value = state.last_err
self.screen.reset()
return
state.clear_last_err()
self.find_widget('status').value = state.last_err
search_type = self.data.get("search_type")
if search_type == "1":
loop.run_until_complete(self._lookup_arcade_by_name(self.data.get("search_str")))
elif search_type == "2":
loop.run_until_complete(self._lookup_arcade_by_serial(self.data.get("search_str")))
elif search_type == "3":
real_id = int(self.data.get("search_str"), 16)
loop.run_until_complete(self._lookup_arcade_by_id(real_id))
elif search_type == "4":
loop.run_until_complete(self._lookup_arcade_by_id(self.data.get("search_str")))
else:
state.set_last_err("Unknown search type")
self.find_widget('status').value = state.last_err
self.screen.reset()
return
if len(state.search_results) < 1:
state.set_last_err("Search returned no results")
self.find_widget('status').value = state.last_err
self.screen.reset()
return
state.search_type = "user"
raise NextScene("Search Results")
async def _lookup_arcade_by_id(self, ac_id: str):
ac = await data.arcade.get_arcade(ac_id)
if ac is not None:
res = ac._asdict()
num_cabs = await data.arcade.get_arcade_machines(ac_id)
res['mech_ct'] = len(num_cabs) if num_cabs else 0
state.search_results = [res]
async def _lookup_arcade_by_name(self, name: str):
ac = await data.arcade.get_arcade_by_name(name)
if ac is not None:
res = []
for ac_res in ac:
t = ac_res._asdict()
num_cabs = await data.arcade.get_arcade_machines(t['id'])
t['mech_ct'] = len(num_cabs) if num_cabs else 0
res.append(t)
state.search_results = res
async def _lookup_arcade_by_serial(self, serial: str):
mech = await data.arcade.get_machine(serial)
if mech is not None:
ac = await data.arcade.get_arcade(mech['arcade'])
if ac is not None:
res = ac._asdict()
num_cabs = await data.arcade.get_arcade_machines(mech['arcade'])
res['mech_ct'] = len(num_cabs) if num_cabs else 0
state.search_results = [res]
def _cancel(self):
state.clear_last_err()
self.find_widget('status').value = state.last_err
raise NextScene("Machine Management")
def demo(screen:Screen, scene: Scene): def demo(screen:Screen, scene: Scene):
scenes = [ scenes = [
Scene([MainView(screen)], -1, name="Main"), Scene([MainView(screen)], -1, name="Main"),
@ -810,7 +1096,11 @@ def demo(screen:Screen, scene: Scene):
Scene([ManageCardView(screen)], -1, name="Card Management"), Scene([ManageCardView(screen)], -1, name="Card Management"),
Scene([EditUserView(screen)], -1, name="Edit User"), Scene([EditUserView(screen)], -1, name="Edit User"),
Scene([ManageArcadeView(screen)], -1, name="Arcade Management"), Scene([ManageArcadeView(screen)], -1, name="Arcade Management"),
Scene([CreateArcadeView(screen)], -1, name="Create Arcade"),
Scene([LookupArcadeView(screen)], -1, name="Lookup Arcade"), Scene([LookupArcadeView(screen)], -1, name="Lookup Arcade"),
Scene([ManageMachineView(screen)], -1, name="Machine Management"),
Scene([LookupMachineView(screen)], -1, name="Lookup Machine"),
Scene([CreateMachineView(screen)], -1, name="Create Machine"),
] ]
screen.play(scenes, stop_on_resize=False, start_scene=scene, allow_int=True) screen.play(scenes, stop_on_resize=False, start_scene=scene, allow_int=True)