Merge branch '3-user-subject-relations' into 'master'
Added base for user-subject relations See merge request JustScreaMy/facturio!4
This commit is contained in:
commit
a6bac23b9f
13 changed files with 185 additions and 39 deletions
|
@ -1,6 +1,13 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import User
|
||||
from . import models
|
||||
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
@admin.register(models.User)
|
||||
class UserAdmin(BaseUserAdmin):
|
||||
fieldsets = (
|
||||
*BaseUserAdmin.fieldsets,
|
||||
(_("Subjects"), {"fields": ("subjects",)})
|
||||
)
|
||||
|
|
18
accounts/migrations/0003_user_subjects.py
Normal file
18
accounts/migrations/0003_user_subjects.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("accounts", "0002_alter_user_email_alter_user_first_name_and_more"),
|
||||
("subjects", "0003_alter_subject_options"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="subjects",
|
||||
field=models.ManyToManyField(to="subjects.subject"),
|
||||
),
|
||||
]
|
18
accounts/migrations/0004_alter_user_subjects.py
Normal file
18
accounts/migrations/0004_alter_user_subjects.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.1 on 2024-01-29 21:19
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("accounts", "0003_user_subjects"),
|
||||
("subjects", "0003_alter_subject_options"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="subjects",
|
||||
field=models.ManyToManyField(blank=True, to="subjects.subject"),
|
||||
),
|
||||
]
|
|
@ -2,6 +2,8 @@ from django.contrib.auth.models import AbstractUser
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from subjects.models import Subject
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
REQUIRED_FIELDS = ["email", "first_name", "last_name"]
|
||||
|
@ -10,5 +12,7 @@ class User(AbstractUser):
|
|||
last_name = models.CharField(_("last name"), max_length=150)
|
||||
email = models.EmailField(_("email address"))
|
||||
|
||||
subjects = models.ManyToManyField(Subject, blank=True)
|
||||
|
||||
class Meta(AbstractUser.Meta):
|
||||
pass
|
||||
...
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
{% block title %}{% trans "About Me" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2 class="mb-4">{% trans "About Me" %}</h2>
|
||||
<div class="card">
|
||||
<h2 class="mb-2">{% trans "About Me" %}</h2>
|
||||
<div class="card mb-2">
|
||||
<h5 class="card-header">
|
||||
{% blocktrans trimmed with firstname=request.user.first_name lastname=request.user.last_name %}Welcome,
|
||||
{{ firstname }} {{ lastname }}!{% endblocktrans %}
|
||||
|
@ -19,4 +19,14 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% if request.user.subjects.exists %}
|
||||
<div class="card mb-2">
|
||||
<h5 class="card-header">{% trans "Linked subjects" %}</h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
{% for subject in request.user.subjects.all %}
|
||||
<li class="list-group-item">{{ subject.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-01-29 20:46+0000\n"
|
||||
"POT-Creation-Date: 2024-02-01 20:43+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"
|
||||
|
@ -18,25 +18,31 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
|
||||
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
||||
|
||||
#: accounts/admin.py:12 subjects/models.py:9
|
||||
#: subjects/templates/subjects/index.html:4 templates/facturio/base.html:20
|
||||
msgid "Subjects"
|
||||
msgstr "Subjekty"
|
||||
|
||||
#: accounts/forms.py:17 accounts/templates/account/login.html:6
|
||||
#: templates/facturio/base.html:39
|
||||
#: templates/facturio/base.html:42
|
||||
msgid "Login"
|
||||
msgstr "Přihlásit se"
|
||||
|
||||
#: accounts/forms.py:30 accounts/templates/account/register.html:6
|
||||
#: templates/facturio/base.html:42
|
||||
#: templates/facturio/base.html:45
|
||||
msgid "Register"
|
||||
msgstr "Registrovat se"
|
||||
|
||||
#: accounts/models.py:9
|
||||
#: accounts/models.py:11
|
||||
msgid "first name"
|
||||
msgstr "křestní jméno"
|
||||
|
||||
#: accounts/models.py:10
|
||||
#: accounts/models.py:12
|
||||
msgid "last name"
|
||||
msgstr "přijmení"
|
||||
|
||||
#: accounts/models.py:11
|
||||
#: accounts/models.py:13
|
||||
msgid "email address"
|
||||
msgstr "emailová adresa"
|
||||
|
||||
|
@ -59,6 +65,10 @@ msgstr "Uživatelské jméno: %(username)s"
|
|||
msgid "Email: %(email)s"
|
||||
msgstr "Email: %(email)s"
|
||||
|
||||
#: accounts/templates/account/me.html:24
|
||||
msgid "Linked subjects"
|
||||
msgstr "Propojené Subjekty"
|
||||
|
||||
#: facturio/settings.py:109
|
||||
msgid "English"
|
||||
msgstr "Angličtina"
|
||||
|
@ -92,11 +102,6 @@ msgstr "Vytvořit"
|
|||
msgid "Subject"
|
||||
msgstr "Subjekt"
|
||||
|
||||
#: subjects/models.py:9 subjects/templates/subjects/index.html:4
|
||||
#: templates/facturio/base.html:19
|
||||
msgid "Subjects"
|
||||
msgstr "Subjekty"
|
||||
|
||||
#: subjects/models.py:18 subjects/templates/subjects/index.html:12
|
||||
msgid "Name"
|
||||
msgstr "Jméno"
|
||||
|
@ -129,14 +134,26 @@ msgstr "Vytvořit Subjekty"
|
|||
msgid "Add new"
|
||||
msgstr "Přidat nový"
|
||||
|
||||
#: subjects/templates/subjects/index.html:18
|
||||
msgid "Connect"
|
||||
msgstr "Propojit"
|
||||
|
||||
#: subjects/templates/subjects/index.html:35
|
||||
msgid "Link"
|
||||
msgstr "Propojit"
|
||||
|
||||
#: subjects/templates/subjects/index.html:38
|
||||
msgid "Unlink"
|
||||
msgstr "Odpojit"
|
||||
|
||||
#: templates/facturio/base.html:8 templates/facturio/index.html:4
|
||||
msgid "App"
|
||||
msgstr "Aplikace"
|
||||
|
||||
#: templates/facturio/base.html:31
|
||||
#: templates/facturio/base.html:34
|
||||
msgid "Profile"
|
||||
msgstr "Profil"
|
||||
|
||||
#: templates/facturio/base.html:34
|
||||
#: templates/facturio/base.html:37
|
||||
msgid "Logout"
|
||||
msgstr "Odhlásit se"
|
||||
|
|
16
subjects/migrations/0003_alter_subject_options.py
Normal file
16
subjects/migrations/0003_alter_subject_options.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("subjects", "0002_alter_subject_city_alter_subject_city_part_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="subject",
|
||||
options={"verbose_name": "Subject", "verbose_name_plural": "Subjects"},
|
||||
),
|
||||
]
|
|
@ -50,3 +50,6 @@ class Subject(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_linked_users(self) -> list[int]:
|
||||
return list(self.user_set.values_list("id", flat=True))
|
||||
|
|
|
@ -15,19 +15,32 @@
|
|||
<th>{% trans "Zip Code" %}</th>
|
||||
<th>{% trans "City" %}</th>
|
||||
<th>{% trans "City part" %}</th>
|
||||
<th>{% trans "Connect" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for subject in subjects %}
|
||||
<tr>
|
||||
<td>{{ subject.id }}</td>
|
||||
<td>{{ subject.name }}</td>
|
||||
<td>{{ subject.vat_id }}</td>
|
||||
<td>{{ subject.street }}</td>
|
||||
<td>{{ subject.zip_code }}</td>
|
||||
<td>{{ subject.city }}</td>
|
||||
<td>{{ subject.city_part }}</td>
|
||||
</tr>
|
||||
{# FIXME: in the future, or when this create problems, find a better way#}
|
||||
{% with linked_users=subject.get_linked_users %}
|
||||
<tr>
|
||||
<td>{{ subject.id }}</td>
|
||||
<td>{{ subject.name }}</td>
|
||||
<td>{{ subject.vat_id }}</td>
|
||||
<td>{{ subject.street }}</td>
|
||||
<td>{{ subject.zip_code }}</td>
|
||||
<td>{{ subject.city }}</td>
|
||||
<td>{{ subject.city_part }}</td>
|
||||
<td>
|
||||
{% if request.user.id not in linked_users %}
|
||||
<a href="{% url "subjects:link" subject_id=subject.id %}" class="btn btn-primary"
|
||||
role="button">{% trans "Link" %}</a>
|
||||
{% else %}
|
||||
<a href="{% url "subjects:unlink" subject_id=subject.id %}" class="btn btn-danger"
|
||||
role="button">{% trans "Unlink" %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -6,5 +6,7 @@ app_name = "subjects"
|
|||
|
||||
urlpatterns = [
|
||||
path("", views.main_page, name="list"),
|
||||
path("new/", views.create_subject, name="create")
|
||||
path("new/", views.create_subject, name="create"),
|
||||
path("link/<int:subject_id>", views.link_subject, name="link"),
|
||||
path("unlink/<int:subject_id>", views.unlink_subject, name="unlink")
|
||||
]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from ares_util.ares import call_ares
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import render, redirect
|
||||
from django.urls import reverse
|
||||
|
@ -10,11 +11,13 @@ def build_address(street: str, zip_code: int | str, city: str, city_part: str) -
|
|||
return f"{street}, {zip_code}, {city} - {city_part}"
|
||||
|
||||
|
||||
@login_required
|
||||
def main_page(req: HttpRequest) -> HttpResponse:
|
||||
subjects = models.Subject.objects.all()
|
||||
return render(req, "subjects/index.html", dict(subjects=subjects))
|
||||
|
||||
|
||||
@login_required
|
||||
def create_subject(req: HttpRequest) -> HttpResponse:
|
||||
if req.method == "POST":
|
||||
form = forms.CreateSubjectForm(data=req.POST)
|
||||
|
@ -45,3 +48,17 @@ def create_subject(req: HttpRequest) -> HttpResponse:
|
|||
return render(req, "subjects/create.html", dict(form=form))
|
||||
|
||||
return HttpResponse(status=405)
|
||||
|
||||
|
||||
@login_required
|
||||
def link_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
||||
subject = models.Subject.objects.get(pk=subject_id)
|
||||
subject.user_set.add(request.user)
|
||||
return redirect(reverse("subjects:list"))
|
||||
|
||||
|
||||
@login_required
|
||||
def unlink_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
||||
subject = models.Subject.objects.get(pk=subject_id)
|
||||
subject.user_set.remove(request.user)
|
||||
return redirect(reverse("subjects:list"))
|
||||
|
|
|
@ -13,16 +13,19 @@
|
|||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="{% url "main-page" %}">Facturio</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "subjects:list" %}">{% trans "Subjects" %}</a>
|
||||
</li>
|
||||
{#<li class="nav-item">#}
|
||||
{# <a class="nav-link" href="#">Item 2</a>#}
|
||||
{#</li>#}
|
||||
</ul>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "subjects:list" %}">{% trans "Subjects" %}</a>
|
||||
</li>
|
||||
{#<li class="nav-item">#}
|
||||
{# <a class="nav-link" href="#">Item 2</a>#}
|
||||
{#</li>#}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="collapse navbar-collapse justify-content-end">
|
||||
<ul class="navbar-nav">
|
||||
|
|
18
utils/start.sh
Executable file
18
utils/start.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
#set -x
|
||||
|
||||
if [[ ! -f "manage.py" ]]; then
|
||||
echo 'Control `manage.py` is not in current directory!'
|
||||
echo 'Please, launch this script from the root directory'
|
||||
echo 'Example: `./utils/start.sh`'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Compiling messages!"
|
||||
./manage.py compilemessages >/dev/null
|
||||
|
||||
echo "Migrating"
|
||||
./manage.py migrate >/dev/null
|
Reference in a new issue