Compare commits

...

17 commits

Author SHA1 Message Date
Simon Brooke 0ebbc71d5c
Continuing with salvage
There appears to be bitrot in the JavaScript dependencies; specifically in how secretary is doing routing. I have NOT got to the bottom of this.
2022-06-16 19:30:00 +01:00
Simon Brooke f93a0e854a
Starting salvage operation; documenting things which need doing. 2022-06-16 17:28:30 +01:00
Simon Brooke c9c9d09b97
Merge branch 'feature/30' into develop 2022-06-16 15:35:34 +01:00
Simon Brooke 440171851a
Now using VS Code 2022-02-14 10:34:16 +00:00
Simon Brooke e12bf82f7f
Merge remote-tracking branch 'origin/develop' into develop 2022-02-14 10:33:38 +00:00
Simon Brooke 1d97622a48
Cope with the fact that servlet-context is no longer working...
At least as I think it did.
Also moved some assets to fixed URLs so that they can be served by Apache, reducing load on Tomcat.
2022-02-14 10:33:23 +00:00
Simon Brooke dba006ad57
Cope with the fact that servlet-context is no longer working...
At least as I think it did.
Also moved some assets to fixed URLs so that they can be served by Apache, reducing load on Tomcat.
2022-02-14 10:33:06 +00:00
Simon Brooke 644dfcb517
Merge branch 'feature/60' into develop 2021-05-21 10:17:40 +01:00
Simon Brooke 03c274486e
feature/60: revert to trusting Selmer to resolve the servlet context...
Even though it doesn't. This works in Jetty, which is OK for development. It doesn't work in Tomcat, which I would like it to, but that possibly doesn't matter and at least isn't an issue for now.
2021-05-21 10:17:12 +01:00
Simon Brooke e0a310a7e5
Merge remote-tracking branch 'origin/feature/60' into feature/60 2021-05-21 10:14:04 +01:00
Simon Brooke bd9bb89cce
At this stage, it's mostly (not entirely) working under Jetty
Still not working under Tomcat.
2021-05-17 10:03:49 +01:00
Simon Brooke d43eb22cd3
Selmer style and script tags are not working cleanly for me. 2021-05-17 08:22:21 +01:00
Simon Brooke a805f3ccc5
Getting the database back to life (dodgy, will probably revert) 2020-09-20 14:25:17 +01:00
Simon Brooke 20d6c9bd9a Woohoo! Map renders in Firefox!
Much else still doesn't work, however.
2019-11-22 14:11:49 +00:00
Simon Brooke db5a034d9a Still not working 2019-11-18 13:17:06 +00:00
Simon Brooke 2594a1954f Nothing works at this stage. 2019-11-18 12:05:23 +00:00
Simon Brooke 00e520f900 lein-release plugin: bumped version from 0.2.2 to 0.2.3-SNAPSHOT for next development cycle 2019-05-02 16:32:16 +01:00
26 changed files with 10337 additions and 189 deletions

79
.classpath Normal file
View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/clj">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="target/cljsbuild">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="test/clj">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="env/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="env/dev/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src/cljc">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry exported="true" kind="lib" path="classes">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

10
.gitignore vendored
View file

@ -11,11 +11,13 @@ pom.xml.asc
/resources/public/vendor
/bower_components/
/resources/public/js/lib/
.clj-kondo/
.lein-deps-sum
.lein-repl-history
.lein-plugins/
.lein-failures
.lein-env
.lsp/
.nrepl-port
/node_modules/
.DS_Store
@ -49,3 +51,11 @@ youyesyet\.dump\.20180816
*.tar
src/clj/youyesyet/cache\.clj
.lsp/sqlite.db
.settings/
.classpath
.project

40
.project Normal file
View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>youyesyet</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>ccw.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>ccw.nature</nature>
</natures>
<filteredResources>
<filter>
<id>1621149723161</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View file

@ -0,0 +1,9 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.5

View file

@ -10,7 +10,7 @@ generated using Luminus version "2.9.11.05"
## Status
Very early pre-alpha; user interface mostly works (enough to demonstrate), back end is hardly started.
Alpha level code. Most of it works, but it's a bit fragile.
## What is it supposed to do?
@ -36,6 +36,20 @@ Where *username* is the username required to access the database, and *thisisnot
It will be helpful for you to have the [Zenhub](https://www.zenhub.com/) plugin in your browser, either Firefox or Chrome, as I'm using it for project planning.
## Build procedure
YouYesYet is build on the [Application Description Language](https://github.com/simon-brooke/adl) framework, which is also mine and not widely used. Application Description Language is a very high level descriptor language for applications, which allows a huge amount of code to be automatically generated. This generated code is **not** checked into the repository; instead, you must regenerate it before you can build.
Consequently, to get a build running:
1. clone the repository, if you have not already done so;
2. within your cloned repository, check out a branch (usually `develop` or `master`);
3. if you have previously built the project within your cloned repository, run `lein clean`;
4. run `lein npm install`;
5. **this is the important bit** run `lein adl` to generate much of the application code;
6. run `lein run` to start your development server;
7. if you want to do client debugging, you'll want to run `figwheel` in a separate process, but also from the same cloned repository directory; I normally do this by opening a second terminal and invoking `lein figwheel`.
## Further Reading
If you're thinking of joining in development on this I'd strongly recommend you get hold of a copy of [Dmitry Sotnikov](https://github.com/yogthos)'s [Web Development with Clojure, Second Edition](https://pragprog.com/book/dswdcloj2/web-development-with-clojure-second-edition).
@ -187,5 +201,4 @@ Copyright © 2016 Simon Brooke for the Radical Independence Campaign.
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
do have a GPL header at the top.
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

@ -30,6 +30,6 @@
(.bind "java:comp/env/jdbc/testdb"
(doto (org.postgresql.ds.PGSimpleDataSource.)
(.setServerName "localhost")
(.setDatabaseName "youyesyet_dev")
(.setDatabaseName "loriner") ;; "youyesyet_dev")
(.setUser "youyesyet")
(.setPassword "thisisnotsecure"))))

View file

@ -1,55 +1,63 @@
(defproject youyesyet "0.2.2"
(defproject youyesyet "0.2.3-SNAPSHOT"
:description "Canvassing tool for referenda"
:license {:name "GNU General Public License,version 2.0 or (at your option) any later version"
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
:url "https://github.com/simon-brooke/youyesyet"
;; NOTE: lein-ancient failed on 20220616; it will have to be done soon if the project is to
;; procede, but I need to fix regressions first.
:dependencies [[adl-support "0.1.6"]
[binaryage/devtools "1.0.3"]
[bouncer "1.0.1"]
[ch.qos.logback/logback-classic "1.2.3"]
[clj-oauth "1.5.5"]
[cljsjs/react-leaflet "1.6.5-0"]
;; [cljsjs/react-leaflet "2.0.1-0"] is available but doesn't seem to work fully
;; [cljsjs/react-leaflet "1.6.5-0"]
;; [cljsjs/react-leaflet "2.4.0-0"] is available but doesn't seem to work fully
[cljsjs/leaflet "1.5.1-0"] ;; leaflet-reagent-reframe uses this and it works with Firefox!
[cljsjs/react "16.11.0-0"]
[cljsjs/react-dom "16.11.0-0"]
[cljs-ajax "0.8.0"]
[com.andrewmcveigh/cljs-time "0.5.2"]
[clojure.java-time "0.3.2"]
[com.cemerick/url "0.1.1"]
[compojure "1.6.1"]
[conman "0.8.3"]
[cprop "0.1.13"]
[cprop "0.1.14"]
[day8.re-frame/http-fx "0.1.6"]
[korma "0.4.3"]
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
[luminus/ring-ttl-session "0.3.2"]
[luminus/ring-ttl-session "0.3.3"]
[luminus-nrepl "0.1.6"]
[luminus-migrations "0.6.5"]
[luminus-migrations "0.6.6"]
[luminus-immutant "0.2.5"]
[markdown-clj "1.0.8"]
[metosin/compojure-api "1.1.12"]
[markdown-clj "1.10.0"]
[metosin/compojure-api "1.1.13"]
[metosin/ring-http-response "0.9.1"]
[migratus "1.2.3"]
[migratus "1.2.7"]
[mount "0.1.16"]
[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.10.520" :scope "provided"]
[org.clojure/core.memoize "0.7.1"]
[org.clojure/core.memoize "0.8.2"]
;;[org.clojure/spec.alpha "0.2.168"]
[org.clojure/tools.cli "0.4.2"]
[org.clojure/tools.logging "0.4.1"]
[org.postgresql/postgresql "42.2.5"]
[org.clojure/tools.logging "0.5.0"]
[org.postgresql/postgresql "42.2.8"]
[org.webjars/bootstrap "4.3.1"]
[org.webjars/font-awesome "5.8.1"]
[org.webjars/font-awesome "5.11.2"]
[org.webjars.bower/tether "1.4.4"]
[postgre-types "0.0.4"]
[re-frame "0.10.6"]
[reagent "0.8.1"]
[reagent-utils "0.3.2"]
[re-frame "1.2.0"]
[reagent "1.1.1"]
[reagent-utils "0.3.4"]
[recalcitrant "0.1.2"]
[ring-middleware-format "0.7.4"]
[ring/ring-defaults "0.3.2"]
[ring/ring-servlet "1.7.1"]
[ring-webjars "0.2.0"]
[secretary "1.2.3"]
[selmer "1.12.12"]]
[clj-commons/secretary "1.2.4"]
[selmer "1.12.40"]]
:deploy-repositories [["releases" :clojars]
["snapshots" :clojars]]
@ -64,9 +72,9 @@
:main ^:skip-aot youyesyet.core
:migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
:plugins [[lein-adl "0.1.7"]
:plugins [[lein-adl "0.1.8-SNAPSHOT"]
[lein-cljsbuild "1.1.7"]
[lein-codox "0.10.7-multilang"]
[lein-codox "0.10.7"]
[lein-cprop "1.0.3"]
[lein-kibit "0.1.6"]
[lein-less "1.7.5"]
@ -89,7 +97,8 @@
:npm {:dependencies [[datatables.net "1.10.19"]
[datatables.net-dt "1.10.19"]
[jquery "3.3.1"]
[leaflet "1.3.1"]
;; [leaflet "1.3.1"]
;; [react "18.2.0"]
[selectize "0.12.6"]
[signature_pad "2.3.2"]
[simplemde "1.11.2"]]
@ -153,15 +162,15 @@
[ring/ring-devel "1.7.1"]
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
[luminus-immutant "0.2.5"]
[pjstadig/humane-test-output "0.9.0"]
[pjstadig/humane-test-output "0.10.0"]
[binaryage/devtools "0.9.10"]
[com.cemerick/piggieback "0.2.2"]
[directory-naming/naming-java "0.8"]
[doo "0.1.11"]
[figwheel-sidecar "0.5.18"]]
[figwheel-sidecar "0.5.19"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.23.0"]
[lein-doo "0.1.10"]
[lein-figwheel "0.5.16"]
[lein-figwheel "0.5.19"]
[org.clojure/clojurescript "1.10.520"]]
:cljsbuild {:builds
{:app

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

View file

@ -2,9 +2,9 @@
{% block head %}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="css/yyy-common.css" />
<link rel="stylesheet" type="text/css" href="css/yyy-app.css" />
<link rel="stylesheet" type="text/css" href="css/spinner.css" />
<link rel="stylesheet" type="text/css" href="/css/yyy-common.css" />
<link rel="stylesheet" type="text/css" href="/css/yyy-app.css" />
<link rel="stylesheet" type="text/css" href="/css/spinner.css" />
<link href="https://fonts.googleapis.com/css?family=Archivo+Black|Archivo+Narrow" rel="stylesheet"/>
<title>{{site-title}}: {{title}}</title>
{% endblock %}
@ -42,13 +42,17 @@
{% endblock %}
{% block extra-tail %}
<!-- scripts and styles -->
<!-- ATTENTION \/ -->
<!-- ATTENTION /\ -->
<!-- Leaflet -->
<link rel="stylesheet" href="js/lib/node_modules/leaflet/dist/leaflet.css" />
{% script "js/lib/node_modules/signature_pad/dist/signature_pad.min.js" %}
{% script "js/lib/node_modules/leaflet/dist/leaflet.js" %}
{% script "/js/app.js" %}
<!-- script src="js/lib/node_modules/leaflet/dist/leaflet.js"></script -->
<!-- TEMP: react seems no longer to be automatically added to the dependencies by reagent? -->
<!-- script src="js/lib/node_modules/react/index.js"></script -->
<!-- Signature pad -->
<script src="js/lib/node_modules/signature_pad/dist/signature_pad.min.js"></script>
<!-- our actual app -->
<script src="js/app.js"></script>
{% endblock %}

View file

@ -17,6 +17,9 @@
<!-- extra-head: put any additional markup to go into the head of your document into this block -->
<!-- e.g. script tags, link tags -->
{% endblock %}
{% if servlet-context %}
<!-- Servlet context is {{servlet-context}} -->
{% endif %}
</head>
<body>
{% block whole-page %}
@ -24,20 +27,20 @@
{% block top %}
<header>
<div id="nav">
<img id="nav-icon" src="{{servlet-context}}/img/threelines.png" alt="Menu"/>
<img id="nav-icon" src="/img/threelines.png" alt="Menu"/>
<menu id="nav-menu" class="nav">
<li class=""><a href="{{servlet-context}}/home">Home</a></li>
<li class=""><a href="/">Home</a></li>
<li class=""><a href="https://library.projecthope.scot/">Library</a></li>
{% if user %}
<li class=""><a href="{{servlet-context}}/roles">Roles</a></li>
<li class=""><a href="{{servlet-context}}/logout">Logout</a></li>
<li class=""><a href="roles">Roles</a></li>
<li class=""><a href="logout">Logout</a></li>
{% else %}
<li class=""><a href="{{servlet-context}}/register">Register</a></li>
<li class=""><a href="{{servlet-context}}/login">Login</a></li>
<li class=""><a href="register">Register</a></li>
<li class=""><a href="login">Login</a></li>
{% endif %}
<li class=""><a href="{{servlet-context}}/about">About</a></li>
<li class=""><a href="about">About</a></li>
{% if user %}
<li id="user"><a href="{{servlet-context}}/profile">Logged in as {{user.username}}</a></li>
<li id="user"><a href="profile">Logged in as {{user.username}}</a></li>
{% endif %}
</menu>
</div>
@ -87,17 +90,17 @@
<!-- foot: override this block if you don't want the standard footer -->
<footer>
<div id="credits">
<!-- div>
<img src="{{servlet-context}}/img/credits/ric-logo.png" width="24" height="24"/>
<div>
<img src="/img/credits/ric-logo.png" width="24" height="24"/>
A project of the
<a href="https://radical.scot/">Radical Independence Campaign</a> ||
Version {{version}}
</div -->
</div>
<div>
<img height="16" width="16" alt="Clojure" 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/youyesyet">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>
<img height="16" width="16" alt="Clojure" src="/img/credits/luminus-logo.png"/>Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> ||
<img height="16" width="16" alt="Clojure" src="/img/credits/clojure-icon.gif"/> Powered by <a href="http://clojure.org">Clojure</a> ||
<img height="16" width="16" alt="GitHub" src="/img/credits/github-logo-transparent.png"/>Find me/fork me on <a href="https://github.com/simon-brooke/youyesyet">Github</a> ||
<img height="16" width="16" alt="Free Software Foundation" src="/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>

View file

@ -11,7 +11,7 @@
{% endblock %}
{% block content %}
<form action="{{servlet-context}}/login" method="post">
<form action="login" method="post">
{% csrf-field %}
<input type="hidden" name="redirect-to" value="{{servlet-context}}/roles"/>
<h2>

View file

@ -22,7 +22,8 @@
"Primary connection to the main database. TODO: this does not yet enable
sharding."
:start (conman/connect! {:jdbc-url-env (env :database-url)
:jdbc-url "jdbc:postgresql://127.0.0.1/youyesyet_dev?user=youyesyet&password=thisisnotsecure"
;; :jdbc-url "jdbc:postgresql://127.0.0.1/youyesyet_dev?user=youyesyet&password=thisisnotsecure"
:jdbc-url "jdbc:postgresql://127.0.0.1/loriner?user=youyesyet&password=thisisnotsecure"
:driver-class-name "org.postgresql.Driver"})
:stop (conman/disconnect! *db*))

View file

@ -2,6 +2,7 @@
youyesyet.middleware
(:require [clojure.tools.logging :as log]
[ring.middleware.anti-forgery :refer [wrap-anti-forgery]]
[ring.middleware.content-type :refer [wrap-content-type]]
[ring.middleware.defaults :refer [site-defaults wrap-defaults]]
[ring.middleware.format :refer [wrap-restful-format]]
[ring.middleware.webjars :refer [wrap-webjars]]
@ -29,7 +30,11 @@
(do
(log/debug "Taking '" (:app-context env) "' as *app-context* from env")
(:app-context env)))]
(handler (assoc request :servlet-context *app-context*)))))
(handler (assoc
request
;; bind both possible keys just to save grief
:selmer/context *app-context*
:servlet-context *app-context*)))))
(defn wrap-internal-error [handler]
@ -83,5 +88,6 @@
(assoc-in [:security :anti-forgery] false)
(assoc-in [:session :store] (ttl-memory-store (* 60 30)))))
wrap-context
wrap-content-type
wrap-internal-error))

View file

@ -1,19 +1,16 @@
(ns ^{:doc "Routes/pages available to unauthenticated users."
:author "Simon Brooke"} youyesyet.routes.home
(:require [adl-support.utils :refer [safe-name]]
[clojure.java.io :as io]
[clojure.string :as s]
(:require [clojure.java.io :as io]
[clojure.tools.logging :as log]
[clojure.walk :refer [keywordize-keys]]
[markdown.core :refer [md-to-html-string]]
[noir.util.route :as route]
[ring.util.http-response :as response]
[youyesyet.config :refer [env]]
[youyesyet.db.core :as db-core]
[youyesyet.layout :as layout]
[youyesyet.oauth :as oauth]
[compojure.core :refer [defroutes GET POST]]
))
[youyesyet.routes.utils :refer [with-servlet-context]]
[compojure.core :refer [defroutes GET POST]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
@ -48,27 +45,41 @@
(if (.exists motd) (slurp motd) "")))
(defn about-page []
(defn about-page
"Render a page describing the app and its purpose."
[request]
(layout/render "md.html" {:title
(str "About " (:site-title env))
:servlet-context (:servlet-context request)
:content (md-to-html-string (slurp (io/resource "about.md")))}))
(defn call-me-page [request]
(defn call-me-page
"Render a page requesting a call to a particular elector from a member of the
telephone canvassing team."
[request]
(if
request
(do
;; do something to store it in the database
(layout/render "call-me-accepted.html" (:session request) (:params request)))
(layout/render
"call-me-accepted.html"
(:session request)
(assoc (:params request) :servlet-context (:servlet-context request)))
(layout/render "call-me.html" (:session request)
{:title "Please call me!"
(with-servlet-context {:title "Please call me!"
;; TODO: Issues need to be fetched from the database
:concerns (db-core/list-issues db-core/*db* {})})))
:concerns (db-core/list-issues db-core/*db* {})}
request)))))
(defn home-page []
(layout/render "home.html" {:title "You yes yet?"
:motd (md-to-html-string (motd))}))
(defn home-page
"Render the default page."
[request]
(layout/render "home.html" (with-servlet-context
{:title "You yes yet?"
:motd (md-to-html-string (motd))}
request)))
(defn login-page
@ -77,7 +88,7 @@
(let [params (keywordize-keys (:params request))
session (:session request)
username (:username params)
user (if username (db-core/get-canvasser-by-username db-core/*db* {:username username}))
user (when username (db-core/get-canvasser-by-username db-core/*db* {:username username}))
password (:password params)
redirect-to (or
(:redirect-to params)
@ -108,27 +119,37 @@
username
(layout/render
"login.html"
(with-servlet-context
{:title (str "User " username " is unknown")
:redirect-to redirect-to
:warnings ["Your user name was not recognised or your password did not match"]})
:warnings ["Your user name was not recognised or your password did not match"]}
request))
;; if we've no username, just invite the user to log in
true
:else
(layout/render
"login.html"
(with-servlet-context
{:title "Please log in"
:redirect-to redirect-to
:authorities (db-core/list-authorities db-core/*db*)}))))
:authorities (db-core/list-authorities db-core/*db*)}
request)))))
(defroutes home-routes
(GET "/" [] (home-page))
(GET "/home" [] (home-page))
(GET "/about" [] (about-page))
(GET "/call-me" [] (call-me-page nil))
(GET "/" [request] (home-page request))
(GET "/home" [request] (home-page request))
(GET "/about" [request] (about-page request))
(GET "/call-me" [request] (call-me-page request))
(POST "/call-me" request (call-me-page request))
(GET "/login" request (login-page request))
(POST "/login" request (login-page request))
(GET "/notyet" [] (layout/render "notyet.html"
{:title "Can we persuade you?"}))
(GET "/supporter" [] (layout/render "supporter.html"
{:title "Have you signed up as a canvasser yet?"})))
(GET "/notyet" [request] (layout/render
"notyet.html"
(with-servlet-context
{:title "Can we persuade you?"}
request)))
(GET "/supporter" [request] (layout/render
"supporter.html"
(with-servlet-context
{:title "Have you signed up as a canvasser yet?"}
request))))

View file

@ -1,23 +1,15 @@
(ns ^{:doc "Manually maintained routes which handle data transfer to/from the canvasser app."
:author "Simon Brooke"} youyesyet.routes.rest
(:require [adl-support.rest-support :refer :all]
[adl-support.core :refer [massage-params do-or-log-error
do-or-return-reason]]
(:require [adl-support.core :refer [massage-params]]
[adl-support.rest-support :refer [do-or-server-fail valid-user-or-forbid with-params-or-error]]
[clojure.core.memoize :as memo]
[clojure.data.json :as json]
[clojure.java.io :as io]
[clojure.string :as s]
[clojure.tools.logging :as log]
[clojure.walk :refer [keywordize-keys]]
[compojure.core :refer [defroutes GET POST]]
[compojure.core :refer [defroutes GET]]
[java-time :as jt]
[mount.core :as mount]
[noir.response :as nresponse]
[noir.util.route :as route]
[ring.util.http-response :as response]
[youyesyet.locality :as l]
[youyesyet.db.core :as db]
[youyesyet.utils :refer :all]
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -3,20 +3,20 @@
(:require [adl-support.core :as support]
[adl-support.utils :refer [safe-name]]
[clojure.tools.logging :as log]
[clojure.walk :refer [keywordize-keys]]
[compojure.core :refer [defroutes GET POST]]
[noir.util.route :as route]
[ring.util.http-response :as response]
[youyesyet.config :refer [env]]
[youyesyet.db.core :as db-core]
[youyesyet.routes.issue-experts :as expert]
[youyesyet.layout :as layout]
[youyesyet.oauth :as oauth]
[youyesyet.routes.auto :as auto]))
[youyesyet.routes.auto :as auto]
[youyesyet.routes.utils :refer [with-servlet-context]]))
(defn roles-page [request]
(defn roles-page
"Render the routing page for the roles the currently logged in user is member of."
[request]
(let
[session (:session request)
user (-> request :session :user)
@ -29,6 +29,7 @@
(layout/render
"roles.html"
{:title (str "Welcome " (:fullname user) ", what do you want to do?")
:servlet-context (:servlet-context request)
:user user
:roles (map #(assoc % :link (safe-name (:name %) :sql)) roles)})
(assoc (response/found "/login") :session (dissoc session :user)))))
@ -38,7 +39,7 @@
[request]
(layout/render
(support/resolve-template "application-index.html")
{:title "Administrative menu"}))
(with-servlet-context {:title "Administrative menu"} request)))
(defn analysts-page
@ -48,21 +49,21 @@
[request]
(layout/render
(support/resolve-template "application-index.html")
{:title "Administrative menu"}))
(with-servlet-context {:title "Administrative menu"} request)))
(defn canvassers-page
[request]
(layout/render
"roles/canvasser.html"
{}))
(with-servlet-context {} request)))
(defn team-organisers-page
[request]
(layout/render
"roles/team-orgenisers.html"
{}))
(with-servlet-context {} request)))
(defroutes roles-routes

View file

@ -0,0 +1,12 @@
(ns youyesyet.routes.utils)
(defn with-servlet-context
"Returns a map like `m` into which the servlet context from `request`,
expected to be a request map, has been merged. When an app is served from
Tomcat, there will be a `:servlet-context` key in the map, and it matters;
when served from Jetty or other lightweight servlet containers, there won't
be. TODO: should probably be moved (or copied) to adl-support."
[m request]
(if (:servlet-context m)
(assoc m :servlet-context (:servlet-context request))
m))

View file

@ -1,14 +1,16 @@
(ns ^{:doc "Canvasser app navigation and routing."
:author "Simon Brooke"}
youyesyet.canvasser-app.core
(:require cljsjs.react-leaflet
[ajax.core :refer [GET POST]]
(:require [ajax.core :refer [GET POST]]
[cljsjs.leaflet]
[devtools.core :as devtools]
[goog.events :as events]
[goog.history.EventType :as HistoryEventType]
[markdown.core :refer [md->html]]
[reagent.core :as r]
[re-frame.core :as rf]
[re-frame.fx]
[recalcitrant.core :refer [error-boundary]] ;; may not be needed here
[secretary.core :as secretary]
[youyesyet.canvasser-app.ajax :refer [load-interceptors!]]
[youyesyet.canvasser-app.gis :refer [get-current-location]]
@ -49,6 +51,11 @@
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; install tools to aid debugging in Chrome/Chromium.
(devtools/install!)
;;; So that we can do debug logging!
(enable-console-print!)
@ -121,20 +128,22 @@
(if content [content]
[:div.error (str "No content in page " @(rf/subscribe [:page]))])
[:footer
[:div.error {:style [:display (if (empty? error) :none :block)]} (apply str error)]
(if-not (empty? error)
[:div.error
error])
(if-not (empty? feedback)
[:div.feedback
{:style [:display (if (empty? feedback) :none :block)]}
(apply str (map #(h/feedback-messages %) (distinct feedback)))]
[:div.queue (if
(nil? outqueue) ""
(str (count outqueue) " items queued to send"))]]]))
(apply str (map #(h/feedback-messages %) (distinct feedback)))])
;; (if-not (empty? outqueue)
;; [:div.queue (str (count outqueue) " items queued to send")])
]]))
;; -------------------------
;; Routes
(secretary/set-config! :prefix "#")
(secretary/defroute "/" []
(ui/log-and-dispatch [:set-active-page :map]))
(ui/log-and-dispatch [:set-active-page :about]))
(secretary/defroute "/about" []
(ui/log-and-dispatch [:set-active-page :about]))
@ -152,7 +161,7 @@
(secretary/defroute "/elector" []
(ui/log-and-dispatch [:set-active-page :elector]))
(secretary/defroute "/elector/:elector/:consent" {elector-id :elector}
(secretary/defroute "/elector/:elector" {elector-id :elector}
(ui/log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :elector}]))
(secretary/defroute "/elector/:elector/:consent" {elector-id :elector consent :consent}
@ -191,12 +200,20 @@
(defn hook-browser-navigation!
"Interceptor for the browser back button."
[]
(try
(js/console.log "Entering `hook-browser-navigation!`")
(doto (History.)
(events/listen
HistoryEventType/NAVIGATE
(fn [event]
(secretary/dispatch! (.-token event))))
(.setEnabled true)))
(js/console.log "Entering anonymous history update handler")
(try
(secretary/dispatch! (.-token event))
(catch js/Error e (js/console.warn e)))
(js/console.log "Exiting anonymous history update handler")))
(.setEnabled true))
(catch js/Error e (js/console.warn e)))
(js/console.log "Exiting `hook-browser-navigation!`"))
;; -------------------------
;; Initialize app
@ -213,8 +230,9 @@
(rf/dispatch [:fetch-options])
(rf/dispatch [:fetch-issues])
(rf/dispatch [:fetch-followupmethods])
(rf/dispatch [:dispatch-later [{:ms 60000 :dispatch [:process-queue]}]])
;; (rf/dispatch [:dispatch-later [{:ms 60000 :dispatch [:process-queue]}]])
(load-interceptors!)
;; TEMP: the browser navigation hook is breaking the loading of the building page, and I don't at this moment understand why.
(hook-browser-navigation!)
(mount-components))

View file

@ -45,13 +45,23 @@
(.getCurrentPosition
(.-geolocation js/navigator)
(fn [position]
(let [lat (.-latitude (.-coords position))
(let [view @(subscribe [:view])
lat (.-latitude (.-coords position))
lng (.-longitude (.-coords position))]
(js/console.log (str "Current location is: " lat ", " lng))
(if
(and view (float? lat) (float? lng))
(do
(dispatch [:set-latitude lat])
(dispatch [:set-longitude lng])
(.panTo @(subscribe [:view]) (.latLng js/L lat lng))
(locality lat lng))))
(.panTo view (.latLng js/L lat lng))
(locality lat lng))
(do
(js/console.log
(if view
(str "Geolocation failed lat: '" lat "'; lng '" lng "'")
"No value for subscription to [:view]"))
0)))))
(do
(js/console.log "Geolocation not available")
0))
@ -84,12 +94,15 @@
so back links work."
[id]
(js/console.log (str "Click handler for address #" id))
(let [view @(subscribe [:view])
centre (.getCenter view)]
(dispatch [:set-zoom (.getZoom view)])
(dispatch [:set-latitude (.-lat centre)])
(dispatch [:set-longitude (.-lng centre)]))
(set! window.location.href (str "#building/" id)))
;; (let [view @(subscribe [:view])
;; centre (.getCenter view)]
;; (dispatch [:set-zoom (.getZoom view)])
;; (dispatch [:set-latitude (.-lat centre)])
;; (dispatch [:set-longitude (.-lng centre)]))
(js/console.log (str "Navigating to " "#/building/" id))
;; (set! window.location.href (str "#/building/" id))
(dispatch [:set-address 262])
)
(defn add-map-pin

View file

@ -64,8 +64,8 @@
(apply 'do forms)))
(defn compose-packet
[item]
"Convert this `item` into a URI which can be sent as a GET call"
[item]
(assoc
(url js/window.location)
:path (str "/rest/" (name (:action item)))
@ -74,9 +74,11 @@
(def feedback-messages
"Messages used as feedback to the user"
{:fetch-locality "Fetching local data."
:send-request "Request has been queued."
:send-intention-and-visit "Voting intention has been sent"
:bad-address "No valid address has been selected"
})
@ -118,9 +120,10 @@
(remove-from-key db :outqueue x))
(defn coerce-to-number [v]
(defn coerce-to-number
"If it is possible to do so, coerce `v` to a number.
NOTE: I tried to do this in *cljc*, but it did not work. Leave it alone."
[v]
(if (number? v) v
(try
(read-string (str v))
@ -378,7 +381,7 @@
(assoc (clear-messages db) :page k)
db)))
;; TEMP: this is what doesn't seem to be being called
(reg-event-db
:set-address
(fn [db [_ address-id]]

View file

@ -59,7 +59,7 @@
(reg-sub
:error
(fn [db _]
(:error db)))
(apply str (:error db))))
(reg-sub
:feedback

View file

@ -38,6 +38,8 @@
[]
(let [address @(subscribe [:address])
dwellings (:dwellings address)]
(js/console.log (str "Address: address"))
(if address
[:div
[:h1 (str "Flats at " (:address address))]
[:div.container {:id "main-container"}
@ -51,4 +53,4 @@
:target (str "#/dwelling/" (:id dwelling))) )
(sort-by
:sub_address
(:dwellings address)))]]]))
(:dwellings address)))]]])))

View file

@ -1,8 +1,10 @@
(ns ^{:doc "Canvasser app map view panel."
:author "Simon Brooke"}
youyesyet.canvasser-app.views.map
(:require [re-frame.core :refer [reg-sub subscribe dispatch dispatch-sync]]
(:require [cljsjs.leaflet]
[re-frame.core :refer [reg-sub subscribe dispatch dispatch-sync]]
[reagent.core :as reagent]
[recalcitrant.core :refer [error-boundary]]
[youyesyet.canvasser-app.gis :refer [refresh-map-pins get-current-location]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -48,7 +50,7 @@
;;; thought.
;; which provider to use
(def ^dynamic *map-provider* :osm)
(def ^:dynamic *map-provider* :osm)
(def osm-url "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png")
(def osm-attrib "Map data &copy; <a href='http://openstreetmap.org'>OpenStreetMap</a> contributors")
@ -58,7 +60,8 @@
"Did-mount function loading map tile data from MapBox (proprietary)."
[]
(get-current-location)
(let [view (.setView (.map js/L "map" (clj->js {:zoomControl "false"})) #js [55.82 -4.25] 40)]
(let [view (.setView
(.map js/L "map" (clj->js {:zoomControl "false"})))]
;; NEED TO REPLACE FIXME with your mapID!
(.addTo (.tileLayer js/L "http://{s}.tiles.mapbox.com/v3/FIXME/{z}/{x}/{y}.png"
(clj->js {:attribution "Map data &copy; [...]"
@ -69,7 +72,7 @@
(defn map-did-mount-osm
"Did-mount function loading map tile data from Open Street Map."
[]
(get-current-location)
(get-current-location) ;; - [Violation] Only request geolocation information in response to a user gesture.
(let [view (.setView
(.map js/L
"map"
@ -110,6 +113,6 @@
(defn panel
"A reagent class for the map object."
[]
(get-current-location)
;; (get-current-location)
(reagent/create-class {:reagent-render map-render
:component-did-mount map-did-mount}))

14
workspace.code-workspace Normal file
View file

@ -0,0 +1,14 @@
{
"folders": [
{
"path": "."
},
{
"path": "../adl-support"
},
{
"path": "../Selmer"
}
],
"settings": {}
}

View file

@ -242,7 +242,7 @@ version="0.1.1">
<property type="real" name="longitude" column="longitude">
<prompt prompt="Longitude" locale="en_GB.UTF-8"/>
</property>
<property type="list" name="dwellings" entity="dwellings"/>
<property type="list" name="dwellings" entity="dwellings" farkey="address_id"/>
<property type="integer" name="locality" column="locality">
<documentation>Locality indexing; see issue #44. Note that
this property should be generated automatically from the
@ -320,7 +320,7 @@ version="0.1.1">
<prompt prompt="Canvasser" locale="en_GB.UTF-8"/>
</property>
<property required="true" type="timestamp" name="date"
column="date" default="CURRENT_TIMESTAMP" distinct="user">
column="date" default="now()" distinct="user">
<prompt prompt="Date" locale="en_GB.UTF-8"/>
</property>
<permission group="canvassers" permission="noedit">
@ -1000,7 +1000,7 @@ version="0.1.1">
column="actor" entity="canvassers" farkey="id">
<prompt prompt="Actor" locale="en_GB.UTF-8"/>
</property>
<property default="CURRENT_TIMESTAMP" type="timestamp"
<property default="now()" type="timestamp"
name="date" column="date" distinct="user">
<prompt prompt="Date" locale="en_GB.UTF-8"/>
</property>

9895
youyesyet.dump.20191116 Normal file

File diff suppressed because it is too large Load diff