From 641bda11cbdf18e84074cc594570f7694680a7e2 Mon Sep 17 00:00:00 2001 From: sterbo Date: Mon, 18 Apr 2022 18:52:30 -0700 Subject: [PATCH 01/24] Added three get organizations variations --- tests/common/db/organizations.py | 6 +-- tests/unit/organizations/test_services.py | 48 +++++++++++++++++++++++ warehouse/organizations/interfaces.py | 16 ++++++++ warehouse/organizations/services.py | 30 ++++++++++++++ 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/tests/common/db/organizations.py b/tests/common/db/organizations.py index 0c5bda236cc3..09ce232fd8cc 100644 --- a/tests/common/db/organizations.py +++ b/tests/common/db/organizations.py @@ -41,15 +41,13 @@ class Meta: link_url = factory.Faker("uri") description = factory.Faker("sentence") is_active = True - is_approved = False + is_approved = None created = factory.Faker( "date_time_between_dates", datetime_start=datetime.datetime(2020, 1, 1), datetime_end=datetime.datetime(2022, 1, 1), ) - date_approved = factory.Faker( - "date_time_between_dates", datetime_start=datetime.datetime(2020, 1, 1) - ) + date_approved = None class OrganizationEventFactory(WarehouseFactory): diff --git a/tests/unit/organizations/test_services.py b/tests/unit/organizations/test_services.py index 571469911ee1..02c44a5dbbd8 100644 --- a/tests/unit/organizations/test_services.py +++ b/tests/unit/organizations/test_services.py @@ -64,6 +64,54 @@ def test_find_organizationid(self, organization_service): def test_find_organizationid_nonexistent_org(self, organization_service): assert organization_service.find_organizationid("a_spoon_in_the_matrix") is None + def test_get_organizations(self, organization_service): + organization = OrganizationFactory.create(name="org") + another_organization = OrganizationFactory.create(name="another_org") + orgs = organization_service.get_organizations() + + assert organization in orgs + assert another_organization in orgs + + def test_get_organizations_needing_approval(self, organization_service): + i_need_it = OrganizationFactory.create() + assert i_need_it.is_approved is None + + i_has_it = OrganizationFactory.create() + organization_service.approve_organization(i_has_it.id) + assert i_has_it.is_approved is True + + orgs_needing_approval = ( + organization_service.get_organizations_needing_approval() + ) + + assert i_need_it in orgs_needing_approval + assert i_has_it not in orgs_needing_approval + + def test_get_organizations_by_user(self, organization_service, user_service): + user_organization = OrganizationFactory.create() + user = UserFactory.create() + organization_service.add_organization_role( + OrganizationRoleType.Owner.value, user.id, user_organization.id + ) + + another_user_organization = OrganizationFactory.create() + another_user = UserFactory.create() + organization_service.add_organization_role( + OrganizationRoleType.Owner.value, + another_user.id, + another_user_organization.id, + ) + + user_orgs = organization_service.get_organizations_by_user(user.id) + another_user_orgs = organization_service.get_organizations_by_user( + another_user.id + ) + + assert user_organization in user_orgs + assert user_organization not in another_user_orgs + assert another_user_organization in another_user_orgs + assert another_user_organization not in user_orgs + def test_add_organization(self, organization_service): organization = OrganizationFactory.create() new_org = organization_service.add_organization( diff --git a/warehouse/organizations/interfaces.py b/warehouse/organizations/interfaces.py index 02894dc5e01e..f54a04824749 100644 --- a/warehouse/organizations/interfaces.py +++ b/warehouse/organizations/interfaces.py @@ -32,6 +32,22 @@ def find_organizationid(name): is no organization with the given name. """ + def get_organizations(): + """ + Return a list of all organization objects, or None if there are none. + """ + + def get_organizations_needing_approval(): + """ + Return a list of all organization objects in need of approval or None + if there are currently no organization requests. + """ + + def get_organizations_by_user(user_id): + """ + Return a list of all organization objects associated with a given user id. + """ + def add_organization(name, display_name, orgtype, link_url, description): """ Accepts a organization object, and attempts to create an organization with those diff --git a/warehouse/organizations/services.py b/warehouse/organizations/services.py index 0558f6aa1413..6cbafa4f6eca 100644 --- a/warehouse/organizations/services.py +++ b/warehouse/organizations/services.py @@ -64,6 +64,36 @@ def find_organizationid(self, name): return organization.id + def get_organizations(self): + """ + Return a list of all organization objects, or None if there are none. + """ + return self.db.query(Organization).order_by(Organization.name).all() + + def get_organizations_needing_approval(self): + """ + Return a list of all organization objects in need of approval or None + if there are currently no organization requests. + """ + return ( + self.db.query(Organization) + .filter(Organization.is_approved == None) # noqa + .order_by(Organization.name) + .all() + ) + + def get_organizations_by_user(self, user_id): + """ + Return a list of all organization objects associated with a given user id. + """ + return ( + self.db.query(Organization) + .join(OrganizationRole, OrganizationRole.organization_id == Organization.id) + .filter(OrganizationRole.user_id == user_id) + .order_by(Organization.name) + .all() + ) + def add_organization(self, name, display_name, orgtype, link_url, description): """ Accepts a organization object, and attempts to create an organization with those From af9e24e75e37173041229935f00b12b611b14ad1 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 19 Apr 2022 11:13:17 -0700 Subject: [PATCH 02/24] List organizations on /manage/organizations/ page Borrowing styles from list of projects for now. --- tests/unit/manage/test_views.py | 17 +++- warehouse/locale/messages.pot | 94 +++++++++++-------- warehouse/manage/views.py | 35 +++++++ warehouse/templates/manage/organizations.html | 39 +++++++- 4 files changed, 142 insertions(+), 43 deletions(-) diff --git a/tests/unit/manage/test_views.py b/tests/unit/manage/test_views.py index c38eecc86eae..12443ca9b432 100644 --- a/tests/unit/manage/test_views.py +++ b/tests/unit/manage/test_views.py @@ -2313,11 +2313,22 @@ def test_default_response(self, monkeypatch): ) monkeypatch.setattr(views, "CreateOrganizationForm", create_organization_cls) + organization = pretend.stub(name=pretend.stub()) + + user_organizations = pretend.call_recorder( + lambda *a, **kw: {"organizations_owned": [organization]} + ) + monkeypatch.setattr(views, "user_organizations", user_organizations) + + organization_service = pretend.stub( + get_organizations_by_user=lambda *a, **kw: [organization] + ) + user_service = pretend.stub() request = pretend.stub( user=pretend.stub(id=pretend.stub(), username=pretend.stub()), find_service=lambda interface, **kw: { - IOrganizationService: pretend.stub(), - IUserService: pretend.stub(), + IOrganizationService: organization_service, + IUserService: user_service, }[interface], ) @@ -2325,6 +2336,8 @@ def test_default_response(self, monkeypatch): assert view.default_response == { "create_organization_form": create_organization_obj, + "organizations": [organization], + "organizations_owned": [organization.name], } def test_manage_organizations(self, monkeypatch): diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 697009e306b4..e4c98b716ab3 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -116,7 +116,7 @@ msgstr "" msgid "Successful WebAuthn assertion" msgstr "" -#: warehouse/accounts/views.py:441 warehouse/manage/views.py:817 +#: warehouse/accounts/views.py:441 warehouse/manage/views.py:822 msgid "Recovery code accepted. The supplied code cannot be used again." msgstr "" @@ -261,51 +261,51 @@ msgid "" "description with 400 characters or less." msgstr "" -#: warehouse/manage/views.py:248 +#: warehouse/manage/views.py:253 msgid "Email ${email_address} added - check your email for a verification link" msgstr "" -#: warehouse/manage/views.py:765 +#: warehouse/manage/views.py:770 msgid "Recovery codes already generated" msgstr "" -#: warehouse/manage/views.py:766 +#: warehouse/manage/views.py:771 msgid "Generating new recovery codes will invalidate your existing codes." msgstr "" -#: warehouse/manage/views.py:1299 +#: warehouse/manage/views.py:1334 msgid "" "There have been too many attempted OpenID Connect registrations. Try " "again later." msgstr "" -#: warehouse/manage/views.py:1980 +#: warehouse/manage/views.py:2015 msgid "User '${username}' already has ${role_name} role for project" msgstr "" -#: warehouse/manage/views.py:1991 +#: warehouse/manage/views.py:2026 msgid "" "User '${username}' does not have a verified primary email address and " "cannot be added as a ${role_name} for project" msgstr "" -#: warehouse/manage/views.py:2004 +#: warehouse/manage/views.py:2039 msgid "User '${username}' already has an active invite. Please try again later." msgstr "" -#: warehouse/manage/views.py:2062 +#: warehouse/manage/views.py:2097 msgid "Invitation sent to '${username}'" msgstr "" -#: warehouse/manage/views.py:2109 +#: warehouse/manage/views.py:2144 msgid "Could not find role invitation." msgstr "" -#: warehouse/manage/views.py:2120 +#: warehouse/manage/views.py:2155 msgid "Invitation already expired." msgstr "" -#: warehouse/manage/views.py:2144 +#: warehouse/manage/views.py:2179 msgid "Invitation revoked from '${username}'." msgstr "" @@ -932,11 +932,11 @@ msgstr "" #: warehouse/templates/manage/account/recovery_codes-burn.html:70 #: warehouse/templates/manage/account/totp-provision.html:69 #: warehouse/templates/manage/account/webauthn-provision.html:44 -#: warehouse/templates/manage/organizations.html:34 -#: warehouse/templates/manage/organizations.html:57 -#: warehouse/templates/manage/organizations.html:79 -#: warehouse/templates/manage/organizations.html:97 -#: warehouse/templates/manage/organizations.html:116 +#: warehouse/templates/manage/organizations.html:69 +#: warehouse/templates/manage/organizations.html:92 +#: warehouse/templates/manage/organizations.html:114 +#: warehouse/templates/manage/organizations.html:132 +#: warehouse/templates/manage/organizations.html:151 #: warehouse/templates/manage/publishing.html:85 #: warehouse/templates/manage/publishing.html:97 #: warehouse/templates/manage/publishing.html:109 @@ -2764,6 +2764,8 @@ msgid "from %(ip_address)s" msgstr "" #: warehouse/templates/manage/manage_base.html:16 +#: warehouse/templates/manage/organizations.html:46 +#: warehouse/templates/manage/organizations.html:50 #: warehouse/templates/manage/projects.html:143 #: warehouse/templates/manage/projects.html:148 #: warehouse/templates/manage/releases.html:88 @@ -2994,63 +2996,83 @@ msgstr "" msgid "Your organizations" msgstr "" -#: warehouse/templates/manage/organizations.html:25 +#: warehouse/templates/manage/organizations.html:21 +#, python-format +msgid "Your organizations (%(organization_count)s)" +msgstr "" + +#: warehouse/templates/manage/organizations.html:35 +#: warehouse/templates/manage/projects.html:41 +#: warehouse/templates/manage/projects.html:106 +#, python-format +msgid "Created %(creation_date)s" +msgstr "" + +#: warehouse/templates/manage/organizations.html:45 +msgid "Manage this organization" +msgstr "" + +#: warehouse/templates/manage/organizations.html:49 +msgid "You are not an owner of this organization" +msgstr "" + +#: warehouse/templates/manage/organizations.html:61 msgid "Create new organization" msgstr "" -#: warehouse/templates/manage/organizations.html:32 +#: warehouse/templates/manage/organizations.html:67 msgid "Organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:37 +#: warehouse/templates/manage/organizations.html:72 msgid "Select an organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:48 +#: warehouse/templates/manage/organizations.html:83 msgid "This account name will be used in URLs on PyPI." msgstr "" -#: warehouse/templates/manage/organizations.html:49 -#: warehouse/templates/manage/organizations.html:71 -#: warehouse/templates/manage/organizations.html:89 +#: warehouse/templates/manage/organizations.html:84 +#: warehouse/templates/manage/organizations.html:106 +#: warehouse/templates/manage/organizations.html:124 msgid "For example" msgstr "" -#: warehouse/templates/manage/organizations.html:55 +#: warehouse/templates/manage/organizations.html:90 msgid "Organization name" msgstr "" -#: warehouse/templates/manage/organizations.html:60 +#: warehouse/templates/manage/organizations.html:95 msgid "Name of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:77 +#: warehouse/templates/manage/organizations.html:112 msgid "️Organization URL" msgstr "" -#: warehouse/templates/manage/organizations.html:83 +#: warehouse/templates/manage/organizations.html:118 msgid "URL for your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:95 +#: warehouse/templates/manage/organizations.html:130 msgid "Organization description" msgstr "" -#: warehouse/templates/manage/organizations.html:100 +#: warehouse/templates/manage/organizations.html:135 msgid "Description of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:114 +#: warehouse/templates/manage/organizations.html:149 msgid "️Organization type" msgstr "" -#: warehouse/templates/manage/organizations.html:126 +#: warehouse/templates/manage/organizations.html:161 msgid "" "Companies can create organization accounts as a paid service while " "community projects are granted complimentary access." msgstr "" -#: warehouse/templates/manage/organizations.html:132 +#: warehouse/templates/manage/organizations.html:167 msgid "Create" msgstr "" @@ -3059,12 +3081,6 @@ msgstr "" msgid "Pending invitations (%(project_count)s)" msgstr "" -#: warehouse/templates/manage/projects.html:41 -#: warehouse/templates/manage/projects.html:106 -#, python-format -msgid "Created %(creation_date)s" -msgstr "" - #: warehouse/templates/manage/projects.html:72 #: warehouse/templates/manage/projects.html:135 msgid "This project requires 2FA to be enabled to manage" diff --git a/warehouse/manage/views.py b/warehouse/manage/views.py index df878e7ae075..d228ad5b2f9b 100644 --- a/warehouse/manage/views.py +++ b/warehouse/manage/views.py @@ -87,6 +87,11 @@ from warehouse.oidc.interfaces import TooManyOIDCRegistrations from warehouse.oidc.models import GitHubProvider, OIDCProvider from warehouse.organizations.interfaces import IOrganizationService +from warehouse.organizations.models import ( + Organization, + OrganizationRole, + OrganizationRoleType, +) from warehouse.packaging.models import ( File, JournalEntry, @@ -972,6 +977,27 @@ def delete_macaroon(self): return HTTPSeeOther(redirect_to) +def user_organizations(request): + """Return all the organizations for which the user is an owner.""" + organizations_owned = ( + request.db.query(Organization.id) + .join(OrganizationRole.organization) + .filter( + OrganizationRole.role_name == OrganizationRoleType.Owner, + OrganizationRole.user == request.user, + ) + .subquery() + ) + return { + "organizations_owned": ( + request.db.query(Organization) + .join(organizations_owned, Organization.id == organizations_owned.c.id) + .order_by(Organization.name) + .all() + ), + } + + @view_defaults( route_name="manage.organizations", renderer="manage/organizations.html", @@ -991,7 +1017,16 @@ def __init__(self, request): @property def default_response(self): + all_user_organizations = user_organizations(self.request) return { + "organizations": self.organization_service.get_organizations_by_user( + self.request.user.id + ), + **user_organizations(self.request), + "organizations_owned": list( + organization.name + for organization in all_user_organizations["organizations_owned"] + ), "create_organization_form": CreateOrganizationForm( organization_service=self.organization_service, ), diff --git a/warehouse/templates/manage/organizations.html b/warehouse/templates/manage/organizations.html index 1dacd0227bca..778f911a4aa8 100644 --- a/warehouse/templates/manage/organizations.html +++ b/warehouse/templates/manage/organizations.html @@ -18,12 +18,47 @@ {% block title %}{% trans %}Your organizations{% endtrans %}{% endblock %} {% block main %} -

{{ title }}

+

{% trans organization_count=organizations|length %}Your organizations ({{ organization_count }}){% endtrans %}

+ +
+ {% for organization in organizations %} +
+
+
+

{{ organization.name }} + {% if organization.name in organizations_owned %} + {# TODO {% trans %}Owner{% endtrans %} #} + Owner + {% endif %} +

+

+ {% trans creation_date=humanize(organization.created) %}Created {{ creation_date }}{% endtrans %} +

+
+
+ {% if organization.name in organizations_owned %} + {# Show manage button #} + {% trans %}Manage{% endtrans %} + {% else %} + {# Show disabled button #} + + {% endif %} +
+
+
+ {% endfor %} +
{{ form_error_anchor(create_organization_form) }}

{% trans %}Create new organization{% endtrans %}

-
{{ form_errors(create_organization_form) }} From 48bc58699fab6ad533d930cee5bdfb03cbfb9c68 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Thu, 21 Apr 2022 23:32:59 -0700 Subject: [PATCH 03/24] Add SVG of `fa-users` from Font Awesome 5.13.0 https://github.com/FortAwesome/Font-Awesome/blob/4e6402443679e0a9d12c7401ac8783ef4646657f/js-packages/%40fortawesome/free-solid-svg-icons/faUsers.js --- warehouse/static/images/users.svg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 warehouse/static/images/users.svg diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg new file mode 100644 index 000000000000..55dc955777e6 --- /dev/null +++ b/warehouse/static/images/users.svg @@ -0,0 +1,3 @@ + + + From 7fd7eb4227275245d35ce54b7381d6b22a25a7da Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Thu, 21 Apr 2022 23:59:08 -0700 Subject: [PATCH 04/24] Convert users.svg to light gray --- warehouse/static/images/users.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg index 55dc955777e6..c36c75d6aa43 100644 --- a/warehouse/static/images/users.svg +++ b/warehouse/static/images/users.svg @@ -1,3 +1,3 @@ - + From c9b78a17433b7e180a197576929a99cc2a40fbc0 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Fri, 22 Apr 2022 00:24:34 -0700 Subject: [PATCH 05/24] 3 shades of gray for users.svg Use the same gradient of grays as white-cube.svg. --- warehouse/static/images/users.svg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg index c36c75d6aa43..3d3f0ba31ee5 100644 --- a/warehouse/static/images/users.svg +++ b/warehouse/static/images/users.svg @@ -1,3 +1,5 @@ - + + + From 084a380844928a6ecb811000ea1f353af0cc21f5 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Fri, 22 Apr 2022 00:46:42 -0700 Subject: [PATCH 06/24] Darker shades of gray for users.svg --- warehouse/static/images/users.svg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg index 3d3f0ba31ee5..3b4c27d86de5 100644 --- a/warehouse/static/images/users.svg +++ b/warehouse/static/images/users.svg @@ -1,5 +1,5 @@ - - - + + + From 44dfd93f12fec26c42cf55847fa2eb820adc7d55 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Fri, 22 Apr 2022 08:37:41 -0700 Subject: [PATCH 07/24] Add Font Awesome 5.13.0 attribution to users.svg --- warehouse/static/images/users.svg | 1 + 1 file changed, 1 insertion(+) diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg index 3b4c27d86de5..b88858e7dca2 100644 --- a/warehouse/static/images/users.svg +++ b/warehouse/static/images/users.svg @@ -1,4 +1,5 @@ + From 15597d73210191224b17dbe3c3e434273841e243 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Mon, 25 Apr 2022 00:14:09 -0700 Subject: [PATCH 08/24] Resize users.svg to match size of white-cube.svg --- warehouse/static/images/users.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/warehouse/static/images/users.svg b/warehouse/static/images/users.svg index b88858e7dca2..b591f93b5633 100644 --- a/warehouse/static/images/users.svg +++ b/warehouse/static/images/users.svg @@ -1,4 +1,4 @@ - + From d0a3d6172776f8998f1f881401c075d14560b822 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Mon, 25 Apr 2022 00:18:54 -0700 Subject: [PATCH 09/24] Convert {users.svg => users.png} --- warehouse/static/images/users.png | Bin 0 -> 1007 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 warehouse/static/images/users.png diff --git a/warehouse/static/images/users.png b/warehouse/static/images/users.png new file mode 100644 index 0000000000000000000000000000000000000000..a25395b01b607abc30845df48e8811a993cd6c8a GIT binary patch literal 1007 zcmV`u z=usiytmE|>6DOu)D7*7|pQVu%?=h_Of|Hr2oq6+u*M}XHBSh;aSJ_{Op|1vma0Lhh zPdQ3{)#XDu_ZJPLasAfnvD0WYZj;^4gy-7JfNhzRhS9vc8i$!f;mtrP>#J%W(=>1E z^@52kOP2w9Jt?JmcP+WVS962DS8xQLJ=bcrZsBSr5jdMA82GOG;)^ei%DD0I@zaOH-tuM%4x(_Gw=oQZ2~Lco*9)m0JJ?@n zX&ph|l}kuo#tsKtBDgd?J$*`<11+s1nCIzQJwBwqj-V$Ok-Tg%wQE}~M!j_iuGQm5 zS!QjEl_kb`ESB(Q3DR%Aj7LH8piE$9fwc4uK^c1g=d=T>NlmEWO+Iu)H?2~@|_1Cj? z?ZbD7K`f86ZR_p1xtZEE!yQHEAOLP~U^JU|Au$!Z+Og#azVDh*S{q1|sFH&}2 zHH_B7&1Ulk0I%^GzC#RRL*EtnEm_=^Ya%o5Az=(aM(Zd#2MK(8-Y|>@4z=ZRny*Z! z*eo3YT2+$^r6jILk(1i^5c%=E&QT7-oYfH&qWw-uE=>l1qQFidO$UFJBppY+S4WV> zpr|G2Ix?VkoQk&co7*W+&Qu6-1$;S8ldzVc=g4FfLD@Aw``-dp_d_Jy4cJnCfEr=w ze=&++k_-}RpYfdQSV?ugkexk=WgL Date: Mon, 25 Apr 2022 10:33:11 -0700 Subject: [PATCH 10/24] NFC: Rename {_package-snippet => _snippet}.scss --- .../static/sass/blocks/{_package-snippet.scss => _snippet.scss} | 0 warehouse/static/sass/warehouse.scss | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename warehouse/static/sass/blocks/{_package-snippet.scss => _snippet.scss} (100%) diff --git a/warehouse/static/sass/blocks/_package-snippet.scss b/warehouse/static/sass/blocks/_snippet.scss similarity index 100% rename from warehouse/static/sass/blocks/_package-snippet.scss rename to warehouse/static/sass/blocks/_snippet.scss diff --git a/warehouse/static/sass/warehouse.scss b/warehouse/static/sass/warehouse.scss index bfec85ddff5e..48b510eb899a 100644 --- a/warehouse/static/sass/warehouse.scss +++ b/warehouse/static/sass/warehouse.scss @@ -102,7 +102,7 @@ /*rtl:begin:ignore*/ @import "blocks/package-description"; @import "blocks/package-header"; -@import "blocks/package-snippet"; +@import "blocks/snippet"; /*rtl:end:ignore*/ @import "blocks/password-strength"; /*rtl:begin:ignore*/ From 5d40f2c86b06b6143040d64c4d8f2935642d2e99 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Mon, 25 Apr 2022 10:40:03 -0700 Subject: [PATCH 11/24] NFC: Rename .package-snippet__* classes - {.package-snippet__project-badge => .package-snippet__badge} - {.package-snippet__released => .package-snippet__created} --- warehouse/static/sass/blocks/_snippet.scss | 4 ++-- warehouse/templates/manage/organizations.html | 2 +- warehouse/templates/manage/projects.html | 10 +++++----- warehouse/templates/search/results.html | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/warehouse/static/sass/blocks/_snippet.scss b/warehouse/static/sass/blocks/_snippet.scss index db24f51789d6..43baa243ad1b 100644 --- a/warehouse/static/sass/blocks/_snippet.scss +++ b/warehouse/static/sass/blocks/_snippet.scss @@ -70,7 +70,7 @@ font-weight: $bold-font-weight; } - &__released { + &__created { font-weight: $base-font-weight; float: right; color: $text-color; @@ -87,7 +87,7 @@ color: $text-color; } - &__project-badge { + &__badge { margin-left: 4px; position: relative; top: -1px; diff --git a/warehouse/templates/manage/organizations.html b/warehouse/templates/manage/organizations.html index 778f911a4aa8..359899dfe5f6 100644 --- a/warehouse/templates/manage/organizations.html +++ b/warehouse/templates/manage/organizations.html @@ -27,7 +27,7 @@

{% trans organization_count=organizations|length %}Your o

{{ organization.name }} {% if organization.name in organizations_owned %} - {# TODO {% trans %}Owner{% endtrans %} #} + {# TODO {% trans %}Owner{% endtrans %} #} Owner {% endif %}

diff --git a/warehouse/templates/manage/projects.html b/warehouse/templates/manage/projects.html index 0c52f778a6e2..2a49121462f5 100644 --- a/warehouse/templates/manage/projects.html +++ b/warehouse/templates/manage/projects.html @@ -69,29 +69,29 @@

{{ project.name }} request.registry.settings["warehouse.two_factor_requirement.enabled"] and project.owners_require_2fa ) %} - + {% trans %}2FA Required{% endtrans %} {% elif ( request.registry.settings["warehouse.two_factor_mandate.enabled"] and project.pypi_mandates_2fa ) %} - + {% trans %}Critical Project{% endtrans %} - + {% trans %}2FA Mandated{% endtrans %} {% elif ( request.registry.settings["warehouse.two_factor_mandate.available"] and project.pypi_mandates_2fa ) %} - + {% trans %}Critical Project{% endtrans %} {% endif %} {% if project.name in projects_sole_owned %} - {% trans %}Sole owner{% endtrans %} + {% trans %}Sole owner{% endtrans %} {% endif %}

{% if release %} diff --git a/warehouse/templates/search/results.html b/warehouse/templates/search/results.html index fb73b3f18861..390bf681605a 100644 --- a/warehouse/templates/search/results.html +++ b/warehouse/templates/search/results.html @@ -23,7 +23,7 @@

{{ item.name }} {{ item.latest_version }} - {{ humanize(item.created) }} + {{ humanize(item.created) }}

{{ item.summary }}

From c5ff0f20977f655b59e1b97ca1663a679648a7c4 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Mon, 25 Apr 2022 11:35:47 -0700 Subject: [PATCH 12/24] `snippet` mixin for organizations and packages Cards with similar styling but different icons: - .organization-snippet - .package-snippet --- .../sass/blocks/_organization-snippet.scss | 33 +++++++++++++++++++ .../static/sass/blocks/_package-snippet.scss | 33 +++++++++++++++++++ warehouse/static/sass/blocks/_snippet.scss | 20 ++++------- warehouse/static/sass/warehouse.scss | 3 +- warehouse/templates/manage/organizations.html | 12 +++---- 5 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 warehouse/static/sass/blocks/_organization-snippet.scss create mode 100644 warehouse/static/sass/blocks/_package-snippet.scss diff --git a/warehouse/static/sass/blocks/_organization-snippet.scss b/warehouse/static/sass/blocks/_organization-snippet.scss new file mode 100644 index 000000000000..913b308fca14 --- /dev/null +++ b/warehouse/static/sass/blocks/_organization-snippet.scss @@ -0,0 +1,33 @@ +/*! + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "_snippet"; + +/* + A card that contains information about a organization. Often found in organization lists. + The card can be an "a" or "div" element, but if it contains a link, choosing + a top-level "a" element is recommended for accessibility reasons. + + +

+ // Package title + // Version // Optional! +

+

// Description

+
+*/ + +.organization-snippet { + @include snippet(url("../images/users.png"), url("../images/users.svg")); +} diff --git a/warehouse/static/sass/blocks/_package-snippet.scss b/warehouse/static/sass/blocks/_package-snippet.scss new file mode 100644 index 000000000000..a5dd2d19aa36 --- /dev/null +++ b/warehouse/static/sass/blocks/_package-snippet.scss @@ -0,0 +1,33 @@ +/*! + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "_snippet"; + +/* + A card that contains information about a package. Often found in package lists. + The card can be an "a" or "div" element, but if it contains a link, choosing + a top-level "a" element is recommended for accessibility reasons. + + +

+ // Package title + // Version // Optional! +

+

// Description

+
+*/ + +.package-snippet { + @include snippet(url("../images/white-cube.png"), url("../images/white-cube.svg")); +} diff --git a/warehouse/static/sass/blocks/_snippet.scss b/warehouse/static/sass/blocks/_snippet.scss index 43baa243ad1b..ec884ef667c9 100644 --- a/warehouse/static/sass/blocks/_snippet.scss +++ b/warehouse/static/sass/blocks/_snippet.scss @@ -13,20 +13,12 @@ */ /* - A card that contains information about a package. Often found in package lists. - The card can be an "a" or "div" element, but if it contains a link, choosing - a top-level "a" element is recommended for accessibility reasons. - - -

- // Package title - // Version // Optional! -

-

// Description

-
+ A card that contains information about a package or an organization. + - Extended by .package-snippet and often found in package lists. + - Extended by .organization-snippet and often found in package lists. */ -.package-snippet { +@mixin snippet($snippet-icon-svg, $snippet-icon-png) { @include card; direction: ltr; text-align: left; @@ -42,9 +34,9 @@ &, &:hover { // Use png fallback - background: $white url("../images/white-cube.png") no-repeat 0 50%; + background: $white $snippet-icon-png no-repeat 0 50%; // Or svg if the browser supports it - background-image: url("../images/white-cube.svg"), linear-gradient(transparent, transparent); + background-image: $snippet-icon-svg, linear-gradient(transparent, transparent); background-position: 20px; } } diff --git a/warehouse/static/sass/warehouse.scss b/warehouse/static/sass/warehouse.scss index 48b510eb899a..65153384a0b8 100644 --- a/warehouse/static/sass/warehouse.scss +++ b/warehouse/static/sass/warehouse.scss @@ -100,9 +100,10 @@ @import "blocks/modal"; @import "blocks/notification-bar"; /*rtl:begin:ignore*/ +@import "blocks/organization-snippet"; @import "blocks/package-description"; @import "blocks/package-header"; -@import "blocks/snippet"; +@import "blocks/package-snippet"; /*rtl:end:ignore*/ @import "blocks/password-strength"; /*rtl:begin:ignore*/ diff --git a/warehouse/templates/manage/organizations.html b/warehouse/templates/manage/organizations.html index 359899dfe5f6..5d40ca8bfd6a 100644 --- a/warehouse/templates/manage/organizations.html +++ b/warehouse/templates/manage/organizations.html @@ -20,22 +20,22 @@ {% block main %}

{% trans organization_count=organizations|length %}Your organizations ({{ organization_count }}){% endtrans %}

-
+
{% for organization in organizations %} -
+
-

{{ organization.name }} +

{{ organization.name }} {% if organization.name in organizations_owned %} - {# TODO {% trans %}Owner{% endtrans %} #} + {# TODO {% trans %}Owner{% endtrans %} #} Owner {% endif %}

-

+

{% trans creation_date=humanize(organization.created) %}Created {{ creation_date }}{% endtrans %}

-
+
{% if organization.name in organizations_owned %} {# Show manage button #} Date: Tue, 26 Apr 2022 01:04:57 -0700 Subject: [PATCH 13/24] Add "Your organizations" to "Your account" sidebar --- warehouse/locale/messages.pot | 45 +++++++++++---------- warehouse/templates/manage/manage_base.html | 8 ++++ 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index e4c98b716ab3..9913f9a45b2c 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -623,8 +623,8 @@ msgstr "" #: warehouse/templates/includes/session-notifications.html:20 #: warehouse/templates/manage/account.html:716 #: warehouse/templates/manage/documentation.html:27 -#: warehouse/templates/manage/manage_base.html:278 -#: warehouse/templates/manage/manage_base.html:330 +#: warehouse/templates/manage/manage_base.html:286 +#: warehouse/templates/manage/manage_base.html:338 #: warehouse/templates/manage/release.html:163 #: warehouse/templates/manage/settings.html:119 msgid "Warning" @@ -906,7 +906,7 @@ msgstr "" #: warehouse/templates/accounts/login.html:69 #: warehouse/templates/accounts/register.html:110 #: warehouse/templates/accounts/reset-password.html:38 -#: warehouse/templates/manage/manage_base.html:339 +#: warehouse/templates/manage/manage_base.html:347 #: warehouse/templates/re-auth.html:49 msgid "Password" msgstr "" @@ -954,7 +954,7 @@ msgid "Your password" msgstr "" #: warehouse/templates/accounts/login.html:92 -#: warehouse/templates/manage/manage_base.html:342 +#: warehouse/templates/manage/manage_base.html:350 #: warehouse/templates/re-auth.html:72 msgid "Show password" msgstr "" @@ -1691,7 +1691,7 @@ msgstr "" #: warehouse/templates/includes/current-user-indicator.html:37 #: warehouse/templates/manage/manage_base.html:204 -#: warehouse/templates/manage/manage_base.html:224 +#: warehouse/templates/manage/manage_base.html:232 #: warehouse/templates/manage/projects.html:18 msgid "Your projects" msgstr "" @@ -1699,8 +1699,8 @@ msgstr "" #: warehouse/templates/includes/current-user-indicator.html:43 #: warehouse/templates/manage/account.html:17 #: warehouse/templates/manage/account/two-factor.html:17 -#: warehouse/templates/manage/manage_base.html:210 -#: warehouse/templates/manage/manage_base.html:230 +#: warehouse/templates/manage/manage_base.html:218 +#: warehouse/templates/manage/manage_base.html:238 msgid "Account settings" msgstr "" @@ -1730,8 +1730,8 @@ msgstr "" #: warehouse/templates/manage/account.html:199 #: warehouse/templates/manage/account.html:201 #: warehouse/templates/manage/account.html:211 -#: warehouse/templates/manage/manage_base.html:266 -#: warehouse/templates/manage/manage_base.html:268 +#: warehouse/templates/manage/manage_base.html:274 +#: warehouse/templates/manage/manage_base.html:276 #: warehouse/templates/manage/release.html:118 #: warehouse/templates/manage/releases.html:172 #: warehouse/templates/manage/roles.html:38 @@ -2946,34 +2946,39 @@ msgid "Your account" msgstr "" #: warehouse/templates/manage/manage_base.html:199 -#: warehouse/templates/manage/manage_base.html:219 +#: warehouse/templates/manage/manage_base.html:227 msgid "Account navigation" msgstr "" -#: warehouse/templates/manage/manage_base.html:279 -#: warehouse/templates/manage/manage_base.html:331 -msgid "This action cannot be undone!" +#: warehouse/templates/manage/manage_base.html:211 +#: warehouse/templates/manage/organizations.html:18 +msgid "Your organizations" msgstr "" #: warehouse/templates/manage/manage_base.html:287 +#: warehouse/templates/manage/manage_base.html:339 +msgid "This action cannot be undone!" +msgstr "" + +#: warehouse/templates/manage/manage_base.html:295 msgid "Confirm your username to continue." msgstr "" -#: warehouse/templates/manage/manage_base.html:289 +#: warehouse/templates/manage/manage_base.html:297 #, python-format msgid "Confirm the %(item)s to continue." msgstr "" -#: warehouse/templates/manage/manage_base.html:297 -#: warehouse/templates/manage/manage_base.html:349 +#: warehouse/templates/manage/manage_base.html:305 +#: warehouse/templates/manage/manage_base.html:357 msgid "Cancel" msgstr "" -#: warehouse/templates/manage/manage_base.html:320 +#: warehouse/templates/manage/manage_base.html:328 msgid "close" msgstr "" -#: warehouse/templates/manage/manage_base.html:336 +#: warehouse/templates/manage/manage_base.html:344 msgid "Enter your password to continue." msgstr "" @@ -2992,10 +2997,6 @@ msgstr "" msgid "Back to projects" msgstr "" -#: warehouse/templates/manage/organizations.html:18 -msgid "Your organizations" -msgstr "" - #: warehouse/templates/manage/organizations.html:21 #, python-format msgid "Your organizations (%(organization_count)s)" diff --git a/warehouse/templates/manage/manage_base.html b/warehouse/templates/manage/manage_base.html index 404868fbe043..68422acf4ef6 100644 --- a/warehouse/templates/manage/manage_base.html +++ b/warehouse/templates/manage/manage_base.html @@ -204,6 +204,14 @@ {% trans %}Your projects{% endtrans %} + {% if not request.flags.enabled(AdminFlagValue.DISABLE_ORGANIZATIONS) %} +
  • + + + {% trans %}Your organizations{% endtrans %} + +
  • + {% endif %}
  • From 50ed81490330fe79afc0ba439b34ee482d730d03 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 26 Apr 2022 01:22:29 -0700 Subject: [PATCH 14/24] Display callout block if user has no organizations --- warehouse/locale/messages.pot | 46 ++++++++++--------- warehouse/templates/manage/organizations.html | 6 +++ 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 9913f9a45b2c..4d469a1dad0e 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -932,11 +932,11 @@ msgstr "" #: warehouse/templates/manage/account/recovery_codes-burn.html:70 #: warehouse/templates/manage/account/totp-provision.html:69 #: warehouse/templates/manage/account/webauthn-provision.html:44 -#: warehouse/templates/manage/organizations.html:69 -#: warehouse/templates/manage/organizations.html:92 -#: warehouse/templates/manage/organizations.html:114 -#: warehouse/templates/manage/organizations.html:132 -#: warehouse/templates/manage/organizations.html:151 +#: warehouse/templates/manage/organizations.html:75 +#: warehouse/templates/manage/organizations.html:98 +#: warehouse/templates/manage/organizations.html:120 +#: warehouse/templates/manage/organizations.html:138 +#: warehouse/templates/manage/organizations.html:157 #: warehouse/templates/manage/publishing.html:85 #: warehouse/templates/manage/publishing.html:97 #: warehouse/templates/manage/publishing.html:109 @@ -3017,63 +3017,67 @@ msgstr "" msgid "You are not an owner of this organization" msgstr "" -#: warehouse/templates/manage/organizations.html:61 -msgid "Create new organization" +#: warehouse/templates/manage/organizations.html:58 +msgid "You have not joined any organizations on PyPI, yet." msgstr "" #: warehouse/templates/manage/organizations.html:67 +msgid "Create new organization" +msgstr "" + +#: warehouse/templates/manage/organizations.html:73 msgid "Organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:72 +#: warehouse/templates/manage/organizations.html:78 msgid "Select an organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:83 +#: warehouse/templates/manage/organizations.html:89 msgid "This account name will be used in URLs on PyPI." msgstr "" -#: warehouse/templates/manage/organizations.html:84 -#: warehouse/templates/manage/organizations.html:106 -#: warehouse/templates/manage/organizations.html:124 +#: warehouse/templates/manage/organizations.html:90 +#: warehouse/templates/manage/organizations.html:112 +#: warehouse/templates/manage/organizations.html:130 msgid "For example" msgstr "" -#: warehouse/templates/manage/organizations.html:90 +#: warehouse/templates/manage/organizations.html:96 msgid "Organization name" msgstr "" -#: warehouse/templates/manage/organizations.html:95 +#: warehouse/templates/manage/organizations.html:101 msgid "Name of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:112 +#: warehouse/templates/manage/organizations.html:118 msgid "️Organization URL" msgstr "" -#: warehouse/templates/manage/organizations.html:118 +#: warehouse/templates/manage/organizations.html:124 msgid "URL for your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:130 +#: warehouse/templates/manage/organizations.html:136 msgid "Organization description" msgstr "" -#: warehouse/templates/manage/organizations.html:135 +#: warehouse/templates/manage/organizations.html:141 msgid "Description of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:149 +#: warehouse/templates/manage/organizations.html:155 msgid "️Organization type" msgstr "" -#: warehouse/templates/manage/organizations.html:161 +#: warehouse/templates/manage/organizations.html:167 msgid "" "Companies can create organization accounts as a paid service while " "community projects are granted complimentary access." msgstr "" -#: warehouse/templates/manage/organizations.html:167 +#: warehouse/templates/manage/organizations.html:173 msgid "Create" msgstr "" diff --git a/warehouse/templates/manage/organizations.html b/warehouse/templates/manage/organizations.html index 5d40ca8bfd6a..296ec8df7169 100644 --- a/warehouse/templates/manage/organizations.html +++ b/warehouse/templates/manage/organizations.html @@ -53,9 +53,15 @@

    {{ organization.name }}

  • + {% else %} +
    +

    {% trans %}You have not joined any organizations on PyPI, yet.{% endtrans %}

    +
    {% endfor %}
    +
    + {{ form_error_anchor(create_organization_form) }}

    {% trans %}Create new organization{% endtrans %}

    From 81997b3d26d4f0a3b5fffa7a520c265e269d2a9b Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 26 Apr 2022 01:26:22 -0700 Subject: [PATCH 15/24] NFC: Use for..else Jinja2 syntax for projects.html --- warehouse/locale/messages.pot | 48 ++++++++++++------------ warehouse/templates/manage/projects.html | 4 +- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 4d469a1dad0e..4793df5d5889 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -1088,7 +1088,7 @@ msgstr "" #: warehouse/templates/accounts/profile.html:73 #: warehouse/templates/manage/projects.html:34 -#: warehouse/templates/manage/projects.html:99 +#: warehouse/templates/manage/projects.html:98 #, python-format msgid "Last released %(release_date)s" msgstr "" @@ -2766,8 +2766,8 @@ msgstr "" #: warehouse/templates/manage/manage_base.html:16 #: warehouse/templates/manage/organizations.html:46 #: warehouse/templates/manage/organizations.html:50 -#: warehouse/templates/manage/projects.html:143 -#: warehouse/templates/manage/projects.html:148 +#: warehouse/templates/manage/projects.html:142 +#: warehouse/templates/manage/projects.html:147 #: warehouse/templates/manage/releases.html:88 msgid "Manage" msgstr "" @@ -3004,7 +3004,7 @@ msgstr "" #: warehouse/templates/manage/organizations.html:35 #: warehouse/templates/manage/projects.html:41 -#: warehouse/templates/manage/projects.html:106 +#: warehouse/templates/manage/projects.html:105 #, python-format msgid "Created %(creation_date)s" msgstr "" @@ -3086,63 +3086,63 @@ msgstr "" msgid "Pending invitations (%(project_count)s)" msgstr "" -#: warehouse/templates/manage/projects.html:72 -#: warehouse/templates/manage/projects.html:135 +#: warehouse/templates/manage/projects.html:71 +#: warehouse/templates/manage/projects.html:134 msgid "This project requires 2FA to be enabled to manage" msgstr "" -#: warehouse/templates/manage/projects.html:73 -#: warehouse/templates/manage/projects.html:136 +#: warehouse/templates/manage/projects.html:72 +#: warehouse/templates/manage/projects.html:135 msgid "2FA Required" msgstr "" -#: warehouse/templates/manage/projects.html:79 -#: warehouse/templates/manage/projects.html:89 +#: warehouse/templates/manage/projects.html:78 +#: warehouse/templates/manage/projects.html:88 msgid "This is a critical project for the Python ecosystem" msgstr "" -#: warehouse/templates/manage/projects.html:80 -#: warehouse/templates/manage/projects.html:90 +#: warehouse/templates/manage/projects.html:79 +#: warehouse/templates/manage/projects.html:89 msgid "Critical Project" msgstr "" -#: warehouse/templates/manage/projects.html:82 -#: warehouse/templates/manage/projects.html:123 +#: warehouse/templates/manage/projects.html:81 +#: warehouse/templates/manage/projects.html:122 msgid "PyPI requires 2FA to be enabled to manage this project" msgstr "" -#: warehouse/templates/manage/projects.html:83 -#: warehouse/templates/manage/projects.html:124 +#: warehouse/templates/manage/projects.html:82 +#: warehouse/templates/manage/projects.html:123 msgid "2FA Mandated" msgstr "" -#: warehouse/templates/manage/projects.html:94 +#: warehouse/templates/manage/projects.html:93 msgid "Sole owner" msgstr "" -#: warehouse/templates/manage/projects.html:142 +#: warehouse/templates/manage/projects.html:141 msgid "Manage this project" msgstr "" -#: warehouse/templates/manage/projects.html:147 +#: warehouse/templates/manage/projects.html:146 msgid "You are not an owner of this project" msgstr "" -#: warehouse/templates/manage/projects.html:155 +#: warehouse/templates/manage/projects.html:154 msgid "View this project's public page" msgstr "" -#: warehouse/templates/manage/projects.html:156 -#: warehouse/templates/manage/projects.html:159 +#: warehouse/templates/manage/projects.html:155 +#: warehouse/templates/manage/projects.html:158 #: warehouse/templates/manage/releases.html:94 msgid "View" msgstr "" -#: warehouse/templates/manage/projects.html:158 +#: warehouse/templates/manage/projects.html:157 msgid "This project has no releases" msgstr "" -#: warehouse/templates/manage/projects.html:168 +#: warehouse/templates/manage/projects.html:166 #, python-format msgid "" "You have not uploaded any projects to PyPI, yet. To learn how to get " diff --git a/warehouse/templates/manage/projects.html b/warehouse/templates/manage/projects.html index 2a49121462f5..0e47d68e4026 100644 --- a/warehouse/templates/manage/projects.html +++ b/warehouse/templates/manage/projects.html @@ -57,7 +57,6 @@

    {% endif %}

    {% trans project_count=projects|length %}Your projects ({{ project_count }}){% endtrans %}

    - {% if projects %} {% set user_has_two_factor = request.user.has_two_factor %} {% for project in projects %} {% set release = project.releases[0] if project.releases else None %} @@ -162,11 +161,10 @@

    {{ project.name }}

    - {% endfor %} {% else %} - {% endif %} + {% endfor %}
    {% endblock %} From 81eb8fcf222c3dc60ee7df5776f426351a3ec68d Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 26 Apr 2022 03:00:15 -0700 Subject: [PATCH 16/24] "Manage" collaborators for each organization "Manage" link for each organization listed on /manage/organizations/ navigates to a "Collaborators" management page for the organization. --- tests/unit/manage/test_views.py | 22 +++++ tests/unit/organizations/test_models.py | 33 +++++++ tests/unit/test_routes.py | 7 ++ warehouse/locale/messages.pot | 94 ++++++++++++------- warehouse/manage/views.py | 17 ++++ warehouse/organizations/models.py | 36 ++++--- warehouse/routes.py | 7 ++ .../manage_organization_base.html | 21 +++++ .../templates/manage/organization/roles.html | 37 ++++++++ warehouse/templates/manage/organizations.html | 4 +- warehouse/templates/manage/roles.html | 2 +- 11 files changed, 221 insertions(+), 59 deletions(-) create mode 100644 tests/unit/organizations/test_models.py create mode 100644 warehouse/templates/manage/organization/manage_organization_base.html create mode 100644 warehouse/templates/manage/organization/roles.html diff --git a/tests/unit/manage/test_views.py b/tests/unit/manage/test_views.py index 12443ca9b432..f485ae2b69f5 100644 --- a/tests/unit/manage/test_views.py +++ b/tests/unit/manage/test_views.py @@ -58,6 +58,7 @@ from warehouse.utils.project import remove_documentation from ...common.db.accounts import EmailFactory +from ...common.db.organizations import OrganizationFactory from ...common.db.packaging import ( FileFactory, JournalEntryFactory, @@ -2606,6 +2607,27 @@ def test_create_organizations_disable_organizations(self, monkeypatch): ] +class TestManageOrganizationRoles: + def test_get_manage_organization_roles(self, db_request): + organization = OrganizationFactory.create(name="foobar") + request = pretend.stub( + flags=pretend.stub(enabled=pretend.call_recorder(lambda *a: False)), + ) + + result = views.manage_organization_roles(organization, request) + + assert result == {"organization": organization} + + def test_get_manage_organization_roles_disable_organizations(self, db_request): + organization = OrganizationFactory.create(name="foobar") + request = pretend.stub( + flags=pretend.stub(enabled=pretend.call_recorder(lambda *a: True)), + ) + + with pytest.raises(HTTPNotFound): + views.manage_organization_roles(organization, request) + + class TestManageProjects: def test_manage_projects(self, db_request): older_release = ReleaseFactory(created=datetime.datetime(2015, 1, 1)) diff --git a/tests/unit/organizations/test_models.py b/tests/unit/organizations/test_models.py new file mode 100644 index 000000000000..bafc61deab06 --- /dev/null +++ b/tests/unit/organizations/test_models.py @@ -0,0 +1,33 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +from warehouse.organizations.models import OrganizationFactory + +from ...common.db.organizations import OrganizationFactory as DBOrganizationFactory + + +class TestOrganizationFactory: + @pytest.mark.parametrize(("name", "normalized"), [("foo", "foo"), ("Bar", "bar")]) + def test_traversal_finds(self, db_request, name, normalized): + organization = DBOrganizationFactory.create(name=name) + root = OrganizationFactory(db_request) + + assert root[normalized] == organization + + def test_traversal_cant_find(self, db_request): + organization = DBOrganizationFactory.create() + root = OrganizationFactory(db_request) + + with pytest.raises(KeyError): + root[organization.name + "invalid"] diff --git a/tests/unit/test_routes.py b/tests/unit/test_routes.py index dcccf822e5d8..a91299f27671 100644 --- a/tests/unit/test_routes.py +++ b/tests/unit/test_routes.py @@ -240,6 +240,13 @@ def add_policy(name, filename): pretend.call( "manage.organizations", "/manage/organizations/", domain=warehouse ), + pretend.call( + "manage.organization.roles", + "/manage/organization/{organization_name}/collaboration/", + factory="warehouse.organizations.models:OrganizationFactory", + traverse="/{organization_name}", + domain=warehouse, + ), pretend.call("manage.projects", "/manage/projects/", domain=warehouse), pretend.call( "manage.project.settings", diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 4793df5d5889..0fe2cdfc4dc1 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -273,39 +273,39 @@ msgstr "" msgid "Generating new recovery codes will invalidate your existing codes." msgstr "" -#: warehouse/manage/views.py:1334 +#: warehouse/manage/views.py:1351 msgid "" "There have been too many attempted OpenID Connect registrations. Try " "again later." msgstr "" -#: warehouse/manage/views.py:2015 +#: warehouse/manage/views.py:2032 msgid "User '${username}' already has ${role_name} role for project" msgstr "" -#: warehouse/manage/views.py:2026 +#: warehouse/manage/views.py:2043 msgid "" "User '${username}' does not have a verified primary email address and " "cannot be added as a ${role_name} for project" msgstr "" -#: warehouse/manage/views.py:2039 +#: warehouse/manage/views.py:2056 msgid "User '${username}' already has an active invite. Please try again later." msgstr "" -#: warehouse/manage/views.py:2097 +#: warehouse/manage/views.py:2114 msgid "Invitation sent to '${username}'" msgstr "" -#: warehouse/manage/views.py:2144 +#: warehouse/manage/views.py:2161 msgid "Could not find role invitation." msgstr "" -#: warehouse/manage/views.py:2155 +#: warehouse/manage/views.py:2172 msgid "Invitation already expired." msgstr "" -#: warehouse/manage/views.py:2179 +#: warehouse/manage/views.py:2196 msgid "Invitation revoked from '${username}'." msgstr "" @@ -932,11 +932,11 @@ msgstr "" #: warehouse/templates/manage/account/recovery_codes-burn.html:70 #: warehouse/templates/manage/account/totp-provision.html:69 #: warehouse/templates/manage/account/webauthn-provision.html:44 -#: warehouse/templates/manage/organizations.html:75 -#: warehouse/templates/manage/organizations.html:98 -#: warehouse/templates/manage/organizations.html:120 -#: warehouse/templates/manage/organizations.html:138 -#: warehouse/templates/manage/organizations.html:157 +#: warehouse/templates/manage/organizations.html:73 +#: warehouse/templates/manage/organizations.html:96 +#: warehouse/templates/manage/organizations.html:118 +#: warehouse/templates/manage/organizations.html:136 +#: warehouse/templates/manage/organizations.html:155 #: warehouse/templates/manage/publishing.html:85 #: warehouse/templates/manage/publishing.html:97 #: warehouse/templates/manage/publishing.html:109 @@ -1884,6 +1884,7 @@ msgid "Releases" msgstr "" #: warehouse/templates/includes/manage/manage-project-menu.html:25 +#: warehouse/templates/manage/organization/roles.html:35 #: warehouse/templates/manage/roles.html:35 msgid "Collaborators" msgstr "" @@ -2764,8 +2765,8 @@ msgid "from %(ip_address)s" msgstr "" #: warehouse/templates/manage/manage_base.html:16 -#: warehouse/templates/manage/organizations.html:46 -#: warehouse/templates/manage/organizations.html:50 +#: warehouse/templates/manage/organizations.html:44 +#: warehouse/templates/manage/organizations.html:48 #: warehouse/templates/manage/projects.html:142 #: warehouse/templates/manage/projects.html:147 #: warehouse/templates/manage/releases.html:88 @@ -3002,82 +3003,82 @@ msgstr "" msgid "Your organizations (%(organization_count)s)" msgstr "" -#: warehouse/templates/manage/organizations.html:35 +#: warehouse/templates/manage/organizations.html:34 #: warehouse/templates/manage/projects.html:41 #: warehouse/templates/manage/projects.html:105 #, python-format msgid "Created %(creation_date)s" msgstr "" -#: warehouse/templates/manage/organizations.html:45 +#: warehouse/templates/manage/organizations.html:43 msgid "Manage this organization" msgstr "" -#: warehouse/templates/manage/organizations.html:49 +#: warehouse/templates/manage/organizations.html:47 msgid "You are not an owner of this organization" msgstr "" -#: warehouse/templates/manage/organizations.html:58 +#: warehouse/templates/manage/organizations.html:56 msgid "You have not joined any organizations on PyPI, yet." msgstr "" -#: warehouse/templates/manage/organizations.html:67 +#: warehouse/templates/manage/organizations.html:65 msgid "Create new organization" msgstr "" -#: warehouse/templates/manage/organizations.html:73 +#: warehouse/templates/manage/organizations.html:71 msgid "Organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:78 +#: warehouse/templates/manage/organizations.html:76 msgid "Select an organization account name" msgstr "" -#: warehouse/templates/manage/organizations.html:89 +#: warehouse/templates/manage/organizations.html:87 msgid "This account name will be used in URLs on PyPI." msgstr "" -#: warehouse/templates/manage/organizations.html:90 -#: warehouse/templates/manage/organizations.html:112 -#: warehouse/templates/manage/organizations.html:130 +#: warehouse/templates/manage/organizations.html:88 +#: warehouse/templates/manage/organizations.html:110 +#: warehouse/templates/manage/organizations.html:128 msgid "For example" msgstr "" -#: warehouse/templates/manage/organizations.html:96 +#: warehouse/templates/manage/organizations.html:94 msgid "Organization name" msgstr "" -#: warehouse/templates/manage/organizations.html:101 +#: warehouse/templates/manage/organizations.html:99 msgid "Name of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:118 +#: warehouse/templates/manage/organizations.html:116 msgid "️Organization URL" msgstr "" -#: warehouse/templates/manage/organizations.html:124 +#: warehouse/templates/manage/organizations.html:122 msgid "URL for your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:136 +#: warehouse/templates/manage/organizations.html:134 msgid "Organization description" msgstr "" -#: warehouse/templates/manage/organizations.html:141 +#: warehouse/templates/manage/organizations.html:139 msgid "Description of your business, product, or project" msgstr "" -#: warehouse/templates/manage/organizations.html:155 +#: warehouse/templates/manage/organizations.html:153 msgid "️Organization type" msgstr "" -#: warehouse/templates/manage/organizations.html:167 +#: warehouse/templates/manage/organizations.html:165 msgid "" "Companies can create organization accounts as a paid service while " "community projects are granted complimentary access." msgstr "" -#: warehouse/templates/manage/organizations.html:173 +#: warehouse/templates/manage/organizations.html:171 msgid "Create" msgstr "" @@ -3574,16 +3575,20 @@ msgstr "" msgid "Manage '%(project_name)s' collaborators" msgstr "" +#: warehouse/templates/manage/organization/roles.html:22 #: warehouse/templates/manage/roles.html:22 msgid "2FA enabled" msgstr "" +#: warehouse/templates/manage/organization/roles.html:23 +#: warehouse/templates/manage/organization/roles.html:28 #: warehouse/templates/manage/roles.html:23 #: warehouse/templates/manage/roles.html:28 #: warehouse/templates/manage/roles.html:53 msgid "2FA" msgstr "" +#: warehouse/templates/manage/organization/roles.html:27 #: warehouse/templates/manage/roles.html:27 msgid "2FA disabled" msgstr "" @@ -3592,7 +3597,7 @@ msgstr "" #, python-format msgid "" "Use this page to control which PyPI users can help you to manage " -"%(project_name)s" +"%(project_name)s." msgstr "" #: warehouse/templates/manage/roles.html:39 @@ -4135,6 +4140,23 @@ msgid "" " not work with PyPI." msgstr "" +#: warehouse/templates/manage/organization/manage_organization_base.html:21 +#, python-format +msgid "Manage '%(organization_name)s'" +msgstr "" + +#: warehouse/templates/manage/organization/roles.html:18 +#, python-format +msgid "Manage '%(organization_name)s' collaborators" +msgstr "" + +#: warehouse/templates/manage/organization/roles.html:36 +#, python-format +msgid "" +"Use this page to control which PyPI users can help you to manage " +"%(organization_name)s." +msgstr "" + #: warehouse/templates/packaging/detail.html:106 msgid "view hashes" msgstr "" diff --git a/warehouse/manage/views.py b/warehouse/manage/views.py index d228ad5b2f9b..2791960873c8 100644 --- a/warehouse/manage/views.py +++ b/warehouse/manage/views.py @@ -1112,6 +1112,23 @@ def create_organization(self): return self.default_response +@view_config( + route_name="manage.organization.roles", + context=Organization, + renderer="manage/organization/roles.html", + uses_session=True, + require_methods=False, + # permission="manage:organization", + has_translations=True, + require_reauth=True, +) +def manage_organization_roles(organization, request): + if request.flags.enabled(AdminFlagValue.DISABLE_ORGANIZATIONS): + raise HTTPNotFound + + return {"organization": organization} + + @view_config( route_name="manage.projects", renderer="manage/projects.html", diff --git a/warehouse/organizations/models.py b/warehouse/organizations/models.py index 38b8bdb860f0..e8070a836168 100644 --- a/warehouse/organizations/models.py +++ b/warehouse/organizations/models.py @@ -26,8 +26,7 @@ orm, sql, ) - -# from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.orm.exc import NoResultFound from sqlalchemy_utils.types.url import URLType from warehouse import db @@ -110,23 +109,22 @@ class OrganizationType(enum.Enum): Company = "Company" -# TODO: For future use -# class OrganizationFactory: -# def __init__(self, request): -# self.request = request -# -# def __getitem__(self, organization): -# try: -# return ( -# self.request.db.query(Organization) -# .filter( -# Organization.normalized_name -# == func.normalize_pep426_name(organization) -# ) -# .one() -# ) -# except NoResultFound: -# raise KeyError from None +class OrganizationFactory: + def __init__(self, request): + self.request = request + + def __getitem__(self, organization): + try: + return ( + self.request.db.query(Organization) + .filter( + Organization.normalized_name + == func.normalize_pep426_name(organization) + ) + .one() + ) + except NoResultFound: + raise KeyError from None # TODO: Determine if this should also utilize SitemapMixin and TwoFactorRequireable diff --git a/warehouse/routes.py b/warehouse/routes.py index c3e28a28f529..1376d5d81c79 100644 --- a/warehouse/routes.py +++ b/warehouse/routes.py @@ -222,6 +222,13 @@ def includeme(config): ) config.add_route("manage.account.token", "/manage/account/token/", domain=warehouse) config.add_route("manage.organizations", "/manage/organizations/", domain=warehouse) + config.add_route( + "manage.organization.roles", + "/manage/organization/{organization_name}/collaboration/", + factory="warehouse.organizations.models:OrganizationFactory", + traverse="/{organization_name}", + domain=warehouse, + ) config.add_route("manage.projects", "/manage/projects/", domain=warehouse) config.add_route( "manage.project.settings", diff --git a/warehouse/templates/manage/organization/manage_organization_base.html b/warehouse/templates/manage/organization/manage_organization_base.html new file mode 100644 index 000000000000..66fe564a6dd1 --- /dev/null +++ b/warehouse/templates/manage/organization/manage_organization_base.html @@ -0,0 +1,21 @@ +{# + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-#} +{% extends "manage/manage_base.html" %} + +{% set user = request.user %} +{% set organizations = user.organizations %} +{% set current_organization = organization %} +{% set active_tab = active_tab|default('collaborators') %} + +{% block title %}{% trans organization_name=organization.name %}Manage '{{ organization_name }}'{% endtrans %}{% endblock %} diff --git a/warehouse/templates/manage/organization/roles.html b/warehouse/templates/manage/organization/roles.html new file mode 100644 index 000000000000..19fc7b799a9a --- /dev/null +++ b/warehouse/templates/manage/organization/roles.html @@ -0,0 +1,37 @@ +{# + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-#} +{% extends "manage_organization_base.html" %} + +{% set active_tab = 'collaborators' %} + +{% block title %}{% trans organization_name=organization.name %}Manage '{{ organization_name }}' collaborators{% endtrans %}{% endblock %} + +{% macro two_factor_badge(user) -%} + {% if user.has_two_factor %} + + {% trans %}2FA{% endtrans %} + + + {% else %} + + {% trans %}2FA{% endtrans %} + + + {% endif %} +{% endmacro %} + +{% block main %} +

    {% trans %}Collaborators{% endtrans %}

    +

    {% trans organization_name=organization.name %}Use this page to control which PyPI users can help you to manage {{ organization_name }}.{% endtrans %}

    +{% endblock %} diff --git a/warehouse/templates/manage/organizations.html b/warehouse/templates/manage/organizations.html index 296ec8df7169..cd25207680d6 100644 --- a/warehouse/templates/manage/organizations.html +++ b/warehouse/templates/manage/organizations.html @@ -28,7 +28,6 @@

    {% trans organization_count=organizations|length %}Your o

    {{ organization.name }} {% if organization.name in organizations_owned %} {# TODO {% trans %}Owner{% endtrans %} #} - Owner {% endif %}

    @@ -39,8 +38,7 @@

    {{ organization.name }} {% if organization.name in organizations_owned %} {# Show manage button #} {% trans %}Manage{% endtrans %} diff --git a/warehouse/templates/manage/roles.html b/warehouse/templates/manage/roles.html index 735e2d22149a..2f99f056f2cd 100644 --- a/warehouse/templates/manage/roles.html +++ b/warehouse/templates/manage/roles.html @@ -33,7 +33,7 @@ {% block main %}

    {% trans %}Collaborators{% endtrans %}

    -

    {% trans project_name=project.name %}Use this page to control which PyPI users can help you to manage {{ project_name }}{% endtrans %}

    +

    {% trans project_name=project.name %}Use this page to control which PyPI users can help you to manage {{ project_name }}.{% endtrans %}

    {% trans %}There are two possible roles for collaborators:{% endtrans %}

    From 3fdb89b7160a56cb3282302bb5aad386e93ebd82 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 26 Apr 2022 13:50:18 -0700 Subject: [PATCH 17/24] Add sidebar for managing "Your organizations" --- warehouse/locale/messages.pot | 23 +++++++++--- .../manage/manage-organization-menu.html | 23 ++++++++++++ .../manage_organization_base.html | 37 +++++++++++++++++++ 3 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 warehouse/templates/includes/manage/manage-organization-menu.html diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 0fe2cdfc4dc1..7d01838956aa 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -1874,21 +1874,27 @@ msgstr "" msgid "Email" msgstr "" -#: warehouse/templates/includes/manage/manage-project-menu.html:14 +#: warehouse/templates/includes/manage/manage-organization-menu.html:14 #, python-format -msgid "Navigation for managing %(project)s" -msgstr "" - -#: warehouse/templates/includes/manage/manage-project-menu.html:19 -msgid "Releases" +msgid "Navigation for managing %(organization)s" msgstr "" +#: warehouse/templates/includes/manage/manage-organization-menu.html:19 #: warehouse/templates/includes/manage/manage-project-menu.html:25 #: warehouse/templates/manage/organization/roles.html:35 #: warehouse/templates/manage/roles.html:35 msgid "Collaborators" msgstr "" +#: warehouse/templates/includes/manage/manage-project-menu.html:14 +#, python-format +msgid "Navigation for managing %(project)s" +msgstr "" + +#: warehouse/templates/includes/manage/manage-project-menu.html:19 +msgid "Releases" +msgstr "" + #: warehouse/templates/includes/manage/manage-project-menu.html:31 #: warehouse/templates/manage/account.html:459 #: warehouse/templates/manage/history.html:23 @@ -2998,6 +3004,7 @@ msgstr "" msgid "Back to projects" msgstr "" +#: warehouse/templates/manage/organization/manage_organization_base.html:32 #: warehouse/templates/manage/organizations.html:21 #, python-format msgid "Your organizations (%(organization_count)s)" @@ -4145,6 +4152,10 @@ msgstr "" msgid "Manage '%(organization_name)s'" msgstr "" +#: warehouse/templates/manage/organization/manage_organization_base.html:41 +msgid "Back to organizations" +msgstr "" + #: warehouse/templates/manage/organization/roles.html:18 #, python-format msgid "Manage '%(organization_name)s' collaborators" diff --git a/warehouse/templates/includes/manage/manage-organization-menu.html b/warehouse/templates/includes/manage/manage-organization-menu.html new file mode 100644 index 000000000000..07875d8292f8 --- /dev/null +++ b/warehouse/templates/includes/manage/manage-organization-menu.html @@ -0,0 +1,23 @@ +{# + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-#} + diff --git a/warehouse/templates/manage/organization/manage_organization_base.html b/warehouse/templates/manage/organization/manage_organization_base.html index 66fe564a6dd1..c217e7df993c 100644 --- a/warehouse/templates/manage/organization/manage_organization_base.html +++ b/warehouse/templates/manage/organization/manage_organization_base.html @@ -19,3 +19,40 @@ {% set active_tab = active_tab|default('collaborators') %} {% block title %}{% trans organization_name=organization.name %}Manage '{{ organization_name }}'{% endtrans %}{% endblock %} + +{# Hide mobile search on manager pages #} +{% block mobile_search %}{% endblock %} + +{% block content %} +
    +
    +
    + +
    +
    + + + + {% trans %}Back to organizations{% endtrans %} + +
    +
    +

    {{ organization.name }}

    +
    + + {% with mode="mobile" %} + {% include "warehouse:templates/includes/manage/manage-organization-menu.html" %} + {% endwith %} + + {% block main %}{% endblock %} +
    + {% block mobile_tabs_bottom %}{% endblock %} +
    +
    +
    +{% endblock %} From 5e2fbf5e182af9e7554bbe61a1fd4ba0dff23290 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 26 Apr 2022 14:03:40 -0700 Subject: [PATCH 18/24] Clean up SCSS imports to fix `bin/static_lint` --- warehouse/static/sass/blocks/_organization-snippet.scss | 2 +- warehouse/static/sass/blocks/_package-snippet.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/warehouse/static/sass/blocks/_organization-snippet.scss b/warehouse/static/sass/blocks/_organization-snippet.scss index 913b308fca14..129a81defec4 100644 --- a/warehouse/static/sass/blocks/_organization-snippet.scss +++ b/warehouse/static/sass/blocks/_organization-snippet.scss @@ -12,7 +12,7 @@ * limitations under the License. */ -@import "_snippet"; +@import "snippet"; /* A card that contains information about a organization. Often found in organization lists. diff --git a/warehouse/static/sass/blocks/_package-snippet.scss b/warehouse/static/sass/blocks/_package-snippet.scss index a5dd2d19aa36..472945c11e67 100644 --- a/warehouse/static/sass/blocks/_package-snippet.scss +++ b/warehouse/static/sass/blocks/_package-snippet.scss @@ -12,7 +12,7 @@ * limitations under the License. */ -@import "_snippet"; +@import "snippet"; /* A card that contains information about a package. Often found in package lists. From 9e436398f97bf2d08778594fde39ab6fef4db0eb Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Thu, 28 Apr 2022 11:14:26 -0700 Subject: [PATCH 19/24] Rename {Collaborators => People} for organizations Discussed with @s-mm and renaming to differentiate "people" in organizations from "collaborators" in projects. --- tests/unit/test_routes.py | 2 +- warehouse/locale/messages.pot | 11 +++++++---- warehouse/routes.py | 2 +- .../includes/manage/manage-organization-menu.html | 4 ++-- warehouse/templates/manage/organization/roles.html | 6 +++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/unit/test_routes.py b/tests/unit/test_routes.py index a91299f27671..1baadf16bfb5 100644 --- a/tests/unit/test_routes.py +++ b/tests/unit/test_routes.py @@ -242,7 +242,7 @@ def add_policy(name, filename): ), pretend.call( "manage.organization.roles", - "/manage/organization/{organization_name}/collaboration/", + "/manage/organization/{organization_name}/people/", factory="warehouse.organizations.models:OrganizationFactory", traverse="/{organization_name}", domain=warehouse, diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index 7d01838956aa..e53ae88c80ba 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -1880,10 +1880,8 @@ msgid "Navigation for managing %(organization)s" msgstr "" #: warehouse/templates/includes/manage/manage-organization-menu.html:19 -#: warehouse/templates/includes/manage/manage-project-menu.html:25 #: warehouse/templates/manage/organization/roles.html:35 -#: warehouse/templates/manage/roles.html:35 -msgid "Collaborators" +msgid "People" msgstr "" #: warehouse/templates/includes/manage/manage-project-menu.html:14 @@ -1895,6 +1893,11 @@ msgstr "" msgid "Releases" msgstr "" +#: warehouse/templates/includes/manage/manage-project-menu.html:25 +#: warehouse/templates/manage/roles.html:35 +msgid "Collaborators" +msgstr "" + #: warehouse/templates/includes/manage/manage-project-menu.html:31 #: warehouse/templates/manage/account.html:459 #: warehouse/templates/manage/history.html:23 @@ -4158,7 +4161,7 @@ msgstr "" #: warehouse/templates/manage/organization/roles.html:18 #, python-format -msgid "Manage '%(organization_name)s' collaborators" +msgid "Manage people in '%(organization_name)s'" msgstr "" #: warehouse/templates/manage/organization/roles.html:36 diff --git a/warehouse/routes.py b/warehouse/routes.py index 1376d5d81c79..5382660949db 100644 --- a/warehouse/routes.py +++ b/warehouse/routes.py @@ -224,7 +224,7 @@ def includeme(config): config.add_route("manage.organizations", "/manage/organizations/", domain=warehouse) config.add_route( "manage.organization.roles", - "/manage/organization/{organization_name}/collaboration/", + "/manage/organization/{organization_name}/people/", factory="warehouse.organizations.models:OrganizationFactory", traverse="/{organization_name}", domain=warehouse, diff --git a/warehouse/templates/includes/manage/manage-organization-menu.html b/warehouse/templates/includes/manage/manage-organization-menu.html index 07875d8292f8..5d2dc57352f1 100644 --- a/warehouse/templates/includes/manage/manage-organization-menu.html +++ b/warehouse/templates/includes/manage/manage-organization-menu.html @@ -14,9 +14,9 @@