From 5e56fc0139c33c425888f910eb73720f441c997b Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Sat, 30 Jan 2021 17:40:40 -0700 Subject: [PATCH] Add home; overwrite save method on Period model --- accounts/models.py | 1 + attendance/forms.py | 17 ++++++ attendance/models.py | 8 ++- .../attendance_overview_instructor.html | 3 + .../attendance_overview_student.html | 10 +++- .../templates/attendance/code_form.html | 3 +- .../templates/attendance/period_detail.html | 2 + .../templates/attendance/period_form.html | 5 +- attendance/urls.py | 1 + attendance/views.py | 32 +++++++---- home/__init__.py | 0 home/admin.py | 3 + home/apps.py | 5 ++ home/migrations/__init__.py | 0 home/models.py | 3 + home/templates/home/home.html | 6 ++ home/tests.py | 3 + home/urls.py | 12 ++++ home/views.py | 5 ++ static/css/base.css | 56 +++++++++---------- templates/application.html | 6 +- tracker/settings.py | 1 + tracker/urls.py | 1 + 23 files changed, 133 insertions(+), 50 deletions(-) create mode 100644 home/__init__.py create mode 100644 home/admin.py create mode 100644 home/apps.py create mode 100644 home/migrations/__init__.py create mode 100644 home/models.py create mode 100644 home/templates/home/home.html create mode 100644 home/tests.py create mode 100644 home/urls.py create mode 100644 home/views.py diff --git a/accounts/models.py b/accounts/models.py index a12186b..6330c67 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -29,6 +29,7 @@ class Student(models.Model): student_number = models.IntegerField() department = models.ForeignKey(Department, on_delete=models.CASCADE) is_clocked_in = models.BooleanField(default=False) + current_period_id = models.IntegerField(blank=True, null=True) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) diff --git a/attendance/forms.py b/attendance/forms.py index 0fd6005..5a3e492 100644 --- a/attendance/forms.py +++ b/attendance/forms.py @@ -7,3 +7,20 @@ class AttendanceUpdateForm(forms.Form): max_length=100, widget=forms.TextInput(attrs={'autofocus': True}) ) + +class PeriodForm(forms.ModelForm): + class Meta: + model = Period + fields = ['student', 'station_number', 'clocked_in', 'clocked_out'] + widgets = { + 'clocked_in': forms.DateTimeInput(format = '%Y-%m-%d %H:%M', attrs = { + 'placeholder': '2006-10-25 14:30' + }), + 'clocked_out': forms.DateTimeInput(format = '%Y-%m-%d %H:%M', attrs = { + 'placeholder': '2006-10-25 14:30' + }), + } + labels = { + 'clocked_in': 'Clocked in (example 2006-10-25 14:30):', + 'clocked_out': 'Clocked out (example 2006-10-25 14:30):', + } diff --git a/attendance/models.py b/attendance/models.py index d17d700..34f5e27 100644 --- a/attendance/models.py +++ b/attendance/models.py @@ -1,3 +1,4 @@ +from datetime import datetime from django.db import models from django.urls import reverse from accounts.models import Student @@ -20,7 +21,7 @@ class Code(models.Model): class Period(models.Model): student = models.ForeignKey(Student, on_delete=models.CASCADE) - clocked_in = models.DateTimeField(auto_now_add=True) + clocked_in = models.DateTimeField() clocked_out = models.DateTimeField(blank=True, null=True) station_number = models.IntegerField() duration = models.DurationField(blank=True, null=True) @@ -38,3 +39,8 @@ class Period(models.Model): def __str__(self): return f'{self.clocked_in}: {self.student.user.first_name} {self.student.user.last_name}' + + def save(self, *args, **kwargs): + if isinstance(self.clocked_out, datetime): + self.duration = self.clocked_out - self.clocked_in + super(Period, self).save(*args, **kwargs) diff --git a/attendance/templates/attendance/attendance_overview_instructor.html b/attendance/templates/attendance/attendance_overview_instructor.html index de5d202..1825ac8 100644 --- a/attendance/templates/attendance/attendance_overview_instructor.html +++ b/attendance/templates/attendance/attendance_overview_instructor.html @@ -7,6 +7,9 @@

Active sessions

+

+ + Add new session +

diff --git a/attendance/templates/attendance/attendance_overview_student.html b/attendance/templates/attendance/attendance_overview_student.html index 7033e47..134623d 100644 --- a/attendance/templates/attendance/attendance_overview_student.html +++ b/attendance/templates/attendance/attendance_overview_student.html @@ -1,13 +1,17 @@
-
+

{{ user.first_name }} {{ user.last_name }}

Update profile
{{ user.student.department.name }}
- {% if user.student.is_clocked_in %} + {% if user.student.is_clocked_in and user.student.code_set.last %}

You are currently clocked in.
- Current sesson: {{ period_list.first.clocked_in|timesince }}

