#6: Automatic pan and zoom on loading data now works
Additionally, all client namespaces have been renamed to geocsv.client.xxx to avoid confusion with server side namespaces.
This commit is contained in:
		
							parent
							
								
									4516980981
								
							
						
					
					
						commit
						ce7b204a19
					
				
					 8 changed files with 66 additions and 28 deletions
				
			
		
							
								
								
									
										2
									
								
								env/dev/cljs/geocsv/app.cljs
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								env/dev/cljs/geocsv/app.cljs
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
(ns^:figwheel-no-load geocsv.app
 | 
			
		||||
  (:require
 | 
			
		||||
    [geocsv.core :as core]
 | 
			
		||||
    [geocsv.client.core :as core]
 | 
			
		||||
    [cljs.spec.alpha :as s]
 | 
			
		||||
    [expound.alpha :as expound]
 | 
			
		||||
    [devtools.core :as devtools]))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,7 +107,7 @@
 | 
			
		|||
                  :cljsbuild{:builds
 | 
			
		||||
                   {:app
 | 
			
		||||
                    {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
 | 
			
		||||
                     :figwheel {:on-jsload "geocsv.core/mount-components"}
 | 
			
		||||
                     :figwheel {:on-jsload "geocsv.client.core/mount-components"}
 | 
			
		||||
                     :compiler
 | 
			
		||||
                     {:output-dir "target/cljsbuild/public/js/out"
 | 
			
		||||
                      :closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
(ns geocsv.ajax
 | 
			
		||||
(ns geocsv.client.ajax
 | 
			
		||||
  (:require
 | 
			
		||||
    [ajax.core :as ajax]
 | 
			
		||||
    [luminus-transit.time :as time]
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,15 @@
 | 
			
		|||
(ns geocsv.core
 | 
			
		||||
(ns geocsv.client.core
 | 
			
		||||
  (:require
 | 
			
		||||
    [day8.re-frame.http-fx]
 | 
			
		||||
    [reagent.core :as r]
 | 
			
		||||
    [re-frame.core :as rf]
 | 
			
		||||
    [geocsv.gis :as gis]
 | 
			
		||||
    [geocsv.views.map :as mv]
 | 
			
		||||
    [geocsv.client.gis :as gis]
 | 
			
		||||
    [geocsv.client.views.map :as mv]
 | 
			
		||||
    [goog.events :as events]
 | 
			
		||||
    [goog.history.EventType :as HistoryEventType]
 | 
			
		||||
    [markdown.core :refer [md->html]]
 | 
			
		||||
    [geocsv.ajax :as ajax]
 | 
			
		||||
    [geocsv.events]
 | 
			
		||||
    [geocsv.client.ajax :as ajax]
 | 
			
		||||
    [geocsv.client.events]
 | 
			
		||||
    [reitit.core :as reitit]
 | 
			
		||||
    [reitit.frontend.easy :as rfe]
 | 
			
		||||
    [clojure.string :as s])
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
(ns ^{:doc "geocsv app initial database."
 | 
			
		||||
      :author "Simon Brooke"}
 | 
			
		||||
  geocsv.db)
 | 
			
		||||
  geocsv.client.db)
 | 
			
		||||
 | 
			
		||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
			
		||||
;;;;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,5 +37,7 @@
 | 
			
		|||
                           "Operator"
 | 
			
		||||
                           "Other-key-customers"
 | 
			
		||||
                           "Power-supplier"}  ;; need to be fetched from server side
 | 
			
		||||
   :latitude 56
 | 
			
		||||
   :longitude -4
 | 
			
		||||
   :map {:map-centre [56 -4]
 | 
			
		||||
         :map-zoom  6}})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
(ns geocsv.events
 | 
			
		||||
(ns geocsv.client.events
 | 
			
		||||
  (:require [ajax.core :as ajax]
 | 
			
		||||
            [ajax.json :refer [json-request-format json-response-format]]
 | 
			
		||||
            [cemerick.url :refer [url url-encode]]
 | 
			
		||||
            [geocsv.db :refer [default-db]]
 | 
			
		||||
            [geocsv.gis :refer [refresh-map-pins]]
 | 
			
		||||
            [geocsv.client.db :refer [default-db]]
 | 
			
		||||
            [geocsv.client.gis :refer [compute-centre refresh-map-pins]]
 | 
			
		||||
            [re-frame.core :as rf]
 | 
			
		||||
            [reitit.frontend.easy :as rfe]
 | 
			
		||||
            [reitit.frontend.controllers :as rfc]))
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,6 @@
 | 
			
		|||
    :query nil
 | 
			
		||||
    :anchor nil))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;dispatchers: keep in alphabetical order, please.
 | 
			
		||||
(rf/reg-event-fx
 | 
			
		||||
  :bad-data
 | 
			
		||||
| 
						 | 
				
			
			@ -138,12 +137,15 @@
 | 
			
		|||
  ;; TODO: why is this an `-fx`? Does it need to be?
 | 
			
		||||
  (fn
 | 
			
		||||
    [{db :db} [_ response]]
 | 
			
		||||
    (let [data (js->clj response)]
 | 
			
		||||
    (let [db' (assoc db :data (js->clj response))]
 | 
			
		||||
      (js/console.log (str "processing fetched JSON data"))
 | 
			
		||||
    {:db (if
 | 
			
		||||
           (:view db)
 | 
			
		||||
           (refresh-map-pins (assoc db :data data))
 | 
			
		||||
           db)})))
 | 
			
		||||
      {:db (if-let [data (:data db')]
 | 
			
		||||
             (let [centre (compute-centre data)]
 | 
			
		||||
               (if
 | 
			
		||||
                 (:view db')
 | 
			
		||||
                 (refresh-map-pins (merge db' centre))
 | 
			
		||||
                 db)
 | 
			
		||||
               db))})))
 | 
			
		||||
 | 
			
		||||
(rf/reg-event-fx
 | 
			
		||||
  :process-pin-image-names
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
(ns ^{:doc "geocsv app map stuff."
 | 
			
		||||
      :author "Simon Brooke"}
 | 
			
		||||
  geocsv.gis
 | 
			
		||||
  geocsv.client.gis
 | 
			
		||||
  (:require [ajax.core :refer [GET]]
 | 
			
		||||
            [ajax.json :refer [json-request-format json-response-format]]
 | 
			
		||||
            [cljs.reader :refer [read-string]]
 | 
			
		||||
| 
						 | 
				
			
			@ -158,17 +158,52 @@
 | 
			
		|||
                   (.removeLayer view %)))
 | 
			
		||||
    view))
 | 
			
		||||
 | 
			
		||||
(defn compute-zoom
 | 
			
		||||
  "See [explanation here](https://leafletjs.com/examples/zoom-levels/). Brief
 | 
			
		||||
  summary: it's hard, but it doesn't need to be precise."
 | 
			
		||||
  [min-lat max-lat min-lng max-lng]
 | 
			
		||||
  (let [n (min (/ 360 (- max-lng min-lng)) (/ 180 (- max-lat min-lat)))]
 | 
			
		||||
    (first
 | 
			
		||||
      (remove
 | 
			
		||||
        nil?
 | 
			
		||||
        (map
 | 
			
		||||
          #(if (> (reduce * (repeat 2 %)) n) %)
 | 
			
		||||
          (range))))))
 | 
			
		||||
 | 
			
		||||
(defn compute-centre
 | 
			
		||||
  "Compute, and return as a map with keys `:latitude` and `:longitude`, the
 | 
			
		||||
  centre of the locations of these records as indicated by the values of their
 | 
			
		||||
  `:latitude` and `:longitude` keys."
 | 
			
		||||
  [records]
 | 
			
		||||
  (let [lats (filter number? (map :latitude records))
 | 
			
		||||
        min-lat (apply min lats)
 | 
			
		||||
        max-lat (apply max lats)
 | 
			
		||||
        lngs (filter number? (map :longitude records))
 | 
			
		||||
        min-lng (apply min lngs)
 | 
			
		||||
        max-lng (apply max lngs)]
 | 
			
		||||
    (if-not
 | 
			
		||||
      (or (empty? lats) (empty? lngs))
 | 
			
		||||
      {:latitude (+ min-lat (/ (- max-lat min-lat) 2))
 | 
			
		||||
       :longitude (+ min-lng (/ (- max-lng min-lng) 2))
 | 
			
		||||
       :zoom (compute-zoom min-lat max-lat min-lng max-lng)}
 | 
			
		||||
      {})))
 | 
			
		||||
 | 
			
		||||
(defn refresh-map-pins
 | 
			
		||||
  "Refresh the map pins on the current map. Side-effecty; liable to be
 | 
			
		||||
    problematic."
 | 
			
		||||
  [db]
 | 
			
		||||
  (let [view (map-remove-pins @(subscribe [:view]))
 | 
			
		||||
        data (:data db)]
 | 
			
		||||
        data (:data db)
 | 
			
		||||
        centre (compute-centre data)]
 | 
			
		||||
    (if
 | 
			
		||||
      view
 | 
			
		||||
      (let [added (remove nil? (map #(add-map-pin db %1 %2 view) data (range)))]
 | 
			
		||||
        (js/console.log (str "Adding " (count added) " pins"))
 | 
			
		||||
        db)
 | 
			
		||||
        (if
 | 
			
		||||
          (:latitude centre)
 | 
			
		||||
          (do
 | 
			
		||||
            (js/console.log (str "computed centre: " centre))
 | 
			
		||||
            (.setView view (clj->js [(:latitude centre) (:longitude centre)]) (:zoom centre))
 | 
			
		||||
            (merge db centre))
 | 
			
		||||
          db))
 | 
			
		||||
      (do (js/console.log "View is not yet ready") db))))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
(ns ^{:doc "a map onto which to project CSV data."
 | 
			
		||||
      :author "Simon Brooke"}
 | 
			
		||||
  geocsv.views.map
 | 
			
		||||
  geocsv.client.views.map
 | 
			
		||||
  (:require [cljsjs.leaflet]
 | 
			
		||||
            [re-frame.core :refer [reg-sub subscribe dispatch dispatch-sync]]
 | 
			
		||||
            [reagent.core :as reagent]
 | 
			
		||||
            [recalcitrant.core :refer [error-boundary]]
 | 
			
		||||
            [geocsv.gis :refer [refresh-map-pins get-current-location]]))
 | 
			
		||||
            [geocsv.client.gis :refer [refresh-map-pins get-current-location]]))
 | 
			
		||||
 | 
			
		||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
			
		||||
;;;;
 | 
			
		||||
| 
						 | 
				
			
			@ -61,9 +61,8 @@
 | 
			
		|||
  (let [view (.setView
 | 
			
		||||
               (.map js/L
 | 
			
		||||
                     "map"
 | 
			
		||||
                     ;; (clj->js {:zoomControl false})
 | 
			
		||||
                     )
 | 
			
		||||
               #js [56 -4] ;;[@(subscribe [:latitude]) @(subscribe [:longitude])]
 | 
			
		||||
                     (clj->js {:zoomControl false}))
 | 
			
		||||
               #js [@(subscribe [:latitude]) @(subscribe [:longitude])]
 | 
			
		||||
               @(subscribe [:zoom]))]
 | 
			
		||||
    (.addTo (.tileLayer js/L osm-url
 | 
			
		||||
                        (clj->js {:attribution osm-attrib
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue