Add training level list

Plus various other fettling
This commit is contained in:
2021-09-03 22:34:08 +01:00
parent 45dfe2db51
commit d80aeca01f
9 changed files with 90 additions and 30 deletions

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.1.7 on 2021-09-03 20:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('training', '0005_auto_20210819_1833'),
]
operations = [
migrations.AddField(
model_name='traininglevel',
name='icon',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AlterField(
model_name='traininglevelrequirement',
name='depth',
field=models.IntegerField(choices=[(0, 'Training Started'), (1, 'Training Complete'), (2, 'Passed Out')]),
),
]

View File

@@ -119,6 +119,19 @@ class TrainingLevel(models.Model, RevisionMixin):
department = models.IntegerField(choices=DEPARTMENTS, null=True) # N.B. Technical Assistant does not have a department
level = models.IntegerField(choices=CHOICES)
prerequisite_levels = models.ManyToManyField('self', related_name='prerequisites', symmetrical=False, blank=True)
icon = models.CharField(null=True, blank=True, max_length=20)
def get_department_colour(self):
if self.department == 0:
return "info"
elif self.department == 1:
return "dark"
elif self.department == 2:
return "danger"
elif self.department == 3:
return "light"
else:
return "primary"
def get_requirements_of_depth(self, depth):
return self.requirements.filter(depth=depth)

View File

@@ -20,6 +20,8 @@
Item Detail</a>
</div>
</li>
<li class="nav-item"><a class="nav-link" href="{% url 'level_list' %}"><span class="fas fa-layer-group"></span> All Levels</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'item_list' %}"><span class="fas fa-sitemap"></span> All Items</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'training_activity_table' %}"><span class="fas fa-random"></span> Recent Changes</a></li>
{% endif %}
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends 'base_rigs.html' %}
{% extends 'base_training.html' %}
{% block content %}
<div class="row">

View File

