Add new application members to an empty application.

The link button to add a new application member to an app that did not
have any ("empty state")  was not wired up. This:

- Moves the two steps of the new member modal into macros so that they
  can be reused with different button/link types
- Wires the "invite a new team member" button on the application team
  page
- Makes a minor CSS tweak so that icons nested under `.empty-state` in
  the modal aren't enormous
This commit is contained in:
dandds 2019-05-07 06:39:00 -04:00
parent fb7efc6057
commit f974dab330
4 changed files with 162 additions and 138 deletions

View File

@ -10,7 +10,7 @@
padding: 8rem ($gap * 4) 0; padding: 8rem ($gap * 4) 0;
} }
.icon { > .icon {
@include icon-size(50); @include icon-size(50);
@include icon-color($color-gray-light); @include icon-color($color-gray-light);
} }

View File

@ -1,136 +1,15 @@
{% from "components/icon.html" import Icon %}
{% from "components/text_input.html" import TextInput %}
{% from "components/checkbox_input.html" import CheckboxInput %}
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %} {% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
{% set step_one %} {% import "fragments/applications/new_member_modal_content.html" as member_steps %}
<div class="modal__form--header">
<h1>Invite new member</h1>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.first_name, validation='requiredField') }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.last_name, validation='requiredField') }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.email, validation='email') }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.phone_number, validation='usPhone', optional=True) }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.dod_id, validation='dodId') }}
</div>
<div class='form-col form-col--half'>
</div>
</div>
<div class='action-group'>
<input
type='button'
v-on:click="next()"
v-bind:disabled="invalid"
class='action-group__action usa-button'
value='Next'>
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('{{ new_port_mem }}')">{{ "common.cancel" | translate }}</a>
</div>
{% endset %}
{% set step_two %}
<div class="modal__form">
<div class="modal__form--header">
<h1>{{ "portfolios.applications.members.new.assign_roles" | translate }}</h1>
<a class='icon-link'>
{{ Icon('info') }}
{{ "portfolios.applications.members.new.learn_more" | translate }}
</a>
<div class="environment-roles-new">
<div class="form-row">
<div class="form-col form-col--quarter">
<span class="environment-roles-new__head">
{{ "common.resource_names.environments" | translate }}:
</span>
</div>
<div class="form-col form-col--three-quarters">
<span class="environment-roles-new__head">
{{ "common.choose_role" | translate }}:
</span>
</div>
</div>
{% for environment_data in new_member_form.environment_roles %}
<optionsinput inline-template
v-bind:initial-value="'{{ environment_data.role.data | string }}'"
>
<div class="usa-input">
<fieldset data-ally-disabled="true" class="usa-input__choices">
<div class="form-row">
<div class="form-col form-col--quarter">
<legend>
<div v-bind:class='["usa-input__title-inline", {"environment-name--gray": value === "None" }]'>
{{ environment_data.environment_name.data }}
</div>
</legend>
</div>
<div class="form-col form-col--three-quarters">
{{ environment_data.role(**{"v-model": "value"}) }}
</div>
</div>
</fieldset>
</div>
</optionsinput>
{{ environment_data.environment_id() }}
{% endfor %}
</div>
<h1>{{ "portfolios.applications.members.new.manage_perms" | translate({"application_name": application.name}) }}</h1>
{{ CheckboxInput(new_member_form.permission_sets.perms_team_mgmt, classes="input__inline-fields") }}
{% call CheckboxInput(new_member_form.permission_sets.perms_env_mgmt, classes="input__inline-fields") %}
{% set field=new_member_form.permission_sets.perms_del_env %}
<nestedcheckboxinput
name='{{ field.name }}'
inline-template
key='{{ field.name }}'
v-bind:is-parent-checked="isChecked"
>
<div class="usa-input input__inline-fields input__inline-fields--indented">
<fieldset data-ally-disabled="true" class="usa-input__choices usa-input__choices--inline">
<legend>
<input
id="permission_sets-perms_del_env"
name="permission_sets-perms_del_env"
type="checkbox"
v-model="isChecked"
v-bind:disabled="!$parent.isChecked">
{{ field.label | safe }}
</legend>
</fieldset>
</div>
</checkboxinput>
{% endcall %}
</div>
<div class='action-group'>
<input
type="submit"
class='action-group__action usa-button'
form="add-app-mem"
value='Invite member'>
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('{{ new_port_mem }}')">{{ "common.cancel" | translate }}</a>
<input
type='button'
v-on:click="previous()"
class='action-group__action usa-button action-group__action--left'
value='Previous step'>
</div>
</div>
{% endset %}
{{ MultiStepModalForm( {{ MultiStepModalForm(
'add-app-mem', name='add-app-mem',
new_member_form, form=new_member_form,
url_for("applications.create_member", application_id=application.id), form_action=url_for("applications.create_member", application_id=application.id),
[step_one, step_two], steps=[
member_steps.MemberStepOne(new_member_form),
member_steps.MemberStepTwo(new_member_form, application)
],
button_text=("portfolios.admin.add_new_member" | translate), button_text=("portfolios.admin.add_new_member" | translate),
button_icon="plus", button_icon="plus",
) }} ) }}

View File

