diff --git a/pyproject.toml b/pyproject.toml
index a7eb586..a1d165d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,7 +44,7 @@ dev-dependencies = [
[tool.pytest.ini_options]
-DJANGO_SETTINGS_MODULE="tests.settings"
+DJANGO_SETTINGS_MODULE="project.settings"
addopts = "--reuse-db"
norecursedirs = "build dist docs .eggs/* *.egg-info htmlcov .git"
python_files = "test*.py"
diff --git a/src/membership/admin.py b/src/membership/admin.py
index 7cea5a6..c8b77c7 100644
--- a/src/membership/admin.py
+++ b/src/membership/admin.py
@@ -14,6 +14,9 @@ from django.db import transaction
from django.db.models import QuerySet
from django.http import HttpRequest
from django.http import HttpResponse
+from django.shortcuts import render
+from django.urls import path
+from django.urls.resolvers import URLPattern
from django.utils.text import slugify
from .emails import InviteEmail
@@ -150,9 +153,43 @@ class MemberAdmin(UserAdmin):
class WaitingListEntryAdmin(admin.ModelAdmin):
"""Admin for WaitingList model."""
- list_display = ("email", "member")
+ list_display = ("email", "name", "geography", "created", "wants_introduction", "member")
+ list_filter = ("wants_introduction", "created", "geography")
+ search_fields = ("email", "name", "comment", "geography")
+ readonly_fields = ("created", "modified")
actions = ("create_member",)
+ def get_urls(self) -> list[URLPattern]:
+ """Add custom URLs to the admin."""
+ urls = super().get_urls()
+ custom_urls = [
+ path(
+ "statistics/",
+ self.admin_site.admin_view(self.application_statistics_view),
+ name="membership_waitinglistentry_statistics",
+ ),
+ ]
+ return custom_urls + urls
+
+ def application_statistics_view(self, request: HttpRequest) -> HttpResponse:
+ """View to display application statistics."""
+ applications_by_month = WaitingListEntry.get_applications_by_month()
+
+ context = {
+ **self.admin_site.each_context(request),
+ "title": "Application Statistics",
+ "applications_by_month": applications_by_month,
+ "opts": self.model._meta, # noqa: SLF001
+ }
+
+ return render(request, "admin/membership/waitinglistentry/statistics.html", context)
+
+ def changelist_view(self, request: HttpRequest, extra_context: dict | None = None) -> HttpResponse:
+ """Add a link to the statistics view."""
+ extra_context = extra_context or {}
+ extra_context["show_statistics_link"] = True
+ return super().changelist_view(request, extra_context)
+
@admin.action(description="Create member account for entries")
def create_member(self, request: HttpRequest, queryset: QuerySet[WaitingListEntry]) -> None:
"""Create a user account for this entry.
diff --git a/src/membership/forms.py b/src/membership/forms.py
index 9df7b9e..2dd92f0 100644
--- a/src/membership/forms.py
+++ b/src/membership/forms.py
@@ -1,10 +1,23 @@
"""Form for the membership app."""
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
from allauth.account.adapter import get_adapter as get_allauth_adapter
from allauth.account.forms import SetPasswordForm
from django import forms
from django.utils.translation import gettext_lazy as _
+from .models import MembershipType
+from .models import WaitingListEntry
+
+if TYPE_CHECKING:
+ from typing import Any
+ from typing import ClassVar
+
+ from django_stubs_ext import StrOrPromise
+
class InviteForm(SetPasswordForm):
"""Create a new password for a user account that is created through an invite."""
@@ -39,3 +52,63 @@ class InviteForm(SetPasswordForm):
self.user.is_active = True
self.user.save()
super().save()
+
+
+class MemberApplicationForm(forms.ModelForm):
+ """Form for applying for membership."""
+
+ accepted_aup = forms.BooleanField(
+ label=_("I have read and accepted the Acceptable Usage Policy."),
+ required=False,
+ )
+ has_read_bylaws = forms.BooleanField(
+ label=_("I have read the bylaws."),
+ required=False,
+ )
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # noqa: ANN401
+ super().__init__(*args, **kwargs)
+ # To evaluate the queryset before the form is rendered, we need to set the choices here.
+ # Otherwise, django-zen-queries will complain about queries in the template.
+ self.fields["membership_type"].choices = MembershipType.objects.filter(active=True).values_list("id", "name")
+
+ class Meta:
+ model = WaitingListEntry
+ fields: ClassVar[list[str]] = [
+ "name",
+ "email",
+ "username",
+ "geography",
+ "membership_type",
+ "comment",
+ "wants_introduction",
+ "accepted_aup",
+ "has_read_bylaws",
+ ]
+ labels: ClassVar[dict[str, StrOrPromise]] = {
+ "username": _("Your preferred username"),
+ "comment": _("Tell us about yourself"),
+ "geography": _("Location"),
+ "membership_type": _("Membership Type"),
+ "wants_introduction": _("I would like an introduction to the association."),
+ "accepted_aup": _("I have read and accepted the Acceptable Usage Policy."),
+ "has_read_bylaws": _("I have read the bylaws."),
+ }
+ help_texts: ClassVar[dict[str, StrOrPromise]] = {
+ "username": _("The username you would like to use."),
+ "membership_type": _("Please select the membership type you are applying for."),
+ "comment": _("Please provide a brief description about yourself and why you want to join."),
+ "geography": _("Where are you located? This helps us organize local events."),
+ }
+ widgets: ClassVar[dict[str, forms.Widget]] = {
+ "comment": forms.Textarea(attrs={"rows": 4}),
+ }
+
+ def clean(self) -> dict[str, str]:
+ """Check that the user has read the bylaws."""
+ cleaned_data = super().clean()
+ if not cleaned_data.get("has_read_bylaws"):
+ self.add_error("has_read_bylaws", _("You must read the bylaws before applying."))
+ if not cleaned_data.get("accepted_aup"):
+ self.add_error("accepted_aup", _("You must accept the AUP before applying."))
+ return cleaned_data
diff --git a/src/membership/migrations/0015_waitinglistentry_membership_type_and_more.py b/src/membership/migrations/0015_waitinglistentry_membership_type_and_more.py
new file mode 100644
index 0000000..6c9f567
--- /dev/null
+++ b/src/membership/migrations/0015_waitinglistentry_membership_type_and_more.py
@@ -0,0 +1,47 @@
+# Generated by Django 5.1.4 on 2025-03-08 22:04
+
+import django.db.models.deletion
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("membership", "0014_alter_membership_options"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="waitinglistentry",
+ name="membership_type",
+ field=models.ForeignKey(
+ default=1,
+ help_text="The membership type the person wants to apply for.",
+ limit_choices_to=models.Q(("active", True)),
+ on_delete=django.db.models.deletion.PROTECT,
+ to="membership.membershiptype",
+ verbose_name="membership type",
+ ),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name="waitinglistentry",
+ name="name",
+ field=models.CharField(default="", max_length=255, verbose_name="navn"),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name="waitinglistentry",
+ name="username",
+ field=models.CharField(blank=True, default="", max_length=150, verbose_name="brugernavn"),
+ ),
+ migrations.AddField(
+ model_name="waitinglistentry",
+ name="wants_introduction",
+ field=models.BooleanField(
+ default=False,
+ help_text="Whether the person wants an introduction to the association.",
+ verbose_name="wants introduction",
+ ),
+ ),
+ ]
diff --git a/src/membership/models.py b/src/membership/models.py
index 5180c1d..188d068 100644
--- a/src/membership/models.py
+++ b/src/membership/models.py
@@ -241,9 +241,23 @@ class MembershipType(CreatedModifiedAbstract):
class WaitingListEntry(CreatedModifiedAbstract):
"""People who for some reason could want to be added to a waiting list and invited to join later."""
+ name = models.CharField(verbose_name=_("name"), max_length=255)
email = models.EmailField()
+ username = models.CharField(verbose_name=_("username"), max_length=150, blank=True, default="")
geography = models.CharField(verbose_name=_("geography"), blank=True, default="")
comment = models.TextField(blank=True)
+ wants_introduction = models.BooleanField(
+ verbose_name=_("wants introduction"),
+ default=False,
+ help_text=_("Whether the person wants an introduction to the association."),
+ )
+ membership_type = models.ForeignKey(
+ MembershipType,
+ verbose_name=_("membership type"),
+ help_text=_("The membership type the person wants to apply for."),
+ on_delete=models.PROTECT,
+ limit_choices_to=models.Q(active=True),
+ )
member = models.ForeignKey(
Member,
null=True,
@@ -256,6 +270,20 @@ class WaitingListEntry(CreatedModifiedAbstract):
def __str__(self) -> str:
return self.email
+ @classmethod
+ def get_applications_by_month(cls) -> dict[str, int]:
+ """Return a dictionary with the number of applications by month."""
+ from django.db.models import Count
+ from django.db.models.functions import TruncMonth
+
+ return dict(
+ cls.objects.annotate(month=TruncMonth("created"))
+ .values("month")
+ .annotate(count=Count("id"))
+ .order_by("-month")
+ .values_list("month", "count")
+ )
+
class Meta:
verbose_name = _("waiting list entry")
verbose_name_plural = _("waiting list entries")
diff --git a/src/membership/templates/admin/membership/waitinglistentry/change_list.html b/src/membership/templates/admin/membership/waitinglistentry/change_list.html
new file mode 100644
index 0000000..6354cd3
--- /dev/null
+++ b/src/membership/templates/admin/membership/waitinglistentry/change_list.html
@@ -0,0 +1,13 @@
+{% extends "admin/change_list.html" %}
+{% load i18n admin_urls %}
+
+{% block object-tools-items %}
+ {% if show_statistics_link %}
+
+
+ {% trans "Application Statistics" %}
+
+
+ {% endif %}
+ {{ block.super }}
+{% endblock %}
diff --git a/src/membership/templates/admin/membership/waitinglistentry/statistics.html b/src/membership/templates/admin/membership/waitinglistentry/statistics.html
new file mode 100644
index 0000000..15fa34c
--- /dev/null
+++ b/src/membership/templates/admin/membership/waitinglistentry/statistics.html
@@ -0,0 +1,36 @@
+{% extends "admin/base_site.html" %}
+{% load i18n admin_urls %}
+
+{% block content %}
+
+
+
+
{% trans "Applications by Month" %}
+
+ {% if applications_by_month %}
+
+
+
+ {% trans "Month" %} |
+ {% trans "Number of Applications" %} |
+
+
+
+ {% for month, count in applications_by_month.items %}
+
+ {{ month|date:"F Y" }} |
+ {{ count }} |
+
+ {% endfor %}
+
+
+ {% else %}
+
{% trans "No applications found." %}
+ {% endif %}
+
+
+
+
+{% endblock %}
diff --git a/src/membership/templates/membership/apply.html b/src/membership/templates/membership/apply.html
new file mode 100644
index 0000000..f2860a0
--- /dev/null
+++ b/src/membership/templates/membership/apply.html
@@ -0,0 +1,135 @@
+{% extends "account/pre_login_base.html" %}
+{% load i18n %}
+
+{% block head_title %}
+ {% trans "Apply for Membership" %}
+{% endblock %}
+
+{% block non_login_content %}
+
+
+
+

+
+
{% trans "About data.coop" %}
+
{% trans "We are a cooperative association dedicated to helping members manage data ethically and securely." %}
+
+ {% blocktrans trimmed %}
+ Read more about becoming a member on
+ our main website.
+ {% endblocktrans %}
+
+
+
+
+{% endblock %}
diff --git a/src/membership/views.py b/src/membership/views.py
index 504de80..a707504 100644
--- a/src/membership/views.py
+++ b/src/membership/views.py
@@ -17,6 +17,7 @@ from utils.view_utils import RowAction
from utils.view_utils import render
from .forms import InviteForm
+from .forms import MemberApplicationForm
from .models import Membership
from .permissions import ADMINISTRATE_MEMBERS
from .selectors import get_member
@@ -168,3 +169,29 @@ def invite(request: HttpRequest, referral_code: str, token: str) -> HttpResponse
template_name="membership/invite.html",
context=context,
)
+
+
+@member_view(
+ paths="apply/",
+ name="apply",
+ login_required=False,
+)
+def apply_for_membership(request: HttpRequest) -> HttpResponse:
+ """View for applying for membership."""
+ if request.method == "POST":
+ form = MemberApplicationForm(request.POST)
+ if form.is_valid():
+ form.save()
+ messages.success(
+ request,
+ _("Thank you for your application! We will review it and get back to you soon."),
+ )
+ return redirect("index")
+ else:
+ form = MemberApplicationForm()
+
+ return render(
+ request,
+ "membership/apply.html",
+ {"form": form},
+ )
diff --git a/src/project/locale/da/LC_MESSAGES/django.po b/src/project/locale/da/LC_MESSAGES/django.po
index 4eb2982..97146af 100644
--- a/src/project/locale/da/LC_MESSAGES/django.po
+++ b/src/project/locale/da/LC_MESSAGES/django.po
@@ -1,174 +1,684 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR , YEAR.
+#
+# <>, YEAR-2025.
#
msgid ""
msgstr ""
-"Project-Id-Version: \n"
+"Project-Id-Version: unnamed project\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-03-04 09:06+0100\n"
-"PO-Revision-Date: 2021-03-04 09:06+0100\n"
-"Last-Translator: \n"
-"Language-Team: \n"
-"Language: da\n"
+"POT-Creation-Date: 2025-03-08 22:43+0100\n"
+"PO-Revision-Date: 2025-03-06 08:35+0100\n"
+"Last-Translator: <>\n"
+"Language-Team: Abkhazian\n"
+"Language: ab\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.4.1\n"
+"X-Generator: Gtranslator 47.1\n"
-#: src/accounting/admin.py:15 src/accounting/admin.py:26
-msgid "Customer"
+#: accounting/admin.py:26
+msgid "Leave empty to auto-choose the member's own account or to create one."
msgstr ""
-#: src/accounting/admin.py:31
+#: accounting/admin.py:77
msgid "Order ID"
msgstr ""
-#: src/accounting/models.py:13 src/membership/models.py:11
-msgid "modified"
-msgstr ""
-
-#: src/accounting/models.py:14 src/membership/models.py:12
-msgid "created"
-msgstr ""
-
-#: src/accounting/models.py:43
+#: accounting/models.py:48
msgid "amount"
msgstr ""
-#: src/accounting/models.py:46
+#: accounting/models.py:51
msgid "This will include VAT"
msgstr ""
-#: src/accounting/models.py:48 src/accounting/models.py:61
-#: src/accounting/models.py:100
+#: accounting/models.py:53 accounting/models.py:69 accounting/models.py:158
+#: accounting/models.py:194
msgid "description"
msgstr ""
-#: src/accounting/models.py:64
-msgid "price (excl. VAT)"
-msgstr ""
-
-#: src/accounting/models.py:66
-msgid "VAT"
-msgstr ""
-
-#: src/accounting/models.py:68
+#: accounting/models.py:71
msgid "is paid"
msgstr ""
-#: src/accounting/models.py:88
-msgctxt "accounting term"
+#: accounting/models.py:74 accounting/templates/accounting/order/detail.html:5
+msgctxt "accounting"
msgid "Order"
msgstr ""
-#: src/accounting/models.py:89
-msgctxt "accounting term"
+#: accounting/models.py:75
+msgctxt "accounting"
msgid "Orders"
msgstr ""
-#: src/accounting/models.py:121
+#: accounting/models.py:140
+msgid "ordered product"
+msgstr ""
+
+#: accounting/models.py:141
+msgid "ordered products"
+msgstr ""
+
+#: accounting/models.py:164
msgid "payment"
msgstr ""
-#: src/accounting/models.py:122
+#: accounting/models.py:165
msgid "payments"
msgstr ""
-#: src/membership/models.py:45
+#: accounting/templates/accounting/order/cancel.html:5
+msgid "Payment cancelled"
+msgstr ""
+
+#: accounting/templates/accounting/order/cancel.html:11
+msgid "Payment canceled"
+msgstr ""
+
+#: accounting/templates/accounting/order/cancel.html:14
+msgid "Return to order page"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:14
+msgctxt "accounting"
+msgid "Ordered"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:15
+#, fuzzy
+#| msgid "Status"
+msgctxt "accounting"
+msgid "Status"
+msgstr "Status"
+
+#: accounting/templates/accounting/order/detail.html:15
+msgid "paid,unpaid"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:21
+msgctxt "accounting"
+msgid "Item"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:22
+msgid "Quantity"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:23
+msgid "Price"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:24
+msgid "VAT"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:25
+msgid "Total"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:41
+msgid "Total price"
+msgstr ""
+
+#: accounting/templates/accounting/order/detail.html:45
+msgid "Pay now"
+msgstr ""
+
+#: accounting/templates/accounting/order/success.html:5
+#: accounting/templates/accounting/order/success.html:11
+msgid "Payment received"
+msgstr ""
+
+#: accounting/templates/accounting/order/success.html:14
+#, python-format
+msgid ""
+"Thanks fellow member! We received your payment for Order %(order_id)s. We're "
+"adding more features to the site, so expect to see a confirmation email "
+"(receipt) for the order soon."
+msgstr ""
+
+#: membership/emails.py:95
+msgid "Email successfully sent to {}"
+msgstr ""
+
+#: membership/emails.py:101
+msgid "Not sent, something wrong with the mail server."
+msgstr ""
+
+#: membership/emails.py:108
+msgid "Invite to data.coop membership"
+msgstr ""
+
+#: membership/emails.py:129
+msgid "Your data.coop order and payment"
+msgstr ""
+
+#: membership/forms.py:26 membership/forms.py:27 membership/views.py:84
+msgid "Username"
+msgstr "Brugernavn"
+
+#: membership/forms.py:61
+#, fuzzy
+#| msgid "I have read and accepted the Acceptable Usage Policy."
+msgid "I have read and accept the Acceptable Usage Policy."
+msgstr "Jeg har læst og accepteret foreningens Acceptable Usage Policy."
+
+#: membership/forms.py:65 membership/forms.py:95
+msgid "I have read the bylaws."
+msgstr "Jeg har læst vedtægterne."
+
+#: membership/forms.py:89
+msgid "Your preferred username"
+msgstr "Dit foretrukne brugernavn"
+
+#: membership/forms.py:90
+msgid "Tell us about yourself"
+msgstr "Fortæl os om dig selv"
+
+#: membership/forms.py:91
+msgid "Location"
+msgstr "Beliggenhed"
+
+#: membership/forms.py:92
+msgid "Membership Type"
+msgstr "Medlemskabstype"
+
+#: membership/forms.py:93
+msgid "I would like an introduction to the association."
+msgstr "Jeg vil gerne have en introduktion til foreningen."
+
+#: membership/forms.py:94
+msgid "I have read and accepted the Acceptable Usage Policy."
+msgstr "Jeg har læst og accepteret foreningens Acceptable Usage Policy."
+
+#: membership/forms.py:98
+msgid "The username you would like to use."
+msgstr "Brugernavnet, du gerne vil have."
+
+#: membership/forms.py:99
+msgid "Please select the membership type you are applying for."
+msgstr "Vælg den medlemsskabstype, du ansøger om."
+
+#: membership/forms.py:100
+msgid ""
+"Please provide a brief description about yourself and why you want to join."
+msgstr ""
+"Skriv venligst en kort beskrivelse af dig selv og hvorfor du gerne vil blive "
+"medlem."
+
+#: membership/forms.py:101
+msgid "Where are you located? This helps us organize local events."
+msgstr "Hvor bor du? Dette hjælper os med at organisere lokale events."
+
+#: membership/forms.py:111
+msgid "You must read the bylaws before applying."
+msgstr "Du skal have læst vedtægterne for at ansøge om medlemsskab."
+
+#: membership/forms.py:113
+msgid "You must accept the AUP before applying."
+msgstr "Du skal have læst AUP'en for at ansøge om medlemsskab."
+
+#: membership/models.py:92
+msgid "period"
+msgstr "periode"
+
+#: membership/models.py:150 membership/models.py:219 membership/models.py:256
+msgid "membership type"
+msgstr "medlemskabstype"
+
+#: membership/models.py:163
+msgid "order"
+msgstr "ordre"
+
+#: membership/models.py:164
+msgid "The order filled in for paying this membership."
+msgstr ""
+
+#: membership/models.py:169
+msgid "activated"
+msgstr "aktiveret"
+
+#: membership/models.py:169
+msgid "Membership was activated."
+msgstr ""
+
+#: membership/models.py:175
+msgid "revoked"
+msgstr ""
+
+#: membership/models.py:177
+msgid ""
+"Membership has explicitly been revoked. Revoking a membership is not "
+"associated with regular expiration of the membership period."
+msgstr ""
+
+#: membership/models.py:185
msgid "membership"
msgstr "medlemskab"
-#: src/membership/models.py:46
+#: membership/models.py:186
msgid "memberships"
msgstr "medlemskaber"
-#: src/membership/models.py:53
-msgid "subscription type"
-msgstr ""
-
-#: src/membership/models.py:57
-msgid "The duration this subscription is for. "
-msgstr ""
-
-#: src/membership/models.py:70
-msgid "membership type"
-msgstr ""
-
-#: src/membership/models.py:71
-msgid "membership types"
-msgstr ""
-
-#: src/membership/models.py:73
+#: membership/models.py:212 membership/models.py:244
msgid "name"
msgstr "navn"
-#: src/membership/templates/membership_overview.html:7
+#: membership/models.py:220
+msgid "membership types"
+msgstr ""
+
+#: membership/models.py:246
+msgid "username"
+msgstr "brugernavn"
+
+#: membership/models.py:247
+msgid "geography"
+msgstr "lokation"
+
+#: membership/models.py:250
+msgid "wants introduction"
+msgstr "vil have en introduktion"
+
+#: membership/models.py:252
+msgid "Whether the person wants an introduction to the association."
+msgstr ""
+
+#: membership/models.py:257
+msgid "The membership type the person wants to apply for."
+msgstr ""
+
+#: membership/models.py:265
+msgid "has member"
+msgstr "har medlem"
+
+#: membership/models.py:266
+msgid ""
+"Once a member account is generated (use the admin action), this field will "
+"be marked."
+msgstr ""
+
+#: membership/models.py:288
+msgid "waiting list entry"
+msgstr ""
+
+#: membership/models.py:289
+msgid "waiting list entries"
+msgstr ""
+
+#: membership/permissions.py:56
+msgid "Can administrate members"
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/change_list.html:8
+msgid "Application Statistics"
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/statistics.html:8
+msgid "Applications by Month"
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/statistics.html:14
+msgid "Month"
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/statistics.html:15
+msgid "Number of Applications"
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/statistics.html:28
+msgid "No applications found."
+msgstr ""
+
+#: membership/templates/admin/membership/waitinglistentry/statistics.html:33
+msgid "Back to list"
+msgstr ""
+
+#: membership/templates/membership/apply.html:5
+#: membership/templates/membership/apply.html:11
+msgid "Apply for Membership"
+msgstr "Ansøg om medlemskab"
+
+#: membership/templates/membership/apply.html:13
+msgid "Fill out the form below to apply for membership of data.coop."
+msgstr "Udfyld formularen nedenfor for at ansøge om medlemskab af data.coop."
+
+#: membership/templates/membership/apply.html:18
+#, python-format
+msgid ""
+"All applicants are required to have read and understood the Acceptable Usage "
+"Policy and the bylaws of the association."
+msgstr ""
+"Alle ansøgere har pligt til at læse og forstå vores Acceptable Usage Policy og vedtægterne for foreningen."
+
+#: membership/templates/membership/apply.html:29
+msgid "Name"
+msgstr "Navn"
+
+#: membership/templates/membership/apply.html:37 membership/views.py:87
+#: project/templates/account/login.html:22
+#: project/templates/account/login.html:28
+msgid "Email"
+msgstr "E-mail"
+
+#: membership/templates/membership/apply.html:113
+msgid "Submit Application"
+msgstr "Indsend ansøgning"
+
+#: membership/templates/membership/apply.html:118
+msgid "Already a member? Log in"
+msgstr "Allerede medlem? Log ind"
+
+#: membership/templates/membership/apply.html:124
+msgid "About data.coop"
+msgstr "Om data.coop"
+
+#: membership/templates/membership/apply.html:125
+msgid ""
+"We are a cooperative association dedicated to helping members manage data "
+"ethically and securely."
+msgstr ""
+"Vi er et kooperativ, som er dedikeret til at hjælpe medlemmerne med at "
+"administrere sine data etisk og sikkert."
+
+#: membership/templates/membership/apply.html:127
+msgid ""
+"Read more about becoming a member on our main website."
+msgstr ""
+"Læs mere om at blive medlem på vores hjemmeside."
+
+#: membership/templates/membership/emails/base.txt:1
+#, python-format
+msgid "Dear %(recipient_name)s,"
+msgstr "Kære %(recipient_name)s"
+
+#: membership/templates/membership/emails/base.txt:6
+msgid "Cooperatively yours,"
+msgstr "Kooperative hilsener"
+
+#: membership/templates/membership/emails/invite.txt:3
+#, python-format
+msgid ""
+"Here is your secret URL for creating an account with us:\n"
+"\n"
+"%(protocol)s://%(domain)s%(invite_url)s\n"
+"\n"
+"If you did not request this account, get in touch with us."
+msgstr ""
+"Her er en hemmelig URL til at oprette en konto hos os:\n"
+"\n"
+"%(protocol)s://%(domain)s%(invite_url)s\n"
+"\n"
+"Hvis du ikke har bedt om dette, så skriv til os."
+
+#: membership/templates/membership/emails/order.txt:3
+#, python-format
+msgid ""
+"You have an order in our system, which you can pay here:\n"
+"\n"
+"%(protocol)s://%(domain)s%(order_url)s\n"
+"\n"
+"We used to handle membership stuff in a spreadsheet and via bank transfers. "
+"This is now all handled with our custom-made membership system. We hope you "
+"like it.\n"
+"\n"
+"If you received this email and no longer want a membership, you can ignore "
+"it. But please let us know by writing board@data.coop, so we can erase any "
+"personal data we have about your previous membership.\n"
+"\n"
+"Dansk:\n"
+"\n"
+"Hej! Så kører medlemsystemet endeligt! Det er mega-fedt, fordi vi længe har "
+"haft besvær med manuelle procedurer. Nu har vi flyttet medlemsdata over på "
+"member.data.coop, og betalingen fungerer. Vi kan dermed fremover arbejde "
+"stille og roligt på at integrere systemet, så man kan styre sine services "
+"via medlemssystemet.\n"
+"\n"
+"Hvis du ikke længere vil være medlem, kan du ignorere mailen her; men du må "
+"meget gerne informere os via board@data.coop, så vi kan slette evt. "
+"personlige data og services, du har kørende på dit tidligere medlemskab.\n"
+"\n"
+msgstr ""
+
+#: membership/templates/membership/invite.html:5
+#: membership/templates/membership/members_admin_detail.html:17
+#: membership/templates/membership/membership_overview.html:5
+msgid "Membership"
+msgstr "Medlemskab"
+
+#: membership/templates/membership/invite.html:11
+#: membership/templates/membership/invite.html:17
+msgid "Create account"
+msgstr "Opret konto"
+
+#: membership/templates/membership/invite.html:12
+msgid "Congratulations! You've been invited to create an account with us:"
+msgstr "Tillykke! Du er blevet inviteret til at oprette en konto hos os:"
+
+#: membership/templates/membership/members_admin_detail.html:5
+#, fuzzy
+#| msgid "Membership"
+msgid "Member detail"
+msgstr "Medlemskab"
+
+#: membership/templates/membership/members_admin_detail.html:23
+msgid "Start"
+msgstr ""
+
+#: membership/templates/membership/members_admin_detail.html:24
+msgid "End"
+msgstr ""
+
+#: membership/templates/membership/members_admin_detail.html:25
+msgid "Has membership"
+msgstr "Har medlemskab"
+
+#: membership/templates/membership/members_admin_detail.html:26
+#: utils/templates/utils/list.html:27
+msgid "Actions"
+msgstr "Handlinger"
+
+#: membership/templates/membership/members_admin_detail.html:41
+msgid "No memberships"
+msgstr "Ingen medlemskaber"
+
+#: membership/templates/membership/membership_overview.html:13
msgid "You do not have an active membership!"
msgstr "Du har ikke et aktivt medlemskab!"
-#: src/membership/templates/membership_overview.html:9
+#: membership/templates/membership/membership_overview.html:15
msgid ""
"You can become a member by depositing the membership fee to our bank account."
msgstr ""
-#: src/membership/templates/membership_overview.html:17
+#: membership/templates/membership/membership_overview.html:23
msgid "You are a member!"
msgstr "Du er medlem!"
-#: src/membership/templates/membership_overview.html:19
+#: membership/templates/membership/membership_overview.html:25
+msgid "next general assembly"
+msgstr ""
+
+#: membership/templates/membership/membership_overview.html:26
msgid "Period"
msgstr "Periode"
-#: src/membership/templates/membership_overview.html:20
+#: membership/templates/membership/membership_overview.html:27
msgid "Type"
msgstr "Type"
-#: src/project/settings.py:131
+#: membership/views.py:85
+msgid "First name"
+msgstr "Fornavn"
+
+#: membership/views.py:86
+msgid "Last name"
+msgstr "Efternavn"
+
+#: membership/views.py:88
+msgid "Active membership"
+msgstr "Aktivt medlemskab"
+
+#: membership/views.py:92
+msgid "View"
+msgstr "Vis"
+
+#: membership/views.py:157
+msgid "Password is set for your account and you can now login."
+msgstr ""
+
+#: membership/views.py:187
+msgid ""
+"Thank you for your application! We will review it and get back to you soon."
+msgstr ""
+
+#: services/models.py:24
+msgid "New"
+msgstr "Ny"
+
+#: services/models.py:25
+msgid "Resolved"
+msgstr "Færdigbehandlet"
+
+#: services/models.py:33
+msgid "service"
+msgstr "tjeneste"
+
+#: services/models.py:36
+msgid "subscription data"
+msgstr ""
+
+#: services/models.py:42
+#, fuzzy
+#| msgid "Services"
+msgid "service access"
+msgstr "Tjenester"
+
+#: services/models.py:43
+msgid "service accesses"
+msgstr ""
+
+#: services/models.py:78
+msgid "Notes from the member, intended to guide the resolution of the request."
+msgstr ""
+
+#: services/models.py:81
+msgid ""
+"Readable by member: Notes from the admin / status updates, resolutions etc."
+msgstr ""
+
+#: services/models.py:86
+msgid "assigned to"
+msgstr ""
+
+#: services/models.py:87
+msgid "the admin team member assigned to this request"
+msgstr ""
+
+#: services/models.py:96
+#, fuzzy
+#| msgid "Services"
+msgid "service request"
+msgstr "Tjenester"
+
+#: services/models.py:97
+msgid "service requests"
+msgstr ""
+
+#: services/registry.py:19
+msgid "Creation"
+msgstr ""
+
+#: services/registry.py:20
+#, fuzzy
+#| msgid "Password Reset E-mail"
+msgid "Password reset"
+msgstr "Nulstilling af password"
+
+#: services/registry.py:21
+msgid "Deletion"
+msgstr ""
+
+#: utils/mixins.py:10
+msgid "modified"
+msgstr ""
+
+#: utils/mixins.py:11
+msgid "created"
+msgstr ""
+
+#: utils/templates/utils/list.html:58 utils/templates/utils/list.html:64
+msgid "Previous"
+msgstr ""
+
+#: utils/templates/utils/list.html:93 utils/templates/utils/list.html:99
+msgid "Next"
+msgstr ""
+
+#: project/settings.py:155
msgid "Danish"
msgstr "Dansk"
-#: src/project/settings.py:132
+#: project/settings.py:156
msgid "English"
msgstr "Engelsk"
-#: src/project/templates/account/account_inactive.html:5
-#: src/project/templates/account/account_inactive.html:8
+#: project/templates/account/account_inactive.html:5
+#: project/templates/account/account_inactive.html:8
msgid "Account Inactive"
msgstr "Inaktiv konto"
-#: src/project/templates/account/account_inactive.html:10
+#: project/templates/account/account_inactive.html:10
msgid "This account is inactive."
msgstr "Denne konto er inaktiv."
-#: src/project/templates/account/email.html:5
-#: src/project/templates/account/email.html:16
-msgid "E-mail Addresses"
+#: project/templates/account/email.html:5
+#: project/templates/account/email.html:9
+#, fuzzy
+#| msgid "E-mail Addresses"
+msgid "Email Addresses"
msgstr "E-mail adresser"
-#: src/project/templates/account/email.html:21
-msgid "The following e-mail addresses are associated with your account:"
+#: project/templates/account/email.html:10
+#, fuzzy
+#| msgid "The following e-mail addresses are associated with your account:"
+msgid "The following email addresses are associated with your account:"
msgstr "De følgende e-mail adresser er tilknyttet din konto:"
-#: src/project/templates/account/email.html:31
+#: project/templates/account/email.html:28
msgid "Address"
msgstr "Adresse"
-#: src/project/templates/account/email.html:32
+#: project/templates/account/email.html:29
msgid "Status"
msgstr "Status"
-#: src/project/templates/account/email.html:33
+#: project/templates/account/email.html:30
+#: project/templates/account/email.html:62
msgid "Primary"
msgstr "Primær"
-#: src/project/templates/account/email.html:90
+#: project/templates/account/email.html:55
+msgid "Verified"
+msgstr ""
+
+#: project/templates/account/email.html:57
+msgid "Unverified"
+msgstr ""
+
+#: project/templates/account/email.html:75
msgid "Warning:"
msgstr "Advarsel:"
-#: src/project/templates/account/email.html:91
+#: project/templates/account/email.html:76
msgid ""
"You currently do not have any e-mail address set up. You should really add "
"an e-mail address so you can receive notifications, reset your password, etc."
@@ -176,28 +686,32 @@ msgstr ""
"Du har lige nu ingen e-mail adresse tilknyttet. Du burde virkelig tilføje en "
"e-mail adresse så du kan modtage notifikationer, nulstille dit kodeord, osv."
-#: src/project/templates/account/email.html:99
-#: src/project/templates/account/email.html:107
+#: project/templates/account/email.html:82
+#: project/templates/account/email.html:88
msgid "Add E-mail"
msgstr "Tilføj e-mail"
-#: src/project/templates/account/email.html:118
+#: project/templates/account/email.html:90
+msgid "Cancel"
+msgstr ""
+
+#: project/templates/account/email.html:98
msgid "Do you really want to remove the selected e-mail address?"
msgstr "Vil du virkelig fjerne den valgte e-mail?"
-#: src/project/templates/account/email/base_message.txt:1
+#: project/templates/account/email/base_message.txt:1
#, python-format
msgid "Hello from %(site_name)s!"
msgstr "Hej fra %(site_name)s!"
-#: src/project/templates/account/email/base_message.txt:5
+#: project/templates/account/email/base_message.txt:5
#, python-format
msgid ""
"Thank you for using %(site_name)s!\n"
"%(site_domain)s"
msgstr ""
-#: src/project/templates/account/email/email_confirmation_message.txt:5
+#: project/templates/account/email/email_confirmation_message.txt:5
#, python-format
msgid ""
"You're receiving this e-mail because user %(user_display)s has given your e-"
@@ -206,11 +720,11 @@ msgid ""
"To confirm this is correct, go to %(activate_url)s"
msgstr ""
-#: src/project/templates/account/email/email_confirmation_subject.txt:3
+#: project/templates/account/email/email_confirmation_subject.txt:3
msgid "Please Confirm Your E-mail Address"
msgstr "Venligst bekræft din e-mail adresse"
-#: src/project/templates/account/email/password_reset_key_message.txt:4
+#: project/templates/account/email/password_reset_key_message.txt:4
msgid ""
"You're receiving this e-mail because you or someone else has requested a "
"password for your user account.\n"
@@ -222,180 +736,193 @@ msgstr ""
"Du kan trygt ignorere dette hvis det ikke var dig der anmodede om "
"nulstillingen. Klik på linket herunder for at nulstille dit kodeord."
-#: src/project/templates/account/email/password_reset_key_message.txt:9
+#: project/templates/account/email/password_reset_key_message.txt:9
#, python-format
msgid "In case you forgot, your username is %(username)s."
msgstr ""
-#: src/project/templates/account/email/password_reset_key_subject.txt:3
+#: project/templates/account/email/password_reset_key_subject.txt:3
msgid "Password Reset E-mail"
msgstr "Nulstilling af password"
-#: src/project/templates/account/email_confirm.html:6
-#: src/project/templates/account/email_confirm.html:10
+#: project/templates/account/email_confirm.html:6
+#: project/templates/account/email_confirm.html:10
msgid "Confirm E-mail Address"
msgstr "Bekræft e-mail adresse"
-#: src/project/templates/account/email_confirm.html:16
+#: project/templates/account/email_confirm.html:16
#, python-format
msgid ""
"Please confirm that %(email)s is an e-mail "
"address for user %(user_display)s."
msgstr ""
-#: src/project/templates/account/email_confirm.html:20
+#: project/templates/account/email_confirm.html:20
msgid "Confirm"
msgstr "Bekræft"
-#: src/project/templates/account/email_confirm.html:27
+#: project/templates/account/email_confirm.html:27
#, python-format
msgid ""
-"This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request."
+"This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request."
msgstr ""
-#: src/project/templates/account/login.html:20
-#: src/project/templates/account/login.html:26
-#: src/project/templates/account/signup.html:26
-#: src/project/templates/account/signup.html:32
-msgid "E-mail"
-msgstr "E-mail"
+#: project/templates/account/login.html:15
+msgid "Login "
+msgstr ""
-#: src/project/templates/account/login.html:31
-#: src/project/templates/account/login.html:37
-#: src/project/templates/account/signup.html:44
-#: src/project/templates/account/signup.html:50
+#: project/templates/account/login.html:34
+#: project/templates/account/login.html:40
+#: project/templates/account/signup.html:49
+#: project/templates/account/signup.html:55
msgid "Password"
msgstr "Kodeord"
-#: src/project/templates/account/login.html:41
-msgid "Sign in"
-msgstr "Log ind"
+#: project/templates/account/login.html:44
+#, fuzzy
+#| msgid "To login"
+msgid "Login"
+msgstr "Til login"
-#: src/project/templates/account/login.html:45
+#: project/templates/account/login.html:49
msgid "Forgot password / no password?"
msgstr "Glemt/intet kodeord?"
-#: src/project/templates/account/login.html:48
-msgid "Or"
-msgstr "Eller"
+#: project/templates/account/login.html:56
+#: project/templates/account/password_reset.html:51
+#: project/templates/account/password_reset_done.html:30
+#: project/templates/account/signup.html:82
+msgid "Are you new here?"
+msgstr ""
-#: src/project/templates/account/login.html:53
-#: src/project/templates/account/signup.html:6
-msgid "Become a member"
-msgstr "Bliv medlem"
+#: project/templates/account/login.html:57
+#, fuzzy
+#| msgid "membership"
+msgid "Apply for membership"
+msgstr "medlemskab"
-#: src/project/templates/account/logout.html:5
-#: src/project/templates/account/logout.html:8
-#: src/project/templates/account/logout.html:17
+#: project/templates/account/logout.html:5
+#: project/templates/account/logout.html:9
+#: project/templates/account/logout.html:18
msgid "Sign Out"
msgstr "Log ud"
-#: src/project/templates/account/logout.html:10
+#: project/templates/account/logout.html:11
msgid "Are you sure you want to sign out?"
msgstr "Er du sikker på at du vil logge ind?"
-#: src/project/templates/account/messages/cannot_delete_primary_email.txt:2
+#: project/templates/account/messages/cannot_delete_primary_email.txt:2
#, python-format
msgid "You cannot remove your primary e-mail address (%(email)s)."
msgstr ""
-#: src/project/templates/account/messages/email_confirmation_sent.txt:2
+#: project/templates/account/messages/email_confirmation_sent.txt:2
#, python-format
msgid "Confirmation e-mail sent to %(email)s."
msgstr ""
-#: src/project/templates/account/messages/email_confirmed.txt:2
+#: project/templates/account/messages/email_confirmed.txt:2
#, python-format
msgid "You have confirmed %(email)s."
msgstr ""
-#: src/project/templates/account/messages/email_deleted.txt:2
+#: project/templates/account/messages/email_deleted.txt:2
#, python-format
msgid "Removed e-mail address %(email)s."
msgstr ""
-#: src/project/templates/account/messages/logged_in.txt:4
+#: project/templates/account/messages/logged_in.txt:4
#, python-format
msgid "Successfully signed in as %(name)s."
msgstr ""
-#: src/project/templates/account/messages/logged_out.txt:2
+#: project/templates/account/messages/logged_out.txt:2
msgid "You have signed out."
msgstr "Du er nu logget ud."
-#: src/project/templates/account/messages/password_changed.txt:2
+#: project/templates/account/messages/password_changed.txt:2
msgid "Password successfully changed."
msgstr ""
-#: src/project/templates/account/messages/password_set.txt:2
+#: project/templates/account/messages/password_set.txt:2
msgid "Password successfully set."
msgstr ""
-#: src/project/templates/account/messages/primary_email_set.txt:2
+#: project/templates/account/messages/primary_email_set.txt:2
msgid "Primary e-mail address set."
msgstr ""
-#: src/project/templates/account/messages/unverified_primary_email.txt:2
+#: project/templates/account/messages/unverified_primary_email.txt:2
msgid "Your primary e-mail address must be verified."
msgstr ""
-#: src/project/templates/account/password_change.html:5
-#: src/project/templates/account/password_change.html:8
-#: src/project/templates/account/password_change.html:13
-#: src/project/templates/account/password_reset_from_key.html:4
-#: src/project/templates/account/password_reset_from_key.html:7
-#: src/project/templates/account/password_reset_from_key_done.html:4
-#: src/project/templates/account/password_reset_from_key_done.html:7
+#: project/templates/account/password_change.html:5
+#: project/templates/account/password_change.html:8
+#: project/templates/account/password_change.html:13
+#: project/templates/account/password_reset_from_key.html:5
+#: project/templates/account/password_reset_from_key.html:8
+#: project/templates/account/password_reset_from_key_done.html:4
+#: project/templates/account/password_reset_from_key_done.html:7
msgid "Change Password"
msgstr "Skift kodeord"
-#: src/project/templates/account/password_change.html:14
+#: project/templates/account/password_change.html:14
msgid "Forgot Password?"
msgstr "Glemt kodeord?"
-#: src/project/templates/account/password_reset.html:6
-#: src/project/templates/account/password_reset.html:10
-#: src/project/templates/account/password_reset_done.html:6
-#: src/project/templates/account/password_reset_done.html:9
+#: project/templates/account/password_reset.html:6
+#: project/templates/account/password_reset.html:11
+#: project/templates/account/password_reset_done.html:6
+#: project/templates/account/password_reset_done.html:12
msgid "Password Reset"
msgstr ""
-#: src/project/templates/account/password_reset.html:16
+#: project/templates/account/password_reset.html:17
msgid ""
-"Forgotten your password? Enter your e-mail address below, and we'll send you "
-"an e-mail allowing you to reset it."
+"Enter your e-mail address below, and we'll send you an e-mail allowing you "
+"to reset your password."
msgstr ""
-#: src/project/templates/account/password_reset.html:21
-#: src/project/templates/account/password_reset.html:27
-msgid "E-mail address"
-msgstr "E-mail adresser"
+#: project/templates/account/password_reset.html:23
+#: project/templates/account/password_reset.html:29
+#: project/templates/account/signup.html:29
+#: project/templates/account/signup.html:35
+msgid "E-mail"
+msgstr "E-mail"
-#: src/project/templates/account/password_reset.html:38
+#: project/templates/account/password_reset.html:39
msgid "Reset My Password"
msgstr ""
-#: src/project/templates/account/password_reset.html:41
+#: project/templates/account/password_reset.html:42
msgid "Please contact us if you have any trouble resetting your password."
msgstr ""
-#: src/project/templates/account/password_reset.html:47
-#: src/project/templates/account/signup.html:72
+#: project/templates/account/password_reset.html:45
+#: project/templates/account/password_reset_done.html:24
+#: project/templates/account/signup.html:75
msgid "To login"
msgstr "Til login"
-#: src/project/templates/account/password_reset_done.html:15
+#: project/templates/account/password_reset.html:52
+#: project/templates/account/password_reset_done.html:31
+#: project/templates/account/signup.html:8
+#: project/templates/account/signup.html:83
+msgid "Become a member"
+msgstr "Bliv medlem"
+
+#: project/templates/account/password_reset_done.html:19
msgid ""
"We have sent you an e-mail. Please contact us if you do not receive it "
"within a few minutes."
msgstr ""
-#: src/project/templates/account/password_reset_from_key.html:7
+#: project/templates/account/password_reset_from_key.html:8
msgid "Bad Token"
msgstr ""
-#: src/project/templates/account/password_reset_from_key.html:11
+#: project/templates/account/password_reset_from_key.html:12
#, python-format
msgid ""
"The password reset link was invalid, possibly because it has already been "
@@ -403,117 +930,109 @@ msgid ""
"a>."
msgstr ""
-#: src/project/templates/account/password_reset_from_key.html:17
+#: project/templates/account/password_reset_from_key.html:18
msgid "change password"
msgstr ""
-#: src/project/templates/account/password_reset_from_key.html:20
-#: src/project/templates/account/password_reset_from_key_done.html:8
+#: project/templates/account/password_reset_from_key.html:21
+#: project/templates/account/password_reset_from_key_done.html:8
msgid "Your password is now changed."
msgstr ""
-#: src/project/templates/account/password_set.html:5
-#: src/project/templates/account/password_set.html:8
-#: src/project/templates/account/password_set.html:13
+#: project/templates/account/password_set.html:5
+#: project/templates/account/password_set.html:8
+#: project/templates/account/password_set.html:13
msgid "Set Password"
msgstr "Sæt kodeord"
-#: src/project/templates/account/signup.html:19
+#: project/templates/account/signup.html:21
msgid "To become a member, you need to have an account. Create one here."
msgstr ""
-#: src/project/templates/account/signup.html:66
+#: project/templates/account/signup.html:71
msgid "Sign up"
msgstr "Bliv medlem"
-#: src/project/templates/account/signup_closed.html:5
-#: src/project/templates/account/signup_closed.html:8
+#: project/templates/account/signup_closed.html:5
+#: project/templates/account/signup_closed.html:8
msgid "Sign Up Closed"
msgstr ""
-#: src/project/templates/account/signup_closed.html:10
+#: project/templates/account/signup_closed.html:10
msgid "We are sorry, but the sign up is currently closed."
msgstr ""
-#: src/project/templates/account/snippets/already_logged_in.html:5
+#: project/templates/account/snippets/already_logged_in.html:5
msgid "Note"
msgstr ""
-#: src/project/templates/account/snippets/already_logged_in.html:5
+#: project/templates/account/snippets/already_logged_in.html:5
#, python-format
msgid "you are already logged in as %(user_display)s."
msgstr ""
-#: src/project/templates/account/verification_sent.html:5
-#: src/project/templates/account/verification_sent.html:8
-#: src/project/templates/account/verified_email_required.html:5
-#: src/project/templates/account/verified_email_required.html:8
+#: project/templates/account/verification_sent.html:5
+#: project/templates/account/verification_sent.html:8
+#: project/templates/account/verified_email_required.html:5
+#: project/templates/account/verified_email_required.html:8
msgid "Verify Your E-mail Address"
msgstr "Verificér din e-mail adresse"
-#: src/project/templates/account/verification_sent.html:10
+#: project/templates/account/verification_sent.html:10
msgid ""
"We have sent an e-mail to you for verification. Follow the link provided to "
"finalize the signup process. Please contact us if you do not receive it "
"within a few minutes."
msgstr ""
-#: src/project/templates/account/verified_email_required.html:12
+#: project/templates/account/verified_email_required.html:12
msgid ""
"This part of the site requires us to verify that\n"
"you are who you claim to be. For this purpose, we require that you\n"
"verify ownership of your e-mail address. "
msgstr ""
-#: src/project/templates/account/verified_email_required.html:16
+#: project/templates/account/verified_email_required.html:16
msgid ""
"We have sent an e-mail to you for\n"
"verification. Please click on the link inside this e-mail. Please\n"
"contact us if you do not receive it within a few minutes."
msgstr ""
-#: src/project/templates/account/verified_email_required.html:20
+#: project/templates/account/verified_email_required.html:20
#, python-format
msgid ""
"Note: you can still change your e-"
"mail address."
msgstr ""
-#: src/project/templates/base.html:140
-msgid "Dashboard"
+#: project/templates/index.html:4
+msgid "Home"
msgstr ""
-#: src/project/templates/base.html:146
-msgid "Profile"
-msgstr "Profil"
+#~ msgid "Sign in"
+#~ msgstr "Log ind"
-#: src/project/templates/base.html:152
-msgid "Details"
-msgstr "Detaljer"
+#~ msgid "Or"
+#~ msgstr "Eller"
-#: src/project/templates/base.html:158
-msgid "Emails"
-msgstr "Emails"
+#~ msgid "E-mail address"
+#~ msgstr "E-mail adresser"
-#: src/project/templates/base.html:164
-msgid "Membership"
-msgstr "Medlemskab"
+#~ msgid "Profile"
+#~ msgstr "Profil"
-#: src/project/templates/base.html:171 src/project/templates/base.html:184
-msgid "Overview"
-msgstr "Oversigt"
+#~ msgid "Details"
+#~ msgstr "Detaljer"
-#: src/project/templates/base.html:177
-msgid "Services"
-msgstr "Tjenester"
+#~ msgid "Overview"
+#~ msgstr "Oversigt"
-#: src/project/templates/base.html:191
-msgid "Admin"
-msgstr "Admin"
+#~ msgid "Admin"
+#~ msgstr "Admin"
-#: src/project/templates/base.html:197
-msgid "Members"
-msgstr "Medlemmer"
+#~ msgid "Members"
+#~ msgstr "Medlemmer"
#~ msgid "OR"
#~ msgstr "Eller"
diff --git a/src/project/static/css/style.css b/src/project/static/css/style.css
index 661b6f6..8675959 100644
--- a/src/project/static/css/style.css
+++ b/src/project/static/css/style.css
@@ -391,6 +391,9 @@ article table tbody td input[type="radio"] {
form>div {
margin: 0 0 var(--double-space);
}
+form>div.checkbox {
+ margin: 0 0 var(--space);
+}
form>div>label {
display: block;
@@ -441,10 +444,47 @@ form div.buttonHolder button {
}
#login {
- height: 100%;
display: flex;
+ flex-flow: column;
align-items: center;
justify-content: center;
+ min-height: 100vh;
+ margin: 1em 0 1em 0;
+}
+
+#login-messages {
+ width: 800px;
+ max-width: 100%;
+ margin-bottom: 20px;
+}
+
+#login-messages .message {
+ padding: 15px;
+ border-radius: var(--space);
+ background-color: var(--light-dust);
+ margin-bottom: 10px;
+ text-align: center;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+#login-messages .message.success {
+ background-color: #d4edda;
+ color: #155724;
+}
+
+#login-messages .message.error {
+ background-color: #f8d7da;
+ color: #721c24;
+}
+
+#login-messages .message.warning {
+ background-color: #fff3cd;
+ color: #856404;
+}
+
+#login-messages .message.info {
+ background-color: #d1ecf1;
+ color: #0c5460;
}
#loginbox {
@@ -508,6 +548,65 @@ form div.buttonHolder button {
padding: 0 var(--double-space);
}
+/* Application box styling - matches loginbox */
+#applicationbox {
+ border-radius: var(--space);
+ border: 6px solid white;
+ width: 800px;
+ height: auto;
+ display: flex;
+ flex-flow: row;
+ max-width: 100%;
+}
+
+#applicationbox>div {
+ padding: var(--double-space);
+ flex: 1;
+ overflow-y: visible;
+}
+
+#applicationbox>div.application-form {
+ background: var(--light-dust);
+ display: flex;
+ flex-flow: column;
+ justify-content: flex-start;
+}
+
+#applicationbox>div.application-info {
+ background: var(--water);
+}
+
+#applicationbox>div:first-child {
+ border-radius: var(--half-space) 0 0 var(--half-space);
+}
+
+#applicationbox>div:last-child {
+ border-radius: 0 var(--half-space) var(--half-space) 0;
+}
+
+#applicationbox>div:last-child>* {
+ flex: 1;
+}
+
+#applicationbox div.about {
+ margin-top: var(--double-space);
+}
+
+#applicationbox h2 {
+ margin: var(--double-space) 0 var(--space);
+}
+#applicationbox p {
+ margin: 0 0 var(--space);
+}
+
+#applicationbox button {
+ width: 100%;
+}
+
+#applicationbox img {
+ padding: 0 var(--double-space);
+}
+
footer {
margin: var(--space) var(--outer-space);
padding: var(--space);
@@ -578,3 +677,19 @@ span.time_remaining {
.pagination .page-item.disabled .page-link {
cursor: default;
}
+
+@media (max-width: 800px) {
+ #applicationbox {
+ flex-flow: column;
+ width: 100%;
+ height: auto;
+ }
+
+ #applicationbox>div:first-child {
+ border-radius: var(--half-space) var(--half-space) 0 0;
+ }
+
+ #applicationbox>div:last-child {
+ border-radius: 0 0 var(--half-space) var(--half-space);
+ }
+}
diff --git a/src/project/templates/account/login.html b/src/project/templates/account/login.html
index 5f36b63..1ae9dbe 100644
--- a/src/project/templates/account/login.html
+++ b/src/project/templates/account/login.html
@@ -54,7 +54,8 @@
diff --git a/src/project/templates/account/pre_login_base.html b/src/project/templates/account/pre_login_base.html
index 114386b..7b9d4c0 100644
--- a/src/project/templates/account/pre_login_base.html
+++ b/src/project/templates/account/pre_login_base.html
@@ -12,6 +12,15 @@
+ {% if messages %}
+
+ {% for message in messages %}
+
+ {{ message }}
+
+ {% endfor %}
+
+ {% endif %}
{% block non_login_content %}
{% endblock %}