diff --git a/accounts/tests.py b/accounts/tests.py index c41d893b1a..c90377e919 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -6,17 +6,19 @@ from django_hosts.resolvers import reverse from accounts.forms import DeleteProfileForm +from djangoproject.tests import ReleaseMixin from foundation import models as foundationmodels from tracdb.models import Revision, Ticket, TicketChange from tracdb.testutils import TracDBCreateDatabaseMixin @override_settings(TRAC_URL="https://code.djangoproject.com/") -class UserProfileTests(TracDBCreateDatabaseMixin, TestCase): +class UserProfileTests(TracDBCreateDatabaseMixin, ReleaseMixin, TestCase): databases = {"default", "trac"} @classmethod def setUpTestData(cls): + super().setUpTestData() User.objects.create_user(username="user1", password="password") User.objects.create_user(username="user2", password="password") cls.user1_url = reverse("user_profile", args=["user1"]) @@ -175,7 +177,7 @@ def test_caches_trac_stats(self): self.assertIsNotNone(cache.get(key)) -class ViewsTests(TestCase): +class ViewsTests(ReleaseMixin, TestCase): def test_login_redirect(self): credentials = {"username": "a-user", "password": "password"} @@ -193,7 +195,7 @@ def test_profile_view_reversal(self): reverse("user_profile", host="www", args=[username]) -class UserDeletionTests(TestCase): +class UserDeletionTests(ReleaseMixin, TestCase): def create_user_and_form(self, bound=True, **userkwargs): userkwargs.setdefault("username", "test") userkwargs.setdefault("email", "test@example.com") diff --git a/aggregator/tests.py b/aggregator/tests.py index 9f705be184..a8e583decf 100644 --- a/aggregator/tests.py +++ b/aggregator/tests.py @@ -26,7 +26,7 @@ def setUp(self, mocker): ) DocumentRelease.objects.update_or_create( release=release, - lang="en", + lang=settings.DEFAULT_LANGUAGE_CODE, defaults={"is_default": True}, ) @@ -92,7 +92,7 @@ def setUp(self, mocker): def test_community_index_number_of_queries(self): """Intended to prevent an n+1 issue on the community index view""" url = reverse("community-index") - with self.assertNumQueries(6): + with self.assertNumQueries(7): self.client.get(url) def test_empty_feed_type_not_rendered(self): @@ -119,7 +119,7 @@ def test_feed_list_number_of_queries(self): url = reverse( "community-feed-list", kwargs={"feed_type_slug": self.feed_type.slug} ) - with self.assertNumQueries(7): + with self.assertNumQueries(8): self.client.get(url) def test_management_command_sends_no_email_with_no_pending_feeds(self): diff --git a/blog/models.py b/blog/models.py index 988c607eb4..c365185ca1 100644 --- a/blog/models.py +++ b/blog/models.py @@ -196,7 +196,7 @@ def invalidate_cached_entry(self): ) is_secure = url.scheme == "https" request = rf.get(url.path, secure=is_secure) - request.LANGUAGE_CODE = "en" + request.LANGUAGE_CODE = settings.DEFAULT_LANGUAGE_CODE cache = caches[settings.CACHE_MIDDLEWARE_ALIAS] cache_key = _generate_cache_header_key( settings.CACHE_MIDDLEWARE_KEY_PREFIX, request diff --git a/blog/tests.py b/blog/tests.py index b5c1b1802b..2f68edb9ba 100644 --- a/blog/tests.py +++ b/blog/tests.py @@ -12,6 +12,8 @@ from django.urls import reverse from django.utils import timezone, translation +from djangoproject.tests import ReleaseMixin + from .models import ContentFormat, Entry, Event, ImageUpload from .sitemaps import WeblogSitemap @@ -189,7 +191,7 @@ def test_past_future_ordering(self): ) -class ViewsTestCase(DateTimeMixin, TestCase): +class ViewsTestCase(ReleaseMixin, DateTimeMixin, TestCase): def test_staff_with_change_permission_can_see_unpublished_detail_view(self): """ Staff users with change permission on BlogEntry can't see unpublished entries @@ -418,7 +420,7 @@ def test_user_cannot_see_unpublished_entries(self): + ["django.middleware.cache.FetchFromCacheMiddleware"] ), ) -class ViewsCachingTestCase(DateTimeMixin, TestCase): +class ViewsCachingTestCase(ReleaseMixin, DateTimeMixin, TestCase): def test_drafts_have_no_cache_headers(self): """ Draft (unpublished) entries have no-cache headers. diff --git a/contact/tests.py b/contact/tests.py index a11ea52241..cf5f0b5028 100644 --- a/contact/tests.py +++ b/contact/tests.py @@ -6,6 +6,8 @@ from django.test import TestCase from django.test.utils import override_settings +from djangoproject.tests import ReleaseMixin + from .views import FoundationContactForm @@ -21,7 +23,7 @@ def check_network_connection(): @override_settings(AKISMET_TESTING=True) -class ContactFormTests(TestCase): +class ContactFormTests(ReleaseMixin, TestCase): def setUp(self): self.url = "/contact/foundation/" diff --git a/dashboard/tests.py b/dashboard/tests.py index 577158959e..5049825067 100644 --- a/dashboard/tests.py +++ b/dashboard/tests.py @@ -9,6 +9,7 @@ from django.test import RequestFactory, TestCase from django_hosts.resolvers import reverse +from djangoproject.tests import ReleaseMixin from tracdb.models import Ticket from tracdb.testutils import TracDBCreateDatabaseMixin from tracdb.tractime import datetime_to_timestamp @@ -24,7 +25,7 @@ from .views import index, metric_detail, metric_json -class ViewTests(TestCase): +class ViewTests(ReleaseMixin, TestCase): fixtures = ["dashboard_test_data"] def setUp(self): diff --git a/djangoproject/scss/_dark-mode.scss b/djangoproject/scss/_dark-mode.scss index c7365abf35..53b26067d2 100644 --- a/djangoproject/scss/_dark-mode.scss +++ b/djangoproject/scss/_dark-mode.scss @@ -346,20 +346,28 @@ html[data-theme="light"] .theme-toggle .theme-label-when-light { background-color: var(--body-bg); } -.mobile-toggle { - width: 45px; - height: 45px; +// Section of the header that is only visible on mobile. +.header-mobile-only { line-height: 45px; text-align: center; - margin: 4px 10px; + display: flex; + align-items: center; - @include respond-min(768px) { + @include respond-min(1080px) { display: none; } + + .light-dark-mode-toggle { + height: 45px; + width: 45px; + margin: 2px; + } } -header nav li:last-child { - @include respond-max(768px) { +// The last 2 items of the nav list are the searchbar and the light/dark mode toggle. +// These are not visible on mobile as they are within the .header-mobile-only section. +header nav li:nth-last-child(-n+2) { + @include respond-max(1080px) { display: none; } } diff --git a/djangoproject/scss/_style.scss b/djangoproject/scss/_style.scss index 2fe7c0cfd1..1a580b655e 100644 --- a/djangoproject/scss/_style.scss +++ b/djangoproject/scss/_style.scss @@ -425,7 +425,6 @@ main { .container { @include respond-min(768px) { margin: 0 auto; - max-width: 1400px; padding: 0 (32/768) * 100%; } @@ -463,13 +462,10 @@ header { .container { display: flex; - flex-direction: row; - @include respond-min(768px) { - position: relative; - } + align-items: center; } - .mobile-toggle {margin-left: auto} + .header-mobile-only {margin-left: auto} .meta { @include font-size(13); @@ -479,7 +475,7 @@ header { margin: 8px 0 0 10px; display: none; - @include respond-min(1150px) { + @include respond-min(1080px) { width: 200px; display: block; } @@ -490,19 +486,26 @@ header { .logo { @include font-size(40); @include sans-serif; - background: url(../img/logo-django.svg) center center no-repeat; + // Small screens less than 500px use the dj logo. This gives more + // horizontal space for a searchbar in the header. + background: url(../img/logo-dj.svg) center center no-repeat; color: var(--white-color); display: block; font-weight: 700; - margin: 10px; + margin: 10px 4px; overflow: hidden; text-decoration: none; text-indent: 100%; - width: 104px; + width: 45px; height: 36px; - @include respond-min(768px) { - margin-left: 0; + @include respond-min(500px) { + background: url(../img/logo-django.svg) center center no-repeat; + width: 104px; + } + + @include respond-min(1080px) { + margin-left: 10px; } } @@ -514,13 +517,12 @@ header { cursor: pointer; display: block; height: 45px; - line-height: 48px; - margin: 4px 10px; + margin: 2px; text-align: center; text-decoration: none; width: 45px; - @include respond-min(768px) { + @include respond-min(1080px) { display: none; } @@ -544,7 +546,7 @@ header { max-height: 580px; } - @include respond-min(768px) { + @include respond-min(1080px) { width: auto; max-height: none; // always show menu on a desktop width } @@ -553,7 +555,9 @@ header { margin: 10px 0 0; padding: 0; - @include respond-min(768px) { + @include respond-min(1080px) { + display: flex; + align-items: center; margin: 0; } } @@ -568,14 +572,18 @@ header { text-transform: uppercase; margin: 0 10px; border-top: 1px solid lighten($green-dark, 5%); - padding: 20px 0px; + > :not(.search){ + padding: 20px 0px; + } - @include respond-min(768px) { + @include respond-min(1080px) { margin: 0; border: 0; float: left; text-align: left; - padding: 20px 10px; + > :not(.search){ + padding: 10px; + } } &.active a { @@ -608,18 +616,11 @@ header { color: var(--secondary-accent); } - @include respond-min(768px) { + @include respond-min(1080px) { padding: 20px 10px; } } - .nav-primary { - @include respond-min(768px) { - position: absolute; - right: 0; - top: 45px; - } - } } } @@ -645,7 +646,7 @@ header { top: 0; max-width: 660px; - @include respond-min(768px) { + @include respond-min(1080px) { position: static; } } @@ -2646,7 +2647,7 @@ search.filters { position: relative; a { - padding: 10px 20px; + padding: 10px 15px; text-decoration: none; border-bottom: 3px solid transparent; transition: color 0.3s ease, border-bottom 0.3s ease; @@ -3005,14 +3006,10 @@ form { height: 40px; padding: 0; position: absolute; - right: 2%; + right: 0; top: 6%; width: 40px; - @include respond-min(768px) { - right: 1%; - } - i { @include font-size(20); line-height: 1; @@ -3054,16 +3051,15 @@ form { } &.search { - @include respond-min(768px) { - flex: 0 0 40%; - margin: 10px 0; - } - - flex: 0 0 100%; - margin: 0 0 10px 0; - - button { - top: 19%; + width: 20%; + min-width: 200px; + margin: 10px; + margin-left: 0; + input { + margin: 0; + @include respond-min(1080px) { + margin: 0 10px; + } } } } @@ -3602,7 +3598,7 @@ ul.corporate-members li { justify-content: space-between; } - @include respond-max(1200px) { + @include respond-max(1080px) { .community-title { text-align: center; } diff --git a/djangoproject/settings/common.py b/djangoproject/settings/common.py index 82819c3cc0..a607f68cf9 100644 --- a/djangoproject/settings/common.py +++ b/djangoproject/settings/common.py @@ -313,3 +313,5 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField" FORMS_URLFIELD_ASSUME_HTTPS = True + +DEFAULT_LANGUAGE_CODE = "en" diff --git a/djangoproject/static/img/logo-dj.svg b/djangoproject/static/img/logo-dj.svg new file mode 100644 index 0000000000..5ecd24d91d --- /dev/null +++ b/djangoproject/static/img/logo-dj.svg @@ -0,0 +1,10 @@ + + + django-dj-centered + + + + + + + diff --git a/djangoproject/templates/includes/header.html b/djangoproject/templates/includes/header.html index 8c9da6cd65..b51fb9fe72 100644 --- a/djangoproject/templates/includes/header.html +++ b/djangoproject/templates/includes/header.html @@ -1,3 +1,4 @@ +{% load docs %} {% if 'preview.djangoproject.com' in request.get_host %}
{% endif %} @@ -5,8 +6,11 @@

The web framework for perfectionists with deadlines.

-
- {% include "includes/toggle_theme.html" %} +
+ {% search_form %} +
+ {% include "includes/toggle_theme.html" %} +