@@ -17,13 +17,13 @@
<p>{{ object.description }}</p>
</div>
</div>
<div class="card mb-3">
<div class="card mb-3 d-none d-md-block">
<h4 class="card-header">Users with this level</h4>
<div class="card-body">
<div class="card-columns">
<div class="card-columns" style="column-count: 5">
{% for user in users_with %}
{% user_level_if_present user object as level_qualification %}
<div class="card w-50" {% if not level_qualification.confirmed_on %}style="border-style: dashed; opacity: 70%"{%endif%}>
<div class="card" {% if not level_qualification.confirmed_on %}style="border-style: dashed; opacity: 70%"{%endif%}>
<img src="{{user.profile_picture}}" class="card-img-top" />
<div class="card-body">
<h5 class="card-title">{{user}}</h5>
@@ -32,7 +32,7 @@
<div class="card-footer text-right pr-1"><a href="{% url 'profile_detail' user.pk %}" class="btn btn-primary btn-sm"><span class="fas fa-user"></span> View Profile</a></div>
</div>
{% empty %}
Nobody here but us chickens...
Nobody here but us chickens... <span class="fas fa-egg text-warning"></span>
{% endfor %}
</div>
</div>
@@ -62,7 +62,7 @@
{% user_level_if_present request.user level as level_qualification %}
<li><a href="{{level.get_absolute_url}}">{{ level }}</a> <span class="fas {% if level_qualification %}text-success fa-check{% if level_qualification.confirmed_by is not None %}-double{% endif %}{% else %}fa-hourglass-start text-warning{%endif%}"></span></li>
{% for nested_level in level.prerequisite_levels.all %}
{% user_level_if_present request.user level as nested_level_qualification %}
{% user_level_if_present request.user nested_level as nested_level_qualification %}
<ul>
<li><a href="{{nested_level.get_absolute_url}}">{{ nested_level }}</a> <span class="fas {% if nested_level_qualification %}text-success fa-check{% if nested_level_qualification.confirmed_by is not None %}-double{% endif %}{% else %}fa-hourglass-start text-warning{%endif%}"></span></li>
</ul>
@@ -73,5 +73,9 @@
</ul>
</div>
</div>
{% include 'partials/last_edited.html' with target="traininglevel_history" %}
<div class="row">
<div class="col text-right">
{% include 'partials/last_edited.html' with target="traininglevel_history" %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends 'base_training.html' %}
{% block content %}
<div class="alert alert-info" role="alert">
<p>Please Note:</p>
<ul>
<li>Technical Assistant status is automatically valid when the item requirements are met.</li>
<li>Technician status is also automatic, but notification of status should be made at the next general meeting, at which point 'approval' should be granted on the system.</li>
<li>Supervisor status is <em>not automatically valid</em> and until signed off at a general meeting, does not count.</li>
</ul>
<sup>Correct as of 3rd September 2021, check the Training Policy.</sup>
</div>
<div class="card-columns">
{% for level in levels %}
<div class="card my-3">
<h3 class="card-header"><a href="{% url 'level_detail' level.pk %}">{{ level }}</a></h3>
<div class="card-body">
<p>{{ level.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endblock %}

View File

@@ -6,19 +6,7 @@
{% load user_level_if_present from tags %}
{% load colour_from_depth from tags %}
{% block css %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'css/selects.css' %}"/>
{% endblock %}
{% block preload_js %}
{{ block.super }}
<script src="{% static 'js/selects.js' %}"></script>
{% endblock %}
{% block js %}
<script src="{% static 'js/autocompleter.js' %}"></script>
<script src="{% static 'js/tooltip.js' %}"></script>
<script>
$('document').ready(function(){
$('#add_record').click(function (e) {
@@ -54,22 +42,15 @@
</div>
<div class="row mb-3">
<h2 class="col-12">Training Levels</h2>
<div class="alert alert-info" role="alert">
<ul>
<li>Technical Assistant is conferred automatically when the item requirements are met.</li>
<li>Technician status is also automatic, but notification of status should be made at the next general meeting, at which point 'approval' should be granted on the system.</li>
<li>Supervisor status is <em>not automatic</em> and until signed off at a general meeting, does not count.</li>
</ul>
<sup>Correct as of 7th July 2021, check the Training Policy.</sup>
</div>
<div class="card-columns">
{% for level in levels %}
{% percentage_complete level object as completion %}
{% if completion > 0 %}
<div class="card my-3">
<h3 class="card-header"><a href="{% url 'level_detail' level.pk %}">{{ level }}</a></h3>
<div class="card-body">
<p>{{ level.description|truncatewords:30 }}</p>
<div class="progress mb-2">
{% percentage_complete level object as completion %}
<div class="progress-bar progress-bar-striped" role="progressbar" style="width: {{completion}}%" aria-valuenow="{{completion}}" aria-valuemin="0" aria-valuemax="100">{{completion}}% complete</div>
</div>
</div>
@@ -90,6 +71,7 @@
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>

View File

@@ -7,7 +7,6 @@ from training import views
urlpatterns = [
path('items/', views.ItemList.as_view(), name='item_list'),
path('trainee/list/', views.TraineeList.as_view(), name='trainee_list'),
path('trainee/', login_required(views.TraineeDetail.as_view()), name='trainee_detail'),
path('trainee/<int:pk>/',
@@ -16,6 +15,7 @@ urlpatterns = [
path('trainee/<int:pk>/edit/', views.AddQualification.as_view(),
name='edit_record'),
path('session/', views.SessionLog.as_view(), name='session_log'),
path('levels/', views.LevelList.as_view(), name='level_list'),
path('level/<int:pk>/', views.LevelDetail.as_view(), name='level_detail'),
path('level/<int:pk>/add_requirement/', views.AddLevelRequirement.as_view(), name='add_requirement'),
path('level/remove_requirement/<int:pk>/', views.RemoveRequirement.as_view(), name='remove_requirement'),

View File

@@ -28,6 +28,7 @@ class TraineeDetail(views.ProfileDetail, ModalURLMixin):
def get_context_data(self, **kwargs):
context = super(TraineeDetail, self).get_context_data(**kwargs)
context["page_title"] = "{}'s Training Record".format(self.object.first_name + " " + self.object.last_name)
# TODO Filter this to levels the user has
context["levels"] = models.TrainingLevel.objects.all()
context["categories"] = models.TrainingCategory.objects.all().prefetch_related('items')
choices = models.TrainingItemQualification.CHOICES
@@ -53,6 +54,17 @@ class TraineeItemDetail(generic.ListView):
return context
class LevelList(generic.ListView):
model = models.TrainingLevel
template_name = "level_list.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_title"] = "All Training Levels"
context["levels"] = models.TrainingLevel.objects.all()
return context
class TraineeList(generic.ListView):
model = models.Trainee
template_name = 'trainee_list.html'
@@ -130,7 +142,7 @@ class LevelDetail(generic.DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_title"] = "Training Level {}".format(self.object)
context["page_title"] = "Training Level {} <span class='badge badge-{} badge-pill'><span class='fas fa-{}'></span></span>".format(self.object, self.object.get_department_colour(), self.object.icon)
context["users_with"] = map(lambda qual: qual.trainee, models.TrainingLevelQualification.objects.filter(level=self.object))
return context