Browse Source

Create public and private geojson files.

opi 10 years ago
parent
commit
a7d8cfcd71
5 changed files with 249 additions and 1 deletions
  1. 5 0
      README.md
  2. 22 0
      assets/main.css
  3. 58 0
      assets/map.js
  4. 107 1
      backend.py
  5. 57 0
      views/map.tpl

+ 5 - 0
README.md

@@ -31,6 +31,11 @@ Create the DataBase
 
     $ python backend.py createdb
 
+Build GeoJSON files
+===================
+
+    $ python backend.py buildgeojson
+
 Drop the database
 =================
 

+ 22 - 0
assets/main.css

@@ -1,4 +1,9 @@
 
+.back-link {
+    display: inline-block;
+    margin-bottom: 30px;
+}
+
 #map {
     min-height: 300px;
 }
@@ -24,4 +29,21 @@ body > footer {
 #errors ul {
     margin: 0 0 0 1em;
     padding: 0;
+}
+
+/** Results **/
+#map.results {
+    min-height: 500px;
+    margin-bottom: 1em;
+}
+
+.results .leaflet-popup-content {
+    margin: 1em;
+}
+.results .leaflet-popup-content h2 {
+    font-size: 20px;
+}
+.results .leaflet-popup-content ul {
+    margin: 0.5em 0;
+    padding-left: 1.5em;
 }

+ 58 - 0
assets/map.js

@@ -0,0 +1,58 @@
+$( document ).ready(function() {
+
+    // Defaults
+    defaults = {
+        lat: 47.218371,
+        lng: -1.553621,
+        zoom: 13,
+    }
+
+    // Create map
+    var map = L.map('map', {scrollWheelZoom: false}).setView([defaults.lat,defaults.lng], defaults.zoom);
+    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
+        maxZoom: 18
+    }).addTo(map);
+
+    // Get JSON
+    var GeoJsonPath = $('#map').data('json')
+    $.getJSON(GeoJsonPath, function(data){
+
+        function buildPopupContent(feature, layer) {
+            feature.properties.popupContent = '';
+
+            if (feature.properties.name) {
+                feature.properties.popupContent += '<h2>#'+feature.id+': '+feature.properties.name+'</h2>';
+            }
+            else {
+                feature.properties.popupContent += '<h2>#'+feature.id+'</h2>';
+            }
+
+            if (feature.properties.place) {
+                feature.properties.popupContent += '<ul>';
+                if (feature.properties.place.floor) feature.properties.popupContent += '<li>Étage: '+feature.properties.place.floor+'</li>';
+                if (feature.properties.place.orientations[0]) feature.properties.popupContent += '<li>Orientation: '+feature.properties.place.orientations.join(', ')+'</li>';
+                feature.properties.popupContent += '</ul>'
+            }
+
+            if (feature.properties.comment) {
+                feature.properties.popupContent += '<p>'+feature.properties.comment+'</p>';
+            }
+
+            layer.bindPopup(feature.properties.popupContent);
+        }
+
+        // Add to map
+        var featureLayer = L.geoJson(data, {
+            onEachFeature: buildPopupContent
+        }).addTo(map);
+
+        // Auto Zoom
+        // Strange leaflet bug, we need to set a null timeout
+        setTimeout(function () {
+            map.fitBounds(featureLayer.getBounds())
+        }, 2);
+
+    });
+
+});

+ 107 - 1
backend.py

@@ -5,10 +5,12 @@ import sys
 import sqlite3
 import urlparse
 import datetime
+import json
 from email import utils
 from os.path import join, dirname
 
