From 16ddd81a6356885c641dde1cf52a8a350abee51c Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Wed, 27 Jul 2022 15:45:11 -0600 Subject: [PATCH] Add most of the original functionality back --- .../templates/attendance/entry_form.html | 4 +- src/core/forms.py | 39 +- ...core_studen_content_a7305d_idx_and_more.py | 30 ++ ...8_remove_studenttag_tag_studenttag_name.py | 23 ++ src/core/models.py | 27 +- .../core/attendanceentry_confirm_delete.html | 13 + .../core/attendanceentry_create_form.html | 12 + .../core/attendanceentry_detail.html | 33 ++ .../templates/core/attendanceentry_form.html | 33 ++ .../templates/core/attendanceentry_list.html | 16 + src/core/templates/core/component_detail.html | 2 +- src/core/templates/core/component_form.html | 2 +- .../core/schoolday_confirm_delete.html | 29 ++ .../templates/core/schoolday_create_form.html | 46 +++ src/core/templates/core/schoolday_detail.html | 46 +++ src/core/templates/core/schoolday_form.html | 53 +++ src/core/templates/core/schoolday_list.html | 54 +++ .../templates/core/schoolyear_detail.html | 5 +- src/core/templates/core/schoolyear_form.html | 22 +- src/core/templates/core/schoolyear_list.html | 2 +- src/core/templates/core/score_form.html | 15 +- src/core/templates/core/student_detail.html | 50 +-- src/core/templates/core/student_form.html | 2 +- src/core/templates/core/student_list.html | 14 +- .../core/studenttag_confirm_delete.html | 13 + .../core/studenttag_create_form.html | 28 ++ .../templates/core/studenttag_detail.html | 50 +++ src/core/templates/core/studenttag_form.html | 28 ++ src/core/templates/core/studenttag_list.html | 32 ++ src/core/templates/core/subject_form.html | 34 +- src/core/templates/core/subject_list.html | 2 +- src/core/templates/core/today.html | 69 ++++ src/core/urls.py | 95 +++++ src/core/views.py | 340 ++++++++++++++++-- .../templates/gradebook/component_detail.html | 4 +- .../templates/gradebook/component_form.html | 6 +- src/indici/middleware.py | 1 + src/static/styles/main.css | 11 +- src/templates/base.html | 8 +- 39 files changed, 1172 insertions(+), 121 deletions(-) create mode 100644 src/core/migrations/0007_remove_studenttag_core_studen_content_a7305d_idx_and_more.py create mode 100644 src/core/migrations/0008_remove_studenttag_tag_studenttag_name.py create mode 100644 src/core/templates/core/attendanceentry_confirm_delete.html create mode 100644 src/core/templates/core/attendanceentry_create_form.html create mode 100644 src/core/templates/core/attendanceentry_detail.html create mode 100644 src/core/templates/core/attendanceentry_form.html create mode 100644 src/core/templates/core/attendanceentry_list.html create mode 100644 src/core/templates/core/schoolday_confirm_delete.html create mode 100644 src/core/templates/core/schoolday_create_form.html create mode 100644 src/core/templates/core/schoolday_detail.html create mode 100644 src/core/templates/core/schoolday_form.html create mode 100644 src/core/templates/core/schoolday_list.html create mode 100644 src/core/templates/core/studenttag_confirm_delete.html create mode 100644 src/core/templates/core/studenttag_create_form.html create mode 100644 src/core/templates/core/studenttag_detail.html create mode 100644 src/core/templates/core/studenttag_form.html create mode 100644 src/core/templates/core/studenttag_list.html create mode 100644 src/core/templates/core/today.html diff --git a/src/attendance/templates/attendance/entry_form.html b/src/attendance/templates/attendance/entry_form.html index ba63152..a1b4d62 100644 --- a/src/attendance/templates/attendance/entry_form.html +++ b/src/attendance/templates/attendance/entry_form.html @@ -4,7 +4,7 @@

Update Entry

- Delete {{entry}} + Delete

For {{student}}

