Support for optional text notes on invitations

This commit is contained in:
Matthew Wild
2024-04-29 18:39:06 +01:00
parent 8c824149cc
commit 64c6548a48
4 changed files with 22 additions and 0 deletions

View File

@@ -301,6 +301,10 @@ class InvitePost(BaseForm):
default="prosody:registered", default="prosody:registered",
) )
note = wtforms.StringField(
_l("Comment (optional)"),
)
action_create_invite = wtforms.SubmitField( action_create_invite = wtforms.SubmitField(
_l("New invitation link") _l("New invitation link")
) )
@@ -382,12 +386,14 @@ async def create_invite() -> typing.Union[str, werkzeug.Response]:
group_ids=form.circles.data, group_ids=form.circles.data,
role_names=[form.role.data], role_names=[form.role.data],
ttl=form.lifetime.data, ttl=form.lifetime.data,
note=form.note.data,
) )
else: else:
invite = await client.create_account_invite( invite = await client.create_account_invite(
group_ids=form.circles.data, group_ids=form.circles.data,
role_names=[form.role.data], role_names=[form.role.data],
ttl=form.lifetime.data, ttl=form.lifetime.data,
note=form.note.data,
) )
await flash( await flash(
_("Invitation created"), _("Invitation created"),

View File

@@ -162,6 +162,7 @@ class AdminInviteInfo:
group_ids: typing.Collection[str] group_ids: typing.Collection[str]
role_names: typing.Collection[str] role_names: typing.Collection[str]
is_reset: bool is_reset: bool
note: typing.Optional[str]
@classmethod @classmethod
def from_api_response( def from_api_response(
@@ -181,6 +182,7 @@ class AdminInviteInfo:
role_names=data.get("roles", []), role_names=data.get("roles", []),
reusable=data["reusable"], reusable=data["reusable"],
is_reset=data.get("reset", False), is_reset=data.get("reset", False),
note=data.get("note"),
) )
@@ -1091,6 +1093,7 @@ class ProsodyClient:
role_names: typing.Collection[str] = [], role_names: typing.Collection[str] = [],
restrict_username: typing.Optional[str] = None, restrict_username: typing.Optional[str] = None,
ttl: typing.Optional[int] = None, ttl: typing.Optional[int] = None,
note: typing.Optional[str] = None,
session: aiohttp.ClientSession, session: aiohttp.ClientSession,
) -> AdminInviteInfo: ) -> AdminInviteInfo:
payload: typing.Dict[str, typing.Any] = {} payload: typing.Dict[str, typing.Any] = {}
@@ -1100,6 +1103,8 @@ class ProsodyClient:
payload["username"] = restrict_username payload["username"] = restrict_username
if ttl is not None: if ttl is not None:
payload["ttl"] = ttl payload["ttl"] = ttl
if note is not None:
payload["note"] = note
async with session.post( async with session.post(
self._admin_v1_endpoint("/invites/account"), self._admin_v1_endpoint("/invites/account"),
@@ -1114,6 +1119,7 @@ class ProsodyClient:
group_ids: typing.Collection[str] = [], group_ids: typing.Collection[str] = [],
role_names: typing.Collection[str] = [], role_names: typing.Collection[str] = [],
ttl: typing.Optional[int] = None, ttl: typing.Optional[int] = None,
note: typing.Optional[str] = None,
session: aiohttp.ClientSession, session: aiohttp.ClientSession,
) -> AdminInviteInfo: ) -> AdminInviteInfo:
payload: typing.Dict[str, typing.Any] = { payload: typing.Dict[str, typing.Any] = {
@@ -1122,6 +1128,8 @@ class ProsodyClient:
} }
if ttl is not None: if ttl is not None:
payload["ttl"] = ttl payload["ttl"] = ttl
if note is not None:
payload["note"] = note
async with session.post( async with session.post(
self._admin_v1_endpoint("/invites/group"), self._admin_v1_endpoint("/invites/group"),

View File

@@ -66,6 +66,12 @@
{%- call render_errors(invite_form.circles) -%}{%- endcall -%} {%- call render_errors(invite_form.circles) -%}{%- endcall -%}
</div> </div>
<!-- Comment -->
<div class="f-ebox">
{{ invite_form.note.label }}
{{ invite_form.note }}
</div>
<div class="f-bbox"> <div class="f-bbox">
{%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%} {%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%}
</div> </div>

View File

@@ -21,6 +21,7 @@
<th class="collapsible">{% trans %}Type{% endtrans %}</th> <th class="collapsible">{% trans %}Type{% endtrans %}</th>
<th class="collapsible">{% trans %}Circle{% endtrans %}</th> <th class="collapsible">{% trans %}Circle{% endtrans %}</th>
<th>{% trans %}Expires{% endtrans %}</th> <th>{% trans %}Expires{% endtrans %}</th>
<th>{% trans %}Comment{% endtrans %}</th>
<th>{% trans %}Actions{% endtrans %}</th> <th>{% trans %}Actions{% endtrans %}</th>
</tr> </tr>
</thead> </thead>
@@ -39,6 +40,7 @@
{#- -#} {#- -#}
</td> </td>
<td>{{ (invite.expires - now) | format_timedelta(add_direction=True) }}</td> <td>{{ (invite.expires - now) | format_timedelta(add_direction=True) }}</td>
<td>{% if invite.note is not none %}{{ invite.note }}{% endif %}</td>
<td class="nowrap"> <td class="nowrap">
{%- call action_button("more", url_for(".edit_invite", id_=invite.id_), class="secondary") -%} {%- call action_button("more", url_for(".edit_invite", id_=invite.id_), class="secondary") -%}
{% trans %}Show invite details{% endtrans %} {% trans %}Show invite details{% endtrans %}