Skip to content

Commit

Permalink
OCDS - Group validation errors by type
Browse files Browse the repository at this point in the history
  • Loading branch information
odscjames committed Apr 24, 2019
1 parent ba19f3d commit 365c991
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 19 deletions.
16 changes: 16 additions & 0 deletions cove_ocds/lib/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from collections import defaultdict
import json


def group_validation_errors(validation_errors):
validation_errors_grouped = defaultdict(list)
for error_json, values in validation_errors:
error = json.loads(error_json)
if error['message_type'] == 'required':
validation_errors_grouped['required'].append((error_json, values))
elif error['message_type'] in ['format', 'pattern', 'number', 'minLength', 'string',
'date-time', 'uri', 'object', 'integer', 'array']:
validation_errors_grouped['format'].append((error_json, values))
else:
validation_errors_grouped['other'].append((error_json, values))
return validation_errors_grouped
89 changes: 71 additions & 18 deletions cove_ocds/templates/cove_ocds/explore_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -241,26 +241,79 @@ <h4 class="panel-title">
</div>
{% endif %}

{% if validation_errors %}
{% for error_json, values in validation_errors %}
{% with error=error_json|json_decode %}
{% cove_modal_errors className="validation-errors-"|concat:forloop.counter modalTitle=error.message errorList=values file_type=file_type full_table=True %}
{% endwith %}
{% endfor %}


<a name="validation-errors" class="anchor"></a>
<div class="panel panel-danger">
<div id="validation-panel" class="panel-heading pointer" role="region" aria-expanded="true" aria-controls="validationTable" data-toggle="collapse" data-target="#validationTable">
<h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-up"></span>{% trans 'Structural Errors' %}
</h4>
{% with validation_errors=validation_errors_grouped.required error_prefix='required-' %}
{% if validation_errors %}
{% for error_json, values in validation_errors %}
{% with error=error_json|json_decode %}
{% cove_modal_errors className="validation-errors-"|concat:error_prefix|concat:forloop.counter modalTitle=error.message errorList=values file_type=file_type full_table=True %}
{% endwith %}
{% endfor %}

<a name="validation-errors" class="anchor"></a>
<div class="panel panel-danger">
<div id="validation-panel" class="panel-heading pointer" role="region" aria-expanded="true" aria-controls="validationTable" data-toggle="collapse" data-target="#validationTable">
<h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-up"></span>{% trans 'Structural Errors - Required Fields' %}
</h4>
</div>
<div id="validationTable" class="collapse in panel-body">
{% blocktrans %}Some or all of your data is missing fields which are required by the OCDS schema.{% endblocktrans %}
{% include "cove_ocds/validation_table.html" %}
</div>
</div>
<div id="validationTable" class="collapse in">
{% include "validation_table.html" %}

{% endif %}
{% endwith %}

{% with validation_errors=validation_errors_grouped.format error_prefix='format-' %}
{% if validation_errors %}
{% for error_json, values in validation_errors %}
{% with error=error_json|json_decode %}
{% cove_modal_errors className="validation-errors-"|concat:error_prefix|concat:forloop.counter modalTitle=error.message errorList=values file_type=file_type full_table=True %}
{% endwith %}
{% endfor %}

<a name="validation-errors" class="anchor"></a>
<div class="panel panel-danger">
<div id="validation-panel" class="panel-heading pointer" role="region" aria-expanded="true" aria-controls="validationTable" data-toggle="collapse" data-target="#validationTable">
<h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-up"></span>{% trans 'Structural Errors - Format' %}
</h4>
</div>
<div id="validationTable" class="collapse in panel-body">
{% blocktrans %}Some or all of your data includes fields which are incorrectly formatted.{% endblocktrans %}
{% include "cove_ocds/validation_table.html" %}
</div>
</div>
</div>
{% endif %}

{% endif %}
{% endwith %}

{% with validation_errors=validation_errors_grouped.other error_prefix='other-' %}
{% if validation_errors %}
{% for error_json, values in validation_errors %}
{% with error=error_json|json_decode %}
{% cove_modal_errors className="validation-errors-"|concat:error_prefix|concat:forloop.counter modalTitle=error.message errorList=values file_type=file_type full_table=True %}
{% endwith %}
{% endfor %}

