update member view, add description to jobgroup, add pinned feature

This commit is contained in:
2020-10-20 14:02:18 +00:00
parent 4f46a3d694
commit 49a36e4f20
8 changed files with 180 additions and 140 deletions

View File

@@ -1,8 +1,8 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from .models import Member, Job, JobMember, JobGroup from .models import Member, Job, JobGroup, JobMember
from .forms import MyMemberForm, MyJobForm, MyJobGroupForm from .forms import MemberForm, JobForm, JobGroupForm
class MemberRoleFilter(admin.SimpleListFilter): class MemberRoleFilter(admin.SimpleListFilter):
@@ -35,7 +35,7 @@ class ActiveMemberInline(JobMemberInline):
verbose_name_plural = "Aktive Mitglieder Liste" verbose_name_plural = "Aktive Mitglieder Liste"
def get_queryset(self, request): def get_queryset(self, request):
return JobMember.active_member.get_all() return JobMember.active_member.get_queryset()
class InactiveMemberInline(JobMemberInline): class InactiveMemberInline(JobMemberInline):
@@ -43,7 +43,7 @@ class InactiveMemberInline(JobMemberInline):
verbose_name_plural = "Inaktive Mitglieder Liste" verbose_name_plural = "Inaktive Mitglieder Liste"
def get_queryset(self, request): def get_queryset(self, request):
return JobMember.inactive_member.get_all() return JobMember.inactive_member.get_queryset()
class JobInline(admin.TabularInline): class JobInline(admin.TabularInline):
@@ -51,8 +51,8 @@ class JobInline(admin.TabularInline):
extra = 0 extra = 0
class MyMemberAdmin(admin.ModelAdmin): class MemberAdmin(admin.ModelAdmin):
form = MyMemberForm form = MemberForm
model = Member model = Member
fieldsets = ( fieldsets = (
(None, { (None, {
@@ -94,11 +94,8 @@ class MyMemberAdmin(admin.ModelAdmin):
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(Member, MyMemberAdmin) class JobAdmin(admin.ModelAdmin):
form = JobForm
class MyJobAdmin(admin.ModelAdmin):
form = MyJobForm
model = Job model = Job
list_display = ['name'] list_display = ['name']
inlines = (ActiveMemberInline, InactiveMemberInline) inlines = (ActiveMemberInline, InactiveMemberInline)
@@ -124,13 +121,10 @@ class MyJobAdmin(admin.ModelAdmin):
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(Job, MyJobAdmin) class JobGroupAdmin(admin.ModelAdmin):
form = JobGroupForm
class MyJobGroupAdmin(admin.ModelAdmin):
form = MyJobGroupForm
model = JobGroup model = JobGroup
list_display = ['name'] list_display = ['name', 'is_pinned', ]
inlines = (JobInline, ) inlines = (JobInline, )
search_fields = ['name'] search_fields = ['name']
@@ -154,4 +148,6 @@ class MyJobGroupAdmin(admin.ModelAdmin):
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(JobGroup, MyJobGroupAdmin) admin.site.register(Member, MemberAdmin)
admin.site.register(Job, JobAdmin)
admin.site.register(JobGroup, JobGroupAdmin)

View File

@@ -4,7 +4,7 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget
from .models import Member, Job, JobGroup from .models import Member, Job, JobGroup
class MyMemberForm(forms.ModelForm): class MemberForm(forms.ModelForm):
class Meta: class Meta:
model = Member model = Member
fields = [ fields = [
@@ -25,7 +25,7 @@ class MyMemberForm(forms.ModelForm):
} }
class MyJobForm(forms.ModelForm): class JobForm(forms.ModelForm):
class Meta: class Meta:
model = Job model = Job
fields = [ fields = [
@@ -33,16 +33,20 @@ class MyJobForm(forms.ModelForm):
'shortterm', 'shortterm',
'slug', 'slug',
'job_group', 'job_group',
]
class JobGroupForm(forms.ModelForm):
class Meta:
model = JobGroup
fields = [
'name',
'shortterm',
'slug',
'description', 'description',
'image' 'is_pinned',
] ]
widgets = { widgets = {
'description': CKEditorUploadingWidget(config_name='default') 'description': CKEditorUploadingWidget(config_name='default')
} }
class MyJobGroupForm(forms.ModelForm):
class Meta:
model = JobGroup
fields = ['name', 'shortterm', 'slug', 'is_pinned']

View File

@@ -10,75 +10,71 @@ from easy_thumbnails.fields import ThumbnailerImageField
from rest_framework import serializers from rest_framework import serializers
class MemberQuerySet(models.QuerySet):
def get_active(self):
date_today = timezone.now().date()
return self.filter(
Q(member__role=Member.MemberRole.ACTIVE)
& (Q(job_end__gt=date_today) | Q(job_end__isnull=True))
)
def get_inactive(self):
date_today = timezone.now().date()
return self.filter(
Q(member__role=Member.MemberRole.PENSION)
| (Q(job_end__lt=date_today + timedelta(days=1)) & Q(job_end__isnull=False))
)
class ActiveMemberManager(models.Manager): class ActiveMemberManager(models.Manager):
''' '''
return a list of active member, and members who are still working return a list of active member, and members who are still working
''' '''
def get_members_of_job(self, job_names): def get_all_by_slug(self, slug):
tmp_list = [] return self.get_queryset().filter(job__job_group__slug=slug)
for job_name in job_names:
tmp_list.append(self.get_queryset().get_active().filter(Q(job__name=job_name)))
return tmp_list
def get_all(self):
return self.get_queryset().get_active()
def get_queryset(self): def get_queryset(self):
return MemberQuerySet(self.model, using=self._db) date_today = timezone.now().date()
return super().get_queryset().filter(
Q(member__role=Member.MemberRole.ACTIVE)
& (Q(job_end__gt=date_today) | Q(job_end__isnull=True))
)
class InactiveMemberManager(models.Manager): class InactiveMemberManager(models.Manager):
''' '''
return a list of inactive member return a list of inactive member
''' '''
def get_members_of_job(self, job_names): def get_all_by_slug(self, slug):
tmp_list = [] return self.get_queryset().filter(job__job_group__slug=slug)
for job_name in job_names:
tmp_list.append(self.get_queryset().get_inactive().filter(Q(job__name=job_name)))
return tmp_list
def get_all(self):
return self.get_queryset().get_inactive()
def get_queryset(self): def get_queryset(self):
return MemberQuerySet(self.model, using=self._db) date_today = timezone.now().date()
return super().get_queryset().filter(
Q(member__role=Member.MemberRole.PENSION)
| (Q(job_end__lt=date_today + timedelta(days=1)) & Q(job_end__isnull=False))
)
class MemberManager(models.Manager): class MemberManager(models.Manager):
def get_members(self, role): def get_members(self, role):
return self.get_queryset().filter(Q(member__role=role)) return self.get_queryset().filter(Q(member__role=role))
def get_all(self):
return self.get_queryset()
class JobGroupManager(models.Manager):
def get_active_jobgroup(self):
job_groups = list(self.get_queryset())
class JobManager(models.Manager): # delete job groups which don't have active members
def get_job_names(self, slug): for elem in job_groups:
job_list = [] if not JobMember.active_member.get_all_by_slug(slug=elem.slug):
slug_list = [] job_groups.remove(elem)
for i in self.get_queryset().filter(Q(job__job_group__slug=slug)):
if i.job.name not in job_list: return job_groups
job_list.append(i.job.name)
slug_list.append(i.job.slug) def get_pinned_active_jobgroups(self):
return job_list, slug_list job_groups = []
for elem in self.get_active_jobgroup():
if elem.is_pinned:
job_groups.append(elem)
return job_groups
def get_unpinned_active_jobgroups(self):
job_groups = []
for elem in self.get_active_jobgroup():
if not elem.is_pinned:
job_groups.append(elem)
return job_groups
class Member(models.Model): class Member(models.Model):
@@ -145,12 +141,17 @@ class MemberSerializer(serializers.HyperlinkedModelSerializer):
class JobGroup(models.Model): class JobGroup(models.Model):
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
shortterm = models.CharField(max_length=128)
shortterm = models.CharField(max_length=128)
slug = models.SlugField(unique=True, null=True, blank=True) slug = models.SlugField(unique=True, null=True, blank=True)
description = models.TextField(null=True, blank=True)
is_pinned = models.BooleanField(default=False) is_pinned = models.BooleanField(default=False)
# Managers
all_jobgroups = JobGroupManager()
class Meta: class Meta:
verbose_name = "Tätigkeit-Gruppierung" verbose_name = "Tätigkeit-Gruppierung"
verbose_name_plural = "Tätigkeit-Gruppierungen" verbose_name_plural = "Tätigkeit-Gruppierungen"
@@ -167,13 +168,10 @@ class JobGroup(models.Model):
class Job(models.Model): class Job(models.Model):
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
shortterm = models.CharField(max_length=128) shortterm = models.CharField(max_length=128)
slug = models.SlugField(unique=True, null=True, blank=True) slug = models.SlugField(unique=True, null=True, blank=True)
description = models.TextField(null=True, blank=True)
image = models.ImageField(null=True, blank=True)
job_group = models.ForeignKey( job_group = models.ForeignKey(
JobGroup, JobGroup,
on_delete=models.CASCADE, on_delete=models.CASCADE,
@@ -222,5 +220,3 @@ class JobMember(models.Model):
members = MemberManager() members = MemberManager()
active_member = ActiveMemberManager() active_member = ActiveMemberManager()
inactive_member = InactiveMemberManager() inactive_member = InactiveMemberManager()
jobs = JobManager()

View File

@@ -5,8 +5,7 @@ from . import views
urlpatterns = [ urlpatterns = [
path('', views.index, name='members'), path('', views.index, name='members'),
path('<str:filter>', views.members_view), path('<str:filter>', views.members_view),
path('jobs/<str:slug>', views.jobs_view), path('jobs/<str:slug>', views.jobs_view),
path('member/<str:member_name>', views.profile_view, name="member"), path('member/<str:member_name>', views.profile_view, name='member'),
] ]

View File

@@ -10,12 +10,27 @@ from rest_framework import permissions
# from django_filters.rest_framework import DjangoFilterBackend # from django_filters.rest_framework import DjangoFilterBackend
def __get_job_groups():
pinned_job_groups = JobGroup.all_jobgroups.get_pinned_active_jobgroups()
unpinned_job_groups = JobGroup.all_jobgroups.get_unpinned_active_jobgroups()
# show max 5 pinned jobgroups
if len(pinned_job_groups) > 5:
for idx, val in enumerate(pinned_job_groups[5:]):
unpinned_job_groups.append(val)
pinned_job_groups = pinned_job_groups[:5]
return pinned_job_groups, unpinned_job_groups
def index(request): def index(request):
job_group = deque(JobGroup.objects.all()) pinned_job_groups, unpinned_job_groups = __get_job_groups()
members = deque(Member.all_members.all()) members = deque(Member.all_members.all())
context = { context = {
"job_group": job_group, "pinned_job_groups": pinned_job_groups,
"unpinned_job_groups": unpinned_job_groups,
"members": members, "members": members,
} }
@@ -23,31 +38,23 @@ def index(request):
def jobs_view(request, slug=None): def jobs_view(request, slug=None):
job_group = deque(JobGroup.objects.all()) pinned_job_groups, unpinned_job_groups = __get_job_groups()
job_list = []
job_names, slug_list = JobMember.jobs.get_job_names(slug=slug) description = JobGroup.all_jobgroups.filter(slug=slug).values().first()['description']
job_members = JobMember.active_member.get_all_by_slug(slug=slug)
if not job_names:
raise Http404("no jobs")
active_members = JobMember.active_member.get_members_of_job(job_names=job_names)
inactive_members = JobMember.inactive_member.get_members_of_job(job_names=job_names)
for idx, item in enumerate(job_names):
job_list.append(
(job_names[idx], active_members[idx], inactive_members[idx], slug_list[idx])
)
context = { context = {
"job_group": job_group, # Das sind die Tabs "pinned_job_groups": pinned_job_groups,
"job_list": job_list, # Das ist die Liste, die dargestellt wird "unpinned_job_groups": unpinned_job_groups,
"description": description,
"job_members": job_members,
} }
return render(request, 'members/index.html', context) return render(request, 'members/index.html', context)
def members_view(request, filter=None): def members_view(request, filter=None):
job_group = deque(JobGroup.objects.all()) pinned_job_groups, unpinned_job_groups = __get_job_groups()
if filter in Member.MemberRole: if filter in Member.MemberRole:
members = deque(Member.all_members.filter(role=filter)) members = deque(Member.all_members.filter(role=filter))
@@ -55,7 +62,8 @@ def members_view(request, filter=None):
raise Http404("no member role") raise Http404("no member role")
context = { context = {
"job_group": job_group, "pinned_job_groups": pinned_job_groups,
"unpinned_job_groups": unpinned_job_groups,
"members": members, "members": members,
} }
@@ -63,15 +71,17 @@ def members_view(request, filter=None):
def profile_view(request, member_name=None): def profile_view(request, member_name=None):
job_group = deque(JobGroup.objects.all()) pinned_job_groups, unpinned_job_groups = __get_job_groups()
member = deque(Member.all_members.filter(nickname=member_name))
member = Member.all_members.filter(nickname=member_name).first()
if not member: if not member:
raise Http404("no member") raise Http404("no member")
jobs = deque(JobMember.members.filter(member__nickname=member_name)) jobs = deque(JobMember.members.filter(member__nickname=member_name))
context = { context = {
"job_group": job_group, "pinned_job_groups": pinned_job_groups,
"unpinned_job_groups": unpinned_job_groups,
"member": member, "member": member,
"jobs": jobs, "jobs": jobs,
} }

View File

@@ -53,7 +53,8 @@ footer {
<li class=""><a href="{%url 'tasks'%}">Tasks</a></li> <li class=""><a href="{%url 'tasks'%}">Tasks</a></li>
{% endif %} {% endif %}
<li class=""><a href="{% url 'posts.index' %}">Aktuelles</a></li> <li class=""><a href="{% url 'posts.index' %}">Aktuelles</a></li>
<li class=""><a href="{%url 'members'%}">Fachschaft</a></li> <!-- show active members first -->
<li class=""><a href="{% url 'members'%}A">Fachschaft</a></li>
<li class=""><a href="/fotos/">Fotos</a></li> <li class=""><a href="/fotos/">Fotos</a></li>
<li class=""><a href="/blackboard">Blackboard</a></li> <li class=""><a href="/blackboard">Blackboard</a></li>
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}

View File

@@ -1,47 +1,82 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div class="grid-container"> <div class="grid-container">
<h1>Mitglieder / Tätigkeiten</h1>
<!-- Nav tabs --> <div class="grid-x grid-padding-x padding-top-1">
<div class="tabs.simple"> <div class="cell large-2 medium-4 small-6"><a class="button active" style="width: 100%" href="/members/A">Fachschaft</a></div>
<a href="/members">Mitglieder</a>
<a href="/members/A">Aktive Mitglieder</a>
<a href="/members/P">Inaktive Mitglieder</a>
{% for job in job_group %} {% for job in pinned_job_groups %}
<a href="/members/jobs/{{job.slug}}">{{job.name}}</a> <div class="cell large-2 medium-4 small-6"><a class="button" style="width: 100%" href="/members/jobs/{{job.slug}}">{{job.name}}</a></div>
{% endfor %} {% endfor %}
</div> </div>
<!-- Tab panes --> <ul class="accordion" data-accordion data-allow-all-closed="true">
<div class="tabs-content"> <li class="accordion-item" data-accordion-item>
{% for mem in member %} <!-- Accordion tab title -->
{% with member=mem %} <a class="accordion-title">weitere Gruppen</a>
{% include 'members/partials/_member_details.html' %}
{% endwith %}
{% endfor %}
{% if members is not None %} <!-- Accordion tab content: it would start in the open state due to using the `is-active` state class. -->
{% include 'members/members_list.html' %} <div class="accordion-content" data-tab-content>
<div class="grid-x grid-padding-x">
{% for job in unpinned_job_groups %}
<div class="cell large-2 medium-4 small-6"><a class="button" style="width: 100%" href="/members/jobs/{{job.slug}}">{{job.name}}</a></div>
{% endfor %}
<div class="cell large-2 medium-4 small-6"><a class="button" style="width: 100%" href="/members">Alle Mitglieder</a></div>
<div class="cell large-2 medium-4 small-6"><a class="button" style="width: 100%" href="/members/P">Pension Mitglieder</a></div>
</div>
</div>
</li>
</ul>
<div class="grid-x auto">
{% if description is not None %}
{{ description|safe }}
{% endif %}
</div>
<!-- show details of a member -->
{% if member %}
<div class="padding-top-1 padding-left-1 padding-bottom-1 padding-right-1" style="background-color: white;">
{% include 'members/partials/_member_details.html' %}
</div>
{% endif %} {% endif %}
{% for job in job_list %} <!-- show all, active or pension members -->
<div class="tabs-content" id="{{job.3}}"> {% if members %}
<div class="padding-top-1 padding-left-1 padding-right-1" style="background-color: white;">
<h2>{{job.0}}<a class="headerlink" href="#{{job.3}}" title="Permalink to {{job.0}}"> #</a></h2> {% include 'members/members_list.html' %}
{% with active_members=job.1 inactive_members=job.2 %}
{% include 'members/jobs_list.html' %}
{% endwith %}
</div> </div>
{% endif %}
<!-- show job lists in a job group -->
{% regroup job_members by job.name as all_jobmem_list %}
{% for jobmem in all_jobmem_list %}
<div class="padding-top-1 padding-left-1 padding-bottom-1 padding-right-1" style="background-color: white;">
<h2>{{jobmem.grouper}}<a class="headerlink" href="#{{jobmem.list.0.job.slug}}" title="Permalink to {{jobmem.grouper}}"> #</a></h2>
<b>Aktuelle Mitglieder:</b>
<div class="grid-x">
{% for jm in jobmem.list %}
{% with member=jm.member %}
<div class="medium-3 large-2 small-6 cell">
<h2>{{jm.member.surname}}</h2>
{% include 'members/partials/_member.html' %}
{{jm.get_job_role_display}} ({{jm.job_start|date}} - {{jm.job_end|date}})
</div>
{% endwith %}
{% endfor %} {% endfor %}
</div> </div>
</div>
{% endfor %}
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -1,11 +1,10 @@
<div class="grid-container"> <div class="grid-x">
<div class="grid-x">
{% for member in members %} {% for member in members %}
<div class="medium-3 large-2 small-6 cell"> <div class="cell large-2 medium-3 small-6">
<h2>{{member.surname}}</h2> <h2>{{member.surname}}</h2>
{% include 'members/partials/_member.html' %} {% include 'members/partials/_member.html' %}
</div> </div>
{% endfor %} {% endfor %}
</div>
</div> </div>