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
8 changes: 6 additions & 2 deletions loads/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,12 @@ class ModulesIndexForm(forms.Form):

class ActivityForm(forms.ModelForm):

hours_percentage_combined = HoursPercentageField(label="Hours / Percentage")
semester = SemesterField()
hours_percentage_combined = HoursPercentageField(
label="Hours / Percentage",
help_text="Select whether this activity is measured in hours or as a percentage of a full load, then enter the value.")
semester = SemesterField(
help_text="Select the semester(s) in which this activity takes place."
)

class Meta:
model = Activity
Expand Down
25 changes: 15 additions & 10 deletions loads/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,16 +912,17 @@ class Activity(models.Model):
(HOURS, 'Hours'),
(PERCENTAGE, 'Percentage'),
)
name = models.CharField(max_length=100)
name = models.CharField(max_length=100, help_text="Specify the name of the activity.")
hours = models.PositiveSmallIntegerField()
percentage = models.PositiveSmallIntegerField()
hours_percentage = models.CharField(max_length=1, choices=HOURPERCENTAGE_CHOICES, default=HOURS)
semester = models.CharField(max_length=10, default='1,2,3', validators=[validate_comma_separated_integer_list])
activity_type = models.ForeignKey('ActivityType', on_delete=models.CASCADE)
module = models.ForeignKey('Module', blank=True, null=True, on_delete=models.CASCADE)
comment = models.CharField(max_length=200, default='', blank=True)
activity_type = models.ForeignKey('ActivityType', on_delete=models.CASCADE, help_text="The activity type is used to help categorise this workload.")
module = models.ForeignKey('Module', blank=True, null=True, on_delete=models.CASCADE, help_text="Optionally, if this activity is associated with a module, enter it here.")
comment = models.CharField(max_length=200, default='', blank=True, help_text="Optionally, add any comment associated with this activity here.")
staff = models.ForeignKey(Staff, null=True, blank=True, on_delete=models.SET_NULL,
limit_choices_to={'is_external': False})
limit_choices_to={'is_external': False},
help_text="If known, allocate this workload to a specific member of staff.")
package = models.ForeignKey('WorkPackage', on_delete=models.CASCADE)
activity_set = models.ForeignKey('ActivitySet', blank=True, null=True, on_delete=models.CASCADE)

Expand Down Expand Up @@ -1152,21 +1153,25 @@ class Module(models.Model):
module_code = models.CharField(max_length=10)
module_name = models.CharField(max_length=200)
campus = models.ForeignKey('Campus', on_delete=models.CASCADE)
semester = models.CharField(max_length=10, validators=[validate_comma_separated_integer_list])
semester = models.CharField(max_length=10, validators=[validate_comma_separated_integer_list],
help_text='Specify which semester(s) this module runs in.')
credits = models.PositiveSmallIntegerField(default=20)
size = models.ForeignKey('ModuleSize', on_delete=models.CASCADE)
contact_hours = models.PositiveSmallIntegerField(blank=True, null=True)
admin_hours = models.PositiveSmallIntegerField(blank=True, null=True)
assessment_hours = models.PositiveSmallIntegerField(blank=True, null=True)
package = models.ForeignKey('WorkPackage', on_delete=models.CASCADE)
details = models.TextField(blank=True, null=True)
programmes = models.ManyToManyField(Programme, blank=True, related_name='modules')
details = models.TextField(blank=True, null=True, help_text="Use this optional field for any explanatory comment.")
programmes = models.ManyToManyField(Programme, blank=True, related_name='modules',
help_text='Specify which programmes this module belongs to, for assessment purposes only.')
lead_programme = models.ForeignKey(Programme, blank=True, null=True, related_name='lead_modules',
on_delete=models.SET_NULL)
on_delete=models.SET_NULL,
help_text='The External Examiner(s) for this programme will be considered the lead examiner, for assessment purposes only.')
coordinator = models.ForeignKey(Staff, blank=True, null=True, related_name='coordinated_modules',
on_delete=models.SET_NULL, limit_choices_to={'is_external': False})
moderators = models.ManyToManyField(Staff, blank=True, related_name='moderated_modules',
limit_choices_to={'is_external': False})
limit_choices_to={'is_external': False},
help_text='Specify who should moderate any assessments in this module. For assessment purposes only.')

