Merge branch 'staging' into environment-mgmt-grp-provisioning

This commit is contained in:
tomdds 2020-02-05 14:52:15 -05:00 committed by GitHub
commit 05f4ef8cb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 286 additions and 254 deletions

View File

@ -466,9 +466,10 @@ def revoke_invite(application_id, application_role_id):
if invite.is_pending:
ApplicationInvitations.revoke(invite.token)
flash(
"application_invite_revoked",
"invite_revoked",
resource="Application",
user_name=app_role.user_name,
application_name=g.application.name,
resource_name=g.application.name,
)
else:
flash(

View File

@ -37,8 +37,14 @@ def accept_invitation(portfolio_token):
)
@user_can(Permissions.EDIT_PORTFOLIO_USERS, message="revoke invitation")
def revoke_invitation(portfolio_id, portfolio_token):
PortfolioInvitations.revoke(portfolio_token)
invite = PortfolioInvitations.revoke(portfolio_token)
flash(
"invite_revoked",
resource="Portfolio",
user_name=invite.user_name,
resource_name=g.portfolio.name,
)
return redirect(
url_for(
"portfolios.admin",

View File

@ -33,11 +33,6 @@ MESSAGES = {
"message": "flash.application_invite.resent.message",
"category": "success",
},
"application_invite_revoked": {
"title": "flash.application_invite.revoked.title",
"message": "flash.application_invite.revoked.message",
"category": "success",
},
"application_member_removed": {
"title": "flash.application_member.removed.title",
"message": "flash.application_member.removed.message",
@ -103,6 +98,11 @@ MESSAGES = {
"message": None,
"category": "warning",
},
"invite_revoked": {
"title": "flash.invite_revoked.title",
"message": "flash.invite_revoked.message",
"category": "success",
},
"logged_out": {
"title": "flash.logged_out.title",
"message": "flash.logged_out.message",

View File

@ -1,30 +1,21 @@
import ExpandSidenavMixin from '../mixins/expand_sidenav'
import ToggleMixin from '../mixins/toggle'
const cookieName = 'expandSidenav'
export default {
name: 'sidenav-toggler',
mixins: [ToggleMixin],
mixins: [ExpandSidenavMixin, ToggleMixin],
props: {
defaultVisible: {
type: Boolean,
default: function() {
if (document.cookie.match(cookieName)) {
return !!document.cookie.match(cookieName + ' *= *true')
} else {
return true
}
},
},
mounted: function() {
this.$parent.$emit('sidenavToggle', this.isVisible)
},
methods: {
toggle: function(e) {
e.preventDefault()
this.isVisible = !this.isVisible
document.cookie = cookieName + '=' + this.isVisible + '; path=/'
document.cookie = this.cookieName + '=' + this.isVisible + '; path=/'
this.$parent.$emit('sidenavToggle', this.isVisible)
},
},
}

View File

@ -32,12 +32,14 @@ import ToForm from './components/forms/to_form'
import ClinFields from './components/clin_fields'
import PopDateRange from './components/pop_date_range'
import ToggleMenu from './components/toggle_menu'
import ExpandSidenav from './mixins/expand_sidenav'
Vue.config.productionTip = false
Vue.use(VTooltip)
Vue.mixin(Modal)
Vue.mixin(ExpandSidenav)
const app = new Vue({
el: '#app-root',
@ -67,6 +69,12 @@ const app = new Vue({
ToggleMenu,
},
data: function() {
return {
sidenavExpanded: this.defaultVisible,
}
},
mounted: function() {
this.$on('modalOpen', data => {
if (data['isOpen']) {
@ -105,6 +113,10 @@ const app = new Vue({
}
})
})
this.$on('sidenavToggle', data => {
this.sidenavExpanded = data
})
},
delimiters: ['!{', '}'],

View File

@ -0,0 +1,15 @@
export default {
props: {
cookieName: 'expandSidenav',
defaultVisible: {
type: Boolean,
default: function() {
if (document.cookie.match(this.cookieName)) {
return !!document.cookie.match(this.cookieName + ' *= *true')
} else {
return true
}
},
},
},
}

View File

@ -47,3 +47,4 @@
@import "sections/application_edit";
@import "sections/reports";
@import "sections/task_order";
@import "sections/ccpo";

View File

@ -11,6 +11,7 @@
.usa-alert {
padding-bottom: 2.4rem;
max-width: $max-panel-width;
}
@mixin alert {
@ -97,38 +98,3 @@
}
}
}
.alert {
@include alert;
@include alert-level("info");
&.alert--success {
@include alert-level("success");
.alert__actions {
.icon-link {
@include icon-link-color($color-green, $color-white);
}
}
}
&.alert--warning {
@include alert-level("warning");
.alert__actions {
.icon-link {
@include icon-link-color($color-gold-dark, $color-white);
}
}
}
&.alert--error {
@include alert-level("error");
.alert__actions {
.icon-link {
@include icon-link-color($color-red, $color-white);
}
}
}
}

View File

@ -1,8 +1,13 @@
.error-page {
max-width: 475px;
margin: auto;
max-width: $max-page-width;
.panel {
box-shadow: none;
background-color: unset;
border: none;
max-width: 475px;
margin: auto;
&__heading {
text-align: center;
padding: $gap 0;
@ -15,17 +20,6 @@
margin-bottom: $gap;
}
}
&__body {
padding: $gap * 2;
margin: 0;
hr {
width: 80%;
margin: auto;
margin-bottom: $gap * 3;
}
}
}
.icon {

View File

@ -12,7 +12,7 @@
flex-direction: row;
align-items: stretch;
justify-content: space-between;
max-width: 1190px;
max-width: $max-page-width;
a {
color: $color-white;

View File

@ -19,6 +19,7 @@ $sidenav-collapsed-width: 10rem;
$max-panel-width: 90rem;
$home-pg-icon-width: 6rem;
$large-spacing: 4rem;
$max-page-width: $max-panel-width + $sidenav-expanded-width + $large-spacing;
/*
* USWDS Variables

View File

@ -32,22 +32,35 @@
}
.action-group-footer {
@extend .action-group;
&:last-child {
margin-bottom: 0;
}
margin-top: 0;
margin-bottom: 0;
padding-top: $gap;
padding-bottom: $gap;
padding-right: $gap * 4;
position: fixed;
bottom: $footer-height;
left: 0;
background: white;
right: 0;
padding-right: $gap * 4;
border-top: 1px solid $color-gray-lighter;
width: 100%;
z-index: 1;
width: 100%;
&.action-group-footer--expand-offset {
padding-left: $sidenav-expanded-width;
}
&.action-group-footer--collapse-offset {
padding-left: $sidenav-collapsed-width;
}
.action-group-footer--container {
@extend .action-group;
margin-top: 0;
margin-bottom: 0;
margin-left: $large-spacing;
max-width: $max-panel-width;
&:last-child {
margin-bottom: 0;
}
}
}

View File

@ -0,0 +1,3 @@
.ccpo-panel-container {
max-width: $max-panel-width;
}

View File

@ -39,14 +39,18 @@
</div>
<span class="action-group-footer">
{% block next_button %}
{{ SaveButton(text=('portfolios.applications.new.step_1_button_text' | translate)) }}
{% endblock %}
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
Cancel
</a>
</span>
<div
class="action-group-footer"
v-bind:class="{'action-group-footer--expand-offset': this.$root.sidenavExpanded, 'action-group-footer--collapse-offset': !this.$root.sidenavExpanded}">
<div class="action-group-footer--container">
{% block next_button %}
{{ SaveButton(text=('portfolios.applications.new.step_1_button_text' | translate)) }}
{% endblock %}
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
Cancel
</a>
</div>
</div>
</form>
</base-form>

View File

@ -58,20 +58,24 @@
{{ Icon("plus") }}
</button>
</div>
</div>
</div>
</div>
<div
class="action-group-footer"
v-bind:class="{'action-group-footer--expand-offset': this.$root.sidenavExpanded, 'action-group-footer--collapse-offset': !this.$root.sidenavExpanded}">
<div class="action-group-footer--container">
{% block next_button %}
{{ SaveButton(text=('portfolios.applications.new.step_2_button_text' | translate)) }}
{% endblock %}
<a class="usa-button usa-button-secondary" href="{{ url_for('applications.view_new_application_step_1', application_id=application.id) }}">
Previous
</a>
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
Cancel
</a>
</div>
</div>
</div>
<span class="action-group-footer">
{% block next_button %}
{{ SaveButton(text=('portfolios.applications.new.step_2_button_text' | translate)) }}
{% endblock %}
<a class="usa-button usa-button-secondary" href="{{ url_for('applications.view_new_application_step_1', application_id=application.id) }}">
Previous
</a>
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
Cancel
</a>
</span>
</form>
</application-environments>

View File

@ -25,16 +25,20 @@
action_update="applications.update_new_application_step_3") }}
<span class="action-group-footer">
<a class="usa-button" href="{{ url_for('applications.settings', application_id=application_id) }}">
{{ "portfolios.applications.new.step_3_button_text" | translate }}
</a>
<a class="usa-button usa-button-secondary" href="{{ url_for('applications.view_new_application_step_2', application_id=application.id) }}">
{{ "common.previous" | translate }}
</a>
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
{{ "common.cancel" | translate }}
</a>
</span>
<div
class="action-group-footer"
v-bind:class="{'action-group-footer--expand-offset': this.$root.sidenavExpanded, 'action-group-footer--collapse-offset': !this.$root.sidenavExpanded}">
<div class="action-group-footer--container">
<a class="usa-button" href="{{ url_for('applications.settings', application_id=application_id) }}">
{{ "portfolios.applications.new.step_3_button_text" | translate }}
</a>
<a class="usa-button usa-button-secondary" href="{{ url_for('applications.view_new_application_step_2', application_id=application.id) }}">
{{ "common.previous" | translate }}
</a>
<a href="{{ url_for('applications.portfolio_applications', portfolio_id=portfolio.id) }}">
{{ "common.cancel" | translate }}
</a>
</div>
</div>
{% endblock %}

View File

@ -4,21 +4,23 @@
{% from "components/text_input.html" import TextInput %}
{% block content %}
<base-form inline-template>
<form id="add-ccpo-user-form" action="{{ url_for('ccpo.submit_new_user') }}" method="POST">
{{ form.csrf_token }}
<h1>{{ "ccpo.form.add_user_title" | translate }}</h1>
<div class='form-row'>
<div class='form-col form-col--two-thirds'>
{{ TextInput(form.dod_id, validation='dodId', optional=False) }}
</div>
<div class="form-col form-col--third">
<div class='action-group'>
{{ SaveButton(text="common.next"|translate, element="input", additional_classes="action-group__action", form="add-ccpo-user-form") }}
<a class='action-group__action icon-link icon-link--default' href="{{ url_for('ccpo.users') }}">{{ "common.cancel" | translate }}</a>
<div class="ccpo-panel-container">
<base-form inline-template>
<form id="add-ccpo-user-form" action="{{ url_for('ccpo.submit_new_user') }}" method="POST">
{{ form.csrf_token }}
<h1>{{ "ccpo.form.add_user_title" | translate }}</h1>
<div class='form-row'>
<div class='form-col form-col--two-thirds'>
{{ TextInput(form.dod_id, validation='dodId', optional=False) }}
</div>
<div class="form-col form-col--third">
<div class='action-group'>
{{ SaveButton(text="common.next"|translate, element="input", additional_classes="action-group__action", form="add-ccpo-user-form") }}
<a class='action-group__action icon-link icon-link--default' href="{{ url_for('ccpo.users') }}">{{ "common.cancel" | translate }}</a>
</div>
</div>
</div>
</div>
</form>
</base-form>
</form>
</base-form>
</div>
{% endblock %}

View File

@ -3,31 +3,33 @@
{% from "components/text_input.html" import TextInput %}
{% block content %}
{% if new_user %}
<h3>{{ 'ccpo.form.confirm_user_title' | translate }}</h3>
<form id="add-ccpo-user-form" action="{{ url_for('ccpo.confirm_new_user') }}" method="POST">
{{ form.csrf_token }}
<input type="hidden" name="dod_id" value="{{ form.dod_id.data }}">
<div>
<p>
{{ "ccpo.form.confirm_user_text" | translate }}
</p>
<p>
{{ new_user.full_name }}
</p>
<p>
{{ new_user.email }}
</p>
</div>
<div class='action-group'>
<input
type='submit'
class='action-group__action usa-button'
value='{{ "ccpo.form.confirm_button" | translate }}'>
<a class='action-group__action icon-link icon-link--default' href="{{ url_for('ccpo.users') }}">
{{ "common.cancel" | translate }}
</a>
</div>
</form>
{% endif %}
<div class="ccpo-panel-container">
{% if new_user %}
<h3>{{ 'ccpo.form.confirm_user_title' | translate }}</h3>
<form id="add-ccpo-user-form" action="{{ url_for('ccpo.confirm_new_user') }}" method="POST">
{{ form.csrf_token }}
<input type="hidden" name="dod_id" value="{{ form.dod_id.data }}">
<div>
<p>
{{ "ccpo.form.confirm_user_text" | translate }}
</p>
<p>
{{ new_user.full_name }}
</p>
<p>
{{ new_user.email }}
</p>
</div>
<div class='action-group'>
<input
type='submit'
class='action-group__action usa-button'
value='{{ "ccpo.form.confirm_button" | translate }}'>
<a class='action-group__action icon-link icon-link--default' href="{{ url_for('ccpo.users') }}">
{{ "common.cancel" | translate }}
</a>
</div>
</form>
{% endif %}
</div>
{% endblock %}

View File

@ -6,78 +6,80 @@
{% from "components/modal.html" import Modal %}
{% block content %}
<div class='col'>
<div class="h2">
{{ "ccpo.users_title" | translate }}
</div>
<div class="ccpo-panel-container">
<div class='col'>
<div class="h2">
{{ "ccpo.users_title" | translate }}
</div>
{% include "fragments/flash.html" %}
<table>
<thead>
<tr>
<th>{{ "common.name" | translate }}</th>
<th>{{ "common.email" | translate }}</th>
<th>{{ "common.dod_id" | translate }}</th>
{% if user_can(permissions.DELETE_CCPO_USER) %}
<th></th>
{% endif %}
</tr>
</thead>
<tbody>
{% for user, form in users_info %}
{% set modal_id = "disable_ccpo_user_{}".format(user.dod_id) %}
{% set disable_button_class = 'button-danger-outline' %}
{% if user == g.current_user %}
{% set disable_button_class = "usa-button-disabled" %}
{% endif %}
{% include "fragments/flash.html" %}
<table>
<thead>
<tr>
<td>{{ user.full_name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.dod_id }}</td>
<th>{{ "common.name" | translate }}</th>
<th>{{ "common.email" | translate }}</th>
<th>{{ "common.dod_id" | translate }}</th>
{% if user_can(permissions.DELETE_CCPO_USER) %}
<td>
<a v-on:click="openModal('{{ modal_id }}')" class='usa-button {{ disable_button_class }}'>
{{ "common.disable" | translate }}
</a>
</td>
<th></th>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for user, form in users_info %}
{% set modal_id = "disable_ccpo_user_{}".format(user.dod_id) %}
{% set disable_button_class = 'button-danger-outline' %}
{% if user == g.current_user %}
{% set disable_button_class = "usa-button-disabled" %}
{% endif %}
<tr>
<td>{{ user.full_name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.dod_id }}</td>
{% if user_can(permissions.DELETE_CCPO_USER) %}
<td>
<a v-on:click="openModal('{{ modal_id }}')" class='usa-button {{ disable_button_class }}'>
{{ "common.disable" | translate }}
</a>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if user_can(permissions.CREATE_CCPO_USER) %}
<a class="icon-link" href="{{ url_for('ccpo.add_new_user')}}">
{{ "ccpo.add_user" | translate }} {{ Icon("plus") }}
</a>
{% endif %}
{% if user_can(permissions.DELETE_CCPO_USER) %}
{% for user, form in users_info %}
{% set modal_id = "disable_ccpo_user_{}".format(user.dod_id) %}
{% call Modal(name=modal_id) %}
<h1>Disable CCPO User</h1>
<hr>
{{
Alert(
title=("components.modal.destructive_title" | translate),
message=("ccpo.disable_user.alert_message" | translate({"user_name": user.full_name})),
level="warning"
)
}}
{{
DeleteConfirmation(
modal_id=modal_id,
delete_text='Remove Access',
delete_action=(url_for('ccpo.remove_access', user_id=user.id)),
form=form,
confirmation_text='remove'
)
}}
{% endcall %}
{% endfor %}
{% endif %}
</div>
{% if user_can(permissions.CREATE_CCPO_USER) %}
<a class="icon-link" href="{{ url_for('ccpo.add_new_user')}}">
{{ "ccpo.add_user" | translate }} {{ Icon("plus") }}
</a>
{% endif %}
{% if user_can(permissions.DELETE_CCPO_USER) %}
{% for user, form in users_info %}
{% set modal_id = "disable_ccpo_user_{}".format(user.dod_id) %}
{% call Modal(name=modal_id) %}
<h1>Disable CCPO User</h1>
<hr>
{{
Alert(
title=("components.modal.destructive_title" | translate),
message=("ccpo.disable_user.alert_message" | translate({"user_name": user.full_name})),
level="warning"
)
}}
{{
DeleteConfirmation(
modal_id=modal_id,
delete_text='Remove Access',
delete_action=(url_for('ccpo.remove_access', user_id=user.id)),
form=form,
confirmation_text='remove'
)
}}
{% endcall %}
{% endfor %}
{% endif %}
{% endblock %}

View File

@ -5,6 +5,7 @@
{% block content %}
<main class="usa-section usa-content error-page">
<div class="panel">
<div class="panel__heading">
{{ Icon('cloud', classes="icon--red icon--large")}}
<hr>
@ -17,6 +18,7 @@
{%- endif %}
</p>
</div>
</div>
</main>
{% endblock %}

View File

@ -10,29 +10,30 @@
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='img/favicon.ico') }} " />
</head>
<body class="{% if g.modalOpen %} modalOpen{% endif %}">
<div id='app-root'>
{% block template_vars %}{% endblock %}
{% block template_vars %}{% endblock %}
{% include 'components/usa_header.html' %}
{% include 'components/usa_header.html' %}
{% include 'navigation/topbar.html' %}
{% include 'navigation/topbar.html' %}
<div class='global-layout'>
<div class='global-layout'>
<div class='global-panel-container'>
{% block sidenav %}{% endblock %}
<div class='global-panel-container'>
{% block sidenav %}{% endblock %}
{% block content %}
these are not the droids you are looking for
{% endblock %}
{% block content %}
these are not the droids you are looking for
{% endblock %}
</div>
</div>
{% include 'footer.html' %}
{% block modal %}{% endblock %}
{% assets "js_all" %}
<script src="{{ ASSET_URL }}"></script>
{% endassets %}
</div>
{% include 'footer.html' %}
{% block modal %}{% endblock %}
{% assets "js_all" %}
<script src="{{ ASSET_URL }}"></script>
{% endassets %}
</body>
</html>

View File

@ -15,6 +15,7 @@
<p>{{ "portfolios.header" | translate }}</p>
<h1>{{ 'portfolios.new.title' | translate }}</h1>
</div>
</div>
{{ StickyCTA(text="portfolios.new.cta_step_1"|translate, context=("portfolios.new.sticky_header_context"|translate({"step": "1"}) )) }}
<base-form inline-template>
<div class="row">
@ -38,13 +39,18 @@
{{ "forms.portfolio.defense_component.help_text" | translate | safe }}
</div>
</div>
<div class='action-group-footer'>
{% block next_button %}
{{ SaveButton(text=('portfolios.new.save' | translate), form="portfolio-create", element="input") }}
{% endblock %}
<a class="usa-button usa-button-secondary" href="{{ url_for('atst.home') }}">
Cancel
</a>
<div
class='action-group-footer'
v-bind:class="{'action-group-footer--expand-offset': this.$root.sidenavExpanded, 'action-group-footer--collapse-offset': !this.$root.sidenavExpanded}">
<div class="action-group-footer--container">
{% block next_button %}
{{ SaveButton(text=('portfolios.new.save' | translate), form="portfolio-create", element="input") }}
{% endblock %}
<a class="usa-button usa-button-secondary" href="{{ url_for('atst.home') }}">
Cancel
</a>
</div>
</div>
</form>
</div>
</base-form>

View File

@ -31,7 +31,10 @@
<div class="task-order">
{% block to_builder_form_field %}{% endblock %}
</div>
<span class="action-group-footer">
<div
class="action-group-footer"
v-bind:class="{'action-group-footer--expand-offset': this.$root.sidenavExpanded, 'action-group-footer--collapse-offset': !this.$root.sidenavExpanded}">
<div class="action-group-footer--container">
{% block next_button %}
<input
type="submit"
@ -58,14 +61,13 @@
</a>
{%- endif %}
{% endif %}
<a
v-on:click="openModal('cancel')"
class="action-group__action icon-link">
{{ "common.cancel" | translate }}
</a>
</span>
</div>
</div>
</form>
</to-form>
{% endblock %}

View File

@ -128,9 +128,6 @@ flash:
message: There was an error processing the invitation for {user_name} from {application_name}
resent:
message: "{email} has been sent an invitation to access this Application"
revoked:
title: Application invitation revoked
message: You have successfully revoked the invite for {user_name} from {application_name}
application_member:
removed:
title: Team member removed from application
@ -166,6 +163,9 @@ flash:
errors:
title: There were some errors
message: Please see below.
invite_revoked:
title: "{resource} invitation revoked"
message: "You have successfully revoked the invite for {user_name} from {resource_name}"
login_required_message: After you log in, you will be redirected to your destination page.
login_required_title: Log in required
logged_out: