Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ WAM/.ropeproject/history
WAM/.ropeproject/objectdb
WAM/local_settings.py
.DS_Store
django.log
*.log
/WAM/local
*THINKINGS.txt*
*.key
Expand Down
2 changes: 2 additions & 0 deletions WAM/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
# This ensures local files are searched first
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'loads/static')]

# Where do we store media
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Expand Down
111 changes: 82 additions & 29 deletions loads/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ class LoadsByModulesForm(forms.Form):
)


class LoadChartsForm(forms.Form):
""" This exposes some options for load charts views """

show_90_110 = forms.BooleanField(required=False, initial=False, help_text='Show 90% and 110% boundaries')
sort_by_load = forms.BooleanField(required=False, initial=True)


class ModulesIndexForm(forms.Form):
"""This prompts for comma separated semesters used for some restrictions"""
semesters = forms.CharField(
Expand Down Expand Up @@ -464,11 +471,14 @@ def save(self):


class BaseModuleStaffByStaffFormSet(FancyModelFormSet):
""" Enables altering teaching allocation for a member of staff from staff views """

def clean(self):
"""
Adds validation to check that no two links have the same anchor or URL
and that all links have both an anchor and URL.
Adds validation to check that no module is in the list twice, or that combined percentages exceed 100
"""

# Don't validate the whole formset (yet) if individual forms have issues
if any(self.errors):
return

Expand Down Expand Up @@ -508,19 +518,23 @@ def clean(self):
code='invalid_assessment_proportion'
)

if duplicates:
raise forms.ValidationError(
'Modules should not appear more than once.',
code='duplicate_modules'
)
if duplicates:
raise forms.ValidationError(
'Modules should not appear more than once.',
code='duplicate_modules'
)


class BaseModuleStaffByModuleFormSet(FancyModelFormSet):
""" Enables altering teaching allocation for a module from module views """

def clean(self):
"""
Adds validation to check that no two links have the same anchor or URL
and that all links have both an anchor and URL.
Adds overall validation to check that no staff member is in the list twice,
or that combined percentages exceed 100
"""

# Don't validate the whole formset (yet) if individual forms have issues
if any(self.errors):
return

Expand Down Expand Up @@ -567,23 +581,62 @@ def clean(self):
code='invalid_assessment_proportion'
)

if duplicates:
raise forms.ValidationError(
'Staff members should not appear more than once.',
code='duplicate_staff'
)
if contact_total > 100:
raise forms.ValidationError(
'Contact proportions are over 100%',
code='invalid_contact_total'
)
if admin_total > 100:
raise forms.ValidationError(
'Admin proportions are over 100%',
code='invalid_contact_total'
)
if assessment_total > 100:
raise forms.ValidationError(
'Assessment proportions are over 100%',
code='invalid_contact_total'
)
if duplicates:
raise forms.ValidationError(
'Staff members should not appear more than once.',
code='duplicate_staff'
)

if contact_total > 100:
raise forms.ValidationError(
'Contact proportions are over 100%',
code='invalid_contact_total'
)

if admin_total > 100:
raise forms.ValidationError(
'Admin proportions are over 100%',
code='invalid_contact_total'
)

if assessment_total > 100:
raise forms.ValidationError(
'Assessment proportions are over 100%',
code='invalid_contact_total'
)


class BaseProjectStaffFormSet(FancyModelFormSet):
""" Enables altering project allocations """

def clean(self):
"""
Adds overall validation to check that no staff member is in the list twice
"""

# Don't validate the whole formset (yet) if individual forms have issues
if any(self.errors):
return

staff_members = []

duplicates = False

for form in self.forms:
# If the form is deleted, don't validate, its data is about to be nuked
if form in self.deleted_forms:
continue

if form.cleaned_data:
staff = form.cleaned_data['staff']

if staff in staff_members:
duplicates = True
staff_members.append(staff)

if duplicates:
raise forms.ValidationError(
'Staff members should not appear more than once.',
code='duplicate_staff'
)

11 changes: 11 additions & 0 deletions loads/static/fancy_formset/README.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
WARNING!

This file is here because there is an apparent bug in fancy_formset 1.0.0, which seems to decrement total forms on
a form deletion. This does not appear to be correct behaviour, and can be diagnosed from trying to delete a single
remaining formset that was already in the model layer.

This file includes a patched version of the library that will be loaded in preference if STATICFILES_DIR is set
up correctly.

This file / directory needs to be removed if and when the library is patched, or this local copy will continue to
override the main library.
1 change: 1 addition & 0 deletions loads/static/fancy_formset/formset.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 77 additions & 2 deletions loads/templates/loads/loads_charts.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,77 @@ <h6 class="fw-bold">!! Please note these exceptions <i class="fw-normal small wa
</div>
{% endif %}