def get_contact_hours(self):
"""returns the contact hours for the module
Expand Down
58 changes: 1 addition & 57 deletions loads/templates/loads/activities/activity_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,63 +21,7 @@ <h3 class="my-3">
{{ 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" or field.field.widget.input_type == "number" %}
<div class="col-12 col-md-9">
<input type="{{ field.field.widget.input_type }}" class="form-control" id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.html_name }}"
value="{% if field.value != None %}{{ field.value|stringformat:'s' }}{% endif %}"{% if field.field.required %} required{% endif %} />
{# Show field errors as a list, one per line #}
{% if field.errors %}
<div class="wam-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-9">
<select class="form-select" id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.name }}"
value="{% if field.value != None %}{{ field.value }}{% else %}{% endif %}"
{% if field.field.widget.allow_multiple_selected %} MULTIPLE {% endif %}>
{% for option in field.field.choices %}
<option value="{{ option.0|escape }}"{% if option.0 in field.value or option.0 == field.value %} selected{% endif %}>
{{ option.1|escape }}
</option>
{% endfor %}
</select>
{# Show field errors as a list, one per line #}
{% if field.errors %}
<div class="wam-text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% else %}
<div class="col-12 col-md-9">
{{ field }}
{% if field.errors %}
<div class="wam-text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% include "loads/partials/_form_field.html" %}
{% endfor %}
<div class="row mt-4 mb-2">
<div class="col-12">
Expand Down
58 changes: 1 addition & 57 deletions loads/templates/loads/modules/module_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,63 +21,7 @@ <h3 class="my-3">
{{ 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" or field.field.widget.input_type == "number" %}
<div class="col-12 col-md-9">
<input type="{{ field.field.widget.input_type }}" class="form-control" id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.html_name }}"
value="{% if field.value != None %}{{ field.value|stringformat:'s' }}{% endif %}"{% if field.field.required %} required{% endif %} />
{# 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-9">
<select class="form-select" id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.name }}"
value="{% if field.value != None %}{{ field.value }}{% else %}{% endif %}"
{% if field.field.widget.allow_multiple_selected %} MULTIPLE {% endif %}>
{% for option in field.field.choices %}
<option value="{{ option.0|escape }}"{% if option.0 in field.value or option.0 == field.value %} 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>
{% else %}
<div class="col-12 col-md-9">
{{ field }}
{% if field.errors %}
<div class="wam-text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% include "loads/partials/_form_field.html" %}
{% endfor %}
<div class="row mt-4 mb-3 d-print-none">
<div class="col-6 col-md-9">
Expand Down
10 changes: 10 additions & 0 deletions loads/templates/loads/partials/_field_footer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% if field.help_text %}
<div class="form-text text-muted">{{ field.help_text }}</div>
{% endif %}
{% if field.errors %}
<div class="wam-text-danger small mt-1">
{% for error in field.errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
60 changes: 60 additions & 0 deletions loads/templates/loads/partials/_form_field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<div class="row mb-3">
<label for="{{ field.id_for_label }}" class="col-12 col-md-{{ label_width|default:'3' }} form-label">
{{ field.label }}
{% if field.field.required %}<span class="text-danger ms-1" title="Required">*</span>{% endif %}
</label>

{% if field.field.widget.input_type == "text" or field.field.widget.input_type == "number" %}
<div class="col-12 col-md-{{ input_width|default:'9' }}">
<input type="{{ field.field.widget.input_type }}"
class="form-control{% if field.errors %} is-invalid{% endif %}"
id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.html_name }}"
value="{% if field.value != None %}{{ field.value|stringformat:'s' }}{% endif %}"
{% if field.field.required %} required{% endif %} />
{% include "loads/partials/_field_footer.html" %}
</div>

{% elif field.field.widget.input_type == "select" %}
<div class="col-12 col-md-{{ input_width|default:'9' }}">
<select class="form-select{% if field.errors %} is-invalid{% endif %}"
id="{{ field.id_for_label }}"
{% for name, value in field.field.widget.attrs.items %}
{% if value is not False %}{{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}
{% endfor %}
name="{{ field.name }}"
{% if field.field.widget.allow_multiple_selected %} multiple{% endif %}>
{% for option in field.field.choices %}
<option value="{{ option.0|escape }}"
{% if option.0 in field.value or option.0 == field.value %} selected{% endif %}>
{{ option.1|escape }}
</option>
{% endfor %}
</select>
{% include "loads/partials/_field_footer.html" %}
{% if field.field.widget.allow_multiple_selected %}
<div class="form-text">Hold down <kbd>CTRL</kbd> or <kbd>CMD</kbd> to select multiple options</div>
{% endif %}
</div>

{% elif field.field.widget.input_type == "checkbox" %}
<div class="col-12 col-md-{{ input_width|default:'9' }}">
<input type="checkbox"
class="form-check-input{% if field.errors %} is-invalid{% endif %}"
id="{{ field.id_for_label }}"
name="{{ field.name }}"
value="1"
{% if field.value is True %} checked{% endif %} />
{% include "loads/partials/_field_footer.html" %}
</div>

{% else %}
<div class="col-12 col-md-{{ input_width|default:'9' }}">
{{ field }}
{% include "loads/partials/_field_footer.html" %}
</div>
{% endif %}
</div>
2 changes: 1 addition & 1 deletion loads/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ def add_assessment_resource(request, module_id):
# Assume a lack of permission, unless a coordinator, teaching team member, moderator, examiner, or superuser
permission = False
logger.debug("[%s] checking status for module %s, pre upload" % (request.user, module))
if staff is module.coordinator:
if staff == module.coordinator:
logger.debug("[%s] is a module coordinator" % request.user)
permission = True
elif staff in module.moderators.all():
Expand Down
Loading