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.domain.projects import Projects
from atst.forms.new_project import NewProjectForm from atst.forms.new_project import NewProjectForm
from atst.forms.new_member import NewMemberForm from atst.forms.new_member import NewMemberForm
from atst.domain.authz import Authorization
from atst.models.permissions import Permissions
bp = Blueprint("workspaces", __name__) bp = Blueprint("workspaces", __name__)
@ -26,7 +28,15 @@ def workspace():
) )
except UnauthorizedError: except UnauthorizedError:
pass 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") @bp.route("/workspaces")

View File

@ -14,7 +14,7 @@
@include icon-color($color-gray-light); @include icon-color($color-gray-light);
} }
p { .empty-state__message {
@include h2; @include h2;
line-height: 1.2; line-height: 1.2;
max-width: 15em; max-width: 15em;
@ -24,4 +24,13 @@
@include h1; @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 %} {% 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'> <div class='empty-state'>
<p>{{ message }}</p> <p class='empty-state__message'>{{ message }}</p>
{% if icon %} {% if icon %}
{{ Icon(icon) }} {{ Icon(icon) }}
{% endif %} {% 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> </div>
{%- endmacro %} {%- endmacro %}

View File

@ -6,7 +6,7 @@
"Projects", "Projects",
href=url_for("workspaces.workspace_projects", workspace_id=workspace.id), href=url_for("workspaces.workspace_projects", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/projects'), 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", "label": "Add New Project",
"href": url_for('workspaces.new_project', workspace_id=workspace.id), "href": url_for('workspaces.new_project', workspace_id=workspace.id),
@ -20,7 +20,7 @@
"Members", "Members",
href=url_for("workspaces.workspace_members", workspace_id=workspace.id), href=url_for("workspaces.workspace_members", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/members'), 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", "label": "Add New Member",
"href": url_for("workspaces.new_member", workspace_id=workspace.id), "href": url_for("workspaces.new_member", workspace_id=workspace.id),

View File

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

View File

@ -6,10 +6,13 @@
{% if not workspace.members %} {% if not workspace.members %}
{% set user_can_invite = user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) %}
{{ EmptyState( {{ EmptyState(
'There are currently no members in this Workspace.', 'There are currently no members in this Workspace.',
actionLabel='Invite a new Member', action_label='Invite a new Member' if user_can_invite else None,
actionHref='/members/new', 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' icon='avatar'
) }} ) }}

View File

@ -1,36 +1,54 @@
{% from "components/icon.html" import Icon %} {% from "components/icon.html" import Icon %}
{% from "components/alert.html" import Alert %} {% from "components/alert.html" import Alert %}
{% from "components/empty_state.html" import EmptyState %}
{% extends "base_workspace.html" %} {% extends "base_workspace.html" %}
{% block workspace_content %} {% block workspace_content %}
{% for project in workspace.projects %} {% if not 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'> {% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %}
<div class='label'>0</div>
<span>members</span> {{ EmptyState(
</div> 'This workspace doesnt have any projects yet.',
</li> action_label='Add a New Project' if can_create_projects else None,
{% endfor %} action_href=url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None,
</ul> icon='cloud',
</div> sub_message=None if can_create_projects else 'Please contact your JEDI workspace administrator to set up a new project.'
{% endfor %} ) }}
{% 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 %} {% 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
)