From ebaeeaaf135c55cc4d3c3092e12687310a325089 Mon Sep 17 00:00:00 2001 From: Max Erenberg Date: Tue, 7 Sep 2021 04:16:29 +0000 Subject: [PATCH] implement ChanageLoginShellView and SetForwardingAddressesView --- ceo/tui/Model.py | 8 ++ ceo/tui/WelcomeView.py | 3 +- ceo/tui/members/ChangeLoginShellView.py | 71 +++++++++++++++++ ceo/tui/members/SetForwardingAddressesView.py | 76 +++++++++++++++++++ ceo/tui/start.py | 4 + 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 ceo/tui/members/ChangeLoginShellView.py create mode 100644 ceo/tui/members/SetForwardingAddressesView.py diff --git a/ceo/tui/Model.py b/ceo/tui/Model.py index 8eac187..9265e4b 100644 --- a/ceo/tui/Model.py +++ b/ceo/tui/Model.py @@ -36,6 +36,14 @@ class Model: 'ResetPassword': { 'uid': '', }, + 'ChangeLoginShell': { + 'uid': '', + 'login_shell': '', + }, + 'SetForwardingAddresses': { + 'uid': '', + 'forwarding_addresses': [''], + }, } self.viewdata = deepcopy(self._initial_viewdata) # data which is shared between multiple views diff --git a/ceo/tui/WelcomeView.py b/ceo/tui/WelcomeView.py index ba57b1d..f2f1b72 100644 --- a/ceo/tui/WelcomeView.py +++ b/ceo/tui/WelcomeView.py @@ -20,7 +20,8 @@ class WelcomeView(Frame): ('Renew club rep', 'RenewUser'), ('Get user info', 'GetUser'), ('Reset password', 'ResetPassword'), - ('Modify user', 'ModifyUser'), + ('Change login shell', 'ChangeLoginShell'), + ('Set forwarding addresses', 'SetForwardingAddresses'), ] self._members_menu = ListBox( Widget.FILL_FRAME, diff --git a/ceo/tui/members/ChangeLoginShellView.py b/ceo/tui/members/ChangeLoginShellView.py new file mode 100644 index 0000000..ab3d722 --- /dev/null +++ b/ceo/tui/members/ChangeLoginShellView.py @@ -0,0 +1,71 @@ +from threading import Thread + +from asciimatics.widgets import Layout, Text + +from ...utils import defer, http_patch, http_get +from ..CeoFrame import CeoFrame + + +class ChangeLoginShellView(CeoFrame): + def __init__(self, screen, width, height, model): + super().__init__( + screen, height, width, model, 'ChangeLoginShell', + save_data=True, + ) + self._username_changed = False + + layout = Layout([100], fill_frame=True) + self.add_layout(layout) + self._username = Text( + "Username:", "uid", + on_change=self._on_username_change, + on_blur=self._on_username_blur, + ) + layout.add_widget(self._username) + self._login_shell = Text('Login shell:', 'login_shell') + layout.add_widget(self._login_shell) + + self.add_flash_message_layout() + self.add_buttons( + back_btn=True, + next_scene='Confirm', on_next=self._next) + self.fix() + + # TODO: deduplicate this from AddUserView + def _on_username_change(self): + self._username_changed = True + + def _on_username_blur(self): + if not self._username_changed: + return + self._username_changed = False + username = self._username.value + if username == '': + return + Thread(target=self._get_user_info, args=[username]).start() + + def _get_user_info(self, username): + self.flash_message('Looking up user...') + try: + resp = http_get('/api/members/' + username) + if resp.status_code != 200: + return + data = resp.json() + self._login_shell.value = data['login_shell'] + finally: + self.clear_flash_message() + + def _next(self): + uid = self._username.value + login_shell = self._login_shell.value + body = {'login_shell': login_shell} + self._model.deferred_req = defer( + http_patch, f'/api/members/{uid}', json=body) + self._model.confirm_lines = [ + f"{uid}'s login shell will be changed to:", + '', + login_shell, + '', + 'Are you sure you want to continue?', + ] + self._model.operations = ['replace_login_shell'] diff --git a/ceo/tui/members/SetForwardingAddressesView.py b/ceo/tui/members/SetForwardingAddressesView.py new file mode 100644 index 0000000..1e622c7 --- /dev/null +++ b/ceo/tui/members/SetForwardingAddressesView.py @@ -0,0 +1,76 @@ +from threading import Thread + +from asciimatics.widgets import Layout, Label, Text, TextBox, Widget + +from ...utils import defer, http_patch, http_get +from ..CeoFrame import CeoFrame + + +class SetForwardingAddressesView(CeoFrame): + def __init__(self, screen, width, height, model): + super().__init__( + screen, height, width, model, 'SetForwardingAddresses', + save_data=True, + ) + self._username_changed = False + + layout = Layout([100], fill_frame=True) + self.add_layout(layout) + self._username = Text( + "Username:", "uid", + on_change=self._on_username_change, + on_blur=self._on_username_blur, + ) + layout.add_widget(self._username) + self._forwarding_addresses = TextBox( + Widget.FILL_FRAME, 'Forwarding addresses:', 'forwarding_addresses', + line_wrap=True) + layout.add_widget(self._forwarding_addresses) + layout.add_widget(Label('Press to switch widgets')) + + self.add_flash_message_layout() + self.add_buttons( + back_btn=True, + next_scene='Confirm', on_next=self._next) + self.fix() + + # TODO: deduplicate this from AddUserView + def _on_username_change(self): + self._username_changed = True + + def _on_username_blur(self): + if not self._username_changed: + return + self._username_changed = False + username = self._username.value + if username == '': + return + Thread(target=self._get_user_info, args=[username]).start() + + def _get_user_info(self, username): + self.flash_message('Looking up user...') + try: + resp = http_get('/api/members/' + username) + if resp.status_code != 200: + return + data = resp.json() + if 'forwarding_addresses' not in data: + return + self._forwarding_addresses.value = data['forwarding_addresses'] + finally: + self.clear_flash_message() + + def _next(self): + uid = self._username.value + forwarding_addresses = self._forwarding_addresses.value + body = {'forwarding_addresses': forwarding_addresses} + self._model.deferred_req = defer( + http_patch, f'/api/members/{uid}', json=body) + self._model.confirm_lines = [ + f"{uid}'s forwarding addresses will be set to:", + '', + *forwarding_addresses, + '', + 'Are you sure you want to continue?', + ] + self._model.operations = ['replace_forwarding_addresses'] diff --git a/ceo/tui/start.py b/ceo/tui/start.py index c5cd3a8..7009dab 100644 --- a/ceo/tui/start.py +++ b/ceo/tui/start.py @@ -12,11 +12,13 @@ from .ResultView import ResultView from .TransactionView import TransactionView from .WelcomeView import WelcomeView from .members.AddUserView import AddUserView +from .members.ChangeLoginShellView import ChangeLoginShellView from .members.GetUserView import GetUserView from .members.GetUserResultView import GetUserResultView from .members.RenewUserView import RenewUserView from .members.ResetPasswordView import ResetPasswordView from .members.ResetPasswordResultView import ResetPasswordResultView +from .members.SetForwardingAddressesView import SetForwardingAddressesView def unhandled(event): @@ -51,6 +53,8 @@ def screen_wrapper(screen, last_scene, model): ('GetUserResult', GetUserResultView(screen, width, height, model)), ('ResetPassword', ResetPasswordView(screen, width, height, model)), ('ResetPasswordResult', ResetPasswordResultView(screen, width, height, model)), + ('ChangeLoginShell', ChangeLoginShellView(screen, width, height, model)), + ('SetForwardingAddresses', SetForwardingAddressesView(screen, width, height, model)), ] scenes = [ Scene([view], -1, name=name) for name, view in views