diff --git a/fet2020/authentications/authentications.py b/fet2020/authentications/authentications.py index 4d01d570..8d469d6a 100644 --- a/fet2020/authentications/authentications.py +++ b/fet2020/authentications/authentications.py @@ -28,6 +28,9 @@ def authentication(username, password): except LDAPBindError as e: logger.info('Username does not exist. Error: {}'.format(e)) username = None + except Exception as e: + logger.info('Connection to server lost. Error: {}'.format(e)) + username = None if not has_user: username = None diff --git a/fet2020/authentications/forms.py b/fet2020/authentications/forms.py new file mode 100644 index 00000000..204803e6 --- /dev/null +++ b/fet2020/authentications/forms.py @@ -0,0 +1,6 @@ +from django import forms + + +class LoginForm(forms.Form): + username = forms.CharField() + password = forms.CharField(label='Passwort', widget=forms.PasswordInput()) diff --git a/fet2020/authentications/views.py b/fet2020/authentications/views.py index 0d9981b2..bbf8b0a3 100644 --- a/fet2020/authentications/views.py +++ b/fet2020/authentications/views.py @@ -3,9 +3,11 @@ from django.contrib.auth import login, logout from django.contrib import messages from django.contrib.auth.models import User +from documents.etherpadlib import del_ep_cookie + from .authentications import authentication from .decorators import unauthenticated_user, authenticated_user -from documents.etherpadlib import del_ep_cookie +from .forms import LoginForm @unauthenticated_user @@ -27,7 +29,11 @@ def loginPage(request): else: messages.info(request, 'username or password is incorrect') - context = {} + form = LoginForm() + + context = { + "form": form, + } return render(request, 'authentications/login.html', context) diff --git a/fet2020/blackboard/__init__.py b/fet2020/blackboard/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fet2020/blackboard/admin.py b/fet2020/blackboard/admin.py new file mode 100644 index 00000000..3258c7a2 --- /dev/null +++ b/fet2020/blackboard/admin.py @@ -0,0 +1,21 @@ +from django.contrib import admin + +from .models import JobPosting + + +class JobPostingAdmin(admin.ModelAdmin): + model = JobPosting + fieldsets = ( + (None, { + 'fields': ( + 'companyName', + 'jobName', + 'salary', + 'pdfLocation', + 'publishDate', + ) + }), + ) + + +admin.site.register(JobPosting, JobPostingAdmin) diff --git a/fet2020/blackboard/apps.py b/fet2020/blackboard/apps.py new file mode 100644 index 00000000..a1b4f21a --- /dev/null +++ b/fet2020/blackboard/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BlackboardConfig(AppConfig): + name = 'blackboard' diff --git a/fet2020/blackboard/models.py b/fet2020/blackboard/models.py new file mode 100644 index 00000000..7f72777b --- /dev/null +++ b/fet2020/blackboard/models.py @@ -0,0 +1,76 @@ +from django.conf import settings +from django.core.validators import ValidationError +from django.db import models +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +import locale +import os +from os.path import splitext, basename + +import ghostscript + +import logging +logger = logging.getLogger('blackboard') + + +class JobPosting(models.Model): + companyName = models.CharField(max_length=128) + jobName = models.CharField(max_length=128) + salary = models.PositiveSmallIntegerField() + pdfLocation = models.FileField(upload_to='uploads/blackboard/pdf/') + pdf_thumb_location = models.CharField(max_length=128) + publishDate = models.DateField('date published', default=timezone.now) + + # Managers + all_jobPosting = models.Manager() + + class Meta: + verbose_name = "Stellenausschreibung" + verbose_name_plural = "Stellenausschreibungen" + + def __str__(self): + return str(self.publishDate) + "_" + self.companyName + "_" + self.jobName + + def pdf2jpeg(self, pdf_input_path, jpeg_output_path): + args = [ + "pef2jpeg", # actual value doesn't matter + "-dNOPAUSE", + "-sDEVICE=jpeg", + "-dDEVICEWIDTHPOINTS=600", + "-dDEVICEHEIGHTPOINTS=800", + "-sOutputFile=" + jpeg_output_path, + pdf_input_path + ] + + encoding = locale.getpreferredencoding() + args = [a.encode(encoding) for a in args] + + ghostscript.Ghostscript(*args) + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + if not os.path.exists(settings.MEDIA_ROOT + "uploads/blackboard/thumb/"): + os.makedirs(settings.MEDIA_ROOT + "uploads/blackboard/thumb/") + + pdf_thumb_location_full = settings.MEDIA_ROOT \ + + "uploads/blackboard/thumb/" \ + + splitext(basename(self.pdfLocation.name))[0] \ + + ".jpg" + + self.pdf_thumb_location = "/files/uploads/blackboard/thumb/" \ + + splitext(basename(self.pdfLocation.name))[0] \ + + ".jpg" + + self.pdf2jpeg(self.pdfLocation.path, pdf_thumb_location_full) + logger.info("SavenThumbAs: " + self.pdf_thumb_location) + super().save(*args, **kwargs) + + def clean(self): + count = 0 + for i in self.pdfLocation.name: + if i == '.': + count = count + 1 + if count > 1: # if more than one dot in filename + raise ValidationError(_('Keine Dateien mit >1 Punkten im Namen erlaubt.')) diff --git a/fet2020/blackboard/tests.py b/fet2020/blackboard/tests.py new file mode 100644 index 00000000..a79ca8be --- /dev/null +++ b/fet2020/blackboard/tests.py @@ -0,0 +1,3 @@ +# from django.test import TestCase + +# Create your tests here. diff --git a/fet2020/blackboard/urls.py b/fet2020/blackboard/urls.py new file mode 100644 index 00000000..89addfe8 --- /dev/null +++ b/fet2020/blackboard/urls.py @@ -0,0 +1,8 @@ +from django.urls import path + +from . import views + + +urlpatterns = [ + path('', views.index, name='blackboard'), +] diff --git a/fet2020/blackboard/views.py b/fet2020/blackboard/views.py new file mode 100644 index 00000000..c51eff0e --- /dev/null +++ b/fet2020/blackboard/views.py @@ -0,0 +1,14 @@ +from django.shortcuts import render +from django.utils import timezone + +from datetime import timedelta + +from .models import JobPosting + + +def index(request): + jobPost_cutoff = timezone.now().date() - timedelta(30) # 30days from now + context = { + "jobPostings": JobPosting.all_jobPosting.filter(publishDate__gt=jobPost_cutoff), + } + return render(request, 'blackboard/index.html', context) diff --git a/fet2020/fet2020/settings.py b/fet2020/fet2020/settings.py index 982d9545..869f2ab6 100644 --- a/fet2020/fet2020/settings.py +++ b/fet2020/fet2020/settings.py @@ -17,7 +17,7 @@ env = environ.Env( DEBUG=(bool, True), MYSQL_HOST=(str, "mysql"), MYSQL_PORT=(int, 3308), - MYSQL_DATABASE=(str,"fet2020db"), + MYSQL_DATABASE=(str, "fet2020db"), MYSQL_USER=(str), MYSQL_PASSWORD=(str) ) @@ -50,7 +50,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = env('DEBUG') if DEBUG: -# SECURITY WARNING: keep the secret key used in production secret! + # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'r37-i7l)vrduzz2-gira+z#u!p!di9#f+%s*5-bb($hg)55@ns' else: SECRET_KEY = env('SECRET_KEY') @@ -81,6 +81,8 @@ INSTALLED_APPS = [ 'posts.apps.PostsConfig', 'members.apps.MembersConfig', 'documents.apps.DocumentsConfig', + 'blackboard.apps.BlackboardConfig', + 'tasks.apps.TasksConfig', ] MIDDLEWARE = [ @@ -121,21 +123,21 @@ WSGI_APPLICATION = 'fet2020.wsgi.application' # https://docs.djangoproject.com/en/3.0/ref/settings/#databases if DEBUG: DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } } -} else: DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': env('MYSQL_DATABASE'), - 'USER': env('MYSQL_USER'), - 'PASSWORD':env('MYSQL_PASSWORD'), - 'HOST': env('MYSQL_HOST'), - 'PORT':env('MYSQL_PORT') - } + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': env('MYSQL_DATABASE'), + 'USER': env('MYSQL_USER'), + 'PASSWORD': env('MYSQL_PASSWORD'), + 'HOST': env('MYSQL_HOST'), + 'PORT': env('MYSQL_PORT') + } } diff --git a/fet2020/fet2020/urls.py b/fet2020/fet2020/urls.py index bb0bac6d..32459f82 100644 --- a/fet2020/fet2020/urls.py +++ b/fet2020/fet2020/urls.py @@ -38,4 +38,6 @@ urlpatterns = [ path('ckeditor/', include('ckeditor_uploader.urls')), path('api/', include(router.urls)), path('members/', include('members.urls'), name='members'), + path('blackboard/', include('blackboard.urls'), name='blackboard'), + path('tasks/', include('tasks.urls'), name='tasks'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/fet2020/fet2020/views.py b/fet2020/fet2020/views.py index 4ad4f151..33a212ba 100644 --- a/fet2020/fet2020/views.py +++ b/fet2020/fet2020/views.py @@ -26,11 +26,19 @@ def index(request): # remove the pinned post posts.remove(featured_post) + featured_event = Event.only_events.get_future_events().first() + # if there is no futurity event + if not featured_event: + featured_event = Event.only_events.get_past_events().first() + + featured_meeting = FetMeeting.objects.get_meetings() + context = { 'posts': posts, 'events': Event.all_events.get_five_events(), 'featured_post': featured_post, - 'featured_meeting': FetMeeting.objects.get_meetings(), + 'featured_event': featured_event, + 'featured_meeting': featured_meeting, 'tags_list': ", ".join(t) } diff --git a/fet2020/members/models.py b/fet2020/members/models.py index b10fa292..855c83d1 100644 --- a/fet2020/members/models.py +++ b/fet2020/members/models.py @@ -158,6 +158,12 @@ class JobGroup(models.Model): def __str__(self): return self.name + def save(self, *args, **kwargs): + if not self.slug: + self.slug = self.shortterm + + super().save(*args, **kwargs) + class Job(models.Model): name = models.CharField(max_length=128) diff --git a/fet2020/posts/managers.py b/fet2020/posts/managers.py index f46c1e24..eb0e0f46 100644 --- a/fet2020/posts/managers.py +++ b/fet2020/posts/managers.py @@ -5,7 +5,7 @@ from django.utils import timezone class PostManager(models.Manager): def get_queryset(self): - return super().get_queryset() + return super().get_queryset().order_by('-public_date') def get_visible_articles(self): return self.get_queryset().filter(is_hidden=False) @@ -34,7 +34,7 @@ class NewsManager(models.Manager): Provide a query set only for "News" """ def get_queryset(self): - return super().get_queryset().filter(post_type='N') + return super().get_queryset().filter(post_type='N').order_by('-public_date') def get_visible_articles(self): return self.get_queryset().filter(is_hidden=False) @@ -48,7 +48,8 @@ class AllEventManager(models.Manager): return super().get_queryset().filter(Q(post_type='E') | Q(post_type='F')) def get_five_events(self): - return self.get_queryset().order_by('-event_start')[:5] + date_today = timezone.now() + return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start')[:5] class EventManager(models.Manager): @@ -59,6 +60,14 @@ class EventManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(post_type='E') + def get_future_events(self): + date_today = timezone.now() + return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start') + + def get_past_events(self): + date_today = timezone.now() + return self.get_queryset().filter(event_start__lt=date_today).order_by('-event_start') + class FetMeetingManager(models.Manager): """ diff --git a/fet2020/posts/models.py b/fet2020/posts/models.py index e5d1fe34..9ffbcbca 100644 --- a/fet2020/posts/models.py +++ b/fet2020/posts/models.py @@ -219,14 +219,6 @@ class Event(Post): verbose_name = "Event" verbose_name_plural = "Events" - @property - def event_start_month(self): - return self.event_start.strftime("%b") - - @property - def event_start_day(self): - return self.event_start.strftime("%d") - def clean(self): if self.event_end is None or self.event_start is None: raise ValidationError(_('Das Datum des Events fehlt.')) diff --git a/fet2020/requirements.txt b/fet2020/requirements.txt index 0420e50f..6b492dd1 100644 --- a/fet2020/requirements.txt +++ b/fet2020/requirements.txt @@ -1,9 +1,10 @@ django==3.1.* -django-taggit==1.3.0 -django-ckeditor==5.9.0 -Pillow==7.2.0 -djangorestframework==3.11.0 +django-ckeditor==6.0.0 +django-environ==0.4.5 +django-filter==2.3.0 django-static-jquery-ui==1.12.1.1 +django-taggit==1.3.0 +djangorestframework==3.12.1 docutils==0.16 easy-thumbnails==2.7.0 etherpad-lite==0.5 @@ -11,3 +12,7 @@ django-filter ldap3 django-environ mysql-python +ldap3==2.8.1 +#mysqlclient==2.0.1 +Pillow==7.2.0 +ghostscript==0.6 diff --git a/fet2020/tasks/__init__.py b/fet2020/tasks/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fet2020/tasks/admin.py b/fet2020/tasks/admin.py new file mode 100644 index 00000000..3e8760f6 --- /dev/null +++ b/fet2020/tasks/admin.py @@ -0,0 +1,33 @@ +from django.contrib import admin + +from .models import Task, TaskList + + +class TaskAdmin(admin.ModelAdmin): + model = Task + fieldsets = ( + (None, { + 'fields': ( + 'title', + 'task_list', + 'due_date', + 'completed', + 'completed_date', + 'assigned_to', + 'note', + 'priority', + ) + }), + ) + list_display = ('title', 'task_list', 'completed', 'priority', 'due_date') + list_filter = ('task_list', ) + ordering = ('priority', ) + search_fields = ('title', ) + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + +admin.site.register(TaskList) +admin.site.register(Task, TaskAdmin) diff --git a/fet2020/tasks/apps.py b/fet2020/tasks/apps.py new file mode 100644 index 00000000..20547224 --- /dev/null +++ b/fet2020/tasks/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TasksConfig(AppConfig): + name = 'tasks' diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py new file mode 100644 index 00000000..2ef71ee2 --- /dev/null +++ b/fet2020/tasks/forms.py @@ -0,0 +1,15 @@ +from django import forms + +from .models import Task + + +class TaskForm(forms.ModelForm): + class Meta: + model = Task + + fields = [ + 'title', + 'task_list', + 'due_date', + 'assigned_to', + ] diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py new file mode 100644 index 00000000..58e9d18a --- /dev/null +++ b/fet2020/tasks/models.py @@ -0,0 +1,75 @@ +from django.conf import settings +from django.db import models +from django.db.models import Q +from django.utils import timezone + + +class TaskQuerySet(models.QuerySet): + def get_ordered(self): + return self.order_by('task_list') + + +class TaskManager(models.Manager): + def get_tasks(self, user, completed): + if completed: + return self.get_queryset().get_ordered().filter(Q(assigned_to=user)) + else: + return self.get_queryset().get_ordered().filter( + Q(assigned_to=user) + & Q(completed=completed) + ) + + def get_queryset(self): + return TaskQuerySet(self.model, using=self._db) + + +class TaskList(models.Model): + name = models.CharField(max_length=60) + slug = models.SlugField(unique=True, null=True, blank=True) + + objects = models.Manager() + + def __str__(self): + return self.name + + +class Task(models.Model): + title = models.CharField(max_length=140) + task_list = models.ForeignKey(TaskList, on_delete=models.CASCADE, null=True) + + created_date = models.DateTimeField(auto_now_add=True) + due_date = models.DateField(blank=True, null=True) + + completed = models.BooleanField(default=False) + completed_date = models.DateField(blank=True, null=True) + + created_by = models.ForeignKey( + settings.AUTH_USER_MODEL, + related_name="todo_created_by", + on_delete=models.CASCADE, + ) + assigned_to = models.ForeignKey( + settings.AUTH_USER_MODEL, + blank=True, + null=True, + related_name="todo_assigned_to", + on_delete=models.CASCADE, + ) + + note = models.TextField(blank=True, null=True) + priority = models.PositiveIntegerField(blank=True, null=True) + + objects = models.Manager() + taskmanager = TaskManager() + + def __str__(self): + return self.title + + def save(self, *args, **kwargs): + if self.completed and not self.completed_date: + self.completed_date = timezone.now().date() + + if not self.completed and self.completed_date: + self.completed_date = None + + super().save(*args, **kwargs) diff --git a/fet2020/tasks/tests.py b/fet2020/tasks/tests.py new file mode 100644 index 00000000..a79ca8be --- /dev/null +++ b/fet2020/tasks/tests.py @@ -0,0 +1,3 @@ +# from django.test import TestCase + +# Create your tests here. diff --git a/fet2020/tasks/urls.py b/fet2020/tasks/urls.py new file mode 100644 index 00000000..f1eab942 --- /dev/null +++ b/fet2020/tasks/urls.py @@ -0,0 +1,8 @@ +from django.urls import path + +from . import views + + +urlpatterns = [ + path('', views.index, name='tasks'), +] diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py new file mode 100644 index 00000000..b5870267 --- /dev/null +++ b/fet2020/tasks/views.py @@ -0,0 +1,56 @@ +from django.contrib.auth.models import User +from django.shortcuts import render +from django.utils import timezone + +from collections import deque + +from .forms import TaskForm +from .models import Task + + +def index(request): + current_user = request.user.id + current_action = False + + if request.method == 'POST': + if 'btn_input' in request.POST: + form = TaskForm(request.POST) + + if form.is_valid(): + task = form.save(commit=False) + task.created_by = request.user + task.save() + + elif 'btn_checkbox' in request.POST: + for task_id in request.POST.getlist('checkbox'): + task = Task.objects.get(id=task_id) + + if not task.completed: + task.completed = True + task.completed_date = timezone.now().date() + task.save() + + elif 'btn_user' in request.POST: + if request.POST['action'] == 'show_incompleted': + current_action = False + else: + current_action = True + + if request.POST['user'] == 'all': + current_user = None + else: + current_user = int(request.POST['user']) + + form = TaskForm() + tasks = deque(Task.taskmanager.get_tasks(user=current_user, completed=current_action)) + users = User.objects.all() + + context = { + "form": form, + "tasks": tasks, + "users": users, + "current_user": current_user, + "current_action": current_action, + } + + return render(request, 'tasks/index.html', context) diff --git a/fet2020/templates/authentications/login.html b/fet2020/templates/authentications/login.html index 85620a87..20fc8a90 100644 --- a/fet2020/templates/authentications/login.html +++ b/fet2020/templates/authentications/login.html @@ -1,123 +1,23 @@ - - - -
-{{message}}
- {% endfor %} - -{{job.jobName}}
+ Mindestgehalt: {{job.salary}}€
{{job.jobName}}
+ Mindestgehalt: {{job.salary}}€