@@ -17,4 +17,4 @@
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/core/forms.py b/src/core/forms.py index 431c045..4552c7f 100644 --- a/src/core/forms.py +++ b/src/core/forms.py @@ -16,36 +16,55 @@ from .models import ( class SchoolYearCreateForm(forms.ModelForm): class Meta: model = SchoolYear - fields = [ - 'year' - ] + fields = ['year'] class StudentForm(forms.ModelForm): class Meta: model = Student - fields = ( + fields = [ 'student_id', 'first_name', 'last_name', 'address', 'dob', - ) + 'tags' + ] labels = { 'student_id': 'Student ID', - 'dob': 'DOB', + 'dob': 'DOB' } class ComponentCreateForm(forms.ModelForm): class Meta: model = Component - fields = ( + fields = [ 'name', 'category', 'due_date', - 'grade_total', - ) + 'grade_total' + ] widgets = { - 'due_date': forms.DateInput(attrs={'type': 'date'}), + 'due_date': forms.DateInput(attrs={'type': 'date'}) + } + + +class SchoolDayForm(forms.ModelForm): + class Meta: + model = SchoolDay + fields = ['date'] + widgets = { + 'date': forms.DateInput(attrs={ + 'type': 'date', + }) + } + + +class AttendanceEntryForm(forms.ModelForm): + class Meta: + model = AttendanceEntry + fields = ['status'] + widgets = { + 'status': forms.RadioSelect() } diff --git a/src/core/migrations/0007_remove_studenttag_core_studen_content_a7305d_idx_and_more.py b/src/core/migrations/0007_remove_studenttag_core_studen_content_a7305d_idx_and_more.py new file mode 100644 index 0000000..8e71e28 --- /dev/null +++ b/src/core/migrations/0007_remove_studenttag_core_studen_content_a7305d_idx_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.0.5 on 2022-07-27 19:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_score'), + ] + + operations = [ + migrations.RemoveIndex( + model_name='studenttag', + name='core_studen_content_a7305d_idx', + ), + migrations.RemoveField( + model_name='studenttag', + name='content_type', + ), + migrations.RemoveField( + model_name='studenttag', + name='object_id', + ), + migrations.AddField( + model_name='student', + name='tags', + field=models.ManyToManyField(blank=True, to='core.studenttag'), + ), + ] diff --git a/src/core/migrations/0008_remove_studenttag_tag_studenttag_name.py b/src/core/migrations/0008_remove_studenttag_tag_studenttag_name.py new file mode 100644 index 0000000..9c7dda9 --- /dev/null +++ b/src/core/migrations/0008_remove_studenttag_tag_studenttag_name.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.5 on 2022-07-27 19:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0007_remove_studenttag_core_studen_content_a7305d_idx_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='studenttag', + name='tag', + ), + migrations.AddField( + model_name='studenttag', + name='name', + field=models.CharField(default='Allergy: Seasonal/Hay', max_length=255), + preserve_default=False, + ), + ] diff --git a/src/core/models.py b/src/core/models.py index c23034e..b2eb966 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -30,21 +30,13 @@ class SchoolYear(models.Model): class StudentTag(models.Model): - tag = models.SlugField() - content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) - object_id = models.PositiveIntegerField() - content_object = GenericForeignKey('content_type', 'object_id') + name = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): - return self.tag - - class Meta: - indexes = [ - models.Index(fields=['content_type', 'object_id']), - ] + return self.name # class StudentManager(models.Manager): @@ -70,7 +62,7 @@ class Student(models.Model): address = models.TextField(blank=True) dob = models.DateField() - tags = GenericRelation(StudentTag) + tags = models.ManyToManyField(StudentTag, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -236,6 +228,12 @@ class SchoolDay(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + def get_absolute_url(self): + return reverse('core:schoolday-detail', kwargs={ + 'year': self.school_year.year, + 'pk': self.pk + }) + def __str__(self): return f'{self.date}' @@ -265,6 +263,13 @@ class AttendanceEntry(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + def get_absolute_url(self): + return reverse('core:schoolday-detail', kwargs={ + 'year': self.school_day.school_year.year, + 'pk': self.school_day.pk, + 'entry_pk': self.pk + }) + def __str__(self): return f"{self.day} | {self.student} | {self.status}" diff --git a/src/core/templates/core/attendanceentry_confirm_delete.html b/src/core/templates/core/attendanceentry_confirm_delete.html new file mode 100644 index 0000000..c1ae1ff --- /dev/null +++ b/src/core/templates/core/attendanceentry_confirm_delete.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +

Delete Attendanceentry

+
+ {% csrf_token %} +

Are you sure you want to delete "{{ attendanceentry }}"?

+ {{ form.as_p }} +

+ or cancel +

+
+{% endblock %} diff --git a/src/core/templates/core/attendanceentry_create_form.html b/src/core/templates/core/attendanceentry_create_form.html new file mode 100644 index 0000000..d4a2762 --- /dev/null +++ b/src/core/templates/core/attendanceentry_create_form.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} + +{% block content %} +

+ New Attendanceentry

+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+{% endblock %} diff --git a/src/core/templates/core/attendanceentry_detail.html b/src/core/templates/core/attendanceentry_detail.html new file mode 100644 index 0000000..0ae4565 --- /dev/null +++ b/src/core/templates/core/attendanceentry_detail.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + +{% block head_title %}Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Edit Attendance

+
+

Delete

+
+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+
+{% endblock %} diff --git a/src/core/templates/core/attendanceentry_form.html b/src/core/templates/core/attendanceentry_form.html new file mode 100644 index 0000000..ce10d77 --- /dev/null +++ b/src/core/templates/core/attendanceentry_form.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + +{% block head_title %}Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Edit Attendance

+
+

Delete

+
+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+
+{% endblock %} diff --git a/src/core/templates/core/attendanceentry_list.html b/src/core/templates/core/attendanceentry_list.html new file mode 100644 index 0000000..bd7d376 --- /dev/null +++ b/src/core/templates/core/attendanceentry_list.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} + +{% block content %} +

Attendanceentrys

