From e4e0d6a95d1b82c88858bf3e2d11d304ec71ff4e Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Tue, 28 Jan 2020 14:23:10 +0000 Subject: [PATCH] Some documentation; good enough for other folk to look at --- .gitignore | 2 + README.md | 55 +- resources/docs/docs.md | 107 ++- resources/html/home.html | 27 +- resources/public/css/geocsv.css | 48 ++ .../img/map-pins/Planning-authority-pin.svg | 10 +- .../lib/node_modules/leaflet/dist/leaflet.css | 636 ++++++++++++++++++ src/cljs/geocsv/db.cljs | 25 + src/cljs/geocsv/events.cljs | 27 + src/cljs/geocsv/gis.cljs | 22 +- src/cljs/geocsv/views/map.cljs | 2 +- 11 files changed, 876 insertions(+), 85 deletions(-) create mode 100644 resources/public/css/geocsv.css create mode 100644 resources/public/js/lib/node_modules/leaflet/dist/leaflet.css diff --git a/.gitignore b/.gitignore index 13b6ead..d939eb9 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ profiles.clj .idea/ *.iml + +resources/docs/orig.md diff --git a/README.md b/README.md index 884224c..af49f3d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,52 @@ # geocsv -generated using Luminus version "3.57" +GeoCSV is a wee tool to show comma-separated value data on a map. -FIXME +The CSV file must have + +* column names in the first row; +* data in all other rows; +* a column whose name is `name`, which always contains data; +* a column whose name is `latitude`, whose value is always a number between -90.0 and 90.0; +* a column whose name is `longitude`, whose value is always a number between -180.0 and 180.90 + +Additionally, the value of the column `category`, if present, will be used to select map pins from the map pins folder, if a suitable pin is present. Thus is the value of `category` is `foo`, a map pin image with the name `Foo-pin.png` will be selected. + +## Not yet working + +GeoCSV is at an early stage of development, and some features are not yet working. + +### Doesn't actually interpret CSV + +I haven't yet found an easy way to parse CSV into EDN client side, so I've written a [separate library](https://github.com/simon-brooke/csv2edn) to do it server side. However, that library is not yet integrated. Currently the client side actually interprets JSON. + +### Missing map pin images + +At the current stage of development, if no appropriate image exists in the `resources/public/img/map-pins` folder, that's your problem. **TODO:** I intend at some point to make missing pin images default to `unknown-pin.png`, which does exist. + +### Doesn't scale and centre the map to show the data in the sheet + +Currently the map is initially centred roughly on the centre of Scotland, and scaled arbitrarily. It should compute an appropriate centre and scale from the data provided, but currently doesn't. + +### There's no way of linking your own data feed + +Currently, the data is taken from the file `resources/public/data/data.json`. What I intend is that you should have a form which allows you to either + +1. enter [the `DOCID` of your own (publicly readable) Google Sheets spreadsheet](https://stackoverflow.com/questions/33713084/download-link-for-google-spreadsheets-csv-export-with-multiple-sheets); +2. enter the URL of a CSV file publicly available on the web; +3. upload a CSV file to the server. + +### There's no way of shareing the map of your own data with other people + +Currently, the data that is shared is just the data that's present when the app is compiled. Ideally, there should be a way of generating a URL, which might take the form: + + https://server.name/geocsv/docid/564747867 + +To show data from the first sheet of the Google Sheets spreadsheet whose `DOCID` is 564747867; or + + https://server.name/geocsv?uri=https://address.of.another.server/path/to/csv-file.csv + +to show the content of a publicly available CSV file. ## Prerequisites @@ -19,4 +63,9 @@ To start a web server for the application, run: ## License -Copyright © 2020 FIXME +Copyright © 2020 Simon Brooke + +Licensed under the GNU General Public License, version 2.0 or (at your option) any later version. + +**NOTE THAT** files which are directly created by the Luminus template do not currently have a GPL header +at the top; files which are new in this project or which have been substantially modified for this project should have a GPL header at the top. diff --git a/resources/docs/docs.md b/resources/docs/docs.md index c42c831..af49f3d 100644 --- a/resources/docs/docs.md +++ b/resources/docs/docs.md @@ -1,88 +1,71 @@ -

