Changes before error encountered

Co-authored-by: vanschelven <223833+vanschelven@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-09-05 09:22:59 +00:00
parent 3d07cf6480
commit 42bcd5d955
21 changed files with 170 additions and 37 deletions

View File

@@ -2,6 +2,7 @@
# alternative would be: just put "everything" in the big settings.py (or some mix-using-imports version of that).
# but for now I like the idea of keeping the bugsink-as-an-app stuff separate from the regular Django/db/global stuff.
import os
import urllib.parse
from contextlib import contextmanager
from django.conf import settings
@@ -110,6 +111,22 @@ def _sanitize(settings):
settings["TEAM_CREATION"] = CB_NOBODY
def get_path_prefix():
"""Extract the path prefix from BASE_URL for subpath hosting support."""
base_url = get_settings().BASE_URL
parsed_url = urllib.parse.urlparse(base_url)
path = parsed_url.path
# Ensure path starts with / and doesn't end with / (unless it's just "/")
if path and path != "/":
if not path.startswith("/"):
path = "/" + path
if path.endswith("/"):
path = path[:-1]
return path
return ""
def get_settings():
global _settings
if _settings is None:

View File

@@ -10,7 +10,7 @@ from django.contrib.auth.models import AnonymousUser
from django.db.utils import OperationalError
from django.db.models import Sum
from bugsink.app_settings import get_settings, CB_ANYBODY
from bugsink.app_settings import get_settings, CB_ANYBODY, get_path_prefix
from bugsink.transaction import durable_atomic
from bugsink.timed_sqlite_backend.base import different_runtime_limit
@@ -135,6 +135,7 @@ def useful_settings_processor(request):
'site_title': get_settings().SITE_TITLE,
'registration_enabled': get_settings().USER_REGISTRATION == CB_ANYBODY,
'app_settings': get_settings(),
'path_prefix': get_path_prefix(),
'system_warnings': get_system_warnings,
}

View File

@@ -343,3 +343,10 @@ if I_AM_RUNNING == "SNAPPEA":
for logger in LOGGING['loggers'].values():
if "handlers" in logger and "console" in logger["handlers"]:
logger["handlers"] = ["snappea"]
# Set FORCE_SCRIPT_NAME for subpath hosting support
# Import here to avoid circular dependency
from bugsink.app_settings import get_path_prefix
_path_prefix = get_path_prefix()
if _path_prefix:
FORCE_SCRIPT_NAME = _path_prefix

67
bugsink/test_subpath.py Normal file
View File

@@ -0,0 +1,67 @@
from django.test import TestCase, override_settings
from django.template import Template, Context
from bugsink.app_settings import get_path_prefix, override_settings as override_bugsink_settings
from bugsink.context_processors import useful_settings_processor
class SubpathHostingTestCase(TestCase):
"""Test subpath hosting functionality."""
def test_get_path_prefix_default(self):
"""Test that get_path_prefix returns empty string for default BASE_URL."""
with override_bugsink_settings(BASE_URL="http://localhost:8000"):
self.assertEqual(get_path_prefix(), "")
def test_get_path_prefix_subpath(self):
"""Test that get_path_prefix extracts path from BASE_URL."""
with override_bugsink_settings(BASE_URL="https://example.com/bugsink"):
self.assertEqual(get_path_prefix(), "/bugsink")
def test_get_path_prefix_subpath_with_trailing_slash(self):
"""Test that get_path_prefix handles trailing slash correctly."""
with override_bugsink_settings(BASE_URL="https://example.com/bugsink/"):
self.assertEqual(get_path_prefix(), "/bugsink")
def test_get_path_prefix_deeper_path(self):
"""Test that get_path_prefix handles deeper paths."""
with override_bugsink_settings(BASE_URL="https://example.com/tools/bugsink"):
self.assertEqual(get_path_prefix(), "/tools/bugsink")
def test_context_processor_includes_path_prefix(self):
"""Test that context processor includes path prefix."""
from django.http import HttpRequest
request = HttpRequest()
request.user = None # Mock an anonymous user
with override_bugsink_settings(BASE_URL="https://example.com/bugsink"):
context = useful_settings_processor(request)
self.assertEqual(context['path_prefix'], "/bugsink")
def test_template_filter_with_prefix(self):
"""Test the with_prefix template filter."""
template = Template('{% load urls %}{{ url | with_prefix }}')
with override_bugsink_settings(BASE_URL="https://example.com/bugsink"):
context = Context({'url': '/admin/'})
result = template.render(context)
self.assertEqual(result, "/bugsink/admin/")
def test_template_filter_without_prefix(self):
"""Test the with_prefix template filter with no prefix."""
template = Template('{% load urls %}{{ url | with_prefix }}')
with override_bugsink_settings(BASE_URL="http://localhost:8000"):
context = Context({'url': '/admin/'})
result = template.render(context)
self.assertEqual(result, "/admin/")
def test_template_filter_relative_url(self):
"""Test the with_prefix template filter with relative URLs."""
template = Template('{% load urls %}{{ url | with_prefix }}')
with override_bugsink_settings(BASE_URL="https://example.com/bugsink"):
context = Context({'url': 'admin/'})
result = template.render(context)
self.assertEqual(result, "admin/") # Should not add prefix to relative URLs

