Skip to content

Commit 7120315

Browse files
Addons: allow users to show/hide notifications on latest/non-stable (#11718)
We currently allow users to disable the latest and non-stable notifications with only one checkbox. This PR split this checkbox into two, so users can decide to show a notification on latest and/or on non-stable versions individually. Note this PR also changes the addons API response: `non_latest_version_warning` and `external_version_warning` are combined into `notifications`. I think nobody is using this yet, so I'm not expecting issues with it. Let me know if you think differently here. Required by readthedocs/addons#133 --------- Co-authored-by: Eric Holscher <[email protected]> Co-authored-by: Eric Holscher <[email protected]>
1 parent 63f3926 commit 7120315

File tree

11 files changed

+186
-40
lines changed

11 files changed

+186
-40
lines changed

docs/user/addons.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ and can be accessed via hotkeys or on screen UI elements.
88
:doc:`DocDiff </pull-requests>`
99
Highlight changed output from pull requests
1010

11-
:doc:`Pull request notification </pull-requests>`
12-
Notify readers that they are reading docs from a pull request
11+
:doc:`Documentation notification </doc-notifications>`
12+
Alert users to various documentation states
1313

1414
:doc:`Flyout </flyout-menu>`
1515
Easily switch between versions and translations

docs/user/doc-notifications.rst

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Documentation notifications
2+
===========================
3+
4+
Documentation notifications alert users to information about the documentation they are viewing.
5+
These notifications can be enabled or disabled by the project maintainer,
6+
and are displayed to the user in the rendered documentation.
7+
8+
Overview
9+
--------
10+
11+
The current notifications are:
12+
13+
- **Pull request warning**: Show a notification on builds from pull requests, with a link back to the pull request for giving feedback.
14+
- **Latest version warning**: Show a notification on latest version, warning users that they are reading docs from a development version.
15+
- **Non-stable version warning**: Show a notification on non-stable versions, warning users that they are reading docs from a non-stable release.
16+
17+
Manage notifications
18+
--------------------
19+
20+
To manage notifications for your project:
21+
22+
1. Go to the :term:`dashboard`.
23+
2. Click on a project name.
24+
3. Go to :guilabel:`Settings`.
25+
4. In the left bar, go to :guilabel:`Addons`.
26+
5. Configure each Addon in the :guilabel:`Notifications` section.

docs/user/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Read the Docs: documentation simplified
4747
/localization
4848
/versioning-schemes
4949
/custom-domains
50+
/doc-notifications
5051
/canonical-urls
5152
/reference/cdn
5253
/reference/sitemaps

readthedocs/projects/forms.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -654,23 +654,26 @@ class Meta:
654654
"analytics_enabled",
655655
"doc_diff_enabled",
656656
"doc_diff_root_selector",
657-
"external_version_warning_enabled",
658657
"flyout_enabled",
659658
"flyout_sorting",
660659
"flyout_sorting_latest_stable_at_beginning",
661660
"flyout_sorting_custom_pattern",
662661
"hotkeys_enabled",
663662
"search_enabled",
664-
"stable_latest_version_warning_enabled",
663+
"notifications_enabled",
664+
"notifications_show_on_latest",
665+
"notifications_show_on_non_stable",
666+
"notifications_show_on_external",
665667
)
666668
labels = {
667669
"enabled": _("Enable Addons"),
668-
"external_version_warning_enabled": _(
670+
"notifications_show_on_external": _(
669671
"Show a notification on builds from pull requests"
670672
),
671-
"stable_latest_version_warning_enabled": _(
672-
"Show a notification on non-stable and latest versions"
673+
"notifications_show_on_non_stable": _(
674+
"Show a notification on non-stable versions"
673675
),
676+
"notifications_show_on_latest": _("Show a notification on latest version"),
674677
}
675678
widgets = {
676679
"doc_diff_root_selector": forms.TextInput(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Generated by Django 4.2.16 on 2024-10-29 14:05
2+
3+
from django.db import migrations, models
4+
from django_safemigrate import Safe
5+
6+
7+
def forward_add_fields(apps, schema_editor):
8+
AddonsConfig = apps.get_model("projects", "AddonsConfig")
9+
for addons in AddonsConfig.objects.filter(project__isnull=False):
10+
addons.notifications_show_on_latest = (
11+
addons.stable_latest_version_warning_enabled
12+
)
13+
addons.notifications_show_on_non_stable = (
14+
addons.stable_latest_version_warning_enabled
15+
)
16+
addons.notifications_show_on_external = addons.external_version_warning_enabled
17+
addons.save()
18+
19+
20+
def reverse_remove_fields(apps, schema_editor):
21+
AddonsConfig = apps.get_model("projects", "AddonsConfig")
22+
for addons in AddonsConfig.objects.filter(project__isnull=False):
23+
addons.stable_latest_version_warning_enabled = (
24+
addons.notifications_show_on_latest
25+
or addons.notifications_show_on_non_stable
26+
)
27+
addons.external_version_warning_enabled = addons.notifications_show_on_external
28+
addons.save()
29+
30+
31+
class Migration(migrations.Migration):
32+
safe = Safe.before_deploy
33+
34+
dependencies = [
35+
("projects", "0127_default_to_semver"),
36+
]
37+
38+
operations = [
39+
migrations.AddField(
40+
model_name="addonsconfig",
41+
name="notifications_enabled",
42+
field=models.BooleanField(default=True),
43+
),
44+
migrations.AddField(
45+
model_name="addonsconfig",
46+
name="notifications_show_on_external",
47+
field=models.BooleanField(default=True),
48+
),
49+
migrations.AddField(
50+
model_name="addonsconfig",
51+
name="notifications_show_on_latest",
52+
field=models.BooleanField(default=True),
53+
),
54+
migrations.AddField(
55+
model_name="addonsconfig",
56+
name="notifications_show_on_non_stable",
57+
field=models.BooleanField(default=True),
58+
),
59+
migrations.AddField(
60+
model_name="historicaladdonsconfig",
61+
name="notifications_enabled",
62+
field=models.BooleanField(default=True),
63+
),
64+
migrations.AddField(
65+
model_name="historicaladdonsconfig",
66+
name="notifications_show_on_external",
67+
field=models.BooleanField(default=True),
68+
),
69+
migrations.AddField(
70+
model_name="historicaladdonsconfig",
71+
name="notifications_show_on_latest",
72+
field=models.BooleanField(default=True),
73+
),
74+
migrations.AddField(
75+
model_name="historicaladdonsconfig",
76+
name="notifications_show_on_non_stable",
77+
field=models.BooleanField(default=True),
78+
),
79+
migrations.RunPython(forward_add_fields, reverse_remove_fields),
80+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Generated by Django 4.2.16 on 2024-10-29 14:09
2+
3+
from django.db import migrations
4+
from django_safemigrate import Safe
5+
6+
7+
class Migration(migrations.Migration):
8+
safe = Safe.after_deploy
9+
10+
dependencies = [
11+
("projects", "0128_addons_notifications"),
12+
]
13+
14+
operations = [
15+
migrations.RemoveField(
16+
model_name="addonsconfig",
17+
name="external_version_warning_enabled",
18+
),
19+
migrations.RemoveField(
20+
model_name="addonsconfig",
21+
name="stable_latest_version_warning_enabled",
22+
),
23+
migrations.RemoveField(
24+
model_name="historicaladdonsconfig",
25+
name="external_version_warning_enabled",
26+
),
27+
migrations.RemoveField(
28+
model_name="historicaladdonsconfig",
29+
name="stable_latest_version_warning_enabled",
30+
),
31+
]

readthedocs/projects/models.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,6 @@ class AddonsConfig(TimeStampedModel):
178178
help_text="CSS selector for the main content of the page",
179179
)
180180

181-
# External version warning
182-
external_version_warning_enabled = models.BooleanField(default=True)
183-
184181
# EthicalAds
185182
ethicalads_enabled = models.BooleanField(default=True)
186183

@@ -215,8 +212,11 @@ class AddonsConfig(TimeStampedModel):
215212
search_enabled = models.BooleanField(default=True)
216213
search_default_filter = models.CharField(null=True, blank=True, max_length=128)
217214

218-
# Stable/Latest version warning
219-
stable_latest_version_warning_enabled = models.BooleanField(default=True)
215+
# Notifications
216+
notifications_enabled = models.BooleanField(default=True)
217+
notifications_show_on_latest = models.BooleanField(default=True)
218+
notifications_show_on_non_stable = models.BooleanField(default=True)
219+
notifications_show_on_external = models.BooleanField(default=True)
220220

221221

222222
class AddonSearchFilter(TimeStampedModel):

readthedocs/proxito/tests/responses/v1.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@
125125
"enabled": false,
126126
"code": null
127127
},
128-
"external_version_warning": {
129-
"enabled": true
130-
},
131128
"hotkeys": {
132129
"enabled": true,
133130
"doc_diff": {
@@ -139,8 +136,11 @@
139136
"trigger": "Slash"
140137
}
141138
},
142-
"non_latest_version_warning": {
143-
"enabled": true
139+
"notifications": {
140+
"enabled": true,
141+
"show_on_external": true,
142+
"show_on_latest": true,
143+
"show_on_non_stable": true
144144
},
145145
"doc_diff": {
146146
"enabled": true,

readthedocs/proxito/tests/test_hosting.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ def test_disabled_addons_via_addons_config(self):
149149
addons.flyout_enabled = False
150150
addons.hotkeys_enabled = False
151151
addons.search_enabled = False
152-
addons.stable_latest_version_warning_enabled = False
152+
addons.notifications_enabled = False
153+
addons.notifications_show_on_latest = False
154+
addons.notifications_show_on_non_stable = False
155+
addons.notifications_show_on_external = False
153156
addons.save()
154157

155158
r = self.client.get(
@@ -166,8 +169,10 @@ def test_disabled_addons_via_addons_config(self):
166169
)
167170
assert r.status_code == 200
168171
assert r.json()["addons"]["analytics"]["enabled"] is False
169-
assert r.json()["addons"]["external_version_warning"]["enabled"] is False
170-
assert r.json()["addons"]["non_latest_version_warning"]["enabled"] is False
172+
assert r.json()["addons"]["notifications"]["enabled"] is False
173+
assert r.json()["addons"]["notifications"]["show_on_latest"] is False
174+
assert r.json()["addons"]["notifications"]["show_on_non_stable"] is False
175+
assert r.json()["addons"]["notifications"]["show_on_external"] is False
171176
assert r.json()["addons"]["doc_diff"]["enabled"] is False
172177
assert r.json()["addons"]["flyout"]["enabled"] is False
173178
assert r.json()["addons"]["search"]["enabled"] is False

readthedocs/proxito/views/hosting.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -462,17 +462,11 @@ def _v1(self, project, version, build, filename, url, request):
462462
# https://github.com/readthedocs/readthedocs.org/issues/9530
463463
"code": project.analytics_code,
464464
},
465-
"external_version_warning": {
466-
"enabled": project.addons.external_version_warning_enabled,
467-
# NOTE: I think we are moving away from these selectors
468-
# since we are doing floating noticications now.
469-
# "query_selector": "[role=main]",
470-
},
471-
"non_latest_version_warning": {
472-
"enabled": project.addons.stable_latest_version_warning_enabled,
473-
# NOTE: I think we are moving away from these selectors
474-
# since we are doing floating noticications now.
475-
# "query_selector": "[role=main]",
465+
"notifications": {
466+
"enabled": project.addons.notifications_enabled,
467+
"show_on_latest": project.addons.notifications_show_on_latest,
468+
"show_on_non_stable": project.addons.notifications_show_on_non_stable,
469+
"show_on_external": project.addons.notifications_show_on_external,
476470
},
477471
"flyout": {
478472
"enabled": project.addons.flyout_enabled,

readthedocs/rtd_tests/tests/test_project_forms.py

+15-9
Original file line numberDiff line numberDiff line change
@@ -1133,14 +1133,16 @@ def test_addonsconfig_form(self):
11331133
"enabled": True,
11341134
"analytics_enabled": False,
11351135
"doc_diff_enabled": False,
1136-
"external_version_warning_enabled": True,
11371136
"flyout_enabled": True,
11381137
"flyout_sorting": ADDONS_FLYOUT_SORTING_CALVER,
11391138
"flyout_sorting_latest_stable_at_beginning": True,
11401139
"flyout_sorting_custom_pattern": None,
11411140
"hotkeys_enabled": False,
11421141
"search_enabled": False,
1143-
"stable_latest_version_warning_enabled": True,
1142+
"notifications_enabled": True,
1143+
"notifications_show_on_latest": True,
1144+
"notifications_show_on_non_stable": True,
1145+
"notifications_show_on_external": True,
11441146
}
11451147
form = AddonsConfigForm(data=data, project=self.project)
11461148
self.assertTrue(form.is_valid())
@@ -1149,7 +1151,10 @@ def test_addonsconfig_form(self):
11491151
self.assertEqual(self.project.addons.enabled, True)
11501152
self.assertEqual(self.project.addons.analytics_enabled, False)
11511153
self.assertEqual(self.project.addons.doc_diff_enabled, False)
1152-
self.assertEqual(self.project.addons.external_version_warning_enabled, True)
1154+
self.assertEqual(self.project.addons.notifications_enabled, True)
1155+
self.assertEqual(self.project.addons.notifications_show_on_latest, True)
1156+
self.assertEqual(self.project.addons.notifications_show_on_non_stable, True)
1157+
self.assertEqual(self.project.addons.notifications_show_on_external, True)
11531158
self.assertEqual(self.project.addons.flyout_enabled, True)
11541159
self.assertEqual(
11551160
self.project.addons.flyout_sorting,
@@ -1162,24 +1167,25 @@ def test_addonsconfig_form(self):
11621167
self.assertEqual(self.project.addons.flyout_sorting_custom_pattern, None)
11631168
self.assertEqual(self.project.addons.hotkeys_enabled, False)
11641169
self.assertEqual(self.project.addons.search_enabled, False)
1165-
self.assertEqual(
1166-
self.project.addons.stable_latest_version_warning_enabled,
1167-
True,
1168-
)
1170+
self.assertEqual(self.project.addons.notifications_show_on_latest, True)
1171+
self.assertEqual(self.project.addons.notifications_show_on_non_stable, True)
1172+
self.assertEqual(self.project.addons.notifications_show_on_external, True)
11691173

11701174
def test_addonsconfig_form_invalid_sorting_custom_pattern(self):
11711175
data = {
11721176
"enabled": True,
11731177
"analytics_enabled": False,
11741178
"doc_diff_enabled": False,
1175-
"external_version_warning_enabled": True,
11761179
"flyout_enabled": True,
11771180
"flyout_sorting": ADDONS_FLYOUT_SORTING_CUSTOM_PATTERN,
11781181
"flyout_sorting_latest_stable_at_beginning": True,
11791182
"flyout_sorting_custom_pattern": None,
11801183
"hotkeys_enabled": False,
11811184
"search_enabled": False,
1182-
"stable_latest_version_warning_enabled": True,
1185+
"notifications_enabled": True,
1186+
"notifications_show_on_latest": True,
1187+
"notifications_show_on_non_stable": True,
1188+
"notifications_show_on_external": True,
11831189
}
11841190
form = AddonsConfigForm(data=data, project=self.project)
11851191
self.assertFalse(form.is_valid())

0 commit comments

Comments
 (0)