<a name="validation-errors" class="anchor"></a>
<div class="panel panel-danger">
<div id="validation-panel" class="panel-heading pointer" role="region" aria-expanded="true" aria-controls="validationTable" data-toggle="collapse" data-target="#validationTable">
<h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-up"></span>{% trans 'Structural Errors - Other' %}
</h4>
</div>
<div id="validationTable" class="collapse in panel-body">
{% blocktrans %}Some or all of your data has validation errors.{% endblocktrans %}
{% include "cove_ocds/validation_table.html" %}
</div>
</div>

{% endif %}
{% endwith %}



{% if structure_warnings %}
<a name="structure-warnings" class="anchor"></a>
Expand Down
87 changes: 87 additions & 0 deletions cove_ocds/templates/cove_ocds/validation_table.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{% load i18n %}
{% load cove_tags %}

<table class="table table-condensed">
<thead>
<tr>
<th>{% trans 'Error Description' %}</th>
<th>{% trans 'Error Count' %}</th>
<th>{% trans 'First 3 Examples' %}</th>
<th>{% trans 'Location of first 3 errors' %}</th>
{% if file_type == 'xlsx' or file_type == 'csv' %}
<th>{% trans 'Spreadsheet Location of first 3 errors' %}</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for error_json, values in validation_errors %}
{% with error=error_json|json_decode %}
<tr>
{% if error.message_safe %}
<td>
<p>
<strong>{{ error.message_safe | safe }}</strong>
{% if error.message_type in common_error_types %}
<a href="{% url 'common_errors' %}#{{error.message_type}}" target="_blank">(more info)</a>
{% endif %}
</p>
{% if 'schema_title' in error %}
<div class="well well-sm">
<h4>{{ error.schema_title }}</h4>
<p>{{ error.schema_description_safe | safe }}</p>
</div>
{% endif %}
</td>
{% elif error.message_type in common_error_types %}
<td><a href="{% url 'common_errors' %}#{{error.message_type}}"> {{error.message}} </a></td>
{% else %}
<td>{{error.message}}</td>
{% endif %}
<td class="text-center">
{% if values|length > 3 %}
{% if error_prefix %}
<a data-toggle="modal" data-target=".{{"validation-errors-"|concat:error_prefix|concat:forloop.counter}}">
{% else %}
<a data-toggle="modal" data-target=".{{"validation-errors-"|concat:forloop.counter}}">
{% endif %}
{{values|length}}
</a>
{% else %}
{{values|length}}
{% endif %}
</td>
<td>
<ul class="list-unstyled">
{% for value in values|slice:":3" %}
<li> {{value.value}} </li>
{% endfor %}
</ul>
</td>
<td>
<ul class="list-unstyled">
{% for value in values|slice:":3" %}
<li>
{% if value.line %}
<b>{% trans 'Path:' %}</b> {{value.path}}
<b>{% trans 'Line:' %}</b> {{value.line}}
{% else %}
{{ value.path }}
{% endif %}
</li>
{% endfor %}
</ul>
</td>
{% if file_type == 'xlsx' or file_type == 'csv' %}
<td style="white-space: nowrap">
<ul class="list-unstyled">
{% for value in values|slice:":3" %}
<li> <b>Sheet:</b> {{value.sheet}} <b>Row:</b> {{value.row_number}} {% if value.header %} <b>Column:</b> {{value.header}} {% endif %} </li>
{% endfor %}
</ul>
</td>
{% endif %}
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
4 changes: 3 additions & 1 deletion cove_ocds/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from libcove.lib.exceptions import CoveInputDataError
from . lib.ocds_show_extra import add_extra_fields
from cove.views import explore_data_context
from cove_ocds.lib.views import group_validation_errors


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -164,7 +165,8 @@ def explore_ocds(request, pk):

context.update({
'data_schema_version': db_data.data_schema_version,
'first_render': not db_data.rendered
'first_render': not db_data.rendered,
'validation_errors_grouped': group_validation_errors(context['validation_errors']),
})

schema_version = getattr(schema_ocds, 'version', None)
Expand Down

0 comments on commit 365c991

Please sign in to comment.