Delete unused Jinja macros and rearrange templates.
Templates and fragments that relate to specific resources (portfolios, applications, task orders) should reside in directories named for the relevant resource. This also matches the way the application routes are distributed among modules named for each resource type.
This commit is contained in:
16
templates/applications/base.html
Normal file
16
templates/applications/base.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends "portfolios/base.html" %}
|
||||
|
||||
{% from "components/sticky_cta.html" import StickyCTA %}
|
||||
|
||||
{% block portfolio_header %}
|
||||
{% include "portfolios/header.html" %}
|
||||
{% if application %}
|
||||
{{ StickyCTA(text=application.name, return_link_url=url_for('applications.portfolio_applications', portfolio_id=application.portfolio_id), return_link_text="BACK TO APPLICATIONS") }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block portfolio_content %}
|
||||
<div class='application-content'>
|
||||
{% block application_content %}{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
34
templates/applications/fragments/add_new_environment.html
Normal file
34
templates/applications/fragments/add_new_environment.html
Normal file
@@ -0,0 +1,34 @@
|
||||
{% 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">
|
||||
{{ SaveButton(text=('common.save' | translate), element="input", form="add-new-env") }}
|
||||
<a class='action-group__action icon-link icon-link--default' v-on:click="toggle">
|
||||
{{ "common.cancel" | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<a class='icon-link icon-link__add' v-on:click="toggle">
|
||||
{{ Icon('plus') }}
|
||||
{{ "portfolios.applications.add_environment" | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</new-environment>
|
||||
@@ -0,0 +1,52 @@
|
||||
{% from "components/checkbox_input.html" import CheckboxInput %}
|
||||
|
||||
{% macro MemberPermsFields(form, new=False, member_role_id=None) %}
|
||||
<div class="form-content--app-mem">
|
||||
<h4>{{ "portfolios.applications.members.form.project_perms" | translate }}</h4>
|
||||
<div class="application-perms">
|
||||
{% if new %}
|
||||
{% set team_mgmt = form.perms_team_mgmt.name %}
|
||||
{% set env_mgmt = form.perms_env_mgmt.name %}
|
||||
{% set del_env = form.perms_del_env.name %}
|
||||
{% else %}
|
||||
{% set team_mgmt = "perms_team_mgmt-{}".format(member_role_id) %}
|
||||
{% set env_mgmt = "perms_env_mgmt-{}".format(member_role_id) %}
|
||||
{% set del_env = "perms_del_env-{}".format(member_role_id) %}
|
||||
{% endif %}
|
||||
|
||||
{{ CheckboxInput(form.perms_team_mgmt, classes="input__inline-fields", key=team_mgmt, id=team_mgmt, optional=True) }}
|
||||
{{ CheckboxInput(form.perms_env_mgmt, classes="input__inline-fields", key=env_mgmt, id=env_mgmt, optional=True) }}
|
||||
{{ CheckboxInput(form.perms_del_env, classes="input__inline-fields", key=del_env, id=del_env, optional=True) }}
|
||||
</div>
|
||||
<div class="environment_roles environment-roles-new">
|
||||
<h4>{{ "portfolios.applications.members.form.env_access" | translate }}</h4>
|
||||
<hr>
|
||||
{% for environment_data in form.environment_roles %}
|
||||
<optionsinput inline-template
|
||||
v-bind:initial-value="'{{ environment_data.role.data | string }}'"
|
||||
v-bind:name="'{{ environment_data.name | string }}'"
|
||||
v-bind:optional="true"
|
||||
v-bind:watch="true">
|
||||
<div class="usa-input">
|
||||
<fieldset data-ally-disabled="true" v-on:change="onInput" class="usa-input__choices">
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
<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--third">
|
||||
{{ environment_data.role(**{"v-model": "value"}) }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</optionsinput>
|
||||
{{ environment_data.environment_id() }}
|
||||
<hr>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,69 @@
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/checkbox_input.html" import CheckboxInput %}
|
||||
{% from "components/phone_input.html" import PhoneInput %}
|
||||
{% from "applications/fragments/member_perms_form_fields.html" import MemberPermsFields %}
|
||||
|
||||
{% macro MemberFormTemplate(title, next_button, previous=True) %}
|
||||
<div class="modal__form--header">
|
||||
<h1>{{ Icon('avatar') }} {{ title }}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
{{ caller() }}
|
||||
|
||||
<div class='action-group'>
|
||||
{{ next_button }}
|
||||
{% if previous %}
|
||||
<input
|
||||
type='button'
|
||||
v-on:click="previous()"
|
||||
class='action-group__action usa-button usa-button-secondary'
|
||||
value='{{ "common.previous" | translate }}'>
|
||||
{% endif %}
|
||||
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('{{ new_port_mem }}')">{{ "common.cancel" | translate }}</a>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro MemberStepOne(member_form) %}
|
||||
{% set next_button %}
|
||||
<input
|
||||
type='button'
|
||||
v-on:click="next()"
|
||||
v-bind:disabled="invalid"
|
||||
class='action-group__action usa-button'
|
||||
value='{{ "portfolios.applications.members.form.next_button" | translate }}'>
|
||||
{% endset %}
|
||||
|
||||
{% call MemberFormTemplate(title="portfolios.applications.members.form.add_member"|translate, next_button=next_button, previous=False) %}
|
||||
<div class='form-row'>
|
||||
{{ TextInput(member_form.user_data.first_name, validation='requiredField', optional=False) }}
|
||||
</div>
|
||||
<div class='form-row'>
|
||||
{{ TextInput(member_form.user_data.last_name, validation='requiredField', optional=False) }}
|
||||
</div>
|
||||
<div class='form-row'>
|
||||
{{ TextInput(member_form.user_data.email, validation='email', optional=False) }}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ PhoneInput(member_form.user_data.phone_number, member_form.user_data.phone_ext)}}
|
||||
</div>
|
||||
<div class='form-row'>
|
||||
{{ TextInput(member_form.user_data.dod_id, validation='dodId', optional=False) }}
|
||||
</div>
|
||||
<a href="#">How do I find the DoD ID?</a>
|
||||
{% endcall %}
|
||||
{% endmacro %}
|
||||
{% macro MemberStepTwo(member_form, application) %}
|
||||
{% set next_button %}
|
||||
<input
|
||||
type="submit"
|
||||
class='action-group__action usa-button'
|
||||
form="add-app-mem"
|
||||
value='{{ "portfolios.applications.members.form.add_member" | translate}}'>
|
||||
{% endset %}
|
||||
|
||||
{% call MemberFormTemplate(title="portfolios.applications.members.form.step_2_title"|translate, next_button=next_button) %}
|
||||
{{ MemberPermsFields(form=member_form) }}
|
||||
{% endcall %}
|
||||
{% endmacro %}
|
||||
93
templates/applications/index.html
Normal file
93
templates/applications/index.html
Normal file
@@ -0,0 +1,93 @@
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from "components/empty_state.html" import EmptyState %}
|
||||
|
||||
{% extends "portfolios/base.html" %}
|
||||
|
||||
{% set can_create_applications = user_can(permissions.CREATE_APPLICATION) %}
|
||||
|
||||
{% block portfolio_content %}
|
||||
|
||||
<div class='portfolio-applications'>
|
||||
{% include "fragments/flash.html" %}
|
||||
<div class='portfolio-applications__header row'>
|
||||
<div class='portfolio-applications__header--title col col--grow'>Applications</div>
|
||||
<div class='portfolio-applications__header--actions col'>
|
||||
{% if can_create_applications %}
|
||||
<a class='icon-link' href='{{ url_for('applications.view_new_application_step_1', portfolio_id=portfolio.id) }}'>
|
||||
{{ 'portfolios.applications.add_application_text' | translate }}
|
||||
{{ Icon("plus", classes="sidenav__link-icon") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if not portfolio.applications %}
|
||||
|
||||
{{ EmptyState(
|
||||
'This portfolio doesn’t have any applications',
|
||||
action_label='Add a new application' if can_create_applications else None,
|
||||
action_href=url_for('applications.create_new_application_step_1', portfolio_id=portfolio.id) if can_create_applications else None,
|
||||
icon='cloud',
|
||||
sub_message=None if can_create_applications else 'Please contact your JEDI Cloud portfolio administrator to set up a new application.',
|
||||
add_perms=can_create_applications
|
||||
) }}
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class='application-list'>
|
||||
{% for application in portfolio.applications|sort(attribute='name') %}
|
||||
{% set section_name = "application-{}".format(application.id) %}
|
||||
|
||||
<toggler inline-template>
|
||||
<div class='accordion application-list-item'>
|
||||
<header class='accordion__header row'>
|
||||
<div class='col col-grow'>
|
||||
<h3 class='icon-link accordion__title' v-on:click="toggleSection('{{ section_name }}')">{{ application.name }}</h3>
|
||||
<p class='accordion__description'>
|
||||
{{ application.description }}
|
||||
</p>
|
||||
<div class='accordion__actions'>
|
||||
<a class='icon-link' href='{{ url_for("applications.settings", application_id=application.id) }}'>
|
||||
<span>{{ "portfolios.applications.app_settings_text" | translate }}</span>
|
||||
</a>
|
||||
<div class='separator'></div>
|
||||
{% set has_environments = 0 < (application.environments|length) %}
|
||||
<a class='icon-link triangle-box' v-on:click="toggleSection('{{ section_name }}')" disabled="{{ not has_environments }}">
|
||||
<span>Environments ({{ application.environments|length }})</span>
|
||||
{% if has_environments %}
|
||||
<span v-if="selectedSection === '{{ section_name }}'">
|
||||
{{ Icon('caret_up') }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ Icon('caret_down') }}
|
||||
</span>
|
||||
<div class="triangle-up" v-if="selectedSection === '{{ section_name }}'"></div>
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<ul v-show="selectedSection === '{{ section_name }}'">
|
||||
{% for environment in application.environments %}
|
||||
<li class='accordion__item application-list-item__environment'>
|
||||
<div class='application-list-item__environment__name'>
|
||||
<span>{{ environment.displayname }}</span>
|
||||
</div>
|
||||
{% if g.current_user in environment.users %}
|
||||
<a href='{{ url_for("applications.access_environment", environment_id=environment.id)}}' target='_blank' rel='noopener noreferrer' class='application-list-item__environment__csp_link icon-link'>
|
||||
<span>{{ "portfolios.applications.csp_console_text" | translate }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</toggler>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
51
templates/applications/new/step_1.html
Normal file
51
templates/applications/new/step_1.html
Normal file
@@ -0,0 +1,51 @@
|
||||
{% extends "applications/base.html" %}
|
||||
|
||||
{% from "components/alert.html" import Alert %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
|
||||
{% set secondary_breadcrumb = 'portfolios.applications.new_application_title' | translate %}
|
||||
|
||||
{% if application_id %}
|
||||
{% set action = url_for('applications.update_new_application_step_1', portfolio_id=portfolio.id, application_id=application_id) %}
|
||||
{% else %}
|
||||
{% set action = url_for('applications.create_new_application_step_1', portfolio_id=portfolio.id, application_id=application_id) %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% block application_content %}
|
||||
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<div class='subheading'>{{ 'portfolios.applications.settings_heading' | translate }}</div>
|
||||
|
||||
<application-name-and-description inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<form method="POST" action="{{ action }}" v-on:submit="handleSubmit">
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
{{ 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, optional=False) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
{{ TextInput(form.description, paragraph=True, optional=False) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="action-group">
|
||||
{% block next_button %}
|
||||
{{ SaveButton(text=('portfolios.applications.next_button_text' | translate)) }}
|
||||
{% endblock %}
|
||||
</span>
|
||||
</form>
|
||||
</application-name-and-description>
|
||||
|
||||
{% endblock %}
|
||||
72
templates/applications/new/step_2.html
Normal file
72
templates/applications/new/step_2.html
Normal file
@@ -0,0 +1,72 @@
|
||||
{% extends "applications/base.html" %}
|
||||
|
||||
{% from "components/alert.html" import Alert %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from "components/modal.html" import Modal %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
|
||||
{% set secondary_breadcrumb = 'portfolios.applications.new_application_title' | translate %}
|
||||
|
||||
{% block application_content %}
|
||||
|
||||
{% set modalName = "newApplicationConfirmation" %}
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<div class='subheading'>{{ 'portfolios.applications.settings_heading' | translate }}</div>
|
||||
<application-environments inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<form method="POST" action="{{ url_for('applications.view_new_application_step_2', portfolio_id=portfolio.id, application_id=application_id) }}" v-on:submit="handleSubmit">
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
{{ form.csrf_token }}
|
||||
<div> {# this extra div prevents this bug: https://www.pivotaltracker.com/story/show/160768940 #}
|
||||
<div v-cloak v-for="title in errors" :key="title">
|
||||
{{ Alert(message=None, level="error", vue_template=True) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="application-list-item">
|
||||
<header>
|
||||
<h2 class="block-list__title">{{ 'portfolios.applications.environments_heading' | translate }}</h2>
|
||||
<p>
|
||||
{{ 'portfolios.applications.environments_description' | translate }}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<ul>
|
||||
<li v-for="(environment, i) in environments" class="application-edit__env-list-item">
|
||||
<div class="usa-input">
|
||||
<label :for="'environment_names-' + i">Environment Name</label>
|
||||
<input type="text" :id="'environment_names-' + i" v-model="environment.name" @input="onInput" placeholder="e.g. Development, Staging, Production"/> <input type="hidden" :name="'environment_names-' + i" v-model="environment.name"/>
|
||||
</div>
|
||||
<div class="application-edit__env-list-item-block">
|
||||
<button v-on:click="removeEnvironment(i)" v-if="environments.length > 1" type="button" class="application-edit__env-list-item__remover">
|
||||
{{ Icon('trash') }}
|
||||
<span>Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="block-list__footer">
|
||||
<button
|
||||
v-on:click="addEnvironment"
|
||||
class="icon-link"
|
||||
tabindex="0"
|
||||
type="button">
|
||||
{{ 'portfolios.applications.add_another_environment' | translate }}
|
||||
{{ Icon("plus") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="action-group">
|
||||
{% block next_button %}
|
||||
{{ SaveButton(text=('portfolios.applications.create_button_text' | translate)) }}
|
||||
{% endblock %}
|
||||
</span>
|
||||
</form>
|
||||
</application-environments>
|
||||
|
||||
{% endblock %}
|
||||
365
templates/applications/settings.html
Normal file
365
templates/applications/settings.html
Normal file
@@ -0,0 +1,365 @@
|
||||
{% extends "applications/base.html" %}
|
||||
|
||||
{% from "components/alert.html" import Alert %}
|
||||
{% from "components/delete_confirmation.html" import DeleteConfirmation %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% import "applications/fragments/new_member_modal_content.html" as member_steps %}
|
||||
{% from "applications/fragments/member_perms_form_fields.html" import MemberPermsFields %}
|
||||
{% from "components/modal.html" import Modal %}
|
||||
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
|
||||
{% from "components/pagination.html" import Pagination %}
|
||||
{% from "components/save_button.html" import SaveButton %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/toggle_list.html" import ToggleButton, ToggleSection %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/checkbox_input.html" import CheckboxInput %}
|
||||
{% from "components/phone_input.html" import PhoneInput %}
|
||||
|
||||
{% set secondary_breadcrumb = 'portfolios.applications.existing_application_title' | translate({ "application_name": application.name }) %}
|
||||
|
||||
{% block application_content %}
|
||||
|
||||
<div class='subheading'>{{ 'portfolios.applications.settings.name_description' | translate }}</div>
|
||||
|
||||
{% if user_can(permissions.EDIT_APPLICATION) %}
|
||||
<base-form inline-template>
|
||||
<form method="POST" action="{{ url_for('applications.update', application_id=application.id) }}">
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
{{ application_form.csrf_token }}
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
{{ TextInput(application_form.name, optional=False) }}
|
||||
{{ TextInput(application_form.description, paragraph=True, optional=False) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel__footer">
|
||||
<div class="action-group">
|
||||
{{ SaveButton('common.save_changes'|translate) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</base-form>
|
||||
{% else %}
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
<p>
|
||||
{{ "fragments.edit_application_form.explain" | translate }}
|
||||
</p>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<div class="usa-input usa-input__title__view-only">
|
||||
{{ application_form.name.label() }}
|
||||
</div>
|
||||
<p>
|
||||
{{ application_form.name.data }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<div class="usa-input usa-input__title__view-only">
|
||||
{{ application_form.description.label() }}
|
||||
</div>
|
||||
<p>
|
||||
{{ application_form.description.data }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not application.members %}
|
||||
{% set user_can_invite = user_can(permissions.CREATE_APPLICATION_MEMBER) %}
|
||||
|
||||
<div class='empty-state'>
|
||||
<p class='empty-state__message'>{{ ("portfolios.applications.team_settings.blank_slate.title" | translate) }}</p>
|
||||
|
||||
{{ 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 %}
|
||||
{% set new_member_modal_name = "add-app-mem" %}
|
||||
<a class="usa-button usa-button-big" v-on:click="openModal('{{ new_member_modal_name }}')">
|
||||
{{ "portfolios.applications.team_settings.blank_slate.action_label" | translate }}
|
||||
</a>
|
||||
{{ MultiStepModalForm(
|
||||
name=new_member_modal_name,
|
||||
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)
|
||||
],
|
||||
) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<div class='subheading'>
|
||||
{{ 'portfolios.applications.settings.team_members' | translate }}
|
||||
|
||||
{% set new_member_modal_name = "add-app-mem" %}
|
||||
{% if user_can(permissions.CREATE_APPLICATION_MEMBER) %}
|
||||
<a class="icon-link modal-link icon-link__add" v-on:click="openModal('{{ new_member_modal_name }}')">
|
||||
{{ Icon("plus") }}
|
||||
{{ "portfolios.applications.add_member" | translate }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<section class="member-list application-list" id="application-members">
|
||||
<div class='responsive-table-wrapper panel'>
|
||||
{% if g.matchesPath("application-members") %}
|
||||
{% include "fragments/flash.html" %}
|
||||
{% endif %}
|
||||
{% for member in members %}
|
||||
{% set modal_name = "edit_member-{}".format(loop.index) %}
|
||||
{% call Modal(modal_name) %}
|
||||
<div class="modal__form--header">
|
||||
<h1>{{ Icon('avatar') }} {{ member.user_name }}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<base-form inline-template>
|
||||
<form id='{{ modal_name }}' method="POST" action="{{ url_for('applications.update_member', application_id=application.id, application_role_id=member.role_id) }}">
|
||||
{{ member.form.csrf_token }}
|
||||
{{ MemberPermsFields(form=member.form, member_role_id=member.role_id) }}
|
||||
<div class="action-group">
|
||||
{{ SaveButton(text='Update', element='input', additional_classes='action-group__action') }}
|
||||
<a class='action-group__action usa-button usa-button-secondary' v-on:click="closeModal('{{ modal_name }}')">{{ "common.cancel" | translate }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</base-form>
|
||||
{% endcall %}
|
||||
{% endfor %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Member</th>
|
||||
<th>Project Permissions</th>
|
||||
<th>Environment Access</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for member in members %}
|
||||
{% set modal_name = "edit_member-{}".format(loop.index) %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ member.user_name }}
|
||||
<a class="icon-link" v-on:click="openModal('{{ modal_name }}')">
|
||||
{{ Icon('edit') }}
|
||||
</a>
|
||||
<br>
|
||||
{% if member.role_status == 'pending' %}
|
||||
<span class='label label--purple'>INVITE PENDING</span>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{% for perm, value in member.permission_sets.items() %}
|
||||
{{ ("portfolios.applications.members.{}.{}".format(perm, value)) | translate }}<br>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% for env in member.environment_roles %}
|
||||
{{ env.environment_name }}{% if not env == member.environment_roles[-1]%},{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% if member.role_status == 'pending' %}
|
||||
<a href="#">Resend Invite</a><br>
|
||||
<a href="#">Revoke Invite</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if user_can(permissions.CREATE_APPLICATION_MEMBER) %}
|
||||
{% import "applications/fragments/new_member_modal_content.html" as member_steps %}
|
||||
{{ MultiStepModalForm(
|
||||
name=new_member_modal_name,
|
||||
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)
|
||||
],
|
||||
) }}
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<div class='subheading'>
|
||||
{{ 'common.resource_names.environments' | translate }}
|
||||
|
||||
{% if user_can(permissions.CREATE_ENVIRONMENT) %}
|
||||
{% include "applications/fragments/add_new_environment.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
{% if g.matchesPath("application-environments") %}
|
||||
{% include "fragments/flash.html" %}
|
||||
{% endif %}
|
||||
<div class="panel__content">
|
||||
<div class="accordion-table accordion-table-list">
|
||||
<ul class="accordion-table__items">
|
||||
{% for env in environments_obj %}
|
||||
{% set edit_form = env['edit_form'] %}
|
||||
<toggler inline-template>
|
||||
<li class="accordion-table__item">
|
||||
<div class="accordion-table__item-content form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
<div class="environment-list__item">
|
||||
<span>
|
||||
{{ env['name'] }}
|
||||
</span>
|
||||
{% if env['pending'] %}
|
||||
<span class='usa-label'>PROCESSING</span>
|
||||
{% endif %}
|
||||
{% if env['pending'] %}
|
||||
<span class="icon-link">
|
||||
{% set edit_environment_button %}
|
||||
{{ Icon('edit') }}
|
||||
{% endset %}
|
||||
|
||||
{{
|
||||
ToggleButton(
|
||||
open_html=edit_environment_button,
|
||||
close_html=edit_environment_button,
|
||||
section_name="edit"
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{% endif %}
|
||||
<span class="accordion-table__item__toggler icon-link">
|
||||
{% set members_button = "portfolios.applications.member_count" | translate({'count': env['member_count']}) %}
|
||||
{{
|
||||
ToggleButton(
|
||||
open_html=members_button,
|
||||
close_html=members_button,
|
||||
section_name="members"
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-col form-col--third">
|
||||
{% if env['pending'] %}
|
||||
<em>Cloud service provider link unavailable</em>
|
||||
{% else %}
|
||||
<a href='{{ url_for("applications.access_environment", environment_id=env.id)}}' target='_blank' rel='noopener noreferrer' class='application-list-item__environment__csp_link icon-link'>
|
||||
<span>{{ "portfolios.applications.csp_link" | translate }} {{ Icon('link', classes="icon--tiny") }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% call ToggleSection(section_name="members") %}
|
||||
<ul>
|
||||
{% for member in env['members'] %}
|
||||
<li class="accordion-table__item__expanded">
|
||||
{{ member }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endcall %}
|
||||
|
||||
{% call ToggleSection(section_name="edit") %}
|
||||
<ul>
|
||||
<li class="accordion-table__item__expanded">
|
||||
<form action="{{ url_for('applications.update_environment', environment_id=env['id']) }}" method="post" v-on:submit="handleSubmit">
|
||||
{{ edit_form.csrf_token }}
|
||||
{{ TextInput(edit_form.name, validation='requiredField') }}
|
||||
{{
|
||||
SaveButton(
|
||||
text=("common.save" | translate)
|
||||
)
|
||||
}}
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
{% endcall %}
|
||||
</li>
|
||||
</toggler>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{% if user_can(permissions.DELETE_APPLICATION) %}
|
||||
{% set env_count = application.environments | length %}
|
||||
{% if env_count == 1 %}
|
||||
{% set pluralized_env = "environment" %}
|
||||
{% else %}
|
||||
{% set pluralized_env = "environments" %}
|
||||
{% endif %}
|
||||
|
||||
<div class='subheading'>
|
||||
{{ "portfolios.applications.delete.subheading" | translate }}
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel__content">
|
||||
<div class="form-row">
|
||||
<div class="form-col form-col--two-thirds">
|
||||
{{ "portfolios.applications.delete.panel_text" | translate({"name": application.name, "env_count": env_count , "pluralized_env": pluralized_env}) | safe }}
|
||||
</div>
|
||||
<div class="form-col form-col--third">
|
||||
<div class="usa-input">
|
||||
<input
|
||||
id="delete-application"
|
||||
type="button"
|
||||
v-on:click="openModal('delete-application')"
|
||||
class='usa-button button-danger-outline'
|
||||
value="{{ 'portfolios.applications.delete.button' | translate }}"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% call Modal(name="delete-application") %}
|
||||
<h1>{{ "portfolios.applications.delete.header" | translate }}</h1>
|
||||
|
||||
{{
|
||||
Alert(
|
||||
title=("components.modal.destructive_title" | translate),
|
||||
message=("portfolios.applications.delete.alert.message" | translate),
|
||||
level="warning"
|
||||
)
|
||||
}}
|
||||
|
||||
{{
|
||||
DeleteConfirmation(
|
||||
modal_id="delete_application",
|
||||
delete_text=('portfolios.applications.delete.button' | translate),
|
||||
delete_action= url_for('applications.delete', application_id=application.id),
|
||||
form=application_form
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% if user_can(permissions.VIEW_APPLICATION_ACTIVITY_LOG) %}
|
||||
{% include "fragments/audit_events_log.html" %}
|
||||
{{ Pagination(audit_events, url=url_for('applications.settings', application_id=application.id)) }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user