diff --git a/libraries/constants.py b/libraries/constants.py index 311f4545..f78b4308 100644 --- a/libraries/constants.py +++ b/libraries/constants.py @@ -357,4 +357,6 @@ SELECTED_LIBRARY_VIEW_COOKIE_NAME = "library_view" LATEST_RELEASE_URL_PATH_STR = "latest" LEGACY_LATEST_RELEASE_URL_PATH_STR = "release" +DEVELOP_RELEASE_URL_PATH_STR = "develop" +MASTER_RELEASE_URL_PATH_STR = "master" VERSION_SLUG_PREFIX = "boost-" diff --git a/libraries/mixins.py b/libraries/mixins.py index d0df5000..0f1b5bd9 100644 --- a/libraries/mixins.py +++ b/libraries/mixins.py @@ -2,7 +2,11 @@ from django.shortcuts import get_object_or_404 from django.urls import reverse -from libraries.constants import LATEST_RELEASE_URL_PATH_STR +from libraries.constants import ( + LATEST_RELEASE_URL_PATH_STR, + MASTER_RELEASE_URL_PATH_STR, + DEVELOP_RELEASE_URL_PATH_STR, +) from libraries.models import Library from versions.models import Version @@ -50,6 +54,13 @@ def dispatch(self, request, *args, **kwargs): ) version_path_kwargs = {} + # Only when the user uses master or develop do those versions to appear + if self.extra_context["version_str"] in [ + MASTER_RELEASE_URL_PATH_STR, + DEVELOP_RELEASE_URL_PATH_STR, + ]: + version_path_kwargs[f"allow_{self.extra_context['version_str']}"] = True + if self.request.resolver_match.view_name == "library-detail": version_path_kwargs["flag_versions_without_library"] = get_object_or_404( Library, slug=self.kwargs.get("library_slug") diff --git a/libraries/utils.py b/libraries/utils.py index ab73de53..17c0f6a1 100644 --- a/libraries/utils.py +++ b/libraries/utils.py @@ -17,6 +17,8 @@ SELECTED_LIBRARY_VIEW_COOKIE_NAME, LATEST_RELEASE_URL_PATH_STR, LEGACY_LATEST_RELEASE_URL_PATH_STR, + DEVELOP_RELEASE_URL_PATH_STR, + MASTER_RELEASE_URL_PATH_STR, ) from versions.models import Version @@ -144,20 +146,27 @@ def get_category(request): def determine_selected_boost_version(request_value, request): # use the versions in the request if they are available otherwise fall back to DB + version_slug = request_value or get_version_from_cookie(request) + version_args = {} + if version_slug in (DEVELOP_RELEASE_URL_PATH_STR, MASTER_RELEASE_URL_PATH_STR): + version_args = {f"allow_{version_slug}": True} + valid_versions = getattr(request, "extra_context", {}).get( - "versions", Version.objects.get_dropdown_versions() + "versions", Version.objects.get_dropdown_versions(**version_args) ) - version_slug = request_value or get_version_from_cookie(request) if version_slug in [v.slug for v in valid_versions] + [LATEST_RELEASE_URL_PATH_STR]: return version_slug - else: - logger.warning(f"Invalid version slug in cookies: {version_slug}") - return None + logger.warning(f"Invalid version slug in cookies: {version_slug}") + return None def set_selected_boost_version(version_slug: str, response) -> None: """Update the selected version in the cookies.""" - valid_versions = Version.objects.get_dropdown_versions() + versions_kwargs = {} + if version_slug in [MASTER_RELEASE_URL_PATH_STR, DEVELOP_RELEASE_URL_PATH_STR]: + versions_kwargs[f"allow_{version_slug}"] = True + + valid_versions = Version.objects.get_dropdown_versions(**versions_kwargs) if version_slug in [v.slug for v in valid_versions]: response.set_cookie(SELECTED_BOOST_VERSION_COOKIE_NAME, version_slug) elif version_slug == LATEST_RELEASE_URL_PATH_STR: diff --git a/templates/partials/version_select.html b/templates/partials/version_select.html index baf5c5e5..f997ea4a 100644 --- a/templates/partials/version_select.html +++ b/templates/partials/version_select.html @@ -14,7 +14,7 @@ {% if version_str == v.slug %}selected="selected"{% endif %} {% if v.has_library == 0 %}disabled="disabled"{% endif %} > - {{ v.display_name }} + {{ v.display_name|title }} {% endfor %} diff --git a/versions/converters.py b/versions/converters.py index 62f5f90e..5558f589 100644 --- a/versions/converters.py +++ b/versions/converters.py @@ -2,12 +2,16 @@ LATEST_RELEASE_URL_PATH_STR, LEGACY_LATEST_RELEASE_URL_PATH_STR, VERSION_SLUG_PREFIX, + DEVELOP_RELEASE_URL_PATH_STR, + MASTER_RELEASE_URL_PATH_STR, ) def to_python(value): if value in (LATEST_RELEASE_URL_PATH_STR, LEGACY_LATEST_RELEASE_URL_PATH_STR): return LATEST_RELEASE_URL_PATH_STR + if value in (DEVELOP_RELEASE_URL_PATH_STR, MASTER_RELEASE_URL_PATH_STR): + return value return f"{VERSION_SLUG_PREFIX}{value.replace('.', '-')}" diff --git a/versions/managers.py b/versions/managers.py index 191e5ef1..7ee8a7cf 100644 --- a/versions/managers.py +++ b/versions/managers.py @@ -1,8 +1,13 @@ from django.db import models -from django.db.models import Func, Value, Count +from django.db.models import Func, Value, Count, Q from django.db.models.functions import Replace from django.contrib.postgres.fields import ArrayField +from libraries.constants import ( + MASTER_RELEASE_URL_PATH_STR, + DEVELOP_RELEASE_URL_PATH_STR, +) + class VersionQuerySet(models.QuerySet): def active(self): @@ -81,6 +86,8 @@ def minor_versions(self): def get_dropdown_versions( self, *, + allow_develop: bool = False, + allow_master: bool = False, flag_versions_without_library: "Library" = None, # noqa: F821 order_by: str = "-name", ): @@ -91,6 +98,8 @@ def get_dropdown_versions( * doesn't return versions where full_release=False and beta=False Args: + allow_develop (bool): allow the develop branch version to show in result + allow_master (bool): allow the master branch version to show in the result order_by (str): the field to order by flag_versions_without_library (Library): flag the version when it doesn't have the matching library - e.g. used for library detail page @@ -118,9 +127,24 @@ def should_show_beta(most_recent_beta): beta_queryset = self.active().filter(models.Q(name=most_recent_beta.name)) queryset = queryset | beta_queryset + # beta=False here is not redundant, it only applies to the exclusion while a + # beta is allowed for most_recent_beta + flag_exclusions = Q(full_release=False, beta=False) + name_exclusions = [ + "head", + MASTER_RELEASE_URL_PATH_STR, + DEVELOP_RELEASE_URL_PATH_STR, + ] + if allow_master: + flag_exclusions = flag_exclusions & ~Q(name="master") + name_exclusions.remove(MASTER_RELEASE_URL_PATH_STR) + if allow_develop: + flag_exclusions = flag_exclusions & ~Q(name="develop") + name_exclusions.remove(DEVELOP_RELEASE_URL_PATH_STR) + queryset = ( - queryset.exclude(name__in=["develop", "master", "head"]) - .exclude(full_release=False, beta=False) + queryset.exclude(name__in=name_exclusions) + .exclude(flag_exclusions) .defer("data") )