Skip to content

Commit 3cfc29b

Browse files
authored
Addons: update form to show all the options (#11031)
* Addons: update form to show all the options Add all the configuration options to the `AddonsConfigForm` so the user is able to enable/disable each of the addons independently. Closes readthedocs/ext-theme#211 * Addons: create an `AddonsConfig` for projects automatically * Addons: remove features related to them * Create `AddonsConfig` object automatically Create an `AddonsConfig` object when going to the form view to edit its preferences. By default, disable all the addons for now. * Remove the Crispy layout from Python code * Update tests * Typo * Missing save the object * Make form label more explicit
1 parent 4b0f214 commit 3cfc29b

File tree

4 files changed

+56
-128
lines changed

4 files changed

+56
-128
lines changed

readthedocs/projects/forms.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -479,17 +479,36 @@ class AddonsConfigForm(forms.ModelForm):
479479

480480
class Meta:
481481
model = AddonsConfig
482-
fields = ("enabled", "project")
482+
fields = (
483+
"enabled",
484+
"project",
485+
"analytics_enabled",
486+
"doc_diff_enabled",
487+
"external_version_warning_enabled",
488+
"flyout_enabled",
489+
"hotkeys_enabled",
490+
"search_enabled",
491+
"stable_latest_version_warning_enabled",
492+
)
493+
labels = {
494+
"enabled": _("Enable Addons"),
495+
"external_version_warning_enabled": _(
496+
"Show a notification on builds from pull requests"
497+
),
498+
"stable_latest_version_warning_enabled": _(
499+
"Show a notification on non-stable and latest versions"
500+
),
501+
}
483502

484503
def __init__(self, *args, **kwargs):
485504
self.project = kwargs.pop("project", None)
486-
kwargs["instance"] = getattr(self.project, "addons", None)
487-
super().__init__(*args, **kwargs)
505+
addons, created = AddonsConfig.objects.get_or_create(project=self.project)
506+
if created:
507+
addons.enabled = False
508+
addons.save()
488509

489-
try:
490-
self.fields["enabled"].initial = self.project.addons.enabled
491-
except AddonsConfig.DoesNotExist:
492-
self.fields["enabled"].initial = False
510+
kwargs["instance"] = addons
511+
super().__init__(*args, **kwargs)
493512

494513
def clean_project(self):
495514
return self.project

readthedocs/projects/models.py

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,25 +1976,6 @@ def add_features(sender, **kwargs):
19761976
# Build related features
19771977
SCALE_IN_PROTECTION = "scale_in_prtection"
19781978

1979-
# Addons related features
1980-
HOSTING_INTEGRATIONS = "hosting_integrations"
1981-
# NOTE: this is mainly temporal while we are rolling these features out.
1982-
# The idea here is to have more control over particular projects and do some testing.
1983-
# All these features will be enabled by default to all projects,
1984-
# and we can disable them if we want to
1985-
ADDONS_ANALYTICS_DISABLED = "addons_analytics_disabled"
1986-
ADDONS_DOC_DIFF_DISABLED = "addons_doc_diff_disabled"
1987-
ADDONS_ETHICALADS_DISABLED = "addons_ethicalads_disabled"
1988-
ADDONS_EXTERNAL_VERSION_WARNING_DISABLED = (
1989-
"addons_external_version_warning_disabled"
1990-
)
1991-
ADDONS_FLYOUT_DISABLED = "addons_flyout_disabled"
1992-
ADDONS_NON_LATEST_VERSION_WARNING_DISABLED = (
1993-
"addons_non_latest_version_warning_disabled"
1994-
)
1995-
ADDONS_SEARCH_DISABLED = "addons_search_disabled"
1996-
ADDONS_HOTKEYS_DISABLED = "addons_hotkeys_disabled"
1997-
19981979
FEATURES = (
19991980
(
20001981
MKDOCS_THEME_RTD,
@@ -2088,45 +2069,6 @@ def add_features(sender, **kwargs):
20882069
SCALE_IN_PROTECTION,
20892070
_("Build: Set scale-in protection before/after building."),
20902071
),
2091-
# Addons related features.
2092-
(
2093-
HOSTING_INTEGRATIONS,
2094-
_(
2095-
"Proxito: Inject 'readthedocs-addons.js' as <script> HTML tag in responses."
2096-
),
2097-
),
2098-
(
2099-
ADDONS_ANALYTICS_DISABLED,
2100-
_("Addons: Disable Analytics."),
2101-
),
2102-
(
2103-
ADDONS_DOC_DIFF_DISABLED,
2104-
_("Addons: Disable Doc Diff."),
2105-
),
2106-
(
2107-
ADDONS_ETHICALADS_DISABLED,
2108-
_("Addons: Disable EthicalAds."),
2109-
),
2110-
(
2111-
ADDONS_EXTERNAL_VERSION_WARNING_DISABLED,
2112-
_("Addons: Disable External version warning."),
2113-
),
2114-
(
2115-
ADDONS_FLYOUT_DISABLED,
2116-
_("Addons: Disable Flyout."),
2117-
),
2118-
(
2119-
ADDONS_NON_LATEST_VERSION_WARNING_DISABLED,
2120-
_("Addons: Disable Non latest version warning."),
2121-
),
2122-
(
2123-
ADDONS_SEARCH_DISABLED,
2124-
_("Addons: Disable Search."),
2125-
),
2126-
(
2127-
ADDONS_HOTKEYS_DISABLED,
2128-
_("Addons: Disable Hotkeys."),
2129-
),
21302072
)
21312073

21322074
FEATURES = sorted(FEATURES, key=lambda l: l[1])

readthedocs/proxito/tests/test_hosting.py

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
PUBLIC,
1818
SINGLE_VERSION_WITHOUT_TRANSLATIONS,
1919
)
20-
from readthedocs.projects.models import Domain, Feature, Project
20+
from readthedocs.projects.models import AddonsConfig, Domain, Project
2121