+ Current sesson: {{ current_period.clocked_in|timesince }}

Clock out → + {% elif user.student.is_clocked_in and not user.student.code_set.last %} +

You are currently clocked in.
+ Current sesson: {{ current_period.clocked_in|timesince }}

+ Clock out → {% elif user.student.code_set.last %}

You are not clocked in.

Clock in → diff --git a/attendance/templates/attendance/code_form.html b/attendance/templates/attendance/code_form.html index f6fb5dd..7a32adf 100644 --- a/attendance/templates/attendance/code_form.html +++ b/attendance/templates/attendance/code_form.html @@ -8,7 +8,8 @@ {% csrf_token %} {{ form.as_p }} - + or + Cancel
{% endblock %} diff --git a/attendance/templates/attendance/period_detail.html b/attendance/templates/attendance/period_detail.html index 5d12cbb..c13619b 100644 --- a/attendance/templates/attendance/period_detail.html +++ b/attendance/templates/attendance/period_detail.html @@ -19,6 +19,8 @@
{{ period.clocked_in }}
Clocked out
{{ period.clocked_out }}
+
Duration
+
{{ period.duration }}
{% endblock %} diff --git a/attendance/templates/attendance/period_form.html b/attendance/templates/attendance/period_form.html index 4cc43c4..cfd202d 100644 --- a/attendance/templates/attendance/period_form.html +++ b/attendance/templates/attendance/period_form.html @@ -4,11 +4,12 @@

Generate Period

