From ce7b204a19eed9d683e81088886f571d232fe525 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Wed, 29 Jan 2020 19:05:34 +0000 Subject: [PATCH] #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. --- env/dev/cljs/geocsv/app.cljs | 2 +- project.clj | 2 +- src/cljs/geocsv/{ => client}/ajax.cljs | 2 +- src/cljs/geocsv/{ => client}/core.cljs | 10 ++--- src/cljs/geocsv/{ => client}/db.cljs | 4 +- src/cljs/geocsv/{ => client}/events.cljs | 22 ++++++----- src/cljs/geocsv/{ => client}/gis.cljs | 43 +++++++++++++++++++-- src/cljs/geocsv/{ => client}/views/map.cljs | 9 ++--- 8 files changed, 66 insertions(+), 28 deletions(-) rename src/cljs/geocsv/{ => client}/ajax.cljs (97%) rename src/cljs/geocsv/{ => client}/core.cljs (95%) rename src/cljs/geocsv/{ => client}/db.cljs (96%) rename src/cljs/geocsv/{ => client}/events.cljs (92%) rename src/cljs/geocsv/{ => client}/gis.cljs (80%) rename src/cljs/geocsv/{ => client}/views/map.cljs (93%) diff --git a/env/dev/cljs/geocsv/app.cljs b/env/dev/cljs/geocsv/app.cljs index 4283167..9e65331 100644 --- a/env/dev/cljs/geocsv/app.cljs +++ b/env/dev/cljs/geocsv/app.cljs @@ -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])) diff --git a/project.clj b/project.clj index b4d1cc9..824d41a 100644 --- a/project.clj +++ b/project.clj @@ -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} diff --git a/src/cljs/geocsv/ajax.cljs b/src/cljs/geocsv/client/ajax.cljs similarity index 97% rename from src/cljs/geocsv/ajax.cljs rename to src/cljs/geocsv/client/ajax.cljs index 4605fd6..2d55989 100644 --- a/src/cljs/geocsv/ajax.cljs +++ b/src/cljs/geocsv/client/ajax.cljs @@ -1,4 +1,4 @@ -(ns geocsv.ajax +(ns geocsv.client.ajax (:require [ajax.core :as ajax] [luminus-transit.time :as time] diff --git a/src/cljs/geocsv/core.cljs b/src/cljs/geocsv/client/core.cljs similarity index 95% rename from src/cljs/geocsv/core.cljs rename to src/cljs/geocsv/client/core.cljs index 92bf1c7..b67025d 100644 --- a/src/cljs/geocsv/core.cljs +++ b/src/cljs/geocsv/client/core.cljs @@ -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]) diff --git a/src/cljs/geocsv/db.cljs b/src/cljs/geocsv/client/db.cljs similarity index 96% rename from src/cljs/geocsv/db.cljs rename to src/cljs/geocsv/client/db.cljs index 0f2cb73..cba96d4 100644 --- a/src/cljs/geocsv/db.cljs +++ b/src/cljs/geocsv/client/db.cljs @@ -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}}) diff --git a/src/cljs/geocsv/events.cljs b/src/cljs/geocsv/client/events.cljs similarity index 92% rename from src/cljs/geocsv/events.cljs rename to src/cljs/geocsv/client/events.cljs index 9b0e1aa..342db20 100644 --- a/src/cljs/geocsv/events.cljs +++ b/src/cljs/geocsv/client/events.cljs @@ -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)] - (js/console.log (str "processing fetched JSON data")) - {:db (if - (:view db) - (refresh-map-pins (assoc db :data data)) - db)}))) + (let [db' (assoc db :data (js->clj response))] + (js/console.log (str "processing fetched JSON data")) + {: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 diff --git a/src/cljs/geocsv/gis.cljs b/src/cljs/geocsv/client/gis.cljs similarity index 80% rename from src/cljs/geocsv/gis.cljs rename to src/cljs/geocsv/client/gis.cljs index 59d8323..298fbfa 100644 --- a/src/cljs/geocsv/gis.cljs +++ b/src/cljs/geocsv/client/gis.cljs @@ -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)))) - diff --git a/src/cljs/geocsv/views/map.cljs b/src/cljs/geocsv/client/views/map.cljs similarity index 93% rename from src/cljs/geocsv/views/map.cljs rename to src/cljs/geocsv/client/views/map.cljs index e4f4329..bb01c2d 100644 --- a/src/cljs/geocsv/views/map.cljs +++ b/src/cljs/geocsv/client/views/map.cljs @@ -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