+ + + {% for attendanceentry in attendanceentry_list %} + +
{{ attendanceentry }}
+ + {% empty %} + No attendanceentrys yet. + {% endfor %} + +
+{% endblock %} diff --git a/src/core/templates/core/component_detail.html b/src/core/templates/core/component_detail.html index 3ca5d54..12d3285 100644 --- a/src/core/templates/core/component_detail.html +++ b/src/core/templates/core/component_detail.html @@ -63,7 +63,7 @@ {{score.student.student_id}} — {{score.student}} {{score.value}} / {{component.grade_total}} - Edit score + Edit {% endfor %} diff --git a/src/core/templates/core/component_form.html b/src/core/templates/core/component_form.html index ea2259c..426179a 100644 --- a/src/core/templates/core/component_form.html +++ b/src/core/templates/core/component_form.html @@ -1,7 +1,7 @@ {% extends 'base.html' %} {% block content %} -

Update Component

+

Edit Component

{% csrf_token %} {{ form.as_p }} diff --git a/src/core/templates/core/schoolday_confirm_delete.html b/src/core/templates/core/schoolday_confirm_delete.html new file mode 100644 index 0000000..d825f8c --- /dev/null +++ b/src/core/templates/core/schoolday_confirm_delete.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} + +{% block head_title %}Delete Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+

Delete Attendance

+ + {% csrf_token %} +

Are you sure you want to delete "{{ schoolday }}"?

+ {{ form.as_p }} +

+ or cancel +

+ +
+{% endblock %} diff --git a/src/core/templates/core/schoolday_create_form.html b/src/core/templates/core/schoolday_create_form.html new file mode 100644 index 0000000..928c791 --- /dev/null +++ b/src/core/templates/core/schoolday_create_form.html @@ -0,0 +1,46 @@ +{% extends 'base.html' %} + +{% block head_title %}Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+

Take Attendance

+
+ {% csrf_token %} + {{ form.as_p }} + + + + + + + + + + + {% for student in student_list %} + + + + + + + {% endfor %} + +
StudentPresentTardyAbsent
{{student.full_name}}
+

+ or cancel +

+
+
+{% endblock %} diff --git a/src/core/templates/core/schoolday_detail.html b/src/core/templates/core/schoolday_detail.html new file mode 100644 index 0000000..3a14b66 --- /dev/null +++ b/src/core/templates/core/schoolday_detail.html @@ -0,0 +1,46 @@ +{% extends 'base.html' %} +{% load helpers %} + +{% block head_title %}Attendance {{ schoolday.date }} | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Attendance {{ schoolday.date }}

+

Added:
+ Last updated:

+
+ Edit +
+
+ + + + + + + + + {% for entry in schoolday.attendanceentry_set.all %} + + + + + + {% endfor %} + +
StudentStatus
{{entry.student}}{{entry.get_status_display}}Edit
+
+
+{% endblock %} diff --git a/src/core/templates/core/schoolday_form.html b/src/core/templates/core/schoolday_form.html new file mode 100644 index 0000000..0acd59b --- /dev/null +++ b/src/core/templates/core/schoolday_form.html @@ -0,0 +1,53 @@ +{% extends 'base.html' %} + +{% block head_title %}Edit Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Edit Attendance

+
+

Delete

+
+
+ {% csrf_token %} + {{ form.as_p }} + + + + + + + + + + + {% for entry in schoolday.attendanceentry_set.all %} + + + + + + + {% endfor %} + +
StudentPresentTardyAbsent
{{entry.student.full_name}}
+

+ or cancel +

+
+
+{% endblock %} diff --git a/src/core/templates/core/schoolday_list.html b/src/core/templates/core/schoolday_list.html new file mode 100644 index 0000000..36606cc --- /dev/null +++ b/src/core/templates/core/schoolday_list.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} +{% load static %} + +{% block head_title %}Attendance | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Attendance

+ Take attendance → +
+
+ {% for schoolday in schoolday_list %} +
+

{{ schoolday.date }}

+ + + + + + + + + {% for entry in schoolday.attendanceentry_set.all %} + + + + + + {% empty %} + + + + {% endfor %} + +
StudentStatus
{{entry.student}}{{entry.get_status_display}}Edit
No attendance yet.
+
+ {% empty %} +
+

No attendance yet.

+
+ {% endfor %} + {% include 'core/partials/pagination.html' %} +
+{% endblock %} diff --git a/src/core/templates/core/schoolyear_detail.html b/src/core/templates/core/schoolyear_detail.html index 4cd4719..f9214b8 100644 --- a/src/core/templates/core/schoolyear_detail.html +++ b/src/core/templates/core/schoolyear_detail.html @@ -1,13 +1,12 @@ {% extends 'base.html' %} -{% block head_title %}Project {{ schoolyear.name }} | {% endblock head_title %} +{% block head_title %}Year {{ schoolyear.year }} | {% endblock head_title %} {% block content %}

{{ schoolyear }}

-

Created

{% if perms.core.can_change_schoolyear %} Edit @@ -19,7 +18,7 @@

Tool Description

- +

Attendence

Tool Description

diff --git a/src/core/templates/core/schoolyear_form.html b/src/core/templates/core/schoolyear_form.html index 2b3238c..de7da06 100644 --- a/src/core/templates/core/schoolyear_form.html +++ b/src/core/templates/core/schoolyear_form.html @@ -1,12 +1,18 @@ {% extends 'base.html' %} +{% block head_title %}Edit Year {{ schoolyear.year }} | {% endblock head_title %} + {% block content %} -

