olivier.massot 7 anni fa
parent
commit
a560c7de51

+ 0 - 0
resources/netgeo_v2-2_doe.yaml → checkers/netgeo_v2-2_doe.yaml


+ 28 - 40
datachecker.py

@@ -6,11 +6,10 @@ Python 3.7+
 from datetime import datetime
 import json
 import logging
-import subprocess  #@UnusedImport
-import tempfile  #@UnusedImport
+import subprocess  # @UnusedImport
+import tempfile  # @UnusedImport
 import zipfile
 
-from jinja2.environment import Template
 from path import Path, TempDir
 import pypyodbc
 import shapefile
@@ -146,6 +145,8 @@ def check_folder(folder, checker):
     
     report = Report("Contrôle des données de {} au format {}".format(folder.name, checker.stem))
     
+    db_cache = {}
+    
     with open(checker, "r") as cf:
         config = yaml.load(cf)
     
@@ -159,7 +160,6 @@ def check_folder(folder, checker):
         logger.info("* Traitement de %s", path_.name)
         
         report_file = ReportFile(path_.name)
-        report.report_files.append(report_file)
         
         if not path_.isfile():
             report_file.add_error("Fichier introuvable")
@@ -274,47 +274,35 @@ def check_folder(folder, checker):
                 except KeyError:
                     pass
         
-#                 if "in_table" in fieldmodel:
-#                     
-#                     db = databases[fieldmodel["in_table"]["db"]]
-#                     cursor = db.cursor()
-#                     cursor.execute("SELECT DISTINCT {} FROM {};".format(fieldmodel["in_table"]["field"], fieldmodel["in_table"]["table"]))
-#                     rows = [val[0] for val in cursor.fetchall()]
-#                     
-#                     if not val in rows:
-#                         report_field.error = "Valeur invalide, pas dans la liste"
-#                         report_record.add_field(report_field)
-#                         continue
+                if "in_table" in fieldmodel:
+
+                    key = tuple([fieldmodel["in_table"]["db"], fieldmodel["in_table"]["table"], fieldmodel["in_table"]["field"]])
+                    if not key in db_cache:
+                        db = databases[fieldmodel["in_table"]["db"]]
+                        cursor = db.cursor()
+                        cursor.execute("SELECT DISTINCT {} FROM {};".format(fieldmodel["in_table"]["field"], fieldmodel["in_table"]["table"]))
+                        rows = [val[0] for val in cursor.fetchall()]
+                        db_cache[key] = rows
+                     
+                    if not val in db_cache[key]:
+                        report_field.error = "Valeur invalide, pas dans la liste"
+                        report_record.add_field(report_field)
+                        continue
                 
                 report_record.add_field(report_field)
             report_file.add_record(report_record)
-            
+        report.report_files.append(report_file)
         del sf, records
         
     return report
         
 
-def render_to_html(report):
-    with open(MAIN / "templates" / "report.j2", "r") as f:
-        template = Template(f.read())
-
-    return template.render(report=report)
-
-
-# if __name__ == "__main__":
-#     
-#     subject = MAIN / "work" / "SCOPELEC_CAP_097AP0_REC_180829_OK.zip"
-#     checker = MAIN / "resources" / "netgeo_v2-2_doe.yaml"
-#     
-#     report = check(subject, checker)
-#     
-#     result = render_to_html(report)
-#     
-#     result_filename = tempfile.mktemp(".html", dir=MAIN / "website")
-#     
-#     with open(result_filename, "w+") as f:
-#         f.write(result)
-#     
-#     subprocess.run("start {}".format(result_filename), shell=True)
-#     
-#     logger.info("-- Fin --")
+if __name__ == "__main__":
+    
+    logger.disabled = False
+    subject = MAIN / "work" / "SCOPELEC_CAP_097AP0_REC_180829_OK.zip"
+    checker = MAIN / "checkers" / "netgeo_v2-2_doe.yaml"
+     
+    report = check(subject, checker)
+     
+    logger.info("-- Fin --")

+ 18 - 8
index.py

