Compare commits

...

3 Commits

Author SHA1 Message Date
Victor Andersson
65b249f2f8 fix: show edit button and translations 2025-11-11 21:09:59 +01:00
Victor Andersson
3d8e5ed410 feat: allow editing user profile info via modal 2025-11-11 21:04:33 +01:00
Victor Andersson
73ff0a9d45 fix: use precomputed permission flags in template 2025-11-11 20:48:12 +01:00
8 changed files with 380 additions and 141 deletions

View File

@@ -160,6 +160,42 @@ class UserPermissionForm(forms.Form):
grant_change = forms.BooleanField(required=False, label=_("Får besluta utlägg"))
grant_edit = forms.BooleanField(required=False, label=_("Får redigera utlägg"))
grant_pay = forms.BooleanField(required=False, label=_("Får markera betalningar"))
first_name = forms.CharField(
max_length=150,
required=False,
label=_("Förnamn"),
widget=forms.TextInput(attrs={"class": INPUT_CLASSES}),
)
last_name = forms.CharField(
max_length=150,
required=False,
label=_("Efternamn"),
widget=forms.TextInput(attrs={"class": INPUT_CLASSES}),
)
email = forms.EmailField(
required=False,
label=_("E-post"),
widget=forms.EmailInput(attrs={"class": INPUT_CLASSES}),
)
new_password1 = forms.CharField(
required=False,
label=_("Nytt lösenord"),
widget=forms.PasswordInput(attrs={"class": INPUT_CLASSES}),
)
new_password2 = forms.CharField(
required=False,
label=_("Bekräfta nytt lösenord"),
widget=forms.PasswordInput(attrs={"class": INPUT_CLASSES}),
)
def clean(self):
cleaned = super().clean()
pwd1 = cleaned.get("new_password1")
pwd2 = cleaned.get("new_password2")
if pwd1 or pwd2:
if pwd1 != pwd2:
self.add_error("new_password2", _("Lösenorden matchar inte."))
return cleaned
class DeleteUserForm(forms.Form):

View File