-from bottle import route, run, static_file, request, template, FormsDict, redirect
+
+from bottle import route, run, static_file, request, template, FormsDict, redirect, response
 
 ORIENTATIONS = (
     ('N', 'Nord'),
@@ -148,12 +150,116 @@ def wifi_form_thanks():
 def send_asset(filename):
     return static_file(filename, root=join(dirname(__file__), 'assets'))
 
+
+
+"""
+Results Map
+"""
+
+@route('/map')
+def public_map():
+    geojsonPath = '/public.json'
+    return template('map', geojson=geojsonPath)
+
+@route('/public.json')
+def public_geojson():
+    return static_file('public.json', root=join(dirname(__file__), 'json/'))
+
+
+
+"""
+GeoJSON Functions
+"""
+
+# Save feature collection to a json file
+def save_featurecollection_json(id, features):
+    with open('json/' + id + '.json', 'w') as outfile:
+        json.dump({
+            "type" : "FeatureCollection",
+            "features" : features,
+            "id" : id,
+        }, outfile)
+
+# Build GeoJSON files from DB
+def build_geojson():
+
+    # Read from DB
+    DB.row_factory = sqlite3.Row
+    cur = DB.execute("""
+        SELECT * FROM {} ORDER BY id DESC
+        """.format(TABLE_NAME))
+
+    public_features = []
+    private_features = []
+
+    # Loop through results
+    rows = cur.fetchall()
+    for row in rows:
+
+        # Private JSON file
+        private_features.append({
+            "type" : "Feature",
+            "geometry" : {
+                "type": "Point",
+                 "coordinates": [row['longitude'], row['latitude']],
+            },
+             "id" : row['id'],
+             "properties": {
+                "name" : row['name'],
+                "place" : {
+                    'floor' : row['floor'],
+                    'orientations' : row['orientations'].split(','),
+                },
+                "comment" : row['comment']
+             }
+        })
+
+        # Bypass non-public points
+        if not row['privacy_coordinates']:
+            continue
+
+        # Public JSON file
+        public_feature = {
+            "type" : "Feature",
+            "geometry" : {
+                "type": "Point",
+                 "coordinates": [row['longitude'], row['latitude']],
+            },
+             "id" : row['id'],
+             "properties": {}
+        }
+
+        # Add optionnal variables
+        if not row['privacy_name']:
+            public_feature['properties']['name'] = row['name']
+
+        if not row['privacy_comment']:
+            public_feature['properties']['comment'] = row['comment']
+
+        if not row['privacy_place_details']:
+            public_feature['properties']['place'] = {
+                'floor' : row['floor'],
+                'orientations' : row['orientations'].split(','),
+                # 'roof' : row['roof'],
+            }
+
+        # Add to public features list
+        public_features.append(public_feature)
+
+    # Build GeoJSON Feature Collection
+    save_featurecollection_json('private', private_features)
+    save_featurecollection_json('public', public_features)
+
+
+
 DEBUG = bool(os.environ.get('DEBUG', False))
 
 if __name__ == '__main__':
     if len(sys.argv) > 1:
         if sys.argv[1] == 'createdb':
             create_tabble(DB, TABLE_NAME, DB_COLS)
+        if sys.argv[1] == 'buildgeojson':
+            build_geojson()
     else:
         run(host='localhost', port=8080, reloader=DEBUG)
         DB.close()

+ 57 - 0
views/map.tpl

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>FAIMaison − contribution à l'expérimentation wifi</title>
+
+    <!-- jQuery -->
+    <script src="assets/jquery/jquery-1.11.0.min.js" type="text/javascript"></script>
+
+    <!-- Bootstrap -->
+    <script src="assets/bootstrap/js/bootstrap.js"></script>
+    <link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+
+    <!-- Leaflet -->
+    <link rel="stylesheet" type="text/css" media="all" href="assets/leaflet/leaflet.css" />
+    <script src="assets/leaflet/leaflet.js" type="text/javascript"></script>
+
+    <!-- Custom -->
+    <link rel="stylesheet" type="text/css" media="all" href="assets/main.css" />
+    <!-- script src="assets/main.js" type="text/javascript"></script -->
+
+  </head>
+<body>
+  <header class="jumbotron">
+    <div class="container">
+    <h1>Réseau wifi expérimental</h1>
+  </header>
+
+  <section role="main" class="container">
+    <span class="back-link">&larr; <a href="/">Accueil</a></span>
+
+    <div id="map" class="results" data-json="{{geojson}}"></div>
+    <script src="assets/map.js" type="text/javascript"></script>
+    <p>
+      Télécharger le fichier <a href="{{geojson}}">GeoJSON</a>.
+    </p>
+  </section>
+
+  <footer>
+    <p>Vos données personnelles sont en lieu sûr.</p>
+  </footer>
+
+  <div id="modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Resultats" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+      <div class="modal-content">
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Fermer</span></button>
+          <h4 class="modal-title" id="myModalLabel">Résultats</h4>
+        </div>
+        <div class="modal-body">
+        </div>
+      </div>
+    </div>
+  </div>
+
+</body>
+</html>