Compare commits
8 Commits
a47ffa0b0b
...
e5395b6b19
| Author | SHA1 | Date | |
|---|---|---|---|
| e5395b6b19 | |||
| cfafc0f226 | |||
| 5a0c724591 | |||
| 6ea6cd7132 | |||
| fe3c3cea16 | |||
| e228c74402 | |||
| f49f6216ef | |||
| 49c26d96ad |
@ -39,6 +39,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'common',
|
||||||
'member',
|
'member',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
0
common/__init__.py
Normal file
0
common/__init__.py
Normal file
3
common/admin.py
Normal file
3
common/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
common/apps.py
Normal file
6
common/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CommonConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'common'
|
||||||
0
common/migrations/__init__.py
Normal file
0
common/migrations/__init__.py
Normal file
3
common/models.py
Normal file
3
common/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
0
common/templatetags/__init__.py
Normal file
0
common/templatetags/__init__.py
Normal file
22
common/templatetags/svg.py
Normal file
22
common/templatetags/svg.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# common/templatetags/svg.py
|
||||||
|
from django import template
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.contrib.staticfiles import finders
|
||||||
|
import re
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def inline_svg(path, css_class='', style=''):
|
||||||
|
svg_file_path = finders.find(path)
|
||||||
|
if not svg_file_path:
|
||||||
|
return f"<!-- SVG '{path}' not found -->"
|
||||||
|
with open(svg_file_path, 'r', encoding='utf-8') as file:
|
||||||
|
svg_content=mark_safe(file.read())
|
||||||
|
if css_class:
|
||||||
|
svg_content = re.sub(r'<svg([^>]+)?', rf'<svg\1 class="{css_class}"', svg_content, count=1)
|
||||||
|
if style:
|
||||||
|
svg_content = re.sub(r'<svg([^>]+)?', rf'<svg\1 style="{style}"', svg_content, count=1)
|
||||||
|
|
||||||
|
return mark_safe(svg_content)
|
||||||
|
|
||||||
3
common/tests.py
Normal file
3
common/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
common/views.py
Normal file
3
common/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
12
member/forms.py
Normal file
12
member/forms.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# forms.py
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from .models import Person
|
||||||
|
|
||||||
|
class PersonForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Person
|
||||||
|
fields = ['vorname', 'nachname', 'geburtsdatum', 'aktiv']
|
||||||
|
widgets = {
|
||||||
|
'geburtsdatum': forms.DateInput(attrs={'type': 'date'}),
|
||||||
|
}
|
||||||
3
member/static/icons/heroicons/pencil.svg
Normal file
3
member/static/icons/heroicons/pencil.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 362 B |
5
member/static/icons/heroicons/plus.svg
Normal file
5
member/static/icons/heroicons/plus.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!-- plus.svg -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M12 4v16m8-8H4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 222 B |
3
member/static/icons/uxwing/check.svg
Normal file
3
member/static/icons/uxwing/check.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 122.88" style="enable-background:new 0 0 122.88 122.88" xml:space="preserve"><style type="text/css"><![CDATA[
|
||||||
|
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#3AAF3C !important;}
|
||||||
|
]]></style><g><path class="st0" fill="#3AAF3C" d="M61.44,0c33.93,0,61.44,27.51,61.44,61.44c0,33.93-27.51,61.44-61.44,61.44C27.51,122.88,0,95.37,0,61.44 C0,27.51,27.51,0,61.44,0L61.44,0L61.44,0z M39.48,56.79c4.6,2.65,7.59,4.85,11.16,8.78c9.24-14.88,19.28-23.12,32.32-34.83 l1.28-0.49h14.28C79.38,51.51,64.53,69.04,51.24,94.68c-6.92-14.79-13.09-25-26.88-34.47L39.48,56.79L39.48,56.79z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 757 B |
@ -129,3 +129,48 @@ body {
|
|||||||
background-color: #d63031;
|
background-color: #d63031;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.icon {
|
||||||
|
filter: invert(90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.icon {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
display: grid;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #f1f1f1;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--highlight);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #ffd27f;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,9 +5,11 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{ mymember.vorname }} {{ mymember.nachname }}</h1>
|
<div class="member-table">
|
||||||
|
<h1>{{ mymember.vorname }} {{ mymember.nachname }}</h1>
|
||||||
|
|
||||||
<p>Geburtsdatum: {{ mymember.geburtsdatum }}</p>
|
<p>Geburtsdatum: {{ mymember.geburtsdatum }}</p>
|
||||||
|
|
||||||
<p>Back to <a href="/members">Members</a></p>
|
<p>Back to <a href="/members">Members</a></p>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
{% extends "master.html" %}
|
{% extends "master.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load svg %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
List of all persons
|
List of all persons
|
||||||
@ -7,13 +9,25 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="members-table">
|
<div class="members-table">
|
||||||
<h3>Members</h3>
|
<h3>Members</h3>
|
||||||
<ul>
|
<a href="{% url 'create' %}" class="button" title="Neues Mitglied"> <img src="{% static 'icons/heroicons/plus.svg' %}" alt="Neu" class="icon"> Neu</a>
|
||||||
{% for x in mymembers %}
|
<table>
|
||||||
<li><a href="details/{{x.id}}"> {{ x.vorname }} {{ x.nachname }}</a></li>
|
<thead>
|
||||||
{% empty %}
|
<tr>
|
||||||
<li>Keine Datensaetze gefunden</li>
|
<th>Name</th>
|
||||||
{% endfor %}
|
<th>Aktiv</th>
|
||||||
</ul>
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for x in mymembers %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'details' x.id %}"><img src="{% static 'icons/arrow-right.svg' %}" class="icon">{{ x.nachname }} {{ x.vorname}}</a> </td>
|
||||||
|
<td>{% if x.aktiv %}{% inline_svg 'icons/uxwing/check.svg' 'icon' %}{% endif %}</td>
|
||||||
|
<td><a href="{% url 'edit' x.id %}" title="Bearbeiten"><img src="{% static 'icons/heroicons/pencil.svg'%}" class="icon"></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
27
member/templates/person_form.html
Normal file
27
member/templates/person_form.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{% extends "master.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="members-table">
|
||||||
|
<h3>{{ action }} Person</h3>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{form.vorname.id_for_label}}">Vorname</label>
|
||||||
|
{{form.vorname}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{form.nachname.id_for_label}}">Nachname</label>
|
||||||
|
{{ form.nachname}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{form.geburtsdatum.id_for_label}}">Geburtsdatum</label>
|
||||||
|
{{ form.geburtsdatum}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{form.aktiv.id_for_label}}">Aktiv</label>
|
||||||
|
{{ form.aktiv}}
|
||||||
|
</div>
|
||||||
|
<button class="button" type="submit">Speichern</button>
|
||||||
|
<a href="{% url 'members' %}" class="button" style="background:#444;">Abbrechen</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -4,4 +4,6 @@ from . import views
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('members/', views.members, name='members'),
|
path('members/', views.members, name='members'),
|
||||||
path('members/details/<int:id>', views.details, name="details"),
|
path('members/details/<int:id>', views.details, name="details"),
|
||||||
|
path('members/create/', views.create, name="create"),
|
||||||
|
path('members/edit/<int:id>', views.edit, name="edit"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from .models import Person
|
from .models import Person
|
||||||
|
from .forms import PersonForm
|
||||||
|
|
||||||
def members(request):
|
def members(request):
|
||||||
mymembers=Person.objects.all().values()
|
mymembers=Person.objects.all().values()
|
||||||
@ -17,3 +19,24 @@ def details(request, id):
|
|||||||
'mymember': mymember
|
'mymember': mymember
|
||||||
}
|
}
|
||||||
return HttpResponse(template.render(context, request))
|
return HttpResponse(template.render(context, request))
|
||||||
|
|
||||||
|
def create(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
form = PersonForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect('members')
|
||||||
|
else:
|
||||||
|
form = PersonForm()
|
||||||
|
return render(request, "person_form.html", {'form': form, 'action': "Neu anlegen"})
|
||||||
|
|
||||||
|
def edit(request, id):
|
||||||
|
person = get_object_or_404(Person, id=id)
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = PersonForm(request.POST, instance=person)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect('members')
|
||||||
|
else:
|
||||||
|
form = PersonForm(instance=person)
|
||||||
|
return render(request, 'person_form.html', {'form': form, 'action': 'Bearbeiten'})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user