Merge remote-tracking branch 'origin/main'

main
Samuel Zielke 9 months ago
commit a8a653f129

@ -11,6 +11,10 @@ https://docs.djangoproject.com/en/5.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
from import_export.formats.base_formats import CSV
IMPORT_FORMATS = [CSV]
EXPORT_FORMATS = [CSV]
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -35,6 +39,7 @@ INSTALLED_APPS = [
#ADD_ONs #ADD_ONs
'jazzmin', 'jazzmin',
'phonenumber_field', 'phonenumber_field',
'import_export',
#Defaul #Defaul
'django.contrib.admin', 'django.contrib.admin',
@ -143,3 +148,36 @@ JAZZMIN_SETTINGS = {
"site_logo": 'main/img/crewpulse_logo.png', "site_logo": 'main/img/crewpulse_logo.png',
"show_ui_builder": True, # Zeigt den UI-Builder im Admin-Bereich "show_ui_builder": True, # Zeigt den UI-Builder im Admin-Bereich
} }
JAZZMIN_UI_TWEAKS = {
"navbar_small_text": False,
"footer_small_text": False,
"body_small_text": True,
"brand_small_text": False,
"brand_colour": False,
"accent": "accent-warning",
"navbar": "navbar-dark",
"no_navbar_border": False,
"navbar_fixed": False,
"layout_boxed": False,
"footer_fixed": False,
"sidebar_fixed": False,
"sidebar": "sidebar-dark-olive",
"sidebar_nav_small_text": False,
"sidebar_disable_expand": False,
"sidebar_nav_child_indent": False,
"sidebar_nav_compact_style": False,
"sidebar_nav_legacy_style": False,
"sidebar_nav_flat_style": False,
"theme": "solar",
"dark_mode_theme": "solar",
"button_classes": {
"primary": "btn-primary",
"secondary": "btn-secondary",
"info": "btn-info",
"warning": "btn-warning",
"danger": "btn-danger",
"success": "btn-success"
},
"actions_sticky_top": False
}

