diff --git a/tests/unit/manage/test_views.py b/tests/unit/manage/test_views.py index 96afbce61494..a3575c8ef5df 100644 --- a/tests/unit/manage/test_views.py +++ b/tests/unit/manage/test_views.py @@ -100,7 +100,7 @@ def test_active_projects(self, db_request): # A project with a sole owner that is not the user not_an_owner = ProjectFactory.create() - RoleFactory.create(user=user, project=not_an_owner, role_name="Maintatiner") + RoleFactory.create(user=user, project=not_an_owner, role_name="Maintainer") RoleFactory.create(user=another_user, project=not_an_owner, role_name="Owner") view = views.ManageAccountViews(db_request) @@ -683,7 +683,12 @@ def test_manage_projects(self, db_request): older_project_with_no_releases, ] ) + user_second_owner = UserFactory( + projects=[project_with_older_release, older_project_with_no_releases] + ) RoleFactory.create(user=db_request.user, project=project_with_newer_release) + RoleFactory.create(user=db_request.user, project=newer_project_with_no_releases) + RoleFactory.create(user=user_second_owner, project=project_with_newer_release) assert views.manage_projects(db_request) == { "projects": [ @@ -692,7 +697,11 @@ def test_manage_projects(self, db_request): older_project_with_no_releases, project_with_older_release, ], - "projects_owned": {project_with_newer_release.name}, + "projects_owned": { + project_with_newer_release.name, + newer_project_with_no_releases.name, + }, + "projects_sole_owned": {newer_project_with_no_releases.name}, } diff --git a/warehouse/manage/views.py b/warehouse/manage/views.py index 1373be2288fd..61a0f62c26f9 100644 --- a/warehouse/manage/views.py +++ b/warehouse/manage/views.py @@ -39,6 +39,32 @@ from warehouse.utils.project import confirm_project, destroy_docs, remove_project +def user_projects(request): + """ Return all the projects for which the user is a sole owner """ + projects_owned = ( + request.db.query(Project) + .join(Role.project) + .filter(Role.role_name == "Owner", Role.user == request.user) + .subquery() + ) + + with_sole_owner = ( + request.db.query(Role.package_name) + .join(projects_owned) + .filter(Role.role_name == "Owner") + .group_by(Role.package_name) + .having(func.count(Role.package_name) == 1) + .subquery() + ) + + return { + "projects_owned": request.db.query(projects_owned).all(), + "projects_sole_owned": ( + request.db.query(Project).join(with_sole_owner).order_by(Project.name).all() + ), + } + + @view_defaults( route_name="manage.account", renderer="manage/account.html", @@ -57,29 +83,7 @@ def __init__(self, request): @property def active_projects(self): - """ Return all the projects for with the user is a sole owner """ - projects_owned = ( - self.request.db.query(Project) - .join(Role.project) - .filter(Role.role_name == "Owner", Role.user == self.request.user) - .subquery() - ) - - with_sole_owner = ( - self.request.db.query(Role.package_name) - .join(projects_owned) - .filter(Role.role_name == "Owner") - .group_by(Role.package_name) - .having(func.count(Role.package_name) == 1) - .subquery() - ) - - return ( - self.request.db.query(Project) - .join(with_sole_owner) - .order_by(Project.name) - .all() - ) + return user_projects(request=self.request)["projects_sole_owned"] @property def default_response(self): @@ -287,19 +291,18 @@ def _key(project): return project.releases[0].created return project.created + all_user_projects = user_projects(request) projects_owned = set( - project.name - for project in ( - request.db.query(Project.name) - .join(Role.project) - .filter(Role.role_name == "Owner", Role.user == request.user) - .all() - ) + project.name for project in all_user_projects["projects_owned"] + ) + projects_sole_owned = set( + project.name for project in all_user_projects["projects_sole_owned"] ) return { "projects": sorted(request.user.projects, key=_key, reverse=True), "projects_owned": projects_owned, + "projects_sole_owned": projects_sole_owned, } diff --git a/warehouse/static/sass/blocks/_package-snippet.scss b/warehouse/static/sass/blocks/_package-snippet.scss index 119f44130a7d..14dd3a879616 100644 --- a/warehouse/static/sass/blocks/_package-snippet.scss +++ b/warehouse/static/sass/blocks/_package-snippet.scss @@ -74,6 +74,10 @@ font-size: 1rem; } + &__sole-owner-badge { + margin-left: 4px; + } + &__buttons { width: 165px; diff --git a/warehouse/templates/manage/projects.html b/warehouse/templates/manage/projects.html index b2f76ae159be..a120757ff029 100644 --- a/warehouse/templates/manage/projects.html +++ b/warehouse/templates/manage/projects.html @@ -27,7 +27,13 @@

Your projects ({{ projects|length }})

-

{{ project.name }}

+

{{ project.name }} + {% if project.name in projects_sole_owned %} + + Sole owner + + {% endif %} +

{% if release %}

Last released on {{ release.created|format_date() }}