Add custom timedelta filter and styles

This commit is contained in:
Nathan Chapman 2021-02-05 20:32:27 -07:00
parent ec573cafdc
commit 2065c6d1ee
18 changed files with 192 additions and 148 deletions

View File

@ -29,10 +29,9 @@ class Period(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
# def duration(self): @property
# duration = self.clocked_out - self.clocked_in def p_duration(self):
# duration_in_s = duration.total_seconds() return round((self.clocked_out - self.clocked_in).seconds / 3600, 2)
# return divmod(duration_in_s, 3600)[0]
def get_absolute_url(self): def get_absolute_url(self):
return reverse('period-detail', kwargs={'pk': self.pk}) return reverse('period-detail', kwargs={'pk': self.pk})

View File

@ -1,10 +1,9 @@
{% extends 'application.html' %} {% extends 'application.html' %}
{% block content %} {% block content %}
<section class="clockin panel">
<h1>Scan code to clock-in/out</h1> <h1>Scan code to clock-in/out</h1>
<form class="clockin__form" method="post" action="{% url 'attendance-update' %}">
<section>
<form method="post" action="{% url 'attendance-update' %}">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}

View File

@ -1,12 +1,13 @@
<section> {% load timedelta_filter %}
<header> <article class="instructor">
<h1>{{ user.instructor.department.name }}</h1> <section class="instructor__header panel">
<h1 class="instructor__department">{{ user.instructor.department.name }}</h1>
<p> <p>
<a href="">Generate Reports</a> <a class="instructor__generate-reports" href="">Generate Reports</a>
</p> </p>
</header> </header>
<div class="instructor__active_periods">
<h3>Active sessions</h3> <h3>Students clocked-in</h3>
<p> <p>
<a class="action-button" href="{% url 'period-create' %}">+ Add new session</a> <a class="action-button" href="{% url 'period-create' %}">+ Add new session</a>
</p> </p>
@ -40,8 +41,9 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div>
</section> </section>
<article> <section class="instructor__attendance_log">
<div> <div>
<h3>Attendance log</h3> <h3>Attendance log</h3>
<table> <table>
@ -76,8 +78,8 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</article> </section>
<article> <section class="instructor__total_hours">
<table> <table>
<thead> <thead>
<tr> <tr>
@ -89,11 +91,12 @@
{% for student in student_list %} {% for student in student_list %}
<tr> <tr>
<td>{{ student.user.first_name }} {{ student.user.last_name }}</td> <td>{{ student.user.first_name }} {{ student.user.last_name }}</td>
<td>{{ student.total_hours }}</td> <td>{{ student.total_hours|dimedelta_format }}</td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="2">No periods yet.</td></tr> <tr><td colspan="2">No periods yet.</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</section>
</article> </article>

View File

@ -1,9 +1,11 @@
<section class="student panel"> {% load timedelta_filter %}
<article class="student">
<section class="student__header panel">
<h1 class="student__department">{{ user.student.department.name }}</h1> <h1 class="student__department">{{ user.student.department.name }}</h1>
{% if user.student.is_clocked_in %} {% if user.student.is_clocked_in %}
<div class="student__statusbar status"> <div class="student__statusbar status">
<p><span class="status__clocked--clocked-in">You are currently clocked in.</span></p> <p><span class="status__clocked--clocked-in">You are currently clocked in.</span></p>
<p> <p class="status__clocked-info">
Clocked in at: <strong>{{ current_period.clocked_in|date:"P" }}</strong><br> Clocked in at: <strong>{{ current_period.clocked_in|date:"P" }}</strong><br>
Current sesson: <strong>{{ current_period.clocked_in|timesince }}</strong> Current sesson: <strong>{{ current_period.clocked_in|timesince }}</strong>
</p> </p>
@ -14,9 +16,10 @@
{% include 'attendance/_student_code.html' with clocked_in=False %} {% include 'attendance/_student_code.html' with clocked_in=False %}
{% endif %} {% endif %}
</section> </section>
<section class="attendance"> <section class="student__attendance attendance">
<h2 class="attendance__title">Attendance log</h2> <h2 class="attendance__title">Attendance log</h2>
<p class="attendance__total">Total hours for the month: <strong>{{period_total}}</strong><br> <p class="attendance__total">Total hours for the month: <strong>{{ period_total.total|dimedelta_format:2 }}</strong><br>
<small>(Does not include current session.)</small></p> <small>(Does not include current session.)</small></p>
{% include 'attendance/_student_periods.html' %} {% include 'attendance/_student_periods.html' %}
</section> </section>
</article>

View File

@ -2,11 +2,10 @@
{% load qr_code %} {% load qr_code %}
{% block content %} {% block content %}
<section class="code-detail panel">
<h1>Clock in</h1> <h1>Clock in</h1>
<p class="code-detail__instructions"><em>Scan code at clock-in station</em></p>
<section class="code_detail"> <span class="code-detail__qrcode">{% qr_from_text code.qr_code_str size=24 version=2 %}</span>
<p><em>Scan code at clock-in station</em></p> <span class="code-detail__done"><a class="action-button" href="{% url 'attendance-overview' %}">Done</a></span>
<span>{% qr_from_text code.qr_code_str size=24 version=2 %}</span>
<span><a class="action-button" href="{% url 'attendance-overview' %}">Done</a></span>
</section> </section>
{% endblock %} {% endblock %}

