Some documentation; good enough for other folk to look at

This commit is contained in:
Simon Brooke 2020-01-28 14:23:10 +00:00
parent 2291670056
commit e4e0d6a95d
11 changed files with 876 additions and 85 deletions

2
.gitignore vendored
View file

@ -18,3 +18,5 @@ profiles.clj
.idea/
*.iml
resources/docs/orig.md

View file

@ -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.

View file

@ -1,88 +1,71 @@
<h2 class="alert alert-success">Congratulations, your <a class="alert-link" href="http://luminusweb.net">Luminus</a> site is ready!</h2>
# 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.
<a class="btn btn-primary" href="https://metosin.github.io/reitit/basics">learn more about routing »</a>
### 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
<a class="btn btn-primary" href="http://www.luminusweb.net/docs/middleware.md">learn more about middleware »</a>
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.

View file

@ -28,10 +28,25 @@
</section>
</div>
{% block foot %}
<!-- foot: override this block if you don't want the standard footer -->
<footer>
<div id="credits">
<div>
<img height="16" width="16" alt="Luminus" src="{{servlet-context}}/img/credits/luminus-logo.png"/>Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> ||
<img height="16" width="16" alt="Clojure" src="{{servlet-context}}/img/credits/clojure-icon.gif"/> Powered by <a href="http://clojure.org">Clojure</a> ||
<img height="16" width="16" alt="GitHub" src="{{servlet-context}}/img/credits/github-logo-transparent.png"/>Find me/fork me on <a href="https://github.com/simon-brooke/geocsv">Github</a> ||
<img height="16" width="16" alt="Free Software Foundation" src="{{servlet-context}}/img/credits/gnu.small.png"/>Licensed under the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License version 2.0</a>
</div>
</div>
</footer>
{% endblock %}
<!-- scripts and styles -->
{% 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 type="text/javascript">
var csrfToken = "{{csrf-token}}";
@ -40,8 +55,8 @@
<!-- ATTENTION \/ -->
<!-- ATTENTION /\ -->
<!-- Leaflet -->
<link rel="stylesheet" href="js/lib/node_modules/leaflet/dist/leaflet.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" %}
</body>
</html>

View file

@ -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;
}

View file

