urls: Simplify process to add URL redirects for documentation pages.

Creates `zerver.lib.url_redirects.py` to record old and new URLs
for documentation pages that have been renamed/moved and need URL
redirects.

This file is then used by `zproject.urls.py` to redirect links and
by `zerver.test.test_urls.py` to test that all of the old URLs
return a success response with a common page header/text depending
on the type of redirect (help center, policy, or API).

Adds a section to contributor docs on writing documentation for
how to use this redirect system when renaming a help center or api
documentation page.

Fixes #21946. Fixes #17897.
This commit is contained in:
Lauryn Menard 2022-07-08 20:20:17 +02:00 committed by Tim Abbott
parent d21a1fe47f
commit 878b46e758
5 changed files with 140 additions and 102 deletions

View File

@ -112,6 +112,10 @@ existing help center articles:
of the article that again links to any help center documentation
mentioned in the text or related to the feature.
If your updates to the existing article will change the name of the
markdown file, then see section below on [redirecting an existing
article](#redirecting-an-existing-article).
Creating robust and informative help center articles with good links
will allow users to navigate the help center much more effectively.
@ -148,6 +152,57 @@ with modals, etc. should never go in the help center documentation.
In such cases, you may be able to fix the problem by adding text in-app,
where the user will see it as they are interacting with the feature.
### Redirecting an existing article
From time to time, we might want to rename an article in the help
center, or REST API documentation. This change will break incoming
links, including links in published Zulip blog posts, links in other
branches of the repository that haven't been rebased, and more
importantly links from previous versions of Zulip.
To fix these broken links, you can easily add a URL redirect in:
`zerver/lib/url_redirects.py`.
For help center documentation, once you've renamed the file in your
branch (e.g., `git mv path/to/foo.md path/to/bar.md`), go to
`url_redirects.py` and add a new `URLRedirect` to the
`HELP_DOCUMENTATION_REDIRECTS` list:
```python
HELP_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for help center documentation here:
URLRedirect("/help/foo", "/help/bar"),
...
```
Note that you will also need to add redirects when you're deleting
a help center article and adding its content to an existing article
as a section. In that case, the new URL will include the new section
header: `URLRedirect("/help/foo", "/help/bar#new-section-header"),`.
For REST API documentation, you will either need to rename the file
as above, or you will need to update the endpoint's `operationId` in
`zerver/openapi/zulip.yaml`. Then, you would add a new `URLRedirect`
to the `API_DOCUMENTATION_REDIRECTS` list in `url_redirects.py`.
You should still check for references to the old URL in your branch
and replace those with the new URL (e.g., `git grep "/help/foo"`).
Updating section headers in existing help center articles does not
require adding a URL redirect, but you will need to update any
existing links to that article's section in your branch.
If you have the Zulip development environment set up, you can manually
test your changes by loading the old URL in your browser (e.g.,
`http://localhost:9991/help/foo`), and confirming that it redirects to
the new url (e.g., `http://localhost:9991/help/bar`).
There is also an automated test in `zerver/tests/test_urls.py` that
checks all the URL redirects, which you can run from the command line:
```console
./tools/test-backend zerver.tests.test_urls.URLRedirectTest
```
## Writing style
Below are some general style and writing conventions that should be used

View File

@ -481,24 +481,7 @@ def write_instrumentation_reports(full_suite: bool, include_webhooks: bool) -> N
"confirmation_key/",
"node-coverage/(?P<path>.+)",
"docs/(?P<path>.+)",
"help/add-custom-emoji",
"help/configure-who-can-add-custom-emoji",
"help/change-the-topic-of-a-message",
"help/configure-missed-message-emails",
"help/community-topic-edits",
"help/about-streams-and-topics",
"help/delete-a-stream",
"help/add-an-alert-word",
"help/change-notification-sound",
"help/configure-message-notification-emails",
"help/disable-new-login-emails",
"help/test-mobile-notifications",
"help/troubleshooting-desktop-notifications",
"help/web-public-streams",
"for/working-groups-and-communities/",
"help/only-allow-admins-to-add-emoji",
"help/night-mode",
"api/delete-stream",
"casper/(?P<path>.+)",
"static/(?P<path>.+)",
"flush_caches",

View File

@ -0,0 +1,56 @@
from dataclasses import dataclass
from typing import List
@dataclass
class URLRedirect:
old_url: str
new_url: str
API_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for REST API documentation here:
URLRedirect("/api/delete-stream", "/api/archive-stream"),
]
POLICY_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for policy documentation here:
URLRedirect("/privacy/", "/policies/privacy"),
URLRedirect("/terms/", "/policies/terms"),
]
HELP_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for help center documentation here:
URLRedirect("/help/delete-a-stream", "/help/archive-a-stream"),
URLRedirect("/help/change-the-topic-of-a-message", "/help/rename-a-topic"),
URLRedirect("/help/configure-missed-message-emails", "/help/email-notifications"),
URLRedirect("/help/add-an-alert-word", "/help/pm-mention-alert-notifications#alert-words"),
URLRedirect("/help/test-mobile-notifications", "/help/mobile-notifications"),
URLRedirect(
"/help/troubleshooting-desktop-notifications",
"/help/desktop-notifications#troubleshooting-desktop-notifications",
),
URLRedirect(
"/help/change-notification-sound", "/help/desktop-notifications#change-notification-sound"
),
URLRedirect("/help/configure-message-notification-emails", "/help/email-notifications"),
URLRedirect("/help/disable-new-login-emails", "/help/email-notifications#new-login-emails"),
# The `help/about-streams-and-topics` redirect is particularly important,
# because the old URL appears in links from Welcome Bot messages.
URLRedirect("/help/about-streams-and-topics", "/help/streams-and-topics"),
URLRedirect("/help/community-topic-edits", "/help/configure-who-can-edit-topics"),
URLRedirect(
"/help/only-allow-admins-to-add-emoji", "/help/custom-emoji#change-who-can-add-custom-emoji"
),
URLRedirect(
"/help/configure-who-can-add-custom-emoji",
"/help/custom-emoji#change-who-can-add-custom-emoji",
),
URLRedirect("/help/add-custom-emoji", "/help/custom-emoji"),
URLRedirect("/help/night-mode", "/help/dark-theme"),
URLRedirect("/help/web-public-streams", "/help/public-access-option"),
]
DOCUMENTATION_REDIRECTS = (
API_DOCUMENTATION_REDIRECTS + POLICY_DOCUMENTATION_REDIRECTS + HELP_DOCUMENTATION_REDIRECTS
)