@ -0,0 +1,127 @@
{% from "components/icon.html" import Icon %}
{% from "components/text_input.html" import TextInput %}
{% from "components/checkbox_input.html" import CheckboxInput %}
{% macro MemberStepOne(new_member_form) %}
<div class="modal__form--header">
<h1>Invite new member</h1>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.first_name, validation='requiredField') }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.last_name, validation='requiredField') }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.email, validation='email') }}
</div>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.phone_number, validation='usPhone', optional=True) }}
</div>
</div>
<div class='form-row'>
<div class='form-col form-col--half'>
{{ TextInput(new_member_form.user_data.dod_id, validation='dodId') }}
</div>
<div class='form-col form-col--half'>
</div>
</div>
<div class='action-group'>
<input
type='button'
v-on:click="next()"
v-bind:disabled="invalid"
class='action-group__action usa-button'
value='Next'>
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('{{ new_port_mem }}')">{{ "common.cancel" | translate }}</a>
</div>
{% endmacro %}
{% macro MemberStepTwo(new_member_form, application) %}
<div class="modal__form">
<div class="modal__form--header">
<h1>{{ "portfolios.applications.members.new.assign_roles" | translate }}</h1>
<a class='icon-link'>
{{ Icon('info') }}
{{ "portfolios.applications.members.new.learn_more" | translate }}
</a>
<div class="environment-roles-new">
<div class="form-row">
<div class="form-col form-col--quarter">
<span class="environment-roles-new__head">
{{ "common.resource_names.environments" | translate }}:
</span>
</div>
<div class="form-col form-col--three-quarters">
<span class="environment-roles-new__head">
{{ "common.choose_role" | translate }}:
</span>
</div>
</div>
{% for environment_data in new_member_form.environment_roles %}
<optionsinput inline-template
v-bind:initial-value="'{{ environment_data.role.data | string }}'"
>
<div class="usa-input">
<fieldset data-ally-disabled="true" class="usa-input__choices">
<div class="form-row">
<div class="form-col form-col--quarter">
<legend>
<div v-bind:class='["usa-input__title-inline", {"environment-name--gray": value === "None" }]'>
{{ environment_data.environment_name.data }}
</div>
</legend>
</div>
<div class="form-col form-col--three-quarters">
{{ environment_data.role(**{"v-model": "value"}) }}
</div>
</div>
</fieldset>
</div>
</optionsinput>
{{ environment_data.environment_id() }}
{% endfor %}
</div>
<h1>{{ "portfolios.applications.members.new.manage_perms" | translate({"application_name": application.name}) }}</h1>
{{ CheckboxInput(new_member_form.permission_sets.perms_team_mgmt, classes="input__inline-fields") }}
{% call CheckboxInput(new_member_form.permission_sets.perms_env_mgmt, classes="input__inline-fields") %}
{% set field=new_member_form.permission_sets.perms_del_env %}
<nestedcheckboxinput
name='{{ field.name }}'
inline-template
key='{{ field.name }}'
v-bind:is-parent-checked="isChecked"
>
<div class="usa-input input__inline-fields input__inline-fields--indented">
<fieldset data-ally-disabled="true" class="usa-input__choices usa-input__choices--inline">
<legend>
<input
id="permission_sets-perms_del_env"
name="permission_sets-perms_del_env"
type="checkbox"
v-model="isChecked"
v-bind:disabled="!$parent.isChecked">
{{ field.label | safe }}
</legend>
</fieldset>
</div>
</checkboxinput>
{% endcall %}
</div>
<div class='action-group'>
<input
type="submit"
class='action-group__action usa-button'
form="add-app-mem"
value='Invite member'>
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('{{ new_port_mem }}')">{{ "common.cancel" | translate }}</a>
<input
type='button'
v-on:click="previous()"
class='action-group__action usa-button action-group__action--left'
value='Previous step'>
</div>
</div>
{% endmacro %}

View File

@ -4,6 +4,8 @@
{% from "components/icon.html" import Icon %} {% from "components/icon.html" import Icon %}
{% from 'components/save_button.html' import SaveButton %} {% from 'components/save_button.html' import SaveButton %}
{% from "components/toggle_list.html" import ToggleButton, ToggleSection %} {% from "components/toggle_list.html" import ToggleButton, ToggleSection %}
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
{% import "fragments/applications/new_member_modal_content.html" as member_steps %}
{% set secondary_breadcrumb = 'portfolios.applications.team_settings.title' | translate({ "application_name": application.name }) %} {% set secondary_breadcrumb = 'portfolios.applications.team_settings.title' | translate({ "application_name": application.name }) %}
@ -11,13 +13,29 @@
{% if not application.members %} {% if not application.members %}
{% set user_can_invite = user_can(permissions.CREATE_APPLICATION_MEMBER) %} {% set user_can_invite = user_can(permissions.CREATE_APPLICATION_MEMBER) %}
{{ EmptyState( <div class='empty-state'>
("portfolios.applications.team_settings.blank_slate.title" | translate), <p class='empty-state__message'>{{ ("portfolios.applications.team_settings.blank_slate.title" | translate) }}</p>
action_label=("portfolios.applications.team_settings.blank_slate.action_label" | translate),
action_href='#' if user_can_invite else None, {{ Icon('avatar') }}
sub_message=None if user_can_invite else ("portfolios.applications.team_settings.blank_slate.sub_message" | translate),
icon='avatar' {% if not user_can_invite %}
) }} <p class='empty-state__sub-message'>{{ ("portfolios.applications.team_settings.blank_slate.sub_message" | translate) }}</p>
{% endif %}
{% if user_can_invite %}
{{ MultiStepModalForm(
name='add-app-mem',
form=new_member_form,
form_action=url_for("applications.create_member", application_id=application.id),
steps=[
member_steps.MemberStepOne(new_member_form),
member_steps.MemberStepTwo(new_member_form, application)
],
button_text=("portfolios.applications.team_settings.blank_slate.action_label" | translate),
link_classes="usa-button usa-button-big"
) }}
{% endif %}
</div>
{% else %} {% else %}
<div class='subheading'> <div class='subheading'>