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 %} + + + + + + + + + {% for month, count in applications_by_month.items %} + + + + + {% endfor %} + +
    {% trans "Month" %}{% trans "Number of Applications" %}
    {{ month|date:"F Y" }}{{ count }}
    + {% else %} +

    {% trans "No applications found." %}

    + {% endif %} +
    + +
    + {% trans "Back to list" %} +
    +
    +{% 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 "Apply for Membership" %}

    +

    + {% blocktrans trimmed %} + Fill out the form below to apply for membership of data.coop. + {% endblocktrans %} +

    +

    + {% blocktrans trimmed %} + All applicants are required to have read and understood the + Acceptable Usage Policy and the + bylaws of the association. + {% endblocktrans %} +

    + +
    + {% csrf_token %} + +
    + + {{ form.name }} + {% if form.name.errors %} +
    {{ form.name.errors }}
    + {% endif %} +
    + +
    + + {{ form.email }} + {% if form.email.errors %} +
    {{ form.email.errors }}
    + {% endif %} +
    + +
    + + {{ form.username }} + {% if form.username.errors %} +
    {{ form.username.errors }}
    + {% endif %} +
    + +
    + + {{ form.geography }} + {{ form.geography.help_text }} + {% if form.geography.errors %} +
    {{ form.geography.errors }}
    + {% endif %} +
    + +
    + +
    + {{ form.membership_type }} +
    + {{ form.membership_type.help_text }} + {% if form.membership_type.errors %} +
    {{ form.membership_type.errors }}
    + {% endif %} +
    + +
    + + {{ form.comment }} + {{ form.comment.help_text }} + {% if form.comment.errors %} +
    {{ form.comment.errors }}
    + {% endif %} +
    + + +
    + + {% if form.wants_introduction.errors %} +
    {{ form.wants_introduction.errors }}
    + {% endif %} +
    + +
    + + {% if form.accepted_aup.errors %} +
    {{ form.accepted_aup.errors }}
    + {% endif %} +
    + +
    + + {% if form.has_read_bylaws.errors %} +
    {{ form.has_read_bylaws.errors }}
    + {% endif %} +
    + +
    + +
    +
    + + +
    +
    + data.coop logo +
    +

    {% 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 @@ data.coop logo

    {% trans "Are you new here?" %}

    - {% trans "Become a member" %} + {% trans "Apply for membership" %} + {% comment %} {% trans "Become a member" %} {% endcomment %} {% comment %} {% trans "Become a member" %} {% endcomment %}
    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 %}