Update Schoolyear

-
- {% csrf_token %} - {{ form.as_p }} -

- or cancel -

-
+
+
+

Edit Schoolyear

+
+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+
{% endblock %} diff --git a/src/core/templates/core/schoolyear_list.html b/src/core/templates/core/schoolyear_list.html index ac49187..04af0df 100644 --- a/src/core/templates/core/schoolyear_list.html +++ b/src/core/templates/core/schoolyear_list.html @@ -18,7 +18,7 @@ {% for schoolyear in schoolyear_list %}

{{ schoolyear.year }}

-
Students: ()   Subjects: ()
+
Students: ({{ schoolyear.student__count }})   Subjects: ({{ schoolyear.subject__count }})
{% empty %} diff --git a/src/core/templates/core/score_form.html b/src/core/templates/core/score_form.html index 026eba1..d1039a8 100644 --- a/src/core/templates/core/score_form.html +++ b/src/core/templates/core/score_form.html @@ -20,19 +20,18 @@
-

Update Score

-

{{score.component.subject}}— {{score.component.get_category_display}}: {{score.component}}

+

Edit Score

+

{{ score.component.subject }}— {{ score.component.get_category_display }}: {{ score.component }}

-

Delete score

+

Delete

-
+ {% csrf_token %} - -

{{score.student}}

- {{form.as_p}} +

{{ score.student }}

+ {{ form.as_p }}

- or cancel + or cancel

diff --git a/src/core/templates/core/student_detail.html b/src/core/templates/core/student_detail.html index 64ae008..dca1ef2 100644 --- a/src/core/templates/core/student_detail.html +++ b/src/core/templates/core/student_detail.html @@ -25,10 +25,6 @@
- {% if student.allergies %} -
Allergies
-
{{ student.allergies }}
- {% endif %}
Birthday
{{ student.dob }}
Age
@@ -39,37 +35,47 @@
{{ student.address|linebreaksbr }}
{% endif %} + {% if student.tags.count > 0 %} +
Tags
+
+ {% for tag in student.tags.all %} +
{{ tag }}
{% if not forloop.last %}
{% endif %} + {% endfor %} +
+ {% endif %}

Grades

- - + + + + {% for subject in subject_list %} - - + + {% empty %} - + {% endfor %}
SubjectGrade
SubjectGrade
{{subject}}
{{subject.grade|grade_as_percentage:subject.grade_total}}%
{{ subject }}
{{ subject.grade|grade_as_percentage:subject.grade_total }}%
No grades yet. To add a grade you will need to enter a score for this student on a component.No grades yet. You will need to enter a score for this student on a component.
-

Components

+

Scores

{% regroup score_list by component.subject as score_list %} {% for subject in score_list %}
-

{{subject.grouper}}

+

{{ subject.grouper }}

@@ -83,15 +89,14 @@ {% for score in subject.list %} - - - - - - - - + + + + + + + {% endfor %} @@ -112,15 +117,14 @@
{{score.component.due_date}}{{score.component}}{{score.component.get_category_display}}{{score.value}}{{score.component.grade_total}}{{score.grade_as_percentage}}%Change score{{ score.component.due_date }}{{ score.component }}{{ score.component.get_category_display }}{{ score.value }}{{ score.component.grade_total }}{{ score.grade_as_percentage }}%Edit
- - + {% for entry in status.list %} - - + + {% endfor %} diff --git a/src/core/templates/core/student_form.html b/src/core/templates/core/student_form.html index 556dbdc..cdcbfdb 100644 --- a/src/core/templates/core/student_form.html +++ b/src/core/templates/core/student_form.html @@ -17,7 +17,7 @@ {% block content %}
-

Update Student

+

Edit Student

{% csrf_token %} {{ form.as_p }} diff --git a/src/core/templates/core/student_list.html b/src/core/templates/core/student_list.html index d5e82d2..4b39689 100644 --- a/src/core/templates/core/student_list.html +++ b/src/core/templates/core/student_list.html @@ -18,12 +18,12 @@

Students

+ New Student - Student Tags → + Student Tags →
DateStatusDate
{{entry.day.date}}Update{{ entry.school_day.date }}Edit
- + @@ -32,12 +32,16 @@ {% for student in student_list %} - - + + {% empty %} - + {% endfor %} diff --git a/src/core/templates/core/studenttag_confirm_delete.html b/src/core/templates/core/studenttag_confirm_delete.html new file mode 100644 index 0000000..8a0fbdc --- /dev/null +++ b/src/core/templates/core/studenttag_confirm_delete.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +

Delete Studenttag

+ + {% csrf_token %} +

Are you sure you want to delete "{{ studenttag }}"?

+ {{ form.as_p }} +

+ or cancel +

+ +{% endblock %} diff --git a/src/core/templates/core/studenttag_create_form.html b/src/core/templates/core/studenttag_create_form.html new file mode 100644 index 0000000..2d58cec --- /dev/null +++ b/src/core/templates/core/studenttag_create_form.html @@ -0,0 +1,28 @@ +{% extends 'base.html' %} + +{% block head_title %}New Tag | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+

