├── myhpi ├── __init__.py ├── core │ ├── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── markdown │ │ ├── __init__.py │ │ ├── fields.py │ │ └── utils.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0008_remove_footer_column_4.py │ │ ├── 0013_translate_abbreviationexplanations.py │ │ ├── 0010_minutes_location.py │ │ ├── 0004_minuteslabel_color.py │ │ ├── 0009_alter_minuteslabel_slug.py │ │ ├── 0011_alter_taggedminutes_tag.py │ │ ├── 0012_abbreviationexplanation_locale_and_more.py │ │ ├── 0007_alter_footer_column_1_alter_footer_column_2_and_more.py │ │ ├── 0014_alter_abbreviationexplanation_locale_and_more.py │ │ ├── 0006_informationpage_attachments_minutes_attachments_and_more.py │ │ ├── 0005_redirectmenuitem.py │ │ ├── 0003_minutes_guests_alter_informationpage_body_and_more.py │ │ └── 0002_rootpage.py │ ├── templatetags │ │ ├── __init__.py │ │ ├── minutes_tags.py │ │ └── core_extras.py │ ├── admin.py │ ├── tests.py │ ├── urls.py │ ├── templates │ │ └── core │ │ │ ├── label.html │ │ │ ├── toc_button.html │ │ │ ├── text_array_widget.html │ │ │ ├── information_page.html │ │ │ ├── sidebar.html │ │ │ ├── minutes_list.html │ │ │ └── minutes.html │ ├── views.py │ ├── middleware.py │ ├── wagtail_hooks.py │ ├── utils.py │ ├── context.py │ ├── auth.py │ └── widgets.py ├── polls │ ├── __init__.py │ ├── views.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0005_remove_pollchoice_description.py │ │ ├── 0009_alter_poll_description.py │ │ ├── 0010_remove_pollchoice_page_delete_poll_delete_pollchoice.py │ │ ├── 0007_auto_20210612_1620.py │ │ ├── 0006_auto_20210612_1547.py │ │ ├── 0004_poll_participants.py │ │ ├── 0003_auto_20210612_1231.py │ │ ├── 0002_auto_20210612_1217.py │ │ ├── 0013_assign_translation_keys.py │ │ ├── 0008_polllist.py │ │ ├── 0012_alter_majorityvotechoice_options_and_more.py │ │ ├── 0001_initial.py │ │ └── 0014_enforce_translation_key_locale_unique.py │ ├── tests.py │ ├── wagtail_hooks.py │ ├── admin.py │ ├── templates │ │ └── polls │ │ │ ├── poll_list.html │ │ │ ├── majority_vote_poll.html │ │ │ ├── base_poll.html │ │ │ └── ranked_choice_poll.html │ ├── templatetags │ │ └── polls.py │ └── forms.py ├── tests │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ ├── test_metrics.py │ │ ├── test_widgets.py │ │ ├── test_redirect_menu_item.py │ │ ├── test_minute_lists.py │ │ ├── test_email_utils.py │ │ ├── test_search.py │ │ ├── utils.py │ │ ├── test_auth.py │ │ ├── test_page_creation.py │ │ ├── test_minutes.py │ │ ├── test_menu.py │ │ └── test_view_permissions.py │ ├── polls │ │ ├── __init__.py │ │ └── test_ranked_choice_localization.py │ ├── test_example.py │ ├── files │ │ └── test_image.jpg │ ├── settings.py │ └── test_markdown_extensions.py ├── search │ ├── __init__.py │ ├── templates │ │ └── search │ │ │ ├── search_field.html │ │ │ ├── search_result.html │ │ │ └── search.html │ ├── views.py │ └── templatetags │ │ └── search.py ├── tenca_django │ ├── migrations │ │ ├── __init__.py │ │ ├── 0002_alter_hashentry_options_delete_legacyadminurl.py │ │ └── 0001_initial.py │ ├── templatetags │ │ ├── __init__.py │ │ └── tenca_extras.py │ ├── __init__.py │ ├── apps.py │ ├── templates │ │ └── tenca_django │ │ │ ├── backend_error.html │ │ │ ├── report.html │ │ │ ├── action.html │ │ │ ├── delete_list.html │ │ │ ├── manage_subscription.html │ │ │ ├── dashboard.html │ │ │ └── manage_list.html │ ├── README.md │ ├── connection.py │ ├── wagtail_hooks.py │ ├── middleware.py │ ├── urls.py │ ├── tests.py │ ├── mixins.py │ ├── forms.py │ └── models.py ├── static │ ├── security.txt │ ├── js │ │ ├── utils.js │ │ ├── sidebar.js │ │ ├── search.js │ │ ├── admin │ │ │ ├── text_array_widget.js │ │ │ └── easymde_custom.js │ │ ├── print_processor.js │ │ └── myHPI.js │ ├── css │ │ ├── text_array_widget.css │ │ └── myHPI_admin.css │ ├── scss │ │ └── footer.scss │ └── img │ │ ├── favicon │ │ └── favicon.svg │ │ └── myHPI-Logo.svg ├── wsgi.py ├── templates │ ├── 404.html │ ├── 500.html │ ├── login.html │ ├── footer.html │ ├── nav_level.html │ └── 403.html └── urls.py ├── uwsgi.ini ├── .prettierrc ├── .github ├── dependabot.yml └── workflows │ ├── build-container.yml │ ├── codeql-analysis.yml │ └── tests.yml ├── entrypoint.sh ├── .devcontainer ├── setup.sh ├── Dockerfile └── devcontainer.json ├── manage.py ├── Dockerfile ├── .pre-commit-config.yaml ├── .env.example ├── pyproject.toml ├── .gitignore ├── README.md └── tools └── install_bootstrap.py /myhpi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/polls/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/polls/views.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/search/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/tests/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/markdown/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/tests/polls/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/polls/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/tenca_django/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/tenca_django/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /myhpi/core/admin.py: -------------------------------------------------------------------------------- 1 | # Register your models here. 2 | -------------------------------------------------------------------------------- /myhpi/core/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /myhpi/polls/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /myhpi/tests/test_example.py: -------------------------------------------------------------------------------- 1 | def test_example(): 2 | assert 1 + 1 == 2 3 | -------------------------------------------------------------------------------- /uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | socket=0.0.0.0:8000 3 | wsgi-file=/app/myhpi/wsgi.py 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "semi": false, 4 | "singleQuote": false 5 | } 6 | -------------------------------------------------------------------------------- /myhpi/tenca_django/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = "myhpi.tenca_django.apps.TencaDjangoConfig" 2 | -------------------------------------------------------------------------------- /myhpi/tests/files/test_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsr-de/myHPI/HEAD/myhpi/tests/files/test_image.jpg -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /myhpi/static/security.txt: -------------------------------------------------------------------------------- 1 | Contact: https://github.com/fsr-de/myHPI/security/advisories/new 2 | Expires: 2024-10-18T10:00:00.000Z 3 | Preferred-Languages: en,de 4 | -------------------------------------------------------------------------------- /myhpi/core/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from myhpi.core.views import metrics_view 4 | 5 | urlpatterns = [path("metrics", metrics_view, name="prometheus-django-metrics")] 6 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python manage.py migrate 4 | python manage.py compilestatic 5 | python manage.py collectstatic --no-input 6 | python manage.py compilemessages 7 | 8 | exec "$@" 9 | -------------------------------------------------------------------------------- /myhpi/wsgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django.core.wsgi import get_wsgi_application 4 | 5 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myhpi.settings") 6 | 7 | application = get_wsgi_application() 8 | -------------------------------------------------------------------------------- /myhpi/tenca_django/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | from django.utils.translation import gettext_lazy as _ 3 | 4 | 5 | class TencaDjangoConfig(AppConfig): 6 | name = "myhpi.tenca_django" 7 | verbose_name = _("Mailing Lists") 8 | -------------------------------------------------------------------------------- /myhpi/core/templates/core/label.html: -------------------------------------------------------------------------------- 1 | {% if minutes.labels.all %} 2 | {% for label in minutes.labels.all %} 3 | {{ label }} 4 | {% endfor %} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /myhpi/tests/settings.py: -------------------------------------------------------------------------------- 1 | from myhpi.settings import * # NOQA, otherwise it will be removed by autoflake in the pre-commit hook 2 | 3 | STATICFILES_STORAGE = "django.contrib.staticfiles.storage.StaticFilesStorage" 4 | METRICS_API_KEY = "TEST_KEY" 5 | LANGUAGE_CODE = "en" 6 | -------------------------------------------------------------------------------- /myhpi/polls/wagtail_hooks.py: -------------------------------------------------------------------------------- 1 | from wagtail import hooks 2 | 3 | from myhpi.polls.models import BasePoll, PollList 4 | 5 | 6 | @hooks.register("before_serve_page") 7 | def check_view_permissions(page, request, serve_args, serve_kwargs): 8 | if isinstance(page, (PollList, BasePoll)): 9 | page.specific.check_can_view(request) 10 | -------------------------------------------------------------------------------- /myhpi/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load i18n %} 3 | 4 | {% block body_class %}template-404{% endblock %} 5 | 6 | {% block content %} 7 |
10 | {% translate "The page you requested does not exist. Please check the URL or use the menu above to find your page." %} 11 |
12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /myhpi/tenca_django/templates/tenca_django/backend_error.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %} 5 | {% trans "Mailing Lists Unavailable" %} 6 | {% endblock %} 7 | 8 | {% block content %} 9 |10 | {% trans "Sorry for the inconvenience, but the mail server backend does not reply. Please try again later." %} 11 |
12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /myhpi/polls/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from myhpi.polls.models import ( 4 | RankedChoiceBallot, 5 | RankedChoiceBallotEntry, 6 | RankedChoiceOption, 7 | RankedChoicePoll, 8 | ) 9 | 10 | admin.site.register(RankedChoiceBallot) 11 | admin.site.register(RankedChoiceBallotEntry) 12 | admin.site.register(RankedChoiceOption) 13 | admin.site.register(RankedChoicePoll) 14 | -------------------------------------------------------------------------------- /myhpi/static/js/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts a given rem value into pixel. 3 | * 4 | * @param {number} rem Rem value to convert. 5 | * @returns Number of pixel the given rem value corresponds to. 6 | * 7 | * Source: https://stackoverflow.com/questions/36532307/rem-px-in-javascript 8 | */ 9 | function remToPx(rem) { 10 | return rem * parseFloat(getComputedStyle(document.documentElement).fontSize) 11 | } 12 | -------------------------------------------------------------------------------- /.devcontainer/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python -m venv env 3 | source env/bin/activate 4 | poetry install 5 | if python tools/install_bootstrap.py --is-installed; then 6 | echo "Bootstrap is already installed." 7 | else 8 | python tools/install_bootstrap.py 9 | fi 10 | 11 | if [ ! -f .env ]; then 12 | cp .env.example .env 13 | fi 14 | 15 | python manage.py migrate 16 | python manage.py compilemessages 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | if "test" in sys.argv: 7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myhpi.tests.settings") 8 | else: 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myhpi.settings") 10 | 11 | from django.core.management import execute_from_command_line 12 | 13 | execute_from_command_line(sys.argv) 14 | -------------------------------------------------------------------------------- /myhpi/polls/migrations/0005_remove_pollchoice_description.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.8 on 2021-06-12 13:06 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("polls", "0004_poll_participants"), 9 | ] 10 | 11 | operations = [ 12 | migrations.RemoveField( 13 | model_name="pollchoice", 14 | name="description", 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /myhpi/core/migrations/0008_remove_footer_column_4.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.7 on 2023-08-15 19:35 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("core", "0007_alter_footer_column_1_alter_footer_column_2_and_more"), 9 | ] 10 | 11 | operations = [ 12 | migrations.RemoveField( 13 | model_name="footer", 14 | name="column_4", 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /myhpi/core/migrations/0013_translate_abbreviationexplanations.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.8 on 2024-11-22 14:42 2 | 3 | from django.db import migrations 4 | from wagtail.models import BootstrapTranslatableModel 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("core", "0012_abbreviationexplanation_locale_and_more"), 11 | ] 12 | 13 | operations = [ 14 | BootstrapTranslatableModel("core.AbbreviationExplanation"), 15 | ] 16 | -------------------------------------------------------------------------------- /myhpi/tenca_django/templatetags/tenca_extras.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def fqdn_ize(list_id): 8 | # template tags are loaded on django start-up, before a connection can be made 9 | from myhpi.tenca_django.connection import connection 10 | 11 | return connection.fqdn_ize(list_id) 12 | 13 | 14 | @register.filter(name="addcss") 15 | def addcss(field, css): 16 | return field.as_widget(attrs={"class": css}) 17 | -------------------------------------------------------------------------------- /myhpi/core/migrations/0010_minutes_location.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.9 on 2024-01-27 21:59 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("core", "0009_alter_minuteslabel_slug"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="minutes", 14 | name="location", 15 | field=models.CharField(blank=True, max_length=255), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /myhpi/templates/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |19 | {% trans "Sorry for this inconvenience. Please contact the Student Representative Group if this should happen more often." %} 20 |
21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /myhpi/tenca_django/migrations/0002_alter_hashentry_options_delete_legacyadminurl.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.7 on 2022-09-15 19:17 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("tenca_django", "0001_initial"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterModelOptions( 13 | name="hashentry", 14 | options={ 15 | "verbose_name": "Mailing List Hash Entry", 16 | "verbose_name_plural": "Mailing List Hash Entries", 17 | }, 18 | ), 19 | migrations.DeleteModel( 20 | name="LegacyAdminURL", 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /myhpi/tenca_django/connection.py: -------------------------------------------------------------------------------- 1 | import urllib.error 2 | 3 | import tenca.connection 4 | from django.core.exceptions import ImproperlyConfigured 5 | from mailmanclient.restbase.connection import MailmanConnectionError 6 | 7 | 8 | class FakeConnection: 9 | def __init__(self, exception): 10 | self.exception = exception 11 | 12 | def __getattr__(self, name): 13 | raise self.exception 14 | 15 | 16 | try: 17 | connection = tenca.connection.Connection() 18 | except (MailmanConnectionError, AttributeError) as e: 19 | connection = FakeConnection(ImproperlyConfigured(*e.args)) 20 | except urllib.error.HTTPError as e: 21 | connection = FakeConnection(ImproperlyConfigured(str(e))) 22 | -------------------------------------------------------------------------------- /myhpi/tenca_django/templates/tenca_django/action.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %} 5 | {% trans "Adjust Mailing List Subscription" %} 6 | {% endblock %} 7 | 8 | {% block breadcrumbs %} 9 | {% if request.user.is_authenticated %} 10 |19 | {% trans "This link is now invalid. You never need to visit it again." %} 20 |
21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /myhpi/core/migrations/0011_alter_taggedminutes_tag.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.9 on 2024-02-19 00:10 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ("core", "0010_minutes_location"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="taggedminutes", 15 | name="tag", 16 | field=models.ForeignKey( 17 | on_delete=django.db.models.deletion.CASCADE, 18 | related_name="%(app_label)s_%(class)s_items", 19 | to="core.minuteslabel", 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /myhpi/polls/migrations/0004_poll_participants.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.8 on 2021-06-12 11:28 2 | 3 | import modelcluster.fields 4 | from django.conf import settings 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 11 | ("polls", "0003_auto_20210612_1231"), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name="poll", 17 | name="participants", 18 | field=modelcluster.fields.ParentalManyToManyField( 19 | related_name="polls", to=settings.AUTH_USER_MODEL 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /myhpi/tenca_django/wagtail_hooks.py: -------------------------------------------------------------------------------- 1 | from django.utils.translation import gettext_lazy as _ 2 | from wagtail.admin.panels import FieldPanel, MultiFieldPanel 3 | from wagtail.snippets.models import register_snippet 4 | from wagtail.snippets.views.snippets import SnippetViewSet 5 | 6 | from myhpi.tenca_django.models import HashEntry 7 | 8 | 9 | class HashEntryFilterSet(SnippetViewSet): 10 | model = HashEntry 11 | add_to_admin_menu = True 12 | menu_label = _("Mailing Lists") 13 | menu_icon = "mail" 14 | list_display = ("list_id", "hash_id", "manage_page") 15 | 16 | edit_handler = MultiFieldPanel( 17 | [ 18 | FieldPanel("list_id", read_only=True), 19 | FieldPanel("hash_id"), 20 | ] 21 | ) 22 | 23 | 24 | register_snippet(HashEntryFilterSet) 25 | -------------------------------------------------------------------------------- /myhpi/polls/migrations/0003_auto_20210612_1231.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.8 on 2021-06-12 10:31 2 | 3 | import django.utils.timezone 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ("polls", "0002_auto_20210612_1217"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="poll", 15 | name="end_date", 16 | field=models.DateField(default=django.utils.timezone.now), 17 | preserve_default=False, 18 | ), 19 | migrations.AddField( 20 | model_name="poll", 21 | name="start_date", 22 | field=models.DateField(default=django.utils.timezone.now), 23 | preserve_default=False, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /myhpi/tenca_django/middleware.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from django.shortcuts import render 4 | 5 | from myhpi.tenca_django.connection import MailmanConnectionError 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | class TencaNoConnectionMiddleware: 11 | def __init__(self, get_response): 12 | self.get_response = get_response 13 | 14 | def __call__(self, request): 15 | return self.get_response(request) 16 | 17 | def process_exception(self, request, exception): 18 | if isinstance(exception, MailmanConnectionError): 19 | logger.error( 20 | "An exception occurred when connecting to mailman: " 21 | + " ".join(map(str, exception.args)) 22 | ) 23 | return render(request, "tenca_django/backend_error.html") 24 | else: 25 | return None 26 | -------------------------------------------------------------------------------- /myhpi/static/js/sidebar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sidebar script. Contains: 3 | * 4 | * - Hiding table of contents offcanvas on anchor click 5 | * 6 | */ 7 | 8 | /** 9 | * Initialization 10 | */ 11 | 12 | /** 13 | * Applies necessary JS handlers to sidebar. 14 | * Call when sidebar HTML was loaded. Call handler only once per page. 15 | */ 16 | const initializeSidebar = () => { 17 | applyTocOffcanvasBehaviour() 18 | } 19 | 20 | /** 21 | * Hide ToC offcanvas on anchor click ----------------------------------------------- 22 | */ 23 | 24 | const applyTocOffcanvasBehaviour = () => { 25 | const anchors = document.querySelectorAll("#sidebar-offcanvas a") 26 | const offcanvas = new bootstrap.Offcanvas( 27 | document.querySelector("#sidebar-offcanvas"), 28 | ) 29 | anchors.forEach((anchor) => 30 | anchor.addEventListener("click", () => offcanvas.hide()), 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /myhpi/search/templates/search/search_result.html: -------------------------------------------------------------------------------- 1 | {% load static wagtailcore_tags %} 2 | {% load bootstrap_icons %} 3 | {% load search %} 4 | 5 | 6 || {% translate "Title" %} | 13 |{% translate "Voting period" %} | 14 |
|---|---|
| 20 | {{ poll.title }} 21 | | 22 |{{ poll.start_date }} - {{ poll.end_date }} | 23 |
{% translate "Current user:" %} {{ user.email }}
10 | 14 | {% else %} 15 | {% if 'next' in request.GET and not request.GET.user_initiated %} 16 |15 | {% translate "Unfortunately you are not allowed to view this page. This might have one of the following reasons:" %} 16 |
17 | 18 |29 | {% blocktrans trimmed %} 30 | Are you sure you want to delete the list {{ listname }}? 31 | {% endblocktrans %} 32 |
33 | 43 |32 | {% blocktrans trimmed %} 33 | Enter the e-mail address you want to un-/subscribe from/to {{ list_name }}: 34 | {% endblocktrans %} 35 |
36 | 37 | 55 || {% trans "Choice" %} | 30 | {% if has_choice_descriptions %} 31 |{% trans "Description" %} | 32 | {% endif %} 33 |{% trans "Votes" %} | 34 |{% trans "Percentage" %} | 35 |
|---|---|---|---|
| {{ localized_choice.text }} | 40 | {% if has_choice_descriptions %} 41 |{{ localized_choice.description|default_if_none:"" }} | 42 | {% endif %} 43 |{{ choice.votes }} | 44 |{{ choice.percentage }}% | 45 |
21 | {% translate "You've accessed this page outside of the voting period." %} 22 |
23 | {% else %} 24 |25 | {% translate "You are not allowed to cast (another) vote and the results are not visible yet." %} 26 |
27 | {% endif %} 28 || {% translate "Rank" %} | 44 |{% translate "Choice" %} | 45 |{% translate "Final Votes" %} | 46 |
|---|---|---|
| {{ choice.0 }} | 52 |{{ choice.1 }} | 53 |{{ choice.2 }} | 54 |