Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add admin page for site redirects #3502

Merged
merged 4 commits into from
Apr 19, 2024
Merged

Add admin page for site redirects #3502

merged 4 commits into from
Apr 19, 2024

Conversation

rakyi
Copy link
Contributor

@rakyi rakyi commented Apr 16, 2024

I got heavily inspired by RedirectsIndexPage.tsx. I used react-hook-form since I had good experience with it before, and it makes the form handling nice.

Server validation error leads to a generic error popup on the frontend, which is bad UX, but it seems this is what we do also elsewhere. Let me know if there is a good way to avoid that.

@rakyi rakyi requested a review from danyx23 April 16, 2024 13:39
"/site-redirects/new",
async (req: Request, res, trx) => {
const { source, target } = req.body
if (await redirectWithSourceExists(trx, source)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe make source unique in the DB?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that wouldn't hurt. Can you add a migration for it? For this we still use typeorm, the docs are in the /db folder in the readme.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@rakyi rakyi force-pushed the site-redirects-admin branch 3 times, most recently from 5310272 to 02bd8ba Compare April 17, 2024 08:16
@rakyi rakyi linked an issue Apr 17, 2024 that may be closed by this pull request
Copy link
Contributor

@danyx23 danyx23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work, @rakyi! Maybe I'll warm up to hooks after all :).

I have a few comments, mostly around explaining things a bit more to the user and being a bit more strict in the validation.

Comment on lines 49 to 66
`WITH RECURSIVE redirect_chain AS (
-- Base case: Start with the target of the proposed new redirect.
SELECT source, target
FROM redirects
WHERE source = ?

UNION ALL

-- Recursive step: Follow the chain of redirects.
SELECT r.source, r.target
FROM redirects r
INNER JOIN redirect_chain rc ON rc.target = r.source
)
-- Check if the new source appears in the redirect chain starting from
-- the new target.
SELECT COUNT(*) > 0 AS cycleExists
FROM redirect_chain
WHERE source = ? OR target = ?`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't word this carefully in the issue, but I think we want to be stricter which happens to also make this query easier: I think we want to avoid not only cycles but also any chains. If there is already a redirect for /B to /C, and we are about to add a redirect /A to /B then we should just fail and tell the user that there is already a redirect in place for /B to /C and they should just redirect from /A to /C directly.

Doing this then let's us do away with the recursive query (which is cool :) but a bit hard to grok) - instead we can just check if the source matches any existing target or the target matches any existing source.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworked the validation.

"/site-redirects/new",
async (req: Request, res, trx) => {
const { source, target } = req.body
if (await redirectWithSourceExists(trx, source)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that wouldn't hurt. Can you add a migration for it? For this we still use typeorm, the docs are in the /db folder in the readme.

import { AdminAppContext } from "./AdminAppContext.js"
import { AdminLayout } from "./AdminLayout.js"

const VALID_PATTERN = /^\/$|^.*[^\/]+$/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be stricter here and have a different pattern for source and target. Sources have to start with a slash. Targets have to start either with a slash or http://.

I think it is also nice to document regexps a bit more since they are so dense - I tried one form of this e.g. here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. I made the validation messages more specific, which should also serve as docs for the regexps. Let me know if you think it's not sufficient.

<main>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-row">
<div className="form-group col-12 col-md-4">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should explain to the admin users a bit what is expected of them here. Yes, our admin UIs are very barebones but our authors are not very versed in the technical details of HTTP redirects so we should explain a bit what is happening here.

I think it is important to tell them that source has to start with a slash and should not contain query params or fragments (you may also want to strip those if they are given). The target can contain full urls or relative urls starting with a slash and here both query params and fragments are allowed. Maybe give an example for query param and fragment in parens as it might not be obvious what these things are.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also worth calling out that to redirect to our homepage they should use a single slash as the target

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the instructions.

{...register("source", {
required: "Please provide a source.",
pattern: {
value: VALID_PATTERN,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to checking for a leading slash I think we should also either disallow query params/fragments via the regex or strip them out before sending the redirect to the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are now stripped on submit.

@rakyi rakyi requested a review from danyx23 April 19, 2024 10:19
@rakyi rakyi force-pushed the site-redirects-admin branch 2 times, most recently from 50043d2 to 24ea7ac Compare April 19, 2024 10:28
@rakyi rakyi force-pushed the site-redirects-admin branch from 24ea7ac to 762ab77 Compare April 19, 2024 13:10
@rakyi
Copy link
Contributor Author

rakyi commented Apr 19, 2024

@danyx23 do you have an idea why the refresh-etl job would be failing? Rebasing on master didn't help.

Copy link
Contributor

@danyx23 danyx23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thanks for the changes! I had some ideas for slight tweaks and thought it's better to just add them in a commit of my own. Feel free to tweak my styling ideas, I just felt that using concrete examples form our site works better than generic a=b examples. If you are happy with then please ship it! :)

@danyx23
Copy link
Contributor

danyx23 commented Apr 19, 2024

@rakyi No I don't know what is causing the ETL update to fail but it's not relevant for commits in this repo (it is only used when the grapher infrastructure is used as part of PRs in the ETL repository). I think it's good to ship!

@rakyi rakyi merged commit f669869 into master Apr 19, 2024
20 of 22 checks passed
@rakyi rakyi deleted the site-redirects-admin branch April 19, 2024 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add an admin tab for managing redirects
2 participants