+ New Tag

+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+ +
+{% endblock %} diff --git a/src/core/templates/core/studenttag_detail.html b/src/core/templates/core/studenttag_detail.html new file mode 100644 index 0000000..1dc3826 --- /dev/null +++ b/src/core/templates/core/studenttag_detail.html @@ -0,0 +1,50 @@ +{% extends 'base.html' %} +{% load helpers %} + +{% block head_title %}Tag {{ tag }} | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

{{ tag }}

+
+ Edit +
+
+

Students with this tag

+
Student No. ↕Student No. ↕ Name Tags
No students yet.No students yet.
+ + + + + + + + {% for student in tag.student_set.all %} + + + + + {% empty %} + + + + {% endfor %} + +
Student No. ↕Name
No students tagged yet.
+
+
+{% endblock %} diff --git a/src/core/templates/core/studenttag_form.html b/src/core/templates/core/studenttag_form.html new file mode 100644 index 0000000..058ee96 --- /dev/null +++ b/src/core/templates/core/studenttag_form.html @@ -0,0 +1,28 @@ +{% extends 'base.html' %} + +{% block head_title %}Edit Tag | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+

Edit Tag

+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+
+{% endblock %} diff --git a/src/core/templates/core/studenttag_list.html b/src/core/templates/core/studenttag_list.html new file mode 100644 index 0000000..da163a3 --- /dev/null +++ b/src/core/templates/core/studenttag_list.html @@ -0,0 +1,32 @@ +{% extends 'base.html' %} +{% load helpers %} + +{% block head_title %}Student Tags | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + +{% block content %} +
+
+
+

Student Tags

+ + New Tag +
+
+
+ {% for tag in studenttag_list %} + {{ tag }} + {% empty %} +

No tags yet.

+ {% endfor %} +
+
+{% endblock %} diff --git a/src/core/templates/core/subject_form.html b/src/core/templates/core/subject_form.html index 0ce4497..9cd3855 100644 --- a/src/core/templates/core/subject_form.html +++ b/src/core/templates/core/subject_form.html @@ -1,12 +1,30 @@ {% extends 'base.html' %} +{% block head_title %}Edit Subject | {% endblock head_title %} + +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + {% block content %} -

Update Subject

-
- {% csrf_token %} - {{ form.as_p }} -

- or cancel -

-
+
+
+

Edit Subject

+
+
+ {% csrf_token %} + {{ form.as_p }} +

+ or cancel +

+
+
{% endblock %} diff --git a/src/core/templates/core/subject_list.html b/src/core/templates/core/subject_list.html index 173275b..c830ce7 100644 --- a/src/core/templates/core/subject_list.html +++ b/src/core/templates/core/subject_list.html @@ -34,7 +34,7 @@
{{ subject.name }}
{{ subject.description }} - (componenet count) + {{ subject.component__count }} {% empty %} diff --git a/src/core/templates/core/today.html b/src/core/templates/core/today.html new file mode 100644 index 0000000..8dce74c --- /dev/null +++ b/src/core/templates/core/today.html @@ -0,0 +1,69 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+

Here's what's going on today

+
+
+

Birthdays this week

+
    + {% for student in birthdays %} +
  • {{ student }} is turning {{ student.age|add:1 }} on {{ student.dob|date:"M j" }}
  • + {% empty %} +

    No Birthdays this next week.

    + {% endfor %} +
+
+
+

Today's Assignments

+
    + {% for component in components %} +
  • + {{component.subject}}, {{component}} +
  • + {% empty %} +

    Nothing for today.

    + {% endfor %} +
+
+
+

Today's Attendance

+ {% for day in attendance %} +

{{day.date}}

+ + + + + + + + + {% for entry in day.attendanceentry_set.all %} + + + + + + {% endfor %} + +
StudentStatus
{{entry.student}}{{entry.get_status_display}}Edit
+ {% empty %} +

No attendance taken yet: Take attendance

+ {% endfor %} +
+
+

Assignments to be graded

+
    + {% for component in ungraded_components %} +
  • + {{component.subject}}, {{component}} +
  • + {% empty %} +

    Everything is graded to far.

    + {% endfor %} +
