Portfolio manager invite updates:

- Update the form to use BooleanFields for the permissions and make the
form more similar to the Application Members form
- Use MemberFormTemplate macro in the portfolio settings template
- fix tests affected by the form changes
This commit is contained in:
leigh-mil 2020-01-03 16:03:32 -05:00
parent 4d2a175136
commit 79b2773852
10 changed files with 106 additions and 133 deletions

View File

@ -75,10 +75,10 @@ class Portfolios(object):
permission_sets = PortfolioRoles._permission_sets_for_names(
member_data.get("permission_sets", [])
)
role = PortfolioRole(portfolio_id=portfolio.id, permission_sets=permission_sets)
role = PortfolioRole(portfolio=portfolio, permission_sets=permission_sets)
invitation = PortfolioInvitations.create(
inviter=inviter, role=role, member_data=member_data
inviter=inviter, role=role, member_data=member_data["user_data"]
)
PortfoliosQuery.add_and_commit(role)

View File

@ -1,76 +1,59 @@
from wtforms.validators import Required
from wtforms.fields import StringField, FormField, FieldList, HiddenField
from wtforms.fields import BooleanField, FormField
from atst.domain.permission_sets import PermissionSets
from .forms import BaseForm
from .member import NewForm as BaseNewMemberForm
from atst.domain.permission_sets import PermissionSets
from atst.forms.fields import SelectField
from atst.utils.localization import translate
class PermissionsForm(BaseForm):
member_name = StringField()
member_id = HiddenField()
perms_app_mgmt = SelectField(
perms_app_mgmt = BooleanField(
translate("forms.new_member.app_mgmt"),
choices=[
(
PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT,
translate("common.view"),
),
(
PermissionSets.EDIT_PORTFOLIO_APPLICATION_MANAGEMENT,
translate("common.edit"),
),
],
default=False,
description="Add, remove and edit applications in this Portfolio.",
)
perms_funding = SelectField(
perms_funding = BooleanField(
translate("forms.new_member.funding"),
choices=[
(PermissionSets.VIEW_PORTFOLIO_FUNDING, translate("common.view")),
(PermissionSets.EDIT_PORTFOLIO_FUNDING, translate("common.edit")),
],
default=False,
description="Add and Modify Task Orders to fund this Portfolio.",
)
perms_reporting = SelectField(
perms_reporting = BooleanField(
translate("forms.new_member.reporting"),
choices=[
(PermissionSets.VIEW_PORTFOLIO_REPORTS, translate("common.view")),
(PermissionSets.EDIT_PORTFOLIO_REPORTS, translate("common.edit")),
],
default=False,
description="View and export reports about this Portfolio's funding.",
)
perms_portfolio_mgmt = SelectField(
perms_portfolio_mgmt = BooleanField(
translate("forms.new_member.portfolio_mgmt"),
choices=[
(PermissionSets.VIEW_PORTFOLIO_ADMIN, translate("common.view")),
(PermissionSets.EDIT_PORTFOLIO_ADMIN, translate("common.edit")),
],
default=False,
description="Edit this Portfolio's settings.",
)
@property
def data(self):
_data = super().data
_data["permission_sets"] = []
for field in _data:
if "perms" in field:
_data["permission_sets"].append(_data[field])
_data.pop("csrf_token", None)
perm_sets = []
if _data["perms_app_mgmt"]:
perm_sets.append(PermissionSets.EDIT_PORTFOLIO_APPLICATION_MANAGEMENT)
if _data["perms_funding"]:
perm_sets.append(PermissionSets.EDIT_PORTFOLIO_FUNDING)
if _data["perms_reporting"]:
perm_sets.append(PermissionSets.EDIT_PORTFOLIO_REPORTS)
if _data["perms_portfolio_mgmt"]:
perm_sets.append(PermissionSets.EDIT_PORTFOLIO_ADMIN)
_data["permission_sets"] = perm_sets
return _data
class MembersPermissionsForm(BaseForm):
members_permissions = FieldList(FormField(PermissionsForm))
class NewForm(BaseForm):
class NewForm(PermissionsForm):
user_data = FormField(BaseNewMemberForm)
permission_sets = FormField(PermissionsForm)
@property
def update_data(self):
return {
"permission_sets": self.data.get("permission_sets").get("permission_sets"),
**self.data.get("user_data"),
}
class AssignPPOCForm(PermissionsForm):

View File

@ -77,7 +77,7 @@ def render_admin_page(portfolio, form=None):
portfolio_form=portfolio_form,
ppoc=ppoc,
members=filter_members_data(member_list),
member_form=member_forms.NewForm(),
new_manager_form=member_forms.NewForm(),
assign_ppoc_form=assign_ppoc_form,
portfolio=portfolio,
audit_events=audit_events,

View File

@ -79,7 +79,7 @@ def invite_member(portfolio_id):
if form.validate():
try:
invite = Portfolios.invite(portfolio, g.current_user, form.update_data)
invite = Portfolios.invite(portfolio, g.current_user, form.data)
send_portfolio_invitation(
invitee_email=invite.email,
inviter_name=g.current_user.full_name,

View File

@ -185,6 +185,7 @@
modal=new_member_modal_name,
),
member_form.SubmitStep(
name=new_member_modal_name,
form=member_fields.PermsFields(form=new_member_form, new=True),
submit_text="portfolios.applications.members.form.add_member"|translate,
modal=new_member_modal_name,

View File

@ -41,6 +41,7 @@
{% endmacro %}
{% macro SubmitStep(
name=name,
title=None,
form=form,
submit_text=submit_text,
@ -51,7 +52,7 @@
<input
type="submit"
class='action-group__action usa-button'
form="add-app-mem"
form="{{ name }}"
v-bind:disabled="!canSave"
value='{{ submit_text }}'>
{% endset %}

View File

@ -1,79 +1,41 @@
{% from "components/checkbox_input.html" import CheckboxInput %}
{% from "components/icon.html" import Icon %}
{% from "components/phone_input.html" import PhoneInput %}
{% from "components/text_input.html" import TextInput %}
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
{% macro SimpleOptionsInput(field) %}
<div class="usa-input">
<fieldset data-ally-disabled="true" class="usa-input__choices">
<legend>
<div class="usa-input__title-inline">
{{ field.label | striptags}}
</div>
</legend>
{{ field() }}
</fieldset>
</div>
{% endmacro %}
{% set step_one %}
<hr class="full-width">
<h1>Invite new portfolio member</h1>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(member_form.user_data.first_name, validation='requiredField', optional=False) }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(member_form.user_data.last_name, validation='requiredField', optional=False) }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(member_form.user_data.email, validation='email', optional=False) }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(member_form.user_data.phone_number, validation='usPhone') }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(member_form.user_data.dod_id, validation='dodId', optional=False) }}
</div>
<div class='form-col form-col--half'>
</div>
</div>
<div class='action-group'>
<input
type='button'
v-on:click="next()"
v-bind:disabled="!canSave"
class='action-group__action usa-button usa-button-primary'
value='Next'>
<a class='action-group__action' v-on:click="closeModal('{{ new_port_mem }}')">Cancel</a>
</div>
{% endset %}
{% set step_two %}
<hr class="full-width">
<h1>Assign member permissions</h1>
{% macro PermsFields(form, member_role_id=None) %}
<h2>Assign member permissions</h2>
<a class='icon-link'>
{{ Icon('info') }}
{{ "portfolios.admin.permissions_info" | translate }}
</a>
{{ SimpleOptionsInput(member_form.permission_sets.perms_app_mgmt) }}
{{ SimpleOptionsInput(member_form.permission_sets.perms_funding) }}
{{ SimpleOptionsInput(member_form.permission_sets.perms_reporting) }}
{{ SimpleOptionsInput(member_form.permission_sets.perms_portfolio_mgmt) }}
<div class='action-group'>
<input
type="submit"
class='action-group__action usa-button usa-button-primary'
form="add-port-mem"
value='Invite member'>
<a class='action-group__action' v-on:click="closeModal('{{ new_port_mem }}')">Cancel</a>
<div class="application-perms">
{% if new %}
{% set app_mgmt = form.perms_app_mgmt.name %}
{% set funding = form.perms_funding.name %}
{% set reporting = form.perms_reporting.name %}
{% set portfolio_mgmt = form.perms_portfolio_mgmt.name %}
{% else %}
{% set app_mgmt = "perms_app_mgmt-{}".format(member_role_id) %}
{% set funding = "perms_funding-{}".format(member_role_id) %}
{% set reporting = "perms_reporting-{}".format(member_role_id) %}
{% set portfolio_mgmt = "perms_portfolio_mgmt-{}".format(member_role_id) %}
{% endif %}
{{ CheckboxInput(form.perms_app_mgmt, classes="input__inline-fields", key=app_mgmt, id=app_mgmt, optional=True) }}
{{ CheckboxInput(form.perms_funding, classes="input__inline-fields", key=funding, id=funding, optional=True) }}
{{ CheckboxInput(form.perms_reporting, classes="input__inline-fields", key=reporting, id=reporting, optional=True) }}
{{ CheckboxInput(form.perms_portfolio_mgmt, classes="input__inline-fields", key=portfolio_mgmt, id=portfolio_mgmt, optional=True) }}
</div>
{% endset %}
{{ MultiStepModalForm(
'add-port-mem',
member_form,
url_for("portfolios.invite_member", portfolio_id=portfolio.id),
[step_one, step_two],
) }}
{% endmacro %}
{% macro InfoFields(member_form) %}
<div class="application-member__user-info">
{{ TextInput(member_form.first_name, validation='requiredField', optional=False) }}
{{ TextInput(member_form.last_name, validation='requiredField', optional=False) }}
{{ TextInput(member_form.email, validation='email', optional=False) }}
{{ PhoneInput(member_form.phone_number, member_form.phone_ext)}}
{{ TextInput(member_form.dod_id, validation='dodId', optional=False) }}
<a href="#">How do I find the DoD ID?</a>
</div>
{% endmacro %}

View File

@ -1,7 +1,10 @@
{% from "components/icon.html" import Icon %}
{% from 'components/save_button.html' import SaveButton %}
{% from "components/modal.html" import Modal %}
{% from "components/alert.html" import Alert %}
{% from "components/icon.html" import Icon %}
{% import "components/member_form_template.html" as member_form %}
{% from "components/modal.html" import Modal %}
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
{% from 'components/save_button.html' import SaveButton %}
{% import "portfolios/fragments/add_new_portfolio_member.html" as member_form_fields %}
<h3>Portfolio Managers</h3>
<div class="panel">
@ -43,7 +46,30 @@
</section>
{% if user_can(permissions.CREATE_PORTFOLIO_USERS) %}
<a href="#" class="usa-button usa-button-secondary add-new-button">Add Portfolio Manager</a>
{% include "portfolios/fragments/add_new_portfolio_member.html" %}
{% set new_manager_modal = "add-portfolio-manager" %}
<a class="usa-button usa-button-secondary add-new-button" v-on:click="openModal('{{ new_manager_modal }}')">
Add Portfolio Manager
</a>
{{ MultiStepModalForm(
name=new_manager_modal,
form=new_manager_form,
form_action=url_for("portfolios.invite_member", portfolio_id=portfolio.id),
steps=[
member_form.BasicStep(
title="Add Manager",
form=member_form_fields.InfoFields(new_manager_form.user_data),
next_button_text="Next: Permissions",
previous=False,
modal=new_manager_modal_name,
),
member_form.SubmitStep(
name=new_manager_modal,
form=member_form_fields.PermsFields(new_manager_form),
submit_text="Invite member",
modal=new_manager_modal_name,
)
],
) }}
{% endif %}
</div>

View File

@ -205,7 +205,7 @@ def test_invite():
inviter = UserFactory.create()
member_data = UserFactory.dictionary()
invitation = Portfolios.invite(portfolio, inviter, member_data)
invitation = Portfolios.invite(portfolio, inviter, {"user_data": member_data})
assert invitation.role
assert invitation.role.portfolio == portfolio

View File

@ -269,10 +269,10 @@ def test_existing_member_invite_resent_to_email_submitted_in_form(
_DEFAULT_PERMS_FORM_DATA = {
"permission_sets-perms_app_mgmt": PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT,
"permission_sets-perms_funding": PermissionSets.VIEW_PORTFOLIO_FUNDING,
"permission_sets-perms_reporting": PermissionSets.VIEW_PORTFOLIO_REPORTS,
"permission_sets-perms_portfolio_mgmt": PermissionSets.VIEW_PORTFOLIO_ADMIN,
"permission_sets-perms_app_mgmt": False,
"permission_sets-perms_funding": False,
"permission_sets-perms_reporting": False,
"permission_sets-perms_portfolio_mgmt": False,
}