View File

@ -1,10 +1,10 @@
{% extends 'application.html' %} {% extends 'application.html' %}
{% block content %} {% block content %}
<h1>Generate code</h1>
<section> <section class="code-update panel">
<form method="post" action="{% url 'code-create' %}"> <h1>Generate code</h1>
<form method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}

View File

View File

@ -0,0 +1,8 @@
from django import template
register = template.Library()
@register.filter()
def dimedelta_format(value, arg=2):
"""Format timedelta"""
return round((value).seconds / 3600, arg)

View File

@ -27,7 +27,7 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['user'] = User.objects.get(pk=self.request.user.id) context['user'] = self.request.user
if hasattr(self.request.user, 'instructor'): if hasattr(self.request.user, 'instructor'):
context['student_list'] = Student.objects.filter( context['student_list'] = Student.objects.filter(
department=self.request.user.instructor.department department=self.request.user.instructor.department
@ -36,18 +36,18 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView):
elif hasattr(self.request.user, 'student'): elif hasattr(self.request.user, 'student'):
student = self.request.user.student student = self.request.user.student
# sum all duration fields for student # sum all duration fields for student
periods_duration_sum = Period.objects.filter( context['period_total'] = Period.objects.filter(
student = student student = student
).filter( ).filter(
clocked_in__year=timezone.now().year clocked_in__year=timezone.now().year
).filter( ).filter(
clocked_in__month=timezone.now().month clocked_in__month=timezone.now().month
).aggregate(total_duration=Sum('duration')) ).aggregate(total=Sum('duration'))
hours = 0 # hours = 0
# Convert to hours floating point # # Convert to hours floating point
if periods_duration_sum['total_duration'] != None: # if periods_duration_sum['total_duration'] != None:
hours = round((periods_duration_sum['total_duration'].total_seconds() / 3600), 2) # hours = round((periods_duration_sum['total_duration'].total_seconds() / 3600), 2)
context['period_list'] = Period.objects.filter( context['period_list'] = Period.objects.filter(
student=student student=student
@ -56,7 +56,6 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView):
).filter( ).filter(
clocked_in__month=timezone.now().month clocked_in__month=timezone.now().month
).order_by('-clocked_in') ).order_by('-clocked_in')
context['period_total'] = hours
if student.current_period_id != None: if student.current_period_id != None:
context['current_period'] = Period.objects.get(pk=student.current_period_id) context['current_period'] = Period.objects.get(pk=student.current_period_id)
return context return context
@ -141,7 +140,7 @@ class CodeDetailView(LoginRequiredMixin, DetailView):
class CodeUpdateView(LoginRequiredMixin, UpdateView): class CodeUpdateView(LoginRequiredMixin, UpdateView):
model = Code model = Code
fields = ['station_number'] fields = ['station_number']
template_name = 'attendance/code_update_form.html' template_name = 'attendance/code_form.html'
def get_success_url(self): def get_success_url(self):
pk = self.kwargs["pk"] pk = self.kwargs["pk"]

View File

View File

@ -0,0 +1,16 @@
.code-detail {
display: flex;
flex-direction: column;
align-items: center;
&__instructions {
}
&__qrcode {
}
&__done {
margin: 1rem 0;
}
}

View File

@ -51,6 +51,7 @@ input[type=submit],
color: white; color: white;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
border-radius: 3.75rem;
} }
input:focus, input:focus,

View File

@ -51,7 +51,7 @@ hr {
} }
// BLOCK ELEMENTS // BLOCK ELEMENTS
main { main, aside {
max-width: 58rem; max-width: 58rem;
margin: 0 auto; margin: 0 auto;
} }

View File

@ -0,0 +1,14 @@
.instructor {
&__active_periods {
}
&__attendance_log {
margin: 0 1rem;
}
&__total_hours {
margin: 0 1rem;
}
}

View File

@ -0,0 +1,3 @@
.messages {
}

View File

@ -1,9 +1,7 @@
.student { .student {
&__header { &__header {
display: flex;
justify-content: space-between;
align-items: baseline;
} }
&__department { &__department {

View File

@ -3,9 +3,11 @@
@import "helpers"; @import "helpers";
@import "forms"; @import "forms";
@import "nav"; @import "nav";
@import "messages";
@import "registration"; @import "registration";
@import "students"; @import "students";
@import "instructors"; @import "instructors";
@import "attendance";
@import "periods"; @import "periods";
@import "codes"; @import "codes";

View File

@ -32,7 +32,7 @@
<aside> <aside>
{% if messages %} {% if messages %}
<div class="messages"> <div class="messages panel">
{% for message in messages %} {% for message in messages %}
<span {% if message.tags %} class="{{ message.tags }} messages__message"{% endif %}>{{ message }}</span> <span {% if message.tags %} class="{{ message.tags }} messages__message"{% endif %}>{{ message }}</span>
{% endfor %} {% endfor %}