multiple changes

This commit is contained in:
2020-08-26 05:37:49 +00:00
46 changed files with 32258 additions and 450 deletions

6
.gitignore vendored
View File

@@ -4,6 +4,8 @@
fet2020/files/* fet2020/files/*
fet2020/.env/* fet2020/.env/*
*.sqlite3 *.sqlite3
fet2020/posts/migrations/* fet2020/*/migrations/*
fet2020/members/migrations/*
.theia/* .theia/*
.flake8
migrate
run

View File

@@ -1,32 +1,57 @@
from etherpad_lite import EtherpadLiteClient from etherpad_lite import EtherpadLiteClient
from django.conf import settings from django.conf import settings
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.utils.text import slugify
import urllib.parse
t=datetime.now() + timedelta(days=1) t=datetime.now() + timedelta(days=1)
SERVER_URL="http://etherpad2.2020.fet.at/etherpad/" SERVER_URL="https://etherpad2.2020.fet.at/etherpad/"
with open("/srv/andis_test/etherpad_test2/etherpad-lite/APIKEY.txt","r") as f: with open("/srv/andis_test/etherpad_test2/etherpad-lite/APIKEY.txt","r") as f:
k=f.read() k=f.read()
epc=EtherpadLiteClient( base_params={'apikey':k,}, base_url="http://localhost:9003/api") epc=EtherpadLiteClient( base_params={'apikey':k,}, base_url=urllib.parse.urljoin("http://localhost:9003","api"))
a=epc.createAuthorIfNotExistsFor(name="andis", authorMapper="andis") a=epc.createAuthorIfNotExistsFor(name="andis", authorMapper="andis")
g=epc.createGroupIfNotExistsFor(groupMapper="fet") g=epc.createGroupIfNotExistsFor(groupMapper="fet")
def get_ep_sessionid(request):
if request.user is None:
return "NoUser", None
server = SERVER_URL
author = epc.createAuthorIfNotExistsFor(name=str(request.user), authorMapper=str(request.user))['authorID']
expires = datetime.utcnow() + timedelta(
hours=3
)
try:
result = epc.createSession(
groupID=str(g['groupID']),
authorID=str(author),
validUntil=str(int(expires.timestamp()))
)
except Exception as e:
raise e
return None, None
return result['sessionID'],expires
def get_pad_link(padID):
return urllib.parse.urljoin(SERVER_URL,'p/'+g["groupID"] + '$' + slugify(padID))
def add_ep_to_response(request, response): def add_ep_to_response(request, response):
if request.user is None: if request.user is None:
return response return response
padID=id padID=id
server = urlparse(SERVER_URL) server = SERVER_URL
padLink = SERVER_URL + 'p/' + g["groupID"] + '$' + \ #padLink = urllib.parse.urljoin(SERVER_URL , 'p/' + g["groupID"] + '$' + padID)
padID
author = epc.createAuthorIfNotExistsFor(name=str(request.user), authorMapper=str(request.user))['authorID'] author = epc.createAuthorIfNotExistsFor(name=str(request.user), authorMapper=str(request.user))['authorID']
expires = datetime.datetime.utcnow() + datetime.timedelta( expires = datetime.utcnow() + timedelta(
hours=3 hours=3
) )
try: try:
result = epclient.createSession( result = epclient.createSession(
groupID=str(group['groupID']), groupID=str(g['groupID']),
authorID=str(author), authorID=str(author),
validUntil=str(int(expires.timestamp())) validUntil=str(int(expires.timestamp()))
) )
@@ -38,11 +63,11 @@ def add_ep_to_response(request, response):
response.delete_cookie('sessionID', server.hostname) response.delete_cookie('sessionID', server.hostname)
response.delete_cookie('padSessionID') response.delete_cookie('padSessionID')
response.set_cookie( response=response.set_cookie(
'sessionID', 'sessionID',
value=result['sessionID'], value=result['sessionID'],
expires=expires, expires=expires,
domain=server.hostname, domain="https://etherpad2.2020.fet.at",
httponly=False httponly=False
) )

View File

@@ -1,23 +0,0 @@
from django.contrib import admin
from .models import Document
from django.urls import path
from django.contrib.auth import views as auth_views
from django.shortcuts import render
@admin.register(Document)
class DocumentModelAdmin(admin.ModelAdmin):
def my_view(self,request, extra_context=None):
return render(request,"admin/documents/preview.html")
def get_urls(self):
urls = super().get_urls()
select_list_url = [ path("<int:id>/preview", self.admin_site.admin_view(self.my_view),
name='preview'),
path("preview", self.admin_site.admin_view(self.my_view),
name='preview')
]
return select_list_url #+ urls
#admin.site.register(Document,DocumentModelAdmin)

View File

@@ -1,7 +0,0 @@
from django.apps import AppConfig
class DocumentsConfig(AppConfig):
name = 'documents'
from django.contrib.admin.apps import AdminConfig

View File

@@ -1,8 +0,0 @@
from django.db import models
# Create your models here.
class Document(models.Model):
key = models.CharField(max_length=200, primary_key=True)

View File

@@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@@ -1,6 +0,0 @@
import documents.views as views
from django.urls import path
urlpatterns=[
path("document/<id>", views.document)
]

View File

@@ -1,91 +0,0 @@
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponseRedirect
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext_lazy as _
import urllib
from urllib.parse import urlparse
from .models import Document
from documents import epc
from documents import g as group
SERVER_URL="http://etherpad.2020.fet.at/"
import datetime
@login_required
def document(request, id=None):
"""Create and session and display an embedded pad
"""
# Initialize some needed values
#pad = Document.objects.get(key=id)
padID=id
padLink = SERVER_URL + 'p/' + group["groupID"] + '$' + \
padID
server = urlparse(SERVER_URL)
author = epc.createAuthorIfNotExistsFor(name=str(request.user), authorMapper=str(request.user))['authorID']
# Create the session on the etherpad-lite side
expires = datetime.datetime.utcnow() + datetime.timedelta(
hours=3
)
epclient = epc
try:
result = epclient.createSession(
groupID=str(group['groupID']),
authorID=str(author),
validUntil=str(int(expires.timestamp()))
)
except Exception as e:
response = render(
'etherpad-lite/pad.html',
{
'pad': padID,
'link': padLink,
'server': str(server),
'uname': str(request.user),
'error': 'etherpad-lite session request returned:' +
'"' + str(e) + '"'
}
)
return response
# Set up the response
response = render(request,
'documents/pad.html',
{
'pad': padID,
'link': padLink,
'server': str(server),
'uname': str(request.user),
'error': False
}#, context=(request)
)
# Delete the existing session first
if ('padSessionID' in request.COOKIES):
epclient.deleteSession(request.COOKIES['sessionID'])
response.delete_cookie('sessionID', server.hostname)
response.delete_cookie('padSessionID')
# Set the new session cookie for both the server and the local site
response.set_cookie(
'sessionID',
value=result['sessionID'],
expires=expires,
domain=server.hostname,
httponly=False
)
response.set_cookie(
'padSessionID',
value=result['sessionID'],
expires=expires,
httponly=False
)
return response

View File

@@ -1,15 +1,20 @@
from django.contrib.auth.models import User # from django.contrib.auth.models import User
from django.contrib.auth.middleware import RemoteUserMiddleware from django.contrib.auth.middleware import RemoteUserMiddleware
import django # import django
#import logging # import logging
#logger=logging.getLogger("django.request") # logger=logging.getLogger("django.request")
class FETHeaderMiddleware(RemoteUserMiddleware): class FETHeaderMiddleware(RemoteUserMiddleware):
header="Remote-User" header = "Remote-User"
def process_request(self, request): def process_request(self, request):
request.META[self.header]=request.META.get(self.header, request.headers.get(self.header,None)) request.META[self.header] = request.META.get(
self.header,
request.headers.get(self.header, None)
)
super().process_request(request) super().process_request(request)
if request.user.is_authenticated: if request.user.is_authenticated:
request.user.is_admin=True request.user.is_admin = True
request.user.is_superuser=True request.user.is_superuser = True
request.user.is_staff=True request.user.is_staff = True

View File

@@ -12,10 +12,27 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
import os import os
# Prints and logs are written to console
# TODO: Change before release
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SESSION_COOKIE_DOMAIN =".2020.fet.at" SESSION_COOKIE_DOMAIN = ".2020.fet.at"
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
@@ -28,15 +45,13 @@ DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = []
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024*1024*1024 DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024
# Application definition # Application definition
CKEDITOR_UPLOAD_PATH = 'upload' CKEDITOR_UPLOAD_PATH = 'upload'
INSTALLED_APPS = [ INSTALLED_APPS = [
'posts.apps.PostsConfig',
'members.apps.MembersConfig',
'documents.apps.DocumentsConfig',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
@@ -45,10 +60,12 @@ INSTALLED_APPS = [
'taggit', 'taggit',
'ckeditor', 'ckeditor',
'ckeditor_uploader', 'ckeditor_uploader',
'easy_thumbnails',
'rest_framework', 'rest_framework',
'django_filters', 'django_filters',
'django_static_jquery_ui', 'django_static_jquery_ui',
'django.contrib.admindocs' 'posts.apps.PostsConfig',
'members.apps.MembersConfig',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@@ -67,7 +84,10 @@ ROOT_URLCONF = 'fet2020.urls'
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),os.path.join(BASE_DIR, 'templates_design1')], 'DIRS': [
os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'templates_design1')
],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@@ -140,10 +160,8 @@ STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static_design1"), os.path.join(BASE_DIR, "static_design1"),
] ]
MEDIA_ROOT=os.path.join(BASE_DIR, 'files/') MEDIA_ROOT = os.path.join(BASE_DIR, 'files/')
MEDIA_URL='/files/' MEDIA_URL = '/files/'
TAGGIT_FORCE_LOWERCASE = True TAGGIT_FORCE_LOWERCASE = True
@@ -162,5 +180,10 @@ CKEDITOR_CONFIGS = {
}, },
], ],
} }
}
THUMBNAIL_ALIASES = {
'': {
'avatar': {'size': (50, 50), 'crop': True},
'thumb': {'size': (150, 150), 'crop': True},
},
} }

View File

@@ -28,12 +28,11 @@ router.register(r'members', MemberViewSet)
urlpatterns = [ urlpatterns = [
path('posts/', include('posts.urls')), path('posts/', include('posts.urls')),
path('documents/', include('documents.urls')),
path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/doc/', include('django.contrib.admindocs.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', views.index, name='home'), path('', views.index, name='home'),
path('index.html', views.index, name='home'), path('index.html', views.index, name='home'),
path('ckeditor/', include('ckeditor_uploader.urls')), path('ckeditor/', include('ckeditor_uploader.urls')),
path('api/', include(router.urls)), path('api/', include(router.urls)),
path('members/', include('members.urls')), path('members/', include('members.urls'), name='members'),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -1,22 +1,30 @@
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse # from django.http import HttpResponse
from collections import deque from collections import deque
from posts.models import Post from posts.models import Post, FetMeeting, Event
from django.utils import timezone
from django.db.models import Q
def index(request): def index(request):
posts=deque(Post.article_objects.all()) posts = deque(Post.article_objects.all())
l=len(posts) date_today = timezone.now().date()
def get_tags(lst): def get_tags(lst):
for p in lst: for p in lst:
for t in list(p.tags.names()): for t in list(p.tags.names()):
yield "#"+ t yield "#" + t
t = set(t for t in get_tags(posts))
t=set( t for t in get_tags(posts)) if len(posts) >= 1:
if l>=1: featured_post = posts.popleft()
featured_post=posts.popleft()
else: else:
featured_post=0 featured_post = 0
return render(request, 'home.html',{'posts':posts, 'featured_post':featured_post, "tags_list": ", ".join(t)}) context = {
'posts': posts,
'events': Post.objects.filter(is_event=True).filter(Q(event_start__gt=date_today)).order_by('-public_date').all(),
'featured_post': featured_post,
'featured_post2': FetMeeting.objects.first(),
'tags_list': ", ".join(t)
}
return render(request, 'home.html', context)

View File

@@ -16,52 +16,58 @@ class MemberRoleFilter(admin.SimpleListFilter):
) )
def queryset(self, request, queryset): def queryset(self, request, queryset):
if self.value() == 'A': if self.value() in Member.MemberRole:
return queryset.filter(role='A') return queryset.filter(role=self.value())
elif self.value() == 'P':
return queryset.filter(role='P')
class JobMemberInline(admin.TabularInline): class JobMemberInline(admin.TabularInline):
model = JobMember model = JobMember
extra = 0 extra = 0
class JobOverviewInline(JobMemberInline): class JobOverviewInline(JobMemberInline):
verbose_name = "Tätigkeit" verbose_name = "Tätigkeit"
verbose_name_plural = "Tätigkeitsübersicht" verbose_name_plural = "Tätigkeitsübersicht"
class ActiveMemberInline(JobMemberInline): class ActiveMemberInline(JobMemberInline):
verbose_name = "Mitglied" verbose_name = "Mitglied"
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.all() return JobMember.active_member.get_all()
class InactiveMemberInline(JobMemberInline): class InactiveMemberInline(JobMemberInline):
verbose_name = "Mitglied" verbose_name = "Mitglied"
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.all() return JobMember.inactive_member.get_all()
class JobInline(admin.TabularInline): class JobInline(admin.TabularInline):
model = Job model = Job
extra = 0 extra = 0
class MyMemberAdmin(admin.ModelAdmin): class MyMemberAdmin(admin.ModelAdmin):
form = MyMemberForm form = MyMemberForm
model = Member model = Member
list_display = ['nickname', 'firstname', 'surname', 'mailaccount', 'role'] list_display = ['nickname', 'firstname', 'surname', 'mailaccount', 'role']
inlines = (JobOverviewInline,) inlines = (JobOverviewInline,)
search_fields = ['firstname', 'surname','nickname','mailaccount'] search_fields = ['firstname', 'surname', 'nickname', 'mailaccount']
list_filter = [MemberRoleFilter] list_filter = [MemberRoleFilter]
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
obj.author = request.user obj.author = request.user
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(Member, MyMemberAdmin) admin.site.register(Member, MyMemberAdmin)
class MyJobAdmin(admin.ModelAdmin): class MyJobAdmin(admin.ModelAdmin):
form = MyJobForm form = MyJobForm
model = Job model = Job
@@ -74,8 +80,10 @@ class MyJobAdmin(admin.ModelAdmin):
obj.author = request.user obj.author = request.user
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(Job, MyJobAdmin) admin.site.register(Job, MyJobAdmin)
class MyJobGroupAdmin(admin.ModelAdmin): class MyJobGroupAdmin(admin.ModelAdmin):
form = MyJobGroupForm form = MyJobGroupForm
model = JobGroup model = JobGroup
@@ -88,4 +96,5 @@ class MyJobGroupAdmin(admin.ModelAdmin):
obj.author = request.user obj.author = request.user
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
admin.site.register(JobGroup, MyJobGroupAdmin) admin.site.register(JobGroup, MyJobGroupAdmin)

View File

@@ -20,16 +20,29 @@ class MyMemberForm(forms.ModelForm):
'address' 'address'
] ]
widgets = {'description': CKEditorUploadingWidget(config_name='default')} widgets = {
'description': CKEditorUploadingWidget(config_name='default')
}
class MyJobForm(forms.ModelForm): class MyJobForm(forms.ModelForm):
class Meta: class Meta:
model = Job model = Job
fields = ['name', 'shortterm', 'slug', 'job_group', 'description', 'image'] fields = [
'name',
'shortterm',
'slug',
'job_group',
'description',
'image'
]
widgets = {
'description': CKEditorUploadingWidget(config_name='default')
}
widgets = {'description': CKEditorUploadingWidget(config_name='default')}
class MyJobGroupForm(forms.ModelForm): class MyJobGroupForm(forms.ModelForm):
class Meta: class Meta:
model = JobGroup model = JobGroup
fields = ['name', 'shortterm', 'is_pinned'] fields = ['name', 'shortterm', 'slug', 'is_pinned']

View File

@@ -4,50 +4,79 @@ from django.db.models import Q
from django.utils import timezone from django.utils import timezone
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
import uuid
from datetime import timedelta from datetime import timedelta
from rest_framework import serializers
class MemberManager(models.Manager): class MemberQuerySet(models.QuerySet):
def get_queryset(self): def get_members(self):
return super().get_queryset().filter(role='A') 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 PensionManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='P')
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_queryset(self): def get_members_of_job(self, job_names):
date_today = timezone.now().date() tmp_list = []
for job_name in job_names:
tmp_list.append(self.get_queryset().get_members().filter(Q(job__name=job_name)))
return tmp_list
def get_all(self):
return self.get_queryset().get_members()
def get_queryset(self):
return MemberQuerySet(self.model, using=self._db)
return super().get_queryset().filter(
Q(member__role='A') &
(
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_queryset(self): def get_members_of_job(self, job_names):
date_today = timezone.now().date() tmp_list = []
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):
return MemberQuerySet(self.model, using=self._db)
class MemberManager(models.Manager):
def get_members(self, role):
return self.get_queryset().filter(Q(member__role=role))
def get_all(self):
return self.get_queryset()
class JobManager(models.Manager):
def get_job_names(self, slug):
tmp_list = []
for i in self.get_queryset().filter(Q(job__job_group__slug=slug)):
if i.job.name not in tmp_list:
tmp_list.append(i.job.name)
return tmp_list
return super().get_queryset().filter(
Q(member__role='P') |
(
Q(job_end__lt=date_today + timedelta(days=1)) &
Q(job_end__isnull=False)
)
)
class Member(models.Model): class Member(models.Model):
firstname = models.CharField(max_length=128) firstname = models.CharField(max_length=128)
@@ -55,20 +84,19 @@ class Member(models.Model):
nickname = models.CharField(max_length=128) nickname = models.CharField(max_length=128)
mailaccount = models.CharField(max_length=128) mailaccount = models.CharField(max_length=128)
__choices = [ class MemberRole(models.TextChoices):
('A', _('Active')), ACTIVE = 'A', _('Active')
('P', _('Pension')) PENSION = 'P', _('Pension')
]
role = models.CharField(max_length=1, choices= __choices, default='A') role = models.CharField(max_length=1, choices=MemberRole.choices, default=MemberRole.ACTIVE)
description = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True)
image = models.ImageField(null=True, blank=True) image = models.ImageField(null=True, blank=True)
birthday = models.DateField(null=True, blank=True) birthday = models.DateField(null=True, blank=True)
phone_error_msg =_(( phone_error_msg = _((
"Phone number must be entered in the format: " "Phone number must be entered in the format: +999999999'. Up to 15 digits allowed."
"+999999999'. Up to 15 digits allowed."
)) ))
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message=phone_error_msg) phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message=phone_error_msg)
phone = models.CharField(validators=[phone_regex], max_length=17, blank=True) phone = models.CharField(validators=[phone_regex], max_length=17, blank=True)
@@ -80,8 +108,6 @@ class Member(models.Model):
# Managers # Managers
all_members = models.Manager() all_members = models.Manager()
active_member = MemberManager()
pension_member = PensionManager()
class Meta: class Meta:
verbose_name = "Mitglied" verbose_name = "Mitglied"
@@ -90,6 +116,7 @@ class Member(models.Model):
def __str__(self): def __str__(self):
return self.firstname + " " + self.surname return self.firstname + " " + self.surname
class MemberSerializer(serializers.HyperlinkedModelSerializer): class MemberSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = Member model = Member
@@ -100,17 +127,22 @@ class MemberSerializer(serializers.HyperlinkedModelSerializer):
'mailaccount', 'mailaccount',
'role', 'role',
'description', 'description',
'image' 'image',
] ]
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)
is_pinned = models.BooleanField(default=False) is_pinned = models.BooleanField(default=False)
def __str__(self): def __str__(self):
return self.name return self.name
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)
@@ -139,6 +171,7 @@ class Job(models.Model):
def __str__(self): def __str__(self):
return self.shortterm return self.shortterm
class JobMember(models.Model): class JobMember(models.Model):
member = models.ForeignKey( member = models.ForeignKey(
Member, Member,
@@ -154,16 +187,18 @@ class JobMember(models.Model):
job_start = models.DateField('Job Start') job_start = models.DateField('Job Start')
job_end = models.DateField('Job Ende', null=True, blank=True) job_end = models.DateField('Job Ende', null=True, blank=True)
__choices = [ class JobRole(models.TextChoices):
('1V', _('VorsitzendeR')), PRESIDENT = '1V', _('VorsitzendeR')
('2V', _('stv VorsitzendeR')), VICE_PRESIDENT = '2V', _('stv VorsitzendeR')
('3V', _('2. stv VorsitzendeR')), SECOND_VICE_PRESIDENT = '3V', _('2. stv VorsitzendeR')
('M', _('Mitglied')), MEMBER = 'M', _('Mitglied')
('E', _('Ersatzmitglied')), SUBSTITUTE_MEMBER = 'E', _('Ersatzmitglied')
('V', _('VerantwortlicheR')) PERSON_RESPONSIBLE = 'V', _('VerantwortlicheR')
]
job_role = models.CharField(max_length=2, choices=__choices, default='M')
jobmember = models.Manager() job_role = models.CharField(max_length=2, choices=JobRole.choices, default=JobRole.MEMBER)
members = MemberManager()
active_member = ActiveMemberManager() active_member = ActiveMemberManager()
inactive_member = InactiveMemberManager() inactive_member = InactiveMemberManager()
jobs = JobManager()

View File

@@ -1,3 +1,3 @@
from django.test import TestCase # from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@@ -4,5 +4,7 @@ from . import views
urlpatterns = [ urlpatterns = [
path('', views.index, name='members.index'), path('', views.index, name='members'),
path('<str:filter>', views.index),
path('jobs/<str:slug>', views.index),
] ]

View File

@@ -1,31 +1,65 @@
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse # from django.http import HttpResponse
from collections import deque from collections import deque
from .models import Member, Job, JobMember, JobGroup, MemberSerializer from .models import Member, JobMember, JobGroup, MemberSerializer
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework import permissions from rest_framework import permissions
from django_filters.rest_framework import DjangoFilterBackend # from django_filters.rest_framework import DjangoFilterBackend
def index(request): def index(request, slug=None, filter=None):
#members = deque(Member.all_members.all()) job_group = deque(JobGroup.objects.all())
job_list = []
members = None
if slug is not None:
job_names = JobMember.jobs.get_job_names(slug=slug)
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]))
else:
if filter is None:
members = deque(Member.all_members.all()) members = deque(Member.all_members.all())
jobmembers = deque(JobMember.jobmember.all()) elif filter in Member.MemberRole:
jobs = deque(Job.objects.all()) members = deque(Member.all_members.filter(role=filter))
jobgroups = deque(JobGroup.objects.all()) else:
members = None
context = { context = {
"job_group": job_group,
"job_list": job_list,
"members": members, "members": members,
"jobmembers" : jobmembers,
"jobgroups" : jobgroups,
"jobs" : jobs,
} }
return render(request, 'members/index.html', context) return render(request, 'members/index.html', context)
<<<<<<< HEAD
def show_job(request, slug=None):
job=Job.objects.get(slug=slug)
return render(request, 'members/show_job.html', {"job": job})
def show_member(request, slug=None):
member=Member.objects.get()
return render(request, 'members/show_member.html', {"member": member})
def list(request, filter=None):
"""
View for a list of members filtered or not
"""
if filter is None:
members = deque(Member.all_members.all())
if filter in Member.role_choices:
members=deque(Member.all_members.filter(role=filter).all())
return render(request, 'members/list.html',{"members": members})
=======
>>>>>>> origin/master
class MemberViewSet(viewsets.ModelViewSet): class MemberViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows users to be viewed or edited. API endpoint that allows users to be viewed or edited.
@@ -34,9 +68,9 @@ class MemberViewSet(viewsets.ModelViewSet):
serializer_class = MemberSerializer serializer_class = MemberSerializer
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
#filter_backends = [DjangoFilterBackend] # filter_backends = [DjangoFilterBackend]
#filterset_fields = ['legacy_id', 'slug','legacy_rubrik_id'] # filterset_fields = ['legacy_id', 'slug','legacy_rubrik_id']
lookup_field='name' lookup_field = 'name'
def pre_save(self, obj): def pre_save(self, obj):
obj.image = self.request.FILES.get('image') obj.image = self.request.FILES.get('image')

View File

@@ -1,5 +1,5 @@
import django.contrib.auth.admin # import django.contrib.auth.admin
import django.contrib.auth.models # import django.contrib.auth.models
import taggit.admin import taggit.admin
from django.contrib import admin, auth from django.contrib import admin, auth
@@ -11,6 +11,9 @@ admin.site.unregister(auth.models.User)
admin.site.unregister(auth.models.Group) admin.site.unregister(auth.models.Group)
admin.site.unregister(taggit.models.Tag) admin.site.unregister(taggit.models.Tag)
def make_fetmeeting(modeladmin, request, queryset):
queryset.update(post_type ='F')
make_fetmeeting.short_description = "In eine Fachschaftssitzung konvertieren"
class MyPostAdmin(admin.ModelAdmin): class MyPostAdmin(admin.ModelAdmin):
form = MyPostForm form = MyPostForm
@@ -33,21 +36,27 @@ class MyPostAdmin(admin.ModelAdmin):
"jquery-ui/jquery-ui.min.js", "jquery-ui/jquery-ui.min.js",
] ]
class MyEventAdmin(MyPostAdmin): class MyEventAdmin(MyPostAdmin):
form = MyEventForm form = MyEventForm
model = Event model = Event
list_display = ['title', 'subtitle', 'slug', 'event_start', 'public_date'] list_display = ['title', 'subtitle', 'slug', 'event_start', 'public_date']
actions=[make_fetmeeting]
admin.site.register(Event, MyEventAdmin) admin.site.register(Event, MyEventAdmin)
class MyNewsAdmin(MyPostAdmin): class MyNewsAdmin(MyPostAdmin):
form = MyNewsForm form = MyNewsForm
model = News model = News
admin.site.register(News, MyNewsAdmin) admin.site.register(News, MyNewsAdmin)
class MyFetMeetingAdmin(MyEventAdmin): class MyFetMeetingAdmin(MyEventAdmin):
form = MyFetMeetingForm form = MyFetMeetingForm
model = FetMeeting model = FetMeeting
admin.site.register(FetMeeting, MyFetMeetingAdmin) admin.site.register(FetMeeting, MyFetMeetingAdmin)

View File

@@ -17,6 +17,7 @@ class MyPostForm(forms.ModelForm):
'js/tag_completion.js', # to get a list for tag autocompletion via ajax 'js/tag_completion.js', # to get a list for tag autocompletion via ajax
) )
class MyNewsForm(MyPostForm): class MyNewsForm(MyPostForm):
class Meta: class Meta:
model = News model = News
@@ -27,6 +28,7 @@ class MyNewsForm(MyPostForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set super().__init__(*args, **kwargs) # to get the self.fields set
class MyEventForm(MyPostForm): class MyEventForm(MyPostForm):
class Meta: class Meta:
model = Event model = Event
@@ -44,6 +46,7 @@ class MyEventForm(MyPostForm):
if 'event_place' in self.fields: if 'event_place' in self.fields:
self.fields['event_place'].required = True self.fields['event_place'].required = True
class MyFetMeetingForm(MyEventForm): class MyFetMeetingForm(MyEventForm):
class Meta: class Meta:
model = FetMeeting model = FetMeeting

View File

@@ -8,8 +8,8 @@ from django.utils.translation import gettext_lazy as _
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
#from ckeditor_uploader import RichTextUploadingField # from ckeditor_uploader import RichTextUploadingField
import uuid # import uuid
import re import re
from rest_framework import serializers from rest_framework import serializers
@@ -27,25 +27,29 @@ class PostManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset() return super().get_queryset()
class ArticleManager(models.Manager): class ArticleManager(models.Manager):
""" """
Provide a query set only for "Article" Provide a query set only for "Article"
regular fet meetings should not be contained in the news stream regular fet meetings should not be contained in the news stream
""" """
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(Q(post_type='E') | Q(post_type='N')) return super().get_queryset().filter(Q(post_type='E') | Q(post_type='N')).order_by('-public_date')
class NewsManager(models.Manager): class NewsManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(~Q(is_event=True)) return super().get_queryset().filter(~Q(is_event=True))
class EventManager(models.Manager): class EventManager(models.Manager):
""" """
Provide a query set only for "Events" Provide a query set only for "Events"
regular fet meetings should not be contained in the news stream regular fet meetings should not be contained in the news stream
""" """
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(Q(is_event=True) & Q(post_type='E')) return super().get_queryset().filter(Q(is_event=True) & ~Q(post_type='F')).order_by('-public_date')
class FetMeetingManager(models.Manager): class FetMeetingManager(models.Manager):
def get_queryset(self): def get_queryset(self):
@@ -62,7 +66,7 @@ class Category(models.Model):
subtitle = models.CharField(max_length=500, null=True, blank=True) subtitle = models.CharField(max_length=500, null=True, blank=True)
# Slug = Text Basierter url bestandteil zb Fetsitzung 22.1.2020 --> fetsitzung_22_1_2020 für Url # Slug = Text Basierter url bestandteil zb Fetsitzung 22.1.2020 --> fetsitzung_22_1_2020 für Url
slug = models.SlugField(unique=True,null=True,blank=True) slug = models.SlugField(unique=True, null=True, blank=True)
# Ein Haupt Bild für den Post # Ein Haupt Bild für den Post
image = models.ImageField(null=True, blank=True) image = models.ImageField(null=True, blank=True)
@@ -72,8 +76,9 @@ class Category(models.Model):
verbose_name = "Category" verbose_name = "Category"
verbose_name_plural = "Categories" verbose_name_plural = "Categories"
class Post(models.Model): class Post(models.Model):
#id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
legacy_id = models.IntegerField(null=True) legacy_id = models.IntegerField(null=True)
legacy_rubrik_id = models.IntegerField(null=True) legacy_rubrik_id = models.IntegerField(null=True)
# Titel des Posts # Titel des Posts
@@ -132,7 +137,7 @@ class Post(models.Model):
if self.image: if self.image:
return self.image.url return self.image.url
else: else:
image=self.find_an_image() image = self.find_an_image()
if image: if image:
return image.url return image.url
else: else:
@@ -145,12 +150,13 @@ class Post(models.Model):
"find an image via another post" "find an image via another post"
# TODO: Explain why this image is selected on save of the image # TODO: Explain why this image is selected on save of the image
# Query all posts that have a slug that equals one of the tags # Query all posts that have a slug that equals one of the tags
posts1 = Post.objects.filter(slug__in=self.tags.names()).filter(image__isnull=False)[0:1].all() posts1 = Post.objects.filter(
slug__in=self.tags.names()).filter(image__isnull=False)[0:1].all()
if len(posts1) > 0: if len(posts1) > 0:
return posts1.get().image return posts1.get().image
#posts2=self.tags.similar_objects() # posts2=self.tags.similar_objects()
#for p in posts2: # for p in posts2:
# if p.image is not None: # if p.image is not None:
# return p.image # return p.image
return None return None
@@ -170,7 +176,8 @@ class Post(models.Model):
*re.findall(r'\#([\d\w-]+)', str(self.title))) *re.findall(r'\#([\d\w-]+)', str(self.title)))
def __str__(self): def __str__(self):
return "Post (%s, %s): %s " %(self.slug, self.public_date.strftime("%d.%m.%Y"), self.title) return "Post (%s, %s): %s " % (self.slug, self.public_date.strftime("%d.%m.%Y"), self.title)
class PostSerializer(serializers.HyperlinkedModelSerializer): class PostSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
@@ -186,9 +193,10 @@ class PostSerializer(serializers.HyperlinkedModelSerializer):
'image', 'image',
'event_start', 'event_start',
'event_end', 'event_end',
'is_fetsitzung' 'is_fetsitzung',
] ]
class News(Post): class News(Post):
objects = NewsManager() objects = NewsManager()
@@ -204,6 +212,7 @@ class News(Post):
super().save(*args, **kwargs) super().save(*args, **kwargs)
class Event(Post): class Event(Post):
objects = EventManager() objects = EventManager()
@@ -218,6 +227,7 @@ class Event(Post):
super().save(*args, **kwargs) super().save(*args, **kwargs)
class FetMeeting(Event): class FetMeeting(Event):
objects = FetMeetingManager() objects = FetMeetingManager()
@@ -232,13 +242,13 @@ class FetMeeting(Event):
self.slug = slugify(self.event_start.date()) + "-" + slugify(self.title) self.slug = slugify(self.event_start.date()) + "-" + slugify(self.title)
self.body = "TODO: Agenda + Protokoll Link" self.body = "TODO: Agenda + Protokoll Link"
#TODO # TODO
#self.image # self.image
self.has_protocol = True self.has_protocol = True
self.has_agenda = True self.has_agenda = True
#TODO # TODO
# self.protocol_key # self.protocol_key
# self.agenda_key # self.agenda_key

View File

@@ -5,9 +5,8 @@ from django.utils.safestring import mark_safe
register = template.Library() register = template.Library()
@register.filter(is_safe=True) @register.filter(is_safe=True)
@stringfilter @stringfilter
def tags_to_url(value): def tags_to_url(value):
#return "Tag to url: %s" % value # return "Tag to url: %s" % value
return mark_safe(re.sub(r'\#([\d\w-]+)', '<a href="/posts/t/\g<1>">#\g<1></a>', value)) return mark_safe(re.sub(r'\#([\d\w-]+)', r'<a href="/posts/t/\g<1>">#\g<1></a>', value))

View File

@@ -1,3 +1,3 @@
from django.test import TestCase # from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@@ -2,7 +2,7 @@ from django.urls import path
from . import views from . import views
urlpatterns=[ urlpatterns = [
path('func/tag_complete', views.tag_complete), path('func/tag_complete', views.tag_complete),
path('func/slug_calc', views.slug_calc), path('func/slug_calc', views.slug_calc),
path('t/<str:tag>', views.tags, name='posts.tags'), path('t/<str:tag>', views.tags, name='posts.tags'),

View File

@@ -1,13 +1,13 @@
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse, HttpResponseServerError
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from django.core.cache import cache # from django.core.cache import cache
from django.utils.text import slugify from django.utils.text import slugify
from django.utils import timezone from django.utils import timezone
from taggit.models import Tag from taggit.models import Tag
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework import permissions # from rest_framework import permissions
from .models import Post, PostSerializer from .models import Post, PostSerializer
@@ -20,26 +20,28 @@ from collections import deque
def index(request): def index(request):
posts = deque(Post.objects.order_by('-public_date').all()) posts = deque(Post.objects.order_by('-public_date').all())
f = lambda p: p.tags
def f(p):
return p.tags
t = map(f, posts) t = map(f, posts)
return render(request, 'posts/index.html', {"posts": posts, "tags_list": t}) return render(request, 'posts/index.html', {"posts": posts, "tags_list": t})
def tags(request,tag=""): def tags(request, tag=""):
posts = deque(Post.objects.filter(tags__name=tag)) posts = deque(Post.objects.filter(tags__name=tag))
return render(request, 'posts/index.html', {"posts": posts, "tags_list": None}) return render(request, 'posts/index.html', {"posts": posts, "tags_list": None})
def show(request,id=None): def show(request, id=None):
if id.isdigit() or id is int: if id.isdigit() or id is int:
p = Post.objects.get(id=int(id)) p = Post.objects.get(id=int(id))
elif id != "" and not id is None: elif id != "" and id is not None:
p = Post.objects.get(slug=(id)) p = Post.objects.get(slug=(id))
context = { context = {
"post": p, "post": p,
"next": get_next_dict().get(p.slug,None), "next": get_next_dict().get(p.slug, None),
"related_posts": p.tags.similar_objects() "related_posts": p.tags.similar_objects()
} }
return render(request, 'posts/show.html', context) return render(request, 'posts/show.html', context)
@@ -77,7 +79,7 @@ def tag_complete(request):
tag_objects = Tag.objects.filter(name__istartswith=term) tag_objects = Tag.objects.filter(name__istartswith=term)
tag_array =[] tag_array = []
for elem in tag_objects: for elem in tag_objects:
tag_array.append(elem.name) tag_array.append(elem.name)
@@ -87,15 +89,15 @@ def tag_complete(request):
def get_next_dict(): def get_next_dict():
#TODO: Docstring # TODO: Docstring
posts = Post.article_objects.order_by('-public_date').values('slug') posts = Post.article_objects.order_by('-public_date').values('slug')
print(posts) print(posts)
d = {} d = {}
print(d) print(d)
for k,v in enumerate(posts): for k, v in enumerate(posts):
if k == len(posts) - 1: if k == len(posts) - 1:
break break
d[v['slug']] = posts[k+1]['slug'] d[v['slug']] = posts[k + 1]['slug']
print(d) print(d)
return d return d
@@ -106,9 +108,9 @@ class PostViewSet(viewsets.ModelViewSet):
""" """
queryset = Post.objects.all().order_by('-public_date') queryset = Post.objects.all().order_by('-public_date')
serializer_class = PostSerializer serializer_class = PostSerializer
#permission_classes = [permissions.IsAuthenticated] # permission_classes = [permissions.IsAuthenticated]
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ['legacy_id', 'slug','legacy_rubrik_id'] filterset_fields = ['legacy_id', 'slug', 'legacy_rubrik_id']
lookup_field = 'slug' lookup_field = 'slug'
def pre_save(self, obj): def pre_save(self, obj):

View File

@@ -5,3 +5,4 @@ Pillow
djangorestframework djangorestframework
django-static-jquery-ui django-static-jquery-ui
docutils docutils
easy-thumbnails

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

8911
fet2020/static/app.css Normal file

File diff suppressed because one or more lines are too long

22644
fet2020/static/app.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,162 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/assets/js/building-blocks/responsive-hidden-nav.js":
/*!****************************************************************!*\
!*** ./src/assets/js/building-blocks/responsive-hidden-nav.js ***!
\****************************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
var $topBar = $('[data-responsive-hidden-nav]');
var $button = $('[data-responsive-hidden-nav] .responsive-hidden-button');
var $visibleLinks = $('[data-responsive-hidden-nav] .visible-links');
var $hiddenLinks = $('[data-responsive-hidden-nav] .hidden-links');
var responsiveBreaks = []; // Empty List (Array) on initialization
function updateTopBar() {
var availableSpace = $button.hasClass('hidden') ? $topBar.width() : $topBar.width() - $button.width() - 30; // Calculation of available space on the logic of whether button has the class `hidden` or not
if ($visibleLinks.width() > availableSpace) {
// Logic when visible list is overflowing the nav
responsiveBreaks.push($visibleLinks.width()); // Record the width of the list
$visibleLinks.children().last().prependTo($hiddenLinks); // Move item to the hidden list
// Show the resonsive hidden button
if ($button.hasClass('hidden')) {
$button.removeClass('hidden');
}
} else {
// Logic when visible list is not overflowing the nav
if (availableSpace > responsiveBreaks[responsiveBreaks.length - 1]) {
// Logic when there is space for another item in the nav
$hiddenLinks.children().first().appendTo($visibleLinks);
responsiveBreaks.pop(); // Move the item to the visible list
} // Hide the resonsive hidden button if list is empty
if (responsiveBreaks.length < 1) {
$button.addClass('hidden');
$hiddenLinks.addClass('hidden');
}
}
$button.attr("count", responsiveBreaks.length); // Keeping counter updated
if ($visibleLinks.width() > availableSpace) {
// Occur again if the visible list is still overflowing the nav
updateTopBar();
}
} // Window listeners
$(window).resize(function () {
updateTopBar();
});
$button.on('click', function () {
$hiddenLinks.toggleClass('hidden');
});
updateTopBar();
/***/ }),
/***/ 0:
/*!**********************************************************************!*\
!*** multi ./src/assets/js/building-blocks/responsive-hidden-nav.js ***!
\**********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /srv/test_1/myproject/src/assets/js/building-blocks/responsive-hidden-nav.js */"./src/assets/js/building-blocks/responsive-hidden-nav.js");
/***/ })
/******/ });
//# sourceMappingURL=responsive-hidden-nav.js.map

