Add more features to circle editor

- Manage members
- Update name

(Normally, I’d fix this up into the initial implementation
commit, but things happened in between and the rebase would be
painful.)
This commit is contained in:
Jonas Schäfer
2021-01-21 17:35:42 +01:00
parent ff870ae71e
commit e18b733017
6 changed files with 200 additions and 35 deletions

View File

@@ -272,6 +272,12 @@ async def create_circle() -> typing.Union[str, quart.Response]:
class EditCircleForm(flask_wtf.FlaskForm): # type:ignore class EditCircleForm(flask_wtf.FlaskForm): # type:ignore
name = wtforms.StringField( name = wtforms.StringField(
_l("Name"), _l("Name"),
validators=[wtforms.validators.InputRequired()],
)
user_to_add = wtforms.SelectField(
_l("Select user"),
validate_choice=False,
) )
action_save = wtforms.SubmitField( action_save = wtforms.SubmitField(
@@ -284,6 +290,10 @@ class EditCircleForm(flask_wtf.FlaskForm): # type:ignore
action_remove_user = wtforms.StringField() action_remove_user = wtforms.StringField()
action_add_user = wtforms.SubmitField(
_l("Add user")
)
@bp.route("/circle/<id_>", methods=["GET", "POST"]) @bp.route("/circle/<id_>", methods=["GET", "POST"])
@client.require_admin_session() @client.require_admin_session()
@@ -307,22 +317,51 @@ async def edit_circle(id_: str) -> typing.Union[str, quart.Response]:
for localpart in sorted(circle.members) for localpart in sorted(circle.members)
)) ))
users = await client.list_users()
form = EditCircleForm() form = EditCircleForm()
form.user_to_add.choices = sorted(
(
(u.localpart, u.localpart)
for u in users
if u.localpart not in circle.members
),
key=lambda x: x[1]
)
valid_users = [x[0] for x in form.user_to_add.choices]
invite_form = InvitePost() invite_form = InvitePost()
await invite_form.init_choices() await invite_form.init_choices()
invite_form.circles.data = [id_] invite_form.circles.data = [id_]
if request.method != "POST": if request.method != "POST":
form.name.data = circle.name form.name.data = circle.name
if form.validate_on_submit(): if form.validate_on_submit():
if form.action_save.data: if form.action_save.data:
# TODO: post update await client.update_group(
pass id_,
new_name=form.name.data,
)
elif form.action_delete.data: elif form.action_delete.data:
await client.delete_group(id_) await client.delete_group(id_)
return redirect(url_for(".circles")) return redirect(url_for(".circles"))
elif form.action_add_user.data:
if form.user_to_add.data in valid_users:
print("is valid")
await client.add_group_member(
id_,
form.user_to_add.data,
)
elif form.action_remove_user.data:
await client.remove_group_member(
id_,
form.action_remove_user.data,
)
return redirect(url_for(".edit_circle", id_=id_)) return redirect(url_for(".edit_circle", id_=id_))
else:
print(form.errors)
return await render_template( return await render_template(
"admin_edit_circle.html", "admin_edit_circle.html",

View File

@@ -108,7 +108,7 @@ class AdminGroupInfo:
return cls( return cls(
id_=data["id"], id_=data["id"],
name=data["name"], name=data["name"],
members=data["members"], members=data.get("members", []),
) )
@@ -924,7 +924,47 @@ class ProsodyClient:
new_name: typing.Optional[str] = None, new_name: typing.Optional[str] = None,
session: aiohttp.ClientSession, session: aiohttp.ClientSession,
) -> AdminGroupInfo: ) -> AdminGroupInfo:
pass payload = {}
if new_name is not None:
payload["name"] = new_name
async with session.put(
self._admin_v1_endpoint(
"/groups/{}".format(id_)
),
json=payload,
) as resp:
self._raise_error_from_response(resp)
@autosession
async def add_group_member(
self,
id_: str,
localpart: str,
*,
session: aiohttp.ClientSession,
) -> None:
async with session.put(
self._admin_v1_endpoint(
"/groups/{}/members/{}".format(id_, localpart)
),
) as resp:
self._raise_error_from_response(resp)
@autosession
async def remove_group_member(
self,
id_: str,
localpart: str,
*,
session: aiohttp.ClientSession,
) -> None:
async with session.delete(
self._admin_v1_endpoint(
"/groups/{}/members/{}".format(id_, localpart)
),
) as resp:
self._raise_error_from_response(resp)
@autosession @autosession
async def delete_group( async def delete_group(

View File

@@ -2,9 +2,10 @@
{% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button %} {% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button %}
{% block content %} {% block content %}
<h1>{% trans circle_name=(target_circle | circle_name) %}Edit circle {{ circle_name }}{% endtrans %}</h1> <h1>{% trans circle_name=(target_circle | circle_name) %}Edit circle {{ circle_name }}{% endtrans %}</h1>
<div class="form layout-expanded"><form method="POST"> <form method="POST">
{{- form.csrf_token -}}
<div class="form layout-expanded">
<h2 class="form-title">{% trans %}Circle information{% endtrans %}</h2> <h2 class="form-title">{% trans %}Circle information{% endtrans %}</h2>
{{ form.csrf_token }}
<div class="f-ebox"> <div class="f-ebox">
{{ form.name.label }} {{ form.name.label }}
{{ form.name }} {{ form.name }}
@@ -22,6 +23,7 @@
</div> </div>
</div> </div>
<h2>{% trans %}Circle members{% endtrans %}</h2> <h2>{% trans %}Circle members{% endtrans %}</h2>
{%- if circle_members -%}
<div class="el-2 elevated"><table> <div class="el-2 elevated"><table>
<thead> <thead>
<th>Login name</th> <th>Login name</th>
@@ -42,7 +44,27 @@
{%- endfor -%} {%- endfor -%}
</tbody> </tbody>
</table></div> </table></div>
</form> {%- else -%}
<p>{% trans %}This circle currently has no members.{% endtrans %}</p>
{%- endif -%}
<h3>{% trans %}Invite more members{% endtrans %}</h3> <h3>{% trans %}Invite more members{% endtrans %}</h3>
{%- if form.user_to_add.choices -%}
<div class="form layout-expanded">
<h4 class="form-title">{% trans %}Add existing user{% endtrans %}</h4>
<div class="f-ebox">
{{- form.user_to_add.label -}}
<div class="select-wrap">{{ form.user_to_add }}</div>
</div>
<div class="f-bbox">
{%- call form_button("add", form.action_add_user, class="primary") %}{% endcall -%}
</div>
</div>
{%- else -%}
<div class="box hint el-2">
<header>{% trans %}No users left{% endtrans %}</header>
<p>{% trans %}All users on this instance are already in this circle.{% endtrans %}</p>
</div>
{%- endif -%}
</form>
{%- include "admin_create_invite_form.html" -%} {%- include "admin_create_invite_form.html" -%}
{% endblock %} {% endblock %}

View File

@@ -34,7 +34,12 @@
{#- -#} {#- -#}
<ul class="inline"> <ul class="inline">
{%- for group_id in invite.group_ids -%} {%- for group_id in invite.group_ids -%}
{%- set circle_info = circle_map[group_id] -%}
{%- if circle_info -%}
<li>{{ circle_map[group_id] | circle_name }}</li> <li>{{ circle_map[group_id] | circle_name }}</li>
{%- else -%}
<li><em>{% trans %}deleted{% endtrans %}</em></li>
{%- endif -%}
{%- endfor -%} {%- endfor -%}
</ul> </ul>
{#- -#} {#- -#}

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: SnikketWeb 0.1.0\n" "Project-Id-Version: SnikketWeb 0.1.0\n"
"Report-Msgid-Bugs-To: jonas@zombofant.net\n" "Report-Msgid-Bugs-To: jonas@zombofant.net\n"
"POT-Creation-Date: 2021-01-21 17:00+0100\n" "POT-Creation-Date: 2021-01-21 17:39+0100\n"
"PO-Revision-Date: 2020-03-07 16:32+0100\n" "PO-Revision-Date: 2020-03-07 16:32+0100\n"
"Last-Translator: Jonas Schäfer <jonas@zombofant.net>\n" "Last-Translator: Jonas Schäfer <jonas@zombofant.net>\n"
"Language: de\n" "Language: de\n"
@@ -74,14 +74,22 @@ msgstr "Name"
msgid "Create circle" msgid "Create circle"
msgstr "Gemeinschaft gründen" msgstr "Gemeinschaft gründen"
#: snikket_web/admin.py:278 snikket_web/user.py:68 #: snikket_web/admin.py:279
msgid "Select user"
msgstr "Benutzer auswählen"
#: snikket_web/admin.py:284 snikket_web/user.py:68
msgid "Apply" msgid "Apply"
msgstr "Übernehmen" msgstr "Übernehmen"
#: snikket_web/admin.py:282 #: snikket_web/admin.py:288
msgid "Delete circle permanently" msgid "Delete circle permanently"
msgstr "Gemeinschaft endgültig löschen" msgstr "Gemeinschaft endgültig löschen"
#: snikket_web/admin.py:294
msgid "Add user"
msgstr "Benutzer hinzufügen"
#: snikket_web/infra.py:40 #: snikket_web/infra.py:40
msgid "Main" msgid "Main"
msgstr "Kern" msgstr "Kern"
@@ -334,7 +342,7 @@ msgid "Danger"
msgstr "Gefahr" msgstr "Gefahr"
#: snikket_web/templates/admin_delete_user.html:23 #: snikket_web/templates/admin_delete_user.html:23
#: snikket_web/templates/admin_edit_circle.html:14 #: snikket_web/templates/admin_edit_circle.html:15
#: snikket_web/templates/admin_edit_invite.html:45 #: snikket_web/templates/admin_edit_invite.html:45
#: snikket_web/templates/user_logout.html:13 #: snikket_web/templates/user_logout.html:13
#: snikket_web/templates/user_passwd.html:40 #: snikket_web/templates/user_passwd.html:40
@@ -347,33 +355,49 @@ msgstr "Zurück"
msgid "Edit circle %(circle_name)s" msgid "Edit circle %(circle_name)s"
msgstr "Gemeinschaft %(circle_name)s bearbeiten" msgstr "Gemeinschaft %(circle_name)s bearbeiten"
#: snikket_web/templates/admin_edit_circle.html:6 #: snikket_web/templates/admin_edit_circle.html:8
msgid "Circle information" msgid "Circle information"
msgstr "Gemeinschaftsinformationen" msgstr "Gemeinschaftsinformationen"
#: snikket_web/templates/admin_edit_circle.html:18 #: snikket_web/templates/admin_edit_circle.html:19
msgid "Delete circle" msgid "Delete circle"
msgstr "Gemeinschaft löschen" msgstr "Gemeinschaft löschen"
#: snikket_web/templates/admin_edit_circle.html:19 #: snikket_web/templates/admin_edit_circle.html:20
msgid "Deleting a circle does not delete any users in the circle." msgid "Deleting a circle does not delete any users in the circle."
msgstr "" msgstr ""
"Wenn eine Gemeinschaft gelöscht wird, werden die Benutzer die zu dieser " "Wenn eine Gemeinschaft gelöscht wird, werden die Benutzer die zu dieser "
"Gemeinschaft gehören nicht gelöscht." "Gemeinschaft gehören nicht gelöscht."
#: snikket_web/templates/admin_edit_circle.html:24 #: snikket_web/templates/admin_edit_circle.html:25
msgid "Circle members" msgid "Circle members"
msgstr "Mitglieder der Gemeinschaft" msgstr "Mitglieder der Gemeinschaft"
#: snikket_web/templates/admin_edit_circle.html:38 #: snikket_web/templates/admin_edit_circle.html:40
#, python-format #, python-format
msgid "Remove user %(username)s from circle" msgid "Remove user %(username)s from circle"
msgstr "Benutzer %(username)s aus der Gemeinschaft entfernen" msgstr "Benutzer %(username)s aus der Gemeinschaft entfernen"
#: snikket_web/templates/admin_edit_circle.html:46 #: snikket_web/templates/admin_edit_circle.html:48
msgid "This circle currently has no members."
msgstr "Diese Gemeinschaft hat derzeit keine Mitglieder."
#: snikket_web/templates/admin_edit_circle.html:50
msgid "Invite more members" msgid "Invite more members"
msgstr "Mehr Mitglieder einladen" msgstr "Mehr Mitglieder einladen"
#: snikket_web/templates/admin_edit_circle.html:53
msgid "Add existing user"
msgstr "Bestehenden Benuzter hinzufügen"
#: snikket_web/templates/admin_edit_circle.html:64
msgid "No users left"
msgstr "Keine Benutzer übrig"
#: snikket_web/templates/admin_edit_circle.html:65
msgid "All users on this instance are already in this circle."
msgstr "Alle Benutzer dieser Instanz sind bereits in dieser Gemeinschaft."
#: snikket_web/templates/admin_edit_invite.html:8 #: snikket_web/templates/admin_edit_invite.html:8
msgid "View invitation" msgid "View invitation"
msgstr "Einladung anzeigen" msgstr "Einladung anzeigen"
@@ -505,19 +529,23 @@ msgstr "Ja"
msgid "No" msgid "No"
msgstr "Nein" msgstr "Nein"
#: snikket_web/templates/admin_invites.html:44 #: snikket_web/templates/admin_invites.html:41
msgid "deleted"
msgstr "gelöscht"
#: snikket_web/templates/admin_invites.html:49
msgid "Show invite details" msgid "Show invite details"
msgstr "Einladungsdetails anzeigen" msgstr "Einladungsdetails anzeigen"
#: snikket_web/templates/admin_invites.html:47 #: snikket_web/templates/admin_invites.html:52
msgid "Copy invite link to clipboard" msgid "Copy invite link to clipboard"
msgstr "Einladungslink kopieren" msgstr "Einladungslink kopieren"
#: snikket_web/templates/admin_invites.html:50 #: snikket_web/templates/admin_invites.html:55
msgid "Delete invitation" msgid "Delete invitation"
msgstr "Einladung löschen" msgstr "Einladung löschen"
#: snikket_web/templates/admin_invites.html:58 #: snikket_web/templates/admin_invites.html:63
msgid "Currently, there are no pending invitations." msgid "Currently, there are no pending invitations."
msgstr "Derzeit gibt es keine ausstehenden Einladungen." msgstr "Derzeit gibt es keine ausstehenden Einladungen."

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-21 17:00+0100\n" "POT-Creation-Date: 2021-01-21 17:39+0100\n"
"PO-Revision-Date: 2020-03-07 16:50+0100\n" "PO-Revision-Date: 2020-03-07 16:50+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@@ -74,14 +74,22 @@ msgstr ""
msgid "Create circle" msgid "Create circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:278 snikket_web/user.py:68 #: snikket_web/admin.py:279
msgid "Select user"
msgstr ""
#: snikket_web/admin.py:284 snikket_web/user.py:68
msgid "Apply" msgid "Apply"
msgstr "" msgstr ""
#: snikket_web/admin.py:282 #: snikket_web/admin.py:288
msgid "Delete circle permanently" msgid "Delete circle permanently"
msgstr "" msgstr ""
#: snikket_web/admin.py:294
msgid "Add user"
msgstr ""
#: snikket_web/infra.py:40 #: snikket_web/infra.py:40
msgid "Main" msgid "Main"
msgstr "" msgstr ""
@@ -320,7 +328,7 @@ msgid "Danger"
msgstr "" msgstr ""
#: snikket_web/templates/admin_delete_user.html:23 #: snikket_web/templates/admin_delete_user.html:23
#: snikket_web/templates/admin_edit_circle.html:14 #: snikket_web/templates/admin_edit_circle.html:15
#: snikket_web/templates/admin_edit_invite.html:45 #: snikket_web/templates/admin_edit_invite.html:45
#: snikket_web/templates/user_logout.html:13 #: snikket_web/templates/user_logout.html:13
#: snikket_web/templates/user_passwd.html:40 #: snikket_web/templates/user_passwd.html:40
@@ -333,31 +341,47 @@ msgstr ""
msgid "Edit circle %(circle_name)s" msgid "Edit circle %(circle_name)s"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:6 #: snikket_web/templates/admin_edit_circle.html:8
msgid "Circle information" msgid "Circle information"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:18 #: snikket_web/templates/admin_edit_circle.html:19
msgid "Delete circle" msgid "Delete circle"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:19 #: snikket_web/templates/admin_edit_circle.html:20
msgid "Deleting a circle does not delete any users in the circle." msgid "Deleting a circle does not delete any users in the circle."
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:24 #: snikket_web/templates/admin_edit_circle.html:25
msgid "Circle members" msgid "Circle members"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:38 #: snikket_web/templates/admin_edit_circle.html:40
#, python-format #, python-format
msgid "Remove user %(username)s from circle" msgid "Remove user %(username)s from circle"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:46 #: snikket_web/templates/admin_edit_circle.html:48
msgid "This circle currently has no members."
msgstr ""
#: snikket_web/templates/admin_edit_circle.html:50
msgid "Invite more members" msgid "Invite more members"
msgstr "" msgstr ""
#: snikket_web/templates/admin_edit_circle.html:53
msgid "Add existing user"
msgstr ""
#: snikket_web/templates/admin_edit_circle.html:64
msgid "No users left"
msgstr ""
#: snikket_web/templates/admin_edit_circle.html:65
msgid "All users on this instance are already in this circle."
msgstr ""
#: snikket_web/templates/admin_edit_invite.html:8 #: snikket_web/templates/admin_edit_invite.html:8
msgid "View invitation" msgid "View invitation"
msgstr "" msgstr ""
@@ -479,19 +503,23 @@ msgstr ""
msgid "No" msgid "No"
msgstr "" msgstr ""
#: snikket_web/templates/admin_invites.html:44 #: snikket_web/templates/admin_invites.html:41
msgid "deleted"
msgstr ""
#: snikket_web/templates/admin_invites.html:49
msgid "Show invite details" msgid "Show invite details"
msgstr "" msgstr ""
#: snikket_web/templates/admin_invites.html:47 #: snikket_web/templates/admin_invites.html:52
msgid "Copy invite link to clipboard" msgid "Copy invite link to clipboard"
msgstr "" msgstr ""
#: snikket_web/templates/admin_invites.html:50 #: snikket_web/templates/admin_invites.html:55
msgid "Delete invitation" msgid "Delete invitation"
msgstr "" msgstr ""
#: snikket_web/templates/admin_invites.html:58 #: snikket_web/templates/admin_invites.html:63
msgid "Currently, there are no pending invitations." msgid "Currently, there are no pending invitations."
msgstr "" msgstr ""
@@ -665,3 +693,6 @@ msgstr ""
#~ "link." #~ "link."
#~ msgstr "" #~ msgstr ""
#~ msgid "All users on this instance have already been added."
#~ msgstr ""