Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Answer page saving improvements #171

Merged
merged 9 commits into from
Jul 15, 2024
7 changes: 6 additions & 1 deletion ceuk-marking/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
marking.SectionAuthorityList.as_view(),
name="section_authorities",
),
path(
"authorities/<name>/section/<section_title>/questions/<question>/",
marking.AuthoritySectionJSONQuestion.as_view(),
name="authority_json_question_edit",
),
path(
"authorities/<name>/section/<section_title>/questions/",
marking.AuthoritySectionQuestions.as_view(),
Expand Down Expand Up @@ -240,7 +245,7 @@
),
path(
"volunteers/<user_id>/assign/",
volunteers.VolunteerAssignentView.as_view(),
volunteers.VolunteerAssignmentView.as_view(),
name="assign_volunteer",
),
path(
Expand Down
9 changes: 5 additions & 4 deletions crowdsourcer/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class Meta:


class CreateMarkerForm(MarkerForm):
send_reset = BooleanField(label="Send registration email")
send_reset = BooleanField(label="Send registration email", required=False)


MarkerFormset = inlineformset_factory(User, Marker, form=MarkerForm, can_delete=False)
Expand All @@ -401,12 +401,12 @@ class ResetEmailForm(Form):
user_id = CharField(required=True, widget=HiddenInput)


class VolunteerAssignentForm(ModelForm):
class VolunteerAssignmentForm(ModelForm):
def __init__(self, session=None, **kwargs):
super().__init__(**kwargs)
if session is not None:
self.fields["authority"].queryset = PublicAuthority.objects.filter(
questiongroup__marking_session=session,
marking_session=session,
).order_by("name")
self.fields["section"].queryset = Section.objects.filter(
marking_session=session
Expand All @@ -421,6 +421,7 @@ def __init__(self, session=None, **kwargs):
response_type=self.instance.response_type,
marking_session=session,
section=self.instance.section,
authority__isnull=False,
)
.exclude(id=self.instance.id)
.values_list("authority_id", flat=True)
Expand All @@ -445,7 +446,7 @@ class Meta:


VolunteerAssignmentFormset = inlineformset_factory(
User, Assigned, form=VolunteerAssignentForm, extra=1
User, Assigned, form=VolunteerAssignmentForm, extra=1
)


Expand Down
75 changes: 75 additions & 0 deletions crowdsourcer/static/js/questions.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const form_regex = /form-\d+-/i
function get_name_from_input(input) {
return input.name.replace(form_regex, "");
}

function disable_submit_if_invalid() {
if ($('.invalid-feedback').length > 0) {
$('#save_all_answers').prop("disabled", true);
} else {
$('#save_all_answers').prop("disabled", false);
}
}

$(function(){
$('.form-select, .form-control, .form-check-input').on('blur', function(e){
var $d = $(this);
var $fs = $d.parents('fieldset');

var csrf = $d.parents('form').find('input[name="csrfmiddlewaretoken"]').val()
let data = {"csrfmiddlewaretoken": csrf};
let has_values = false;
$fs.find('.form-select, .form-control, input[type="hidden"]').each(function() {
let $f = $(this);
let name = get_name_from_input($f[0]);
let val = $f.val();
if (name != "question" && name != "authority" && val) {
has_values = true;
}
data[name] = val;
});
if ( $fs.find('.form-check-input').length ) {
let $f = $fs.find('.form-check-input').get(0);
let name = get_name_from_input($f);
data[name] = $( $f.name ).val();
}

if (!has_values) {
$fs.find('.form-select, .form-control, .form-check-input, input[type="hidden"]').each(function() {
let $f = $(this);
$f.removeClass("is-invalid is-valid");
$f.next('.invalid-feedback').remove();
});
disable_submit_if_invalid()
return;
}

let url = window.location + data["question"] + "/";

$.post(url, data, function(r_data) {
if (r_data["success"] != 1) {
$fs.find('.form-select, .form-control, .form-check-input, input[type="hidden"]').each(function() {
let $f = $(this);
let name = get_name_from_input($f[0]);
$f.next('.invalid-feedback').remove();
if (r_data["errors"].hasOwnProperty(name)) {
$f.addClass("is-invalid").removeClass("is-valid");
$f.after('<div class="invalid-feedback">' + r_data["errors"][name] + '</div>');
} else {
$f.addClass("is-valid").removeClass("is-invalid");
}
});
$('#save_all_answers').prop("disabled", true);
} else {
$fs.find('.form-select, .form-control, .form-check-input, input[type="hidden"]').each(function() {
$f = $(this);
let name = get_name_from_input($f[0]);
$f.next('.invalid-feedback').remove();
$f.addClass("is-valid").removeClass("is-invalid");
});

disable_submit_if_invalid()
}
});
});
});
41 changes: 38 additions & 3 deletions crowdsourcer/static/js/volunteer.esm.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
const name_regex = /assigned_set-(?<id>\d+)-(?<name>\w+)/i

async function getAvailableAuthorities($fs) {
var url = "/volunteers/available_authorities/";

var $session = $fs.find('.field_session').eq(0);
var $section = $fs.find('.field_section').eq(0);
var $rt = $fs.find('.field_rt').eq(0);
var $id = $fs.find('[name$="-id"]').eq(0);

if ($rt.val() == "" || $section.val() == "") {
return { results: [] };
}

url = url + "?rt=" + $rt.val() + "&s=" + $section.val() + "&ms=" + $session.val()
var params = {
rt: $rt.val(),
s: $section.val(),
ms: $fs.find('.field_session').eq(0).val()
};


if ($id.val()) {
params['id'] = $id.val();
}

url = url + '?' + $.param(params);

const response = await fetch(url, {
method: 'GET',
Expand All @@ -24,7 +37,7 @@ async function getAvailableAuthorities($fs) {
return response.json()
}
$(function(){
$('select .field_rt,select .field_section').on('change', function(e){
$('.field_rt,.field_section').on('change', function(e){
var $d = $(this);
var $fs = $d.parents('fieldset');

Expand All @@ -42,4 +55,26 @@ $(function(){
}
});
});

$('#add_row').on('click', function(e){
var $form = $('#assign_form');
var $fs = $('#assign_form fieldset').last();

var $new_fs = $fs.clone(true);
$new_fs.find('input, select').each(function() {
let $input = $(this);
let name = $input.attr('name');
let matches = name.match(name_regex);
let id = parseInt(matches.groups['id']);
id = id + 1;

let new_name = 'assigned_set-' + id + '-' + matches.groups['name'];
$input.attr('name', new_name);

});

$fs.after($new_fs);
var $total_forms = $('#assign_form input[name="assigned_set-TOTAL_FORMS"]');
$total_forms.val(parseInt($total_forms.val()) + 1);
});
});
7 changes: 6 additions & 1 deletion crowdsourcer/templates/crowdsourcer/authority_questions.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% extends 'crowdsourcer/base.html' %}

{% load django_bootstrap5 %}
{% load static %}

{% block content %}
<h1 class="mb-3 mb-md-4">
Expand Down Expand Up @@ -82,8 +83,12 @@ <h3 class="mb-4 mb-md-5 text-success">
{% endfor %}

<div class="sticky-bottom py-3 bg-white border-top" style="margin-top: -1px;">
<input type="submit" class="btn btn-primary" value="Save answers">
<input id="save_all_answers" type="submit" class="btn btn-primary" value="Save answers">
</div>
</form>

{% endblock %}

{% block script %}
<script src="{% static 'js/questions.esm.js' %}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

{% load django_bootstrap5 %}
{% load neighbourhood_filters %}
{% load static %}

{% block content %}
<h1 class="mb-3 mb-md-4">
Expand Down Expand Up @@ -173,7 +174,7 @@ <h3 class="h5 text-muted mb-3 mb-lg-4">New response</h3>
{% endfor %}

<div class="sticky-bottom py-3 bg-white border-top" style="margin-top: -1px;">
<input type="submit" class="btn btn-primary" value="Save answers">
<input id="save_all_answers" type="submit" class="btn btn-primary" value="Save answers">
</div>
</form>

Expand Down Expand Up @@ -206,3 +207,7 @@ <h3 class="h5 text-muted mb-3 mb-lg-4">New response</h3>
</script>

{% endblock %}

{% block script %}
<script src="{% static 'js/questions.esm.js' %}"></script>
{% endblock %}
4 changes: 2 additions & 2 deletions crowdsourcer/templates/crowdsourcer/volunteers/assign.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1 class="mb-4">Sign in</h1>
<h3 class="mb-4">Assign to {{ user.username }}</h3>


<form action="" method="post">
<form action="" method="post" id="assign_form">
{% csrf_token %}
{% if formset.total_error_count > 0 %}
<div class="mb-4">
Expand Down Expand Up @@ -86,7 +86,7 @@ <h3 class="mb-4">Assign to {{ user.username }}</h3>
</fieldset>
{% endfor %}
</div>
<input type="submit" value="Update">
<input type="submit" class="btn btn-primary" value="Update"> <input type="button" class="btn btn-secondary" id="add_row" value="Add Row">
</form>

{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion crowdsourcer/templates/crowdsourcer/volunteers/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h1 class="mb-4">Edit Volunteer</h1>
</form>
</div>

{% if self.user.email %}
{% if user.email %}
<div class="mb-4">
<form action="{% session_url 'reset_volunteer_email' %}" method="post">
{% csrf_token %}
Expand Down
Loading
Loading