project -> application everywhere

This commit is contained in:
dandds
2019-01-10 16:38:00 -05:00
parent 9ad3c45200
commit 3fc323d785
67 changed files with 644 additions and 609 deletions

View File

@@ -12,7 +12,7 @@
<br>
in Environment <code>{{ event.event_details["environment_id"] }}</code> ({{ event.event_details["environment"] }})
<br>
in Application <code>{{ event.event_details["project_id"] }}</code> ({{ event.event_details["project"] }})
in Application <code>{{ event.event_details["application_id"] }}</code> ({{ event.event_details["application"] }})
<br>
in Portfolio <code>{{ event.event_details["workspace_id"] }}</code> ({{ event.event_details["workspace"] }})
{% endif %}

View File

@@ -1,6 +1,6 @@
{% from "components/text_input.html" import TextInput %}
{% set title_text = ('fragments.edit_project_form.existing_project_title' | translate({ "project_name": project.name })) if project else ('fragments.edit_project_form.new_project_title' | translate) %}
{% set title_text = ('fragments.edit_application_form.existing_application_title' | translate({ "application_name": application.name })) if application else ('fragments.edit_application_form.new_application_title' | translate) %}
{{ form.csrf_token }}
<div class="panel">
@@ -10,7 +10,7 @@
<div class="panel__content">
<p>
{{ "fragments.edit_project_form.explain" | translate }}
{{ "fragments.edit_application_form.explain" | translate }}
</p>
{{ TextInput(form.name) }}
{{ TextInput(form.description, paragraph=True) }}

View File

@@ -3,7 +3,7 @@
{% set subnav = [
{"label":"Financial Verification", "href":"#financial-verification"},
{"label":"ID/IQ CLINs", "href":"#idiq-clins"},
{"label":"JEDI Cloud Projects", "href":"#jedi-cloud-projects"},
{"label":"JEDI Cloud Applications", "href":"#jedi-cloud-applications"},
] %}
{% block doc_content %}
@@ -122,13 +122,13 @@
<hr>
<h2 id='jedi-cloud-projects'>JEDI Cloud Applications</h2>
<h2 id='jedi-cloud-applications'>JEDI Cloud Applications</h2>
<h3>How are applications organized in the JEDI Cloud?</h3>
<h4>Application Structure for JEDI Cloud</h4>
<p>Separate your portfolio into applications and environments; this allows your team to manage user access to systems more securely and track expenditures for each project.</p>
<p>Separate your portfolio into applications and environments; this allows your team to manage user access to systems more securely and track expenditures for each application.</p>
<p>Heres an example:<br>
Application A has a development environment, production environment, and sandbox environment. The cloud resources in the development environment are grouped and accessed separately from the production environment and sandbox environment.</p>

View File

