Merge pull request #218 from dod-ccpo/no-projects

Empty states and some permissions
This commit is contained in:
montana-mil 2018-08-28 13:46:54 -04:00 committed by GitHub
commit 06968940b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 136 additions and 36 deletions

View File

@ -12,6 +12,8 @@ from atst.domain.workspaces import Workspaces
from atst.domain.projects import Projects
from atst.forms.new_project import NewProjectForm
from atst.forms.new_member import NewMemberForm
from atst.domain.authz import Authorization
from atst.models.permissions import Permissions
bp = Blueprint("workspaces", __name__)
@ -26,7 +28,15 @@ def workspace():
)
except UnauthorizedError:
pass
return {"workspace": workspace}
def user_can(permission):
if workspace:
return Authorization.has_workspace_permission(
g.current_user, workspace, permission
)
return False
return {"workspace": workspace, "permissions": Permissions, "user_can": user_can}
@bp.route("/workspaces")

View File

@ -14,7 +14,7 @@
@include icon-color($color-gray-light);
}
p {
.empty-state__message {
@include h2;
line-height: 1.2;
max-width: 15em;
@ -24,4 +24,13 @@
@include h1;
}
}
.empty-state__sub-message {
@include h4;
color: $color-gray;
@include media($large-screen) {
@include h3;
}
}
}

View File

@ -1,13 +1,20 @@
{% from "components/icon.html" import Icon %}
{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%}
{% macro EmptyState(message, action_label, action_href, icon=None, sub_message=None) -%}
<div class='empty-state'>
<p>{{ message }}</p>
<p class='empty-state__message'>{{ message }}</p>
{% if icon %}
{{ Icon(icon) }}
{% endif %}
<a href='{{ actionHref }}' class='usa-button usa-button-big'>{{ actionLabel }}</a>
{% if sub_message %}
<p class='empty-state__sub-message'>{{ sub_message }}</p>
{% endif %}
{% if action_href and action_label %}
<a href='{{ action_href }}' class='usa-button usa-button-big'>{{ action_label }}</a>
{% endif %}
</div>
{%- endmacro %}

View File

@ -6,7 +6,7 @@
"Projects",
href=url_for("workspaces.workspace_projects", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/projects'),
subnav=[
subnav=None if not user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) else [
{
"label": "Add New Project",
"href": url_for('workspaces.new_project', workspace_id=workspace.id),
@ -20,7 +20,7 @@
"Members",
href=url_for("workspaces.workspace_members", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/members'),
subnav=[
subnav=None if not user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) else [
{
"label": "Add New Member",
"href": url_for("workspaces.new_member", workspace_id=workspace.id),

View File

@ -29,8 +29,8 @@
{{ EmptyState(
'There are currently no active requests for you to see.',
actionLabel='Create a new JEDI Cloud Request',
actionHref=url_for('requests.requests_form_new', screen=1),
action_label='Create a new JEDI Cloud Request',
action_href=url_for('requests.requests_form_new', screen=1),
icon='document'
) }}

View File

@ -6,10 +6,13 @@
{% if not workspace.members %}
{% set user_can_invite = user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) %}
{{ EmptyState(
'There are currently no members in this Workspace.',
actionLabel='Invite a new Member',
actionHref='/members/new',
action_label='Invite a new Member' if user_can_invite else None,
action_href='/members/new' if user_can_invite else None,
sub_message=None if user_can_invite else 'Please contact your JEDI workspace administrator to invite new members.',
icon='avatar'
) }}

View File

@ -1,36 +1,54 @@
{% from "components/icon.html" import Icon %}
{% from "components/alert.html" import Alert %}
{% from "components/empty_state.html" import EmptyState %}
{% extends "base_workspace.html" %}
{% block workspace_content %}
{% for project in workspace.projects %}
<div class='block-list project-list-item'>
<header class='block-list__header'>
<h2 class='block-list__title'>{{ project.name }} ({{ project.environments|length }} environments)</h2>
<a class='icon-link' href='/workspaces/123456/projects/789/edit'>
{{ Icon('edit') }}
<span>edit</span>
</a>
</header>
<ul>
{% for environment in project.environments %}
<li class='block-list__item project-list-item__environment'>
<a href='/' target='_blank' rel='noopener noreferrer' class='project-list-item__environment__link'>
{{ Icon('link') }}
<span>{{ environment.name }}</span>
</a>
{% if not workspace.projects %}
<div class='project-list-item__environment__members'>
<div class='label'>0</div>
<span>members</span>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
{% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
{{ EmptyState(
'This workspace doesnt have any projects yet.',
action_label='Add a New Project' 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 workspace administrator to set up a new project.'
) }}
{% else %}
{% for project in workspace.projects %}
<div class='block-list project-list-item'>
<header class='block-list__header'>
<h2 class='block-list__title'>{{ project.name }} ({{ project.environments|length }} environments)</h2>
<a class='icon-link' href='/workspaces/123456/projects/789/edit'>
{{ Icon('edit') }}
<span>edit</span>
</a>
</header>
<ul>
{% for environment in project.environments %}
<li class='block-list__item project-list-item__environment'>
<a href='/' 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'>0</div>
<span>members</span>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
{% endif %}
{% endblock %}

View File

@ -0,0 +1,53 @@
from tests.factories import UserFactory, WorkspaceFactory
from atst.domain.workspaces import Workspaces
from atst.models.workspace_user import WorkspaceUser
def test_user_with_permission_has_add_project_link(client, user_session):
user = UserFactory.create()
workspace = WorkspaceFactory.create()
Workspaces._create_workspace_role(user, workspace, "owner")
user_session(user)
response = client.get("/workspaces/{}/projects".format(workspace.id))
assert (
'href="/workspaces/{}/projects/new"'.format(workspace.id).encode()
in response.data
)
def test_user_without_permission_has_no_add_project_link(client, user_session):
user = UserFactory.create()
workspace = WorkspaceFactory.create()
Workspaces._create_workspace_role(user, workspace, "developer")
user_session(user)
response = client.get("/workspaces/{}/projects".format(workspace.id))
assert (
'href="/workspaces/{}/projects/new"'.format(workspace.id).encode()
not in response.data
)
def test_user_with_permission_has_add_member_link(client, user_session):
user = UserFactory.create()
workspace = WorkspaceFactory.create()
Workspaces._create_workspace_role(user, workspace, "owner")
user_session(user)
response = client.get("/workspaces/{}/members".format(workspace.id))
assert (
'href="/workspaces/{}/members/new"'.format(workspace.id).encode()
in response.data
)
def test_user_without_permission_has_no_add_member_link(client, user_session):
user = UserFactory.create()
workspace = WorkspaceFactory.create()
Workspaces._create_workspace_role(user, workspace, "developer")
user_session(user)
response = client.get("/workspaces/{}/members".format(workspace.id))
assert (
'href="/workspaces/{}/members/new"'.format(workspace.id).encode()
not in response.data
)