<a class="btn btn-info wam-hide-on-print mb-3" data-bs-toggle="collapse" href="#filterForm" role="button" aria-controls="filterForm">
Filter
</a>

<div class="border border-secondary-subtle rounded-3 p-3 mb-3 collapse wam-hide-on-print"
id="filterForm">
<h6 class="mt-1 mb-5">Use this form to select graph formatting options.</h6>
<form action="" method="post">
{% csrf_token %}
{# Process hidden fields, we don't need to style them #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}

{% for field in form.visible_fields %}
<div class="row mb-3">
<label for="{{ field.id_for_label }}"
class="col-12 col-md-3 form-label">{{ field.label }}</label>
{% if field.field.widget.input_type == "text" %}
<div class="col-12 col-md-8">
<input type="{{ field.field.widget.input_type }}"
class="form-control"
id="{{ field.id_for_label }}"
{% if not field.field.max_length is None %}
maxlength="{{ field.field.max_length }}"
{% endif %}
name="{{ field.html_name }}" value="{{ field.value }}" />
{# Show field errors as a list, one per line #}
{% if field.errors %}
<div class="text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% elif field.field.widget.input_type == "select" %}
<div class="col-12 col-md-8">
<select class="form-select" id="{{ field.id_for_label }}" name="{{ field.name }}" value="{{ field.value }}">
{% for option in field.field.choices %}
<option value="{{ option.0|escape }}"{% if field.value == option.0|stringformat:"s" %} selected{% endif %}>
{{ option.1|escape }}
</option>
{% endfor %}
</select>
{# Show field errors as a list, one per line #}
{% if field.errors %}
<div class="text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% elif field.field.widget.input_type == "checkbox" %}
<div class="col">
<input type="{{ field.field.widget.input_type }}"
class="form-check-input" id="{{ field.id_for_label }}"
name="{{ field.name }}" value="1"{% if field.value is True %} checked{% endif %} />
</div>
{% else %}
<pre>Unknown field type: {{ field.field.widget.input_type }}</pre>
{% endif %}
</div>
{% endfor %}

{# {{ form }} #}
<input type="submit" class="btn btn-primary" value="Submit" />
</form>
</div>

{% if group_data %}
{% for group, group_list, group_total, group_average, group_allocated_staff, group_allocated_average in group_data %}
<div class="container p-5 bg-body-secondary shadow-sm rounded printBreakWAM">
Expand All @@ -51,7 +122,9 @@ <h3>
{% for staff, loads_by_category, hours, bar_width, scaled_hours in group_list %}
<!-- Start a row -->
<div class="chart-row">
<div class="chart-label"><a class="link-offset-2 link-underline link-underline-opacity-25" href="{% url 'activities' staff.id %}">{{ staff }}</a></div>
<div class="chart-label">
<a class="link-offset-2 link-underline link-underline-opacity-25" href="{% url 'activities' staff.id %}">{{ staff }}</a>
</div>
<div class="progress-wrapper">
<div class="hundred-percent-marker"></div>
{% if show_90_110 %}
Expand All @@ -72,7 +145,7 @@ <h3>
</div>
{% endfor %}
</div>
<div class="alert alert-info small">
<div class="alert alert-info small mt-4">
<strong>Legend:</strong> The red dashed line represents 100% capacity, taking into account staff FTE.
{% if show_90_110 %}
Grey dashed lines represent 90% and 100% capacity.
Expand All @@ -98,6 +171,8 @@ <h3>
<p>
No allocations for this group at this time
</p>
</div>
<br/>
{% endif %}
{% endfor %}
<h3 class="mt-4">
Expand Down
7 changes: 7 additions & 0 deletions loads/templates/loads/modules/allocations.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ <h3 class="my-3">
</div>
</fieldset>
{% endfor %}
{% if formset.non_form_errors %}
<div class="text-bg-danger my-3 p-2">
{% for error in formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
</div>
{% endif %}
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
Expand Down
7 changes: 7 additions & 0 deletions loads/templates/loads/projects/allocations.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ <h6 class="d-none d-print-block fw-bold">Project details</h6>
</div>
</fieldset>
{% endfor %}
{% if formset.non_form_errors %}
<div class="text-bg-danger my-3 p-2">
{% for error in formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
</div>
{% endif %}
</div>
</div>

Expand Down
7 changes: 7 additions & 0 deletions loads/templates/loads/staff/allocations.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ <h5 class="font-monospace mb-5">{{package}}</h5>
</div>
</fieldset>
{% endfor %}
{% if formset.non_form_errors %}
<div class="text-bg-danger my-3 p-2">
{% for error in formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
</div>
{% endif %}
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
Expand Down
Loading