View File

@ -6,6 +6,11 @@ import django.urls.resolvers
from django.test import Client
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.url_redirects import (
API_DOCUMENTATION_REDIRECTS,
HELP_DOCUMENTATION_REDIRECTS,
POLICY_DOCUMENTATION_REDIRECTS,
)
from zerver.models import Realm, Stream
from zproject import urls
@ -154,3 +159,20 @@ class ErrorPageTest(ZulipTestCase):
"/json/users", secure=True, HTTP_REFERER="https://somewhere", HTTP_HOST="$nonsense"
)
self.assertEqual(result.status_code, 400)
class RedirectURLTest(ZulipTestCase):
def test_api_redirects(self) -> None:
for redirect in API_DOCUMENTATION_REDIRECTS:
result = self.client_get(redirect.old_url, follow=True)
self.assert_in_success_response(["Zulip homepage", "API documentation home"], result)
def test_help_redirects(self) -> None:
for redirect in HELP_DOCUMENTATION_REDIRECTS:
result = self.client_get(redirect.old_url, follow=True)
self.assert_in_success_response(["Zulip homepage", "Help center home"], result)
def test_policy_redirects(self) -> None:
for redirect in POLICY_DOCUMENTATION_REDIRECTS:
result = self.client_get(redirect.old_url, follow=True)
self.assert_in_success_response(["Policies", "Archive"], result)

