Commit 09895cd0 authored by Pierre Dittgen's avatar Pierre Dittgen

Fix and improve error handling on home page

parent 8e1b9787
{% extends "base_template.html" %} {% extends "base_template.html" %}
{% block title %}Accueil{% endblock %} {% block title %}Accueil{% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
{% for section in sections %} {% for section in sections %} {% if section.catalog %}
{% if section.catalog %} <div class="my-5">
<div class="my-5"> <h2>{{ section.title }}</h2>
<h2>{{ section.title }}</h2> {% if section.description %}
{% if section.description %} <p class="text-muted">{{ section.description | safe }}</p>
<p class="text-muted">{{ section.description | safe }}</p> {% endif %}
{% endif %} <form action="{{ url_for('custom_validator') }}" method="GET">
<form action="{{ url_for('custom_validator') }}" method="GET"> <div class="form-row">
<div class="form-row"> <div class="form-group col-lg-9">
<div class="form-group col-lg-9"> <select required name="schema_name" class="form-control">
<select required name="schema_name" class="form-control"> <option disabled selected value="">Choisissez un schéma</option>
<option disabled selected value="">Choisissez un schéma</option> {% for item in section.catalog %}
{% for item in section.catalog %} <option
<option {% if item.err %}disabled{% endif %} {%
value="{{ section.name }}.{{ item.name }}">{{ item.title }}</option> if
{% endfor %} item.err
</select> %}disabled{%
</div> endif
<div class="form-group col-lg-3"> %}
<button type="submit" class="btn btn-primary">Valider un fichier</button> value="{{ section.name }}.{{ item.name }}"
>{{ item.title }}</option
>
{% endfor %}
</select>
</div>
<div class="form-group col-lg-3">
<button type="submit" class="btn btn-primary">
Valider un fichier
</button>
</div>
</div> </div>
</form>
</div>
{% elif section.err %}
<div class="my-5">
<h2>{{ section.title }}</h2>
{% if section.description %}
<p class="text-muted">{{ section.description | safe }}</p>
{% endif %}
<div class="alert alert-danger" role="alert">
Catalogue indisponible: {{ section.err | safe }}
</div> </div>
</form>
</div>
{% elif section.err %}
<div class="my-5">
<h2>{{ section.title }}</h2>
{% if section.description %}
<p class="text-muted">{{ section.description }}</p>
{% endif %}
<div class="alert alert-danger" role="alert">
Catalogue indisponible: {{ section.err }}
</div> </div>
</div> {% endif %} {% endfor %}
{% endif %}
{% endfor %}
<div class="my-5"> <div class="my-5">
<h2>Schéma à la carte</h2> <h2>Schéma à la carte</h2>
<p class="text-muted">Indiquez ici l'URL d'un schéma que vous souhaitez utiliser pour valider un fichier.</p> <p class="text-muted">
<form action="{{ url_for('custom_validator') }}" data-cy="custom_schema_form" method="GET"> Indiquez ici l'URL d'un schéma que vous souhaitez utiliser pour valider un
<div class="form-row"> fichier.
<div class="form-group col-lg-9"> </p>
<input <form
name="schema_url" action="{{ url_for('custom_validator') }}"
type="url" data-cy="custom_schema_form"
class="form-control" method="GET"
id="schema_url" >
aria-describedby="urlHelpBlock" <div class="form-row">
placeholder="https://example.com/schema.json" <div class="form-group col-lg-9">
required <input
/> name="schema_url"
<small id="urlHelpBlock" class="form-text text-muted"> type="url"
Le schéma doit être au format class="form-control"
<a href="https://frictionlessdata.io/docs/table-schema/" target="_blank">Table Schema</a>. id="schema_url"
</small> aria-describedby="urlHelpBlock"
</div> placeholder="https://example.com/schema.json"
<div class="form-group col-lg-3"> required
<button type="submit" class="btn btn-primary">Valider un fichier</button> />
<small id="urlHelpBlock" class="form-text text-muted">
Le schéma doit être au format
<a
href="https://frictionlessdata.io/docs/table-schema/"
target="_blank"
>Table Schema</a
>.
</small>
</div>
<div class="form-group col-lg-3">
<button type="submit" class="btn btn-primary">
Valider un fichier
</button>
</div>
</div> </div>
</div> </form>
</form> </div>
</div>
{% for section in sections %} {% for section in sections %} {% if section.links %}
{% if section.links %} <div class="my-5">
<div class="my-5"> <h2>{{ section.title }}</h2>
<h2>{{ section.title }}</h2> {% if section.description %}
{% if section.description %} <p class="text-muted">{{ section.description }}</p>
<p class="text-muted">{{ section.description }}</p> {% endif %}
{% endif %} <div class="row my-4">
<div class="row my-4"> {% for item in section.links %}
{% for item in section.links %} <div class="col-sm-4 mb-4">
<div class="col-sm-4 mb-4"> <div class="card h-100">
<div class="card h-100"> <div class="card-body d-flex flex-column">
<div class="card-body d-flex flex-column"> <h4 class="card-title">{{ item.title }}</h4>
<h4 class="card-title">{{ item.title }}</h4> <p class="card-text">{{ item.description }}</p>
<p class="card-text">{{ item.description }}</p> <a
<a href="{{ item.website }}"
href="{{ item.website }}" target="_blank" target="_blank"
class="btn btn-outline-secondary mt-auto" class="btn btn-outline-secondary mt-auto"
>Utiliser >Utiliser
<i class="fas fa-external-link-alt ml-1"></i> <i class="fas fa-external-link-alt ml-1"></i>
</a> </a>
</div>
</div> </div>
</div> </div>
{% endfor %}
</div> </div>
{% endfor %}
</div> </div>
</div> {% endif %} {% endfor %}
{% endif %} {% block page_scripts %}
{% endfor %} <style>
/* Error message display */
.btn-xs {
padding: .25rem .4rem;
font-size: .875rem;
line-height: .5;
border-radius: .2rem;
}
#exception_info {
padding-top: 1.3em;
padding-bottom: 0;
margin-bottom: 0;
}
</style>
{% endblock %}
</div> </div>
{% endblock %} {% endblock %}
...@@ -22,6 +22,7 @@ from backports.datetime_fromisoformat import MonkeyPatch ...@@ -22,6 +22,7 @@ from backports.datetime_fromisoformat import MonkeyPatch
from commonmark import commonmark from commonmark import commonmark
from flask import abort, make_response, redirect, render_template, request, url_for from flask import abort, make_response, redirect, render_template, request, url_for
from opendataschema import GitSchemaReference, by_commit_date from opendataschema import GitSchemaReference, by_commit_date
from validata_core import messages, repair from validata_core import messages, repair
from . import app, config, schema_catalog_registry, tableschema_from_url from . import app, config, schema_catalog_registry, tableschema_from_url
...@@ -591,6 +592,44 @@ def bytes_data(f): ...@@ -591,6 +592,44 @@ def bytes_data(f):
return iob.getvalue() return iob.getvalue()
def retrieve_schema_catalog(section):
"""Retrieve schema catalog and return formatted error if it fails."""
def format_error_message(err_message, exc):
"""Prepare a bootstrap error message with details if wanted."""
exception_text = '\n'.join([str(arg) for arg in exc.args])
return f"""{err_msg}
<div class="float-right">
<button type="button" class="btn btn-info btn-xs" data-toggle="collapse" data-target="#exception_info">détails</button>
</div>
<div id="exception_info" class="collapse">
<pre>{exception_text}</pre>
</div>
"""
try:
schema_catalog = get_schema_catalog(section['name'])
return (schema_catalog, None)
except Exception as exc:
log.exception(exc)
err_msg = "une erreur s'est produite"
if isinstance(exc, requests.ConnectionError):
err_msg = "problème de connexion"
elif isinstance(exc, json.decoder.JSONDecodeError):
err_msg = "format JSON incorrect"
elif isinstance(exc, jsonschema.exceptions.ValidationError):
err_msg = "le catalogue ne respecte pas le schéma de référence"
error_catalog = {
**{k: v for k,v in section.items() if k != 'catalog'},
"err": format_error_message(err_msg, exc)
}
return None, error_catalog
# Routes # Routes
...@@ -609,28 +648,18 @@ def home(): ...@@ -609,28 +648,18 @@ def home():
# section with only links to external validators # section with only links to external validators
if "links" in section: if "links" in section:
yield section yield section
continue
# section with catalog # section with catalog
if not "catalog" in section: if not "catalog" in section:
# skip section # skip section
continue continue
# error while getting schema catatalog # retrieving schema catatalog
try: schema_catalog, catalog_error = retrieve_schema_catalog(section)
schema_catalog = get_schema_catalog(section['name']) if schema_catalog is None:
except Exception as exc: yield catalog_error
log.exception(exc) continue
err_msg = "une erreur s'est produite"
if isinstance(exc, requests.ConnectionError):
err_msg = "problème de connexion"
elif isinstance(exc, json.decoder.JSONDecodeError):
err_msg = "format JSON incorrect"
elif isinstance(exc, jsonschema.exceptions.ValidationError):
err_msg = "le catalogue ne respecte pas le schéma de référence"
yield {
**{k: v for k,v in section.items() if k != 'catalog'},
"err": err_msg
}
# Working on catalog # Working on catalog
schema_info_list = [] schema_info_list = []
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment