mirror of https://github.com/zulip/zulip.git
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:
parent
d21a1fe47f
commit
878b46e758
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue