mirror of
https://github.com/bugsink/bugsink.git
synced 2025-12-30 01:40:08 -06:00
Changes before error encountered
Co-authored-by: vanschelven <223833+vanschelven@users.noreply.github.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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
67
bugsink/test_subpath.py
Normal 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
|
||||
@@ -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 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 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 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 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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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> {% endif %}{{ issue.title|truncatechars:100 }}</a>
|
||||
|
||||
1
ith_prefix }}"|g
Normal file
1
ith_prefix }}"|g
Normal 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>
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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>
|
||||
|
||||
27
theme/templatetags/urls.py
Normal file
27
theme/templatetags/urls.py
Normal 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)
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user