diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index 0ca20a27..21ea67a8 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -191,3 +191,21 @@ def delete(application_id): "applications.portfolio_applications", portfolio_id=application.portfolio_id ) ) + + +@applications_bp.route("/environments//delete", methods=["POST"]) +@user_can(Permissions.DELETE_ENVIRONMENT, message="delete environment") +def delete_environment(environment_id): + environment = Environments.get(environment_id) + Environments.delete(environment=environment, commit=True) + + flash("environment_deleted", environment_name=environment.name) + + return redirect( + url_for( + "applications.settings", + application_id=environment.application_id, + _anchor="application-environments", + fragment="application-environments", + ) + ) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 9fff1be2..9855628e 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -2,6 +2,11 @@ from flask import flash, render_template_string from atst.utils.localization import translate MESSAGES = { + "environment_deleted": { + "title_template": "{{ environment_name }} deleted", + "message_template": 'The environment "{{ environment_name }}" has been deleted', + "category": "success", + }, "application_environments_updated": { "title_template": "Application environments updated", "message_template": "Application environments have been updated", diff --git a/templates/components/delete_confirmation.html b/templates/components/delete_confirmation.html new file mode 100644 index 00000000..e5e9bfc5 --- /dev/null +++ b/templates/components/delete_confirmation.html @@ -0,0 +1,25 @@ +{% macro DeleteConfirmation(modal_id, delete_text, delete_action, form) %} + +
+
+ + +
+
+
+ {{ form.csrf_token }} + +
+ +
+
+
+{% endmacro %} diff --git a/templates/fragments/applications/edit_environments.html b/templates/fragments/applications/edit_environments.html index f821e4bf..5b9457dd 100644 --- a/templates/fragments/applications/edit_environments.html +++ b/templates/fragments/applications/edit_environments.html @@ -1,7 +1,9 @@ +{% from "components/delete_confirmation.html" import DeleteConfirmation %} {% from "components/icon.html" import Icon %} -{% from "components/toggle_list.html" import ToggleButton, ToggleSection %} -{% from "components/text_input.html" import TextInput %} +{% from "components/modal.html" import Modal %} {% from "components/save_button.html" import SaveButton %} +{% from "components/text_input.html" import TextInput %} +{% from "components/toggle_list.html" import ToggleButton, ToggleSection %} {% macro RolePanel(users=[], role='no_access') %} {% if role == 'no_access' %} @@ -52,6 +54,7 @@ {% set member_count = env['members_form'].data['team_roles'] | length %} {% set members_by_role = env['members'] %} {% set unassigned = members_by_role['no_access'] %} + {% set delete_environment_modal_id = "delete_modal_environment{}".format(env['id']) %}
  • @@ -75,7 +78,7 @@
    - + {{ Icon('trash') }}
    @@ -122,6 +125,27 @@ {% endcall %}
  • + + {% call Modal(name=delete_environment_modal_id, dismissable=True) %} +

    Are you sure you want to delete this environment?

    + + {{ + Alert( + level="warning", + title="Warning! This action is permanent", + message="You will no longer be able to access this environment", + ) + }} + + {{ + DeleteConfirmation( + modal_id=delete_modal_environment_id, + delete_text=('portfolios.applications.environments.delete.button' | translate), + delete_action= url_for('applications.delete_environment', environment_id=env['id']), + form=form + ) + }} + {% endcall %} {% endfor %} diff --git a/templates/portfolios/applications/settings.html b/templates/portfolios/applications/settings.html index 49739d2f..7de3e1b5 100644 --- a/templates/portfolios/applications/settings.html +++ b/templates/portfolios/applications/settings.html @@ -1,9 +1,10 @@ {% extends "portfolios/applications/base.html" %} {% from "components/alert.html" import Alert %} -{% from "components/text_input.html" import TextInput %} +{% from "components/delete_confirmation.html" import DeleteConfirmation %} {% from "components/icon.html" import Icon %} {% from "components/modal.html" import Modal %} +{% from "components/text_input.html" import TextInput %} {% set secondary_breadcrumb = 'portfolios.applications.existing_application_title' | translate({ "application_name": application.name }) %} @@ -94,29 +95,14 @@ ) }} - -
    -
    - - -
    -
    -
    - {{ form.csrf_token }} - -
    - -
    -
    -
    + {{ + DeleteConfirmation( + modal_id=delete_modal_environment_id, + delete_text=('portfolios.applications.delete.button' | translate), + delete_action= url_for('applications.delete', application_id=application.id), + form=form + ) + }} {% endcall %} {% endif %} diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 803b6e62..d335e4bb 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -326,3 +326,32 @@ def test_delete_application(client, user_session): # app and envs are soft deleted assert len(port.applications) == 0 assert len(application.environments) == 0 + + +def test_delete_environment(client, user_session): + user = UserFactory.create() + portfolio = PortfolioFactory(owner=user) + application = ApplicationFactory.create(portfolio=portfolio) + environment = EnvironmentFactory.create(application=application) + + user_session(user) + + response = client.post( + url_for("applications.delete_environment", environment_id=environment.id) + ) + + # appropriate response and redirect + assert response.status_code == 302 + assert response.location == url_for( + "applications.settings", + application_id=application.id, + _anchor="application-environments", + _external=True, + fragment="application-environments", + ) + # appropriate flash message + message = get_flashed_messages()[0] + assert "deleted" in message["message"] + assert environment.name in message["message"] + # deletes environment + assert len(application.environments) == 0 diff --git a/translations.yaml b/translations.yaml index d6f065dc..9f144c01 100644 --- a/translations.yaml +++ b/translations.yaml @@ -413,6 +413,8 @@ portfolios: header: Are you sure you want to delete this application? environments: name: Name + delete: + button: Delete environment edit_name: Edit name environments_description: Each environment created within an application is logically separated from one another for easier management and security. environments_heading: Application environments