@@ -105,23 +105,47 @@
{{ user.get_full_name|default:_("Saknar namn") }} · {{ user.email|default:_("Ingen e-post") }}
</p>
</div>
<p class="text-xs uppercase tracking-wide text-gray-400">ID: {{ user.id }}</p>
<div class="flex items-center gap-3">
<p class="text-xs uppercase tracking-wide text-gray-400">ID: {{ user.id }}</p>
{% if can_change_users %}
<button type="button"
data-open-permission-edit="{{ user.id }}"
class="inline-flex items-center gap-2 rounded-full border border-gray-200 px-3 py-1 text-xs font-semibold text-gray-700 transition hover:bg-gray-100">
{% trans "Redigera användare" %}
</button>
{% endif %}
</div>
</div>
<div class="mt-4 grid gap-6 lg:grid-cols-[2fr,1fr]">
<div class="rounded-2xl bg-slate-50 p-4">
<p class="text-sm font-semibold text-gray-700">{% trans "Behörigheter" %}</p>
<div class="mt-3 flex flex-wrap gap-2 text-xs">
<span class="rounded-full px-3 py-1 {% if user.is_staff %}bg-emerald-100 text-emerald-800{% else %}bg-slate-200 text-slate-600{% endif %}">{% trans "Admin/staff" %}</span>
<span class="rounded-full px-3 py-1 {% if user.has_perm('claims.view_claim') %}bg-blue-100 text-blue-800{% else %}bg-slate-200 text-slate-600{% endif %}">{% trans "Får se utlägg" %}</span>
<span class="rounded-full px-3 py-1 {% if user.has_perm('claims.change_claim') %}bg-indigo-100 text-indigo-800{% else %}bg-slate-200 text-slate-600{% endif %}">{% trans "Får besluta utlägg" %}</span>
<span class="rounded-full px-3 py-1 {% if user.has_perm('claims.edit_claim_details') %}bg-purple-100 text-purple-800{% else %}bg-slate-200 text-slate-600{% endif %}">{% trans "Får redigera utlägg" %}</span>
<span class="rounded-full px-3 py-1 {% if user.has_perm('claims.mark_claim_paid') %}bg-amber-100 text-amber-800{% else %}bg-slate-200 text-slate-600{% endif %}">{% trans "Får markera betalningar" %}</span>
{% if row.permission_flags.is_staff %}
<span class="rounded-full px-3 py-1 bg-emerald-100 text-emerald-800">{% trans "Admin/staff" %}</span>
{% endif %}
{% if row.permission_flags.view %}
<span class="rounded-full px-3 py-1 bg-blue-100 text-blue-800">{% trans "Får se utlägg" %}</span>
{% endif %}
{% if row.permission_flags.change %}
<span class="rounded-full px-3 py-1 bg-indigo-100 text-indigo-800">{% trans "Får besluta utlägg" %}</span>
{% endif %}
{% if row.permission_flags.edit %}
<span class="rounded-full px-3 py-1 bg-purple-100 text-purple-800">{% trans "Får redigera utlägg" %}</span>
{% endif %}
{% if row.permission_flags.pay %}
<span class="rounded-full px-3 py-1 bg-amber-100 text-amber-800">{% trans "Får markera betalningar" %}</span>
{% endif %}
{% if not row.permission_flags.is_staff and not row.permission_flags.view and not row.permission_flags.change and not row.permission_flags.edit and not row.permission_flags.pay %}
<span class="rounded-full bg-slate-200 px-3 py-1 text-slate-600">{% trans "Inga behörigheter tilldelade" %}</span>
{% endif %}
</div>
<button type="button"
data-open-permission-edit="{{ user.id }}"
class="mt-4 inline-flex items-center gap-2 rounded-full bg-brand-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-brand-700">
{% trans "Redigera behörigheter" %}
</button>
{% if can_change_users %}
<button type="button"
data-open-permission-edit="{{ user.id }}"
class="mt-4 inline-flex items-center gap-2 rounded-full bg-brand-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-brand-700">
{% trans "Redigera behörigheter" %}
</button>
{% endif %}
</div>
<div class="rounded-2xl border border-red-100 bg-red-50 p-4 text-sm text-red-800">
<p class="font-semibold">{% trans "Ta bort konto" %}</p>
@@ -155,8 +179,9 @@
{% block modals %}
{{ block.super }}
{% for row in user_rows %}
{% with user=row.user form=row.permission_form %}
{% if can_change_users %}
{% for row in user_rows %}
{% with user=row.user form=row.permission_form %}
<div class="fixed inset-0 z-40 hidden items-center justify-center bg-slate-900/80 p-4"
data-permission-modal="{{ user.id }}"
aria-hidden="true"
@@ -178,7 +203,55 @@
{% csrf_token %}
<input type="hidden" name="action" value="update">
{{ form.user_id }}
<div class="space-y-3 text-sm text-gray-800">
<div class="space-y-5 text-sm text-gray-800">
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-gray-500">{% trans "Kontaktuppgifter" %}</p>
<div class="mt-3 grid gap-3 md:grid-cols-2">
<div>
<label class="text-xs font-semibold text-gray-600" for="{{ form.first_name.id_for_label }}">{{ form.first_name.label }}</label>
{{ form.first_name }}
{% for error in form.first_name.errors %}
<p class="text-xs text-rose-600">{{ error }}</p>
{% endfor %}
</div>
<div>
<label class="text-xs font-semibold text-gray-600" for="{{ form.last_name.id_for_label }}">{{ form.last_name.label }}</label>
{{ form.last_name }}
{% for error in form.last_name.errors %}
<p class="text-xs text-rose-600">{{ error }}</p>
{% endfor %}
</div>
<div class="md:col-span-2">
<label class="text-xs font-semibold text-gray-600" for="{{ form.email.id_for_label }}">{{ form.email.label }}</label>
{{ form.email }}
{% for error in form.email.errors %}
<p class="text-xs text-rose-600">{{ error }}</p>
{% endfor %}
</div>
</div>
</div>
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-gray-500">{% trans "Lösenord" %}</p>
<div class="mt-3 grid gap-3 md:grid-cols-2">
<div>
<label class="text-xs font-semibold text-gray-600" for="{{ form.new_password1.id_for_label }}">{{ form.new_password1.label }}</label>
{{ form.new_password1 }}
{% for error in form.new_password1.errors %}
<p class="text-xs text-rose-600">{{ error }}</p>
{% endfor %}
</div>
<div>
<label class="text-xs font-semibold text-gray-600" for="{{ form.new_password2.id_for_label }}">{{ form.new_password2.label }}</label>
{{ form.new_password2 }}
{% for error in form.new_password2.errors %}
<p class="text-xs text-rose-600">{{ error }}</p>
{% endfor %}
</div>
</div>
<p class="mt-1 text-xs text-gray-500">{% trans "Lämna fälten tomma för att behålla nuvarande lösenord." %}</p>
</div>
<div class="space-y-3">
<p class="text-xs font-semibold uppercase tracking-wide text-gray-500">{% trans "Behörigheter" %}</p>
<label class="flex items-center gap-3" for="{{ form.is_staff.id_for_label }}">
{{ form.is_staff }}
<span>{% trans "Admin/staff" %}</span>
@@ -199,6 +272,7 @@
{{ form.grant_pay }}
<span>{% trans "Får markera betalningar" %}</span>
</label>
</div>
</div>
<div class="flex items-center justify-end gap-3">
<button type="button"
@@ -213,12 +287,14 @@
</form>
</div>
</div>
{% endwith %}
{% endfor %}
{% endwith %}
{% endfor %}
{% endif %}
{% endblock %}
{% block extra_js %}
{{ block.super }}
{% if can_change_users %}
<script>
(function () {
function lockScroll() {
@@ -286,4 +362,5 @@
});
})();
</script>
{% endif %}
{% endblock %}

