Merge pull request #7 from vincentmdealmeida/ValidationV2.3
Modified the polls view for an event to show not only the list of pol…
This commit is contained in:
commit
e7440e6d6e
4 changed files with 117 additions and 69 deletions
|
@ -45,8 +45,8 @@ class CreateNewEventModelAdaptor:
|
|||
self.form_data = form_data.copy()
|
||||
self.user = user
|
||||
# TODO: Call validation func here (incl functionality for verifying CSRF + reCAPTCHA)
|
||||
print("Form Data:")
|
||||
print(self.form_data)
|
||||
#print("Form Data:")
|
||||
#print(self.form_data)
|
||||
self.__extractData()
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<div class="form-group">
|
||||
<label for="name-input" class="col-sm-3 col-md-2 control-label">Name:</label> <!-- This text can be a template variable -->
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<input type="text" class="form-control input-control" id="name-input" placeholder="Example: My poll" name="name-input" maxlength="255">
|
||||
<input type="text" class="form-control input-control" id="name-input" placeholder="Example: EU Election" name="name-input" maxlength="255">
|
||||
<span id="name-input-hint-block" class="help-block">
|
||||
A short and clear name.
|
||||
</span>
|
||||
|
@ -57,7 +57,7 @@
|
|||
<div class="form-group">
|
||||
<label for="identifier-input" class="col-sm-3 col-md-2 control-label">Identifier:</label> <!-- This text can be a template variable -->
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<input type="text" class="form-control input-control" id="identifier-input" placeholder="Example: My-poll" name="identifier-input" maxlength="255">
|
||||
<input type="text" class="form-control input-control" id="identifier-input" placeholder="Example: eu-election" name="identifier-input" maxlength="255">
|
||||
<span id="identifier-input-help-block" class="help-block">
|
||||
Used in the election URL, it must only consist of letters, numbers, underscores or hyphens; no whitespace is permitted.
|
||||
</span>
|
||||
|
|
|
@ -4,17 +4,25 @@
|
|||
|
||||
{% block event_nav_polls %}active{% endblock %}
|
||||
{% block event_content %}
|
||||
<h2>Related Polls</h2>
|
||||
<h2>Event Polls</h2>
|
||||
{% if object.polls.all %}
|
||||
<ul class="list-group">
|
||||
{% for poll in object.polls.all %}
|
||||
<li class="list-group-item"><a href="{% url 'polls:view-poll' event_id=event.id poll_num=forloop.counter %}">{{ poll.question_text }}</a></li>
|
||||
<hr/>
|
||||
<h3>Poll: {{ poll.question_text }} (<a href="{% url 'polls:view-poll' event_id=event.id poll_num=forloop.counter %}">Edit</a>)</h3>
|
||||
<br/>
|
||||
<h4>Poll Options:</h4>
|
||||
<ul class="list-group">
|
||||
{% for option in poll.options.all %}
|
||||
<li class="list-group-item">{{ option.choice_text }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p>Minimum Number of Option Selections: {{ poll.min_num_selections }}. Maximum Number of Option Selections: {{ poll.max_num_selections }}.</p>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>No polls are available for this Event.</p>
|
||||
{% endif %}
|
||||
{% if is_organiser %}
|
||||
<hr/>
|
||||
<a href="{% url 'polls:create-poll' event.id %}" class="btn btn-default" role="button">Add Poll</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Form submission and validation
|
||||
var updateModes = {create: 1, update: 2, delete: 3};
|
||||
var submitBtn = $("#submit-event-create");
|
||||
var submitBtnLabel = "Create Event";
|
||||
var submitBtnWaitLabel = "Please wait...";
|
||||
|
@ -10,6 +11,8 @@ var generalErrorBlock = document.getElementById('all-errors-help-block');
|
|||
var errors = [];
|
||||
var create = true;
|
||||
var pollCount = 0;
|
||||
var pollIndex = 0;
|
||||
var pollEditActive = false;
|
||||
var numOfOpts = 2;
|
||||
|
||||
function finalisePolls() {
|
||||
|
@ -278,12 +281,12 @@ function isPollQValid() {
|
|||
var valid = true;
|
||||
|
||||
// Check question is valid
|
||||
var question = $('#question-name-input-' + pollCount).val();
|
||||
var question = $('#question-name-input-' + pollIndex).val();
|
||||
|
||||
if(question === '') {
|
||||
checkAndAddError({
|
||||
error: "Question / Statement for the poll is blank.",
|
||||
helpBlockId: "question-input-error-block-" + pollCount
|
||||
helpBlockId: "question-input-error-block-" + pollIndex
|
||||
});
|
||||
|
||||
valid = false;
|
||||
|
@ -294,8 +297,8 @@ function isPollQValid() {
|
|||
|
||||
function isPollOptionsValid() {
|
||||
var valid = true;
|
||||
var optsInputs = $('.option-formset #option-name-input-' + pollCount);
|
||||
var helpBlockId = "options-input-error-block-" + pollCount;
|
||||
var optsInputs = $('.option-formset #option-name-input-' + pollIndex);
|
||||
var helpBlockId = "options-input-error-block-" + pollIndex;
|
||||
|
||||
if(numOfOpts < 1) {
|
||||
checkAndAddError({
|
||||
|
@ -337,10 +340,10 @@ function isPollOptionsValid() {
|
|||
|
||||
function isMinMaxSelectionValid() {
|
||||
var valid = true;
|
||||
var minInput = $('#minimum-input-' + pollCount);
|
||||
var minInput = $('#minimum-input-' + pollIndex);
|
||||
var minInputMinAttr = parseInt(minInput[0].min);
|
||||
var minInputVal = minInput.val();
|
||||
var helpBlockId = "selections-input-error-block-" + pollCount;
|
||||
var helpBlockId = "selections-input-error-block-" + pollIndex;
|
||||
var errorStr = "";
|
||||
|
||||
if(minInputVal === "" || minInputVal < minInputMinAttr) {
|
||||
|
@ -351,7 +354,7 @@ function isMinMaxSelectionValid() {
|
|||
valid = false;
|
||||
}
|
||||
|
||||
var maxInput = $('#maximum-input-' + pollCount);
|
||||
var maxInput = $('#maximum-input-' + pollIndex);
|
||||
var maxInputMinAttr = parseInt(maxInput[0].min);
|
||||
var maxInputVal = maxInput.val();
|
||||
|
||||
|
@ -365,7 +368,7 @@ function isMinMaxSelectionValid() {
|
|||
valid = false;
|
||||
} else if (maxInputVal > numOfOpts) {
|
||||
if (errorStr !== '') {
|
||||
errorStr = errorStr + " and the same applies to the maximum";
|
||||
errorStr = errorStr + " and the maximum cannot be more than the number of options (" + numOfOpts + ")";
|
||||
} else {
|
||||
errorStr = "The maximum option selection value (" + maxInputVal + ") cannot be more than the number of options (" + numOfOpts + ")";
|
||||
}
|
||||
|
@ -803,14 +806,14 @@ function updateFormset(formset) { // Ported from DEMOS 1. Updates the row number
|
|||
var forms = formset.children('.formset-form:not(.formset-form-empty, .formset-form-removed)');
|
||||
var removedForms = formset.children('.formset-form.formset-form-removed');
|
||||
forms.each(function(index) {
|
||||
updateForm($(this), index);
|
||||
updateForm($(this), index, updateModes.update);
|
||||
});
|
||||
removedForms.each(function(index) {
|
||||
updateForm($(this), forms.length + index);
|
||||
updateForm($(this), forms.length + index, updateModes.delete);
|
||||
});
|
||||
}
|
||||
|
||||
function updateForm(form, formIndex) { // Ported from DEMOS 1.
|
||||
function updateForm(form, formIndex, mode) { // Ported from DEMOS 1.
|
||||
// Specific update for option forms
|
||||
var mayBeTextInput = form.find('input:text')[0];
|
||||
if(mayBeTextInput !== undefined && mayBeTextInput.placeholder !== undefined) {
|
||||
|
@ -825,6 +828,16 @@ function updateForm(form, formIndex) { // Ported from DEMOS 1.
|
|||
|
||||
var formset = form.parent('.formset');
|
||||
var formsetPrefix = formset.attr('data-formset-prefix');
|
||||
|
||||
if (formsetPrefix === 'polls' && mode === updateModes.update) {
|
||||
// Get a reference to the fields that need updating from the form including the table
|
||||
var formFields = form.find('.formset-form-fields:first >');
|
||||
var table = form.find('.table:first');
|
||||
|
||||
// Perform the ID updates on the fields based on the poll index
|
||||
performFormInputUpdates(formFields, table, formIndex);
|
||||
}
|
||||
|
||||
var formPrefix = formsetPrefix + '-' + formIndex;
|
||||
var formPrefixRegex = new RegExp(formsetPrefix + '-(?:__prefix__|\\d+)');
|
||||
form.find('*').addBack().each(function(index, element) {
|
||||
|
@ -848,54 +861,61 @@ function manageTotalForms(formset, value) { // Ported from DEMOS1.
|
|||
addButton.prop('disabled', parseInt(totalForms.val()) - removedForms.length >= parseInt(maxNumForms.val()));
|
||||
}
|
||||
|
||||
function updateQuestionFormInputs(form) {
|
||||
// Update the name and IDs of all the dialog input fields
|
||||
function updatePollFormInputs(form) {
|
||||
// Obtain the cloned input fields for the dialog in order to update them
|
||||
var clonedFields = form.find('.formset-form-fields:first >');
|
||||
|
||||
// Update the table ID
|
||||
// Obtain a reference to the options table
|
||||
var table = form.find('.table:first');
|
||||
table.attr("id", "options-table-" + pollCount);
|
||||
|
||||
// Perform the ID updates on the fields based on the poll index
|
||||
performFormInputUpdates(clonedFields, table, pollIndex);
|
||||
}
|
||||
|
||||
function performFormInputUpdates(fields, table, index) {
|
||||
// Update the table ID
|
||||
table.attr("id", "options-table-" + index);
|
||||
|
||||
// Update the poll question / statement ID
|
||||
clonedFields.find(".dialogQ:first")
|
||||
.attr("id", "question-name-input-" + pollCount)
|
||||
.attr("name", "question-name-input-" + pollCount);
|
||||
fields.find(".dialogQ:first")
|
||||
.attr("id", "question-name-input-" + index)
|
||||
.attr("name", "question-name-input-" + index);
|
||||
|
||||
// Update one of the help block IDs for various sections of the dialog
|
||||
var pollQuestionErrorHelpBlock = clonedFields.find("#question-input-error-block");
|
||||
pollQuestionErrorHelpBlock.attr("id", "question-input-error-block-" + pollCount);
|
||||
var pollQuestionErrorHelpBlock = fields.find("#question-input-error-block");
|
||||
pollQuestionErrorHelpBlock.attr("id", "question-input-error-block-" + index);
|
||||
|
||||
var pollOptionsErrorHelpBlock = clonedFields.find("#options-input-error-block");
|
||||
pollOptionsErrorHelpBlock.attr("id", "options-input-error-block-" + pollCount);
|
||||
var pollOptionsErrorHelpBlock = fields.find("#options-input-error-block");
|
||||
pollOptionsErrorHelpBlock.attr("id", "options-input-error-block-" + index);
|
||||
|
||||
var pollSelectionsErrorHelpBlock = clonedFields.find("#selections-input-error-block");
|
||||
pollSelectionsErrorHelpBlock.attr("id", "selections-input-error-block-" + pollCount);
|
||||
var pollSelectionsErrorHelpBlock = fields.find("#selections-input-error-block");
|
||||
pollSelectionsErrorHelpBlock.attr("id", "selections-input-error-block-" + index);
|
||||
|
||||
// Update the poll option input IDs
|
||||
var optsInputs = clonedFields.find(".dialogO");
|
||||
var optsInputs = fields.find(".dialogO");
|
||||
|
||||
for(var i = 0; i < optsInputs.length; i++) {
|
||||
var input = optsInputs[i];
|
||||
input.id = "option-name-input-" + pollCount;
|
||||
input.name = "option-name-input-" + pollCount;
|
||||
input.id = "option-name-input-" + index;
|
||||
input.name = "option-name-input-" + index;
|
||||
}
|
||||
|
||||
// Update the data-formset-prefix for correct referencing
|
||||
var dataFormsetPrefix = "options-" + pollCount;
|
||||
var optionFormSet = clonedFields.find(".option-formset");
|
||||
var dataFormsetPrefix = "options-" + index;
|
||||
var optionFormSet = fields.find(".option-formset");
|
||||
optionFormSet.attr("data-formset-prefix", dataFormsetPrefix);
|
||||
|
||||
var addPollOptBtn = clonedFields.find('.formset-add');
|
||||
var addPollOptBtn = fields.find('.formset-add');
|
||||
addPollOptBtn.attr("data-formset-prefix", dataFormsetPrefix);
|
||||
|
||||
// Update the poll min and max selection
|
||||
clonedFields.find(".min-input:first")
|
||||
.attr("id", "minimum-input-" + pollCount)
|
||||
.attr("name", "minimum-input-" + pollCount);
|
||||
fields.find(".min-input:first")
|
||||
.attr("id", "minimum-input-" + index)
|
||||
.attr("name", "minimum-input-" + index);
|
||||
|
||||
clonedFields.find(".max-input:first")
|
||||
.attr("id", "maximum-input-" + pollCount)
|
||||
.attr("name", "maximum-input-" + pollCount);
|
||||
fields.find(".max-input:first")
|
||||
.attr("id", "maximum-input-" + index)
|
||||
.attr("name", "maximum-input-" + index);
|
||||
}
|
||||
|
||||
function isDialogFormValid() {
|
||||
|
@ -904,7 +924,7 @@ function isDialogFormValid() {
|
|||
var minMaxSelValid = true;
|
||||
|
||||
// Check question is valid
|
||||
var pollQErrorHelpBlockId = "question-input-error-block-" + pollCount;
|
||||
var pollQErrorHelpBlockId = "question-input-error-block-" + pollIndex;
|
||||
pollQValid = isPollQValid();
|
||||
|
||||
if(pollQValid === true) {
|
||||
|
@ -914,7 +934,7 @@ function isDialogFormValid() {
|
|||
}
|
||||
|
||||
// Check opts are valid
|
||||
var pollOptsErrorHelpBlockId = "options-input-error-block-" + pollCount;
|
||||
var pollOptsErrorHelpBlockId = "options-input-error-block-" + pollIndex;
|
||||
optsValid = isPollOptionsValid();
|
||||
|
||||
if(optsValid === true) {
|
||||
|
@ -924,7 +944,7 @@ function isDialogFormValid() {
|
|||
}
|
||||
|
||||
// Check min and max selections are valid
|
||||
var pollSelErrorHelpBlockId = "selections-input-error-block-" + pollCount;
|
||||
var pollSelErrorHelpBlockId = "selections-input-error-block-" + pollIndex;
|
||||
minMaxSelValid = isMinMaxSelectionValid();
|
||||
|
||||
if(minMaxSelValid === true) {
|
||||
|
@ -937,8 +957,8 @@ function isDialogFormValid() {
|
|||
}
|
||||
|
||||
function updateSelectionsMaxAtrr() {
|
||||
var minInput = $('#minimum-input-' + pollCount);
|
||||
var maxInput = $('#maximum-input-' + pollCount);
|
||||
var minInput = $('#minimum-input-' + pollIndex);
|
||||
var maxInput = $('#maximum-input-' + pollIndex);
|
||||
|
||||
// Get the vals from the selection inputs and update them if they exceed the new max
|
||||
var minInputVal = minInput.val();
|
||||
|
@ -967,23 +987,29 @@ $('.formset-add').click(function (e) { // Ported from DEMOS1
|
|||
|
||||
switch (formsetPrefix) {
|
||||
case "polls":
|
||||
// Update the IDs and names of all of the cloned input form fields based on the number of polls
|
||||
updateQuestionFormInputs(form);
|
||||
// Set the index
|
||||
pollIndex = pollCount;
|
||||
|
||||
// 2 is the default number shown upon the launch of the dialog
|
||||
// Update the IDs and names of all of the cloned input form fields based on the number of polls
|
||||
updatePollFormInputs(form);
|
||||
|
||||
// 2 is the default number of opts shown upon the launch of the dialog
|
||||
numOfOpts = 2;
|
||||
|
||||
// New poll is being created so edit mode hasn't been activated
|
||||
pollEditActive = false;
|
||||
break;
|
||||
case "options-" + pollCount:
|
||||
case "options-" + pollIndex:
|
||||
numOfOpts++;
|
||||
updateSelectionsMaxAtrr();
|
||||
clearError("options-input-error-block-" + pollCount);
|
||||
clearError("options-input-error-block-" + pollIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
var formIndex = formset.children('.formset-form:not(.formset-form-empty)').length;
|
||||
|
||||
formset.append(form);
|
||||
updateForm(form, formIndex);
|
||||
updateForm(form, formIndex, updateModes.create);
|
||||
emptyFormCheckedInputs.each(function (index) {
|
||||
$(this).prop('checked', true);
|
||||
});
|
||||
|
@ -1010,19 +1036,23 @@ $('.formset-form-remove').click(function (e) { // Ported from DEMOS1
|
|||
form.remove();
|
||||
manageTotalForms(formset, -1);
|
||||
}
|
||||
|
||||
// We need to reduce the poll count if we've removed a poll
|
||||
if(formPrefix === "poll") {
|
||||
pollCount--;
|
||||
}
|
||||
|
||||
// Update the formset and inform that a form has been removed
|
||||
updateFormset(formset);
|
||||
formset.trigger('formsetFormRemoved');
|
||||
|
||||
// Perform validation now that a row has been removed
|
||||
// Perform validation and other operations now that a row has been removed based on the affected table
|
||||
switch (formPrefix) {
|
||||
case 'poll':
|
||||
// TODO: A poll has been removed so we need to update the poll count
|
||||
break;
|
||||
case 'option':
|
||||
// Decrement the number of total options and validate the options list
|
||||
numOfOpts--;
|
||||
updateSelectionsMaxAtrr();
|
||||
validateFormField(isPollOptionsValid, "options-input-error-block-" + pollCount);
|
||||
validateFormField(isPollOptionsValid, "options-input-error-block-" + pollIndex);
|
||||
break;
|
||||
case 'organiser':
|
||||
validateFormField(areOrganisersEmailsValid, "organisers-input-error-block");
|
||||
|
@ -1037,25 +1067,35 @@ $('.formset-form-save').click(function (e) {
|
|||
var dialogValid = isDialogFormValid();
|
||||
|
||||
if(dialogValid === true) {
|
||||
// TODO: Clear errors
|
||||
var modal = $(this).closest('.modal');
|
||||
var form = modal.data('form');
|
||||
var name = $('#question-name-input-' + pollCount).val();
|
||||
var name = $('#question-name-input-' + pollIndex).val();
|
||||
form.find('.formset-form-name:first').text(name);
|
||||
modal.data('formSave', true);
|
||||
modal.modal('hide');
|
||||
|
||||
if(!pollEditActive) {
|
||||
// Increment the poll count and clear any validation errors
|
||||
pollCount++;
|
||||
clearError("polls-input-error-block");
|
||||
} else {
|
||||
//highlightErrors();
|
||||
pollEditActive = false;
|
||||
}
|
||||
|
||||
clearError("polls-input-error-block");
|
||||
}
|
||||
});
|
||||
|
||||
function extractPollIndexFromId(id) {
|
||||
var idSplitArray = id.split('-');
|
||||
pollIndex = parseInt(idSplitArray[3]);
|
||||
}
|
||||
|
||||
$('.formset-form-edit').click(function (e) {
|
||||
var form = $(this).closest('.formset-form');
|
||||
var questionNameInput = form.find('.formset-form-fields:first > .dialogFormField > .dialogQ');
|
||||
extractPollIndexFromId(questionNameInput.attr('id'));
|
||||
$('#formset-modal').data('form', form).modal('show');
|
||||
pollEditActive = true;
|
||||
});
|
||||
|
||||
$('#formset-modal').on('show.bs.modal', function (e) { // Ported from DEMOS1
|
||||
|
@ -1074,7 +1114,7 @@ $('#formset-modal').on('show.bs.modal', function (e) { // Ported from DEMOS1
|
|||
formset.trigger('formsetModalShow', [modalBody]);
|
||||
|
||||
// Attach an event handler for poll option row sorting
|
||||
$("#options-table-" + pollCount).sortable({
|
||||
$("#options-table-" + pollIndex).sortable({
|
||||
items: "tr",
|
||||
update: update
|
||||
});
|
||||
|
|
Reference in a new issue