@ -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" />
<g
transform="translate(354.75,65.100704)"
id="g986" />
@ -164,7 +167,10 @@
id="g1014" />
<g
transform="matrix(0.47531389,0,0,0.47531389,410.17013,212.25752)"
id="g984">
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">
<path
inkscape:connector-curvature="0"
d="m 13.076,135.976 c 0.004,0.166 0.01,0.332 0.025,0.499 0.009,0.098 0.023,0.194 0.036,0.292 0.02,0.144 0.038,0.288 0.066,0.431 0.023,0.12 0.052,0.238 0.081,0.356 0.028,0.116 0.055,0.232 0.089,0.348 0.042,0.143 0.092,0.281 0.142,0.42 0.032,0.09 0.063,0.18 0.099,0.269 0.064,0.159 0.137,0.313 0.211,0.466 0.026,0.055 0.047,0.111 0.075,0.165 0.007,0.013 0.016,0.024 0.023,0.037 0.148,0.283 0.313,0.555 0.496,0.815 0.044,0.063 0.092,0.123 0.138,0.184 0.143,0.191 0.293,0.375 0.453,0.552 0.061,0.068 0.121,0.138 0.185,0.203 0.203,0.208 0.416,0.406 0.642,0.589 0.059,0.048 0.121,0.09 0.182,0.136 0.188,0.144 0.382,0.278 0.583,0.403 0.071,0.045 0.144,0.09 0.216,0.132 0.525,0.304 1.089,0.546 1.684,0.716 0.066,0.019 0.131,0.034 0.195,0.05 0.233,0.06 0.471,0.108 0.712,0.146 0.083,0.013 0.164,0.028 0.247,0.038 0.279,0.034 0.563,0.056 0.851,0.058 0.022,0.001 0.045,0.005 0.067,0.005 0.008,0 0.017,-0.001 0.025,-0.001 h 7.221 v 17.745 c 0,4.142 3.357,7.5 7.5,7.5 h 9.326 v 132 H 35.32 c -4.143,0 -7.5,3.357 -7.5,7.5 0,4.142 3.357,7.5 7.5,7.5 h 16.826 28.311 59.89 28.311 59.889 28.311 59.889 28.311 18.646 c 4.143,0 7.5,-3.358 7.5,-7.5 0,-4.143 -3.357,-7.5 -7.5,-7.5 h -11.146 v -132 h 12.954 c 0.039,0 0.078,-0.006 0.117,-0.006 0.039,0.001 0.078,0.006 0.117,0.006 4.143,0 7.5,-3.358 7.5,-7.5 v -17.745 h 6.895 c 0.04,0 0.079,-0.005 0.119,-0.006 0.043,0.001 0.086,0.008 0.128,0.008 2.714,0 5.334,-1.479 6.667,-4.056 1.903,-3.679 0.464,-8.204 -3.215,-10.107 L 204.912,36.568 c -1.324,-0.685 -2.756,-0.93 -4.137,-0.801 -1.377,-0.128 -2.804,0.116 -4.122,0.796 L 17.13,129.119 c -0.016,0.008 -0.029,0.018 -0.045,0.026 -0.153,0.081 -0.302,0.17 -0.448,0.261 -0.069,0.043 -0.142,0.082 -0.209,0.127 -0.116,0.077 -0.228,0.162 -0.34,0.246 -0.09,0.067 -0.183,0.131 -0.269,0.201 -0.073,0.06 -0.141,0.126 -0.212,0.188 -0.113,0.101 -0.229,0.199 -0.336,0.306 -0.039,0.039 -0.074,0.081 -0.112,0.122 -0.13,0.135 -0.258,0.27 -0.376,0.413 -0.036,0.044 -0.066,0.091 -0.102,0.136 -0.113,0.143 -0.225,0.286 -0.326,0.435 -0.087,0.128 -0.163,0.263 -0.242,0.396 -0.041,0.07 -0.088,0.138 -0.127,0.21 -0.112,0.204 -0.214,0.415 -0.307,0.63 -0.002,0.004 -0.004,0.008 -0.006,0.012 -0.086,0.201 -0.161,0.407 -0.229,0.616 -0.007,0.02 -0.017,0.041 -0.023,0.062 -0.052,0.163 -0.093,0.33 -0.133,0.497 -0.019,0.073 -0.041,0.145 -0.057,0.218 -0.025,0.122 -0.042,0.247 -0.063,0.372 -0.02,0.124 -0.043,0.249 -0.057,0.374 -0.01,0.091 -0.013,0.184 -0.02,0.276 -0.012,0.162 -0.023,0.323 -0.024,0.486 0,0.019 -0.003,0.038 -0.003,0.057 0.002,0.064 0.01,0.126 0.012,0.19 z m 187.697,-84.661 148.796,76.97 H 51.479 Z M 132.845,168.53 v 132 h -44.89 v -132 z m 88.199,0 v 132 h -44.889 v -132 z m -161.399,132 V 169.619 H 72.956 V 300.53 Z m 88.2,0 V 169.619 h 13.311 V 300.53 Z m 88.199,0 V 169.619 h 13.311 V 300.53 Z m 88.2,0 V 169.619 h 13.311 V 300.53 Z m -15,0 h -44.889 v -132 h 44.889 z m 49,-147 H 42.818 v -10.245 h 315.426 z"

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View file

@ -0,0 +1,636 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > 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;
}

View file

@ -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}})

View file

@ -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

View file

@ -72,12 +72,14 @@
(defn pin-image
"Return the name of a suitable pin image for this `record`."
[record]
(let [available @(subscribe [:available-pin-images])]
(js/console.log (str "pin-image: available is of type `" (type available) "`; `(fn? available)` returns " (set? available)))
(if
(:category record)
(contains? available (:category record))
(str
(s/capitalize
(s/replace (s/lower-case (str (:category record))) #"[^a-z0-9]" "-")) "-pin")
"unknown-pin"))
"unknown-pin")))
(defn popup-content
"Appropriate content for the popup of a map pin for this `record`."
@ -102,7 +104,9 @@
"</h5><table>"
(apply
str
(map #(str "<tr><th>" (name %) "</th><td>" (record %) "</td></tr>") (keys record)))
(map
#(str "<tr><th>" (name %) "</th><td>" (record %) "</td></tr>")
(sort (keys record))))
"</table>"))
(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))))

View file

@ -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."