View File

@@ -5,6 +5,7 @@
{% load stricter_templates %}
{% load add_to_qs %}
{% load i18n %}
{% load urls %}
{% block title %}{{ issue.title }} · {{ block.super }}{% endblock %}
@@ -109,13 +110,13 @@
{# overflow-x-auto is needed at the level of the flex item such that it works at the level where we need it (the code listings)#}
<div class="ml-4 mb-4 mr-4 border-2 overflow-x-auto flex-[2_1_96rem]"><!-- the whole of the big tabbed view--> {# 96rem is 1536px, which matches the 2xl class; this is no "must" but eyeballing revealed: good result #}
<div class="flex bg-slate-50 dark:bg-slate-800 border-b-2"><!-- container for the actual tab buttons -->
<a href="/issues/issue/{{ issue.id }}/event/{% if event %}{{ event.id }}{% else %}last{% endif %}/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "stacktrace" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Stacktrace" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/event/{% if event %}{{ event.id }}{% else %}last{% endif %}/details/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "event-details" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Event&nbsp;Details" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/event/{% if event %}{{ event.id }}{% else %}last{% endif %}/breadcrumbs/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "breadcrumbs" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Breadcrumbs" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/events/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "event-list" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Event&nbsp;List" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/tags/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "tags" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Tags" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/grouping/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "grouping" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Grouping" %}</div></a>
<a href="/issues/issue/{{ issue.id }}/history/{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "history" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "History" %}</div></a>
<a href="{% with event_id=event.id|default:'last' %}{{ "/issues/issue/" | add:issue.id | add:"/event/" | add:event_id | add:"/" | with_prefix }}{% endwith %}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "stacktrace" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Stacktrace" %}</div></a>
<a href="{% with event_id=event.id|default:'last' %}{{ "/issues/issue/" | add:issue.id | add:"/event/" | add:event_id | add:"/details/" | with_prefix }}{% endwith %}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "event-details" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Event&nbsp;Details" %}</div></a>
<a href="{% with event_id=event.id|default:'last' %}{{ "/issues/issue/" | add:issue.id | add:"/event/" | add:event_id | add:"/breadcrumbs/" | with_prefix }}{% endwith %}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "breadcrumbs" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Breadcrumbs" %}</div></a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/events/" | with_prefix }}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "event-list" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Event&nbsp;List" %}</div></a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/tags/" | with_prefix }}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "tags" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Tags" %}</div></a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/grouping/" | with_prefix }}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "grouping" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "Grouping" %}</div></a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/history/" | with_prefix }}{% current_qs %}"><div class="p-4 font-bold hover:bg-slate-200 dark:hover:bg-slate-800 {% if tab == "history" %}text-cyan-500 dark:text-cyan-300 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">{% translate "History" %}</div></a>
</div>
<div class="m-4"><!-- div for tab_content -->
@@ -127,16 +128,16 @@
{% if is_event_page %}<div>{% blocktranslate with digest_order=event.digest_order|intcomma total_events=issue.digested_event_count|intcomma ingested_at=event.ingested_at|date:"j M G:i T" %}Event {{ digest_order }} of {{ total_events }} which occured at <span class="font-bold">{{ ingested_at }}</span>{% endblocktranslate %}</div>{% endif %}
<div class="ml-auto pr-4 font-bold text-slate-500 dark:text-slate-300">
{% if is_event_page %}
<a href="/events/event/{{ event.id }}/download/">{% translate "Download" %}</a>
| <a href="/events/event/{{ event.id }}/raw/" >{% translate "JSON" %}</a>
| <a href="/events/event/{{ event.id }}/plain/" >{% translate "Plain" %}</a>
<a href="{{ "/events/event/" | add:event.id | add:"/download/" | with_prefix }}">{% translate "Download" %}</a>
| <a href="{{ "/events/event/" | add:event.id | add:"/raw/" | with_prefix }}" >{% translate "JSON" %}</a>
| <a href="{{ "/events/event/" | add:event.id | add:"/plain/" | with_prefix }}" >{% translate "Plain" %}</a>
{% endif %}
{% if app_settings.USE_ADMIN and user.is_staff %}
{% if is_event_page %}
| <a href="/admin/events/event/{{ event.id }}/change/">{% translate "Event Admin" %}</a> |
| <a href="{{ "/admin/events/event/" | add:event.id | add:"/change/" | with_prefix }}">{% translate "Event Admin" %}</a> |
{% endif %}
<a href="/admin/issues/issue/{{ issue.id }}/change/">{% translate "Issue Admin" %}</a>
<a href="{{ "/admin/issues/issue/" | add:issue.id | add:"/change/" | with_prefix }}">{% translate "Issue Admin" %}</a>
{% endif %}
</div>