@@ -2,7 +2,7 @@
 
 @author: olivier.massot, sept 218
 '''
-import tempfile
+from tempfile import TemporaryDirectory
 
 from flask import request
 from flask.app import Flask
@@ -12,23 +12,33 @@ from werkzeug.utils import secure_filename
 
 from core.constants import MAIN
 import datachecker
-from tempfile import TemporaryDirectory
 
 
 app = Flask(__name__)
 
 @app.route('/', methods=['GET'])
 def index():
-    return render_template("index.html")
+    return render_template("index.html", validation_error="")
 
 @app.route('/', methods=['POST'])
 def submit():
-    f = request.files['dossier']
+    try:
+        f = request.files['dossier']
+    except KeyError:
+        return render_template("index.html", validation_error="Aucun fichier sélectionné")
+    
+    filename = secure_filename(f.filename)
     
-    with TemporaryDirectory(dir=MAIN / "upload") as d:
-        filename = Path(d) / secure_filename(f.filename)
-        f.save(filename)
-        report = datachecker.check(filename, MAIN / "resources" / "netgeo_v2-2_doe.yaml")
+    if Path(filename).ext != ".zip":
+        return render_template("index.html", validation_error="Le fichier doit être un fichier .ZIP ({})".format(Path(filename).ext))
     
+    try:
+        with TemporaryDirectory(dir=MAIN / "upload") as d:
+            filename = Path(d) / filename
+            f.save(filename)
+            report = datachecker.check(filename, MAIN / "checkers" / "netgeo_v2-2_doe.yaml")
+    except Exception as e:
+        return render_template("index.html", validation_error=str(e))
+      
     return render_template("report.html", report=report)
         

BIN
static/ajax-loader.gif


+ 34 - 11
static/datachecker.css

@@ -11,10 +11,25 @@ header {
 	margin: 0;
 	padding: 10px;
 	width: 100%;
-	height: 50px;
+	height: 55px;
 	top: 0;
-	border-bottom: 1px solid #000066;
-	background-color: #e6e6ff;
+	border-bottom: 1px solid #001a33;
+	background-color: #004280;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+
+#logo {
+	float: right;
+	position: fixed;
+	top: 3px;
+	left: 20px;
+}
+
+h1 {
+	color: white;
+	margin: 10px 0;
 }
 
 #main {
@@ -22,12 +37,6 @@ header {
 	margin: 50px 10%;
 }
 
-h1 {
-	color: #0047b3;
-	width: 100%;
-	text-align: center;
-	margin: 0;
-}
 
 h2 {
 	color: #666666;
@@ -46,6 +55,7 @@ h2 {
 	align-items: center;
 	border: 2px solid #0047b3;
 	border-radius: 5px;
+	box-shadow: 3px 5px 5px rgb(166, 166, 166, 0.5);
 	padding: 30px;
 }
 
@@ -76,7 +86,20 @@ h2 {
 	width: 100% !important;
 }
 
+.annotation {
+	color: #595959;
+	font-size: 0.9em;
+}
+
+.please-wait {
+	margin-top: 30px;
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+}
+
 footer {
+	color: #004280;
 	width: 100%;
 	text-align: center;
 	position: fixed;
@@ -85,6 +108,6 @@ footer {
     left: 0;
     right: 0;
     margin: 0;
-    background-color: #f2f2f2;
+    background-color: #e6e6e6;
     padding-top: 23px;
-}
+}

+ 15 - 1
static/datachecker.js

@@ -1,5 +1,19 @@
+
 $(document).ready( function () {
     $('.datatable').DataTable( {
         "scrollX": true
     } );
-} );
+    
+    $('#submit-form').submit(function(e) {
+    	 e.preventDefault();
+    	 
+    	 $("body").addClass("loading");
+    	 
+    	 $('.error').html("");
+    	 
+    	 $("#submit-form > .please-wait").show();
+    	 
+    	 $(this).unbind("submit");
+    	 $(this).submit();
+	});
+} );

+ 16 - 2
templates/index.html

@@ -4,10 +4,12 @@
 	    <title>Manche Numérique - Contrôlez vos données</title>
 	    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='font-awesome-4.7.0/css/font-awesome.min.css') }}">
 		<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='jquery-ui/jquery-ui.min.css') }}"/>
+		<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='DataTables/datatables.min.css') }}"/>
 		<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='datachecker.css') }}"/>
 		 
 		<script type="text/javascript" src="{{ url_for('static', filename='jquery-3.3.1.min.js') }}"></script>
 		<script type="text/javascript" src="{{ url_for('static', filename='jquery-ui/jquery-ui.min.js') }}"></script>
+		<script type="text/javascript" src="{{ url_for('static', filename='DataTables/datatables.min.js') }}"></script>
 		<script type="text/javascript" src="{{ url_for('static', filename='datachecker.js') }}"> </script>
 	</head>
 	
@@ -16,16 +18,28 @@
 			<h1>Manche Numérique - Contrôlez vos données</h1>
 		</header>
 		
+		<a id="logo" href="\" title="Retour à l'accueil">
+			<img src="{{ url_for('static', filename='mn_logo_mini.png') }}" />
+		</a>
+		
 		<section id="main">
 			<section id="submit-file">
 				<form id="submit-form" method="post" enctype="multipart/form-data">
 			        <label for="dossier">Sélectionnez le fichier à contrôler (Au format <b>.zip</b>)</label>
 			        <input type="file" id="dossier" name="dossier" accept="application/zip" />
-				    <button class="ui-button ui-corner-all ui-widget">Soumettre</button>
+
+				    <button type="submit" class="ui-button ui-corner-all ui-widget">Soumettre</button>
+					
+					<div class="please-wait" style="display:none;">
+					  <img src="{{ url_for('static', filename='ajax-loader.gif') }}" /> <i>Veuillez patienter, le traitement peut durer plusieurs minutes...</i>
+					</div>
+			        {%- if validation_error -%}
+			        <p class="error">{{ validation_error }}</p>
+			        {% endif %}
 				</form>
 			</section>
 		</section>
-
+		
 	    <footer>
 	    	Manche Numérique, 2018 - <a href="">Contact</a>
     	</footer>

+ 7 - 4
templates/report.html

@@ -14,13 +14,17 @@
 </head>
 <body>
 	<header>
-		<h1>{{ report.title }}</h1>
+		<h1>Rapport du Contrôle</h1>
 	</header>
 	
+	<a id="logo" href="\" title="Retour à l'accueil">
+		<img src="{{ url_for('static', filename='mn_logo_mini.png') }}" />
+	</a>
+	
 	<section id=main>
     {% for reportfile in report.report_files %}
     
-        <h2>{{ reportfile.file }}</h2>
+        <h2><i class="fa fa-file"></i> {{ reportfile.file }}</h2>
         
         {%- if reportfile.errors -%}
         	<ul>
@@ -33,7 +37,7 @@
         <table class="datatable cell-border display compact stripe">
         	<thead>
 	       		<tr>
-		       		<th>N</th>
+		       		<th>N°</th>
 		       		<th>Valide</th>
 		       		{% for header in reportfile.headers %}
 		       			<th>{{ header }}</th>
@@ -51,7 +55,6 @@
 	       					<i class="fa fa-times error"></i>
 	       				{% endif %}
 	       			</td>
-       			
 	       			{% for field in record.fields %}
 	       				{%- if field.valid -%}
 							<td>{{ field.value }}</td>