2222

2323
@override_settings(
@@ -128,42 +128,20 @@ def test_get_config_unsupported_version(self):
128128
assert r.status_code == 400
129129
assert r.json() == self._get_response_dict("v2")
130130

131-
def test_disabled_addons_via_feature_flags(self):
132-
fixture.get(
133-
Feature,
134-
projects=[self.project],
135-
feature_id=Feature.ADDONS_ANALYTICS_DISABLED,
136-
)
137-
fixture.get(
138-
Feature,
139-
projects=[self.project],
140-
feature_id=Feature.ADDONS_EXTERNAL_VERSION_WARNING_DISABLED,
141-
)
142-
fixture.get(
143-
Feature,
144-
projects=[self.project],
145-
feature_id=Feature.ADDONS_NON_LATEST_VERSION_WARNING_DISABLED,
146-
)
147-
fixture.get(
148-
Feature,
149-
projects=[self.project],
150-
feature_id=Feature.ADDONS_DOC_DIFF_DISABLED,
151-
)
152-
fixture.get(
153-
Feature,
154-
projects=[self.project],
155-
feature_id=Feature.ADDONS_FLYOUT_DISABLED,
156-
)
157-
fixture.get(
158-
Feature,
159-
projects=[self.project],
160-
feature_id=Feature.ADDONS_SEARCH_DISABLED,
161-
)
162-
fixture.get(
163-
Feature,
164-
projects=[self.project],
165-
feature_id=Feature.ADDONS_HOTKEYS_DISABLED,
131+
def test_disabled_addons_via_addons_config(self):
132+
addons = fixture.get(
133+
AddonsConfig,
134+
project=self.project,
166135
)
136+
addons.analytics_enabled = False
137+
addons.doc_diff_enabled = False
138+
addons.external_version_warning_enabled = False
139+
addons.ethicalads_enabled = False
140+
addons.flyout_enabled = False
141+
addons.hotkeys_enabled = False
142+
addons.search_enabled = False
143+
addons.stable_latest_version_warning_enabled = False
144+
addons.save()
167145

168146
r = self.client.get(
169147
reverse("proxito_readthedocs_docs_addons"),
@@ -678,7 +656,7 @@ def test_number_of_queries_project_version_slug(self):
678656
active=True,
679657
)
680658

681-
with self.assertNumQueries(17):
659+
with self.assertNumQueries(20):
682660
r = self.client.get(
683661
reverse("proxito_readthedocs_docs_addons"),
684662
{
@@ -707,7 +685,7 @@ def test_number_of_queries_url(self):
707685
active=True,
708686
)
709687

710-
with self.assertNumQueries(17):
688+
with self.assertNumQueries(20):
711689
r = self.client.get(
712690
reverse("proxito_readthedocs_docs_addons"),
713691
{
@@ -743,7 +721,7 @@ def test_number_of_queries_url_subproject(self):
743721
active=True,
744722
)
745723

746-
with self.assertNumQueries(21):
724+
with self.assertNumQueries(24):
747725
r = self.client.get(
748726
reverse("proxito_readthedocs_docs_addons"),
749727
{
@@ -769,7 +747,7 @@ def test_number_of_queries_url_translations(self):
769747
language=language,
770748
)
771749

772-
with self.assertNumQueries(21):
750+
with self.assertNumQueries(24):
773751
r = self.client.get(
774752
reverse("proxito_readthedocs_docs_addons"),
775753
{

readthedocs/proxito/views/hosting.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from readthedocs.core.resolver import Resolver
2424
from readthedocs.core.unresolver import UnresolverError, unresolver
2525
from readthedocs.core.utils.extend import SettingsOverrideObject
26-
from readthedocs.projects.models import Feature, Project
26+
from readthedocs.projects.models import AddonsConfig, Project
2727

2828
log = structlog.get_logger(__name__) # noqa
2929

@@ -280,15 +280,9 @@ def _v0(self, project, version, build, filename, url, user):
280280
# en (original), es, ru
281281
project_translations = itertools.chain([main_project], project_translations)
282282

283-
# Make one DB query here and then check on Python code
284-
# TODO: make usage of ``Project.addons.<name>_enabled`` to decide if enabled
285-
#
286-
# NOTE: using ``feature_id__startswith="addons_"`` to make the query faster.
287-
# It went down from 20ms to 1ms since it does not have to check the
288-
# `Project.pub_date` against all the features.
289-
project_features = project.features.filter(
290-
feature_id__startswith="addons_"
291-
).values_list("feature_id", flat=True)
283+
# Automatically create an AddonsConfig with the default values for
284+
# projects that don't have one already
285+
AddonsConfig.objects.get_or_create(project=project)
292286

293287
data = {
294288
"api_version": "0",
@@ -320,24 +314,21 @@ def _v0(self, project, version, build, filename, url, user):
320314
# serializer than the keys ``project``, ``version`` and ``build`` from the top level.
321315
"addons": {
322316
"analytics": {
323-
"enabled": Feature.ADDONS_ANALYTICS_DISABLED
324-
not in project_features,
317+
"enabled": project.addons.analytics_enabled,
325318
# TODO: consider adding this field into the ProjectSerializer itself.
326319
# NOTE: it seems we are removing this feature,
327320
# so we may not need the ``code`` attribute here
328321
# https://github.com/readthedocs/readthedocs.org/issues/9530
329322
"code": project.analytics_code,
330323
},
331324
"external_version_warning": {
332-
"enabled": Feature.ADDONS_EXTERNAL_VERSION_WARNING_DISABLED
333-
not in project_features,
325+
"enabled": project.addons.external_version_warning_enabled,
334326
# NOTE: I think we are moving away from these selectors
335327
# since we are doing floating noticications now.
336328
# "query_selector": "[role=main]",
337329
},
338330
"non_latest_version_warning": {
339-
"enabled": Feature.ADDONS_NON_LATEST_VERSION_WARNING_DISABLED
340-
not in project_features,
331+
"enabled": project.addons.stable_latest_version_warning_enabled,
341332
# NOTE: I think we are moving away from these selectors
342333
# since we are doing floating noticications now.
343334
# "query_selector": "[role=main]",
@@ -346,7 +337,7 @@ def _v0(self, project, version, build, filename, url, user):
346337
),
347338
},
348339
"flyout": {
349-
"enabled": Feature.ADDONS_FLYOUT_DISABLED not in project_features,
340+
"enabled": project.addons.flyout_enabled,
350341
"translations": [
351342
{
352343
# TODO: name this field "display_name"
@@ -398,7 +389,7 @@ def _v0(self, project, version, build, filename, url, user):
398389
# },
399390
},
400391
"search": {
401-
"enabled": Feature.ADDONS_SEARCH_DISABLED not in project_features,
392+
"enabled": project.addons.search_enabled,
402393
"project": project.slug,
403394
"version": version.slug if version else None,
404395
"api_endpoint": "/_/api/v3/search/",
@@ -416,7 +407,7 @@ def _v0(self, project, version, build, filename, url, user):
416407
else None,
417408
},
418409
"hotkeys": {
419-
"enabled": Feature.ADDONS_HOTKEYS_DISABLED not in project_features,
410+
"enabled": project.addons.hotkeys_enabled,
420411
"doc_diff": {
421412
"enabled": True,
422413
"trigger": "KeyD", # Could be something like "Ctrl + D"
@@ -437,8 +428,7 @@ def _v0(self, project, version, build, filename, url, user):
437428
data["addons"].update(
438429
{
439430
"doc_diff": {
440-
"enabled": Feature.ADDONS_DOC_DIFF_DISABLED
441-
not in project_features,
431+
"enabled": project.addons.doc_diff_enabled,
442432
# "http://test-builds-local.devthedocs.org/en/latest/index.html"
443433
"base_url": resolver.resolve(
444434
project=project,
@@ -478,8 +468,7 @@ def _v0(self, project, version, build, filename, url, user):
478468
data["addons"].update(
479469
{
480470
"ethicalads": {
481-
"enabled": Feature.ADDONS_ETHICALADS_DISABLED
482-
not in project_features,
471+
"enabled": project.addons.ethicalads_enabled,
483472
# NOTE: this endpoint is not authenticated, the user checks are done over an annonymous user for now
484473
#
485474
# NOTE: it requires ``settings.USE_PROMOS=True`` to return ``ad_free=false`` here

0 commit comments

Comments
 (0)