View File

@@ -3,6 +3,7 @@
{% load add_to_qs %}
{% load humanize %}
{% load add_to_qs %}
{% load urls %}
{% block tab_content %}
@@ -119,11 +120,11 @@ TODO
<tr class="border-slate-200 dark:border-slate-700 border-2 ">
<td class="p-4 font-bold text-slate-500 dark:text-slate-300 align-top">
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/{% current_qs %}">{{ event.digest_order }}</a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/event/" | add:event.id | add:"/" | with_prefix }}{% current_qs %}">{{ event.digest_order }}</a>
</td>
<td class="p-4 font-bold text-slate-500 dark:text-slate-300 align-top"> {# how useful is this really? #}
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/{% current_qs %}">{{ event.id|truncatechars:9 }}</a>
<a href="{{ "/issues/issue/" | add:issue.id | add:"/event/" | add:event.id | add:"/" | with_prefix }}{% current_qs %}">{{ event.id|truncatechars:9 }}</a>
</td>
<td class="p-4 font-mono whitespace-nowrap align-top">

View File

@@ -3,6 +3,7 @@
{% load humanize %}
{% load add_to_qs %}
{% load i18n %}
{% load urls %}
{% block title %}{% translate "Issues" %} · {{ project.name }} · {{ site_title }}{% endblock %}
@@ -170,7 +171,7 @@
</td>
<td class="w-full ml-0 pb-4 pt-4 pr-4">
<div>
<a href="/issues/issue/{{ issue.id }}/event/last/{% current_qs %}" class="text-cyan-500 dark:text-cyan-300 fill-cyan-500 font-bold {% if issue.is_resolved %}italic{% endif %}">{% if issue.is_resolved %}<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 inline"><path fill-rule="evenodd" d="M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z" clip-rule="evenodd" />
<a href="{{ "/issues/issue/" | add:issue.id | add:"/event/last/" | with_prefix }}{% current_qs %}" class="text-cyan-500 dark:text-cyan-300 fill-cyan-500 font-bold {% if issue.is_resolved %}italic{% endif %}">{% if issue.is_resolved %}<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 inline"><path fill-rule="evenodd" d="M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z" clip-rule="evenodd" />
</svg>{% endif %}{% if issue.is_muted %}<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 inline">
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 9.75 19.5 12m0 0 2.25 2.25M19.5 12l2.25-2.25M19.5 12l-2.25 2.25m-10.5-6 4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
</svg>&nbsp;&nbsp;{% endif %}{{ issue.title|truncatechars:100 }}</a>

1
ith_prefix }}"|g Normal file
View File

