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:
parent
4d2a175136
commit
79b2773852
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 %}
|
||||
|
@ -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 %}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user