@@ -3,14 +3,14 @@
<nav class='sidenav workspace-navigation'>
<ul>
{{ SidenavItem(
("navigation.workspace_navigation.projects" | translate),
href=url_for("workspaces.workspace_projects", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/projects'),
("navigation.workspace_navigation.applications" | translate),
href=url_for("workspaces.workspace_applications", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/applications'),
subnav=None if not user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) else [
{
"label": ("navigation.workspace_navigation.add_new_project_label" | translate),
"href": url_for('workspaces.new_project', workspace_id=workspace.id),
"active": g.matchesPath('\/workspaces\/[A-Za-z0-9-]*\/projects'),
"label": ("navigation.workspace_navigation.add_new_application_label" | translate),
"href": url_for('workspaces.new_application', workspace_id=workspace.id),
"active": g.matchesPath('\/workspaces\/[A-Za-z0-9-]*\/applications'),
"icon": "plus"
}
]

View File

@@ -17,7 +17,7 @@
<p>The Portfolio Owner is the primary point of contact and technical administrator of the JEDI Cloud Portfolio and will have the
following responsibilities:</p>
<ul>
<li>Organize your cloud-hosted systems into projects and environments</li>
<li>Organize your cloud-hosted systems into applications and environments</li>
<li>Add users to this portfolio and manage members</li>
<li>Manage access to the JEDI Cloud service providers portal</li>
</ul>

View File

@@ -4,11 +4,11 @@
{% block workspace_content %}
<form method="POST" action="{{ url_for('workspaces.edit_project', workspace_id=workspace.id, project_id=project.id) }}">
<form method="POST" action="{{ url_for('workspaces.edit_application', workspace_id=workspace.id, application_id=application.id) }}">
{% include "fragments/edit_project_form.html" %}
{% include "fragments/edit_application_form.html" %}
<div class="block-list project-list-item">
<div class="block-list application-list-item">
<header class="block-list__header block-list__header--grow">
<h2 class="block-list__title">Application Environments</h2>
<p>
@@ -17,8 +17,8 @@
</header>
<ul>
{% for environment in project.environments %}
<li class="block-list__item project-edit__env-list-item">
{% for environment in application.environments %}
<li class="block-list__item application-edit__env-list-item">
<div class="usa-input">
<label>Environment Name</label>
<input type="text" value="{{ environment.name }}" readonly />

View File

@@ -0,0 +1,55 @@
{% from "components/icon.html" import Icon %}
{% from "components/empty_state.html" import EmptyState %}
{% extends "workspaces/base.html" %}
{% block workspace_content %}
{% if not workspace.applications %}
{% set can_create_applications = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
{{ EmptyState(
'This portfolio doesnt have any applications yet.',
action_label='Add a New Application' if can_create_applications else None,
action_href=url_for('workspaces.new_application', workspace_id=workspace.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.'
) }}
{% else %}
{% for application in workspace.applications %}
<div v-cloak class='block-list application-list-item'>
<header class='block-list__header'>
<h2 class='block-list__title'>{{ application.name }} ({{ application.environments|length }} environments)</h2>
{% if user_can(permissions.RENAME_APPLICATION_IN_WORKSPACE) %}
<a class='icon-link' href='{{ url_for("workspaces.edit_application", workspace_id=workspace.id, application_id=application.id) }}'>
{{ Icon('edit') }}
<span>edit</span>
</a>
{% endif %}
</header>
<ul>
{% for environment in application.environments %}
<li class='block-list__item application-list-item__environment'>
<a href='{{ url_for("workspaces.access_environment", workspace_id=workspace.id, environment_id=environment.id)}}' target='_blank' rel='noopener noreferrer' class='application-list-item__environment__link'>
{{ Icon('link') }}
<span>{{ environment.name }}</span>
</a>
<div class='application-list-item__environment__members'>
<div class='label'>{{ environment.num_users }}</div>
<span>members</span>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
{% endif %}
{% endblock %}

View File

@@ -7,11 +7,11 @@
{% block workspace_content %}
{% set modalName = "newProjectConfirmation" %}
{% set modalName = "newApplicationConfirmation" %}
{% include "fragments/flash.html" %}
<new-project inline-template v-bind:initial-data='{{ form.data|tojson }}' modal-name='{{ modalName }}'>
<form method="POST" action="{{ url_for('workspaces.create_project', workspace_id=workspace.id) }}" v-on:submit="handleSubmit">
<new-application inline-template v-bind:initial-data='{{ form.data|tojson }}' modal-name='{{ modalName }}'>
<form method="POST" action="{{ url_for('workspaces.create_application', workspace_id=workspace.id) }}" v-on:submit="handleSubmit">
{% call Modal(name=modalName, dismissable=False) %}
<h1>Create application !{ name }</h1>
@@ -21,7 +21,7 @@
<span v-for="(environment, index) in environments">
<strong>!{environment.name}</strong><template v-if="index < (environments.length - 1)">, </template>
</span>
will be created as individual cloud resource groups under <strong>!{ name }</strong> project.
will be created as individual cloud resource groups under <strong>!{ name }</strong> application.
</p>
<div class='action-group'>
@@ -30,7 +30,7 @@
</div>
{% endcall %}
{% include "fragments/edit_project_form.html" %}
{% include "fragments/edit_application_form.html" %}
<div> {# this extra div prevents this bug: https://www.pivotaltracker.com/story/show/160768940 #}
<div v-cloak v-for="title in errors" :key="title">
@@ -38,7 +38,7 @@
</div>
</div>
<div class="block-list project-list-item">
<div class="block-list application-list-item">
<header class="block-list__header block-list__header--grow">
<h2 class="block-list__title">Application Environments</h2>
<p>
@@ -47,13 +47,13 @@
</header>
<ul>
<li v-for="(environment, i) in environments" class="block-list__item project-edit__env-list-item">
<li v-for="(environment, i) in environments" class="block-list__item 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" placeholder="e.g. Development, Staging, Production"/>
<input type="hidden" :name="'environment_names-' + i" v-model="environment.name"/>
</div>
<button v-on:click="removeEnvironment(i)" v-if="environments.length > 1" type="button" class='project-edit__env-list-item__remover'>
<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>
@@ -69,6 +69,6 @@
<button class="usa-button usa-button-primary" tabindex="0" type="submit">Create Application</button>
</div>
</form>
</new-project>
</new-application>
{% endblock %}

View File

@@ -24,7 +24,7 @@
<div class='action-group'>
<button type="submit" class="usa-button usa-button-big usa-button-primary" tabindex="0">Save</button>
<a href='{{ url_for("workspaces.workspace_projects", workspace_id=workspace.id) }}' class='action-group__action icon-link'>
<a href='{{ url_for("workspaces.workspace_applications", workspace_id=workspace.id) }}' class='action-group__action icon-link'>
{{ Icon('x') }}
<span>Cancel</span>
</a>

View File

@@ -14,7 +14,7 @@
{% for workspace in workspaces %}
<tr>
<td>
<a class='icon-link icon-link--large' href="/workspaces/{{ workspace.id }}/projects">{{ workspace.name }}</a><br>
<a class='icon-link icon-link--large' href="/workspaces/{{ workspace.id }}/applications">{{ workspace.name }}</a><br>
</td>
<td>
#{{ workspace.legacy_task_order.number }}

View File

@@ -69,24 +69,24 @@
<div class='search-bar'>
<div class='usa-input search-input'>
<label for='project-search'>Search by application name</label>
<input type='search' id='project-search' name='project-search' placeholder="Search by application name"/>
<label for='application-search'>Search by application name</label>
<input type='search' id='application-search' name='application-search' placeholder="Search by application name"/>
<button type="submit">
<span class="hide">Search</span>
</button>
</div>
</div>
{% for project in projects %}
{% set revoke_modal_name = (project.id|string) + 'RevokeModal' %}
<edit-project-roles inline-template name="{{ project.name }}" id="{{ project.id }}">
<div is='toggler' default-visible class='block-list project-list-item'>
{% for application in applications %}
{% set revoke_modal_name = (application.id|string) + 'RevokeModal' %}
<edit-application-roles inline-template name="{{ application.name }}" id="{{ application.id }}">
<div is='toggler' default-visible class='block-list application-list-item'>
<template slot-scope='props'>
<header class='block-list__header'>
<button v-on:click='props.toggle' class='icon-link icon-link--large icon-link--default spend-table__project__toggler'>
<button v-on:click='props.toggle' class='icon-link icon-link--large icon-link--default spend-table__application__toggler'>
<template v-if='props.isVisible'>{{ Icon('caret_down') }}</template>
<template v-else>{{ Icon('caret_right') }}</template>
<h3 class="block-list__title">{{ project.name }}</h3>
<h3 class="block-list__title">{{ application.name }}</h3>
</button>
<span><a v-on:click="openModal('{{ revoke_modal_name }}')" class="icon-link icon-link--danger">revoke all access</a></span>
</header>
@@ -94,7 +94,7 @@
<div>
<h1>Revoke Access</h1>
<p>
Confirming will revoke access for {{ member.user.full_name }} to any environments associated with {{ project.name }}.
Confirming will revoke access for {{ member.user.full_name }} to any environments associated with {{ application.name }}.
</p>
<div class='action-group'>
<a v-on:click="doRevoke(); closeModal('{{ revoke_modal_name }}')" class='action-group__action usa-button'>Confirm</a>
@@ -103,19 +103,19 @@
</div>
{% endcall %}
<ul v-show='props.isVisible'>
{% for env in project.environments %}
{% for env in application.environments %}
{% set role = EnvironmentRoles.get(member.user_id, env.id).role %}
{% set env_modal_name = (env.id|string) + 'RolesModal' %}
<li class='block-list__item'>
<edit-environment-role inline-template initial-data='{{ role or "" }}' v-bind:choices='{{ choices | tojson }}' v-bind:project-id="'{{ project.id }}'">
<div class='project-list-item__environment'>
<span class='project-list-item__environment__link'>
<edit-environment-role inline-template initial-data='{{ role or "" }}' v-bind:choices='{{ choices | tojson }}' v-bind:application-id="'{{ application.id }}'">
<div class='application-list-item__environment'>
<span class='application-list-item__environment__link'>
{{ env.name }}
</span>
<div class='project-list-item__environment__actions'>
<div class='application-list-item__environment__actions'>
<span v-bind:class="label_class" v-html:on=displayName></span>
<button v-on:click="openModal('{{env_modal_name}}')" type="button" class="icon-link">set role</button>
{% call Modal(name=env_modal_name, dismissable=False) %}
@@ -170,7 +170,7 @@
</ul>
</template>
</div>
</edit-project-roles>
</edit-application-roles>
{% endfor %}
<div class='action-group'>

View File

@@ -1,55 +0,0 @@
{% from "components/icon.html" import Icon %}
{% from "components/empty_state.html" import EmptyState %}
{% extends "workspaces/base.html" %}
{% block workspace_content %}
{% if not workspace.projects %}
{% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
{{ EmptyState(
'This portfolio doesnt have any applications yet.',
action_label='Add a New Application' if can_create_projects else None,
action_href=url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None,
icon='cloud',
sub_message=None if can_create_projects else 'Please contact your JEDI Cloud portfolio administrator to set up a new project.'
) }}
{% else %}
{% for project in workspace.projects %}
<div v-cloak class='block-list project-list-item'>
<header class='block-list__header'>
<h2 class='block-list__title'>{{ project.name }} ({{ project.environments|length }} environments)</h2>
{% if user_can(permissions.RENAME_APPLICATION_IN_WORKSPACE) %}
<a class='icon-link' href='{{ url_for("workspaces.edit_project", workspace_id=workspace.id, project_id=project.id) }}'>
{{ Icon('edit') }}
<span>edit</span>
</a>
{% endif %}
</header>
<ul>
{% for environment in project.environments %}
<li class='block-list__item project-list-item__environment'>
<a href='{{ url_for("workspaces.access_environment", workspace_id=workspace.id, environment_id=environment.id)}}' target='_blank' rel='noopener noreferrer' class='project-list-item__environment__link'>
{{ Icon('link') }}
<span>{{ environment.name }}</span>
</a>
<div class='project-list-item__environment__members'>
<div class='label'>{{ environment.num_users }}</div>
<span>members</span>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
{% endif %}
{% endblock %}

View File

@@ -113,18 +113,18 @@
{% set two_months_ago_index = two_months_ago.strftime('%m/%Y') %}
{% set reports_url = url_for("workspaces.workspace_reports", workspace_id=workspace.id) %}
{% if not workspace.projects %}
{% if not workspace.applications %}
{% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
{% set can_create_applications = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
{% set message = 'This portfolio has no cloud environments set up, so there is no spending data to report. Create an application with some cloud environments to get started.'
if can_create_projects
if can_create_applications
else 'This portfolio has no cloud environments set up, so there is no spending data to report. Contact the portfolio owner to set up some cloud environments.'
%}
{{ EmptyState(
'Nothing to report',
action_label='Add a New Application' if can_create_projects else None,
action_href=url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None,
action_label='Add a New Application' if can_create_applications else None,
action_href=url_for('workspaces.new_application', workspace_id=workspace.id) if can_create_applications else None,
icon='chart',
sub_message=message
) }}
@@ -353,7 +353,7 @@
</div>
<spend-table
v-bind:projects='{{ monthly_totals['projects'] | tojson }}'
v-bind:applications='{{ monthly_totals['applications'] | tojson }}'
v-bind:workspace='{{ workspace_totals | tojson }}'
v-bind:environments='{{ monthly_totals['environments'] | tojson }}'
current-month-index='{{ current_month_index }}'
@@ -383,40 +383,40 @@
</tr>
</tbody>
<tbody v-for='(project, name) in projectsState' class='spend-table__project'>
<tbody v-for='(application, name) in applicationsState' class='spend-table__application'>
<tr>
<th scope='rowgroup'>
<button v-on:click='toggle($event, name)' class='icon-link icon-link--large spend-table__project__toggler'>
<template v-if='project.isVisible'>{{ Icon('caret_down') }}</template>
<button v-on:click='toggle($event, name)' class='icon-link icon-link--large spend-table__application__toggler'>
<template v-if='application.isVisible'>{{ Icon('caret_down') }}</template>
<template v-else>{{ Icon('caret_right') }}</template>
<span v-html='name'></span>
</button>
</th>
<td class='table-cell--align-right previous-month'>
<span v-html='formatDollars(project[twoMonthsAgoIndex] || 0)'></span>
<span v-html='formatDollars(application[twoMonthsAgoIndex] || 0)'></span>
</td>
<td class='table-cell--align-right previous-month'>
<span v-html='formatDollars(project[prevMonthIndex] || 0)'></span>
<span v-html='formatDollars(application[prevMonthIndex] || 0)'></span>
</td>
<td class='table-cell--align-right current-month'>
<span v-html='formatDollars(project[currentMonthIndex] || 0)'></span>
<span v-html='formatDollars(application[currentMonthIndex] || 0)'></span>
</td>
<td class='table-cell--expand current-month meter-cell'>
<span class='spend-table__meter-value'>
<span v-html='round( 100 * ((project[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%"'></span>
<span v-html='round( 100 * ((application[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%"'></span>
</span>
<meter v-bind:value='project[currentMonthIndex] || 0' min='0' v-bind:max='workspace[currentMonthIndex] || 1'>
<div class='meter__fallback' v-bind:style='"width:" + round( 100 * ((project[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%;"'></div>
<meter v-bind:value='application[currentMonthIndex] || 0' min='0' v-bind:max='workspace[currentMonthIndex] || 1'>
<div class='meter__fallback' v-bind:style='"width:" + round( 100 * ((application[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%;"'></div>
</meter>
</td>
</tr>
<tr v-for='(environment, envName) in environments[name]' v-show='project.isVisible' class='spend-table__project__env'>
<tr v-for='(environment, envName) in environments[name]' v-show='application.isVisible' class='spend-table__application__env'>
<th scope='rowgroup'>
<a href='#' class='icon-link spend-table__project__env'>
<a href='#' class='icon-link spend-table__application__env'>
{{ Icon('link') }}
<span v-html='envName'></span>
</a>