File diff suppressed because one or more lines are too long

View File

@@ -32,36 +32,11 @@
</a> </a>
<div class="article-row-section"> <div class="article-row-section">
{% with post=featured_post %} {% with post=featured_post %}
<a href="{{post.url}}"> {% include 'posts/partials/_article_row.html' %}
{% endwith %}
<article class="article-row"> {% with post=featured_post2 %}
{% include 'posts/partials/_article_row.html' %}
<div class="article-row-content">
<h1 class="article-row-content-header">{{post.title}}</h1>
<p class="article-row-content-description">{{post.subtitle}}</p>
<p class="article-row-content-author">{{post.author}}</p>
<time class="article-row-content-time" datetime="2008-02-14 20:00">{{post.public_date}}</time>
</div>
</article>
</a>
{% endwith %} {% endwith %}
<a href="#">
<article class="article-row">
<div class="article-row-content">
<h1 class="article-row-content-header">Nächste Fachschaftssitzung</h1>
<p class="article-row-content-description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore accusamus sint quas, odit, enim architecto officiis culpa!</p>
<p class="article-row-content-author">By Yeti</p>
<time class="article-row-content-time" datetime="2008-02-14 20:00">July 14th 2021</time>
</div>
</article>
</a>
</div> </div>
</div> </div>
@@ -74,27 +49,19 @@
<div class="grid-x grid-x-padding"> <div class="grid-x grid-x-padding">
<div class="medium-8 cell"> <div class="medium-8 small-12 small-order-2 medium-order-1"">
{% for post in posts %} {% for post in posts %}
{% include 'posts/_posts_hero.html' %} {% include 'posts/partials/_posts_hero.html' %}
{% endfor %} {% endfor %}
</div> </div>
<div class="medium-4 cell"> <div class="medium-4 small-12 small-order-1 medium-order-2 padding-1">
<div class="date-box"> {% for post in events %}
{% include 'posts/partials/_date_box.html' %}
{% endfor %}
<span class="date-badge badge primary" style="">
<span class="date-badge-day">16</span>
<span class="date-badge-month">Apr</span>
</span>
<span class="date-text"><strong>Title</strong></span>
</div>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@@ -23,7 +23,7 @@
<li class=""><a href="{%url 'home'%}">Aktuelles</a> </li> <li class=""><a href="{%url 'home'%}">Aktuelles</a> </li>
<li class=""><a href="/fotos">Fotos</a> </li> <li class=""><a href="/fotos">Fotos</a> </li>
<li class=""><a href="{%url 'members.index'%}">Mitarbeiter</a> <li class=""><a href="{%url 'members'%}">Mitarbeiter</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -1,79 +1,46 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div class="grid-container"> <div class="grid-container">
<div class="grid-x"> <h1>Mitglieder / Tätigkeiten</h1>
<div class="medium-8 cell">
<h1>Members</h1> <!-- Nav tabs -->
{% for m in members %} <ul class="nav nav-tabs nav-fill">
<div class="member-hero-text"> <a class="active" id="members" data-toggle="tab" href="/members">Mitglieder</a>
{% if m.image %} <a id="members" data-toggle="tab" href="/members/A">Aktive Mitglieder</a>
<img src={{m.image.url}} style="width:150px;"/> </br> <a id="members" data-toggle="tab" href="/members/P">Inaktive Mitglieder</a>
{% else %} {% for job in job_group %}
{% endif %} <a id="jobs-{{job.id}}" data-toggle="tab" href="/members/jobs/{{job.slug}}">{{job.name}}</a>
Name: {{m.firstname|safe}} {{m.surname}} </br>
Spitzname: {{m.nickname|safe}} </br>
Mailaccount: {{m.mailaccount|safe}} </br>
Beschreibung: {{m.description|safe}} </br>
Geburtstag: {{m.birthday}} </br>
Telefonnummer: {{m.phone}} </br>
Adresse: {{m.address}} </br>
</div>
</br>
<h2>Jobs</h2>
{% for jobm in jobmembers %}
{% if m == jobm.member %}
Job: {{ jobm.job.shortterm }} </br>
Job Start: {{ jobm.job_start }} </br>
Job Ende: {{ jobm.job_end }} </br>
{% else %}
{% endif %}
{% endfor %} {% endfor %}
<hr/> </ul>
<!-- Tab panes -->
<div class="tab-content" id="nav-tabContent">
<div id="members" class="tab-pane fade in active">
{% if members == None %}
{% else %}
{% include 'members/members_list.html' %}
{% endif %}
</div>
<div id="jobs-{{job.id}}" class="tab-pane">
{% if members is None %}
{% for job in job_list %}
{% if job_list|length > 1 %}
<h2>{{job.0}}</h2>
{% endif %}
{% with active_members=job.1 inactive_members=job.2 %}
{% include 'members/jobs_list.html' %}
{% endwith %}
{% endfor %} {% endfor %}
<h1>Job Groups</h1>
<h2>pinned JG</h2>
{% for jg in jobgroups %}
{% if jg.is_pinned %}
JobGroup: {{ jg.name }} </br>
{% for job in jobs %}
{% if job.job_group.name == jg.name %}
Job: {{ job.name }} </br>
{% for jobm in jobmembers %}
{% if job.name == jobm.job.name %}
Member Name: {{ jobm.member.nickname }} </br>
{% else %}
{% endif %} {% endif %}
{% endfor %}
{% else %}
{% endif %}
{% endfor %}
{% else %}
{% endif %}
{% endfor %}
<hr/>
<h2>unpinned JG</h2>
{% for jg in jobgroups %}
{% if jg.is_pinned %}
{% else %}
JobGroup: {{ jg.name }} </br>
{% for job in jobs %}
{% if job.job_group.name == jg.name %}
Job: {{ job.name }} </br>
{% for jobm in jobmembers %}
{% if job.name == jobm.job.name %}
Member Name: {{ jobm.member.nickname }} </br>
{% else %}
{% endif %}
{% endfor %}
{% else %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</div> </div>
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,26 @@
<div class="grid-container">
Aktuelle Mitglieder: {{active_members.count}}
<div class="grid-x">
{% for mem in active_members %}
<div class="medium-6 cell">
<h2>{{mem.get_job_role_display}} (seit {{mem.job_start}})</h2>
{% with member=mem.member %}
{% include 'members/partials/_member_details.html' %}
{% endwith %}
</div>
{% endfor %}
</div>
Vergangene Mitglieder: {{inactive_members.count}}
<div class="grid-x">
{% for mem in inactive_members %}
<div class="medium-6 cell">
<h2>{{mem.get_job_role_display}} ({{mem.job_start}} - {{mem.job_end}})</h2>
{% with member=mem.member %}
{% include 'members/partials/_member_details.html' %}
{% endwith %}
</div>
{% endfor %}
</div>

View File

@@ -0,0 +1,26 @@
<div class="grid-container">
<h1> Mitarbeiter Liste </h1>
<h2> Grid Style</h2>
<div class="grid-x">
{% for member in members %}
<div class="medium-3 large-2 small-6 cell">
{% include 'members/partials/_member.html' %}
</div>
{% endfor %}
</div>
<h2> Grid Style 2</h2>
<div class="grid-x">
{% for member in members %}
{% include 'members/partials/_member.html' %}
{% endfor %}
</div>
<h2>Detail List</h2>
<div class="grid-container">
{% for member in members %}
{% include 'members/partials/_member_details.html' %}
{% endfor %}
</div>
</div>

View File

@@ -0,0 +1,8 @@
{# only thumb and name of member #}
{% load thumbnail %}
<a class="thumbnail member-thumb" style="width:150px;height:150px">
{% if member.image %}<img src="{{member.image | thumbnail_url:'thumb'}}" />{% endif %}
<div class="thumb-layer"><div><h1>{{member.nickname}}</h1> <p>{{member.firstname}} {{member.surname}}</p></div></div>
</a>

View File

@@ -0,0 +1,19 @@
{# This template shows one member and all the details (that are ment for public) including a list of current jobs #}
{% load thumbnail %}
<div class="media-object">
<div class="media-object-section">
<div class="thumbnail">
<img src= "{{member.image.url}}" style="width:150px;">
</div>
</div>
<div class="media-object-section main-section">
<h1>{{member.firstname}} {{member.surname}}</h1>
<p>Spitzname: {{member.nickname}} </br>
Name: {{member.firstname}} {{member.surname}} </br>
Mailaccount: {{member.mailaccount}} </br>
Beschreibung: {{member.description|safe}} </br>
</p>
</div>
</div>

View File

@@ -3,10 +3,12 @@
{% block content %} {% block content %}
<div class="grid-container"> <div class="grid-container">
<div class="grid-x"> <div class="grid-x">
<div class="medium-8 cell"> <div class="medium-8 cell">
{% for post in posts %} {% for post in posts %}
{% include 'posts/_posts_hero.html' %} {% include 'posts/partials/_posts_hero.html' %}
{% endfor %} {% endfor %}

View File

@@ -0,0 +1,15 @@
<a href="{{post.url}}">
<article class="article-row">
<div class="article-row-content">
<h1 class="article-row-content-header">{{post.title}}</h1>
<p class="article-row-content-description">{{post.subtitle}}</p>
<p class="article-row-content-author">{{post.author}}</p>
<time class="article-row-content-time" datetime="2008-02-14 20:00">{{post.public_date}}</time>
</div>
</article>
</a>

View File

@@ -0,0 +1,10 @@
<a href ="">
<div class="date-box">
<span>
<span class="date-badge badge primary" style="">
<span class="date-badge-day">16</span>
<span class="date-badge-month">Apr</span>
</span></span>
<span class="date-text"><strong>{{post.title}}</strong></span>
</div></a>

View File

@@ -0,0 +1,8 @@
<a href="{% url 'posts.show' post.slug %}">
<div class="news-hero padding-bottom-1" style="background-image:url('{{post.imageurl}}')">
<div class="news-hero-text">
<h1>{{post.title}}</h1>
<h2>{{post.subtitle}}</h2>{{post}}
</div>
</div>
</a>