Merge pull request #815 from dod-ccpo/add-new-env-app-settings
Add New Environment via app settings
This commit is contained in:
commit
1c4725840c
@ -85,20 +85,33 @@ def check_users_are_in_application(user_ids, application):
|
||||
return True
|
||||
|
||||
|
||||
@applications_bp.route("/applications/<application_id>/settings")
|
||||
@user_can(Permissions.VIEW_APPLICATION, message="view application edit form")
|
||||
def settings(application_id):
|
||||
application = Applications.get(application_id)
|
||||
form = ApplicationForm(name=application.name, description=application.description)
|
||||
def render_settings_page(application, **kwargs):
|
||||
environments_obj = get_environments_obj_for_app(application=application)
|
||||
members_form = AppEnvRolesForm(data=data_for_app_env_roles_form(application))
|
||||
new_env_form = EditEnvironmentForm()
|
||||
|
||||
if "application_form" not in kwargs:
|
||||
kwargs["application_form"] = ApplicationForm(
|
||||
name=application.name, description=application.description
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"portfolios/applications/settings.html",
|
||||
application=application,
|
||||
form=form,
|
||||
environments_obj=environments_obj,
|
||||
members_form=members_form,
|
||||
new_env_form=new_env_form,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
@applications_bp.route("/applications/<application_id>/settings")
|
||||
@user_can(Permissions.VIEW_APPLICATION, message="view application edit form")
|
||||
def settings(application_id):
|
||||
application = Applications.get(application_id)
|
||||
|
||||
return render_settings_page(
|
||||
application=application,
|
||||
active_toggler=http_request.args.get("active_toggler"),
|
||||
active_toggler_section=http_request.args.get("active_toggler_section"),
|
||||
)
|
||||
@ -129,16 +142,8 @@ def update_environment(environment_id):
|
||||
)
|
||||
else:
|
||||
return (
|
||||
render_template(
|
||||
"portfolios/applications/settings.html",
|
||||
render_settings_page(
|
||||
application=application,
|
||||
form=ApplicationForm(
|
||||
name=application.name, description=application.description
|
||||
),
|
||||
environments_obj=get_environments_obj_for_app(application=application),
|
||||
members_form=AppEnvRolesForm(
|
||||
data=data_for_app_env_roles_form(application)
|
||||
),
|
||||
active_toggler=environment.id,
|
||||
active_toggler_section="edit",
|
||||
),
|
||||
@ -146,6 +151,31 @@ def update_environment(environment_id):
|
||||
)
|
||||
|
||||
|
||||
@applications_bp.route(
|
||||
"/applications/<application_id>/environments/new", methods=["POST"]
|
||||
)
|
||||
@user_can(Permissions.CREATE_ENVIRONMENT, message="create application environment")
|
||||
def new_environment(application_id):
|
||||
application = Applications.get(application_id)
|
||||
env_form = EditEnvironmentForm(formdata=http_request.form)
|
||||
|
||||
if env_form.validate():
|
||||
Environments.create(application=application, name=env_form.name.data)
|
||||
|
||||
flash("environment_added", environment_name=env_form.data["name"])
|
||||
|
||||
return redirect(
|
||||
url_for(
|
||||
"applications.settings",
|
||||
application_id=application.id,
|
||||
fragment="application-environments",
|
||||
_anchor="application-environments",
|
||||
)
|
||||
)
|
||||
else:
|
||||
return (render_settings_page(application=application), 400)
|
||||
|
||||
|
||||
@applications_bp.route("/applications/<application_id>/edit", methods=["POST"])
|
||||
@user_can(Permissions.EDIT_APPLICATION, message="update application")
|
||||
def update(application_id):
|
||||
@ -162,12 +192,7 @@ def update(application_id):
|
||||
)
|
||||
)
|
||||
else:
|
||||
return render_template(
|
||||
"portfolios/applications/settings.html",
|
||||
application=application,
|
||||
form=form,
|
||||
environments_obj=get_environments_obj_for_app(application=application),
|
||||
)
|
||||
return render_settings_page(application=application, application_form=form)
|
||||
|
||||
|
||||
@applications_bp.route("/environments/<environment_id>/roles", methods=["POST"])
|
||||
@ -214,13 +239,8 @@ def update_env_roles(environment_id):
|
||||
)
|
||||
else:
|
||||
return (
|
||||
render_template(
|
||||
"portfolios/applications/settings.html",
|
||||
render_settings_page(
|
||||
application=application,
|
||||
form=ApplicationForm(
|
||||
name=application.name, description=application.description
|
||||
),
|
||||
environments_obj=get_environments_obj_for_app(application=application),
|
||||
active_toggler=environment.id,
|
||||
active_toggler_section="edit",
|
||||
),
|
||||
|
@ -5,6 +5,7 @@ from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from atst.database import db
|
||||
from atst.domain.authz import Authorization
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.domain.portfolios.scopes import ScopedPortfolio
|
||||
from atst.models import (
|
||||
Application,
|
||||
|
@ -17,6 +17,13 @@ MESSAGES = {
|
||||
"message_template": "Application environment members have been updated",
|
||||
"category": "success",
|
||||
},
|
||||
"environment_added": {
|
||||
"title_template": translate("flash.success"),
|
||||
"message_template": """
|
||||
{{ "flash.environment_added" | translate({ "env_name": environment_name }) }}
|
||||
""",
|
||||
"category": "success",
|
||||
},
|
||||
"application_environments_updated": {
|
||||
"title_template": "Application environments updated",
|
||||
"message_template": "Application environments have been updated",
|
||||
@ -29,7 +36,7 @@ MESSAGES = {
|
||||
},
|
||||
"invitation_resent": {
|
||||
"title_template": "Invitation resent",
|
||||
"message_template": "The {{ officer_type }} has been resent instructions to join this portfolio.",
|
||||
"message_template": "The {{ officer_type }} has been resent instructions to join this portfolio.",
|
||||
"category": "success",
|
||||
},
|
||||
"task_order_draft": {
|
||||
|
24
js/components/forms/new_environment.js
Normal file
24
js/components/forms/new_environment.js
Normal file
@ -0,0 +1,24 @@
|
||||
import FormMixin from '../../mixins/form'
|
||||
import textinput from '../text_input'
|
||||
|
||||
export default {
|
||||
name: 'new-environment',
|
||||
|
||||
mixins: [FormMixin],
|
||||
|
||||
components: {
|
||||
textinput,
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
open: false,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggle: function() {
|
||||
this.open = !this.open
|
||||
},
|
||||
},
|
||||
}
|
@ -38,6 +38,7 @@ import SidenavToggler from './components/sidenav_toggler'
|
||||
import KoReview from './components/forms/ko_review'
|
||||
import BaseForm from './components/forms/base_form'
|
||||
import DeleteConfirmation from './components/delete_confirmation'
|
||||
import NewEnvironment from './components/forms/new_environment'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
@ -78,6 +79,7 @@ const app = new Vue({
|
||||
BaseForm,
|
||||
DeleteConfirmation,
|
||||
nestedcheckboxinput,
|
||||
NewEnvironment,
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
|
@ -42,6 +42,19 @@
|
||||
|
||||
.usa-input {
|
||||
margin: 0;
|
||||
|
||||
.icon-validation {
|
||||
left: 135%;
|
||||
}
|
||||
}
|
||||
|
||||
#name {
|
||||
max-width: none;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.usa-alert {
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
select {
|
||||
@ -50,6 +63,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.new-env {
|
||||
margin-top: 5rem;
|
||||
padding: 0 5rem;
|
||||
}
|
||||
|
||||
.accordion-table__items {
|
||||
margin: 0;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
</button>
|
||||
</form>
|
||||
<div class="action-group">
|
||||
<a v-on:click="deleteText = ''; $root.closeModal({{ modal_id }})" class="action-group__action icon-link icon-link--default">{{ "common.cancel" | translate }}</a>
|
||||
<a v-on:click="deleteText = ''; $root.closeModal('{{ modal_id }}')" class="action-group__action icon-link icon-link--default">{{ "common.cancel" | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
42
templates/fragments/applications/add_new_environment.html
Normal file
42
templates/fragments/applications/add_new_environment.html
Normal file
@ -0,0 +1,42 @@
|
||||
{% from "components/alert.html" import Alert %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
|
||||
<new-environment inline-template>
|
||||
<div>
|
||||
<div v-if="open">
|
||||
<form method='POST' id="add-new-env" action='{{ url_for("applications.new_environment", application_id=application.id) }}' autocomplete="off" enctype="multipart/form-data">
|
||||
{{ new_env_form.csrf_token }}
|
||||
|
||||
<div class="accordion-table__item-content new-env">
|
||||
{{ Alert(
|
||||
title=("portfolios.applications.create_new_env" | translate),
|
||||
message=("portfolios.applications.create_new_env_info" | translate )
|
||||
) }}
|
||||
<div class="h4">{{ "portfolios.applications.enter_env_name" | translate }}</div>
|
||||
{{ TextInput(new_env_form.name, label="", validation="requiredField") }}
|
||||
</div>
|
||||
<div class="panel__footer">
|
||||
<div class="action-group">
|
||||
<div class='action-group-cancel'>
|
||||
<a class='action-group-cancel__action icon-link icon-link--default' v-on:click="toggle">
|
||||
{{ "common.cancel" | translate }}
|
||||
</a>
|
||||
{{ SaveButton(text=('common.save' | translate), element="input", form="add-new-env") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-else class="panel__footer">
|
||||
<div class="action-group">
|
||||
<a class='icon-link' v-on:click="toggle">
|
||||
{{ "portfolios.applications.add_environment" | translate }}
|
||||
{{ Icon('plus') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</new-environment>
|
||||
|
@ -115,10 +115,10 @@
|
||||
|
||||
{{
|
||||
DeleteConfirmation(
|
||||
modal_id=delete_modal_environment_id,
|
||||
modal_id=delete_environment_modal_id,
|
||||
delete_text=('portfolios.applications.environments.delete.button' | translate),
|
||||
delete_action= url_for('applications.delete_environment', environment_id=env['id']),
|
||||
form=form
|
||||
form=edit_form
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
@ -126,11 +126,3 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel__footer">
|
||||
<div class="action-group">
|
||||
<a class='icon-link'>
|
||||
{{ "portfolios.applications.add_environment" | translate }}
|
||||
{{ Icon('plus') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
{% from "components/options_input.html" import OptionsInput %}
|
||||
{% from "components/toggle_list.html" import ToggleButton, ToggleSection %}
|
||||
|
||||
{{ team_form.csrf_token }}
|
||||
|
||||
|
@ -16,13 +16,13 @@
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
|
||||
{{ form.csrf_token }}
|
||||
{{ application_form.csrf_token }}
|
||||
<p>
|
||||
{{ "fragments.edit_application_form.explain" | translate }}
|
||||
</p>
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
{{ TextInput(form.name) }}
|
||||
{{ TextInput(application_form.name) }}
|
||||
</div>
|
||||
<div class="form-col form-col--third">
|
||||
{% if user_can(permissions.DELETE_APPLICATION) %}
|
||||
@ -45,7 +45,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
{{ TextInput(form.description, paragraph=True) }}
|
||||
{{ TextInput(application_form.description, paragraph=True) }}
|
||||
</div>
|
||||
<div class="form-col form-col--third">
|
||||
|
||||
@ -69,6 +69,10 @@
|
||||
{% if user_can(permissions.EDIT_APPLICATION) %}
|
||||
{% include "fragments/applications/edit_environments.html" %}
|
||||
|
||||
{% if user_can(permissions.CREATE_ENVIRONMENT) %}
|
||||
{% include "fragments/applications/add_new_environment.html" %}
|
||||
{% endif %}
|
||||
|
||||
{% elif user_can(permissions.VIEW_ENVIRONMENT) %}
|
||||
{% include "fragments/applications/read_only_environments.html" %}
|
||||
{% endif %}
|
||||
@ -89,10 +93,10 @@
|
||||
|
||||
{{
|
||||
DeleteConfirmation(
|
||||
modal_id=delete_modal_environment_id,
|
||||
modal_id="delete_application",
|
||||
delete_text=('portfolios.applications.delete.button' | translate),
|
||||
delete_action= url_for('applications.delete', application_id=application.id),
|
||||
form=form
|
||||
form=application_form
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
|
@ -1,10 +1,8 @@
|
||||
{% extends "portfolios/applications/base.html" %}
|
||||
|
||||
{% from "components/empty_state.html" import EmptyState %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
{% from "components/toggle_list.html" import ToggleButton, ToggleSection %}
|
||||
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
{% import "fragments/applications/new_member_modal_content.html" as member_steps %}
|
||||
{% from "components/alert.html" import Alert %}
|
||||
{% from "components/delete_confirmation.html" import DeleteConfirmation %}
|
||||
|
@ -54,7 +54,7 @@ def test_updating_application_environments_success(client, user_session):
|
||||
assert environment.name == "new name a"
|
||||
|
||||
|
||||
def test_updating_application_environments_failure(client, user_session):
|
||||
def test_update_environment_failure(client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
application = ApplicationFactory.create(portfolio=portfolio)
|
||||
environment = EnvironmentFactory.create(
|
||||
@ -391,6 +391,38 @@ def test_delete_application(client, user_session):
|
||||
assert len(application.environments) == 0
|
||||
|
||||
|
||||
def test_new_environment(client, user_session):
|
||||
user = UserFactory.create()
|
||||
portfolio = PortfolioFactory(owner=user)
|
||||
application = ApplicationFactory.create(portfolio=portfolio)
|
||||
num_envs = len(application.environments)
|
||||
|
||||
user_session(user)
|
||||
response = client.post(
|
||||
url_for("applications.new_environment", application_id=application.id),
|
||||
data={"name": "dabea"},
|
||||
)
|
||||
|
||||
assert response.status_code == 302
|
||||
assert len(application.environments) == num_envs + 1
|
||||
|
||||
|
||||
def test_new_environment_with_bad_data(client, user_session):
|
||||
user = UserFactory.create()
|
||||
portfolio = PortfolioFactory(owner=user)
|
||||
application = ApplicationFactory.create(portfolio=portfolio)
|
||||
num_envs = len(application.environments)
|
||||
|
||||
user_session(user)
|
||||
response = client.post(
|
||||
url_for("applications.new_environment", application_id=application.id),
|
||||
data={"name": None},
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert len(application.environments) == num_envs
|
||||
|
||||
|
||||
def test_delete_environment(client, user_session):
|
||||
user = UserFactory.create()
|
||||
portfolio = PortfolioFactory(owner=user)
|
||||
|
@ -69,6 +69,7 @@ flash:
|
||||
congrats: Congrats!
|
||||
delete_member_success: 'You have successfully deleted {member_name} from the portfolio.'
|
||||
deleted_member: Portfolio member deleted
|
||||
environment_added: 'The environment "{env_name}" has been added to the application.'
|
||||
login_required_message: After you log in, you will be redirected to your destination page.
|
||||
login_required_title: Log in required
|
||||
new_portfolio: You've created a new JEDI portfolio and jump-started your first task order!
|
||||
@ -420,6 +421,8 @@ portfolios:
|
||||
add_another_environment: Add another environment
|
||||
app_settings_text: App settings
|
||||
create_button_text: Create
|
||||
create_new_env: Create a new environment.
|
||||
create_new_env_info: Creating an environment gives you access to the Cloud Service Provider. This environment will function within the constraints of the task order, and any costs will be billed against the portfolio.
|
||||
csp_console_text: CSP console
|
||||
remove_member:
|
||||
alert:
|
||||
@ -431,6 +434,7 @@ portfolios:
|
||||
message: You will lose access to this application and all of its reporting and metrics tools. The activity log will be retained.
|
||||
button: Delete application
|
||||
header: Are you sure you want to delete this application?
|
||||
enter_env_name: "Enter environment name:"
|
||||
environments:
|
||||
name: Name
|
||||
delete:
|
||||
|
Loading…
x
Reference in New Issue
Block a user