@@ -0,0 +1 @@
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>

View File

@@ -1,6 +1,7 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% load urls %}
{% block title %}{% translate "Projects" %} · {{ site_title }}{% endblock %}
@@ -64,7 +65,7 @@
<td class="w-full p-4">
<div>
{% if project.member or request.user.is_superuser %}
<a href="/issues/{{ project.id }}" class="text-xl text-cyan-500 dark:text-cyan-300 font-bold">{{ project.name }}</a>
<a href="{{ "/issues/" | add:project.id | with_prefix }}" class="text-xl text-cyan-500 dark:text-cyan-300 font-bold">{{ project.name }}</a>
{% else %}
<span class="text-xl text-slate-800 dark:text-slate-100 font-bold">{{ project.name }}</span>
{% endif %}

View File

@@ -1,4 +1,5 @@
{% extends "barest_base.html" %}
{% load urls %}
{% load static %}
{% load i18n %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -1,4 +1,5 @@
{% extends "barest_base.html" %}
{% load urls %}
{% load static %}
{% load tailwind_forms %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -1,4 +1,4 @@
{% load static tailwind_tags %}<!DOCTYPE html>{# copy of base.html, but without variables (and hence no menu), for use in contextless templates (e.g. 500.html) #}
{% load static tailwind_tags urls %}<!DOCTYPE html>{# copy of base.html, but without variables (and hence no menu), for use in contextless templates (e.g. 500.html) #}
<html lang="en" data-theme="system">
<head>
<title>{% block title %}Bugsink{% endblock %}</title>
@@ -26,8 +26,8 @@
<body class="dark:bg-slate-700 dark:text-slate-100">
<div id="content">
<div class="flex pl-4 bg-slate-200 dark:bg-slate-800">
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="p-2 h-12 w-12 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="p-2 h-12 w-12 hidden dark:block" alt="Bugsink logo"></a>
<a href="/"><div class="pt-4 pb-4 pl-2 pr-2 font-bold">Bugsink</div></a>
<a href="{{ "/" | with_prefix }}"><img src="{% static 'images/bugsink-logo.png' %}" class="p-2 h-12 w-12 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="p-2 h-12 w-12 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" | with_prefix }}"><div class="pt-4 pb-4 pl-2 pr-2 font-bold">Bugsink</div></a>
</div>
<div>
{% block content %}{% endblock %}

View File

@@ -1,4 +1,4 @@
{% load static tailwind_tags version add_to_qs %}{% load i18n %}<!DOCTYPE html>
{% load static tailwind_tags version add_to_qs urls %}{% load i18n %}<!DOCTYPE html>
<html lang="en" data-theme="{% if user.is_authenticated %}{{ user.theme_preference }}{% else %}dark{% endif %}">
<!-- version: {% version %} -->
<head>
@@ -27,8 +27,8 @@
<body class="dark:bg-slate-700 dark:text-slate-100">
<div id="content">
<div class="flex pl-4 bg-slate-200 dark:bg-slate-800">
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="p-2 h-12 w-12 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="p-2 h-12 w-12 hidden dark:block" alt="Bugsink logo"></a>
<a href="/"><div class="px-2 py-2 my-2 font-bold hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{{ site_title }}</div></a>
<a href="{{ "/" | with_prefix }}"><img src="{% static 'images/bugsink-logo.png' %}" class="p-2 h-12 w-12 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="p-2 h-12 w-12 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" | with_prefix }}"><div class="px-2 py-2 my-2 font-bold hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{{ site_title }}</div></a>
{% if not app_settings.SINGLE_TEAM %}
<a href="{% url "team_list" %}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Teams" %}</div></a>
@@ -42,18 +42,18 @@
<div class="ml-auto flex">
{% if app_settings.USE_ADMIN and user.is_staff %}
<a href="/admin/"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Admin" %}</div></a>
<a href="{{ "/admin/" | with_prefix }}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Admin" %}</div></a>
{% endif %}
{% if user.is_superuser %}
<a href="/users/"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Users" %}</div></a>
<a href="/bsmain/auth_tokens/"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Tokens" %}</div></a>
<a href="{{ "/users/" | with_prefix }}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Users" %}</div></a>
<a href="{{ "/bsmain/auth_tokens/" | with_prefix }}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Tokens" %}</div></a>
{% endif %}
{% if logged_in_user.is_anonymous %}
<a href="/accounts/login/"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Login" %}</div></a> {# I don't think this is actually ever shown in practice, because you must always be logged in #}
<a href="{{ "/accounts/login/" | with_prefix }}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Login" %}</div></a> {# I don't think this is actually ever shown in practice, because you must always be logged in #}
{% else %}
<a href="/accounts/preferences/"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Preferences" %}</div></a>
<a href="{{ "/accounts/preferences/" | with_prefix }}"><div class="px-4 py-2 my-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl">{% translate "Preferences" %}</div></a>
<div class="px-4 py-2 my-2 mr-2 hover:bg-slate-300 dark:hover:bg-slate-700 rounded-xl"><form id="logout-form" method="post" action="{% url 'logout' %}">{% csrf_token %}<button type="submit">{% translate "Log out" %}</button></form></div>
{% endif %}
</div>

View File

@@ -0,0 +1,27 @@
from django import template
from bugsink.app_settings import get_path_prefix
register = template.Library()
@register.filter
def with_prefix(url):
"""Add the path prefix to a URL for subpath hosting support."""
if not url:
return url
prefix = get_path_prefix()
if not prefix:
return url
# Handle absolute URLs that start with /
if url.startswith('/'):
return prefix + url
return url
@register.simple_tag
def prefixed_url(url):
"""Template tag version of the with_prefix filter."""
return with_prefix(url)

View File

@@ -1,4 +1,5 @@
{% extends "barest_base.html" %}
{% load urls %}
{% load static %}
{% load i18n %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -1,6 +1,7 @@
{% extends "barest_base.html" %}
{% load static %}
{% load i18n %}
{% load urls %}
{% block title %}Verification email sent · {{ site_title }}{% endblock %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" | with_prefix }}"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -1,6 +1,7 @@
{% extends "barest_base.html" %}
{% load static %}
{% load i18n %}
{% load urls %}
{% block title %}Logged out · {{ site_title }}{% endblock %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" | with_prefix }}"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -2,6 +2,7 @@
{% load static %}
{% load tailwind_forms %}
{% load i18n %}
{% load urls %}
{% block title %}Resend confirmation · {{ site_title }}{% endblock %}
@@ -10,7 +11,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -1,4 +1,5 @@
{% extends "barest_base.html" %}
{% load urls %}
{% load static %}
{% load tailwind_forms %}
{% load i18n %}
@@ -10,7 +11,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">

View File

@@ -2,6 +2,7 @@
{% load static %}
{% load tailwind_forms %}
{% load i18n %}
{% load urls %}
{% block title %}Reset password · {{ site_title }}{% endblock %}
@@ -10,7 +11,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" | with_prefix }}"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>

View File

@@ -1,6 +1,7 @@
{% extends "barest_base.html" %}
{% load static %}
{% load i18n %}
{% load urls %}
{% block title %}Password reset sent · {{ site_title }}{% endblock %}
@@ -9,7 +10,7 @@
<div class="bg-cyan-100 dark:bg-cyan-900 h-screen overflow-y-scroll flex items-center justify-center"> {# the cyan background #}
<div class="bg-white dark:bg-slate-900 lg:w-5/12 md:6/12 w-10/12"> {# the centered box #}
<div class="bg-slate-200 dark:bg-slate-800 absolute left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full p-4 md:p-8"> {# the logo #}
<a href="/"><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
<a href="{{ "/" ><img src="{% static 'images/bugsink-logo.png' %}" class="h-8 w-8 md:h-16 md:w-16 dark:hidden block" alt="Bugsink logo"><img src="{% static 'images/bugsink-logo-dark.png' %}" class="h-8 w-8 md:h-16 md:w-16 hidden dark:block" alt="Bugsink logo"></a>
</div>
<div class="p-12 md:pt-24 md:pl-24 md:pr-24 md:pb-16">