+
+
+{% endblock %} diff --git a/src/core/urls.py b/src/core/urls.py index a4a811e..88be69a 100644 --- a/src/core/urls.py +++ b/src/core/urls.py @@ -2,6 +2,8 @@ from django.urls import path, include from . import views urlpatterns = [ + path('today/', views.TodayView.as_view(), name='today'), + # SchoolYears path('years/', include([ path( @@ -55,6 +57,37 @@ urlpatterns = [ name='student-delete' ), ])), + + # StudentTags + path('tags/', include([ + path( + '', + views.StudentTagListView.as_view(), + name='stag-list' + ), + path( + 'new/', + views.StudentTagCreateView.as_view(), + name='stag-create' + ), + path('/', include([ + path( + '', + views.StudentTagDetailView.as_view(), + name='stag-detail' + ), + path( + 'update/', + views.StudentTagUpdateView.as_view(), + name='stag-update' + ), + path( + 'delete/', + views.StudentTagDeleteView.as_view(), + name='stag-delete' + ), + ])), + ])), ])), # Subjects @@ -124,6 +157,68 @@ urlpatterns = [ ])), ])), + # SchoolDays + path('schooldays/', include([ + path( + '', + views.SchoolDayListView.as_view(), + name='schoolday-list' + ), + path( + 'new/', + views.SchoolDayCreateView.as_view(), + name='schoolday-create' + ), + path('/', include([ + path( + '', + views.SchoolDayDetailView.as_view(), + name='schoolday-detail' + ), + path( + 'update/', + views.SchoolDayUpdateView.as_view(), + name='schoolday-update' + ), + path( + 'delete/', + views.SchoolDayDeleteView.as_view(), + name='schoolday-delete' + ), + + # AttendanceEntries + path('entries/', include([ + path( + '', + views.AttendanceEntryListView.as_view(), + name='entry-list' + ), + path( + 'new/', + views.AttendanceEntryCreateView.as_view(), + name='entry-create' + ), + path('/', include([ + path( + '', + views.AttendanceEntryDetailView.as_view(), + name='entry-detail' + ), + path( + 'update/', + views.AttendanceEntryUpdateView.as_view(), + name='entry-update' + ), + path( + 'delete/', + views.AttendanceEntryDeleteView.as_view(), + name='entry-delete' + ), + ])), + ])), + ])), + ])), + # Scores path('scores/', include([ path( diff --git a/src/core/views.py b/src/core/views.py index 346e175..fceee03 100644 --- a/src/core/views.py +++ b/src/core/views.py @@ -1,3 +1,4 @@ +import datetime as dt from django.conf import settings from django.utils import timezone from django.db import models @@ -34,29 +35,67 @@ from .models import ( from .forms import ( SchoolYearCreateForm, - ComponentCreateForm + ComponentCreateForm, + SchoolDayForm, + AttendanceEntryForm ) -class SchoolYearListView(ListView): +class TodayView(LoginRequiredMixin, TemplateView): + template_name = 'core/today.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + today = timezone.localtime(timezone.now()).date() + enddate = today + dt.timedelta(days=7) + + context['birthdays'] = Student.objects.filter( + dob__month=today.month, + dob__day__range=[today.day, enddate.day] + ).order_by('dob') + + context['components'] = Component.objects.filter( + due_date=today + ).select_related('subject') + + context['attendance'] = SchoolDay.objects.filter( + date=today + ).prefetch_related('attendanceentry_set', 'attendanceentry_set__student') + + context['ungraded_components'] = Component.objects.filter( + due_date__lte=today, + finished_grading=False + ).select_related('subject') + + return context + + +class SchoolYearListView(LoginRequiredMixin, ListView): model = SchoolYear paginate_by = 10 + def get_queryset(self): + queryset = SchoolYear.objects.annotate( + models.Count('student', distinct=True), + models.Count('subject', distinct=True) + ).order_by('-year') + return queryset -class SchoolYearCreateView(SuccessMessageMixin, CreateView): + +class SchoolYearCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = SchoolYear success_message = 'SchoolYear created.' form_class = SchoolYearCreateForm template_name_suffix = '_create_form' -class SchoolYearDetailView(DetailView): +class SchoolYearDetailView(LoginRequiredMixin, DetailView): model = SchoolYear slug_url_kwarg = 'year' slug_field = 'year' -class SchoolYearUpdateView(SuccessMessageMixin, UpdateView): +class SchoolYearUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = SchoolYear slug_url_kwarg = 'year' slug_field = 'year' @@ -64,7 +103,7 @@ class SchoolYearUpdateView(SuccessMessageMixin, UpdateView): fields = '__all__' -class StudentListView(ListView): +class StudentListView(LoginRequiredMixin, ListView): model = Student paginate_by = 50 @@ -82,7 +121,7 @@ class StudentListView(ListView): return context -class StudentCreateView(SuccessMessageMixin, CreateView): +class StudentCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = Student success_message = 'Student created.' template_name_suffix = '_create_form' @@ -106,12 +145,16 @@ class StudentCreateView(SuccessMessageMixin, CreateView): return context -class StudentDetailView(DetailView): +class StudentDetailView(LoginRequiredMixin, DetailView): model = Student def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + context['score_list'] = Score.objects.select_related( 'student' ).prefetch_related( @@ -141,26 +184,124 @@ class StudentDetailView(DetailView): return context -class StudentUpdateView(SuccessMessageMixin, UpdateView): +class StudentUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = Student success_message = 'Student saved.' fields = '__all__' -class StudentDeleteView(SuccessMessageMixin, DeleteView): +class StudentDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): model = Student success_message = 'Student deleted.' success_url = reverse_lazy('student-list') -class SubjectListView(ListView): +class StudentTagListView(LoginRequiredMixin, ListView): + model = StudentTag + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + +class StudentTagCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): + model = StudentTag + success_message = 'Tag created.' + template_name_suffix = '_create_form' + fields = '__all__' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + def get_success_url(self): + return reverse('core:stag-list', kwargs={ + 'year': self.kwargs['year'] + }) + + +class StudentTagDetailView(LoginRequiredMixin, DetailView): + model = StudentTag + pk_url_kwarg = 'stag_pk' + context_object_name = 'tag' + + def get_object(self): + queryset = StudentTag.objects.filter( + pk=self.kwargs.get(self.pk_url_kwarg) + ).prefetch_related( + Prefetch( + 'student_set', + queryset=Student.objects.filter( + school_year__year=self.kwargs['year'] + ) + ) + ) + obj = queryset.get() + return obj + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + +class StudentTagUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): + model = StudentTag + pk_url_kwarg = 'stag_pk' + context_object_name = 'tag' + success_message = 'Tag saved.' + fields = '__all__' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + def get_success_url(self): + return reverse('core:stag-list', kwargs={ + 'year': self.kwargs['year'] + }) + + +class StudentTagDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): + model = StudentTag + pk_url_kwarg = 'stag_pk' + context_object_name = 'tag' + success_message = 'Tag deleted.' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + def get_success_url(self): + return reverse('core:stag-list', kwargs={ + 'year': self.kwargs['year'] + }) + + +class SubjectListView(LoginRequiredMixin, ListView): model = Subject paginate_by = 50 def get_queryset(self): queryset = Subject.objects.filter( school_year__year=self.kwargs['year'] - ) + ).annotate( + models.Count('component') + ).order_by('name') return queryset def get_context_data(self, **kwargs): @@ -171,7 +312,7 @@ class SubjectListView(ListView): return context -class SubjectCreateView(SuccessMessageMixin, CreateView): +class SubjectCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = Subject success_message = 'Subject created.' template_name_suffix = '_create_form' @@ -194,7 +335,7 @@ class SubjectCreateView(SuccessMessageMixin, CreateView): return super().form_valid(form) -class SubjectDetailView(DetailView): +class SubjectDetailView(LoginRequiredMixin, DetailView): model = Subject def get_object(self): @@ -214,7 +355,7 @@ class SubjectDetailView(DetailView): return obj -class SubjectUpdateView(SuccessMessageMixin, UpdateView): +class SubjectUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = Subject success_message = 'Subject saved.' fields = '__all__' @@ -227,7 +368,7 @@ class SubjectUpdateView(SuccessMessageMixin, UpdateView): return context -class SubjectDeleteView(SuccessMessageMixin, DeleteView): +class SubjectDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): model = Subject success_message = 'Subject deleted.' success_url = reverse_lazy('subject-list') @@ -240,11 +381,11 @@ class SubjectDeleteView(SuccessMessageMixin, DeleteView): return context -class ComponentListView(ListView): +class ComponentListView(LoginRequiredMixin, ListView): model = Component -class ComponentCreateView(SuccessMessageMixin, CreateView): +class ComponentCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = Component success_message = 'Component created.' template_name_suffix = '_create_form' @@ -270,7 +411,7 @@ class ComponentCreateView(SuccessMessageMixin, CreateView): return super().form_valid(form) -class ComponentDetailView(DetailView): +class ComponentDetailView(LoginRequiredMixin, DetailView): model = Component pk_url_kwarg = 'component_pk' @@ -301,21 +442,21 @@ class ComponentDetailView(DetailView): return context -class ComponentUpdateView(SuccessMessageMixin, UpdateView): +class ComponentUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = Component pk_url_kwarg = 'component_pk' success_message = 'Component saved.' fields = '__all__' -class ComponentDeleteView(SuccessMessageMixin, DeleteView): +class ComponentDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): model = Component pk_url_kwarg = 'component_pk' success_message = 'Component deleted.' success_url = reverse_lazy('core:component-list') -class ComponentManagerView(LoginRequiredMixin, UpdateView): +class ComponentManagerView(LoginRequiredMixin, LoginRequiredMixin, UpdateView): model = Component pk_url_kwarg = 'component_pk' template_name_suffix = '_manager' @@ -353,22 +494,22 @@ class ComponentManagerView(LoginRequiredMixin, UpdateView): return super().form_valid(form) -class ScoreListView(ListView): +class ScoreListView(LoginRequiredMixin, ListView): model = Score -class ScoreCreateView(SuccessMessageMixin, CreateView): +class ScoreCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = Score success_message = 'Score created.' template_name_suffix = '_create_form' fields = '__all__' -class ScoreDetailView(DetailView): +class ScoreDetailView(LoginRequiredMixin, DetailView): model = Score -class ScoreUpdateView(SuccessMessageMixin, UpdateView): +class ScoreUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = Score success_message = 'Score saved.' fields = [ @@ -384,7 +525,7 @@ class ScoreUpdateView(SuccessMessageMixin, UpdateView): return context -class ScoreDeleteView(SuccessMessageMixin, DeleteView): +class ScoreDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): model = Score success_message = 'Score deleted.' @@ -399,3 +540,148 @@ class ScoreDeleteView(SuccessMessageMixin, DeleteView): SchoolYear, year=self.kwargs['year'] ) return context + + +class SchoolDayListView(LoginRequiredMixin, ListView): + model = SchoolDay + paginate_by = 7 + + def get_queryset(self): + queryset = SchoolDay.objects.filter( + school_year__year=self.kwargs['year'] + ) + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + +class SchoolDayCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): + model = SchoolDay + success_message = 'SchoolDay created.' + template_name_suffix = '_create_form' + form_class = SchoolDayForm + + def get_initial(self): + today = timezone.localtime(timezone.now()).date() + initial = { + 'date': today, + } + return initial + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['student_list'] = Student.objects.all() + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + def form_valid(self, form): + form.instance.school_year = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + form.save() + for key, value in self.request.POST.items(): + if 'student' in key: + s = key.split('_')[1] + AttendanceEntry.objects.create( + school_day=form.instance, + student=Student.objects.get(pk=s), + status=value, + ) + return super().form_valid(form) + + +class SchoolDayDetailView(LoginRequiredMixin, DetailView): + model = SchoolDay + + +class SchoolDayUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): + model = SchoolDay + success_message = 'SchoolDay saved.' + form_class = SchoolDayForm + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['student_list'] = Student.objects.all() + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + def form_valid(self, form): + form.save() + for key, value in self.request.POST.items(): + if 'student' in key: + s = key.split('_')[1] + AttendanceEntry.objects.filter( + school_day=self.object, + student=Student.objects.get(pk=s) + ).update(status=value) + return super().form_valid(form) + + +class SchoolDayDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): + model = SchoolDay + success_message = 'SchoolDay deleted.' + + def get_success_url(self): + return reverse('core:schoolday-list', kwargs={ + 'year': self.kwargs['year'] + }) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['school_year'] = get_object_or_404( + SchoolYear, year=self.kwargs['year'] + ) + return context + + +class AttendanceEntryListView(LoginRequiredMixin, ListView): + model = AttendanceEntry + + +class AttendanceEntryCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): + model = AttendanceEntry + success_message = 'Entry created.' + template_name_suffix = '_create_form' + fields = '__all__' + + +class AttendanceEntryDetailView(LoginRequiredMixin, DetailView): + model = AttendanceEntry + pk_url_kwarg = 'entry_pk' + context_object_name = 'entry' + + +class AttendanceEntryUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): + model = AttendanceEntry + pk_url_kwarg = 'entry_pk' + context_object_name = 'entry' + success_message = 'Entry saved.' + form_class = AttendanceEntryForm + + def get_success_url(self): + return reverse('core:schoolday-detail', kwargs={ + 'year': self.kwargs['year'], + 'pk': self.kwargs['pk'] + }) + + +class AttendanceEntryDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): + model = AttendanceEntry + pk_url_kwarg = 'entry_pk' + context_object_name = 'entry' + success_message = 'Entry deleted.' + + def get_success_url(self): + return reverse('core:schoolday-detail', kwargs={ + 'year': self.kwargs['year'], + 'pk': self.kwargs['pk'] + }) diff --git a/src/gradebook/templates/gradebook/component_detail.html b/src/gradebook/templates/gradebook/component_detail.html index 72e2888..324b1f5 100644 --- a/src/gradebook/templates/gradebook/component_detail.html +++ b/src/gradebook/templates/gradebook/component_detail.html @@ -4,7 +4,7 @@

{{component.name}}

- Update Component + Edit
{% if component.finished_grading %}
@@ -74,4 +74,4 @@ {% endif %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/gradebook/templates/gradebook/component_form.html b/src/gradebook/templates/gradebook/component_form.html index 582da01..332f56c 100644 --- a/src/gradebook/templates/gradebook/component_form.html +++ b/src/gradebook/templates/gradebook/component_form.html @@ -3,8 +3,8 @@ {% block content %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/indici/middleware.py b/src/indici/middleware.py index 3a01cd2..a64cb54 100644 --- a/src/indici/middleware.py +++ b/src/indici/middleware.py @@ -1,4 +1,5 @@ import zoneinfo +from urllib import parse from django.utils import timezone diff --git a/src/static/styles/main.css b/src/static/styles/main.css index aeb1c06..34ae6bd 100644 --- a/src/static/styles/main.css +++ b/src/static/styles/main.css @@ -106,6 +106,7 @@ figure { ========================================================================== */ ul, ol, dl { margin-bottom: 1rem; + line-height: 1.3; } dl dt { font-weight: bold; @@ -125,6 +126,7 @@ table { border-collapse: collapse; width: 100%; text-align: left; + margin-bottom: 1rem; border-bottom: var(--table-border); } thead { @@ -221,8 +223,13 @@ input[type=submit], background-color: var(--color-danger); } -form progress { - display: none; +form input[type=radio], +form input[type=checkbox] { + width: 2rem; + height: 2rem; + cursor: pointer; + vertical-align: middle; + margin: 0.25rem; } diff --git a/src/templates/base.html b/src/templates/base.html index 99562cb..15280af 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -25,17 +25,17 @@ {% if user.is_authenticated %} -
  • Years
  • -
  • Today
  • +
  • Today
  • Students
  • -
  • Attendance
  • +
  • Attendance
  • Subjects