View File

@@ -239,3 +239,40 @@ class DashboardViewTests(TestCase):
claim.refresh_from_db()
self.assertIsNone(claim.paid_at)
self.assertFalse(claim.logs.filter(action=ClaimLog.Action.MARKED_PAID).exists())
class UserManagementViewTests(TestCase):
def setUp(self):
User = get_user_model()
self.admin = User.objects.create_user(username="manager", password="test123", email="manager@example.com")
perms = Permission.objects.filter(codename__in=["view_user", "change_user"])
self.admin.user_permissions.add(*perms)
self.client.force_login(self.admin)
self.target = User.objects.create_user(username="editor", password="oldpass123", email="old@example.com")
def test_admin_can_update_profile_and_password(self):
response = self.client.post(
reverse("claims:user-manage"),
{
"action": "update",
"user_id": self.target.id,
"is_staff": "on",
"grant_view": "on",
"grant_change": "",
"grant_edit": "on",
"grant_pay": "on",
"first_name": "New",
"last_name": "Name",
"email": "new@example.com",
"new_password1": "StrongPass123!",
"new_password2": "StrongPass123!",
},
follow=True,
)
self.assertEqual(response.status_code, 200)
target = get_user_model().objects.get(pk=self.target.pk)
self.assertEqual(target.first_name, "New")
self.assertEqual(target.last_name, "Name")
self.assertEqual(target.email, "new@example.com")
self.assertTrue(target.is_staff)
self.assertTrue(target.check_password("StrongPass123!"))

View File

