Redesign UI and fix several bugs

- Add navbar with login/logout, search form, and Find Link branding
- Clean up index page: search-only, examples behind ?debug=1
- Improve article page: remove debug clutter, named Wikipedia links, collapsible candidates
- Add SVG favicon (🔗 emoji)
- Fix diff CSS: compact layout, auto table layout to eliminate wide marker column gap
- Catch TokenRequestDenied in OAuth start and show error page
- Store username in session at login; clear bad session on API failure
- Raise NoMatch when diff is empty (edit already applied)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-05-11 11:30:12 +01:00
parent 7867122326
commit bc6265d4cd
11 changed files with 167 additions and 90 deletions

View file

@ -4,11 +4,13 @@ import html
import itertools
import json
import re
import sys
import typing
import flask
import werkzeug
from requests_oauthlib import OAuth1Session
from requests_oauthlib.oauth1_session import TokenRequestDenied
from werkzeug.wrappers.response import Response
from add_links import api, core, mediawiki_api, mediawiki_oauth
@ -118,17 +120,20 @@ def index() -> str | Response:
url = flask.url_for("oauth_callback", **flask.request.args) # type: ignore
return flask.redirect(url)
examples = load_examples()
examples.sort(
key=lambda i: float(i["with_links"]) / float(i["total"]), reverse=True
)
if q := flask.request.args.get("q"):
if q_trimmed := q.strip():
return flask.redirect(article_url(q_trimmed))
debug = flask.request.args.get("debug")
examples: list[dict[str, str | int]] = []
if debug:
examples = load_examples()
examples.sort(
key=lambda i: float(i["with_links"]) / float(i["total"]), reverse=True
)
return flask.render_template(
"index.html", examples=examples, article_url=article_url
"index.html", examples=examples, article_url=article_url, debug=debug
)
@ -187,7 +192,12 @@ def start_oauth() -> Response:
oauth = OAuth1Session(client_key, client_secret=client_secret, callback_uri="oob")
oauth.headers.update({"User-Agent": api.ua})
fetch_response = oauth.fetch_request_token(request_token_url)
try:
fetch_response = oauth.fetch_request_token(request_token_url)
except TokenRequestDenied as e:
return flask.make_response(
flask.render_template("error.html", message=str(e)), 502
)
flask.session["owner_key"] = fetch_response.get("oauth_token")
flask.session["owner_secret"] = fetch_response.get("oauth_token_secret")
@ -229,7 +239,8 @@ def oauth_callback() -> werkzeug.wrappers.response.Response:
flask.session["owner_key"] = oauth_tokens.get("oauth_token")
flask.session["owner_secret"] = oauth_tokens.get("oauth_token_secret")
print("login successful")
username = mediawiki_oauth.get_username()
print(f"login successful: {username}", file=sys.stderr)
next_page = flask.session.get("after_login")
return flask.redirect(next_page if next_page else flask.url_for("index"))