diff --git a/app/assets/javascripts/conditionalRadios.js b/app/assets/javascripts/conditionalRadios.js new file mode 100644 index 000000000..bb337f984 --- /dev/null +++ b/app/assets/javascripts/conditionalRadios.js @@ -0,0 +1,25 @@ +(function(Modules) { + "use strict"; + + Modules.ConditionalRadios = function() { + + this.start = function(component) { + + const $radios = $('[type=radio]', $(component)), + showHidePanels = function() { + $radios.each(function() { + $('#panel-' + $(this).attr('value')) + .toggleClass( + 'js-hidden', + !$(this).is(":checked") + ); + }); + }; + + $radios.on('click', showHidePanels); + showHidePanels(); + + }; + }; + +})(window.GOVUK.Modules); diff --git a/app/assets/stylesheets/components/conditional-radios.scss b/app/assets/stylesheets/components/conditional-radios.scss new file mode 100644 index 000000000..c5cb2c803 --- /dev/null +++ b/app/assets/stylesheets/components/conditional-radios.scss @@ -0,0 +1,26 @@ +$border-thickness: 9px; + +.multiple-choice { + + z-index: 10; + + .block-label { + &:before { + box-shadow: 0 4px 0 0 $white; + } + } + +} + +.conditional-radios { + + &-panel { + border-left: $border-thickness solid $border-colour; + margin: 0 0 0 ($border-thickness + 6px); + padding: $gutter-one-third 0 0 ($gutter - 3px); + position: relative; + top: -$gutter-one-third; + z-index: 1; + } + +} diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss index 0d98f83f0..43edbaed5 100644 --- a/app/assets/stylesheets/main.scss +++ b/app/assets/stylesheets/main.scss @@ -58,6 +58,7 @@ $path: '/static/images/'; @import 'components/live-search'; @import 'components/stick-at-top-when-scrolling'; @import 'components/fullscreen-table'; +@import 'components/conditional-radios'; @import 'components/vendor/breadcrumbs'; @import 'components/vendor/responsive-embed'; diff --git a/app/main/forms.py b/app/main/forms.py index 0a1e36a5b..16679f7ef 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -287,6 +287,28 @@ class AdminPermissionsForm(AbstractPermissionsForm): self.view_activity.data = True +class CaseworkingPermissionsForm(AbstractPermissionsForm): + + def process(self, *args, **kwargs): + super().process(*args, **kwargs) + if self.user_type.data == 'admin': + self.view_activity.data = True + elif self.user_type.data == 'caseworker': + self.view_activity.data = False + self.manage_templates.data = False + self.manage_service.data = False + self.manage_api_keys.data = False + self.send_messages.data = True + + user_type = RadioField( + 'User type', + choices=[ + ('caseworker', 'Caseworker'), + ('admin', 'Admin'), + ], + ) + + class AbstractInviteUserForm(StripWhitespaceForm): email_address = email_address(gov_user=False) @@ -303,6 +325,10 @@ class AdminInviteUserForm(AbstractInviteUserForm, AdminPermissionsForm): pass +class CaseworkingInviteUserForm(AbstractInviteUserForm, CaseworkingPermissionsForm): + pass + + class InviteOrgUserForm(StripWhitespaceForm): email_address = email_address(gov_user=False) diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 1f3afabd4..0de8407b4 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -1,3 +1,5 @@ +from functools import partial + from flask import abort, flash, redirect, render_template, request, url_for from flask_login import current_user, login_required from notifications_python_client.errors import HTTPError @@ -12,6 +14,8 @@ from app.main import main from app.main.forms import ( AdminInviteUserForm, AdminPermissionsForm, + CaseworkingInviteUserForm, + CaseworkingPermissionsForm, SearchUsersForm, ) from app.notify_client.models import roles @@ -44,9 +48,12 @@ def manage_users(service_id): @user_has_permissions('manage_service') def invite_user(service_id): - form = AdminInviteUserForm( - invalid_email_address=current_user.email_address - ) + if 'caseworking' in current_service['permissions']: + form = CaseworkingInviteUserForm + else: + form = AdminInviteUserForm + + form = form(invalid_email_address=current_user.email_address) service_has_email_auth = 'email_auth' in current_service['permissions'] if not service_has_email_auth: @@ -82,10 +89,19 @@ def edit_user_permissions(service_id, user_id): user = user_api_client.get_user(user_id) user_has_no_mobile_number = user.mobile_number is None - form = AdminPermissionsForm( + if 'caseworking' in current_service['permissions']: + form = partial( + CaseworkingPermissionsForm, + user_type='admin' if user.has_permission_for_service(service_id, 'view_activity') else 'caseworker', + ) + else: + form = AdminPermissionsForm + + form = form( **{role: user.has_permission_for_service(service_id, role) for role in roles.keys()}, login_authentication=user.auth_type ) + if form.validate_on_submit(): user_api_client.set_user_permissions( user_id, service_id, diff --git a/app/notify_client/models.py b/app/notify_client/models.py index 54eadc9b7..bc7a6e7c3 100644 --- a/app/notify_client/models.py +++ b/app/notify_client/models.py @@ -185,7 +185,9 @@ class InvitedUser(object): return set(self.permissions) > set(permissions) def has_permission_for_service(self, service_id, permission): - return self.status != 'cancelled' and self.service == service_id and permission in self.permissions + if self.status == 'cancelled' and permission != 'view_activity': + return False + return self.service == service_id and permission in self.permissions def __eq__(self, other): return ((self.id, diff --git a/app/templates/components/radios.html b/app/templates/components/radios.html index 00be13302..f36a4647b 100644 --- a/app/templates/components/radios.html +++ b/app/templates/components/radios.html @@ -135,3 +135,9 @@ {% endmacro %} + +{% macro conditional_radio_panel(id) %} +
+ {{ caller() }} +
+{% endmacro %} diff --git a/app/templates/views/manage-users.html b/app/templates/views/manage-users.html index dc5c01503..a5ad007a5 100644 --- a/app/templates/views/manage-users.html +++ b/app/templates/views/manage-users.html @@ -63,22 +63,35 @@