Congratulations, your Luminus site is ready!

+# geocsv -This page will help guide you through the first steps of building your site. +GeoCSV is a wee tool to show comma-separated value data on a map. -#### Why are you seeing this page? +The CSV file must have -The `home-routes` handler in the `geocsv.routes.home` namespace -defines the route that invokes the `home-page` function whenever an HTTP -request is made to the `/` URI using the `GET` method. +* column names in the first row; +* data in all other rows; +* a column whose name is `name`, which always contains data; +* a column whose name is `latitude`, whose value is always a number between -90.0 and 90.0; +* a column whose name is `longitude`, whose value is always a number between -180.0 and 180.90 -``` -(defn home-routes [] - ["" - {:middleware [middleware/wrap-csrf - middleware/wrap-formats]} - ["/" {:get home-page}] - ["/docs" {:get (fn [_] - (-> (response/ok (-> "docs/docs.md" io/resource slurp)) - (response/header "Content-Type" "text/plain; charset=utf-8")))}]]) -``` +Additionally, the value of the column `category`, if present, will be used to select map pins from the map pins folder, if a suitable pin is present. Thus is the value of `category` is `foo`, a map pin image with the name `Foo-pin.png` will be selected. -The `home-page` function will in turn call the `geocsv.layout/render` function -to render the HTML content: +## Not yet working -``` -(defn home-page [_] - (layout/render "home.html")) -``` +GeoCSV is at an early stage of development, and some features are not yet working. -The page contains a link to the compiled ClojureScript found in the `target/cljsbuild/public` folder: +### Doesn't actually interpret CSV -``` -{% script "/js/app.js" %} -``` +I haven't yet found an easy way to parse CSV into EDN client side, so I've written a [separate library](https://github.com/simon-brooke/csv2edn) to do it server side. However, that library is not yet integrated. Currently the client side actually interprets JSON. -The rest of this page is rendered by ClojureScript found in the `src/cljs/geocsv/core.cljs` file. +### Missing map pin images +At the current stage of development, if no appropriate image exists in the `resources/public/img/map-pins` folder, that's your problem. **TODO:** I intend at some point to make missing pin images default to `unknown-pin.png`, which does exist. +### Doesn't scale and centre the map to show the data in the sheet -#### Organizing the routes +Currently the map is initially centred roughly on the centre of Scotland, and scaled arbitrarily. It should compute an appropriate centre and scale from the data provided, but currently doesn't. -The routes are aggregated and wrapped with middleware in the `geocsv.handler` namespace: +### There's no way of linking your own data feed -``` -(mount/defstate app - :start - (middleware/wrap-base - (ring/ring-handler - (ring/router - [(home-routes)]) - (ring/routes - (ring/create-resource-handler - {:path "/"}) - (wrap-content-type - (wrap-webjars (constantly nil))) - (ring/create-default-handler - {:not-found - (constantly (error-page {:status 404, :title "404 - Page not found"})) - :method-not-allowed - (constantly (error-page {:status 405, :title "405 - Not allowed"})) - :not-acceptable - (constantly (error-page {:status 406, :title "406 - Not acceptable"}))}))))) -``` +Currently, the data is taken from the file `resources/public/data/data.json`. What I intend is that you should have a form which allows you to either -The `app` definition groups all the routes in the application into a single handler. -A default route group is added to handle the `404`, `405`, and `406` errors. +1. enter [the `DOCID` of your own (publicly readable) Google Sheets spreadsheet](https://stackoverflow.com/questions/33713084/download-link-for-google-spreadsheets-csv-export-with-multiple-sheets); +2. enter the URL of a CSV file publicly available on the web; +3. upload a CSV file to the server. -learn more about routing » +### There's no way of shareing the map of your own data with other people -#### Managing your middleware +Currently, the data that is shared is just the data that's present when the app is compiled. Ideally, there should be a way of generating a URL, which might take the form: -Request middleware functions are located under the `geocsv.middleware` namespace. + https://server.name/geocsv/docid/564747867 -This namespace is reserved for any custom middleware for the application. Some default middleware is -already defined here. The middleware is assembled in the `wrap-base` function. +To show data from the first sheet of the Google Sheets spreadsheet whose `DOCID` is 564747867; or -Middleware used for development is placed in the `geocsv.dev-middleware` namespace found in -the `env/dev/clj/` source path. + https://server.name/geocsv?uri=https://address.of.another.server/path/to/csv-file.csv -learn more about middleware » +to show the content of a publicly available CSV file. +## Prerequisites +You will need [Leiningen][1] 2.0 or above installed. +[1]: https://github.com/technomancy/leiningen -#### Need some help? +## Running -Visit the [official documentation](http://www.luminusweb.net/docs) for examples -on how to accomplish common tasks with Luminus. The `#luminus` channel on the [Clojurians Slack](http://clojurians.net/) and [Google Group](https://groups.google.com/forum/#!forum/luminusweb) are both great places to seek help and discuss projects with other users. +To start a web server for the application, run: + + lein npm install + lein run + +## License + +Copyright © 2020 Simon Brooke + +Licensed under the GNU General Public License, version 2.0 or (at your option) any later version. + +**NOTE THAT** files which are directly created by the Luminus template do not currently have a GPL header +at the top; files which are new in this project or which have been substantially modified for this project should have a GPL header at the top. diff --git a/resources/html/home.html b/resources/html/home.html index 95b7037..770c5cc 100644 --- a/resources/html/home.html +++ b/resources/html/home.html @@ -28,20 +28,35 @@ + {% block foot %} + + + {% endblock %} + {% style "/assets/bulma/css/bulma.min.css" %} {% style "/assets/material-icons/css/material-icons.min.css" %} {% style "/css/screen.css" %} + {% style "/css/geocsv.css" %} - - - - - - {% script "js/lib/node_modules/leaflet/dist/leaflet.js" %} + + + + + {% style "js/lib/node_modules/leaflet/dist/leaflet.css" %} + {% script "/js/lib/node_modules/leaflet/dist/leaflet.js" %} {% script "/js/app.js" %} diff --git a/resources/public/css/geocsv.css b/resources/public/css/geocsv.css new file mode 100644 index 0000000..aa81477 --- /dev/null +++ b/resources/public/css/geocsv.css @@ -0,0 +1,48 @@ +/** + * Static CSS for basic geocsv pages to establish look-and-feel. Something + * more dynamic, designed by someone more skilled than me, will replace it + * later. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * # The Stylesheet + * + * ## html elements generally in alphabetic order + */ + +footer { + border-top: thin solid gray; + clear: both; + font-size: 66%; + text-align: center; + color: silver; + background-color: #3298dc; + width: 100%; + margin: 0; + padding: 0.25em 0; + bottom: 0; + position: fixed; + z-index:150; +} + +footer a { + color: white; + background-color: #3298dc; +} + +footer div { + padding: 0.1em; +} diff --git a/resources/public/img/map-pins/Planning-authority-pin.svg b/resources/public/img/map-pins/Planning-authority-pin.svg index ca9926d..1bbde07 100644 --- a/resources/public/img/map-pins/Planning-authority-pin.svg +++ b/resources/public/img/map-pins/Planning-authority-pin.svg @@ -116,7 +116,10 @@ d="m 430,192.36218 150,0 c 20,1e-5 40,20.00001 40,40 l 0,150 c 0,20.00001 -20,40.00001 -40,40 l -40,0 c -20,0 -20,46.66667 -30,70 -13.33333,-23.33333 -20,-70 -40,-70 l -40,0 c -20,10e-6 -40,-19.99999 -40,-40 l 0,-150 c 0,-19.99999 20,-39.99999 40,-40 z" id="path2387" sodipodi:nodetypes="cccccccccccc" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + inkscape:export-filename="/home/simon/workspace/youyesyet/resources/public/img/map-pins/Planning-authority-pin.png" + inkscape:export-xdpi="11.98" + inkscape:export-ydpi="11.98" /> @@ -164,7 +167,10 @@ id="g1014" /> + id="g984" + inkscape:export-filename="/home/simon/workspace/youyesyet/resources/public/img/map-pins/Planning-authority-pin.png" + inkscape:export-xdpi="11.98" + inkscape:export-ydpi="11.98"> svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer { + max-width: none !important; + max-height: none !important; + } + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; + } +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: url(images/marker-icon.png); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + } diff --git a/src/cljs/geocsv/db.cljs b/src/cljs/geocsv/db.cljs index b350c88..fa530d9 100644 --- a/src/cljs/geocsv/db.cljs +++ b/src/cljs/geocsv/db.cljs @@ -2,7 +2,32 @@ :author "Simon Brooke"} geocsv.db) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; geocsv.db: database initialisation, prior to fetching anything from +;;;; server side. +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU General Public License +;;;; as published by the Free Software Foundation; either version 2 +;;;; of the License, or (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with this program; if not, write to the Free Software +;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;;;; USA. +;;;; +;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (def default-db {:page :home + :available-pin-images #{"Planning authority" "unknown"} ;; need to be fetched from server side :map {:map-centre [56 -4] :map-zoom 6}}) diff --git a/src/cljs/geocsv/events.cljs b/src/cljs/geocsv/events.cljs index cab559a..f620f71 100644 --- a/src/cljs/geocsv/events.cljs +++ b/src/cljs/geocsv/events.cljs @@ -8,6 +8,29 @@ [reitit.frontend.easy :as rfe] [reitit.frontend.controllers :as rfc])) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; geocsv.events: events and subscriptions; things which change the state. +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU General Public License +;;;; as published by the Free Software Foundation; either version 2 +;;;; of the License, or (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with this program; if not, write to the Free Software +;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;;;; USA. +;;;; +;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (def source-host "The base URL of the host from which the app was loaded." @@ -115,6 +138,10 @@ (assoc db :view view))) ;;subscriptions. Keep in alphabetical order, please +(rf/reg-sub + :available-pin-images + (fn [db _] + (:available-pin-images db))) (rf/reg-sub :common/error diff --git a/src/cljs/geocsv/gis.cljs b/src/cljs/geocsv/gis.cljs index 9d19b4e..4e23769 100644 --- a/src/cljs/geocsv/gis.cljs +++ b/src/cljs/geocsv/gis.cljs @@ -72,12 +72,14 @@ (defn pin-image "Return the name of a suitable pin image for this `record`." [record] - (if - (:category record) - (str - (s/capitalize - (s/replace (s/lower-case (str (:category record))) #"[^a-z0-9]" "-")) "-pin") - "unknown-pin")) + (let [available @(subscribe [:available-pin-images])] + (js/console.log (str "pin-image: available is of type `" (type available) "`; `(fn? available)` returns " (set? available))) + (if + (contains? available (:category record)) + (str + (s/capitalize + (s/replace (s/lower-case (str (:category record))) #"[^a-z0-9]" "-")) "-pin") + "unknown-pin"))) (defn popup-content "Appropriate content for the popup of a map pin for this `record`." @@ -102,7 +104,9 @@ "" (apply str - (map #(str "") (keys record))) + (map + #(str "") + (sort (keys record)))) "
" (name %) "" (record %) "
" (name %) "" (record %) "
")) (defn add-map-pin @@ -132,10 +136,6 @@ :title (:name record)}))] (.bindPopup marker (popup-table-content record)) (.addTo marker view) -;; (.on -;; (.addTo marker view) -;; "click" -;; (fn [_] (map-pin-click-handler index))) (js/console.log (str "Added `"(:name record)"` in at " lat ", " lng)) marker)))) diff --git a/src/cljs/geocsv/views/map.cljs b/src/cljs/geocsv/views/map.cljs index 282083b..181d37d 100644 --- a/src/cljs/geocsv/views/map.cljs +++ b/src/cljs/geocsv/views/map.cljs @@ -91,7 +91,7 @@ (defn map-render "Render the actual div containing the map." [] - [:div#map {:style {:height "500px" :width "800px"}}]) + [:div#map {:style {:height "500px"}}]) (defn panel "A reagent class for the map object."