@@ -3,7 +3,7 @@ from decimal import Decimal
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth import get_user_model, password_validation, update_session_auth_hash
from django.contrib.auth.models import Permission
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.db.models import Sum
@@ -14,6 +14,7 @@ from django.utils import timezone
from django.utils.translation import gettext as _
from django.views import View
from django.views.generic import ListView, TemplateView
from django.core.exceptions import ValidationError
from .forms import (
ClaimDecisionForm,
@@ -377,19 +378,30 @@ class UserManagementView(LoginRequiredMixin, PermissionRequiredMixin, TemplateVi
users = User.objects.order_by("username")
rows = []
for user in users:
perms = {
"is_staff": user.is_staff,
"view": user.has_perm("claims.view_claim"),
"change": user.has_perm("claims.change_claim"),
"edit": user.has_perm("claims.edit_claim_details"),
"pay": user.has_perm("claims.mark_claim_paid"),
}
rows.append(
{
"user": user,
"permission_form": UserPermissionForm(
initial={
"user_id": user.id,
"is_staff": user.is_staff,
"grant_view": user.has_perm("claims.view_claim"),
"grant_change": user.has_perm("claims.change_claim"),
"grant_edit": user.has_perm("claims.edit_claim_details"),
"grant_pay": user.has_perm("claims.mark_claim_paid"),
"is_staff": perms["is_staff"],
"grant_view": perms["view"],
"grant_change": perms["change"],
"grant_edit": perms["edit"],
"grant_pay": perms["pay"],
"first_name": user.first_name,
"last_name": user.last_name,
"email": user.email,
}
),
"permission_flags": perms,
"delete_form": None
if user == self.request.user or user.is_superuser
else DeleteUserForm(initial={"user_id": user.id}),
@@ -397,6 +409,7 @@ class UserManagementView(LoginRequiredMixin, PermissionRequiredMixin, TemplateVi
)
context["user_rows"] = rows
context["create_form"] = kwargs.get("create_form") or UserManagementForm()
context["can_change_users"] = self.request.user.has_perm("auth.change_user")
return context
def post(self, request, *args, **kwargs):
@@ -429,11 +442,35 @@ class UserManagementView(LoginRequiredMixin, PermissionRequiredMixin, TemplateVi
form = UserPermissionForm(request.POST)
if form.is_valid():
user = get_object_or_404(User, pk=form.cleaned_data["user_id"])
if user == request.user and not form.cleaned_data["is_staff"]:
new_is_staff = form.cleaned_data["is_staff"]
if user == request.user and not new_is_staff:
messages.error(request, _("Du kan inte ta bort din egen staff-status."))
return redirect(request.path)
user.is_staff = form.cleaned_data["is_staff"]
user.save(update_fields=["is_staff"])
update_fields = set()
if user.is_staff != new_is_staff:
user.is_staff = new_is_staff
update_fields.add("is_staff")
for attr in ("first_name", "last_name", "email"):
new_value = form.cleaned_data.get(attr)
if new_value is None:
continue
if getattr(user, attr) != new_value:
setattr(user, attr, new_value)
update_fields.add(attr)
new_password = form.cleaned_data.get("new_password1")
if new_password:
try:
password_validation.validate_password(new_password, user)
except ValidationError as exc:
for error in exc:
messages.error(request, error)
return redirect(request.path)
user.set_password(new_password)
update_fields.add("password")
if update_fields:
user.save(update_fields=list(update_fields))
if new_password and user == request.user:
update_session_auth_hash(request, user)
self._set_perm(user, "claims.view_claim", form.cleaned_data["grant_view"])
self._set_perm(user, "claims.change_claim", form.cleaned_data["grant_change"])
self._set_perm(user, "claims.edit_claim_details", form.cleaned_data["grant_edit"])

Binary file not shown.

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: claims-system 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-11 19:43+0000\n"
"POT-Creation-Date: 2025-11-11 20:06+0000\n"
"PO-Revision-Date: 2025-11-08 23:40+0100\n"
"Last-Translator: ChatGPT <noreply@example.com>\n"
"Language-Team: English\n"
@@ -18,7 +18,7 @@ msgid "Namn"
msgstr "Name"
#: claims/forms.py:23 claims/forms.py:101 claims/forms.py:112
#: claims/templates/claims/dashboard.html:176
#: claims/forms.py:177 claims/templates/claims/dashboard.html:176
#: claims/templates/claims/dashboard.html:526
msgid "E-post"
msgstr "Email"
@@ -82,15 +82,15 @@ msgstr "A comment is required when you reject an expense."
msgid "Användarnamn"
msgstr "Username"
#: claims/forms.py:113
#: claims/forms.py:113 claims/forms.py:166
msgid "Förnamn"
msgstr "First name"
#: claims/forms.py:114
#: claims/forms.py:114 claims/forms.py:172
msgid "Efternamn"
msgstr "Last name"
#: claims/forms.py:115
#: claims/forms.py:115 claims/templates/claims/user_management.html:234
msgid "Lösenord"
msgstr "Password"
@@ -122,35 +122,47 @@ msgstr "Allow marking payments"
msgid "Användarnamnet är upptaget."
msgstr "That username is already taken."
#: claims/forms.py:140
#: claims/forms.py:140 claims/forms.py:197
msgid "Lösenorden matchar inte."
msgstr "Passwords do not match."
#: claims/forms.py:158 claims/templates/claims/user_management.html:114
#: claims/templates/claims/user_management.html:184
#: claims/forms.py:158 claims/templates/claims/user_management.html:124
#: claims/templates/claims/user_management.html:257
msgid "Admin/staff"
msgstr "Admin/staff"
#: claims/forms.py:159 claims/templates/claims/user_management.html:115
#: claims/templates/claims/user_management.html:188
#: claims/forms.py:159 claims/templates/claims/user_management.html:127
#: claims/templates/claims/user_management.html:261
msgid "Får se utlägg"
msgstr "May view claims"
#: claims/forms.py:160 claims/templates/claims/user_management.html:116
#: claims/templates/claims/user_management.html:192
#: claims/forms.py:160 claims/templates/claims/user_management.html:130
#: claims/templates/claims/user_management.html:265
msgid "Får besluta utlägg"
msgstr "May decide claims"
#: claims/forms.py:161 claims/templates/claims/user_management.html:117
#: claims/templates/claims/user_management.html:196
#: claims/forms.py:161 claims/templates/claims/user_management.html:133
#: claims/templates/claims/user_management.html:269
msgid "Får redigera utlägg"
msgstr "May edit claims"
#: claims/forms.py:162 claims/templates/claims/user_management.html:118
#: claims/templates/claims/user_management.html:200
#: claims/forms.py:162 claims/templates/claims/user_management.html:136
#: claims/templates/claims/user_management.html:273
msgid "Får markera betalningar"
msgstr "May mark payments"
#: claims/forms.py:182
#, fuzzy
#| msgid "Lösenord"
msgid "Nytt lösenord"
msgstr "Password"
#: claims/forms.py:187
#, fuzzy
#| msgid "Bekräfta lösenord"
msgid "Bekräfta nytt lösenord"
msgstr "Confirm password"
#: claims/models.py:30 claims/templates/claims/dashboard.html:342
msgid "Approved"
msgstr "Approved"
@@ -538,7 +550,7 @@ msgid "Redigera utlägg"
msgstr "Edit claim"
#: claims/templates/claims/dashboard.html:513
#: claims/templates/claims/user_management.html:174
#: claims/templates/claims/user_management.html:199
msgid "Stäng"
msgstr "Close"
@@ -547,7 +559,7 @@ msgid "Ingen"
msgstr "None"
#: claims/templates/claims/dashboard.html:563
#: claims/templates/claims/user_management.html:207
#: claims/templates/claims/user_management.html:281
msgid "Avbryt"
msgstr "Cancel"
@@ -851,45 +863,62 @@ msgstr "No name"
msgid "Ingen e-post"
msgstr "No email"
#: claims/templates/claims/user_management.html:112
#: claims/templates/claims/user_management.html:114
msgid "Redigera användare"
msgstr "Edit user"
#: claims/templates/claims/user_management.html:121
#: claims/templates/claims/user_management.html:254
msgid "Behörigheter"
msgstr "Permissions"
#: claims/templates/claims/user_management.html:123
#: claims/templates/claims/user_management.html:168
#: claims/templates/claims/user_management.html:139
msgid "Inga behörigheter tilldelade"
msgstr "No permissions assigned"
#: claims/templates/claims/user_management.html:146
#: claims/templates/claims/user_management.html:193
msgid "Redigera behörigheter"
msgstr "Edit permissions"
#: claims/templates/claims/user_management.html:127
#: claims/templates/claims/user_management.html:151
msgid "Ta bort konto"
msgstr "Remove account"
#: claims/templates/claims/user_management.html:129
#: claims/templates/claims/user_management.html:153
msgid "Åtgärden går inte att ångra. Användaren förlorar omedelbart åtkomst."
msgstr "This action cannot be undone. The user loses access immediately."
#: claims/templates/claims/user_management.html:130
#: claims/templates/claims/user_management.html:154
#, python-format
msgid "Ta bort %(user.username)s?"
msgstr "Delete %(user.username)s?"
#: claims/templates/claims/user_management.html:135
#: claims/templates/claims/user_management.html:159
msgid "Ta bort användare"
msgstr "Delete user"
#: claims/templates/claims/user_management.html:139
#: claims/templates/claims/user_management.html:163
msgid "Kan inte tas bort (antingen du själv eller superuser)."
msgstr "Cannot be removed (either yourself or a superuser)."
#: claims/templates/claims/user_management.html:147
#: claims/templates/claims/user_management.html:171
msgid "Inga användare upplagda."
msgstr "No users yet."
#: claims/templates/claims/user_management.html:148
#: claims/templates/claims/user_management.html:172
msgid "Skapa det första kontot via formuläret ovan."
msgstr "Create the first account using the form above."
#: claims/templates/claims/user_management.html:210
#: claims/templates/claims/user_management.html:208
msgid "Kontaktuppgifter"
msgstr "Contact details"
#: claims/templates/claims/user_management.html:251
msgid "Lämna fälten tomma för att behålla nuvarande lösenord."
msgstr "Leave the fields blank to keep the current password."
#: claims/templates/claims/user_management.html:284
msgid "Spara behörigheter"
msgstr "Save permissions"
@@ -912,125 +941,123 @@ msgstr ""
msgid "Filens innehåll matchar inte förväntat format."
msgstr ""
#: claims/views.py:127
#: claims/views.py:128
#, python-brace-format
msgid "{} utlägg skickade in."
msgstr ""
#: claims/views.py:130
#: claims/views.py:131
msgid "Inga utlägg kunde sparas. Fyll i minst en rad."
msgstr ""
#: claims/views.py:132
#: claims/views.py:133
msgid "Kunde inte spara utläggen. Kontrollera formuläret."
msgstr ""
#: claims/views.py:188
#, fuzzy
#| msgid "Ge behörighet att besluta utlägg"
#: claims/views.py:189
msgid "Du har inte behörighet att uppdatera utlägg."
msgstr "Allow deciding claims"
msgstr "You do not have permission to update claims."
#: claims/views.py:202
#: claims/views.py:203
msgid "Utlägget är redan markerat som betalt och kan inte ändras."
msgstr "This claim is already marked as paid and cannot be changed."
#: claims/views.py:209
#: claims/views.py:210
#, python-format
msgid "%(claim)s markerades som godkänd."
msgstr "%(claim)s was marked as approved."
#: claims/views.py:213
#: claims/views.py:214
#, python-format
msgid "%(claim)s markerades som nekad."
msgstr "%(claim)s was marked as rejected."
#: claims/views.py:217
#: claims/views.py:218
#, python-format
msgid "%(claim)s återställdes till väntande status."
msgstr "%(claim)s was reset to pending status."
#: claims/views.py:237
#: claims/views.py:238
msgid "Betalningshantering är inte aktiverad."
msgstr "Payment handling is not enabled."
#: claims/views.py:240
#: claims/views.py:241
msgid "Du har inte behörighet att markera betalningar i systemet."
msgstr "You do not have permission to mark payments in the system."
#: claims/views.py:245
#: claims/views.py:246
msgid "Endast godkända utlägg kan markeras som betalda."
msgstr "Only approved claims can be marked as paid."
#: claims/views.py:248
#: claims/views.py:249
msgid "Detta utlägg är redan markerat som betalt."
msgstr "This claim is already marked as paid."
#: claims/views.py:259
#: claims/views.py:260
#, python-format
msgid "%(claim)s markerades som betald."
msgstr "%(claim)s was marked as paid."
#: claims/views.py:264
#: claims/views.py:265
msgid "Du har inte behörighet att redigera utlägg."
msgstr "You do not have permission to edit claims."
#: claims/views.py:268
#: claims/views.py:269
msgid "Endast väntande utlägg kan redigeras via panelen."
msgstr "Only pending claims can be edited via the panel."
#: claims/views.py:297
#: claims/views.py:298
#, python-format
msgid "Följande fält uppdaterades: %(fields)s"
msgstr "The following fields were updated: %(fields)s"
#: claims/views.py:303
#: claims/views.py:304
msgid "Informationen uppdaterades."
msgstr "Information updated."
#: claims/views.py:305
#: claims/views.py:306
msgid "Inga förändringar att spara."
msgstr "No changes to save."
#: claims/views.py:371
#: claims/views.py:372
msgid "Du saknar behörighet för åtgärden."
msgstr "You do not have permission to perform this action."
#: claims/views.py:422
#: claims/views.py:435
#, python-format
msgid "Användaren %(user)s skapades."
msgstr ""
#: claims/views.py:433
#: claims/views.py:447
msgid "Du kan inte ta bort din egen staff-status."
msgstr ""
#: claims/views.py:441
#: claims/views.py:478
#, python-format
msgid "Behörigheter uppdaterades för %(user)s."
msgstr ""
#: claims/views.py:443
#: claims/views.py:480
#, fuzzy
#| msgid "Justera behörigheter"
msgid "Kunde inte uppdatera behörigheter."
msgstr "Adjust permissions"
#: claims/views.py:453
#: claims/views.py:490
msgid "Du kan inte ta bort ditt eget konto."
msgstr ""
#: claims/views.py:455
#: claims/views.py:492
msgid "Du kan inte ta bort en superuser via detta gränssnitt."
msgstr ""
#: claims/views.py:458
#: claims/views.py:495
#, fuzzy
#| msgid "Användare"
msgid "Användaren togs bort."
msgstr "Users"
#: claims/views.py:461
#: claims/views.py:498
msgid "Okänd åtgärd."
msgstr ""

Binary file not shown.

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-11 19:43+0000\n"
"POT-Creation-Date: 2025-11-11 20:06+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -24,7 +24,7 @@ msgid "Namn"
msgstr ""
#: claims/forms.py:23 claims/forms.py:101 claims/forms.py:112
#: claims/templates/claims/dashboard.html:176
#: claims/forms.py:177 claims/templates/claims/dashboard.html:176
#: claims/templates/claims/dashboard.html:526
msgid "E-post"
msgstr ""
@@ -88,15 +88,15 @@ msgstr ""
msgid "Användarnamn"
msgstr ""
#: claims/forms.py:113
#: claims/forms.py:113 claims/forms.py:166
msgid "Förnamn"
msgstr ""
#: claims/forms.py:114
#: claims/forms.py:114 claims/forms.py:172
msgid "Efternamn"
msgstr ""
#: claims/forms.py:115
#: claims/forms.py:115 claims/templates/claims/user_management.html:234
msgid "Lösenord"
msgstr ""
@@ -128,35 +128,43 @@ msgstr ""
msgid "Användarnamnet är upptaget."
msgstr ""
#: claims/forms.py:140
#: claims/forms.py:140 claims/forms.py:197
msgid "Lösenorden matchar inte."
msgstr ""
#: claims/forms.py:158 claims/templates/claims/user_management.html:114
#: claims/templates/claims/user_management.html:184
#: claims/forms.py:158 claims/templates/claims/user_management.html:124
#: claims/templates/claims/user_management.html:257
msgid "Admin/staff"
msgstr ""
#: claims/forms.py:159 claims/templates/claims/user_management.html:115
#: claims/templates/claims/user_management.html:188
#: claims/forms.py:159 claims/templates/claims/user_management.html:127
#: claims/templates/claims/user_management.html:261
msgid "Får se utlägg"
msgstr ""
#: claims/forms.py:160 claims/templates/claims/user_management.html:116
#: claims/templates/claims/user_management.html:192
#: claims/forms.py:160 claims/templates/claims/user_management.html:130
#: claims/templates/claims/user_management.html:265
msgid "Får besluta utlägg"
msgstr ""
#: claims/forms.py:161 claims/templates/claims/user_management.html:117
#: claims/templates/claims/user_management.html:196
#: claims/forms.py:161 claims/templates/claims/user_management.html:133
#: claims/templates/claims/user_management.html:269
msgid "Får redigera utlägg"
msgstr ""
#: claims/forms.py:162 claims/templates/claims/user_management.html:118
#: claims/templates/claims/user_management.html:200
#: claims/forms.py:162 claims/templates/claims/user_management.html:136
#: claims/templates/claims/user_management.html:273
msgid "Får markera betalningar"
msgstr ""
#: claims/forms.py:182
msgid "Nytt lösenord"
msgstr ""
#: claims/forms.py:187
msgid "Bekräfta nytt lösenord"
msgstr ""
#: claims/models.py:30 claims/templates/claims/dashboard.html:342
msgid "Approved"
msgstr "Godkänd"
@@ -536,7 +544,7 @@ msgid "Redigera utlägg"
msgstr ""
#: claims/templates/claims/dashboard.html:513
#: claims/templates/claims/user_management.html:174
#: claims/templates/claims/user_management.html:199
msgid "Stäng"
msgstr ""
@@ -545,7 +553,7 @@ msgid "Ingen"
msgstr ""
#: claims/templates/claims/dashboard.html:563
#: claims/templates/claims/user_management.html:207
#: claims/templates/claims/user_management.html:281
msgid "Avbryt"
msgstr ""
@@ -823,45 +831,62 @@ msgstr ""
msgid "Ingen e-post"
msgstr "Ingen e-post"
#: claims/templates/claims/user_management.html:112
#: claims/templates/claims/user_management.html:114
msgid "Redigera användare"
msgstr "Redigera användare"
#: claims/templates/claims/user_management.html:121
#: claims/templates/claims/user_management.html:254
msgid "Behörigheter"
msgstr "Behörigheter"
#: claims/templates/claims/user_management.html:123
#: claims/templates/claims/user_management.html:168
#: claims/templates/claims/user_management.html:139
msgid "Inga behörigheter tilldelade"
msgstr "Inga behörigheter tilldelade"
#: claims/templates/claims/user_management.html:146
#: claims/templates/claims/user_management.html:193
msgid "Redigera behörigheter"
msgstr "Redigera behörigheter"
#: claims/templates/claims/user_management.html:127
#: claims/templates/claims/user_management.html:151
msgid "Ta bort konto"
msgstr "Ta bort konto"
#: claims/templates/claims/user_management.html:129
#: claims/templates/claims/user_management.html:153
msgid "Åtgärden går inte att ångra. Användaren förlorar omedelbart åtkomst."
msgstr "Åtgärden går inte att ångra. Användaren förlorar omedelbart åtkomst."
#: claims/templates/claims/user_management.html:130
#: claims/templates/claims/user_management.html:154
#, python-format
msgid "Ta bort %(user.username)s?"
msgstr "Ta bort %(user.username)s?"
#: claims/templates/claims/user_management.html:135
#: claims/templates/claims/user_management.html:159
msgid "Ta bort användare"
msgstr "Ta bort användare"
#: claims/templates/claims/user_management.html:139
#: claims/templates/claims/user_management.html:163
msgid "Kan inte tas bort (antingen du själv eller superuser)."
msgstr "Kan inte tas bort (antingen du själv eller superuser)."
#: claims/templates/claims/user_management.html:147
#: claims/templates/claims/user_management.html:171
msgid "Inga användare upplagda."
msgstr "Inga användare upplagda."
#: claims/templates/claims/user_management.html:148
#: claims/templates/claims/user_management.html:172
msgid "Skapa det första kontot via formuläret ovan."
msgstr "Skapa det första kontot via formuläret ovan."
#: claims/templates/claims/user_management.html:210
#: claims/templates/claims/user_management.html:208
msgid "Kontaktuppgifter"
msgstr "Kontaktuppgifter"
#: claims/templates/claims/user_management.html:251
msgid "Lämna fälten tomma för att behålla nuvarande lösenord."
msgstr "Lämna fälten tomma för att behålla nuvarande lösenord."
#: claims/templates/claims/user_management.html:284
msgid "Spara behörigheter"
msgstr "Spara behörigheter"
@@ -884,119 +909,119 @@ msgstr ""
msgid "Filens innehåll matchar inte förväntat format."
msgstr ""
#: claims/views.py:127
#: claims/views.py:128
#, python-brace-format
msgid "{} utlägg skickade in."
msgstr ""
#: claims/views.py:130
#: claims/views.py:131
msgid "Inga utlägg kunde sparas. Fyll i minst en rad."
msgstr ""
#: claims/views.py:132
#: claims/views.py:133
msgid "Kunde inte spara utläggen. Kontrollera formuläret."
msgstr ""
#: claims/views.py:188
#: claims/views.py:189
msgid "Du har inte behörighet att uppdatera utlägg."
msgstr ""
msgstr "Du har inte behörighet att uppdatera utlägg."
#: claims/views.py:202
#: claims/views.py:203
msgid "Utlägget är redan markerat som betalt och kan inte ändras."
msgstr ""
#: claims/views.py:209
#: claims/views.py:210
#, python-format
msgid "%(claim)s markerades som godkänd."
msgstr ""
#: claims/views.py:213
#: claims/views.py:214
#, python-format
msgid "%(claim)s markerades som nekad."
msgstr ""
#: claims/views.py:217
#: claims/views.py:218
#, python-format
msgid "%(claim)s återställdes till väntande status."
msgstr ""
#: claims/views.py:237
#: claims/views.py:238
msgid "Betalningshantering är inte aktiverad."
msgstr ""
#: claims/views.py:240
#: claims/views.py:241
msgid "Du har inte behörighet att markera betalningar i systemet."
msgstr ""
#: claims/views.py:245
#: claims/views.py:246
msgid "Endast godkända utlägg kan markeras som betalda."
msgstr ""
#: claims/views.py:248
#: claims/views.py:249
msgid "Detta utlägg är redan markerat som betalt."
msgstr "Detta utlägg är redan markerat som betalt."
#: claims/views.py:259
#: claims/views.py:260
#, python-format
msgid "%(claim)s markerades som betald."
msgstr "%(claim)s markerades som betald."
#: claims/views.py:264
#: claims/views.py:265
msgid "Du har inte behörighet att redigera utlägg."
msgstr ""
#: claims/views.py:268
#: claims/views.py:269
msgid "Endast väntande utlägg kan redigeras via panelen."
msgstr "Endast väntande utlägg kan redigeras via panelen."
#: claims/views.py:297
#: claims/views.py:298
#, python-format
msgid "Följande fält uppdaterades: %(fields)s"
msgstr "Följande fält uppdaterades: %(fields)s"
#: claims/views.py:303
#: claims/views.py:304
msgid "Informationen uppdaterades."
msgstr "Informationen uppdaterades."
#: claims/views.py:305
#: claims/views.py:306
msgid "Inga förändringar att spara."
msgstr "Inga förändringar att spara."
#: claims/views.py:371
#: claims/views.py:372
msgid "Du saknar behörighet för åtgärden."
msgstr "Du saknar behörighet för åtgärden."
#: claims/views.py:422
#: claims/views.py:435
#, python-format
msgid "Användaren %(user)s skapades."
msgstr ""
#: claims/views.py:433
#: claims/views.py:447
msgid "Du kan inte ta bort din egen staff-status."
msgstr ""
#: claims/views.py:441
#: claims/views.py:478
#, python-format
msgid "Behörigheter uppdaterades för %(user)s."
msgstr ""
#: claims/views.py:443
#: claims/views.py:480
msgid "Kunde inte uppdatera behörigheter."
msgstr ""
#: claims/views.py:453
#: claims/views.py:490
msgid "Du kan inte ta bort ditt eget konto."
msgstr ""
#: claims/views.py:455
#: claims/views.py:492
msgid "Du kan inte ta bort en superuser via detta gränssnitt."
msgstr ""
#: claims/views.py:458
#: claims/views.py:495
msgid "Användaren togs bort."
msgstr ""
#: claims/views.py:461
#: claims/views.py:498
msgid "Okänd åtgärd."
msgstr ""