View File

@ -18,6 +18,7 @@ from django.views.generic import RedirectView, TemplateView
from zerver.forms import LoggingSetPasswordForm
from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
from zerver.lib.rest import rest_path
from zerver.lib.url_redirects import DOCUMENTATION_REDIRECTS
from zerver.tornado.views import cleanup_event_queue, get_events, get_events_internal, notify
from zerver.views.alert_words import add_alert_words, list_alert_words, remove_alert_words
from zerver.views.attachments import list_by_user, remove
@ -780,98 +781,19 @@ policy_documentation_view = MarkdownDirectoryView.as_view(
template_name="zerver/documentation_main.html",
policies_view=True,
)
# Redirects due to us having moved help center, API or policy documentation pages:
for redirect in DOCUMENTATION_REDIRECTS:
old_url = redirect.old_url.lstrip("/")
urls += [path(old_url, RedirectView.as_view(url=redirect.new_url, permanent=True))]
urls += [
# Redirects due to us having moved the docs:
path(
"help/delete-a-stream", RedirectView.as_view(url="/help/archive-a-stream", permanent=True)
),
path("api/delete-stream", RedirectView.as_view(url="/api/archive-stream", permanent=True)),
path(
"help/change-the-topic-of-a-message",
RedirectView.as_view(url="/help/rename-a-topic", permanent=True),
),
path(
"help/configure-missed-message-emails",
RedirectView.as_view(url="/help/email-notifications", permanent=True),
),
path(
"help/add-an-alert-word",
RedirectView.as_view(
url="/help/pm-mention-alert-notifications#alert-words", permanent=True
),
),
path(
"help/test-mobile-notifications",
RedirectView.as_view(url="/help/mobile-notifications", permanent=True),
),
path(
"help/troubleshooting-desktop-notifications",
RedirectView.as_view(
url="/help/desktop-notifications#troubleshooting-desktop-notifications", permanent=True
),
),
path(
"help/change-notification-sound",
RedirectView.as_view(
url="/help/desktop-notifications#change-notification-sound", permanent=True
),
),
path(
"help/configure-message-notification-emails",
RedirectView.as_view(url="/help/email-notifications", permanent=True),
),
path(
"help/disable-new-login-emails",
RedirectView.as_view(url="/help/email-notifications#new-login-emails", permanent=True),
),
# This redirect is particularly important, because the old URL
# appears in links from Welcome Bot messages.
path(
"help/about-streams-and-topics",
RedirectView.as_view(url="/help/streams-and-topics", permanent=True),
),
path(
"help/community-topic-edits",
RedirectView.as_view(url="/help/configure-who-can-edit-topics", permanent=True),
),
path(
"help/only-allow-admins-to-add-emoji",
RedirectView.as_view(
url="/help/custom-emoji#change-who-can-add-custom-emoji", permanent=True
),
),
path(
"help/configure-who-can-add-custom-emoji",
RedirectView.as_view(
url="/help/custom-emoji#change-who-can-add-custom-emoji", permanent=True
),
),
path(
"help/add-custom-emoji",
RedirectView.as_view(url="/help/custom-emoji", permanent=True),
),
path(
"help/night-mode",
RedirectView.as_view(url="/help/dark-theme", permanent=True),
),
path(
"help/web-public-streams",
RedirectView.as_view(url="/help/public-access-option", permanent=True),
),
path("help/", help_documentation_view),
path("help/<path:article>", help_documentation_view),
path("api/", api_documentation_view),
path("api/<slug:article>", api_documentation_view),
path("policies/", policy_documentation_view),
path("policies/<slug:article>", policy_documentation_view),
path(
"privacy/",
RedirectView.as_view(url="/policies/privacy"),
),
path(
"terms/",
RedirectView.as_view(url="/policies/terms"),
),
]
# Two-factor URLs