diff --git a/ceo/tui/Model.py b/ceo/tui/Model.py index 741e179..ee8d5cc 100644 --- a/ceo/tui/Model.py +++ b/ceo/tui/Model.py @@ -51,6 +51,10 @@ class Model: 'GetGroup': { 'cn': '', }, + 'AddMemberToGroup': { + 'cn': '', + 'uid': '', + }, } self.viewdata = deepcopy(self._initial_viewdata) # data which is shared between multiple views diff --git a/ceo/tui/ResultView.py b/ceo/tui/ResultView.py index f9ac12f..dcbf163 100644 --- a/ceo/tui/ResultView.py +++ b/ceo/tui/ResultView.py @@ -45,7 +45,11 @@ class ResultView(CeoFrame): resp = self._model.resp if resp.status_code != 200: self._add_text('An error occurred:') - self._add_text(resp.text.rstrip()) + if resp.headers.get('content-type') == 'application/json': + err_msg = resp.json()['error'] + else: + err_msg = resp.text.rstrip() + self._add_text(err_msg) else: self.show_result(resp) # fill the rest of the space diff --git a/ceo/tui/TUIStreamResponseHandler.py b/ceo/tui/TUIStreamResponseHandler.py index 1c83f21..0c1bae4 100644 --- a/ceo/tui/TUIStreamResponseHandler.py +++ b/ceo/tui/TUIStreamResponseHandler.py @@ -31,7 +31,7 @@ class TUIStreamResponseHandler(StreamResponseHandler): self.txn_view.fix() self.screen.force_update() - def _show_msg(self, msg: str = ''): + def _show_msg(self, msg: str = '\n'): for line in msg.splitlines(): self.msg_layout.add_widget(Label(line, align='^')) @@ -43,7 +43,11 @@ class TUIStreamResponseHandler(StreamResponseHandler): def handle_non_200(self, resp: requests.Response): self._abort() self._show_msg('An error occurred:') - self._show_msg(resp.text) + if resp.headers.get('content-type') == 'application/json': + err_msg = resp.json()['error'] + else: + err_msg = resp.text + self._show_msg(err_msg) self._update() def begin(self): @@ -52,8 +56,9 @@ class TUIStreamResponseHandler(StreamResponseHandler): def handle_aborted(self, err_msg: str): self._abort() self._show_msg('The transaction was rolled back.') - self._show_msg('The error was:') + self._show_msg('The error was:\n') self._show_msg(err_msg) + self._show_msg() self._show_msg('Please check the ceod logs.') self._update() diff --git a/ceo/tui/WelcomeView.py b/ceo/tui/WelcomeView.py index 498d3ae..131f444 100644 --- a/ceo/tui/WelcomeView.py +++ b/ceo/tui/WelcomeView.py @@ -1,6 +1,6 @@ import functools -from asciimatics.widgets import Frame, ListBox, Layout, Divider, Button +from asciimatics.widgets import Frame, ListBox, Layout, Divider, Button, Label from asciimatics.exceptions import NextScene, StopApplication @@ -60,6 +60,7 @@ class WelcomeView(Frame): layout = Layout([100]) self.add_layout(layout) + layout.add_widget(Label('Press to switch widgets')) layout.add_widget(Divider()) layout = Layout([1, 1, 1]) diff --git a/ceo/tui/groups/AddMemberToGroupView.py b/ceo/tui/groups/AddMemberToGroupView.py new file mode 100644 index 0000000..9d1c404 --- /dev/null +++ b/ceo/tui/groups/AddMemberToGroupView.py @@ -0,0 +1,43 @@ +from asciimatics.widgets import Layout, Text, CheckBox, Label + +from ...utils import defer, http_post +from ..CeoFrame import CeoFrame +from ceod.transactions.groups import AddMemberToGroupTransaction + + +class AddMemberToGroupView(CeoFrame): + def __init__(self, screen, width, height, model): + super().__init__( + screen, height, width, model, 'AddMemberToGroup', + save_data=True, + ) + layout = Layout([100], fill_frame=True) + self.add_layout(layout) + self._cn = Text('Group name:', 'cn') + layout.add_widget(self._cn) + self._username = Text('Username:', 'uid') + layout.add_widget(self._username) + layout.add_widget(Label('')) + self._checkbox = CheckBox('subscribe to auxiliary mailing lists') + self._checkbox.value = True + layout.add_widget(self._checkbox) + + self.add_buttons( + back_btn=True, + next_scene='Confirm', on_next=self._next) + self.fix() + + def _next(self): + cn = self._cn.value + uid = self._username.value + self._model.confirm_lines = [ + f'Are you sure you want to add {uid} to {cn}?', + ] + operations = AddMemberToGroupTransaction.operations + url = f'/api/groups/{cn}/members/{uid}' + # TODO: deduplicate this logic from the CLI + if not self._checkbox.value: + url += '?subscribe_to_lists=false' + operations.remove('subscribe_user_to_auxiliary_mailing_lists') + self._model.deferred_req = defer(http_post, url) + self._model.operations = operations diff --git a/ceo/tui/groups/__init__.py b/ceo/tui/groups/__init__.py index 633f866..e69de29 100644 --- a/ceo/tui/groups/__init__.py +++ b/ceo/tui/groups/__init__.py @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- - diff --git a/ceo/tui/start.py b/ceo/tui/start.py index f3b3d33..a3e6820 100644 --- a/ceo/tui/start.py +++ b/ceo/tui/start.py @@ -12,6 +12,7 @@ from .ResultView import ResultView from .TransactionView import TransactionView from .WelcomeView import WelcomeView from .groups.AddGroupView import AddGroupView +from .groups.AddMemberToGroupView import AddMemberToGroupView from .groups.GetGroupView import GetGroupView from .groups.GetGroupResultView import GetGroupResultView from .members.AddUserView import AddUserView @@ -61,6 +62,7 @@ def screen_wrapper(screen, last_scene, model): ('AddGroup', AddGroupView(screen, width, height, model)), ('GetGroup', GetGroupView(screen, width, height, model)), ('GetGroupResult', GetGroupResultView(screen, width, height, model)), + ('AddMemberToGroup', AddMemberToGroupView(screen, width, height, model)), ] scenes = [ Scene([view], -1, name=name) for name, view in views diff --git a/ceod/transactions/groups/AddMemberToGroupTransaction.py b/ceod/transactions/groups/AddMemberToGroupTransaction.py index d8a739b..1a310c8 100644 --- a/ceod/transactions/groups/AddMemberToGroupTransaction.py +++ b/ceod/transactions/groups/AddMemberToGroupTransaction.py @@ -69,9 +69,9 @@ class AddMemberToGroupTransaction(AbstractTransaction): yield 'subscribe_user_to_auxiliary_mailing_lists' except KeyError: pass - except Exception: + except Exception as err: logger.error(traceback.format_exc()) - yield 'failed_to_subscribe_user_to_auxiliary_mailing_lists' + yield 'failed_to_subscribe_user_to_auxiliary_mailing_lists: ' + str(err) result = { 'added_to_groups': [self.group_name] + [