From 2d57599b680b95aa0f2ef4645cfe7b405211d501 Mon Sep 17 00:00:00 2001 From: Celeo Date: Fri, 17 Aug 2018 16:23:31 -0700 Subject: [PATCH] Add an error page for non-existent groups Uses the pg_trgm extension (trigrams) to look up groups with similar names to the one that the user tried to visit and offers them as suggestions. --- salt/salt/postgresql/site-db.sls | 7 +++++ salt/salt/postgresql/test-db.sls | 7 +++++ .../templates/error_group_not_found.jinja2 | 27 +++++++++++++++++++ tildes/tildes/views/exceptions.py | 24 ++++++++++++++++- 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tildes/tildes/templates/error_group_not_found.jinja2 diff --git a/salt/salt/postgresql/site-db.sls b/salt/salt/postgresql/site-db.sls index 5f73a1e..91adefb 100644 --- a/salt/salt/postgresql/site-db.sls +++ b/salt/salt/postgresql/site-db.sls @@ -39,6 +39,13 @@ site-db-enable-pg_stat_statements: - require: - postgres_database: tildes +site-db-enable-pg_trgm: + postgres_extension.present: + - name: pg_trgm + - maintenance_db: tildes + - require: + - postgres_database: tildes + site-db-pg_hba-lines: file.accumulated: - name: pg_hba_lines diff --git a/salt/salt/postgresql/test-db.sls b/salt/salt/postgresql/test-db.sls index 813f73d..ad18163 100644 --- a/salt/salt/postgresql/test-db.sls +++ b/salt/salt/postgresql/test-db.sls @@ -26,6 +26,13 @@ test-db-enable-intarray: - require: - postgres_database: tildes_test +test-db-enable-pg_trgm: + postgres_extension.present: + - name: pg_trgm + - maintenance_db: tildes_test + - require: + - postgres_database: tildes_test + test-db-pg_hba-lines: file.accumulated: - name: pg_hba_lines diff --git a/tildes/tildes/templates/error_group_not_found.jinja2 b/tildes/tildes/templates/error_group_not_found.jinja2 new file mode 100644 index 0000000..ab14250 --- /dev/null +++ b/tildes/tildes/templates/error_group_not_found.jinja2 @@ -0,0 +1,27 @@ +{% extends 'base_no_sidebar.jinja2' %} + +{% from 'macros/links.jinja2' import group_linked %} + +{% block title %} +Group not found +{% endblock %} + +{% block content %} + +
+

No group named '{{ supplied_name }}'

+ {% if group_suggestions %} +

+ Did you mean one of these groups instead? +

+ {% for group in group_suggestions %} + {{ group_linked(group) }} +
+ {% endfor %} +

+ {% endif %} +

+ Browse the list of groups +
+ +{% endblock %} diff --git a/tildes/tildes/views/exceptions.py b/tildes/tildes/views/exceptions.py index fec2549..e598f6b 100644 --- a/tildes/tildes/views/exceptions.py +++ b/tildes/tildes/views/exceptions.py @@ -1,7 +1,11 @@ """Views used by Pyramid when an exception is raised.""" +from pyramid.httpexceptions import HTTPNotFound from pyramid.request import Request -from pyramid.view import forbidden_view_config +from pyramid.view import forbidden_view_config, exception_view_config +from sqlalchemy import cast, desc, func, Text + +from tildes.models.group import Group @forbidden_view_config(xhr=False, renderer="error_403.jinja2") @@ -9,3 +13,21 @@ def forbidden(request: Request) -> dict: """403 Forbidden page.""" request.response.status_int = 403 return {} + + +@exception_view_config( + HTTPNotFound, route_name="group", renderer="error_group_not_found.jinja2" +) +def group_not_found(request: Request) -> dict: + """Show the user a customized 404 page for group names.""" + request.response.status_int = 404 + supplied_name = request.matchdict.get("group_path") + # the 'word_similarity' function here is from the 'pg_trgm' extension + group_suggestions = ( + request.query(Group) + .filter(func.word_similarity(cast(Group.path, Text), supplied_name) > 0) + .order_by(desc(func.word_similarity(cast(Group.path, Text), supplied_name))) + .limit(3) + .all() + ) + return {"group_suggestions": group_suggestions, "supplied_name": supplied_name}