diff --git a/snikket_web/admin.py b/snikket_web/admin.py index 083cdb1..0f22054 100644 --- a/snikket_web/admin.py +++ b/snikket_web/admin.py @@ -284,12 +284,21 @@ class InvitePost(BaseForm): type_ = wtforms.RadioField( _l("Invitation type"), choices=[ - ("account", _l("Individual (for one person)")), - ("group", _l("Group (for multiple people)")), + ("account", _l("Individual")), + ("group", _l("Group")), ], default="account", ) + role = wtforms.RadioField( + _l("Access Level"), + choices=[ + ("prosody:restricted", _l("Limited")), + ("prosody:registered", _l("Normal user")), + ("prosody:admin", _l("Administrator")), + ], + ) + action_create_invite = wtforms.SubmitField( _l("New invitation link") ) @@ -369,11 +378,13 @@ async def create_invite() -> typing.Union[str, werkzeug.Response]: if form.type_.data == "group": invite = await client.create_group_invite( group_ids=form.circles.data, + role_names=[form.role.data], ttl=form.lifetime.data, ) else: invite = await client.create_account_invite( group_ids=form.circles.data, + role_names=[form.role.data], ttl=form.lifetime.data, ) await flash( diff --git a/snikket_web/prosodyclient.py b/snikket_web/prosodyclient.py index 5c55c0e..2f9b6d1 100644 --- a/snikket_web/prosodyclient.py +++ b/snikket_web/prosodyclient.py @@ -160,6 +160,7 @@ class AdminInviteInfo: expires: datetime reusable: bool group_ids: typing.Collection[str] + role_names: typing.Collection[str] is_reset: bool @classmethod @@ -177,6 +178,7 @@ class AdminInviteInfo: xmpp_uri=data.get("xmpp_uri"), landing_page=data.get("landing_page"), group_ids=data.get("groups", []), + role_names=data.get("roles", []), reusable=data["reusable"], is_reset=data.get("reset", False), ) @@ -1086,12 +1088,14 @@ class ProsodyClient: self, *, group_ids: typing.Collection[str] = [], + role_names: typing.Collection[str] = [], restrict_username: typing.Optional[str] = None, ttl: typing.Optional[int] = None, session: aiohttp.ClientSession, ) -> AdminInviteInfo: payload: typing.Dict[str, typing.Any] = {} payload["groups"] = list(group_ids) + payload["roles"] = list(role_names) if restrict_username is not None: payload["username"] = restrict_username if ttl is not None: @@ -1108,11 +1112,13 @@ class ProsodyClient: self, *, group_ids: typing.Collection[str] = [], + role_names: typing.Collection[str] = [], ttl: typing.Optional[int] = None, session: aiohttp.ClientSession, ) -> AdminInviteInfo: payload: typing.Dict[str, typing.Any] = { "groups": list(group_ids), + "roles": list(role_names), } if ttl is not None: payload["ttl"] = ttl diff --git a/snikket_web/scss/app.scss b/snikket_web/scss/app.scss index 016b434..22c89b2 100644 --- a/snikket_web/scss/app.scss +++ b/snikket_web/scss/app.scss @@ -259,6 +259,13 @@ div.form.layout-expanded { margin: 0; } + fieldset.descriptive-radio-selection { + p { + margin-top: 0; + margin-bottom: $w-s2; + } + } + input[type="radio"] + label, input[type="checkbox"] + label { font-weight: inherit; color: inherit; @@ -363,6 +370,10 @@ div.form.layout-expanded { margin-left: 0.25em; } + .radio-button-ext { + margin-left: 0.5rem; + } + div.select-wrap { display: block; border-bottom: $w-s4 solid $primary-500; diff --git a/snikket_web/static/img/icons.svg b/snikket_web/static/img/icons.svg index 7b5fbf8..f2a0c88 100644 --- a/snikket_web/static/img/icons.svg +++ b/snikket_web/static/img/icons.svg @@ -148,6 +148,11 @@ licensed under the terms of the Apache 2.0 License --> + + + + + diff --git a/snikket_web/templates/admin_create_invite_form.html b/snikket_web/templates/admin_create_invite_form.html index acda7ec..f4c4144 100644 --- a/snikket_web/templates/admin_create_invite_form.html +++ b/snikket_web/templates/admin_create_invite_form.html @@ -1,20 +1,57 @@ -{% from "library.j2" import form_button, render_errors %} +{% from "library.j2" import form_button, + render_errors, + access_level_description, access_level_icon, + invite_type_description, invite_type_icon +%} {{- invite_form.csrf_token -}} {% trans %}Create new invitation{% endtrans %} {% trans %}Create a new invitation link to invite more users to your Snikket service by clicking the button below.{% endtrans %} + + - {#- -#} + {#- -#} {{ invite_form.type_.label.text }} - {% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %} - {{- invite_form.type_ -}} + {% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %} + + {%- for invite_type in invite_form.type_ -%} + + {{ invite_type }} + {%- trans title=invite_type.label.text, icon=invite_type_icon(invite_type.data), description=invite_type_description(invite_type.data) -%} + {{ title }}{{ icon }}{{ description }} + {%- endtrans -%} + + + {%- endfor -%} + + + + {#- -#} + {{ invite_form.role.label.text }} + {% trans %}The access level of a user determines what interactions are allowed for them on your Snikket service.{% endtrans %} + {%- for level in invite_form.role -%} + + {{ level }} + {%- trans title=level.label.text, icon=access_level_icon(level.data), description=access_level_description(level.data) -%} + {{ title }}{{ icon }}{{ description }} + {%- endtrans -%} + + + {%- endfor -%} + + + + + {{ invite_form.lifetime.label }} {{ invite_form.lifetime }} + + {# NOTE: This is for when/if we ever support multi-group invites. @@ -28,6 +65,7 @@ {{ invite_form.circles }} {%- call render_errors(invite_form.circles) -%}{%- endcall -%} + {%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%} diff --git a/snikket_web/templates/admin_edit_user.html b/snikket_web/templates/admin_edit_user.html index a5ac5e3..387cdba 100644 --- a/snikket_web/templates/admin_edit_user.html +++ b/snikket_web/templates/admin_edit_user.html @@ -1,21 +1,5 @@ {% extends "admin_app.html" %} -{% from "library.j2" import box, form_button, standard_button, icon %} -{% macro access_level_description(role, caller=None) %} -{%- if role == "prosody:restricted" -%} -{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %} -{%- elif role == "prosody:registered" -%} -{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %} -{%- elif role == "prosody:admin" -%} -{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %} -{%- endif -%} -{% endmacro %} -{% macro access_level_icon(role, caller=None) %} -{%- if role == "prosody:restricted" -%} -{% call icon("lock") %}{% endcall %} -{%- elif role == "prosody:admin" -%} -{% call icon("admin") %}{% endcall %} -{%- endif -%} -{% endmacro %} +{% from "library.j2" import box, form_button, standard_button, icon, access_level_description, access_level_icon %} {% block content %} {% trans user_name=target_user.localpart %}Edit user {{ user_name }}{% endtrans %} {{ form.csrf_token }} diff --git a/snikket_web/templates/library.j2 b/snikket_web/templates/library.j2 index 9e5c660..76bcda7 100644 --- a/snikket_web/templates/library.j2 +++ b/snikket_web/templates/library.j2 @@ -147,3 +147,37 @@ {% trans %}Can be used once to create an account on this Snikket service.{% endtrans %} {%- endif -%} {%- endmacro -%} + +{% macro access_level_description(role, caller=None) %} +{%- if role == "prosody:restricted" -%} +{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %} +{%- elif role == "prosody:registered" -%} +{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %} +{%- elif role == "prosody:admin" -%} +{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %} +{%- endif -%} +{% endmacro %} + +{% macro access_level_icon(role, caller=None) %} +{%- if role == "prosody:restricted" -%} +{% call icon("lock") %}{% endcall %} +{%- elif role == "prosody:admin" -%} +{% call icon("admin") %}{% endcall %} +{%- endif -%} +{% endmacro %} + +{% macro invite_type_description(invite_type, caller=None) %} +{%- if invite_type == "account" -%} +{% trans %}Invite a single person (invitation link can only be used once).{% endtrans %} +{%- elif invite_type == "group" -%} +{% trans %}Invite a group of people (invitation link can be used multiple times).{% endtrans %} +{%- endif -%} +{% endmacro %} + +{% macro invite_type_icon(invite_type, caller=None) %} +{%- if invite_type == "account" -%} +{% call icon("person") %}{% endcall %} +{%- elif invite_type == "group" -%} +{% call icon("people") %}{% endcall %} +{%- endif -%} +{% endmacro %} diff --git a/tools/icons.list b/tools/icons.list index 803448e..a17999e 100644 --- a/tools/icons.list +++ b/tools/icons.list @@ -27,6 +27,7 @@ navigation/cancel:cancel navigation/more_vert:more social/groups:groups social/people:people +social/person:person social/group_add:create_group social/person_add:add_user social/person_remove:remove_user
{% trans %}Create a new invitation link to invite more users to your Snikket service by clicking the button below.{% endtrans %}
{% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %}
{{ description }}
{% trans %}The access level of a user determines what interactions are allowed for them on your Snikket service.{% endtrans %}