-
+ {% csrf_token %} {{ form.as_p }} - + or + Cancel
{% endblock %} diff --git a/attendance/urls.py b/attendance/urls.py index 3fd30f4..3f170ce 100644 --- a/attendance/urls.py +++ b/attendance/urls.py @@ -10,6 +10,7 @@ from . import views urlpatterns = [ path('', views.AttendanceOverview.as_view(), name='attendance-overview'), path('update/', views.AttendanceUpdateView.as_view(), name='attendance-update'), + path('periods/new/', views.PeriodCreateView.as_view(), name='period-create'), path('periods//', include([ path('', views.PeriodDetailView.as_view(), name='period-detail'), path('update/', views.PeriodUpdateView.as_view(), name='period-update'), diff --git a/attendance/views.py b/attendance/views.py index 6943278..f1848cd 100644 --- a/attendance/views.py +++ b/attendance/views.py @@ -12,7 +12,7 @@ from django.contrib import messages from django.contrib.auth.models import User from accounts.models import Instructor, Student from .models import Code, Period -from .forms import AttendanceUpdateForm +from .forms import AttendanceUpdateForm, PeriodForm # EXAMPLE PERMISSION MIXIN # class MyView(PermissionRequiredMixin, View): @@ -32,19 +32,18 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView): context['period_list'] = Period.objects.order_by('-clocked_in') elif hasattr(self.request.user, 'student'): # sum all duration fields for student - total_duration = Period.objects.filter( - student=self.request.user.student + periods_duration_sum = Period.objects.filter( + student = self.request.user.student ).filter( clocked_in__year=timezone.now().year ).filter( clocked_in__month=timezone.now().month - ).order_by('-clocked_in' ).aggregate(total_duration=Sum('duration')) - hours = "" + hours = 0 # Convert to hours floating point - if hasattr(total_duration, 'total_duration'): - hours = round((total_duration['total_duration'].total_seconds() / 3600), 2) + if periods_duration_sum['total_duration'] != None: + hours = round((periods_duration_sum['total_duration'].total_seconds() / 3600), 2) context['period_list'] = Period.objects.filter( student=self.request.user.student @@ -54,6 +53,7 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView): clocked_in__month=timezone.now().month ).order_by('-clocked_in') context['period_total'] = hours + context['current_period'] = Period.objects.get(pk=self.request.user.student.current_period_id) return context class AttendanceUpdateView(LoginRequiredMixin, FormView): @@ -67,14 +67,14 @@ class AttendanceUpdateView(LoginRequiredMixin, FormView): student = Student.objects.get(student_number=student_number) if student.is_clocked_in: student.is_clocked_in=False - period = student.period_set.last() + period = student.period_set.get(pk=student.current_period_id) period.clocked_out=timezone.now() - period.duration=period.clocked_out-period.clocked_in student.save() period.save() messages.add_message(self.request, messages.INFO, f'{student.user.first_name} {student.user.last_name} clocked out.') else: - student.period_set.create(student=student, station_number=station_number) + c_p = student.period_set.create(student=student, clocked_in=timezone.now(), station_number=station_number) + student.current_period_id = c_p.id student.is_clocked_in=True student.save() messages.add_message(self.request, messages.INFO, f'{student.user.first_name} {student.user.last_name} clocked in.') @@ -89,7 +89,7 @@ class AttendanceUpdateView(LoginRequiredMixin, FormView): # PERIODS class PeriodCreateView(LoginRequiredMixin, CreateView): model = Period - fields = ['student'] + form_class = PeriodForm template_name = 'attendance/period_form.html' class PeriodDetailView(LoginRequiredMixin, DetailView): @@ -98,9 +98,17 @@ class PeriodDetailView(LoginRequiredMixin, DetailView): class PeriodUpdateView(LoginRequiredMixin, UpdateView): model = Period - fields = ['clocked_out'] + form_class = PeriodForm template_name = 'attendance/period_form.html' + # When editing a period, check if it matches the current period of the student and clock them out + def form_valid(self, form): + student = form.instance.student + if form.instance.id == student.current_period_id: + student.is_clocked_in = False + student.save() + return super().form_valid(form) + def get_success_url(self): pk = self.kwargs["pk"] return reverse('period-detail', kwargs={'pk': pk}) diff --git a/home/__init__.py b/home/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/admin.py b/home/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/home/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/home/apps.py b/home/apps.py new file mode 100644 index 0000000..90dc713 --- /dev/null +++ b/home/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HomeConfig(AppConfig): + name = 'home' diff --git a/home/migrations/__init__.py b/home/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/models.py b/home/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/home/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/home/templates/home/home.html b/home/templates/home/home.html new file mode 100644 index 0000000..2d8144b --- /dev/null +++ b/home/templates/home/home.html @@ -0,0 +1,6 @@ +{% extends 'application.html' %} +{% load static %} + +{% block content %} +

Welcome home

+{% endblock %} diff --git a/home/tests.py b/home/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/home/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/home/urls.py b/home/urls.py new file mode 100644 index 0000000..d66c424 --- /dev/null +++ b/home/urls.py @@ -0,0 +1,12 @@ +from django.urls import include, path +from . import views + +# list/ /users/ +# create/ /users/new/ +# detail/ /users/1/ +# update/ /users/1/update/ (update shift preferences) +# delete/ /users/1/delete/ + +urlpatterns = [ + path('', views.HomeView.as_view(), name='home'), +] diff --git a/home/views.py b/home/views.py new file mode 100644 index 0000000..5202dac --- /dev/null +++ b/home/views.py @@ -0,0 +1,5 @@ +from django.shortcuts import render +from django.views.generic.base import TemplateView + +class HomeView(TemplateView): + template_name = "home/home.html" diff --git a/static/css/base.css b/static/css/base.css index 5ce7dd8..8342344 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -6,10 +6,8 @@ accent 2 (orange) #9b6f45 accent 3 (blue) #242e34 */ -@import url('https://fonts.googleapis.com/css2?family=Heebo:wght@400;700;900&display=swap'); - html { - font-size: 1.125em; + font-size: 100%; } body { @@ -17,46 +15,36 @@ body { margin: 0.25in auto; background-color: #f7f7f7; color: #323834; - font-family: 'Heebo', sans-serif; + font-family: 'Lato', sans-serif; font-weight: 400; - line-height: 1.65; + line-height: 1.75; } - -header { - display: flex; - align-items: baseline; - justify-content: space-between; -} - -/* Text Elements */ - p { - margin-bottom: 1.15rem; + margin-bottom: 1rem; } h1, h2, h3, h4, h5 { - /*margin: 2.75rem 0 1.05rem;*/ - margin: 0 0 1.05rem; - font-weight: 800; - line-height: 1.15; + margin: 3rem 0 1.38rem; + font-family: 'Lato', sans-serif; + line-height: 1.3; } h1 { margin-top: 0; - font-size: 2.488em; + font-size: 2.488rem; } h2 { - font-size: 2.074em; + font-size: 2.074rem; } h3 { - font-size: 1.728em; + font-size: 1.728rem; } h4 { - font-size: 1.44em; + font-size: 1.44rem; } h5 { - font-size: 1.2em; + font-size: 1.2rem; } small { - font-size: 0.833em; + font-size: 0.833rem; } a { @@ -65,14 +53,23 @@ a { white-space: nowrap; } -small { - font-size: 0.8em; -} hr { margin: 0; border: 0.8px solid #bdc3c7; } +.navigation { + display: flex; + align-items: baseline; + justify-content: space-between; +} + +.header { + display: flex; + align-items: top; + justify-content: space-between; +} + blockquote { text-align: left; padding: 0 15px; @@ -109,6 +106,7 @@ label { input[type=text], input[type=email], +input[type=number], input[type=password], select[multiple=multiple], textarea, @@ -219,4 +217,4 @@ th { /* Messages */ -.messages > .info {color: green;} +.info {color: green;} diff --git a/templates/application.html b/templates/application.html index 6edf910..6c4e9ea 100644 --- a/templates/application.html +++ b/templates/application.html @@ -9,11 +9,13 @@ {% block head %} {% endblock %} + + -
-

BTech Time Tracker

+