@ -1,39 +1,95 @@
from django import forms
from django.contrib import admin from django.contrib import admin
import main.models as MainDB import main.models as MainDB
from datetime import date, datetime from datetime import date, datetime
from django.utils.html import format_html
from import_export import resources
from import_export.admin import ExportMixin, ImportMixin, ImportExportModelAdmin
class contributorsResource(resources.ModelResource):
class Meta:
model = MainDB.contributors
# Register your models here. # Register your models here.
@admin.register(MainDB.contributors) @admin.register(MainDB.contributors)
class MainDB_contributorsAdmin(admin.ModelAdmin): # class DeinModellAdmin(ImportExportModelAdmin):
# pass # Damit hast du Import/Export-Funktionalität im Django Admin
class MainDB_contributorsAdmin(ExportMixin, ImportMixin, admin.ModelAdmin):
resource_class = contributorsResource
list_display = ('full_name', 'da_approval', 'teamleader', 'second_teamleader', 'gender', 'birthday_year', 'get_congregation', 'pioneer', 'get_deparment', 'mobilnumber', 'email') list_display = ('full_name', 'actual', 'da_approval', 'leader', 'tage_anzeige', 'gender', 'birthday_year', 'get_congregation', 'pioneer', 'get_deparment', 'mobilnumber', 'email')
list_filter = ('gender', 'roles', 'deparment', 'da_approval') list_filter = ('gender', 'roles', 'deparment', 'da_approval')
search_fields = ('name', 'firstname', 'congregation__title', 'deparment__title', 'mobilnumber', 'email') search_fields = ('name', 'firstname', 'congregation__title', 'deparment__title', 'mobilnumber', 'email')
def get_congregation(self, obj): def get_congregation(self, obj):
# Gebe eine durch Komma getrennte Liste der Namen der contributors zurück return obj.congregation
return ", ".join([str(congregation) for congregation in obj.congregation.all()]) get_congregation.short_description = 'Versammlung'
get_congregation.short_description = 'Versammlung' # Optional: Benennung der Spalte get_congregation.admin_order_field = 'congregation__title'
def get_deparment(self, obj): def get_deparment(self, obj):
# Gebe eine durch Komma getrennte Liste der Namen der contributors zurück # Gebe eine durch Komma getrennte Liste der Namen der contributors zurück
return ", ".join([str(deparment) for deparment in obj.deparment.all()]) return ", ".join([str(deparment) for deparment in obj.deparment.all()])
get_deparment.short_description = 'Abteilung' # Optional: Benennung der Spalte get_deparment.short_description = 'Abteilung' # Optional: Benennung der Spalte
# Methode, um den vollständigen Namen zu kombinieren
def full_name(self, obj):
return f"{obj.name}, {obj.firstname}"
full_name.short_description = 'Name' # Spaltenüberschrift im Admin ändern
# Methode, um nur das Jahr des Birthdays anzuzeigen # Methode, um nur das Jahr des Birthdays anzuzeigen
def birthday_year(self, obj): def birthday_year(self, obj):
year = obj.birthday.year if obj.birthday else None year = obj.birthday.year if obj.birthday != None else 0
return int(datetime.strftime(date.today(), "%Y")) - year return int(datetime.strftime(date.today(), "%Y")) - year
birthday_year.short_description = 'Alter' birthday_year.short_description = 'Alter'
# Teamleiter ansicht
def leader(self, obj):
if obj.teamleader:
color = "green"
elif not obj.teamleader and obj.second_teamleader:
color = "gold"
else:
color = "gray"
status = f'<span style="color: {color}; font-size: 16px;">●</span>'
return format_html(status)
# Verfügbarkeit anzeigen
def tage_anzeige(self, obj):
""" Kompakte Anzeige mit 2er-Gruppen in farbigen Punkten """
tage_pairs = [
("MiV", "MiN"),
("DoV", "DoN"),
("FrV", "FrN"),
("SaV", "SaN"),
("SoV", "SoN"),
("Abbau", None) # Extra2 hat keinen Partner, wird einzeln bewertet
]
symbols = []
for tag1, tag2 in tage_pairs:
active1 = obj.tage & obj.TAGE[tag1]
active2 = obj.TAGE.get(tag2, 0) and obj.tage & obj.TAGE[tag2] if tag2 else None # Sicherstellen, dass None nicht bewertet wird
if tag2 is None: # Falls nur ein Eintrag in der Gruppe existiert
color = "green" if active1 else "red" # Entweder Grün oder Rot
else:
if active1 and active2:
color = "green" # 🟢 beide aktiv
elif active1 or active2:
color = "gold" # 🟡 nur einer aktiv
else:
color = "red" # 🔴 beide inaktiv
symbols.append(f'<span style="color: {color}; font-size: 16px;">●</span>')
return format_html(" ".join(symbols))
admin.site.register(MainDB.department) admin.site.register(MainDB.department)
admin.site.register(MainDB.congregation)
@admin.register(MainDB.congregation)
class MainDB_congregationAdmin(admin.ModelAdmin):
list_display = ('id', 'title')
admin.site.register(MainDB.role) admin.site.register(MainDB.role)

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from django.contrib import admin
# Create your models here. # Create your models here.
class department(models.Model): class department(models.Model):
@ -48,41 +48,57 @@ class role(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse("role_detail", kwargs={"pk": self.pk}) return reverse("role_detail", kwargs={"pk": self.pk})
class contributors(models.Model): class contributors(models.Model):
DAY_OPTIONS = [ TAGE = {
('MI', 'Mittwoch'), "MiV": 1,
('DO', 'Donnerstag'), "MiN": 2,
('FRV', 'Freitag vormittag'), "DoV": 4,
('FRN', 'Freitag nachmittag'), "DoN": 8,
('SAV', 'Samstag vormittag'), "FrV": 16,
('SAN', 'Samstag nachmittag'), "FrN": 32,
('SOV', 'Sonntag vormittag'), "SaV": 64,
('SON', 'Sonntag nachmittag'), "SaN": 128,
('SOA', 'Sonntag abbau'), "SoV": 256,
('MO', 'Montag'), "SoN": 512,
] "Abbau": 1024,
}
name = models.CharField(("name"), max_length=50) name = models.CharField(("name"), max_length=50)
firstname = models.CharField(("vorname"), max_length=50) firstname = models.CharField(("vorname"), max_length=50)
birthday = models.DateField(("geburtstag"), auto_now=False, auto_now_add=False) birthday = models.DateField(("geburtstag"), auto_now=False, auto_now_add=False, blank=True, null=True)
congregation = models.ManyToManyField("main.congregation", verbose_name=("congregation"), null=True) congregation = models.ForeignKey("main.congregation", verbose_name=("Versammlung"), on_delete=models.SET_NULL, null=True, blank=True)
roles = models.ManyToManyField("main.role", verbose_name=("role"), null=True) roles = models.ManyToManyField("main.role", verbose_name=("role"), null=True, blank=True)
pioneer = models.BooleanField(("pionier")) pioneer = models.BooleanField(("pionier"), default=False)
gender = models.CharField("Geschlecht",max_length=20, choices=[("M", "Männlich"), ("W", "Weiblich")]) gender = models.CharField("Geschlecht",max_length=20, choices=[("M", "Männlich"), ("W", "Weiblich")])
da_approval = models.BooleanField(("Freigabe"), default=False) da_approval = models.BooleanField(("Freigabe"), default=False)
deparment = models.ManyToManyField("main.department", verbose_name=("department"), null=True, blank=True) deparment = models.ManyToManyField("main.department", verbose_name=("Abteilung"), null=True, blank=True)
availability = models.CharField(("Verfügbarkeit"), max_length=50, choices=DAY_OPTIONS, blank=True) tage = models.IntegerField(default=0) # Hier speichern wir die Bitmaske
teamleader = models.BooleanField(("Leiter"), default=False) teamleader = models.BooleanField(("Leiter"), default=False)
second_teamleader = models.BooleanField(("V-Leiter"), default=False) second_teamleader = models.BooleanField(("Gruppenleiter"), default=False)
mobilnumber = PhoneNumberField(("Mobilnummer"), null=True, blank=True) mobilnumber = PhoneNumberField(("Mobilnummer"), null=True, blank=True)
email = models.EmailField(("E-Mail"), max_length=254, null=True, blank=True) email = models.EmailField(("E-Mail"), max_length=254, null=True, blank=True)
jwpub = models.EmailField(("JWPUB"), max_length=254, null=True, blank=True)
notes = models.CharField(("Bemerkung"), max_length=255, null=True, blank=True)
actual = models.BooleanField(("Aktuell"), default=False)
class Meta: class Meta:
verbose_name = ("Helfer") verbose_name = ("Helfer")
verbose_name_plural = ("Helfer") verbose_name_plural = ("Helfer")
@property
@admin.display(
ordering="name",
description="Name, Vorname",
boolean=False,
)
def full_name(self):
return self.name + ", " + self.firstname
def get_tage_list(self):
""" Gibt eine Liste der aktiven Tage zurück """
return [name for name, bit in self.TAGE.items() if self.tage & bit]
def __str__(self): def __str__(self):
return f'{self.name}, {self.firstname}' return f'{self.name}, {self.firstname}'

Loading…
Cancel
Save

Powered by TurnKey Linux.